Merge lp:~gary-lasker/software-center/offline-opt-in-lp965397-for-quantal into lp:software-center

Proposed by Gary Lasker
Status: Merged
Merged at revision: 3074
Proposed branch: lp:~gary-lasker/software-center/offline-opt-in-lp965397-for-quantal
Merge into: lp:software-center
Diff against target: 356 lines (+138/-90)
3 files modified
softwarecenter/backend/recagent.py (+17/-1)
softwarecenter/ui/gtk3/widgets/recommendations.py (+56/-26)
tests/gtk3/test_catview.py (+65/-63)
To merge this branch: bzr merge lp:~gary-lasker/software-center/offline-opt-in-lp965397-for-quantal
Reviewer Review Type Date Requested Status
Michael Vogt Approve
Review via email: mp+116961@code.launchpad.net

Commit message

* lp:~gary-lasker/software-center/offline-opt-in-lp965397:
   - implement offline recommendations opt-in behavior as specified
     in the Ubuntu Software Center specification (LP: #965397)

Description of the change

This is targeted for trunk only currently as it includes a new string.

This branch implements the offline recommendations opt-in behavior as specified in bug 965397 (and the corresponding section of the referenced spec). Note that all of the combinations of turning on and off recommendations with network available and not available should do the right thing. Note also that state of the recommendations menu item is consistently updated as well.

Unit tests are included.

Oh, also please note that I re-enabled two of the recommendations unit tests that had been turned off. For me, these work fine now, so I'm not sure why they were disabled initially, and I wonder whether the condition that necessited that is now resolved. mvo, please check these to make sure these work for you as well.

Thanks very much for your review!

To post a comment you must log in.
Revision history for this message
Gary Lasker (gary-lasker) wrote :

I'll bring in the comments from the first MP for 5.2 (https://code.launchpad.net/~gary-lasker/software-center/offline-opt-in-lp965397/+merge/116780), that one has been superceded by this one:

Michael Vogt (mvo) wrote 9 hours ago:

On Wed, Jul 25, 2012 at 11:13:20PM -0000, Gary Lasker wrote:
> This branch implements the offline recommendations opt-in behavior as specified in bug 965397 (and the corresponding section of the referenced spec). Note that all of the combinations of turning on and off recommendations with network available and not available should do the right thing. Note also that state of the recommendations menu item is consistently updated as well.
>
> Unit tests are included.

Thanks for the branch. This looks good.

Could you please target trunk? We want to upload it there first as its
a string change so we can not land this in 5.2 as it is, it would
require coordination with the translators again. Plus when this hits
quantal we will get the translations for free so puting the fix
into 5.2 later will be easier.

I noticed that its using a static check if the network is available or
not but does not react to network state signal changes. I think that
would be really nice from a UI point-of-view. Right now if the user
has no network and opts in he sees the message that recommendations will
appear when he is online next. When he/she goes online then the
message stays there which looks a little bit confusing. It works fine
when I close/restart software-center. Or is there a mechanism for
reacting to network changes that I overlooked maybe?

> Oh, also please note that I re-enabled two of the recommendations unit tests that had been turned off. For me, these work fine now, so I'm not sure why they were disabled initially, and I wonder whether the condition that necessited that is now resolved. mvo, please check these to make sure these work for you as well.

Interessting, that works for me now as well, might be some sort of
race that is not always triggered. I will leave them enabled :)

Cheers,
 Michael

Revision history for this message
Gary Lasker (gary-lasker) wrote :

Hi Michael, thanks for your review! Indeed, this change is not suitable for SRU (at this point) because of the string change, so I'll retarget for trunk.

Regarding adding a listener for the network coming online, I think I will make that change in a separate branch and propose it separately.

Revision history for this message
Gary Lasker (gary-lasker) wrote :

I've added the network listener functionality and the merge proposal for that (which depends on this branch as a prerequisite) can be found here:

  https://code.launchpad.net/~gary-lasker/software-center/offline-network-events/+merge/117000

Thanks again!

