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.
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 on 2012-08-28

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

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 on 2012-08-29

use a class for RecommenderFeedbackActions

3090. By Gary Lasker on 2012-08-29

pep8 fixes

3091. By Gary Lasker on 2012-08-30

merge trunk and resolve conflicts

3092. By Gary Lasker on 2012-08-30

use a set rather than a list for self.recommended_apps_viewed

3093. By Gary Lasker on 2012-08-30

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

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...

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 on 2012-08-31

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 on 2012-08-31

merge with trunk

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 on 2012-09-02

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 on 2012-09-03

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 on 2012-09-04

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 on 2012-09-05

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 on 2012-09-05

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

3101. By Gary Lasker on 2012-09-05

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 on 2012-09-05

pep8 fixes

3103. By Gary Lasker on 2012-09-05

merge with trunk

3104. By Gary Lasker on 2012-09-05

clean up get_test_window_recommendations in windows.py per the new factoring

3105. By Gary Lasker on 2012-09-06

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

3106. By Gary Lasker on 2012-09-06

make a docstring more better per review comment

3107. By Gary Lasker on 2012-09-06

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
1=== modified file 'softwarecenter/backend/piston/sreclient_pristine.py'
2--- softwarecenter/backend/piston/sreclient_pristine.py 2012-08-28 18:16:47 +0000
3+++ softwarecenter/backend/piston/sreclient_pristine.py 2012-08-30 20:56:21 +0000
4@@ -84,7 +84,7 @@
5 scheme=AUTHENTICATED_API_SCHEME)
6
7 @oauth_protected
8- @validate('pkgname', str)
9+ @validate_pattern('pkgname', '[^/]+')
10 @validate_pattern('action', '\w{3,20}')
11 @returns_json
12 def implicit_feedback(self, pkgname, action):
13
14=== modified file 'softwarecenter/backend/recagent.py'
15--- softwarecenter/backend/recagent.py 2012-08-29 18:05:52 +0000
16+++ softwarecenter/backend/recagent.py 2012-08-30 20:56:21 +0000
17@@ -68,6 +68,10 @@
18 GObject.TYPE_NONE,
19 (GObject.TYPE_PYOBJECT,),
20 ),
21+ "submit-implicit-feedback-finished": (GObject.SIGNAL_RUN_LAST,
22+ GObject.TYPE_NONE,
23+ (GObject.TYPE_PYOBJECT,),
24+ ),
25 "error": (GObject.SIGNAL_RUN_LAST,
26 GObject.TYPE_NONE,
27 (str,),
28@@ -215,6 +219,20 @@
29 spawner.run_generic_piston_helper(
30 "SoftwareCenterRecommenderAPI", "recommend_top")
31
32+ def post_implicit_feedback(self, pkgname, action):
33+ # build the command
34+ spawner = SpawnHelper()
35+ spawner.parent_xid = self.xid
36+ spawner.needs_auth = True
37+ spawner.connect("data-available",
38+ self._on_submit_implicit_feedback_data)
39+ spawner.connect("error", lambda spawner, err: self.emit("error", err))
40+ spawner.run_generic_piston_helper(
41+ "SoftwareCenterRecommenderAPI",
42+ "implicit_feedback",
43+ pkgname=pkgname,
44+ action=action)
45+
46 def is_opted_in(self):
47 """
48 Return True is the user is currently opted-in to the recommender
49@@ -244,7 +262,7 @@
50
51 def _on_submit_anon_profile_data(self, spawner,
52 piston_submit_anon_profile):
53- self.emit("submit-anon_profile", piston_submit_anon_profile)
54+ self.emit("submit-anon-profile-finished", piston_submit_anon_profile)
55
56 def _on_recommend_me_data(self, spawner, piston_me_apps):
57 self.emit("recommend-me", piston_me_apps)
58@@ -258,6 +276,11 @@
59 def _on_recommend_top_data(self, spawner, piston_top_apps):
60 self.emit("recommend-top", piston_top_apps)
61
62+ def _on_submit_implicit_feedback_data(self, spawner,
63+ piston_submit_implicit_feedback):
64+ self.emit("submit-implicit-feedback-finished",
65+ piston_submit_implicit_feedback)
66+
67 def _generate_submit_profile_data(self, recommender_uuid, package_list):
68 submit_profile_data = [{
69 'uuid': recommender_uuid,
70
71=== modified file 'softwarecenter/enums.py'
72--- softwarecenter/enums.py 2012-08-23 14:37:28 +0000
73+++ softwarecenter/enums.py 2012-08-30 20:56:21 +0000
74@@ -282,6 +282,10 @@
75 PACKAGE = ","
76
77
78+# action values for recommendations feedback
79+class RecommenderFeedbackActions:
80+ INSTALLED = "installed"
81+
82 # mouse event codes for back/forward buttons
83 # TODO: consider whether we ought to get these values from gconf so that we
84 # can be sure to use the corresponding values used by Nautilus:
85
86=== modified file 'softwarecenter/ui/gtk3/widgets/recommendations.py'
87--- softwarecenter/ui/gtk3/widgets/recommendations.py 2012-08-22 08:16:30 +0000
88+++ softwarecenter/ui/gtk3/widgets/recommendations.py 2012-08-30 20:56:21 +0000
89@@ -28,6 +28,7 @@
90 from softwarecenter.ui.gtk3.utils import get_parent_xid
91 from softwarecenter.db.categories import (RecommendedForYouCategory,
92 AppRecommendationsCategory)
93+from softwarecenter.backend import get_install_backend
94 from softwarecenter.backend.recagent import RecommenderAgent
95 from softwarecenter.backend.login_sso import get_sso_backend
96 from softwarecenter.backend.ubuntusso import get_ubuntu_sso_backend
97@@ -35,6 +36,8 @@
98 LOBBY_RECOMMENDATIONS_CAROUSEL_LIMIT,
99 DETAILS_RECOMMENDATIONS_CAROUSEL_LIMIT,
100 SOFTWARE_CENTER_NAME_KEYRING,
101+ RecommenderFeedbackActions,
102+ TransactionTypes,
103 )
104 from softwarecenter.utils import utf8
105 from softwarecenter.netstatus import network_state_is_connected
106@@ -63,9 +66,39 @@
107 self.catview.connect(
108 "application-activated", self._on_application_activated)
109 self.recommender_agent = RecommenderAgent()
110+ # keep track of applications that have been viewed via a
111+ # recommendation so that we can detect when a recommended app
112+ # has been installed
113+ self.recommended_apps_viewed = set()
114+ self.backend = get_install_backend()
115+ self.backend.connect("transaction-started",
116+ self._on_transaction_started)
117+ self.backend.connect("transaction-finished",
118+ self._on_transaction_finished)
119
120 def _on_application_activated(self, catview, app):
121 self.emit("application-activated", app)
122+ # we only track installed items if the user has opted-in to the
123+ # recommendations service
124+ if self.recommender_agent.is_opted_in():
125+ self.recommended_apps_viewed.add(app.pkgname)
126+
127+ def _on_transaction_started(self, backend, pkgname, appname, trans_id,
128+ trans_type):
129+ if (trans_type != TransactionTypes.INSTALL and
130+ pkgname in self.recommended_apps_viewed):
131+ # if the transaction is not an installation we don't want to
132+ # track it as a recommended item
133+ self.recommended_apps_viewed.remove(pkgname)
134+
135+ def _on_transaction_finished(self, backend, result):
136+ if result.pkgname in self.recommended_apps_viewed:
137+ self.recommended_apps_viewed.remove(result.pkgname)
138+ if network_state_is_connected():
139+ # no need to monitor for an error, etc., for this
140+ self.recommender_agent.post_implicit_feedback(
141+ result.pkgname,
142+ RecommenderFeedbackActions.INSTALLED)
143
144 def _on_recommender_agent_error(self, agent, msg):
145 LOG.warn("Error while accessing the recommender agent: %s" % msg)
146
147=== modified file 'tests/gtk3/test_catview.py'
148--- tests/gtk3/test_catview.py 2012-08-28 21:20:40 +0000
149+++ tests/gtk3/test_catview.py 2012-08-30 20:56:21 +0000
150@@ -20,7 +20,9 @@
151
152 from softwarecenter.db.appfilter import AppFilter
153 from softwarecenter.db.database import StoreDatabase
154-from softwarecenter.enums import SortMethods
155+from softwarecenter.enums import (SortMethods,
156+ TransactionTypes,
157+ RecommenderFeedbackActions)
158 from softwarecenter.ui.gtk3.views import catview_gtk
159 from softwarecenter.ui.gtk3.widgets.containers import FramedHeaderBox
160 from softwarecenter.ui.gtk3.widgets.spinner import SpinnerNotebook
161@@ -35,6 +37,7 @@
162
163 def setUp(self):
164 self._cat = None
165+ self._app = None
166 self.win = get_test_window_catview(self.db)
167 self.addCleanup(self.win.destroy)
168 self.notebook = self.win.get_child()
169@@ -121,6 +124,7 @@
170 '.post_submit_profile')
171 def setUp(self, mock_query, mock_recommender_is_opted_in, mock_sso):
172 self._cat = None
173+ self._app = None
174 # patch the recommender to specify that we are not opted-in at
175 # the start of each test
176 mock_recommender_is_opted_in.return_value = False
177@@ -162,11 +166,7 @@
178 mock_network_state_is_connected):
179 # simulate no network available
180 mock_network_state_is_connected.return_value = False
181- # click the opt-in button to initiate the process
182- self.rec_panel.opt_in_button.clicked()
183- do_events()
184- self.rec_panel._update_recommended_for_you_content()
185- do_events()
186+ self._populate_recommended_for_you_panel()
187 self.assertEqual(self.rec_panel.spinner_notebook.get_current_page(),
188 FramedHeaderBox.CONTENT)
189 # ensure that we are showing the network not available view
190@@ -176,14 +176,9 @@
191 self.rec_panel.NO_NETWORK_RECOMMENDATIONS_TEXT)
192
193 def test_recommended_for_you_display_recommendations(self):
194- # click the opt-in button to initiate the process,
195- # this will show the spinner
196- self.rec_panel.opt_in_button.clicked()
197- do_events()
198- self.rec_panel._update_recommended_for_you_content()
199- do_events()
200+ self._populate_recommended_for_you_panel()
201 # we fake the callback from the agent here
202- for_you = self.lobby.recommended_for_you_panel.recommended_for_you_cat
203+ for_you = self.rec_panel.recommended_for_you_cat
204 for_you._recommend_me_result(None,
205 make_recommender_agent_recommend_me_dict())
206 self.assertNotEqual(for_you.get_documents(self.db), [])
207@@ -192,7 +187,7 @@
208 do_events()
209 # test clicking recommended_for_you More button
210 self.lobby.connect("category-selected", self._on_category_selected)
211- self.lobby.recommended_for_you_panel.more.clicked()
212+ self.rec_panel.more.clicked()
213 # this is delayed for some reason so we need to sleep here
214 do_events_with_sleep()
215 self.assertNotEqual(self._cat, None)
216@@ -208,13 +203,8 @@
217 self.assertFalse(visible)
218
219 def test_recommended_for_you_display_recommendations_opted_in(self):
220- # click the opt-in button to initiate the process,
221- # this will show the spinner
222- self.rec_panel.opt_in_button.clicked()
223- do_events()
224- self.rec_panel._update_recommended_for_you_content()
225- do_events()
226-
227+ self._populate_recommended_for_you_panel()
228+
229 # we want to work in the "subcat" view
230 self.notebook.next_page()
231
232@@ -248,6 +238,68 @@
233 do_events_with_sleep()
234 self.assertNotEqual(self._cat, None)
235 self.assertEqual(self._cat.name, "Recommended For You in Internet")
236+
237+ def test_implicit_recommender_feedback(self):
238+ self._populate_recommended_for_you_panel()
239+ # we fake the callback from the agent here
240+ for_you = self.rec_panel.recommended_for_you_cat
241+ for_you._recommend_me_result(None,
242+ make_recommender_agent_recommend_me_dict())
243+ do_events()
244+
245+ post_implicit_feedback_fn = ('softwarecenter.ui.gtk3.widgets'
246+ '.recommendations.RecommenderAgent'
247+ '.post_implicit_feedback')
248+ with patch(post_implicit_feedback_fn) as mock_post_implicit_feedback:
249+ # we want to grab the recommended app that is activated
250+ self.lobby.connect("application-activated",
251+ self._on_application_activated)
252+ # click a recommendation in the lobby
253+ self._click_first_recommended_tile()
254+ # simulate installing the application
255+ self._simulate_install_events(self._app)
256+ # and verify that after the install has completed we have fired
257+ # the implicit feedback call to the recommender with the correct
258+ # arguments
259+ mock_post_implicit_feedback.assert_called_with(
260+ self._app.pkgname,
261+ RecommenderFeedbackActions.INSTALLED)
262+ # finally, make sure that we have cleared the application
263+ # from the recommended_apps_viewed set
264+ self.assertFalse(self._app.pkgname in
265+ self.rec_panel.recommended_apps_viewed)
266+
267+ def _populate_recommended_for_you_panel(self):
268+ # click the opt-in button to initiate the process
269+ self.rec_panel.opt_in_button.clicked()
270+ do_events()
271+ # and update the recommended for you panel to load it up
272+ self.rec_panel._update_recommended_for_you_content()
273+ do_events()
274+
275+ def _on_application_activated(self, catview, app):
276+ self._app = app
277+
278+ def _click_first_recommended_tile(self):
279+ rec_item_tile = (self.rec_panel.content_box.
280+ get_children()[0].get_children()[0])
281+ rec_item_tile.on_press(None, None)
282+ rec_item_tile.on_release(None, None)
283+ do_events_with_sleep()
284+
285+ def _simulate_install_events(self, app):
286+ # pretend we started an install
287+ self.rec_panel.backend.emit("transaction-started",
288+ app.pkgname, app.appname,
289+ "testid101",
290+ TransactionTypes.INSTALL)
291+ do_events_with_sleep()
292+ # send the signal to complete the install
293+ mock_result = Mock()
294+ mock_result.pkgname = app.pkgname
295+ self.rec_panel.backend.emit("transaction-finished",
296+ mock_result)
297+ do_events()
298
299
300 class ExhibitsTestCase(unittest.TestCase):
301
302=== modified file 'tests/test_recagent.py'
303--- tests/test_recagent.py 2012-08-29 14:46:51 +0000
304+++ tests/test_recagent.py 2012-08-30 20:56:21 +0000
305@@ -129,6 +129,16 @@
306 self.loop.run()
307 self.assertTrue(self.error)
308
309+ @unittest.skip("server returns 401")
310+ def test_recagent_post_implicit_feedback(self):
311+ self.recommender_agent.connect("submit-implicit-feedback-finished",
312+ self.on_query_done)
313+ from softwarecenter.enums import RecommenderFeedbackActions
314+ self.recommender_agent.post_implicit_feedback(
315+ "bluefish",
316+ RecommenderFeedbackActions.INSTALLED)
317+ self.assertServerReturnsWithNoError()
318+
319
320 if __name__ == "__main__":
321 #import logging

Subscribers

People subscribed via source and target branches