Merge lp:~dobey/unity-scope-click/recommends into lp:unity-scope-click/devel

Proposed by dobey
Status: Merged
Approved by: Alejandro J. Cura
Approved revision: 309
Merged at revision: 304
Proposed branch: lp:~dobey/unity-scope-click/recommends
Merge into: lp:unity-scope-click/devel
Diff against target: 643 lines (+241/-78)
13 files modified
libclickscope/click/highlights.cpp (+2/-1)
libclickscope/click/index.cpp (+31/-11)
libclickscope/click/index.h (+2/-1)
libclickscope/click/package.cpp (+6/-30)
libclickscope/click/package.h (+1/-1)
libclickscope/tests/CMakeLists.txt (+4/-3)
libclickscope/tests/fake_json.h (+52/-0)
libclickscope/tests/test_index.cpp (+35/-17)
libclickscope/tests/test_package.cpp (+74/-0)
po/unity-scope-click.pot (+6/-3)
scope/clickstore/store-query.cpp (+13/-2)
scope/tests/integration/webclient_integration.cpp (+2/-1)
scope/tests/test_query.cpp (+13/-8)
To merge this branch: bzr merge lp:~dobey/unity-scope-click/recommends
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Alejandro J. Cura (community) Approve
Review via email: mp+224507@code.launchpad.net

Commit message

Parse and show recommendations from the server in search results.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alejandro J. Cura (alecu) wrote :

This branch is lacking many tests.

Here's a non exhaustive list of tests that would make sense adding:
- package_list_from_json_node: single package, multiple packages, some missing field in a package
- Highlight::from_json_node: single highlight, multiple highlight, missing ci_package field in a highlight

----

Please add names to make the callback parameters more obvious, eg:
std::function<void(Packages, Packages)> callback ->
std::function<void(Packages search_results, Packages recommended)> callback

----

Please refactor the following block out of Index::search into a new method, and add tests for it:

34 + if (root.isObject() && root.isMember(Package::JsonKeys::embedded)) {
35 + auto const emb = root[Package::JsonKeys::embedded];
36 + if (emb.isObject() && emb.isMember(Package::JsonKeys::ci_package)) {
37 + auto const pkg = emb[Package::JsonKeys::ci_package];
38 + pl = click::package_list_from_json_node(pkg);
39 +
40 + if (emb.isMember(Package::JsonKeys::ci_recommends)) {
41 + auto const rec = emb[Package::JsonKeys::ci_recommends];
42 + recommends = click::package_list_from_json_node(rec);
43 + }
44 + }
45 + } else if (root.isArray()) {
46 + qDebug() << "Fell back to old array mode.";
47 + pl = click::package_list_from_json_node(root);
48 + }

Also, please check if the old Array mode is really needed, and if not let's get rid of it.

---

Why are you not using push_package in 375 and below?