Revision history for this message
Michael Vogt (mvo) wrote :
Download full text (6.0 KiB)

On Thu, Jul 26, 2012 at 08:46:26PM -0000, Gary Lasker wrote:
> This is targeted for trunk only currently as it includes a new string.
[..]

Thanks for the update of this branch to trunk.

I reviewed this in detail now. Its a bit of a long reply, I'm sorry
for that. Pleae note that there is nothing wrong with the branch, it
can land as it is. It got a bit long because of various ideas I had
while reading the code and the diff and I wanted to share them. All of
this can be done in future branches if you prefer to land this as it
is. Please also note that those are suggestions, its fine to not agree
with them :)

Some comments inline:

> === modified file 'softwarecenter/backend/recagent.py'
> --- softwarecenter/backend/recagent.py 2012-04-02 18:23:20 +0000
> +++ softwarecenter/backend/recagent.py 2012-07-26 20:45:23 +0000
> @@ -95,6 +95,15 @@
> return hashlib.md5(str(profile)).hexdigest()
>
> @property
> + def opt_in_requested(self):
> + if self.config.has_option("general", "recommender_opt_in_requested"):
> + opt_in_requested = self.config.get("general",
> + "recommender_opt_in_requested")
> + if opt_in_requested == "True":
> + return True
[..]

The config parser has a "getboolean" method that can be used here, it
will automatically convert from various strings and you can simply
return the value of it which should make this easier.

> + def recommender_opt_in_requested(self, opt_in_requested):
> + if opt_in_requested:
> + self.config.set("general",
> + "recommender_opt_in_requested",
> + "True")
> + else:
> + self.config.set("general",
> + "recommender_opt_in_requested",
> + "False")

If we are sure we awlays gets booleans from opt_in_requested, then
this could probably be written in a more compat form as:

          self.config.set("general",
                          "recommender_opt_in_requested",
                          str(value))

(not that it matter much :).

