More cleanup after review comments.
[appstream:software-center.git] / test / gtk3 / test_catview.py
1 import time
2 import unittest
3
4 from gi.repository import Gtk
5 from mock import patch, Mock
6
7 from testutils import setup_test_env
8 setup_test_env()
9
10 import softwarecenter.distro
11 import softwarecenter.paths
12
13 from softwarecenter.db.database import StoreDatabase
14 from softwarecenter.enums import SortMethods
15 from softwarecenter.testutils import (
16     FakedCache,
17     get_test_db,
18     make_recommender_agent_recommend_me_dict,
19     ObjectWithSignals,
20 )
21 from softwarecenter.ui.gtk3.views import catview_gtk
22 from softwarecenter.ui.gtk3.views.catview_gtk import get_test_window_catview
23 from softwarecenter.ui.gtk3.widgets.containers import FramedHeaderBox
24 from softwarecenter.ui.gtk3.widgets.spinner import SpinnerNotebook
25
26
27 class TestCatView(unittest.TestCase):
28
29     def setUp(self):
30         self._cat = None
31         self.db = get_test_db()
32
33     def _on_category_selected(self, subcatview, category):
34         self._cat = category
35
36     def test_top_rated(self):
37         # get the widgets we need
38         win = get_test_window_catview()
39         self.addCleanup(win.destroy)
40         lobby = win.get_data("lobby")
41
42         # simulate review-stats refresh
43         lobby._update_top_rated_content = Mock()
44         lobby.reviews_loader.emit("refresh-review-stats-finished", [])
45         self.assertTrue(lobby._update_top_rated_content.called)
46
47         # test clicking top_rated
48         lobby.connect("category-selected", self._on_category_selected)
49         lobby.top_rated_frame.more.clicked()
50         self._p()
51         self.assertNotEqual(self._cat, None)
52         self.assertEqual(self._cat.name, "Top Rated")
53         self.assertEqual(self._cat.sortmode, SortMethods.BY_TOP_RATED)
54
55     def test_new(self):
56         # get the widgets we need
57         win = get_test_window_catview()
58         self.addCleanup(win.destroy)
59         lobby = win.get_data("lobby")
60
61         # test db reopen triggers whats-new update
62         lobby._update_whats_new_content = Mock()
63         lobby.db.emit("reopen")
64         self.assertTrue(lobby._update_whats_new_content.called)
65
66         # test clicking new
67         lobby.connect("category-selected", self._on_category_selected)
68         lobby.whats_new_frame.more.clicked()
69         self._p()
70         self.assertNotEqual(self._cat, None)
71         # encoding is utf-8 (since r2218, see category.py)
72         self.assertEqual(self._cat.name, 'What\xe2\x80\x99s New')
73         self.assertEqual(self._cat.sortmode, SortMethods.BY_CATALOGED_TIME)
74
75     def test_new_no_sort_info_yet(self):
76         # ensure that we don't show a empty "whats new" category
77         # see LP: #865985
78         from softwarecenter.testutils import get_test_db
79         db = get_test_db()
80         cache = db._aptcache
81         # simulate a fresh install with no catalogedtime info
82         del db._axi_values["catalogedtime"]
83
84         from softwarecenter.testutils import get_test_gtk3_icon_cache
85         icons = get_test_gtk3_icon_cache()
86
87         from softwarecenter.db.appfilter import AppFilter
88         apps_filter = AppFilter(db, cache)
89
90         from softwarecenter.distro import get_distro
91         import softwarecenter.paths
92         from softwarecenter.paths import APP_INSTALL_PATH
93         from softwarecenter.ui.gtk3.views.catview_gtk import LobbyViewGtk
94         view = LobbyViewGtk(softwarecenter.paths.datadir, APP_INSTALL_PATH,
95                             cache, db, icons, get_distro(), apps_filter)
96         view.show()
97
98         # gui
99         win = Gtk.Window()
100         self.addCleanup(win.destroy)
101         win.set_size_request(800, 400)
102
103         scroll = Gtk.ScrolledWindow()
104         scroll.add(view)
105         scroll.show()
106         win.add(scroll)
107         win.show()
108         # test visibility
109         self._p()
110         self.assertFalse(view.whats_new_frame.get_property("visible"))
111         self._p()
112
113     def test_recommended_for_you_opt_in_display(self):
114         # patch the recommender UUID value to ensure that we are not opted-in
115         # for this test
116         recommender_opted_in_patcher = patch(
117             'softwarecenter.backend.recagent.RecommenderAgent.is_opted_in')
118         self.addCleanup(recommender_opted_in_patcher.stop)
119         mock_get_recommender_opted_in = recommender_opted_in_patcher.start()
120         mock_get_recommender_opted_in.return_value = False
121
122         # get the widgets we need
123         win = get_test_window_catview()
124         self.addCleanup(win.destroy)
125
126         lobby = win.get_data("lobby")
127         rec_panel = lobby.recommended_for_you_panel
128         self._p()
129         self.assertEqual(rec_panel.spinner_notebook.get_current_page(),
130                          FramedHeaderBox.CONTENT)
131         self.assertTrue(rec_panel.opt_in_vbox.get_property("visible"))
132
133     # patch out the agent query method to avoid making the actual server call
134     @patch('softwarecenter.backend.recagent.RecommenderAgent'
135            '.post_submit_profile')
136     def test_recommended_for_you_spinner_display(self, mock_query):
137         # patch the recommender UUID value to insure that we are not opted-in
138         # for this test
139         recommender_opted_in_patcher = patch(
140             'softwarecenter.backend.recagent.RecommenderAgent.is_opted_in')
141         self.addCleanup(recommender_opted_in_patcher.stop)
142         mock_get_recommender_opted_in = recommender_opted_in_patcher.start()
143         mock_get_recommender_opted_in.return_value = False
144
145         # get the widgets we need
146         win = get_test_window_catview()
147         self.addCleanup(win.destroy)
148         lobby = win.get_data("lobby")
149         rec_panel = lobby.recommended_for_you_panel
150         self._p()
151         # click the opt-in button to initiate the process,
152         # this will show the spinner
153         rec_panel.opt_in_button.emit('clicked')
154         self._p()
155         self.assertEqual(rec_panel.spinner_notebook.get_current_page(),
156                          SpinnerNotebook.SPINNER_PAGE)
157         self.assertTrue(rec_panel.opt_in_vbox.get_property("visible"))
158
159     # patch out the agent query method to avoid making the actual server call
160     @patch('softwarecenter.backend.recagent.RecommenderAgent'
161            '.post_submit_profile')
162     def test_recommended_for_you_display_recommendations(self,
163             mock_query):
164         # patch the recommender UUID value to insure that we are not opted-in
165         # for this test
166         recommender_opted_in_patcher = patch(
167             'softwarecenter.backend.recagent.RecommenderAgent.is_opted_in')
168         self.addCleanup(recommender_opted_in_patcher.stop)
169         mock_get_recommender_opted_in = recommender_opted_in_patcher.start()
170         mock_get_recommender_opted_in.return_value = False
171
172         # get the widgets we need
173         win = get_test_window_catview()
174         self.addCleanup(win.destroy)
175         lobby = win.get_data("lobby")
176         rec_panel = lobby.recommended_for_you_panel
177         self._p()
178         # click the opt-in button to initiate the process,
179         # this will show the spinner
180         rec_panel.opt_in_button.emit('clicked')
181         self._p()
182         rec_panel._update_recommended_for_you_content()
183         self._p()
184         # we fake the callback from the agent here
185         for_you = lobby.recommended_for_you_panel.recommended_for_you_cat
186         for_you._recommend_me_result(None,
187             make_recommender_agent_recommend_me_dict())
188         self.assertNotEqual(for_you.get_documents(self.db), [])
189         self.assertEqual(rec_panel.spinner_notebook.get_current_page(),
190                          SpinnerNotebook.CONTENT_PAGE)
191         self._p()
192         # test clicking recommended_for_you More button
193         lobby.connect("category-selected", self._on_category_selected)
194         lobby.recommended_for_you_panel.more.clicked()
195         self._p()
196         self.assertNotEqual(self._cat, None)
197         self.assertEqual(self._cat.name, "Recommended For You")
198
199     # patch out the agent query method to avoid making the actual server call
200     @patch('softwarecenter.backend.recagent.RecommenderAgent'
201            '.query_recommend_me')
202     def test_recommended_for_you_display_recommendations_not_opted_in(self,
203             mock_query):
204         # patch the recommender UUID value to insure that we are not opted-in
205         # for this test
206         recommender_opted_in_patcher = patch(
207             'softwarecenter.backend.recagent.RecommenderAgent.is_opted_in')
208         self.addCleanup(recommender_opted_in_patcher.stop)
209         mock_get_recommender_opted_in = recommender_opted_in_patcher.start()
210         mock_get_recommender_opted_in.return_value = False
211
212         # get the widgets we need
213         win = get_test_window_catview()
214         self.addCleanup(win.destroy)
215         # we want to work in the "subcat" view
216         notebook = win.get_child()
217         notebook.next_page()
218
219         subcat_view = win.get_data("subcat")
220         self._p()
221         self.assertFalse(subcat_view.recommended_for_you_in_cat.get_property(
222             "visible"))
223
224     # patch out the agent query method to avoid making the actual server call
225     @patch('softwarecenter.backend.recagent.RecommenderAgent'
226            '.query_recommend_me')
227     def test_recommended_for_you_display_recommendations_opted_in(self, mock_query):
228         # patch the recommender UUID value to insure that we are not opted-in
229         # for this test
230         recommender_opted_in_patcher = patch(
231             'softwarecenter.backend.recagent.RecommenderAgent.is_opted_in')
232         self.addCleanup(recommender_opted_in_patcher.stop)
233         mock_get_recommender_opted_in = recommender_opted_in_patcher.start()
234         mock_get_recommender_opted_in.return_value = True
235
236         # get the widgets we need
237         win = get_test_window_catview()
238         self.addCleanup(win.destroy)
239         # we want to work in the "subcat" view
240         notebook = win.get_child()
241         notebook.next_page()
242
243         subcat_view = win.get_data("subcat")
244         rec_cat_panel = subcat_view.recommended_for_you_in_cat
245         self._p()
246         rec_cat_panel._update_recommended_for_you_content()
247         self._p()
248         # we fake the callback from the agent here
249         rec_cat_panel.recommended_for_you_cat._recommend_me_result(
250                                 None,
251                                 make_recommender_agent_recommend_me_dict())
252         result_docs = rec_cat_panel.recommended_for_you_cat.get_documents(
253             self.db)
254         self.assertNotEqual(result_docs, [])
255         # check that we are getting the correct number of results,
256         # corresponding to the following Internet items:
257         #   Mangler, Midori, Midori Private Browsing, Psi
258         self.assertTrue(len(result_docs) == 4)
259         self.assertEqual(rec_cat_panel.spinner_notebook.get_current_page(),
260                          SpinnerNotebook.CONTENT_PAGE)
261         # check that the tiles themselves are visible
262         self._p()
263         self.assertTrue(rec_cat_panel.recommended_for_you_content.get_property(
264             "visible"))
265         self.assertTrue(rec_cat_panel.recommended_for_you_content.get_children(
266             )[0].title.get_property("visible"))
267         self._p()
268         # test clicking recommended_for_you More button
269         subcat_view.connect("category-selected", self._on_category_selected)
270         rec_cat_panel.more.clicked()
271         self._p()
272         self.assertNotEqual(self._cat, None)
273         self.assertEqual(self._cat.name, "Recommended For You in Internet")
274
275     def _p(self):
276         for i in range(5):
277             time.sleep(0.1)
278             while Gtk.events_pending():
279                 Gtk.main_iteration()
280
281
282 class ExhibitsTestCase(unittest.TestCase):
283     """The test suite for the exhibits carousel."""
284
285     def setUp(self):
286         self.datadir = softwarecenter.paths.datadir
287         self.desktopdir = softwarecenter.paths.APP_INSTALL_PATH
288         self.cache = FakedCache()
289         self.db = StoreDatabase(cache=self.cache)
290         self.lobby = catview_gtk.LobbyViewGtk(datadir=self.datadir,
291             desktopdir=self.desktopdir, cache=self.cache, db=self.db,
292             icons=None, apps_filter=None)
293         self.addCleanup(self.lobby.destroy)
294
295     def _get_banner_from_lobby(self):
296         return self.lobby.vbox.get_children()[-1].get_child()
297
298     def test_featured_exhibit_by_default(self):
299         """Show the featured exhibit before querying the remote service."""
300         self.lobby._append_banner_ads()
301
302         banner = self._get_banner_from_lobby()
303         self.assertEqual(1, len(banner.exhibits))
304         self.assertIsInstance(banner.exhibits[0], catview_gtk.FeaturedExhibit)
305
306     def test_no_exhibit_if_not_available(self):
307         """The exhibit should not be shown if the package is not available."""
308         exhibit = Mock()
309         exhibit.package_names = u'foobarbaz'
310
311         sca = ObjectWithSignals()
312         sca.query_exhibits = lambda: sca.emit('exhibits', sca, [exhibit])
313
314         with patch.object(catview_gtk, 'SoftwareCenterAgent', lambda: sca):
315             self.lobby._append_banner_ads()
316
317         banner = self._get_banner_from_lobby()
318         self.assertEqual(1, len(banner.exhibits))
319         self.assertIsInstance(banner.exhibits[0], catview_gtk.FeaturedExhibit)
320
321     def test_exhibit_if_available(self):
322         """The exhibit should be shown if the package is available."""
323         exhibit = Mock()
324         exhibit.package_names = u'foobarbaz'
325         exhibit.banner_url = 'banner'
326         exhibit.title_translated = ''
327
328         self.cache[u'foobarbaz'] = Mock()
329
330         sca = ObjectWithSignals()
331         sca.query_exhibits = lambda: sca.emit('exhibits', sca, [exhibit])
332
333         with patch.object(catview_gtk, 'SoftwareCenterAgent', lambda: sca):
334             self.lobby._append_banner_ads()
335
336         banner = self._get_banner_from_lobby()
337         self.assertEqual(1, len(banner.exhibits))
338         self.assertIs(banner.exhibits[0], exhibit)
339
340     def test_exhibit_if_mixed_availability(self):
341         """The exhibit should be shown even if some are not available."""
342         # available exhibit
343         exhibit = Mock()
344         exhibit.package_names = u'foobarbaz'
345         exhibit.banner_url = 'banner'
346         exhibit.title_translated = ''
347
348         self.cache[u'foobarbaz'] = Mock()
349
350         # not available exhibit
351         other = Mock()
352         other.package_names = u'not-there'
353
354         sca = ObjectWithSignals()
355         sca.query_exhibits = lambda: sca.emit('exhibits', sca,
356                                               [exhibit, other])
357
358         with patch.object(catview_gtk, 'SoftwareCenterAgent', lambda: sca):
359             self.lobby._append_banner_ads()
360
361         banner = self._get_banner_from_lobby()
362         self.assertEqual(1, len(banner.exhibits))
363         self.assertIs(banner.exhibits[0], exhibit)
364
365
366 if __name__ == "__main__":
367     #import logging
368     #logging.basicConfig(level=logging.DEBUG)
369     unittest.main()