Merge lp:~mvo/software-center/test-catview-cleanup into lp:software-center
- test-catview-cleanup
- Merge into trunk
Proposed by
Michael Vogt
Status: | Superseded |
---|---|
Proposed branch: | lp:~mvo/software-center/test-catview-cleanup |
Merge into: | lp:software-center |
Diff against target: |
879 lines (+350/-246) 7 files modified
softwarecenter/backend/channel.py (+4/-4) softwarecenter/db/application.py (+5/-4) softwarecenter/testutils.py (+62/-0) softwarecenter/ui/gtk3/models/appstore2.py (+11/-5) softwarecenter/ui/gtk3/views/catview_gtk.py (+48/-21) test/gtk3/test_app.py (+2/-36) test/gtk3/test_catview.py (+218/-176) |
To merge this branch: | bzr merge lp:~mvo/software-center/test-catview-cleanup |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
software-store-developers | Pending | ||
Review via email: mp+106766@code.launchpad.net |
This proposal has been superseded by a proposal from 2012-05-22.
Commit message
Description of the change
This branch refactors the test_catview.py code:
- split the TestCases for the Recommender and the Top Rated/Whats New
- remove duplicated code in the tests by using setUp()/tearDown() more efficiently
- use the patch decorator more
- avoid re-creating the DB in each test via setUpClass, this could be optimized further by just having one global instance for the entire test
To post a comment you must log in.
- 3034. By Michael Vogt
-
test/gtk3/
test_catview. py: use addCleanup() instead of tearDown() as suggested by Natalia - 3035. By Michael Vogt
-
merge 5.2 and resolve conflicts
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'softwarecenter/backend/channel.py' | |||
2 | --- softwarecenter/backend/channel.py 2012-03-19 14:20:55 +0000 | |||
3 | +++ softwarecenter/backend/channel.py 2012-05-22 12:42:24 +0000 | |||
4 | @@ -22,7 +22,7 @@ | |||
5 | 22 | 22 | ||
6 | 23 | from gettext import gettext as _ | 23 | from gettext import gettext as _ |
7 | 24 | 24 | ||
9 | 25 | from softwarecenter.distro import get_distro | 25 | import softwarecenter.distro |
10 | 26 | 26 | ||
11 | 27 | from softwarecenter.enums import (SortMethods, | 27 | from softwarecenter.enums import (SortMethods, |
12 | 28 | Icons, | 28 | Icons, |
13 | @@ -34,7 +34,7 @@ | |||
14 | 34 | 34 | ||
15 | 35 | class ChannelsManager(object): | 35 | class ChannelsManager(object): |
16 | 36 | def __init__(self, db, **kwargs): | 36 | def __init__(self, db, **kwargs): |
18 | 37 | self.distro = get_distro() | 37 | self.distro = softwarecenter.distro.get_distro() |
19 | 38 | self.db = db | 38 | self.db = db |
20 | 39 | 39 | ||
21 | 40 | # public | 40 | # public |
22 | @@ -154,7 +154,7 @@ | |||
23 | 154 | self.installed_only = installed_only | 154 | self.installed_only = installed_only |
24 | 155 | self._channel_sort_mode = channel_sort_mode | 155 | self._channel_sort_mode = channel_sort_mode |
25 | 156 | # distro specific stuff | 156 | # distro specific stuff |
27 | 157 | self.distro = get_distro() | 157 | self.distro = softwarecenter.distro.get_distro() |
28 | 158 | # configure the channel | 158 | # configure the channel |
29 | 159 | self._channel_display_name = self._get_display_name_for_channel( | 159 | self._channel_display_name = self._get_display_name_for_channel( |
30 | 160 | channel_name, channel_origin, channel_component) | 160 | channel_name, channel_origin, channel_component) |
31 | @@ -351,7 +351,7 @@ | |||
32 | 351 | return AptChannelsManager.channel_available(channelname) | 351 | return AptChannelsManager.channel_available(channelname) |
33 | 352 | 352 | ||
34 | 353 | if __name__ == "__main__": | 353 | if __name__ == "__main__": |
36 | 354 | distro = get_distro() | 354 | distro = softwarecenter.distro.get_distro() |
37 | 355 | channel = SoftwareChannel(distro.get_distro_channel_name(), | 355 | channel = SoftwareChannel(distro.get_distro_channel_name(), |
38 | 356 | None, None) | 356 | None, None) |
39 | 357 | print(channel) | 357 | print(channel) |
40 | 358 | 358 | ||
41 | === modified file 'softwarecenter/db/application.py' | |||
42 | --- softwarecenter/db/application.py 2012-05-11 13:48:04 +0000 | |||
43 | +++ softwarecenter/db/application.py 2012-05-22 12:42:24 +0000 | |||
44 | @@ -24,9 +24,10 @@ | |||
45 | 24 | import os | 24 | import os |
46 | 25 | import re | 25 | import re |
47 | 26 | 26 | ||
48 | 27 | import softwarecenter.distro | ||
49 | 28 | |||
50 | 27 | from gettext import gettext as _ | 29 | from gettext import gettext as _ |
51 | 28 | from softwarecenter.backend.channel import is_channel_available | 30 | from softwarecenter.backend.channel import is_channel_available |
52 | 29 | from softwarecenter.distro import get_distro | ||
53 | 30 | from softwarecenter.enums import PkgStates, XapianValues, Icons | 31 | from softwarecenter.enums import PkgStates, XapianValues, Icons |
54 | 31 | 32 | ||
55 | 32 | from softwarecenter.paths import (APP_INSTALL_CHANNELS_PATH, | 33 | from softwarecenter.paths import (APP_INSTALL_CHANNELS_PATH, |
56 | @@ -177,7 +178,7 @@ | |||
57 | 177 | self._db = db | 178 | self._db = db |
58 | 178 | self._db.connect("reopen", self._on_db_reopen) | 179 | self._db.connect("reopen", self._on_db_reopen) |
59 | 179 | self._cache = self._db._aptcache | 180 | self._cache = self._db._aptcache |
61 | 180 | self._distro = get_distro() | 181 | self._distro = softwarecenter.distro.get_distro() |
62 | 181 | self._history = None | 182 | self._history = None |
63 | 182 | # import here (intead of global) to avoid dbus dependency | 183 | # import here (intead of global) to avoid dbus dependency |
64 | 183 | # in update-software-center (that imports application, but | 184 | # in update-software-center (that imports application, but |
65 | @@ -298,7 +299,7 @@ | |||
66 | 298 | # try apt first | 299 | # try apt first |
67 | 299 | if self._pkg: | 300 | if self._pkg: |
68 | 300 | for origin in self._pkg.candidate.origins: | 301 | for origin in self._pkg.candidate.origins: |
70 | 301 | if (origin.origin == get_distro().get_distro_channel_name() and | 302 | if (origin.origin == self._distro.get_distro_channel_name() and |
71 | 302 | origin.trusted and origin.component): | 303 | origin.trusted and origin.component): |
72 | 303 | return origin.component | 304 | return origin.component |
73 | 304 | # then xapian | 305 | # then xapian |
74 | @@ -639,7 +640,7 @@ | |||
75 | 639 | self.emit("screenshots-available", self._screenshot_list) | 640 | self.emit("screenshots-available", self._screenshot_list) |
76 | 640 | return | 641 | return |
77 | 641 | # download it | 642 | # download it |
79 | 642 | distro = get_distro() | 643 | distro = self._distro |
80 | 643 | url = distro.SCREENSHOT_JSON_URL % self._app.pkgname | 644 | url = distro.SCREENSHOT_JSON_URL % self._app.pkgname |
81 | 644 | try: | 645 | try: |
82 | 645 | f = Gio.File.new_for_uri(url) | 646 | f = Gio.File.new_for_uri(url) |
83 | 646 | 647 | ||
84 | === modified file 'softwarecenter/testutils.py' | |||
85 | --- softwarecenter/testutils.py 2012-04-16 16:41:29 +0000 | |||
86 | +++ softwarecenter/testutils.py 2012-05-22 12:42:24 +0000 | |||
87 | @@ -22,6 +22,8 @@ | |||
88 | 22 | import tempfile | 22 | import tempfile |
89 | 23 | import time | 23 | import time |
90 | 24 | 24 | ||
91 | 25 | from collections import defaultdict | ||
92 | 26 | |||
93 | 25 | from mock import Mock | 27 | from mock import Mock |
94 | 26 | 28 | ||
95 | 27 | m_dbus = m_polkit = m_aptd = None | 29 | m_dbus = m_polkit = m_aptd = None |
96 | @@ -142,6 +144,12 @@ | |||
97 | 142 | main_loop.iteration() | 144 | main_loop.iteration() |
98 | 143 | 145 | ||
99 | 144 | 146 | ||
100 | 147 | def do_events_with_sleep(iterations=5, sleep=0.1): | ||
101 | 148 | for i in range(iterations): | ||
102 | 149 | do_events() | ||
103 | 150 | time.sleep(sleep) | ||
104 | 151 | |||
105 | 152 | |||
106 | 145 | def get_mock_app_from_real_app(real_app): | 153 | def get_mock_app_from_real_app(real_app): |
107 | 146 | """ take a application and return a app where the details are a mock | 154 | """ take a application and return a app where the details are a mock |
108 | 147 | of the real details so they can easily be modified | 155 | of the real details so they can easily be modified |
109 | @@ -314,3 +322,57 @@ | |||
110 | 314 | {u'rating': 1.5, u'package_name': u'tucan'}], | 322 | {u'rating': 1.5, u'package_name': u'tucan'}], |
111 | 315 | u'app': u'pitivi'} | 323 | u'app': u'pitivi'} |
112 | 316 | return recommend_app_data | 324 | return recommend_app_data |
113 | 325 | |||
114 | 326 | |||
115 | 327 | class ObjectWithSignals(object): | ||
116 | 328 | """A faked object that you can connect to and emit signals.""" | ||
117 | 329 | |||
118 | 330 | def __init__(self, *a, **kw): | ||
119 | 331 | super(ObjectWithSignals, self).__init__() | ||
120 | 332 | self._callbacks = defaultdict(list) | ||
121 | 333 | |||
122 | 334 | def connect(self, signal, callback): | ||
123 | 335 | """Connect a signal with a callback.""" | ||
124 | 336 | self._callbacks[signal].append(callback) | ||
125 | 337 | |||
126 | 338 | def disconnect(self, signal, callback): | ||
127 | 339 | """Connect a signal with a callback.""" | ||
128 | 340 | self._callbacks[signal].remove(callback) | ||
129 | 341 | if len(self._callbacks[signal]) == 0: | ||
130 | 342 | self._callbacks.pop(signal) | ||
131 | 343 | |||
132 | 344 | def disconnect_by_func(self, callback): | ||
133 | 345 | """Disconnect 'callback' from every signal.""" | ||
134 | 346 | # do not use iteritems since we may change the dict inside the for | ||
135 | 347 | for signal, callbacks in self._callbacks.items(): | ||
136 | 348 | if callback in callbacks: | ||
137 | 349 | self.disconnect(signal, callback) | ||
138 | 350 | |||
139 | 351 | def emit(self, signal, *args, **kwargs): | ||
140 | 352 | """Emit 'signal' passing *args, **kwargs to every callback.""" | ||
141 | 353 | for callback in self._callbacks[signal]: | ||
142 | 354 | callback(*args, **kwargs) | ||
143 | 355 | |||
144 | 356 | |||
145 | 357 | class FakedCache(ObjectWithSignals, dict): | ||
146 | 358 | """A faked cache.""" | ||
147 | 359 | |||
148 | 360 | def __init__(self, *a, **kw): | ||
149 | 361 | super(FakedCache, self).__init__() | ||
150 | 362 | self.ready = False | ||
151 | 363 | |||
152 | 364 | def open(self): | ||
153 | 365 | """Open this cache.""" | ||
154 | 366 | self.ready = True | ||
155 | 367 | |||
156 | 368 | def component_available(self, distro_codename, component): | ||
157 | 369 | """Return whether 'component' is available in 'distro_codename'.""" | ||
158 | 370 | |||
159 | 371 | def get_addons(self, pkgname): | ||
160 | 372 | """Return (recommended, suggested) addons for 'pkgname'.""" | ||
161 | 373 | return ([], []) | ||
162 | 374 | |||
163 | 375 | def get_total_size_on_install(self, pkgname, addons_to_install, | ||
164 | 376 | addons_to_remove, archive_suite): | ||
165 | 377 | """Return a fake (total_download_size, total_install_size) result.""" | ||
166 | 378 | return (0, 0) | ||
167 | 317 | 379 | ||
168 | === modified file 'softwarecenter/ui/gtk3/models/appstore2.py' | |||
169 | --- softwarecenter/ui/gtk3/models/appstore2.py 2012-05-18 18:42:27 +0000 | |||
170 | +++ softwarecenter/ui/gtk3/models/appstore2.py 2012-05-22 12:42:24 +0000 | |||
171 | @@ -115,9 +115,7 @@ | |||
172 | 115 | self.icons = icons | 115 | self.icons = icons |
173 | 116 | self.icon_size = icon_size | 116 | self.icon_size = icon_size |
174 | 117 | 117 | ||
178 | 118 | # cache the 'missing icon' used in the treeview for apps without an | 118 | self._missing_icon = None # delay this until actually needed |
176 | 119 | # icon | ||
177 | 120 | self._missing_icon = icons.load_icon(Icons.MISSING_APP, icon_size, 0) | ||
179 | 121 | if global_icon_cache: | 119 | if global_icon_cache: |
180 | 122 | self.icon_cache = _app_icon_cache | 120 | self.icon_cache = _app_icon_cache |
181 | 123 | else: | 121 | else: |
182 | @@ -146,6 +144,14 @@ | |||
183 | 146 | on_image_download_complete, pkgname) | 144 | on_image_download_complete, pkgname) |
184 | 147 | image_downloader.download_file(url, icon_file_path) | 145 | image_downloader.download_file(url, icon_file_path) |
185 | 148 | 146 | ||
186 | 147 | @property | ||
187 | 148 | def missing_icon(self): | ||
188 | 149 | # cache the 'missing icon' used in treeviews for apps without an icon | ||
189 | 150 | if self._missing_icon is None: | ||
190 | 151 | self._missing_icon = self.icons.load_icon(Icons.MISSING_APP, | ||
191 | 152 | self.icon_size, 0) | ||
192 | 153 | return self._missing_icon | ||
193 | 154 | |||
194 | 149 | def update_availability(self, doc): | 155 | def update_availability(self, doc): |
195 | 150 | doc.available = None | 156 | doc.available = None |
196 | 151 | doc.installed = None | 157 | doc.installed = None |
197 | @@ -228,10 +234,10 @@ | |||
198 | 228 | self.get_pkgname(doc), | 234 | self.get_pkgname(doc), |
199 | 229 | full_icon_file_name) | 235 | full_icon_file_name) |
200 | 230 | # display the missing icon while the real one downloads | 236 | # display the missing icon while the real one downloads |
202 | 231 | self.icon_cache[icon_name] = self._missing_icon | 237 | self.icon_cache[icon_name] = self.missing_icon |
203 | 232 | except GObject.GError as e: | 238 | except GObject.GError as e: |
204 | 233 | LOG.debug("get_icon returned '%s'" % e) | 239 | LOG.debug("get_icon returned '%s'" % e) |
206 | 234 | return self._missing_icon | 240 | return self.missing_icon |
207 | 235 | 241 | ||
208 | 236 | def get_review_stats(self, doc): | 242 | def get_review_stats(self, doc): |
209 | 237 | return self.review_loader.get_review_stats(self.get_application(doc)) | 243 | return self.review_loader.get_review_stats(self.get_application(doc)) |
210 | 238 | 244 | ||
211 | === modified file 'softwarecenter/ui/gtk3/views/catview_gtk.py' | |||
212 | --- softwarecenter/ui/gtk3/views/catview_gtk.py 2012-03-16 16:52:54 +0000 | |||
213 | +++ softwarecenter/ui/gtk3/views/catview_gtk.py 2012-05-22 12:42:24 +0000 | |||
214 | @@ -28,9 +28,12 @@ | |||
215 | 28 | 28 | ||
216 | 29 | import softwarecenter.paths | 29 | import softwarecenter.paths |
217 | 30 | from softwarecenter.db.application import Application | 30 | from softwarecenter.db.application import Application |
221 | 31 | from softwarecenter.enums import (NonAppVisibility, | 31 | from softwarecenter.enums import ( |
222 | 32 | SortMethods, | 32 | NonAppVisibility, |
223 | 33 | TOP_RATED_CAROUSEL_LIMIT) | 33 | PkgStates, |
224 | 34 | SortMethods, | ||
225 | 35 | TOP_RATED_CAROUSEL_LIMIT, | ||
226 | 36 | ) | ||
227 | 34 | from softwarecenter.utils import wait_for_apt_cache_ready | 37 | from softwarecenter.utils import wait_for_apt_cache_ready |
228 | 35 | from softwarecenter.ui.gtk3.models.appstore2 import AppPropertiesHelper | 38 | from softwarecenter.ui.gtk3.models.appstore2 import AppPropertiesHelper |
229 | 36 | from softwarecenter.ui.gtk3.widgets.viewport import Viewport | 39 | from softwarecenter.ui.gtk3.widgets.viewport import Viewport |
230 | @@ -224,6 +227,8 @@ | |||
231 | 224 | apps_filter, apps_limit=0): | 227 | apps_filter, apps_limit=0): |
232 | 225 | CategoriesViewGtk.__init__(self, datadir, desktopdir, cache, db, icons, | 228 | CategoriesViewGtk.__init__(self, datadir, desktopdir, cache, db, icons, |
233 | 226 | apps_filter, apps_limit=0) | 229 | apps_filter, apps_limit=0) |
234 | 230 | self.top_rated = None | ||
235 | 231 | self.exhibit_banner = None | ||
236 | 227 | 232 | ||
237 | 228 | # sections | 233 | # sections |
238 | 229 | self.departments = None | 234 | self.departments = None |
239 | @@ -337,24 +342,41 @@ | |||
240 | 337 | flags=['nonapps-visible']) | 342 | flags=['nonapps-visible']) |
241 | 338 | self.emit("category-selected", cat) | 343 | self.emit("category-selected", cat) |
242 | 339 | 344 | ||
243 | 345 | def _pkg_available(self, pkgname): | ||
244 | 346 | try: | ||
245 | 347 | state = Application("", pkgname).get_details(self.db).pkg_state | ||
246 | 348 | except: | ||
247 | 349 | available = False | ||
248 | 350 | else: | ||
249 | 351 | available = state not in (PkgStates.NOT_FOUND, PkgStates.ERROR) | ||
250 | 352 | return available | ||
251 | 353 | |||
252 | 354 | def _filter_and_set_exhibits(self, sca_client, exhibit_list): | ||
253 | 355 | result = [] | ||
254 | 356 | # filter out those exhibits that are not available in this run | ||
255 | 357 | for exhibit in exhibit_list: | ||
256 | 358 | available = all(self._pkg_available(p) for p in | ||
257 | 359 | exhibit.package_names.split(',')) | ||
258 | 360 | if available: | ||
259 | 361 | result.append(exhibit) | ||
260 | 362 | |||
261 | 363 | self.exhibit_banner.set_exhibits(result) | ||
262 | 364 | |||
263 | 340 | def _append_banner_ads(self): | 365 | def _append_banner_ads(self): |
268 | 341 | exhibit_banner = ExhibitBanner() | 366 | self.exhibit_banner = ExhibitBanner() |
269 | 342 | exhibit_banner.set_exhibits([FeaturedExhibit(), | 367 | self.exhibit_banner.set_exhibits([FeaturedExhibit()]) |
270 | 343 | ]) | 368 | self.exhibit_banner.connect( |
271 | 344 | exhibit_banner.connect("show-exhibits-clicked", self._on_show_exhibits) | 369 | "show-exhibits-clicked", self._on_show_exhibits) |
272 | 345 | 370 | ||
273 | 346 | # query using the agent | 371 | # query using the agent |
274 | 347 | scagent = SoftwareCenterAgent() | 372 | scagent = SoftwareCenterAgent() |
277 | 348 | scagent.connect( | 373 | scagent.connect("exhibits", self._filter_and_set_exhibits) |
276 | 349 | "exhibits", lambda sca, l: exhibit_banner.set_exhibits(l)) | ||
278 | 350 | scagent.query_exhibits() | 374 | scagent.query_exhibits() |
279 | 351 | 375 | ||
280 | 352 | a = Gtk.Alignment() | 376 | a = Gtk.Alignment() |
281 | 353 | a.set_padding(0, StockEms.SMALL, 0, 0) | 377 | a.set_padding(0, StockEms.SMALL, 0, 0) |
284 | 354 | a.add(exhibit_banner) | 378 | a.add(self.exhibit_banner) |
283 | 355 | |||
285 | 356 | self.vbox.pack_start(a, False, False, 0) | 379 | self.vbox.pack_start(a, False, False, 0) |
286 | 357 | return | ||
287 | 358 | 380 | ||
288 | 359 | def _append_departments(self): | 381 | def _append_departments(self): |
289 | 360 | # set the departments section to use the label markup we have just | 382 | # set the departments section to use the label markup we have just |
290 | @@ -382,6 +404,8 @@ | |||
291 | 382 | # FIXME: _update_{top_rated,whats_new,recommended_for_you}_content() | 404 | # FIXME: _update_{top_rated,whats_new,recommended_for_you}_content() |
292 | 383 | # duplicates a lot of code | 405 | # duplicates a lot of code |
293 | 384 | def _update_top_rated_content(self): | 406 | def _update_top_rated_content(self): |
294 | 407 | if self.top_rated is None: | ||
295 | 408 | return | ||
296 | 385 | # remove any existing children from the grid widget | 409 | # remove any existing children from the grid widget |
297 | 386 | self.top_rated.remove_all() | 410 | self.top_rated.remove_all() |
298 | 387 | # get top_rated category and docs | 411 | # get top_rated category and docs |
299 | @@ -715,21 +739,24 @@ | |||
300 | 715 | #return | 739 | #return |
301 | 716 | 740 | ||
302 | 717 | 741 | ||
304 | 718 | def get_test_window_catview(): | 742 | def get_test_window_catview(db=None): |
305 | 719 | 743 | ||
306 | 720 | def on_category_selected(view, cat): | 744 | def on_category_selected(view, cat): |
307 | 721 | print "on_category_selected view: ", view | 745 | print "on_category_selected view: ", view |
308 | 722 | print "on_category_selected cat: ", cat | 746 | print "on_category_selected cat: ", cat |
309 | 723 | 747 | ||
313 | 724 | from softwarecenter.db.pkginfo import get_pkg_info | 748 | if db is None: |
314 | 725 | cache = get_pkg_info() | 749 | from softwarecenter.db.pkginfo import get_pkg_info |
315 | 726 | cache.open() | 750 | cache = get_pkg_info() |
316 | 751 | cache.open() | ||
317 | 727 | 752 | ||
323 | 728 | from softwarecenter.db.database import StoreDatabase | 753 | from softwarecenter.db.database import StoreDatabase |
324 | 729 | xapian_base_path = "/var/cache/software-center" | 754 | xapian_base_path = "/var/cache/software-center" |
325 | 730 | pathname = os.path.join(xapian_base_path, "xapian") | 755 | pathname = os.path.join(xapian_base_path, "xapian") |
326 | 731 | db = StoreDatabase(pathname, cache) | 756 | db = StoreDatabase(pathname, cache) |
327 | 732 | db.open() | 757 | db.open() |
328 | 758 | else: | ||
329 | 759 | cache = db._aptcache | ||
330 | 733 | 760 | ||
331 | 734 | import softwarecenter.paths | 761 | import softwarecenter.paths |
332 | 735 | datadir = softwarecenter.paths.datadir | 762 | datadir = softwarecenter.paths.datadir |
333 | 736 | 763 | ||
334 | === modified file 'test/gtk3/test_app.py' | |||
335 | --- test/gtk3/test_app.py 2012-05-16 15:52:07 +0000 | |||
336 | +++ test/gtk3/test_app.py 2012-05-22 12:42:24 +0000 | |||
337 | @@ -8,7 +8,7 @@ | |||
338 | 8 | 8 | ||
339 | 9 | from mock import Mock | 9 | from mock import Mock |
340 | 10 | 10 | ||
342 | 11 | from testutils import get_mock_options, setup_test_env | 11 | from testutils import FakedCache, get_mock_options, setup_test_env |
343 | 12 | setup_test_env() | 12 | setup_test_env() |
344 | 13 | 13 | ||
345 | 14 | import softwarecenter.paths | 14 | import softwarecenter.paths |
346 | @@ -17,40 +17,6 @@ | |||
347 | 17 | from softwarecenter.ui.gtk3 import app | 17 | from softwarecenter.ui.gtk3 import app |
348 | 18 | 18 | ||
349 | 19 | 19 | ||
350 | 20 | class FakedCache(dict): | ||
351 | 21 | """A faked cache.""" | ||
352 | 22 | |||
353 | 23 | def __init__(self, *a, **kw): | ||
354 | 24 | super(FakedCache, self).__init__() | ||
355 | 25 | self._callbacks = defaultdict(list) | ||
356 | 26 | self.ready = False | ||
357 | 27 | |||
358 | 28 | def open(self): | ||
359 | 29 | """Open this cache.""" | ||
360 | 30 | self.ready = True | ||
361 | 31 | |||
362 | 32 | def connect(self, signal, callback): | ||
363 | 33 | """Connect a signal with a callback.""" | ||
364 | 34 | self._callbacks[signal].append(callback) | ||
365 | 35 | |||
366 | 36 | def disconnect_by_func(self, callback): | ||
367 | 37 | """Disconnect 'callback' from every signal.""" | ||
368 | 38 | for signal, cb in self._callbacks.iteritems(): | ||
369 | 39 | if cb == callback: | ||
370 | 40 | self._callbacks[signal].remove(callback) | ||
371 | 41 | if len(self._callbacks[signal]) == 0: | ||
372 | 42 | self._callbacks.pop(signal) | ||
373 | 43 | |||
374 | 44 | def get_addons(self, pkgname): | ||
375 | 45 | """Return (recommended, suggested) addons for 'pkgname'.""" | ||
376 | 46 | return ([],[]) | ||
377 | 47 | |||
378 | 48 | def get_total_size_on_install(self,pkgname, addons_to_install, | ||
379 | 49 | addons_to_remove, archive_suite): | ||
380 | 50 | """Return a fake (total_download_size, total_install_size) result.""" | ||
381 | 51 | return (0, 0) | ||
382 | 52 | |||
383 | 53 | |||
384 | 54 | class ParsePackagesArgsTestCase(unittest.TestCase): | 20 | class ParsePackagesArgsTestCase(unittest.TestCase): |
385 | 55 | """Test suite for the parse_packages_args helper.""" | 21 | """Test suite for the parse_packages_args helper.""" |
386 | 56 | 22 | ||
387 | @@ -109,7 +75,7 @@ | |||
388 | 109 | fname = __file__ | 75 | fname = __file__ |
389 | 110 | assert os.path.exists(fname) | 76 | assert os.path.exists(fname) |
390 | 111 | self.assertRaises(DebFileOpenError, app.parse_packages_args, fname) | 77 | self.assertRaises(DebFileOpenError, app.parse_packages_args, fname) |
392 | 112 | 78 | ||
393 | 113 | 79 | ||
394 | 114 | class ParsePackagesWithAptPrefixTestCase(ParsePackagesArgsTestCase): | 80 | class ParsePackagesWithAptPrefixTestCase(ParsePackagesArgsTestCase): |
395 | 115 | 81 | ||
396 | 116 | 82 | ||
397 | === modified file 'test/gtk3/test_catview.py' | |||
398 | --- test/gtk3/test_catview.py 2012-03-15 22:23:21 +0000 | |||
399 | +++ test/gtk3/test_catview.py 2012-05-22 12:42:24 +0000 | |||
400 | @@ -1,66 +1,81 @@ | |||
401 | 1 | import unittest | ||
402 | 2 | |||
403 | 1 | from gi.repository import Gtk | 3 | from gi.repository import Gtk |
404 | 2 | import time | ||
405 | 3 | import unittest | ||
406 | 4 | from mock import patch, Mock | 4 | from mock import patch, Mock |
407 | 5 | 5 | ||
408 | 6 | from testutils import setup_test_env | 6 | from testutils import setup_test_env |
409 | 7 | setup_test_env() | 7 | setup_test_env() |
410 | 8 | 8 | ||
411 | 9 | import softwarecenter.distro | ||
412 | 10 | import softwarecenter.paths | ||
413 | 11 | |||
414 | 12 | from softwarecenter.db.database import StoreDatabase | ||
415 | 9 | from softwarecenter.enums import SortMethods | 13 | from softwarecenter.enums import SortMethods |
420 | 10 | from softwarecenter.testutils import (get_test_db, | 14 | from softwarecenter.testutils import ( |
421 | 11 | make_recommender_agent_recommend_me_dict) | 15 | do_events_with_sleep, |
422 | 12 | 16 | do_events, | |
423 | 13 | class TestCatView(unittest.TestCase): | 17 | FakedCache, |
424 | 18 | get_test_db, | ||
425 | 19 | make_recommender_agent_recommend_me_dict, | ||
426 | 20 | ObjectWithSignals, | ||
427 | 21 | ) | ||
428 | 22 | from softwarecenter.ui.gtk3.views import catview_gtk | ||
429 | 23 | from softwarecenter.ui.gtk3.views.catview_gtk import get_test_window_catview | ||
430 | 24 | from softwarecenter.ui.gtk3.widgets.containers import FramedHeaderBox | ||
431 | 25 | from softwarecenter.ui.gtk3.widgets.spinner import SpinnerNotebook | ||
432 | 26 | |||
433 | 27 | |||
434 | 28 | class CatViewBaseTestCase(unittest.TestCase): | ||
435 | 29 | |||
436 | 30 | @classmethod | ||
437 | 31 | def setUpClass(cls): | ||
438 | 32 | cls.db = get_test_db() | ||
439 | 14 | 33 | ||
440 | 15 | def setUp(self): | 34 | def setUp(self): |
442 | 16 | self.db = get_test_db() | 35 | self._cat = None |
443 | 36 | self.win = get_test_window_catview(self.db) | ||
444 | 37 | self.addCleanup(self.win.destroy) | ||
445 | 38 | self.notebook = self.win.get_child() | ||
446 | 39 | self.lobby = self.win.get_data("lobby") | ||
447 | 40 | self.subcat_view = self.win.get_data("subcat") | ||
448 | 41 | self.rec_panel = self.lobby.recommended_for_you_panel | ||
449 | 17 | 42 | ||
450 | 18 | def _on_category_selected(self, subcatview, category): | 43 | def _on_category_selected(self, subcatview, category): |
451 | 19 | #print "**************", subcatview, category | ||
452 | 20 | self._cat = category | 44 | self._cat = category |
460 | 21 | 45 | ||
461 | 22 | def test_subcatview_top_rated(self): | 46 | |
462 | 23 | from softwarecenter.ui.gtk3.views.catview_gtk import get_test_window_catview | 47 | class TopAndWhatsNewTestCase(CatViewBaseTestCase): |
463 | 24 | # get the widgets we need | 48 | |
464 | 25 | win = get_test_window_catview() | 49 | def test_top_rated(self): |
458 | 26 | lobby = win.get_data("lobby") | ||
459 | 27 | |||
465 | 28 | # simulate review-stats refresh | 50 | # simulate review-stats refresh |
469 | 29 | lobby._update_top_rated_content = Mock() | 51 | self.lobby._update_top_rated_content = Mock() |
470 | 30 | lobby.reviews_loader.emit("refresh-review-stats-finished", []) | 52 | self.lobby.reviews_loader.emit("refresh-review-stats-finished", []) |
471 | 31 | self.assertTrue(lobby._update_top_rated_content.called) | 53 | self.assertTrue(self.lobby._update_top_rated_content.called) |
472 | 32 | 54 | ||
473 | 33 | # test clicking top_rated | 55 | # test clicking top_rated |
477 | 34 | lobby.connect("category-selected", self._on_category_selected) | 56 | self.lobby.connect("category-selected", self._on_category_selected) |
478 | 35 | lobby.top_rated_frame.more.clicked() | 57 | self.lobby.top_rated_frame.more.clicked() |
479 | 36 | self._p() | 58 | do_events() |
480 | 37 | self.assertNotEqual(self._cat, None) | 59 | self.assertNotEqual(self._cat, None) |
481 | 38 | self.assertEqual(self._cat.name, "Top Rated") | 60 | self.assertEqual(self._cat.name, "Top Rated") |
482 | 39 | self.assertEqual(self._cat.sortmode, SortMethods.BY_TOP_RATED) | 61 | self.assertEqual(self._cat.sortmode, SortMethods.BY_TOP_RATED) |
491 | 40 | win.destroy() | 62 | |
492 | 41 | 63 | def test_new(self): | |
485 | 42 | def test_subcatview_new(self): | ||
486 | 43 | from softwarecenter.ui.gtk3.views.catview_gtk import get_test_window_catview | ||
487 | 44 | # get the widgets we need | ||
488 | 45 | win = get_test_window_catview() | ||
489 | 46 | lobby = win.get_data("lobby") | ||
490 | 47 | |||
493 | 48 | # test db reopen triggers whats-new update | 64 | # test db reopen triggers whats-new update |
497 | 49 | lobby._update_whats_new_content = Mock() | 65 | self.lobby._update_whats_new_content = Mock() |
498 | 50 | lobby.db.emit("reopen") | 66 | self.lobby.db.emit("reopen") |
499 | 51 | self.assertTrue(lobby._update_whats_new_content.called) | 67 | self.assertTrue(self.lobby._update_whats_new_content.called) |
500 | 52 | 68 | ||
501 | 53 | # test clicking new | 69 | # test clicking new |
505 | 54 | lobby.connect("category-selected", self._on_category_selected) | 70 | self.lobby.connect("category-selected", self._on_category_selected) |
506 | 55 | lobby.whats_new_frame.more.clicked() | 71 | self.lobby.whats_new_frame.more.clicked() |
507 | 56 | self._p() | 72 | do_events() |
508 | 57 | self.assertNotEqual(self._cat, None) | 73 | self.assertNotEqual(self._cat, None) |
509 | 58 | # encoding is utf-8 (since r2218, see category.py) | 74 | # encoding is utf-8 (since r2218, see category.py) |
510 | 59 | self.assertEqual(self._cat.name, 'What\xe2\x80\x99s New') | 75 | self.assertEqual(self._cat.name, 'What\xe2\x80\x99s New') |
511 | 60 | self.assertEqual(self._cat.sortmode, SortMethods.BY_CATALOGED_TIME) | 76 | self.assertEqual(self._cat.sortmode, SortMethods.BY_CATALOGED_TIME) |
512 | 61 | win.destroy() | ||
513 | 62 | 77 | ||
515 | 63 | def test_subcatview_new_no_sort_info_yet(self): | 78 | def test_new_no_sort_info_yet(self): |
516 | 64 | # ensure that we don't show a empty "whats new" category | 79 | # ensure that we don't show a empty "whats new" category |
517 | 65 | # see LP: #865985 | 80 | # see LP: #865985 |
518 | 66 | from softwarecenter.testutils import get_test_db | 81 | from softwarecenter.testutils import get_test_db |
519 | @@ -68,7 +83,7 @@ | |||
520 | 68 | cache = db._aptcache | 83 | cache = db._aptcache |
521 | 69 | # simulate a fresh install with no catalogedtime info | 84 | # simulate a fresh install with no catalogedtime info |
522 | 70 | del db._axi_values["catalogedtime"] | 85 | del db._axi_values["catalogedtime"] |
524 | 71 | 86 | ||
525 | 72 | from softwarecenter.testutils import get_test_gtk3_icon_cache | 87 | from softwarecenter.testutils import get_test_gtk3_icon_cache |
526 | 73 | icons = get_test_gtk3_icon_cache() | 88 | icons = get_test_gtk3_icon_cache() |
527 | 74 | 89 | ||
528 | @@ -76,7 +91,6 @@ | |||
529 | 76 | apps_filter = AppFilter(db, cache) | 91 | apps_filter = AppFilter(db, cache) |
530 | 77 | 92 | ||
531 | 78 | from softwarecenter.distro import get_distro | 93 | from softwarecenter.distro import get_distro |
532 | 79 | import softwarecenter.paths | ||
533 | 80 | from softwarecenter.paths import APP_INSTALL_PATH | 94 | from softwarecenter.paths import APP_INSTALL_PATH |
534 | 81 | from softwarecenter.ui.gtk3.views.catview_gtk import LobbyViewGtk | 95 | from softwarecenter.ui.gtk3.views.catview_gtk import LobbyViewGtk |
535 | 82 | view = LobbyViewGtk(softwarecenter.paths.datadir, APP_INSTALL_PATH, | 96 | view = LobbyViewGtk(softwarecenter.paths.datadir, APP_INSTALL_PATH, |
536 | @@ -85,6 +99,7 @@ | |||
537 | 85 | 99 | ||
538 | 86 | # gui | 100 | # gui |
539 | 87 | win = Gtk.Window() | 101 | win = Gtk.Window() |
540 | 102 | self.addCleanup(win.destroy) | ||
541 | 88 | win.set_size_request(800, 400) | 103 | win.set_size_request(800, 400) |
542 | 89 | 104 | ||
543 | 90 | scroll = Gtk.ScrolledWindow() | 105 | scroll = Gtk.ScrolledWindow() |
544 | @@ -93,171 +108,198 @@ | |||
545 | 93 | win.add(scroll) | 108 | win.add(scroll) |
546 | 94 | win.show() | 109 | win.show() |
547 | 95 | # test visibility | 110 | # test visibility |
549 | 96 | self._p() | 111 | do_events() |
550 | 97 | self.assertFalse(view.whats_new_frame.get_property("visible")) | 112 | self.assertFalse(view.whats_new_frame.get_property("visible")) |
620 | 98 | self._p() | 113 | |
621 | 99 | win.destroy() | 114 | |
622 | 100 | 115 | class RecommendationsTestCase(CatViewBaseTestCase): | |
623 | 101 | def test_subcatview_recommended_for_you_opt_in_display(self): | 116 | """The test suite for the recommendations .""" |
624 | 102 | 117 | ||
625 | 103 | # patch the recommender UUID value to insure that we are not opted-in for this test | 118 | @patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in') |
626 | 104 | get_recommender_opted_in_patcher = patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in') | 119 | def test_recommended_for_you_opt_in_display( |
627 | 105 | self.addCleanup(get_recommender_opted_in_patcher.stop) | 120 | self, mock_get_recommender_opted_in): |
628 | 106 | mock_get_recommender_opted_in = get_recommender_opted_in_patcher.start() | 121 | # patch the recommender UUID value to ensure that we are not opted-in |
629 | 107 | mock_get_recommender_opted_in.return_value = False | 122 | # for this test |
630 | 108 | 123 | mock_get_recommender_opted_in.return_value = False | |
631 | 109 | from softwarecenter.ui.gtk3.views.catview_gtk import get_test_window_catview | 124 | |
632 | 110 | # get the widgets we need | 125 | do_events() |
633 | 111 | win = get_test_window_catview() | 126 | self.assertEqual(self.rec_panel.spinner_notebook.get_current_page(), |
634 | 112 | lobby = win.get_data("lobby") | 127 | FramedHeaderBox.CONTENT) |
635 | 113 | rec_panel = lobby.recommended_for_you_panel | 128 | self.assertTrue(self.rec_panel.opt_in_vbox.get_property("visible")) |
636 | 114 | self._p() | 129 | |
637 | 115 | from softwarecenter.ui.gtk3.widgets.containers import FramedHeaderBox | 130 | # patch out the agent query method to avoid making the actual server call |
638 | 116 | self.assertTrue(rec_panel.spinner_notebook.get_current_page() == FramedHeaderBox.CONTENT) | 131 | @patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in') |
639 | 117 | self.assertTrue(rec_panel.opt_in_vbox.get_property("visible")) | 132 | @patch('softwarecenter.backend.recagent.RecommenderAgent' |
640 | 118 | win.destroy() | 133 | '.post_submit_profile') |
641 | 119 | 134 | def test_recommended_for_you_spinner_display( | |
642 | 120 | # patch out the agent query method to avoid making the actual server call | 135 | self, mock_query, mock_get_recommender_opted_in): |
643 | 121 | @patch('softwarecenter.backend.recagent.RecommenderAgent' | 136 | # patch the recommender UUID value to insure that we are not opted-in |
644 | 122 | '.post_submit_profile') | 137 | # for this test |
645 | 123 | def test_subcatview_recommended_for_you_spinner_display(self, mock_query): | 138 | mock_get_recommender_opted_in.return_value = False |
646 | 124 | 139 | ||
647 | 125 | # patch the recommender UUID value to insure that we are not opted-in for this test | 140 | # click the opt-in button to initiate the process, |
648 | 126 | get_recommender_opted_in_patcher = patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in') | 141 | # this will show the spinner |
649 | 127 | self.addCleanup(get_recommender_opted_in_patcher.stop) | 142 | self.rec_panel.opt_in_button.emit('clicked') |
650 | 128 | mock_get_recommender_opted_in = get_recommender_opted_in_patcher.start() | 143 | do_events() |
651 | 129 | mock_get_recommender_opted_in.return_value = False | 144 | self.assertEqual(self.rec_panel.spinner_notebook.get_current_page(), |
652 | 130 | 145 | SpinnerNotebook.SPINNER_PAGE) | |
653 | 131 | from softwarecenter.ui.gtk3.views.catview_gtk import get_test_window_catview | 146 | self.assertTrue(self.rec_panel.opt_in_vbox.get_property("visible")) |
654 | 132 | # get the widgets we need | 147 | |
655 | 133 | win = get_test_window_catview() | 148 | # patch out the agent query method to avoid making the actual server call |
656 | 134 | lobby = win.get_data("lobby") | 149 | @patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in') |
657 | 135 | rec_panel = lobby.recommended_for_you_panel | 150 | @patch('softwarecenter.backend.recagent.RecommenderAgent' |
658 | 136 | self._p() | 151 | '.post_submit_profile') |
659 | 137 | # click the opt-in button to initiate the process, this will show the spinner | 152 | def test_recommended_for_you_display_recommendations(self, |
660 | 138 | rec_panel.opt_in_button.emit('clicked') | 153 | mock_query, mock_get_recommender_opted_in): |
661 | 139 | self._p() | 154 | # patch the recommender UUID value to insure that we are not opted-in |
662 | 140 | from softwarecenter.ui.gtk3.widgets.spinner import SpinnerNotebook | 155 | # for this test |
663 | 141 | self.assertTrue(rec_panel.spinner_notebook.get_current_page() == SpinnerNotebook.SPINNER_PAGE) | 156 | mock_get_recommender_opted_in.return_value = False |
664 | 142 | self.assertTrue(rec_panel.opt_in_vbox.get_property("visible")) | 157 | |
665 | 143 | win.destroy() | 158 | # click the opt-in button to initiate the process, |
666 | 144 | 159 | # this will show the spinner | |
667 | 145 | # patch out the agent query method to avoid making the actual server call | 160 | self.rec_panel.opt_in_button.emit('clicked') |
668 | 146 | @patch('softwarecenter.backend.recagent.RecommenderAgent' | 161 | do_events() |
669 | 147 | '.post_submit_profile') | 162 | self.rec_panel._update_recommended_for_you_content() |
670 | 148 | def test_subcatview_recommended_for_you_display_recommendations(self, mock_query): | 163 | do_events() |
602 | 149 | |||
603 | 150 | # patch the recommender UUID value to insure that we are not opted-in for this test | ||
604 | 151 | get_recommender_opted_in_patcher = patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in') | ||
605 | 152 | self.addCleanup(get_recommender_opted_in_patcher.stop) | ||
606 | 153 | mock_get_recommender_opted_in = get_recommender_opted_in_patcher.start() | ||
607 | 154 | mock_get_recommender_opted_in.return_value = False | ||
608 | 155 | |||
609 | 156 | from softwarecenter.ui.gtk3.views.catview_gtk import get_test_window_catview | ||
610 | 157 | # get the widgets we need | ||
611 | 158 | win = get_test_window_catview() | ||
612 | 159 | lobby = win.get_data("lobby") | ||
613 | 160 | rec_panel = lobby.recommended_for_you_panel | ||
614 | 161 | self._p() | ||
615 | 162 | # click the opt-in button to initiate the process, this will show the spinner | ||
616 | 163 | rec_panel.opt_in_button.emit('clicked') | ||
617 | 164 | self._p() | ||
618 | 165 | rec_panel._update_recommended_for_you_content() | ||
619 | 166 | self._p() | ||
671 | 167 | # we fake the callback from the agent here | 164 | # we fake the callback from the agent here |
680 | 168 | lobby.recommended_for_you_panel.recommended_for_you_cat._recommend_me_result( | 165 | for_you = self.lobby.recommended_for_you_panel.recommended_for_you_cat |
681 | 169 | None, | 166 | for_you._recommend_me_result(None, |
682 | 170 | make_recommender_agent_recommend_me_dict()) | 167 | make_recommender_agent_recommend_me_dict()) |
683 | 171 | self.assertNotEqual( | 168 | self.assertNotEqual(for_you.get_documents(self.db), []) |
684 | 172 | lobby.recommended_for_you_panel.recommended_for_you_cat.get_documents(self.db), []) | 169 | self.assertEqual(self.rec_panel.spinner_notebook.get_current_page(), |
685 | 173 | from softwarecenter.ui.gtk3.widgets.spinner import SpinnerNotebook | 170 | SpinnerNotebook.CONTENT_PAGE) |
686 | 174 | self.assertTrue(rec_panel.spinner_notebook.get_current_page() == SpinnerNotebook.CONTENT_PAGE) | 171 | do_events() |
679 | 175 | self._p() | ||
687 | 176 | # test clicking recommended_for_you More button | 172 | # test clicking recommended_for_you More button |
691 | 177 | lobby.connect("category-selected", self._on_category_selected) | 173 | self.lobby.connect("category-selected", self._on_category_selected) |
692 | 178 | lobby.recommended_for_you_panel.more.clicked() | 174 | self.lobby.recommended_for_you_panel.more.clicked() |
693 | 179 | self._p() | 175 | # this is delayed for some reason so we need to sleep here |
694 | 176 | do_events_with_sleep() | ||
695 | 180 | self.assertNotEqual(self._cat, None) | 177 | self.assertNotEqual(self._cat, None) |
696 | 181 | self.assertEqual(self._cat.name, "Recommended For You") | 178 | self.assertEqual(self._cat.name, "Recommended For You") |
699 | 182 | win.destroy() | 179 | |
698 | 183 | |||
700 | 184 | # patch out the agent query method to avoid making the actual server call | 180 | # patch out the agent query method to avoid making the actual server call |
701 | 181 | @patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in') | ||
702 | 185 | @patch('softwarecenter.backend.recagent.RecommenderAgent' | 182 | @patch('softwarecenter.backend.recagent.RecommenderAgent' |
703 | 186 | '.query_recommend_me') | 183 | '.query_recommend_me') |
710 | 187 | def test_subcatview_recommended_for_you_display_recommendations_not_opted_in(self, mock_query): | 184 | def test_recommended_for_you_display_recommendations_not_opted_in(self, |
711 | 188 | 185 | mock_query, mock_get_recommender_opted_in): | |
712 | 189 | # patch the recommender UUID value to insure that we are not opted-in for this test | 186 | # patch the recommender UUID value to insure that we are not opted-in |
713 | 190 | get_recommender_opted_in_patcher = patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in') | 187 | # for this test |
708 | 191 | self.addCleanup(get_recommender_opted_in_patcher.stop) | ||
709 | 192 | mock_get_recommender_opted_in = get_recommender_opted_in_patcher.start() | ||
714 | 193 | mock_get_recommender_opted_in.return_value = False | 188 | mock_get_recommender_opted_in.return_value = False |
719 | 194 | 189 | ||
716 | 195 | from softwarecenter.ui.gtk3.views.catview_gtk import get_test_window_catview | ||
717 | 196 | # get the widgets we need | ||
718 | 197 | win = get_test_window_catview() | ||
720 | 198 | # we want to work in the "subcat" view | 190 | # we want to work in the "subcat" view |
729 | 199 | notebook = win.get_child() | 191 | self.notebook.next_page() |
730 | 200 | notebook.next_page() | 192 | |
731 | 201 | 193 | do_events() | |
732 | 202 | subcat_view = win.get_data("subcat") | 194 | visible = self.subcat_view.recommended_for_you_in_cat.get_property( |
733 | 203 | self._p() | 195 | "visible") |
734 | 204 | self.assertFalse(subcat_view.recommended_for_you_in_cat.get_property("visible")) | 196 | self.assertFalse(visible) |
735 | 205 | win.destroy() | 197 | |
728 | 206 | |||
736 | 207 | # patch out the agent query method to avoid making the actual server call | 198 | # patch out the agent query method to avoid making the actual server call |
737 | 199 | @patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in') | ||
738 | 208 | @patch('softwarecenter.backend.recagent.RecommenderAgent' | 200 | @patch('softwarecenter.backend.recagent.RecommenderAgent' |
739 | 209 | '.query_recommend_me') | 201 | '.query_recommend_me') |
746 | 210 | def test_subcatview_recommended_for_you_display_recommendations_opted_in(self, mock_query): | 202 | def test_recommended_for_you_display_recommendations_opted_in( |
747 | 211 | 203 | self, mock_query, mock_get_recommender_opted_in): | |
748 | 212 | # patch the recommender UUID value to insure that we are not opted-in for this test | 204 | # patch the recommender UUID value to insure that we are not opted-in |
749 | 213 | get_recommender_opted_in_patcher = patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in') | 205 | # for this test |
744 | 214 | self.addCleanup(get_recommender_opted_in_patcher.stop) | ||
745 | 215 | mock_get_recommender_opted_in = get_recommender_opted_in_patcher.start() | ||
750 | 216 | mock_get_recommender_opted_in.return_value = True | 206 | mock_get_recommender_opted_in.return_value = True |
755 | 217 | 207 | ||
752 | 218 | from softwarecenter.ui.gtk3.views.catview_gtk import get_test_window_catview | ||
753 | 219 | # get the widgets we need | ||
754 | 220 | win = get_test_window_catview() | ||
756 | 221 | # we want to work in the "subcat" view | 208 | # we want to work in the "subcat" view |
763 | 222 | notebook = win.get_child() | 209 | self.notebook.next_page() |
764 | 223 | notebook.next_page() | 210 | |
765 | 224 | 211 | rec_cat_panel = self.subcat_view.recommended_for_you_in_cat | |
760 | 225 | subcat_view = win.get_data("subcat") | ||
761 | 226 | rec_cat_panel = subcat_view.recommended_for_you_in_cat | ||
762 | 227 | self._p() | ||
766 | 228 | rec_cat_panel._update_recommended_for_you_content() | 212 | rec_cat_panel._update_recommended_for_you_content() |
768 | 229 | self._p() | 213 | do_events() |
769 | 230 | # we fake the callback from the agent here | 214 | # we fake the callback from the agent here |
770 | 231 | rec_cat_panel.recommended_for_you_cat._recommend_me_result( | 215 | rec_cat_panel.recommended_for_you_cat._recommend_me_result( |
771 | 232 | None, | 216 | None, |
772 | 233 | make_recommender_agent_recommend_me_dict()) | 217 | make_recommender_agent_recommend_me_dict()) |
774 | 234 | result_docs = rec_cat_panel.recommended_for_you_cat.get_documents(self.db) | 218 | result_docs = rec_cat_panel.recommended_for_you_cat.get_documents( |
775 | 219 | self.db) | ||
776 | 235 | self.assertNotEqual(result_docs, []) | 220 | self.assertNotEqual(result_docs, []) |
779 | 236 | # check that we are getting the correct number of results, corresponding | 221 | # check that we are getting the correct number of results, |
780 | 237 | # to the following Internet items: | 222 | # corresponding to the following Internet items: |
781 | 238 | # Mangler, Midori, Midori Private Browsing, Psi | 223 | # Mangler, Midori, Midori Private Browsing, Psi |
782 | 239 | self.assertTrue(len(result_docs) == 4) | 224 | self.assertTrue(len(result_docs) == 4) |
785 | 240 | from softwarecenter.ui.gtk3.widgets.spinner import SpinnerNotebook | 225 | self.assertEqual(rec_cat_panel.spinner_notebook.get_current_page(), |
786 | 241 | self.assertTrue(rec_cat_panel.spinner_notebook.get_current_page() == SpinnerNotebook.CONTENT_PAGE) | 226 | SpinnerNotebook.CONTENT_PAGE) |
787 | 242 | # check that the tiles themselves are visible | 227 | # check that the tiles themselves are visible |
792 | 243 | self._p() | 228 | do_events() |
793 | 244 | self.assertTrue(rec_cat_panel.recommended_for_you_content.get_property("visible")) | 229 | self.assertTrue(rec_cat_panel.recommended_for_you_content.get_property( |
794 | 245 | self.assertTrue(rec_cat_panel.recommended_for_you_content.get_children()[0].title.get_property("visible")) | 230 | "visible")) |
795 | 246 | self._p() | 231 | self.assertTrue(rec_cat_panel.recommended_for_you_content.get_children( |
796 | 232 | )[0].title.get_property("visible")) | ||
797 | 233 | do_events() | ||
798 | 247 | # test clicking recommended_for_you More button | 234 | # test clicking recommended_for_you More button |
800 | 248 | subcat_view.connect("category-selected", self._on_category_selected) | 235 | self.subcat_view.connect( |
801 | 236 | "category-selected", self._on_category_selected) | ||
802 | 249 | rec_cat_panel.more.clicked() | 237 | rec_cat_panel.more.clicked() |
804 | 250 | self._p() | 238 | # this is delayed for some reason so we need to sleep here |
805 | 239 | do_events_with_sleep() | ||
806 | 251 | self.assertNotEqual(self._cat, None) | 240 | self.assertNotEqual(self._cat, None) |
807 | 252 | self.assertEqual(self._cat.name, "Recommended For You in Internet") | 241 | self.assertEqual(self._cat.name, "Recommended For You in Internet") |
816 | 253 | win.destroy() | 242 | |
817 | 254 | 243 | ||
818 | 255 | def _p(self): | 244 | class ExhibitsTestCase(unittest.TestCase): |
819 | 256 | for i in range(5): | 245 | """The test suite for the exhibits carousel.""" |
820 | 257 | time.sleep(0.1) | 246 | |
821 | 258 | while Gtk.events_pending(): | 247 | def setUp(self): |
822 | 259 | Gtk.main_iteration() | 248 | self.datadir = softwarecenter.paths.datadir |
823 | 260 | 249 | self.desktopdir = softwarecenter.paths.APP_INSTALL_PATH | |
824 | 250 | self.cache = FakedCache() | ||
825 | 251 | self.db = StoreDatabase(cache=self.cache) | ||
826 | 252 | self.lobby = catview_gtk.LobbyViewGtk(datadir=self.datadir, | ||
827 | 253 | desktopdir=self.desktopdir, cache=self.cache, db=self.db, | ||
828 | 254 | icons=None, apps_filter=None) | ||
829 | 255 | self.addCleanup(self.lobby.destroy) | ||
830 | 256 | |||
831 | 257 | def _get_banner_from_lobby(self): | ||
832 | 258 | return self.lobby.vbox.get_children()[-1].get_child() | ||
833 | 259 | |||
834 | 260 | def test_featured_exhibit_by_default(self): | ||
835 | 261 | """Show the featured exhibit before querying the remote service.""" | ||
836 | 262 | self.lobby._append_banner_ads() | ||
837 | 263 | |||
838 | 264 | banner = self._get_banner_from_lobby() | ||
839 | 265 | self.assertEqual(1, len(banner.exhibits)) | ||
840 | 266 | self.assertIsInstance(banner.exhibits[0], catview_gtk.FeaturedExhibit) | ||
841 | 267 | |||
842 | 268 | def test_no_exhibit_if_not_available(self): | ||
843 | 269 | """The exhibit should not be shown if the package is not available.""" | ||
844 | 270 | exhibit = Mock() | ||
845 | 271 | exhibit.package_names = u'foobarbaz' | ||
846 | 272 | |||
847 | 273 | sca = ObjectWithSignals() | ||
848 | 274 | sca.query_exhibits = lambda: sca.emit('exhibits', sca, [exhibit]) | ||
849 | 275 | |||
850 | 276 | with patch.object(catview_gtk, 'SoftwareCenterAgent', lambda: sca): | ||
851 | 277 | self.lobby._append_banner_ads() | ||
852 | 278 | |||
853 | 279 | banner = self._get_banner_from_lobby() | ||
854 | 280 | self.assertEqual(1, len(banner.exhibits)) | ||
855 | 281 | self.assertIsInstance(banner.exhibits[0], catview_gtk.FeaturedExhibit) | ||
856 | 282 | |||
857 | 283 | def test_exhibit_if_available(self): | ||
858 | 284 | """The exhibit should be shown if the package is not available.""" | ||
859 | 285 | exhibit = Mock() | ||
860 | 286 | exhibit.package_names = u'foobarbaz' | ||
861 | 287 | exhibit.banner_url = 'banner' | ||
862 | 288 | |||
863 | 289 | pkg = Mock() | ||
864 | 290 | pkg.banner_url = '' | ||
865 | 291 | pkg.title_translated = '' | ||
866 | 292 | self.cache[u'foobarbaz'] = pkg | ||
867 | 293 | |||
868 | 294 | sca = ObjectWithSignals() | ||
869 | 295 | sca.query_exhibits = lambda: sca.emit('exhibits', sca, [exhibit]) | ||
870 | 296 | |||
871 | 297 | with patch.object(catview_gtk, 'SoftwareCenterAgent', lambda: sca): | ||
872 | 298 | self.lobby._append_banner_ads() | ||
873 | 299 | |||
874 | 300 | banner = self._get_banner_from_lobby() | ||
875 | 301 | self.assertEqual(1, len(banner.exhibits)) | ||
876 | 302 | self.assertIs(banner.exhibits[0], exhibit) | ||
877 | 261 | 303 | ||
878 | 262 | 304 | ||
879 | 263 | if __name__ == "__main__": | 305 | if __name__ == "__main__": |