[..]
> === modified file 'tests/gtk3/test_catview.py'
> --- tests/gtk3/test_catview.py 2012-07-13 07:39:30 +0000
> +++ tests/gtk3/test_catview.py 2012-07-26 20:45:23 +0000
> @@ -33,8 +33,17 @@
> def setUpClass(cls):
> cls.db = get_test_db()
>
> - def setUp(self):
> + @patch('softwarecenter.ui.gtk3.widgets.recommendations.get_sso_backend')
> + @patch('softwarecenter.ui.gtk3.widgets.recommendations.RecommenderAgent'
> + '.is_opted_in')
> + # patch out the agent query method to avoid making the actual server call
> + @patch('softwarecenter.ui.gtk3.widgets.recommendations.RecommenderAgent'
> + '.post_submit_profile')
> + def setUp(self, mock_query, mock_recommender_is_opted_in, mock_sso):
> self._cat = None
> + # patch the recommender to specify that we are not opted-in at
> + # the start of each test
> + mock_recommender_is_opted_in.return_value = False
> self.win = get_test_window_catview(self.db)
> self.addCleanup(self.win.des...

Read more...

Revision history for this message
Michael Vogt (mvo) :
review: Approve
3078. By Gary Lasker

use config's getboolean to simplify the recommender_opt_in_requested code

3079. By Gary Lasker

refactor test_catview so that the patch decorators needed for the recommendations tests are isolated to those tests

3080. By Gary Lasker

more minor test cleanup per review comments from mvo

Revision history for this message
Gary Lasker (gary-lasker) wrote :

Hi mvo! I made the first few changes per your recommendations and retested.

Regarding your comment:

> - could we simply assume that if there is a uuid generated, that
> means that the user requested a opt-in? or is the seperate
> recommender_opt_in_requested config needed (e.g. to make things
> simpler)? like just generate the uuid on opt-in?

The uuid is used to indicate a successful opt-in, so as such it is not set until the profile upload and initial recommendations download is complete. The recommender_opt_in_requested is specifically for the case where opt-in is requested but network connectivity is not available, so it is there only to track the case where an opt-in is pending. This is reset once the opt-in is successfully completed and the uuid generated.

The last couple of recommendations that you made are a bit more involved, so I will hold off on those for another branch.

Thanks as always for your detailed review!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'softwarecenter/backend/recagent.py'
--- softwarecenter/backend/recagent.py 2012-04-02 18:23:20 +0000
+++ softwarecenter/backend/recagent.py 2012-07-31 22:07:20 +0000
@@ -95,6 +95,15 @@
95 return hashlib.md5(str(profile)).hexdigest()95 return hashlib.md5(str(profile)).hexdigest()
9696
97 @property97 @property
98 def opt_in_requested(self):
99 if self.config.has_option("general", "recommender_opt_in_requested"):
100 opt_in_requested = self.config.getboolean(
101 "general",
102 "recommender_opt_in_requested")
103 return opt_in_requested
104 return False
105
106 @property
98 def recommender_uuid(self):107 def recommender_uuid(self):
99 if self.config.has_option("general", "recommender_uuid"):108 if self.config.has_option("general", "recommender_uuid"):
100 recommender_uuid = self.config.get("general",109 recommender_uuid = self.config.get("general",
@@ -118,6 +127,11 @@
118 def _set_recommender_uuid(self, uuid):127 def _set_recommender_uuid(self, uuid):
119 self.config.set("general", "recommender_uuid", uuid)128 self.config.set("general", "recommender_uuid", uuid)
120129
130 def recommender_opt_in_requested(self, opt_in_requested):
131 self.config.set("general",
132 "recommender_opt_in_requested",
133 str(opt_in_requested))
134
121 def post_submit_profile(self, db):135 def post_submit_profile(self, db):
122 """ This will post the users profile to the recommender server136 """ This will post the users profile to the recommender server
123 and also generate the UUID for the user if that is not137 and also generate the UUID for the user if that is not
@@ -222,7 +236,7 @@
222 Return True is the user is currently opted-in to the recommender236 Return True is the user is currently opted-in to the recommender
223 service237 service
224 """238 """
225 if self.recommender_uuid:239 if self.recommender_uuid or self.opt_in_requested:
226 return True240 return True
227 else:241 else:
228 return False242 return False
@@ -230,6 +244,8 @@
230 def opt_out(self):244 def opt_out(self):
231 self.config.set("general", "recommender_uuid", "")245 self.config.set("general", "recommender_uuid", "")
232 self.config.set("general", "recommender_profile_id", "")246 self.config.set("general", "recommender_profile_id", "")
247 if self.recommender_opt_in_requested:
248 self.recommender_opt_in_requested(False)
233249
234 def _on_server_status_data(self, spawner, piston_server_status):250 def _on_server_status_data(self, spawner, piston_server_status):
235 self.emit("server-status", piston_server_status)251 self.emit("server-status", piston_server_status)
236252
=== modified file 'softwarecenter/ui/gtk3/widgets/recommendations.py'
--- softwarecenter/ui/gtk3/widgets/recommendations.py 2012-06-21 08:29:33 +0000
+++ softwarecenter/ui/gtk3/widgets/recommendations.py 2012-07-31 22:07:20 +0000
@@ -144,12 +144,12 @@
144 }144 }
145145
146 TURN_ON_RECOMMENDATIONS_TEXT = _(u"Turn On Recommendations")146 TURN_ON_RECOMMENDATIONS_TEXT = _(u"Turn On Recommendations")
147 # FIXME: This will be the default text once LP: #986437 is approved and
148 # ready to be merged/SRU'd
149 RECOMMENDATIONS_OPT_IN_TEXT = _(u"To make recommendations, "147 RECOMMENDATIONS_OPT_IN_TEXT = _(u"To make recommendations, "
150 "Ubuntu Software Center "148 "Ubuntu Software Center "
151 "will occasionally send to Canonical a list "149 "will occasionally send to Canonical a list "
152 "of software currently installed.")150 "of software currently installed.")
151 NO_NETWORK_RECOMMENDATIONS_TEXT = _(u"Recommendations will appear "
152 "when next online.")
153153
154 def __init__(self, catview):154 def __init__(self, catview):
155 RecommendationsPanel.__init__(self, catview)155 RecommendationsPanel.__init__(self, catview)
@@ -157,37 +157,60 @@
157 self.set_header_label(_(u"Recommended For You"))157 self.set_header_label(_(u"Recommended For You"))
158 self.recommended_for_you_content = None158 self.recommended_for_you_content = None
159 if self.recommender_agent.is_opted_in():159 if self.recommender_agent.is_opted_in():
160 self._try_sso_login()160 if network_state_is_connected():
161 self._try_sso_login()
162 else:
163 self._show_no_network_view()
161 else:164 else:
162 self._show_opt_in_view()165 self._show_opt_in_view()
163166
164 def _show_opt_in_view(self):167 def _show_opt_in_view(self):
165 # opt in box168 # opt in box
166 vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, StockEms.MEDIUM)169 self.recommended_for_you_content = Gtk.Box.new(
167 vbox.set_border_width(StockEms.MEDIUM)170 Gtk.Orientation.VERTICAL,
168 self.opt_in_vbox = vbox # for tests171 StockEms.MEDIUM)
169 self.recommended_for_you_content = vbox # hook it up to the rest172 self.recommended_for_you_content.set_border_width(StockEms.MEDIUM)
170
171 self.add(self.recommended_for_you_content)173 self.add(self.recommended_for_you_content)
172174
173 # opt in button175 # opt in button
174 button = Gtk.Button(_(self.TURN_ON_RECOMMENDATIONS_TEXT))176 self.opt_in_button = Gtk.Button(_(self.TURN_ON_RECOMMENDATIONS_TEXT))
175 button.connect("clicked", self._on_opt_in_button_clicked)177 self.opt_in_button.connect("clicked", self._on_opt_in_button_clicked)
176 hbox = Gtk.Box(Gtk.Orientation.HORIZONTAL)178 hbox = Gtk.Box(Gtk.Orientation.HORIZONTAL)
177 hbox.pack_start(button, False, False, 0)179 hbox.pack_start(self.opt_in_button, False, False, 0)
178 vbox.pack_start(hbox, False, False, 0)180 self.recommended_for_you_content.pack_start(hbox, False, False, 0)
179 self.opt_in_button = button # for tests
180181
181 # opt in text182 # opt in text
182 text = _(self.RECOMMENDATIONS_OPT_IN_TEXT)183 text = _(self.RECOMMENDATIONS_OPT_IN_TEXT)
183 label = Gtk.Label()184 self.opt_in_label = self._create_opt_in_label(text)
184 label.set_use_markup(True)185 self.recommended_for_you_content.pack_start(self.opt_in_label,
185 markup = '<small>%s</small>'186 False, False, 0)
186 label.set_name("subtle-label")187
187 label.set_markup(markup % text)188 def _show_no_network_view(self):
188 label.set_alignment(0, 0.5)189 # display network not available message
189 label.set_line_wrap(True)190 if not self.recommended_for_you_content:
190 vbox.pack_start(label, False, False, 0)191 self.recommended_for_you_content = Gtk.Box.new(
192 Gtk.Orientation.VERTICAL,
193 StockEms.MEDIUM)
194 self.recommended_for_you_content.set_border_width(StockEms.MEDIUM)
195 self.add(self.recommended_for_you_content)
196 text = _(self.NO_NETWORK_RECOMMENDATIONS_TEXT)
197 self.opt_in_label = self._create_opt_in_label(text)
198 self.recommended_for_you_content.pack_start(self.opt_in_label,
199 False, False, 0)
200 else:
201 self.opt_in_button.hide()
202 text = _(self.NO_NETWORK_RECOMMENDATIONS_TEXT)
203 self.opt_in_label.set_markup(self.opt_in_label_markup % text)
204
205 def _create_opt_in_label(self, label_text):
206 opt_in_label = Gtk.Label()
207 opt_in_label.set_use_markup(True)
208 self.opt_in_label_markup = '<small>%s</small>'
209 opt_in_label.set_name("subtle-label")
210 opt_in_label.set_markup(self.opt_in_label_markup % label_text)
211 opt_in_label.set_alignment(0, 0.5)
212 opt_in_label.set_line_wrap(True)
213 return opt_in_label
191214
192 def _on_opt_in_button_clicked(self, button):215 def _on_opt_in_button_clicked(self, button):
193 self.opt_in_to_recommendations_service()216 self.opt_in_to_recommendations_service()
@@ -199,7 +222,12 @@
199 # them here -- a spinner is shown for this process (the spec222 # them here -- a spinner is shown for this process (the spec
200 # wants a progress bar, but we don't have access to real-time223 # wants a progress bar, but we don't have access to real-time
201 # progress info)224 # progress info)
202 self._try_sso_login()225 if network_state_is_connected():
226 self._try_sso_login()
227 else:
228 self._show_no_network_view()
229 self.recommender_agent.recommender_opt_in_requested(True)
230 self.emit("recommendations-opt-in")
203231
204 def opt_out_of_recommendations_service(self):232 def opt_out_of_recommendations_service(self):
205 # tell the backend that the user has opted out233 # tell the backend that the user has opted out
@@ -239,10 +267,12 @@
239 # we are all squared up with SSO login, now we can proceed with the267 # we are all squared up with SSO login, now we can proceed with the
240 # recommendations display, or the profile upload if this is an268 # recommendations display, or the profile upload if this is an
241 # initial opt-in269 # initial opt-in
242 if self.recommender_agent.is_opted_in():270 if not self.recommender_agent.recommender_uuid:
243 self._update_recommended_for_you_content()
244 else:
245 self._upload_user_profile_and_get_recommendations()271 self._upload_user_profile_and_get_recommendations()
272 if self.recommender_agent.recommender_opt_in_requested:
273 self.recommender_agent.recommender_opt_in_requested(False)
274 else:
275 self._update_recommended_for_you_content()
246276
247 def _whoami_error(self, ssologin, e):277 def _whoami_error(self, ssologin, e):
248 self.spinner_notebook.hide_spinner()278 self.spinner_notebook.hide_spinner()
@@ -253,7 +283,7 @@
253 if not network_state_is_connected():283 if not network_state_is_connected():
254 # if there is an error in the SSO whois, first just check if we284 # if there is an error in the SSO whois, first just check if we
255 # have network access and if we do no, just hide the panel285 # have network access and if we do no, just hide the panel
256 self._hide_recommended_for_you_panel()286 self._show_no_network_view()
257 else:287 else:
258 # an error that is not network related indicates that the user's288 # an error that is not network related indicates that the user's
259 # token has likely been revoked or invalidated on the server, for289 # token has likely been revoked or invalidated on the server, for
260290
=== modified file 'tests/gtk3/test_catview.py'
--- tests/gtk3/test_catview.py 2012-07-13 07:39:30 +0000
+++ tests/gtk3/test_catview.py 2012-07-31 22:07:20 +0000
@@ -40,7 +40,6 @@
40 self.notebook = self.win.get_child()40 self.notebook = self.win.get_child()
41 self.lobby = self.win.get_data("lobby")41 self.lobby = self.win.get_data("lobby")
42 self.subcat_view = self.win.get_data("subcat")42 self.subcat_view = self.win.get_data("subcat")
43 self.rec_panel = self.lobby.recommended_for_you_panel
4443
45 def _on_category_selected(self, subcatview, category):44 def _on_category_selected(self, subcatview, category):
46 self._cat = category45 self._cat = category
@@ -111,56 +110,72 @@
111110
112class RecommendationsTestCase(CatViewBaseTestCase):111class RecommendationsTestCase(CatViewBaseTestCase):
113 """The test suite for the recommendations ."""112 """The test suite for the recommendations ."""
114113
115 # FIXME: reenable114 # we need to use a custom setUp method for the recommendations test cases
116 @unittest.skip("Disabled because of race condition in test")115 # so that everything gets configured properly
117 @patch('softwarecenter.ui.gtk3.widgets.recommendations.get_sso_backend')116 @patch('softwarecenter.ui.gtk3.widgets.recommendations.get_sso_backend')
118 @patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in')117 @patch('softwarecenter.ui.gtk3.widgets.recommendations.RecommenderAgent'
119 def test_recommended_for_you_opt_in_display(self,118 '.is_opted_in')
120 mock_get_recommender_opted_in, mock_sso):
121 # patch the recommender UUID value to ensure that we are not opted-in
122 # for this test
123 mock_get_recommender_opted_in.return_value = False
124
125 self.assertEqual(self.rec_panel.spinner_notebook.get_current_page(),
126 FramedHeaderBox.CONTENT)
127 self.assertTrue(self.rec_panel.opt_in_vbox.get_property("visible"))
128
129 # FIXME: reenable
130 @unittest.skip("Disabled because of race condition in test")
131 # patch out the agent query method to avoid making the actual server call119 # patch out the agent query method to avoid making the actual server call
132 @patch('softwarecenter.ui.gtk3.widgets.recommendations.get_sso_backend')120 @patch('softwarecenter.ui.gtk3.widgets.recommendations.RecommenderAgent'
133 @patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in')
134 @patch('softwarecenter.backend.recagent.RecommenderAgent'
135 '.post_submit_profile')121 '.post_submit_profile')
136 def test_recommended_for_you_spinner_display(self,122 def setUp(self, mock_query, mock_recommender_is_opted_in, mock_sso):
137 mock_query, mock_get_recommender_opted_in, mock_sso):123 self._cat = None
138 # patch the recommender UUID value to insure that we are not opted-in124 # patch the recommender to specify that we are not opted-in at
139 # for this test125 # the start of each test
140 mock_get_recommender_opted_in.return_value = False126 mock_recommender_is_opted_in.return_value = False
141127 self.win = get_test_window_catview(self.db)
128 self.addCleanup(self.win.destroy)
129 self.notebook = self.win.get_child()
130 self.lobby = self.win.get_data("lobby")
131 self.subcat_view = self.win.get_data("subcat")
132 self.rec_panel = self.lobby.recommended_for_you_panel
133
134 def test_recommended_for_you_opt_in_display(self):
135 self.assertEqual(self.rec_panel.spinner_notebook.get_current_page(),
136 FramedHeaderBox.CONTENT)
137 self.assertTrue(
138 self.rec_panel.recommended_for_you_content.get_property("visible"))
139
140 # ensure that we are showing the opt-in view
141 self.assertTrue(self.rec_panel.opt_in_button.get_property("visible"))
142 label_text = self.rec_panel.opt_in_label.get_text()
143 self.assertEqual(label_text,
144 self.rec_panel.RECOMMENDATIONS_OPT_IN_TEXT)
145
146 def test_recommended_for_you_spinner_display(self):
142 # click the opt-in button to initiate the process,147 # click the opt-in button to initiate the process,
143 # this will show the spinner148 # this will show the spinner
144 self.rec_panel.opt_in_button.emit('clicked')149 self.rec_panel.opt_in_button.clicked()
145 do_events_with_sleep()150 do_events_with_sleep()
146 self.assertEqual(self.rec_panel.spinner_notebook.get_current_page(),151 self.assertEqual(self.rec_panel.spinner_notebook.get_current_page(),
147 SpinnerNotebook.SPINNER_PAGE)152 SpinnerNotebook.SPINNER_PAGE)
148 self.assertTrue(self.rec_panel.opt_in_vbox.get_visible())153 self.assertTrue(
149154 self.rec_panel.recommended_for_you_content.get_property("visible"))
150 # patch out the agent query method to avoid making the actual server call155
151 @patch('softwarecenter.ui.gtk3.widgets.recommendations.get_sso_backend')156 @patch('softwarecenter.ui.gtk3.widgets.recommendations'
152 @patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in')157 '.network_state_is_connected')
153 @patch('softwarecenter.backend.recagent.RecommenderAgent'158 def test_recommended_for_you_network_not_available(self,
154 '.post_submit_profile')159 mock_network_state_is_connected):
155 def test_recommended_for_you_display_recommendations(self,160 # simulate no network available
156 mock_query, mock_get_recommender_opted_in, mock_sso):161 mock_network_state_is_connected.return_value = False
157 # patch the recommender UUID value to insure that we are not opted-in162 # click the opt-in button to initiate the process
158 # for this test163 self.rec_panel.opt_in_button.clicked()
159 mock_get_recommender_opted_in.return_value = False164 do_events()
160165 self.rec_panel._update_recommended_for_you_content()
166 do_events()
167 self.assertEqual(self.rec_panel.spinner_notebook.get_current_page(),
168 FramedHeaderBox.CONTENT)
169 # ensure that we are showing the network not available view
170 self.assertFalse(self.rec_panel.opt_in_button.get_property("visible"))
171 label_text = self.rec_panel.opt_in_label.get_text()
172 self.assertEqual(label_text,
173 self.rec_panel.NO_NETWORK_RECOMMENDATIONS_TEXT)
174
175 def test_recommended_for_you_display_recommendations(self):
161 # click the opt-in button to initiate the process,176 # click the opt-in button to initiate the process,
162 # this will show the spinner177 # this will show the spinner
163 self.rec_panel.opt_in_button.emit('clicked')178 self.rec_panel.opt_in_button.clicked()
164 do_events()179 do_events()
165 self.rec_panel._update_recommended_for_you_content()180 self.rec_panel._update_recommended_for_you_content()
166 do_events()181 do_events()
@@ -180,17 +195,7 @@
180 self.assertNotEqual(self._cat, None)195 self.assertNotEqual(self._cat, None)
181 self.assertEqual(self._cat.name, "Recommended For You")196 self.assertEqual(self._cat.name, "Recommended For You")
182197
183 # patch out the agent query method to avoid making the actual server call198 def test_recommended_for_you_display_recommendations_not_opted_in(self):
184 @patch('softwarecenter.ui.gtk3.widgets.recommendations.get_sso_backend')
185 @patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in')
186 @patch('softwarecenter.backend.recagent.RecommenderAgent'
187 '.query_recommend_me')
188 def test_recommended_for_you_display_recommendations_not_opted_in(self,
189 mock_query, mock_get_recommender_opted_in, mock_sso):
190 # patch the recommender UUID value to insure that we are not opted-in
191 # for this test
192 mock_get_recommender_opted_in.return_value = False
193
194 # we want to work in the "subcat" view199 # we want to work in the "subcat" view
195 self.notebook.next_page()200 self.notebook.next_page()
196201
@@ -199,17 +204,14 @@
199 "visible")204 "visible")
200 self.assertFalse(visible)205 self.assertFalse(visible)
201206
202 # patch out the agent query method to avoid making the actual server call207 def test_recommended_for_you_display_recommendations_opted_in(self):
203 @patch('softwarecenter.ui.gtk3.widgets.recommendations.get_sso_backend')208 # click the opt-in button to initiate the process,
204 @patch('softwarecenter.backend.recagent.RecommenderAgent.is_opted_in')209 # this will show the spinner
205 @patch('softwarecenter.backend.recagent.RecommenderAgent'210 self.rec_panel.opt_in_button.clicked()
206 '.query_recommend_me')211 do_events()
207 def test_recommended_for_you_display_recommendations_opted_in(self,212 self.rec_panel._update_recommended_for_you_content()
208 mock_query, mock_get_recommender_opted_in, mock_sso):213 do_events()
209 # patch the recommender UUID value to insure that we are not opted-in214
210 # for this test
211 mock_get_recommender_opted_in.return_value = True
212
213 # we want to work in the "subcat" view215 # we want to work in the "subcat" view
214 self.notebook.next_page()216 self.notebook.next_page()
215217

Subscribers

People subscribed via source and target branches