371 foreach (auto p, packages) {
372 push_package(searchReply, category, installedPackages, p);
373 }
374 + foreach (auto r, recommends) {
375 + try {

If there's any reason not to use push_package, lines 375 and below should be refactored to a new method and tested.

---

Please check with design if installed packages should be shown or not on recommendations, and let's open a bug if they should be filtered.

review: Needs Fixing
302. By dobey

Merged tip of devel.

303. By dobey

Factor the parsing of search results and recommends to a new function.
List variable names in the callback declaration.

304. By dobey

Drop the old plain array mode resource_url json key.

305. By dobey

Initial tests for package_list_from_json_node.

306. By dobey

Use push_package instead of duplicating code.

307. By dobey

Fix up the translation template.

308. By dobey

A little more refactoring.

309. By dobey

Change the refactored function to return a pair instead of take a callback.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alejandro J. Cura (alecu) wrote :

Looks good.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libclickscope/click/highlights.cpp'
2--- libclickscope/click/highlights.cpp 2014-06-18 17:37:13 +0000
3+++ libclickscope/click/highlights.cpp 2014-06-26 18:57:41 +0000
4@@ -69,7 +69,8 @@
5 if (item.isObject() && item.isMember(Highlight::JsonKeys::name))
6 {
7 auto name = item[Highlight::JsonKeys::name].asString();
8- auto pkgs = package_list_from_json_node(item);
9+ auto pkg_node = item[Package::JsonKeys::embedded][Package::JsonKeys::ci_package];
10+ auto pkgs = package_list_from_json_node(pkg_node);
11 highlights.push_back(Highlight(name, pkgs));
12 }
13 }
14
15=== modified file 'libclickscope/click/index.cpp'
16--- libclickscope/click/index.cpp 2014-06-23 10:25:44 +0000
17+++ libclickscope/click/index.cpp 2014-06-26 18:57:41 +0000
18@@ -114,7 +114,32 @@
19 };
20 }
21
22-click::web::Cancellable Index::search (const std::string& query, std::function<void(click::Packages)> callback)
23+std::pair<Packages, Packages> Index::package_lists_from_json(const std::string& json)
24+{
25+ Json::Reader reader;
26+ Json::Value root;
27+
28+ click::Packages pl;
29+ click::Packages recommends;
30+ if (reader.parse(json, root)) {
31+ if (root.isObject() && root.isMember(Package::JsonKeys::embedded)) {
32+ auto const emb = root[Package::JsonKeys::embedded];
33+ if (emb.isObject() && emb.isMember(Package::JsonKeys::ci_package)) {
34+ auto const pkg = emb[Package::JsonKeys::ci_package];
35+ pl = click::package_list_from_json_node(pkg);
36+
37+ if (emb.isMember(Package::JsonKeys::ci_recommends)) {
38+ auto const rec = emb[Package::JsonKeys::ci_recommends];
39+ recommends = click::package_list_from_json_node(rec);
40+ }
41+ }
42+ }
43+ }
44+ return std::pair<Packages, Packages>(pl, recommends);
45+}
46+
47+click::web::Cancellable Index::search (const std::string& query,
48+ std::function<void(click::Packages search_results, click::Packages recommendations)> callback)
49 {
50 click::web::CallParams params;
51 const std::string built_query(build_index_query(query, ""));
52@@ -123,21 +148,16 @@
53 get_base_url() + click::SEARCH_PATH, "GET", false, build_headers(), "", params));
54
55 QObject::connect(response.data(), &click::web::Response::finished, [=](QString reply) {
56- Json::Reader reader;
57- Json::Value root;
58-
59- click::Packages pl;
60- if (reader.parse(reply.toUtf8().constData(), root)) {
61- pl = click::package_list_from_json_node(root);
62- qDebug() << "found packages:" << pl.size();
63- }
64- callback(pl);
65+ std::pair<Packages, Packages> package_lists;
66+ package_lists = package_lists_from_json(reply.toUtf8().constData());
67+ callback(package_lists.first, package_lists.second);
68 });
69 QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/) {
70 qDebug() << "No packages found due to network error";
71 click::Packages pl;
72+ click::Packages recommends;
73 qDebug() << "calling callback";
74- callback(pl);
75+ callback(pl, recommends);
76 qDebug() << " ...Done!";
77 });
78 return click::web::Cancellable(response);
79
80=== modified file 'libclickscope/click/index.h'
81--- libclickscope/click/index.h 2014-06-23 10:25:44 +0000
82+++ libclickscope/click/index.h 2014-06-26 18:57:41 +0000
83@@ -74,7 +74,8 @@
84 enum class Error {NoError, CredentialsError, NetworkError};
85 Index(const QSharedPointer<click::web::Client>& client,
86 const QSharedPointer<Configuration> configuration=QSharedPointer<Configuration>(new Configuration()));
87- virtual click::web::Cancellable search (const std::string& query, std::function<void(Packages)> callback);
88+ virtual std::pair<Packages, Packages> package_lists_from_json(const std::string& json);
89+ virtual click::web::Cancellable search (const std::string& query, std::function<void(Packages, Packages)> callback);
90 virtual click::web::Cancellable get_details(const std::string& package_name, std::function<void(PackageDetails, Error)> callback);
91 virtual click::web::Cancellable bootstrap(std::function<void(const DepartmentList&, const HighlightList&, Error, int)> callback);
92 virtual click::web::Cancellable departments(const std::string& department_href, std::function<void(const DepartmentList&, const HighlightList&, Error, int)> callback);
93
94=== modified file 'libclickscope/click/package.cpp'
95--- libclickscope/click/package.cpp 2014-06-18 18:18:14 +0000
96+++ libclickscope/click/package.cpp 2014-06-26 18:57:41 +0000
97@@ -75,42 +75,18 @@
98 p.price = item[Package::JsonKeys::price].asDouble();
99 p.icon_url = item[Package::JsonKeys::icon_url].asString();
100 p.url = item[Package::JsonKeys::links][Package::JsonKeys::self][Package::JsonKeys::href].asString();
101- if (p.url.empty()) {
102- p.url = item[Package::JsonKeys::resource_url].asString();
103- }
104 return p;
105 }
106
107 Packages package_list_from_json_node(const Json::Value& root)
108 {
109 Packages pl;
110- if (root.isObject() && root.isMember(Package::JsonKeys::embedded))
111- {
112- auto const emb = root[Package::JsonKeys::embedded];
113- if (emb.isObject() && emb.isMember(Package::JsonKeys::ci_package))
114- {
115- auto const pkg = emb[Package::JsonKeys::ci_package];
116- for (uint i = 0; i < pkg.size(); i++)
117- {
118- Package p;
119- const json::Value item = pkg[i];
120- p = package_from_json_node(item);
121- pl.push_back(p);
122- }
123- }
124- }
125- else if (root.isArray())
126- {
127- qDebug() << "Fell back to old array mode.";
128- qDebug() << root.size() << "packages returned.";
129- for (uint i = 0; i < root.size(); i++)
130- {
131-
132- Package p;
133- const json::Value item = root[i];
134- p = package_from_json_node(item);
135- pl.push_back(p);
136- }
137+ for (uint i = 0; i < root.size(); i++)
138+ {
139+ Package p;
140+ const json::Value item = root[i];
141+ p = package_from_json_node(item);
142+ pl.push_back(p);
143 }
144 return pl;
145 }
146
147=== modified file 'libclickscope/click/package.h'
148--- libclickscope/click/package.h 2014-06-18 09:01:20 +0000
149+++ libclickscope/click/package.h 2014-06-26 18:57:41 +0000
150@@ -54,11 +54,11 @@
151 constexpr static const char* self{"self"};
152 constexpr static const char* href{"href"};
153 constexpr static const char* ci_package {"clickindex:package"};
154+ constexpr static const char* ci_recommends {"clickindex:recommendation"};
155 constexpr static const char* name{"name"};
156 constexpr static const char* title{"title"};
157 constexpr static const char* price{"price"};
158 constexpr static const char* icon_url{"icon_url"};
159- constexpr static const char* resource_url{"resource_url"};
160 };
161
162 Package() = default;
163
164=== modified file 'libclickscope/tests/CMakeLists.txt'
165--- libclickscope/tests/CMakeLists.txt 2014-06-18 11:29:58 +0000
166+++ libclickscope/tests/CMakeLists.txt 2014-06-26 18:57:41 +0000
167@@ -21,15 +21,16 @@
168 mock_ubuntuone_credentials.h
169 mock_webclient.h
170
171+ test_bootstrap.cpp
172+ test_configuration.cpp
173+ test_departments.cpp
174 test_download_manager.cpp
175 test_index.cpp
176 test_interface.cpp
177- test_configuration.cpp
178+ test_package.cpp
179 test_reviews.cpp
180 test_smartconnect.cpp
181 test_webclient.cpp
182- test_bootstrap.cpp
183- test_departments.cpp
184
185 ${CMAKE_CURRENT_BINARY_DIR}/test_data.cpp
186 )
187
188=== modified file 'libclickscope/tests/fake_json.h'
189--- libclickscope/tests/fake_json.h 2014-06-23 11:33:55 +0000
190+++ libclickscope/tests/fake_json.h 2014-06-26 18:57:41 +0000
191@@ -74,6 +74,24 @@
192 }
193 )foo";
194
195+const std::string FAKE_JSON_SEARCH_RESULT_MISSING_DATA = R"foo({
196+ "_embedded": {
197+ "clickindex:package": [
198+ {
199+ "name": "org.example.awesomelauncher",
200+ "title": "Awesome Launcher",
201+ "description": "This is an awesome launcher.",
202+ "_links": {
203+ "self": {
204+ "href": "http://search.apps.ubuntu.com/api/v1/package/org.example.awesomelauncher"
205+ }
206+ }
207+ }
208+ ]
209+ }
210+ }
211+)foo";
212+
213 const std::string FAKE_JSON_SEARCH_RESULT_MANY = R"foo({
214 "_embedded": {
215 "clickindex:package": [
216@@ -118,6 +136,40 @@
217 }
218 )foo";
219
220+const std::string FAKE_JSON_SEARCH_RESULT_RECOMMENDS = R"foo({
221+ "_embedded": {
222+ "clickindex:package": [
223+ {
224+ "name": "org.example.awesomelauncher",
225+ "title": "Awesome Launcher",
226+ "description": "This is an awesome launcher.",
227+ "price": 1.99,
228+ "icon_url": "http://software-center.ubuntu.com/site_media/appmedia/2012/09/SPAZ.png",
229+ "_links": {
230+ "self": {
231+ "href": "http://search.apps.ubuntu.com/api/v1/package/org.example.awesomelauncher"
232+ }
233+ }
234+ }
235+ ],
236+ "clickindex:recommendation": [
237+ {
238+ "name": "org.example.awesomelauncher2",
239+ "title": "Awesome Launcher 2",
240+ "description": "This is an another awesome launcher.",
241+ "price": 1.99,
242+ "icon_url": "http://software-center.ubuntu.com/site_media/appmedia/2012/09/SPAZ.png",
243+ "_links": {
244+ "self": {
245+ "href": "http://search.apps.ubuntu.com/api/v1/package/org.example.awesomelauncher2"
246+ }
247+ }
248+ }
249+ ]
250+ }
251+ }
252+)foo";
253+
254 const std::string FAKE_JSON_PACKAGE_DETAILS = R"foo(
255 {
256 "name": "ar.com.beuno.wheather-touch",
257
258=== modified file 'libclickscope/tests/test_index.cpp'
259--- libclickscope/tests/test_index.cpp 2014-06-23 10:25:44 +0000
260+++ libclickscope/tests/test_index.cpp 2014-06-26 18:57:41 +0000
261@@ -79,7 +79,7 @@
262 DefaultValue<std::map<std::string, std::string>>::Set(std::map<std::string, std::string>());
263 }
264 public:
265- MOCK_METHOD1(search_callback, void(click::Packages));
266+ MOCK_METHOD2(search_callback, void(click::Packages, click::Packages));
267 MOCK_METHOD2(details_callback, void(click::PackageDetails, click::Index::Error));
268 };
269
270@@ -100,7 +100,7 @@
271 .Times(1)
272 .WillOnce(Return(response));
273
274- indexPtr->search("", [](click::Packages) {});
275+ indexPtr->search("", [](click::Packages, click::Packages) {});
276 }
277
278 TEST_F(IndexTest, testSearchSendsBuiltQueryAsParam)
279@@ -120,7 +120,7 @@
280 .Times(1)
281 .WillOnce(Return(FAKE_BUILT_QUERY));
282
283- indexPtr->search(FAKE_QUERY, [](click::Packages) {});
284+ indexPtr->search(FAKE_QUERY, [](click::Packages, click::Packages) {});
285 }
286
287 TEST_F(IndexTest, testSearchSendsRightPath)
288@@ -133,7 +133,7 @@
289 .Times(1)
290 .WillOnce(Return(response));
291
292- indexPtr->search("", [](click::Packages) {});
293+ indexPtr->search("", [](click::Packages, click::Packages) {});
294 }
295
296 TEST_F(IndexTest, testSearchCallbackIsCalled)
297@@ -148,10 +148,11 @@
298 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
299 .Times(1)
300 .WillOnce(Return(response));
301- EXPECT_CALL(*this, search_callback(_)).Times(1);
302+ EXPECT_CALL(*this, search_callback(_, _)).Times(1);
303
304- indexPtr->search("", [this](click::Packages packages){
305- search_callback(packages);
306+ indexPtr->search("", [this](click::Packages packages,
307+ click::Packages recommends){
308+ search_callback(packages, recommends);
309 });
310 response->replyFinished();
311 }
312@@ -169,10 +170,11 @@
313 .Times(1)
314 .WillOnce(Return(response));
315 click::Packages empty_package_list;
316- EXPECT_CALL(*this, search_callback(empty_package_list)).Times(1);
317+ EXPECT_CALL(*this, search_callback(empty_package_list, _)).Times(1);
318
319- indexPtr->search("", [this](click::Packages packages){
320- search_callback(packages);
321+ indexPtr->search("", [this](click::Packages packages,
322+ click::Packages recommends){
323+ search_callback(packages, recommends);
324 });
325 response->replyFinished();
326 }
327@@ -198,10 +200,11 @@
328 "http://search.apps.ubuntu.com/api/v1/package/org.example.awesomelauncher"
329 }
330 };
331- EXPECT_CALL(*this, search_callback(single_package_list)).Times(1);
332+ EXPECT_CALL(*this, search_callback(single_package_list, _)).Times(1);
333
334- indexPtr->search("", [this](click::Packages packages){
335- search_callback(packages);
336+ indexPtr->search("", [this](click::Packages packages,
337+ click::Packages recommends){
338+ search_callback(packages, recommends);
339 });
340 response->replyFinished();
341 }
342@@ -215,7 +218,8 @@
343 .Times(1)
344 .WillOnce(Return(response));
345
346- auto search_operation = indexPtr->search("", [](click::Packages) {});
347+ auto search_operation = indexPtr->search("", [](click::Packages,
348+ click::Packages) {});
349 EXPECT_CALL(reply.instance, abort()).Times(1);
350 search_operation.cancel();
351 }
352@@ -234,12 +238,13 @@
353 .Times(1)
354 .WillOnce(Return(response));
355 EXPECT_CALL(reply.instance, errorString()).Times(1).WillOnce(Return("fake error"));
356- indexPtr->search("", [this](click::Packages packages){
357- search_callback(packages);
358+ indexPtr->search("", [this](click::Packages packages,
359+ click::Packages recommends){
360+ search_callback(packages, recommends);
361 });
362
363 click::Packages empty_package_list;
364- EXPECT_CALL(*this, search_callback(empty_package_list)).Times(1);
365+ EXPECT_CALL(*this, search_callback(empty_package_list, _)).Times(1);
366
367 emit reply.instance.error(QNetworkReply::UnknownNetworkError);
368 }
369@@ -441,6 +446,19 @@
370 ASSERT_TRUE(unsetenv(click::SEARCH_BASE_URL_ENVVAR.c_str()) == 0);
371 }
372
373+TEST_F(IndexTest, testPackageListsFromJsonNodeNoRecommends)
374+{
375+ auto lists = indexPtr->package_lists_from_json(FAKE_JSON_SEARCH_RESULT_ONE);
376+ EXPECT_EQ(1, lists.first.size());
377+ EXPECT_EQ(0, lists.second.size());
378+}
379+
380+TEST_F(IndexTest, testPackageListsFromJsonNodeHasRecommends)
381+{
382+ auto lists = indexPtr->package_lists_from_json(FAKE_JSON_SEARCH_RESULT_RECOMMENDS);
383+ EXPECT_EQ(1, lists.second.size());
384+}
385+
386 TEST_F(MockPackageManager, testUninstallCommandCorrect)
387 {
388 click::Package package = {
389
390=== added file 'libclickscope/tests/test_package.cpp'
391--- libclickscope/tests/test_package.cpp 1970-01-01 00:00:00 +0000
392+++ libclickscope/tests/test_package.cpp 2014-06-26 18:57:41 +0000
393@@ -0,0 +1,74 @@
394+/*
395+ * Copyright (C) 2014 Canonical Ltd.
396+ *
397+ * This program is free software: you can redistribute it and/or modify it
398+ * under the terms of the GNU General Public License version 3, as published
399+ * by the Free Software Foundation.
400+ *
401+ * This program is distributed in the hope that it will be useful, but
402+ * WITHOUT ANY WARRANTY; without even the implied warranties of
403+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
404+ * PURPOSE. See the GNU General Public License for more details.
405+ *
406+ * You should have received a copy of the GNU General Public License along
407+ * with this program. If not, see <http://www.gnu.org/licenses/>.
408+ *
409+ * In addition, as a special exception, the copyright holders give
410+ * permission to link the code of portions of this program with the
411+ * OpenSSL library under certain conditions as described in each
412+ * individual source file, and distribute linked combinations
413+ * including the two.
414+ * You must obey the GNU General Public License in all respects
415+ * for all of the code used other than OpenSSL. If you modify
416+ * file(s) with this exception, you may extend this exception to your
417+ * version of the file(s), but you are not obligated to do so. If you
418+ * do not wish to do so, delete this exception statement from your
419+ * version. If you delete this exception statement from all source
420+ * files in the program, then also delete it here.
421+ */
422+
423+#include <click/package.h>
424+
425+#include <gtest/gtest.h>
426+
427+#include "fake_json.h"
428+
429+using namespace click;
430+
431+
432+class PackageTest : public ::testing::Test {
433+};
434+
435+TEST_F(PackageTest, testPackageListFromJsonNodeSingle)
436+{
437+ Json::Value root;
438+ Json::Reader().parse(FAKE_JSON_SEARCH_RESULT_ONE, root);
439+ auto const embedded = root[Package::JsonKeys::embedded];
440+ auto const ci_package = embedded[Package::JsonKeys::ci_package];
441+
442+ Packages pl = package_list_from_json_node(ci_package);
443+ ASSERT_EQ(1, pl.size());
444+}
445+
446+TEST_F(PackageTest, testPackageListFromJsonNodeMany)
447+{
448+ Json::Value root;
449+ Json::Reader().parse(FAKE_JSON_SEARCH_RESULT_MANY, root);
450+ auto const embedded = root[Package::JsonKeys::embedded];
451+ auto const ci_package = embedded[Package::JsonKeys::ci_package];
452+
453+ Packages pl = package_list_from_json_node(ci_package);
454+ ASSERT_GT(pl.size(), 1);
455+}
456+
457+TEST_F(PackageTest, testPackageListFromJsonNodeMissingData)
458+{
459+ Json::Value root;
460+ Json::Reader().parse(FAKE_JSON_SEARCH_RESULT_MISSING_DATA, root);
461+ auto const embedded = root[Package::JsonKeys::embedded];
462+ auto const ci_package = embedded[Package::JsonKeys::ci_package];
463+
464+ Packages pl = package_list_from_json_node(ci_package);
465+ ASSERT_EQ(1, pl.size());
466+}
467+
468
469=== modified file 'po/unity-scope-click.pot'
470--- po/unity-scope-click.pot 2014-06-25 13:43:08 +0000
471+++ po/unity-scope-click.pot 2014-06-26 18:57:41 +0000
472@@ -8,7 +8,7 @@
473 msgstr ""
474 "Project-Id-Version: PACKAGE VERSION\n"
475 "Report-Msgid-Bugs-To: \n"
476-"POT-Creation-Date: 2014-06-25 09:42-0400\n"
477+"POT-Creation-Date: 2014-06-26 14:08-0400\n"
478 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
479 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
480 "Language-Team: LANGUAGE <LL@li.org>\n"
481@@ -107,11 +107,14 @@
482 msgid "✔ INSTALLED"
483 msgstr ""
484
485-#. TODO: get the real price from the webservice (upcoming branch)
486-#: ../scope/clickstore/store-query.cpp:236
487+#: ../scope/clickstore/store-query.cpp:235
488 msgid "FREE"
489 msgstr ""
490
491 #: ../scope/clickstore/store-query.cpp:331
492 msgid "Available"
493 msgstr ""
494+
495+#: ../scope/clickstore/store-query.cpp:335
496+msgid "Recommended"
497+msgstr ""
498
499=== modified file 'scope/clickstore/store-query.cpp'
500--- scope/clickstore/store-query.cpp 2014-06-24 16:44:03 +0000
501+++ scope/clickstore/store-query.cpp 2014-06-26 18:57:41 +0000
502@@ -232,8 +232,8 @@
503 res[click::Query::ResultKeys::VERSION] = installed->version;
504 } else {
505 res[click::Query::ResultKeys::INSTALLED] = false;
506+ res["subtitle"] = _("FREE");
507 // TODO: get the real price from the webservice (upcoming branch)
508- res["subtitle"] = _("FREE");
509 }
510
511 this->push_result(searchReply, res);
512@@ -330,17 +330,28 @@
513 scopes::CategoryRenderer categoryRenderer(categoryTemplate);
514 auto category = register_category(searchReply, "appstore", _("Available"), "", categoryRenderer);
515
516+ scopes::CategoryRenderer recommendsCatRenderer(categoryTemplate);
517+ auto recommendsCategory = register_category(searchReply, "recommends",
518+ _("Recommended"), "",
519+ recommendsCatRenderer);
520+
521 assert(searchReply);
522
523 run_under_qt([=]()
524 {
525- auto search_cb = [this, searchReply, category, installedPackages](Packages packages) {
526+ auto search_cb = [this, searchReply,
527+ category, recommendsCategory,
528+ installedPackages](Packages packages, Packages recommends) {
529 qDebug("search callback");
530
531 // handle packages data
532 foreach (auto p, packages) {
533 push_package(searchReply, category, installedPackages, p);
534 }
535+ foreach (auto r, recommends) {
536+ push_package(searchReply, recommendsCategory,
537+ installedPackages, r);
538+ }
539 qDebug() << "search completed";
540 this->finished(searchReply); //FIXME: this shouldn't be needed
541 };
542
543=== modified file 'scope/tests/integration/webclient_integration.cpp'
544--- scope/tests/integration/webclient_integration.cpp 2014-06-23 10:25:44 +0000
545+++ scope/tests/integration/webclient_integration.cpp 2014-06-26 18:57:41 +0000
546@@ -103,7 +103,8 @@
547 new click::web::Client(namPtr));
548 click::Index index(clientPtr);
549 click::Packages packages;
550- index.search("qr,architecture:armhf", [&, this](click::Packages found_packages){
551+ index.search("qr", [&, this](click::Packages found_packages,
552+ click::Packages){
553 packages = found_packages;
554 Quit();
555 });
556
557=== modified file 'scope/tests/test_query.cpp'
558--- scope/tests/test_query.cpp 2014-06-23 10:25:44 +0000
559+++ scope/tests/test_query.cpp 2014-06-26 18:57:41 +0000
560@@ -58,9 +58,11 @@
561
562 class MockIndex : public click::Index {
563 click::Packages packages;
564+ click::Packages recommends;
565 click::DepartmentList departments;
566 click::DepartmentList bootstrap_departments;
567 click::HighlightList bootstrap_highlights;
568+
569 public:
570 MockIndex(click::Packages packages = click::Packages(),
571 click::DepartmentList departments = click::DepartmentList(),
572@@ -73,20 +75,23 @@
573
574 }
575
576- click::web::Cancellable search(const std::string &query, std::function<void (click::Packages)> callback) override
577+ click::web::Cancellable search(const std::string &query, std::function<void (click::Packages, click::Packages)> callback) override
578 {
579 do_search(query, callback);
580- callback(packages);
581+ callback(packages, recommends);
582 return click::web::Cancellable();
583 }
584
585+
586 click::web::Cancellable bootstrap(std::function<void(const click::DepartmentList&, const click::HighlightList&, Error, int)> callback) override
587 {
588 callback(bootstrap_departments, bootstrap_highlights, click::Index::Error::NoError, 0);
589 return click::web::Cancellable();
590 }
591
592- MOCK_METHOD2(do_search, void(const std::string&, std::function<void(click::Packages)>));
593+ MOCK_METHOD2(do_search,
594+ void(const std::string&,
595+ std::function<void(click::Packages, click::Packages)>));
596 };
597
598 class MockQueryBase : public click::Query {
599@@ -178,7 +183,7 @@
600
601 scopes::CategoryRenderer renderer("{}");
602 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
603- EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
604+ EXPECT_CALL(q, register_category(_, _, _, _, _)).Times(2).WillRepeatedly(Return(ptrCat));
605 q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE);
606 }
607
608@@ -198,7 +203,7 @@
609
610 scopes::CategoryRenderer renderer("{}");
611 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
612- EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
613+ EXPECT_CALL(q, register_category(_, _, _, _, _)).Times(2).WillRepeatedly(Return(ptrCat));
614
615 scopes::testing::MockSearchReply mock_reply;
616 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
617@@ -224,7 +229,7 @@
618
619 scopes::CategoryRenderer renderer("{}");
620 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
621- EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
622+ EXPECT_CALL(q, register_category(_, _, _, _, _)).Times(2).WillRepeatedly(Return(ptrCat));
623
624 scopes::testing::MockSearchReply mock_reply;
625 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
626@@ -273,7 +278,7 @@
627
628 scopes::CategoryRenderer renderer("{}");
629 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
630- EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
631+ EXPECT_CALL(q, register_category(_, _, _, _, _)).Times(2).WillRepeatedly(Return(ptrCat));
632
633 scopes::testing::MockSearchReply mock_reply;
634 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
635@@ -303,7 +308,7 @@
636
637 scopes::CategoryRenderer renderer("{}");
638 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
639- EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
640+ EXPECT_CALL(q, register_category(_, _, _, _, _)).Times(2).WillRepeatedly(Return(ptrCat));
641
642 scopes::testing::MockSearchReply mock_reply;
643 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});

Subscribers

People subscribed via source and target branches

to all changes: