Merge lp:~gary-lasker/software-center/recommended-installed-feedback into lp:software-center

Proposed by Gary Lasker
Status: Superseded
Proposed branch: lp:~gary-lasker/software-center/recommended-installed-feedback
Merge into: lp:software-center
Prerequisite: lp:~gary-lasker/software-center/update-to-latest-recommender-client
Diff against target: 321 lines (+145/-23)
6 files modified
softwarecenter/backend/piston/sreclient_pristine.py (+1/-1)
softwarecenter/backend/recagent.py (+24/-1)
softwarecenter/enums.py (+4/-0)
softwarecenter/ui/gtk3/widgets/recommendations.py (+33/-0)
tests/gtk3/test_catview.py (+73/-21)
tests/test_recagent.py (+10/-0)
To merge this branch: bzr merge lp:~gary-lasker/software-center/recommended-installed-feedback
Reviewer Review Type Date Requested Status
software-store-developers Pending
Review via email: mp+121539@code.launchpad.net

This proposal has been superseded by a proposal from 2012-08-30.

Commit message

* lp:~gary-lasker/software-center/recommended-installed-feedback:
   - signal the recommender service when a recommended item has been
     successfully installed (LP: #944060)

Description of the change

This branch implements the "implicit" recommender feedback feature. It detects the case where the user successfully installs a recommended item and fires a "submit_implicit_feedback" call to notify the recommender of the installed package.

This is the client-side implementation for bug 944060.

Note that this branch depends on the lp:~gary-lasker/software-center/update-to-latest-recommender-client branch as that branch adds the new recommender client code from lp:~canonical-ca-hackers/ubuntu-recommender/ubuntu-recommender-client. Also note that I made one small change to sreclient to fix the validate decorator for the pkgname argument to implicit_feedback so that it matches the validator for the other calls that use pkgname as an argument.

Finally, I added a unit test for the new call in test_recagent.py, however like a few of the other tests there, the test is not currently working with the server. Therefore, it remains disabled as the other tests are. I'll look at this tomorrow to try to see what the issue is with these tests.

Meanwhile, everything here should be working. To test, just select any recommended item in the lobby or category views and install it. Once the installation is complete, the corresponding implicit_feedback call will be fired.

Many thanks for your review!

To post a comment you must log in.
Revision history for this message
Michael Vogt (mvo) wrote :
Download full text (5.3 KiB)

On Tue, Aug 28, 2012 at 05:46:23AM -0000, Gary Lasker wrote:
> Gary Lasker has proposed merging lp:~gary-lasker/software-center/recommended-installed-feedback into lp:software-center with lp:~gary-lasker/software-center/update-to-latest-recommender-client as a prerequisite.

Thanks for working on this branch. I'm very happy to see this feature
coming.

[..]
> Note that this branch depends on the lp:~gary-lasker/software-center/update-to-latest-recommender-client branch as that branch adds the new recommender client code from lp:~canonical-ca-hackers/ubuntu-recommender/ubuntu-recommender-client. Also note that I made one small change to sreclient to fix the validate decorator for the pkgname argument to implicit_feedback so that it matches the validator for the other calls that use pkgname as an argument.

Thanks for this, if you fixed the sreclient_pristine.py, please also
send the diff to the server team (if you haven't done already) so that
they add it to their
lp:~canonical-ca-hackers/ubuntu-recommender/ubuntu-recommender-client
branch.

> Finally, I added a unit test for the new call in test_recagent.py, however like a few of the other tests there, the test is not currently working with the server. Therefore, it remains disabled as the other tests are. I'll look at this tomorrow to try to see what the issue is with these tests.
[..]

Maybe the staging server had problems. I just tested enabling them and
its working, but that may well be that its now fixed. While looking at
the test code I noticed that there is a bit of duplication in
there, I pushed a branch at
lp:~mvo/software-center/recagent-test-cleanup that removes most of
that.

I also noticed that the branch is missing a test for the new
functionality, it would be nice to add one to
tests/gtk3/test_recommendations_widget.py. Something like activate a
app, trigger a install transaction and verify that on finish the
self.recommender_agent.post_implicit_feedback() call was done.

> @@ -244,7 +262,7 @@
>
> def _on_submit_anon_profile_data(self, spawner,
> piston_submit_anon_profile):
> - self.emit("submit-anon_profile", piston_submit_anon_profile)
> + self.emit("submit-anon-profile-finished", piston_submit_anon_profile)

Nice that this is more consistent now (plus that it will actually work).

> === modified file 'softwarecenter/enums.py'
> --- softwarecenter/enums.py 2012-08-23 14:37:28 +0000
> +++ softwarecenter/enums.py 2012-08-28 05:45:23 +0000
> @@ -299,6 +299,9 @@
> LOBBY_RECOMMENDATIONS_CAROUSEL_LIMIT = 9
> DETAILS_RECOMMENDATIONS_CAROUSEL_LIMIT = 4
>
> +# action values for recommendations implicit feedback
> +RECOMMENDATIONS_FEEDBACK_INSTALLED = "installed"
> +

That looks like we could use:

class RecommenderFeedback:
      INSTALLED = "installed"

(so that later "REMOVED" can be added there as well and its more
consitent with the rest of enums.py).

[..]
> def _on_application_activated(self, catview, app):
> self.emit("application-activated", app)
> + # we only track installed items of the user has opted-in to the
> + # recommendations service
> + if self.recommender_agent.i...

Read more...

3088. By Gary Lasker

merge latest lp:~gary-lasker/software-center/update-to-latest-recommender-client for changes there after review

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

Just a note that I have a branch for review with the recommender-client changes that I mentioned above (and that have been made to sreclient_pristine.py). The merge proposal is here:

  https://code.launchpad.net/~gary-lasker/ubuntu-recommender/ubuntu-recommender-client-implicit-feedback-tweaks/+merge/121730

3089. By Gary Lasker

use a class for RecommenderFeedbackActions

3090. By Gary Lasker

pep8 fixes

3091. By Gary Lasker

merge trunk and resolve conflicts

3092. By Gary Lasker

use a set rather than a list for self.recommended_apps_viewed

3093. By Gary Lasker

consolidate some duplicated code, other cleanup, add a new unit test for the recommender implicit feedback functionality

Revision history for this message
Gary Lasker (gary-lasker) wrote :
Download full text (7.3 KiB)

> On Tue, Aug 28, 2012 at 05:46:23AM -0000, Gary Lasker wrote:
> > Gary Lasker has proposed merging lp:~gary-lasker/software-center
> /recommended-installed-feedback into lp:software-center with lp:~gary-lasker
> /software-center/update-to-latest-recommender-client as a prerequisite.
>
> Thanks for working on this branch. I'm very happy to see this feature
> coming.
>
> [..]
> > Note that this branch depends on the lp:~gary-lasker/software-center/update-
> to-latest-recommender-client branch as that branch adds the new recommender
> client code from lp:~canonical-ca-hackers/ubuntu-recommender/ubuntu-
> recommender-client. Also note that I made one small change to sreclient to fix
> the validate decorator for the pkgname argument to implicit_feedback so that
> it matches the validator for the other calls that use pkgname as an argument.
>
> Thanks for this, if you fixed the sreclient_pristine.py, please also
> send the diff to the server team (if you haven't done already) so that
> they add it to their
> lp:~canonical-ca-hackers/ubuntu-recommender/ubuntu-recommender-client
> branch.

Yep, I proposed a branch for this and it has been merged by Lukasz.

>
> > Finally, I added a unit test for the new call in test_recagent.py, however
> like a few of the other tests there, the test is not currently working with
> the server. Therefore, it remains disabled as the other tests are. I'll look
> at this tomorrow to try to see what the issue is with these tests.
> [..]
>
> Maybe the staging server had problems. I just tested enabling them and
> its working, but that may well be that its now fixed. While looking at
> the test code I noticed that there is a bit of duplication in
> there, I pushed a branch at
> lp:~mvo/software-center/recagent-test-cleanup that removes most of
> that.
>
> I also noticed that the branch is missing a test for the new
> functionality, it would be nice to add one to
> tests/gtk3/test_recommendations_widget.py. Something like activate a
> app, trigger a install transaction and verify that on finish the
> self.recommender_agent.post_implicit_feedback() call was done.
>

I added a thorough test for this functionality in test_catview.py (this is where the other recommendations panel tests are, and imo it's consistent because the tests for the other lobby panels (What's New and Top Rated) are also located here. While in test_catview.py I did some cleanup and consolidation of duplicated code as well.

> > @@ -244,7 +262,7 @@
> >
> > def _on_submit_anon_profile_data(self, spawner,
> > piston_submit_anon_profile):
> > - self.emit("submit-anon_profile", piston_submit_anon_profile)
> > + self.emit("submit-anon-profile-finished",
> piston_submit_anon_profile)
>
> Nice that this is more consistent now (plus that it will actually work).
>
> > === modified file 'softwarecenter/enums.py'
> > --- softwarecenter/enums.py 2012-08-23 14:37:28 +0000
> > +++ softwarecenter/enums.py 2012-08-28 05:45:23 +0000
> > @@ -299,6 +299,9 @@
> > LOBBY_RECOMMENDATIONS_CAROUSEL_LIMIT = 9
> > DETAILS_RECOMMENDATIONS_CAROUSEL_LIMIT = 4
> >
> > +# action values for recommendations implicit f...

Read more...

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

Oops, I noticed a typo in my last comment:

"...when a person clicks on a recommended item, we remember that they did that for that item for as long as the current USC session is active (it is now, however, persisted between sessions, I think would be a mistake)."

Should be (see the "*not*"):

"...when a person clicks on a recommended item, we remember that they did that for that item for as long as the current USC session is active (it is *not*, however, persisted between sessions, I think would be a mistake)."

Though maybe this was obvious, but I wanted to make sure that I'm clear.

Thanks again!

3094. By Gary Lasker

add a test to insure that no recommender feedback call occurs in the case where the user is *not* opted in to the recommender service

3095. By Gary Lasker

merge with trunk

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

On Thu, Aug 30, 2012 at 09:25:21PM -0000, Gary Lasker wrote:
> > On Tue, Aug 28, 2012 at 05:46:23AM -0000, Gary Lasker wrote:
> > > Gary Lasker has proposed merging lp:~gary-lasker/software-center
> > /recommended-installed-feedback into lp:software-center with lp:~gary-lasker
> > /software-center/update-to-latest-recommender-client as a prerequisite.
> >
> > Thanks for working on this branch. I'm very happy to see this feature
> > coming.
> >
> > [..]
> > > Note that this branch depends on the lp:~gary-lasker/software-center/update-
> > to-latest-recommender-client branch as that branch adds the new recommender
> > client code from lp:~canonical-ca-hackers/ubuntu-recommender/ubuntu-
> > recommender-client. Also note that I made one small change to sreclient to fix
> > the validate decorator for the pkgname argument to implicit_feedback so that
> > it matches the validator for the other calls that use pkgname as an argument.
> >
> > Thanks for this, if you fixed the sreclient_pristine.py, please also
> > send the diff to the server team (if you haven't done already) so that
> > they add it to their
> > lp:~canonical-ca-hackers/ubuntu-recommender/ubuntu-recommender-client
> > branch.
>
> Yep, I proposed a branch for this and it has been merged by Lukasz.

Great, thanks for this.

> > > Finally, I added a unit test for the new call in test_recagent.py, however
> > like a few of the other tests there, the test is not currently working with
> > the server. Therefore, it remains disabled as the other tests are. I'll look
> > at this tomorrow to try to see what the issue is with these tests.
> > [..]
> >
> > Maybe the staging server had problems. I just tested enabling them and
> > its working, but that may well be that its now fixed. While looking at
> > the test code I noticed that there is a bit of duplication in
> > there, I pushed a branch at
> > lp:~mvo/software-center/recagent-test-cleanup that removes most of
> > that.
> >
> > I also noticed that the branch is missing a test for the new
> > functionality, it would be nice to add one to
> > tests/gtk3/test_recommendations_widget.py. Something like activate a
> > app, trigger a install transaction and verify that on finish the
> > self.recommender_agent.post_implicit_feedback() call was done.
> >
>
> I added a thorough test for this functionality in test_catview.py (this is where the other recommendations panel tests are, and imo it's consistent because the tests for the other lobby panels (What's New and Top Rated) are also located here. While in test_catview.py I did some cleanup and consolidation of duplicated code as well.

Thanks for adding the test and for the cleanup there, that looks very
good!

[..]
> > Should self.recommended_apps_viewed we cleared when we get new data,
> > e.g on _on_app_recommendations_agent_refresh (and the equivalent
> > function for the categories). Or should this be persistent? I'm don't
> > know the details of the spec well enough :) I guess it comes down to
> > if we should consider it a recommendation that are reached
> > "indirectly", e.g. click on it "app A", move back to main view search
> > for something else and then reach "app A" again late...

Read more...

3096. By Gary Lasker

RED: add a failing test to show that the implicit recommender call is incorrectly being made from the top rated panel

3097. By Gary Lasker

the fix for the failing test case is to do the refactoring that we know is needed in CategoriesViewGtk to move the add_tiles_to_flowgrid and corresponding on_application_selected methods to where they belong, specifically, to the FlowableGrid class itself, this commit contains the brunt of this refactor, but there are some additional pieces needed to finish it up

3098. By Gary Lasker

GREEN: essential refactor complete and signals wired up, all test cases now working; removed the unused (with FIXME) 'application-selected' signal from catview as it is not used there (we only 'activate' apps from this widget), fix single-line cut-and-paste error in the test case

3099. By Gary Lasker

REFACTOR: make a new TileGrid subclass of FlowableGrid so that FlowableGrid remains generic, wire up the TileGrid for the various panels that it is used

3100. By Gary Lasker

REFACTOR: remove all need for the catview in the recommendations code

3101. By Gary Lasker

don't use hasattr in the FramedHeaderBox so that we can attach listeners to the more button when we need to, connect listeners for this, add a signal to the RecommenderPanelCategory (and subclass RecommenderPanelLobby) so that we can get their correct categories when clicking 'More' in those

3102. By Gary Lasker

pep8 fixes

3103. By Gary Lasker

merge with trunk

3104. By Gary Lasker

clean up get_test_window_recommendations in windows.py per the new factoring

3105. By Gary Lasker

move the application-activated signal into the TileGrid subclass where it belongs

3106. By Gary Lasker

make a docstring more better per review comment

3107. By Gary Lasker

merge with trunk, don't wanna cruft

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'softwarecenter/backend/piston/sreclient_pristine.py'
--- softwarecenter/backend/piston/sreclient_pristine.py 2012-08-28 18:16:47 +0000
+++ softwarecenter/backend/piston/sreclient_pristine.py 2012-08-30 20:56:21 +0000
@@ -84,7 +84,7 @@
84 scheme=AUTHENTICATED_API_SCHEME)84 scheme=AUTHENTICATED_API_SCHEME)
8585
86 @oauth_protected86 @oauth_protected
87 @validate('pkgname', str)87 @validate_pattern('pkgname', '[^/]+')
88 @validate_pattern('action', '\w{3,20}')88 @validate_pattern('action', '\w{3,20}')
89 @returns_json89 @returns_json
90 def implicit_feedback(self, pkgname, action):90 def implicit_feedback(self, pkgname, action):
9191
=== modified file 'softwarecenter/backend/recagent.py'
--- softwarecenter/backend/recagent.py 2012-08-29 18:05:52 +0000
+++ softwarecenter/backend/recagent.py 2012-08-30 20:56:21 +0000
@@ -68,6 +68,10 @@
68 GObject.TYPE_NONE,68 GObject.TYPE_NONE,
69 (GObject.TYPE_PYOBJECT,),69 (GObject.TYPE_PYOBJECT,),
70 ),70 ),
71 "submit-implicit-feedback-finished": (GObject.SIGNAL_RUN_LAST,
72 GObject.TYPE_NONE,
73 (GObject.TYPE_PYOBJECT,),
74 ),
71 "error": (GObject.SIGNAL_RUN_LAST,75 "error": (GObject.SIGNAL_RUN_LAST,
72 GObject.TYPE_NONE,76 GObject.TYPE_NONE,
73 (str,),77 (str,),
@@ -215,6 +219,20 @@
215 spawner.run_generic_piston_helper(219 spawner.run_generic_piston_helper(
216 "SoftwareCenterRecommenderAPI", "recommend_top")220 "SoftwareCenterRecommenderAPI", "recommend_top")
217221
222 def post_implicit_feedback(self, pkgname, action):
223 # build the command
224 spawner = SpawnHelper()
225 spawner.parent_xid = self.xid
226 spawner.needs_auth = True
227 spawner.connect("data-available",
228 self._on_submit_implicit_feedback_data)
229 spawner.connect("error", lambda spawner, err: self.emit("error", err))
230 spawner.run_generic_piston_helper(
231 "SoftwareCenterRecommenderAPI",
232 "implicit_feedback",
233 pkgname=pkgname,
234 action=action)
235
218 def is_opted_in(self):236 def is_opted_in(self):
219 """237 """
220 Return True is the user is currently opted-in to the recommender238 Return True is the user is currently opted-in to the recommender
@@ -244,7 +262,7 @@
244262
245 def _on_submit_anon_profile_data(self, spawner,263 def _on_submit_anon_profile_data(self, spawner,
246 piston_submit_anon_profile):264 piston_submit_anon_profile):
247 self.emit("submit-anon_profile", piston_submit_anon_profile)265 self.emit("submit-anon-profile-finished", piston_submit_anon_profile)
248266
249 def _on_recommend_me_data(self, spawner, piston_me_apps):267 def _on_recommend_me_data(self, spawner, piston_me_apps):
250 self.emit("recommend-me", piston_me_apps)268 self.emit("recommend-me", piston_me_apps)
@@ -258,6 +276,11 @@
258 def _on_recommend_top_data(self, spawner, piston_top_apps):276 def _on_recommend_top_data(self, spawner, piston_top_apps):
259 self.emit("recommend-top", piston_top_apps)277 self.emit("recommend-top", piston_top_apps)
260278
279 def _on_submit_implicit_feedback_data(self, spawner,
280 piston_submit_implicit_feedback):
281 self.emit("submit-implicit-feedback-finished",
282 piston_submit_implicit_feedback)
283
261 def _generate_submit_profile_data(self, recommender_uuid, package_list):284 def _generate_submit_profile_data(self, recommender_uuid, package_list):
262 submit_profile_data = [{285 submit_profile_data = [{
263 'uuid': recommender_uuid,286 'uuid': recommender_uuid,
264287
=== modified file 'softwarecenter/enums.py'
--- softwarecenter/enums.py 2012-08-23 14:37:28 +0000
+++ softwarecenter/enums.py 2012-08-30 20:56:21 +0000
@@ -282,6 +282,10 @@
282 PACKAGE = ","282 PACKAGE = ","
283283
284284
285# action values for recommendations feedback
286class RecommenderFeedbackActions:
287 INSTALLED = "installed"
288
285# mouse event codes for back/forward buttons289# mouse event codes for back/forward buttons
286# TODO: consider whether we ought to get these values from gconf so that we290# TODO: consider whether we ought to get these values from gconf so that we
287# can be sure to use the corresponding values used by Nautilus:291# can be sure to use the corresponding values used by Nautilus:
288292
=== modified file 'softwarecenter/ui/gtk3/widgets/recommendations.py'
--- softwarecenter/ui/gtk3/widgets/recommendations.py 2012-08-22 08:16:30 +0000
+++ softwarecenter/ui/gtk3/widgets/recommendations.py 2012-08-30 20:56:21 +0000
@@ -28,6 +28,7 @@
28from softwarecenter.ui.gtk3.utils import get_parent_xid28from softwarecenter.ui.gtk3.utils import get_parent_xid
29from softwarecenter.db.categories import (RecommendedForYouCategory,29from softwarecenter.db.categories import (RecommendedForYouCategory,
30 AppRecommendationsCategory)30 AppRecommendationsCategory)
31from softwarecenter.backend import get_install_backend
31from softwarecenter.backend.recagent import RecommenderAgent32from softwarecenter.backend.recagent import RecommenderAgent
32from softwarecenter.backend.login_sso import get_sso_backend33from softwarecenter.backend.login_sso import get_sso_backend
33from softwarecenter.backend.ubuntusso import get_ubuntu_sso_backend34from softwarecenter.backend.ubuntusso import get_ubuntu_sso_backend
@@ -35,6 +36,8 @@
35 LOBBY_RECOMMENDATIONS_CAROUSEL_LIMIT,36 LOBBY_RECOMMENDATIONS_CAROUSEL_LIMIT,
36 DETAILS_RECOMMENDATIONS_CAROUSEL_LIMIT,37 DETAILS_RECOMMENDATIONS_CAROUSEL_LIMIT,
37 SOFTWARE_CENTER_NAME_KEYRING,38 SOFTWARE_CENTER_NAME_KEYRING,
39 RecommenderFeedbackActions,
40 TransactionTypes,
38 )41 )
39from softwarecenter.utils import utf842from softwarecenter.utils import utf8
40from softwarecenter.netstatus import network_state_is_connected43from softwarecenter.netstatus import network_state_is_connected
@@ -63,9 +66,39 @@
63 self.catview.connect(66 self.catview.connect(
64 "application-activated", self._on_application_activated)67 "application-activated", self._on_application_activated)
65 self.recommender_agent = RecommenderAgent()68 self.recommender_agent = RecommenderAgent()
69 # keep track of applications that have been viewed via a
70 # recommendation so that we can detect when a recommended app
71 # has been installed
72 self.recommended_apps_viewed = set()
73 self.backend = get_install_backend()
74 self.backend.connect("transaction-started",
75 self._on_transaction_started)
76 self.backend.connect("transaction-finished",
77 self._on_transaction_finished)
6678
67 def _on_application_activated(self, catview, app):79 def _on_application_activated(self, catview, app):
68 self.emit("application-activated", app)80 self.emit("application-activated", app)
81 # we only track installed items if the user has opted-in to the
82 # recommendations service
83 if self.recommender_agent.is_opted_in():
84 self.recommended_apps_viewed.add(app.pkgname)
85
86 def _on_transaction_started(self, backend, pkgname, appname, trans_id,
87 trans_type):
88 if (trans_type != TransactionTypes.INSTALL and
89 pkgname in self.recommended_apps_viewed):
90 # if the transaction is not an installation we don't want to
91 # track it as a recommended item
92 self.recommended_apps_viewed.remove(pkgname)
93
94 def _on_transaction_finished(self, backend, result):
95 if result.pkgname in self.recommended_apps_viewed:
96 self.recommended_apps_viewed.remove(result.pkgname)
97 if network_state_is_connected():
98 # no need to monitor for an error, etc., for this
99 self.recommender_agent.post_implicit_feedback(
100 result.pkgname,
101 RecommenderFeedbackActions.INSTALLED)
69102
70 def _on_recommender_agent_error(self, agent, msg):103 def _on_recommender_agent_error(self, agent, msg):
71 LOG.warn("Error while accessing the recommender agent: %s" % msg)104 LOG.warn("Error while accessing the recommender agent: %s" % msg)
72105
=== modified file 'tests/gtk3/test_catview.py'
--- tests/gtk3/test_catview.py 2012-08-28 21:20:40 +0000
+++ tests/gtk3/test_catview.py 2012-08-30 20:56:21 +0000
@@ -20,7 +20,9 @@
2020
21from softwarecenter.db.appfilter import AppFilter21from softwarecenter.db.appfilter import AppFilter
22from softwarecenter.db.database import StoreDatabase22from softwarecenter.db.database import StoreDatabase
23from softwarecenter.enums import SortMethods23from softwarecenter.enums import (SortMethods,
24 TransactionTypes,
25 RecommenderFeedbackActions)
24from softwarecenter.ui.gtk3.views import catview_gtk26from softwarecenter.ui.gtk3.views import catview_gtk
25from softwarecenter.ui.gtk3.widgets.containers import FramedHeaderBox27from softwarecenter.ui.gtk3.widgets.containers import FramedHeaderBox
26from softwarecenter.ui.gtk3.widgets.spinner import SpinnerNotebook28from softwarecenter.ui.gtk3.widgets.spinner import SpinnerNotebook
@@ -35,6 +37,7 @@
3537
36 def setUp(self):38 def setUp(self):
37 self._cat = None39 self._cat = None
40 self._app = None
38 self.win = get_test_window_catview(self.db)41 self.win = get_test_window_catview(self.db)
39 self.addCleanup(self.win.destroy)42 self.addCleanup(self.win.destroy)
40 self.notebook = self.win.get_child()43 self.notebook = self.win.get_child()
@@ -121,6 +124,7 @@
121 '.post_submit_profile')124 '.post_submit_profile')
122 def setUp(self, mock_query, mock_recommender_is_opted_in, mock_sso):125 def setUp(self, mock_query, mock_recommender_is_opted_in, mock_sso):
123 self._cat = None126 self._cat = None
127 self._app = None
124 # patch the recommender to specify that we are not opted-in at128 # patch the recommender to specify that we are not opted-in at
125 # the start of each test129 # the start of each test
126 mock_recommender_is_opted_in.return_value = False130 mock_recommender_is_opted_in.return_value = False
@@ -162,11 +166,7 @@
162 mock_network_state_is_connected):166 mock_network_state_is_connected):
163 # simulate no network available167 # simulate no network available
164 mock_network_state_is_connected.return_value = False168 mock_network_state_is_connected.return_value = False
165 # click the opt-in button to initiate the process169 self._populate_recommended_for_you_panel()
166 self.rec_panel.opt_in_button.clicked()
167 do_events()
168 self.rec_panel._update_recommended_for_you_content()
169 do_events()
170 self.assertEqual(self.rec_panel.spinner_notebook.get_current_page(),170 self.assertEqual(self.rec_panel.spinner_notebook.get_current_page(),
171 FramedHeaderBox.CONTENT)171 FramedHeaderBox.CONTENT)
172 # ensure that we are showing the network not available view172 # ensure that we are showing the network not available view
@@ -176,14 +176,9 @@
176 self.rec_panel.NO_NETWORK_RECOMMENDATIONS_TEXT)176 self.rec_panel.NO_NETWORK_RECOMMENDATIONS_TEXT)
177177
178 def test_recommended_for_you_display_recommendations(self):178 def test_recommended_for_you_display_recommendations(self):
179 # click the opt-in button to initiate the process,179 self._populate_recommended_for_you_panel()
180 # this will show the spinner
181 self.rec_panel.opt_in_button.clicked()
182 do_events()
183 self.rec_panel._update_recommended_for_you_content()
184 do_events()
185 # we fake the callback from the agent here180 # we fake the callback from the agent here
186 for_you = self.lobby.recommended_for_you_panel.recommended_for_you_cat181 for_you = self.rec_panel.recommended_for_you_cat
187 for_you._recommend_me_result(None,182 for_you._recommend_me_result(None,
188 make_recommender_agent_recommend_me_dict())183 make_recommender_agent_recommend_me_dict())
189 self.assertNotEqual(for_you.get_documents(self.db), [])184 self.assertNotEqual(for_you.get_documents(self.db), [])
@@ -192,7 +187,7 @@
192 do_events()187 do_events()
193 # test clicking recommended_for_you More button188 # test clicking recommended_for_you More button
194 self.lobby.connect("category-selected", self._on_category_selected)189 self.lobby.connect("category-selected", self._on_category_selected)
195 self.lobby.recommended_for_you_panel.more.clicked()190 self.rec_panel.more.clicked()
196 # this is delayed for some reason so we need to sleep here191 # this is delayed for some reason so we need to sleep here
197 do_events_with_sleep()192 do_events_with_sleep()
198 self.assertNotEqual(self._cat, None)193 self.assertNotEqual(self._cat, None)
@@ -208,13 +203,8 @@
208 self.assertFalse(visible)203 self.assertFalse(visible)
209204
210 def test_recommended_for_you_display_recommendations_opted_in(self):205 def test_recommended_for_you_display_recommendations_opted_in(self):
211 # click the opt-in button to initiate the process,206 self._populate_recommended_for_you_panel()
212 # this will show the spinner207
213 self.rec_panel.opt_in_button.clicked()
214 do_events()
215 self.rec_panel._update_recommended_for_you_content()
216 do_events()
217
218 # we want to work in the "subcat" view208 # we want to work in the "subcat" view
219 self.notebook.next_page()209 self.notebook.next_page()
220210
@@ -248,6 +238,68 @@
248 do_events_with_sleep()238 do_events_with_sleep()
249 self.assertNotEqual(self._cat, None)239 self.assertNotEqual(self._cat, None)
250 self.assertEqual(self._cat.name, "Recommended For You in Internet")240 self.assertEqual(self._cat.name, "Recommended For You in Internet")
241
242 def test_implicit_recommender_feedback(self):
243 self._populate_recommended_for_you_panel()
244 # we fake the callback from the agent here
245 for_you = self.rec_panel.recommended_for_you_cat
246 for_you._recommend_me_result(None,
247 make_recommender_agent_recommend_me_dict())
248 do_events()
249
250 post_implicit_feedback_fn = ('softwarecenter.ui.gtk3.widgets'
251 '.recommendations.RecommenderAgent'
252 '.post_implicit_feedback')
253 with patch(post_implicit_feedback_fn) as mock_post_implicit_feedback:
254 # we want to grab the recommended app that is activated
255 self.lobby.connect("application-activated",
256 self._on_application_activated)
257 # click a recommendation in the lobby
258 self._click_first_recommended_tile()
259 # simulate installing the application
260 self._simulate_install_events(self._app)
261 # and verify that after the install has completed we have fired
262 # the implicit feedback call to the recommender with the correct
263 # arguments
264 mock_post_implicit_feedback.assert_called_with(
265 self._app.pkgname,
266 RecommenderFeedbackActions.INSTALLED)
267 # finally, make sure that we have cleared the application
268 # from the recommended_apps_viewed set
269 self.assertFalse(self._app.pkgname in
270 self.rec_panel.recommended_apps_viewed)
271
272 def _populate_recommended_for_you_panel(self):
273 # click the opt-in button to initiate the process
274 self.rec_panel.opt_in_button.clicked()
275 do_events()
276 # and update the recommended for you panel to load it up
277 self.rec_panel._update_recommended_for_you_content()
278 do_events()
279
280 def _on_application_activated(self, catview, app):
281 self._app = app
282
283 def _click_first_recommended_tile(self):
284 rec_item_tile = (self.rec_panel.content_box.
285 get_children()[0].get_children()[0])
286 rec_item_tile.on_press(None, None)
287 rec_item_tile.on_release(None, None)
288 do_events_with_sleep()
289
290 def _simulate_install_events(self, app):
291 # pretend we started an install
292 self.rec_panel.backend.emit("transaction-started",
293 app.pkgname, app.appname,
294 "testid101",
295 TransactionTypes.INSTALL)
296 do_events_with_sleep()
297 # send the signal to complete the install
298 mock_result = Mock()
299 mock_result.pkgname = app.pkgname
300 self.rec_panel.backend.emit("transaction-finished",
301 mock_result)
302 do_events()
251303
252304
253class ExhibitsTestCase(unittest.TestCase):305class ExhibitsTestCase(unittest.TestCase):
254306
=== modified file 'tests/test_recagent.py'
--- tests/test_recagent.py 2012-08-29 14:46:51 +0000
+++ tests/test_recagent.py 2012-08-30 20:56:21 +0000
@@ -129,6 +129,16 @@
129 self.loop.run()129 self.loop.run()
130 self.assertTrue(self.error)130 self.assertTrue(self.error)
131131
132 @unittest.skip("server returns 401")
133 def test_recagent_post_implicit_feedback(self):
134 self.recommender_agent.connect("submit-implicit-feedback-finished",
135 self.on_query_done)
136 from softwarecenter.enums import RecommenderFeedbackActions
137 self.recommender_agent.post_implicit_feedback(
138 "bluefish",
139 RecommenderFeedbackActions.INSTALLED)
140 self.assertServerReturnsWithNoError()
141
132142
133if __name__ == "__main__":143if __name__ == "__main__":
134 #import logging144 #import logging

Subscribers

People subscribed via source and target branches