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
=== modified file 'libclickscope/click/highlights.cpp'
--- libclickscope/click/highlights.cpp 2014-06-18 17:37:13 +0000
+++ libclickscope/click/highlights.cpp 2014-06-26 18:57:41 +0000
@@ -69,7 +69,8 @@
69 if (item.isObject() && item.isMember(Highlight::JsonKeys::name))69 if (item.isObject() && item.isMember(Highlight::JsonKeys::name))
70 {70 {
71 auto name = item[Highlight::JsonKeys::name].asString();71 auto name = item[Highlight::JsonKeys::name].asString();
72 auto pkgs = package_list_from_json_node(item);72 auto pkg_node = item[Package::JsonKeys::embedded][Package::JsonKeys::ci_package];
73 auto pkgs = package_list_from_json_node(pkg_node);
73 highlights.push_back(Highlight(name, pkgs));74 highlights.push_back(Highlight(name, pkgs));
74 }75 }
75 }76 }
7677
=== modified file 'libclickscope/click/index.cpp'
--- libclickscope/click/index.cpp 2014-06-23 10:25:44 +0000
+++ libclickscope/click/index.cpp 2014-06-26 18:57:41 +0000
@@ -114,7 +114,32 @@
114 };114 };
115}115}
116116
117click::web::Cancellable Index::search (const std::string& query, std::function<void(click::Packages)> callback)117std::pair<Packages, Packages> Index::package_lists_from_json(const std::string& json)
118{
119 Json::Reader reader;
120 Json::Value root;
121
122 click::Packages pl;
123 click::Packages recommends;
124 if (reader.parse(json, root)) {
125 if (root.isObject() && root.isMember(Package::JsonKeys::embedded)) {
126 auto const emb = root[Package::JsonKeys::embedded];
127 if (emb.isObject() && emb.isMember(Package::JsonKeys::ci_package)) {
128 auto const pkg = emb[Package::JsonKeys::ci_package];
129 pl = click::package_list_from_json_node(pkg);
130
131 if (emb.isMember(Package::JsonKeys::ci_recommends)) {
132 auto const rec = emb[Package::JsonKeys::ci_recommends];
133 recommends = click::package_list_from_json_node(rec);
134 }
135 }
136 }
137 }
138 return std::pair<Packages, Packages>(pl, recommends);
139}
140
141click::web::Cancellable Index::search (const std::string& query,
142 std::function<void(click::Packages search_results, click::Packages recommendations)> callback)
118{143{
119 click::web::CallParams params;144 click::web::CallParams params;
120 const std::string built_query(build_index_query(query, ""));145 const std::string built_query(build_index_query(query, ""));
@@ -123,21 +148,16 @@
123 get_base_url() + click::SEARCH_PATH, "GET", false, build_headers(), "", params));148 get_base_url() + click::SEARCH_PATH, "GET", false, build_headers(), "", params));
124149
125 QObject::connect(response.data(), &click::web::Response::finished, [=](QString reply) {150 QObject::connect(response.data(), &click::web::Response::finished, [=](QString reply) {
126 Json::Reader reader;151 std::pair<Packages, Packages> package_lists;
127 Json::Value root;152 package_lists = package_lists_from_json(reply.toUtf8().constData());
128153 callback(package_lists.first, package_lists.second);
129 click::Packages pl;
130 if (reader.parse(reply.toUtf8().constData(), root)) {
131 pl = click::package_list_from_json_node(root);
132 qDebug() << "found packages:" << pl.size();
133 }
134 callback(pl);
135 });154 });
136 QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/) {155 QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/) {
137 qDebug() << "No packages found due to network error";156 qDebug() << "No packages found due to network error";
138 click::Packages pl;157 click::Packages pl;
158 click::Packages recommends;
139 qDebug() << "calling callback";159 qDebug() << "calling callback";
140 callback(pl);160 callback(pl, recommends);
141 qDebug() << " ...Done!";161 qDebug() << " ...Done!";
142 });162 });
143 return click::web::Cancellable(response);163 return click::web::Cancellable(response);
144164
=== modified file 'libclickscope/click/index.h'
--- libclickscope/click/index.h 2014-06-23 10:25:44 +0000
+++ libclickscope/click/index.h 2014-06-26 18:57:41 +0000
@@ -74,7 +74,8 @@
74 enum class Error {NoError, CredentialsError, NetworkError};74 enum class Error {NoError, CredentialsError, NetworkError};
75 Index(const QSharedPointer<click::web::Client>& client,75 Index(const QSharedPointer<click::web::Client>& client,
76 const QSharedPointer<Configuration> configuration=QSharedPointer<Configuration>(new Configuration()));76 const QSharedPointer<Configuration> configuration=QSharedPointer<Configuration>(new Configuration()));
77 virtual click::web::Cancellable search (const std::string& query, std::function<void(Packages)> callback);77 virtual std::pair<Packages, Packages> package_lists_from_json(const std::string& json);
78 virtual click::web::Cancellable search (const std::string& query, std::function<void(Packages, Packages)> callback);
78 virtual click::web::Cancellable get_details(const std::string& package_name, std::function<void(PackageDetails, Error)> callback);79 virtual click::web::Cancellable get_details(const std::string& package_name, std::function<void(PackageDetails, Error)> callback);
79 virtual click::web::Cancellable bootstrap(std::function<void(const DepartmentList&, const HighlightList&, Error, int)> callback);80 virtual click::web::Cancellable bootstrap(std::function<void(const DepartmentList&, const HighlightList&, Error, int)> callback);
80 virtual click::web::Cancellable departments(const std::string& department_href, std::function<void(const DepartmentList&, const HighlightList&, Error, int)> callback);81 virtual click::web::Cancellable departments(const std::string& department_href, std::function<void(const DepartmentList&, const HighlightList&, Error, int)> callback);
8182
=== modified file 'libclickscope/click/package.cpp'
--- libclickscope/click/package.cpp 2014-06-18 18:18:14 +0000
+++ libclickscope/click/package.cpp 2014-06-26 18:57:41 +0000
@@ -75,42 +75,18 @@
75 p.price = item[Package::JsonKeys::price].asDouble();75 p.price = item[Package::JsonKeys::price].asDouble();
76 p.icon_url = item[Package::JsonKeys::icon_url].asString();76 p.icon_url = item[Package::JsonKeys::icon_url].asString();
77 p.url = item[Package::JsonKeys::links][Package::JsonKeys::self][Package::JsonKeys::href].asString();77 p.url = item[Package::JsonKeys::links][Package::JsonKeys::self][Package::JsonKeys::href].asString();
78 if (p.url.empty()) {
79 p.url = item[Package::JsonKeys::resource_url].asString();
80 }
81 return p;78 return p;
82}79}
8380
84Packages package_list_from_json_node(const Json::Value& root)81Packages package_list_from_json_node(const Json::Value& root)
85{82{
86 Packages pl;83 Packages pl;
87 if (root.isObject() && root.isMember(Package::JsonKeys::embedded))84 for (uint i = 0; i < root.size(); i++)
88 {85 {
89 auto const emb = root[Package::JsonKeys::embedded];86 Package p;
90 if (emb.isObject() && emb.isMember(Package::JsonKeys::ci_package))87 const json::Value item = root[i];
91 {88 p = package_from_json_node(item);
92 auto const pkg = emb[Package::JsonKeys::ci_package];89 pl.push_back(p);
93 for (uint i = 0; i < pkg.size(); i++)
94 {
95 Package p;
96 const json::Value item = pkg[i];
97 p = package_from_json_node(item);
98 pl.push_back(p);
99 }
100 }
101 }
102 else if (root.isArray())
103 {
104 qDebug() << "Fell back to old array mode.";
105 qDebug() << root.size() << "packages returned.";
106 for (uint i = 0; i < root.size(); i++)
107 {
108
109 Package p;
110 const json::Value item = root[i];
111 p = package_from_json_node(item);
112 pl.push_back(p);
113 }
114 }90 }
115 return pl;91 return pl;
116}92}
11793
=== modified file 'libclickscope/click/package.h'
--- libclickscope/click/package.h 2014-06-18 09:01:20 +0000
+++ libclickscope/click/package.h 2014-06-26 18:57:41 +0000
@@ -54,11 +54,11 @@
54 constexpr static const char* self{"self"};54 constexpr static const char* self{"self"};
55 constexpr static const char* href{"href"};55 constexpr static const char* href{"href"};
56 constexpr static const char* ci_package {"clickindex:package"};56 constexpr static const char* ci_package {"clickindex:package"};
57 constexpr static const char* ci_recommends {"clickindex:recommendation"};
57 constexpr static const char* name{"name"};58 constexpr static const char* name{"name"};
58 constexpr static const char* title{"title"};59 constexpr static const char* title{"title"};
59 constexpr static const char* price{"price"};60 constexpr static const char* price{"price"};
60 constexpr static const char* icon_url{"icon_url"};61 constexpr static const char* icon_url{"icon_url"};
61 constexpr static const char* resource_url{"resource_url"};
62 };62 };
6363
64 Package() = default;64 Package() = default;
6565
=== modified file 'libclickscope/tests/CMakeLists.txt'
--- libclickscope/tests/CMakeLists.txt 2014-06-18 11:29:58 +0000
+++ libclickscope/tests/CMakeLists.txt 2014-06-26 18:57:41 +0000
@@ -21,15 +21,16 @@
21 mock_ubuntuone_credentials.h21 mock_ubuntuone_credentials.h
22 mock_webclient.h22 mock_webclient.h
2323
24 test_bootstrap.cpp
25 test_configuration.cpp
26 test_departments.cpp
24 test_download_manager.cpp27 test_download_manager.cpp
25 test_index.cpp28 test_index.cpp
26 test_interface.cpp29 test_interface.cpp
27 test_configuration.cpp30 test_package.cpp
28 test_reviews.cpp31 test_reviews.cpp
29 test_smartconnect.cpp32 test_smartconnect.cpp
30 test_webclient.cpp33 test_webclient.cpp
31 test_bootstrap.cpp
32 test_departments.cpp
3334
34 ${CMAKE_CURRENT_BINARY_DIR}/test_data.cpp35 ${CMAKE_CURRENT_BINARY_DIR}/test_data.cpp
35)36)
3637
=== modified file 'libclickscope/tests/fake_json.h'
--- libclickscope/tests/fake_json.h 2014-06-23 11:33:55 +0000
+++ libclickscope/tests/fake_json.h 2014-06-26 18:57:41 +0000
@@ -74,6 +74,24 @@
74 }74 }
75)foo";75)foo";
7676
77const std::string FAKE_JSON_SEARCH_RESULT_MISSING_DATA = R"foo({
78 "_embedded": {
79 "clickindex:package": [
80 {
81 "name": "org.example.awesomelauncher",
82 "title": "Awesome Launcher",
83 "description": "This is an awesome launcher.",
84 "_links": {
85 "self": {
86 "href": "http://search.apps.ubuntu.com/api/v1/package/org.example.awesomelauncher"
87 }
88 }
89 }
90 ]
91 }
92 }
93)foo";
94
77const std::string FAKE_JSON_SEARCH_RESULT_MANY = R"foo({95const std::string FAKE_JSON_SEARCH_RESULT_MANY = R"foo({
78 "_embedded": {96 "_embedded": {
79 "clickindex:package": [97 "clickindex:package": [
@@ -118,6 +136,40 @@
118 }136 }
119)foo";137)foo";
120138
139const std::string FAKE_JSON_SEARCH_RESULT_RECOMMENDS = R"foo({
140 "_embedded": {
141 "clickindex:package": [
142 {
143 "name": "org.example.awesomelauncher",
144 "title": "Awesome Launcher",
145 "description": "This is an awesome launcher.",
146 "price": 1.99,
147 "icon_url": "http://software-center.ubuntu.com/site_media/appmedia/2012/09/SPAZ.png",
148 "_links": {
149 "self": {
150 "href": "http://search.apps.ubuntu.com/api/v1/package/org.example.awesomelauncher"
151 }
152 }
153 }
154 ],
155 "clickindex:recommendation": [
156 {
157 "name": "org.example.awesomelauncher2",
158 "title": "Awesome Launcher 2",
159 "description": "This is an another awesome launcher.",
160 "price": 1.99,
161 "icon_url": "http://software-center.ubuntu.com/site_media/appmedia/2012/09/SPAZ.png",
162 "_links": {
163 "self": {
164 "href": "http://search.apps.ubuntu.com/api/v1/package/org.example.awesomelauncher2"
165 }
166 }
167 }
168 ]
169 }
170 }
171)foo";
172
121const std::string FAKE_JSON_PACKAGE_DETAILS = R"foo(173const std::string FAKE_JSON_PACKAGE_DETAILS = R"foo(
122 {174 {
123 "name": "ar.com.beuno.wheather-touch",175 "name": "ar.com.beuno.wheather-touch",
124176
=== modified file 'libclickscope/tests/test_index.cpp'
--- libclickscope/tests/test_index.cpp 2014-06-23 10:25:44 +0000
+++ libclickscope/tests/test_index.cpp 2014-06-26 18:57:41 +0000
@@ -79,7 +79,7 @@
79 DefaultValue<std::map<std::string, std::string>>::Set(std::map<std::string, std::string>());79 DefaultValue<std::map<std::string, std::string>>::Set(std::map<std::string, std::string>());
80 }80 }
81public:81public:
82 MOCK_METHOD1(search_callback, void(click::Packages));82 MOCK_METHOD2(search_callback, void(click::Packages, click::Packages));
83 MOCK_METHOD2(details_callback, void(click::PackageDetails, click::Index::Error));83 MOCK_METHOD2(details_callback, void(click::PackageDetails, click::Index::Error));
84};84};
8585
@@ -100,7 +100,7 @@
100 .Times(1)100 .Times(1)
101 .WillOnce(Return(response));101 .WillOnce(Return(response));
102102
103 indexPtr->search("", [](click::Packages) {});103 indexPtr->search("", [](click::Packages, click::Packages) {});
104}104}
105105
106TEST_F(IndexTest, testSearchSendsBuiltQueryAsParam)106TEST_F(IndexTest, testSearchSendsBuiltQueryAsParam)
@@ -120,7 +120,7 @@
120 .Times(1)120 .Times(1)
121 .WillOnce(Return(FAKE_BUILT_QUERY));121 .WillOnce(Return(FAKE_BUILT_QUERY));
122122
123 indexPtr->search(FAKE_QUERY, [](click::Packages) {});123 indexPtr->search(FAKE_QUERY, [](click::Packages, click::Packages) {});
124}124}
125125
126TEST_F(IndexTest, testSearchSendsRightPath)126TEST_F(IndexTest, testSearchSendsRightPath)
@@ -133,7 +133,7 @@
133 .Times(1)133 .Times(1)
134 .WillOnce(Return(response));134 .WillOnce(Return(response));
135135
136 indexPtr->search("", [](click::Packages) {});136 indexPtr->search("", [](click::Packages, click::Packages) {});
137}137}
138138
139TEST_F(IndexTest, testSearchCallbackIsCalled)139TEST_F(IndexTest, testSearchCallbackIsCalled)
@@ -148,10 +148,11 @@
148 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))148 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
149 .Times(1)149 .Times(1)
150 .WillOnce(Return(response));150 .WillOnce(Return(response));
151 EXPECT_CALL(*this, search_callback(_)).Times(1);151 EXPECT_CALL(*this, search_callback(_, _)).Times(1);
152152
153 indexPtr->search("", [this](click::Packages packages){153 indexPtr->search("", [this](click::Packages packages,
154 search_callback(packages);154 click::Packages recommends){
155 search_callback(packages, recommends);
155 });156 });
156 response->replyFinished();157 response->replyFinished();
157}158}
@@ -169,10 +170,11 @@
169 .Times(1)170 .Times(1)
170 .WillOnce(Return(response));171 .WillOnce(Return(response));
171 click::Packages empty_package_list;172 click::Packages empty_package_list;
172 EXPECT_CALL(*this, search_callback(empty_package_list)).Times(1);173 EXPECT_CALL(*this, search_callback(empty_package_list, _)).Times(1);
173174
174 indexPtr->search("", [this](click::Packages packages){175 indexPtr->search("", [this](click::Packages packages,
175 search_callback(packages);176 click::Packages recommends){
177 search_callback(packages, recommends);
176 });178 });
177 response->replyFinished();179 response->replyFinished();
178}180}
@@ -198,10 +200,11 @@
198 "http://search.apps.ubuntu.com/api/v1/package/org.example.awesomelauncher"200 "http://search.apps.ubuntu.com/api/v1/package/org.example.awesomelauncher"
199 }201 }
200 };202 };
201 EXPECT_CALL(*this, search_callback(single_package_list)).Times(1);203 EXPECT_CALL(*this, search_callback(single_package_list, _)).Times(1);
202204
203 indexPtr->search("", [this](click::Packages packages){205 indexPtr->search("", [this](click::Packages packages,
204 search_callback(packages);206 click::Packages recommends){
207 search_callback(packages, recommends);
205 });208 });
206 response->replyFinished();209 response->replyFinished();
207}210}
@@ -215,7 +218,8 @@
215 .Times(1)218 .Times(1)
216 .WillOnce(Return(response));219 .WillOnce(Return(response));
217220
218 auto search_operation = indexPtr->search("", [](click::Packages) {});221 auto search_operation = indexPtr->search("", [](click::Packages,
222 click::Packages) {});
219 EXPECT_CALL(reply.instance, abort()).Times(1);223 EXPECT_CALL(reply.instance, abort()).Times(1);
220 search_operation.cancel();224 search_operation.cancel();
221}225}
@@ -234,12 +238,13 @@
234 .Times(1)238 .Times(1)
235 .WillOnce(Return(response));239 .WillOnce(Return(response));
236 EXPECT_CALL(reply.instance, errorString()).Times(1).WillOnce(Return("fake error"));240 EXPECT_CALL(reply.instance, errorString()).Times(1).WillOnce(Return("fake error"));
237 indexPtr->search("", [this](click::Packages packages){241 indexPtr->search("", [this](click::Packages packages,
238 search_callback(packages);242 click::Packages recommends){
243 search_callback(packages, recommends);
239 });244 });
240245
241 click::Packages empty_package_list;246 click::Packages empty_package_list;
242 EXPECT_CALL(*this, search_callback(empty_package_list)).Times(1);247 EXPECT_CALL(*this, search_callback(empty_package_list, _)).Times(1);
243248
244 emit reply.instance.error(QNetworkReply::UnknownNetworkError);249 emit reply.instance.error(QNetworkReply::UnknownNetworkError);
245}250}
@@ -441,6 +446,19 @@
441 ASSERT_TRUE(unsetenv(click::SEARCH_BASE_URL_ENVVAR.c_str()) == 0);446 ASSERT_TRUE(unsetenv(click::SEARCH_BASE_URL_ENVVAR.c_str()) == 0);
442}447}
443448
449TEST_F(IndexTest, testPackageListsFromJsonNodeNoRecommends)
450{
451 auto lists = indexPtr->package_lists_from_json(FAKE_JSON_SEARCH_RESULT_ONE);
452 EXPECT_EQ(1, lists.first.size());
453 EXPECT_EQ(0, lists.second.size());
454}
455
456TEST_F(IndexTest, testPackageListsFromJsonNodeHasRecommends)
457{
458 auto lists = indexPtr->package_lists_from_json(FAKE_JSON_SEARCH_RESULT_RECOMMENDS);
459 EXPECT_EQ(1, lists.second.size());
460}
461
444TEST_F(MockPackageManager, testUninstallCommandCorrect)462TEST_F(MockPackageManager, testUninstallCommandCorrect)
445{463{
446 click::Package package = {464 click::Package package = {
447465
=== added file 'libclickscope/tests/test_package.cpp'
--- libclickscope/tests/test_package.cpp 1970-01-01 00:00:00 +0000
+++ libclickscope/tests/test_package.cpp 2014-06-26 18:57:41 +0000
@@ -0,0 +1,74 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#include <click/package.h>
31
32#include <gtest/gtest.h>
33
34#include "fake_json.h"
35
36using namespace click;
37
38
39class PackageTest : public ::testing::Test {
40};
41
42TEST_F(PackageTest, testPackageListFromJsonNodeSingle)
43{
44 Json::Value root;
45 Json::Reader().parse(FAKE_JSON_SEARCH_RESULT_ONE, root);
46 auto const embedded = root[Package::JsonKeys::embedded];
47 auto const ci_package = embedded[Package::JsonKeys::ci_package];
48
49 Packages pl = package_list_from_json_node(ci_package);
50 ASSERT_EQ(1, pl.size());
51}
52
53TEST_F(PackageTest, testPackageListFromJsonNodeMany)
54{
55 Json::Value root;
56 Json::Reader().parse(FAKE_JSON_SEARCH_RESULT_MANY, root);
57 auto const embedded = root[Package::JsonKeys::embedded];
58 auto const ci_package = embedded[Package::JsonKeys::ci_package];
59
60 Packages pl = package_list_from_json_node(ci_package);
61 ASSERT_GT(pl.size(), 1);
62}
63
64TEST_F(PackageTest, testPackageListFromJsonNodeMissingData)
65{
66 Json::Value root;
67 Json::Reader().parse(FAKE_JSON_SEARCH_RESULT_MISSING_DATA, root);
68 auto const embedded = root[Package::JsonKeys::embedded];
69 auto const ci_package = embedded[Package::JsonKeys::ci_package];
70
71 Packages pl = package_list_from_json_node(ci_package);
72 ASSERT_EQ(1, pl.size());
73}
74
075
=== modified file 'po/unity-scope-click.pot'
--- po/unity-scope-click.pot 2014-06-25 13:43:08 +0000
+++ po/unity-scope-click.pot 2014-06-26 18:57:41 +0000
@@ -8,7 +8,7 @@
8msgstr ""8msgstr ""
9"Project-Id-Version: PACKAGE VERSION\n"9"Project-Id-Version: PACKAGE VERSION\n"
10"Report-Msgid-Bugs-To: \n"10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2014-06-25 09:42-0400\n"11"POT-Creation-Date: 2014-06-26 14:08-0400\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -107,11 +107,14 @@
107msgid "✔ INSTALLED"107msgid "✔ INSTALLED"
108msgstr ""108msgstr ""
109109
110#. TODO: get the real price from the webservice (upcoming branch)110#: ../scope/clickstore/store-query.cpp:235
111#: ../scope/clickstore/store-query.cpp:236
112msgid "FREE"111msgid "FREE"
113msgstr ""112msgstr ""
114113
115#: ../scope/clickstore/store-query.cpp:331114#: ../scope/clickstore/store-query.cpp:331
116msgid "Available"115msgid "Available"
117msgstr ""116msgstr ""
117
118#: ../scope/clickstore/store-query.cpp:335
119msgid "Recommended"
120msgstr ""
118121
=== modified file 'scope/clickstore/store-query.cpp'
--- scope/clickstore/store-query.cpp 2014-06-24 16:44:03 +0000
+++ scope/clickstore/store-query.cpp 2014-06-26 18:57:41 +0000
@@ -232,8 +232,8 @@
232 res[click::Query::ResultKeys::VERSION] = installed->version;232 res[click::Query::ResultKeys::VERSION] = installed->version;
233 } else {233 } else {
234 res[click::Query::ResultKeys::INSTALLED] = false;234 res[click::Query::ResultKeys::INSTALLED] = false;
235 res["subtitle"] = _("FREE");
235 // TODO: get the real price from the webservice (upcoming branch)236 // TODO: get the real price from the webservice (upcoming branch)
236 res["subtitle"] = _("FREE");
237 }237 }
238238
239 this->push_result(searchReply, res);239 this->push_result(searchReply, res);
@@ -330,17 +330,28 @@
330 scopes::CategoryRenderer categoryRenderer(categoryTemplate);330 scopes::CategoryRenderer categoryRenderer(categoryTemplate);
331 auto category = register_category(searchReply, "appstore", _("Available"), "", categoryRenderer);331 auto category = register_category(searchReply, "appstore", _("Available"), "", categoryRenderer);
332332
333 scopes::CategoryRenderer recommendsCatRenderer(categoryTemplate);
334 auto recommendsCategory = register_category(searchReply, "recommends",
335 _("Recommended"), "",
336 recommendsCatRenderer);
337
333 assert(searchReply);338 assert(searchReply);
334339
335 run_under_qt([=]()340 run_under_qt([=]()
336 {341 {
337 auto search_cb = [this, searchReply, category, installedPackages](Packages packages) {342 auto search_cb = [this, searchReply,
343 category, recommendsCategory,
344 installedPackages](Packages packages, Packages recommends) {
338 qDebug("search callback");345 qDebug("search callback");
339346
340 // handle packages data347 // handle packages data
341 foreach (auto p, packages) {348 foreach (auto p, packages) {
342 push_package(searchReply, category, installedPackages, p);349 push_package(searchReply, category, installedPackages, p);
343 }350 }
351 foreach (auto r, recommends) {
352 push_package(searchReply, recommendsCategory,
353 installedPackages, r);
354 }
344 qDebug() << "search completed";355 qDebug() << "search completed";
345 this->finished(searchReply); //FIXME: this shouldn't be needed356 this->finished(searchReply); //FIXME: this shouldn't be needed
346 };357 };
347358
=== modified file 'scope/tests/integration/webclient_integration.cpp'
--- scope/tests/integration/webclient_integration.cpp 2014-06-23 10:25:44 +0000
+++ scope/tests/integration/webclient_integration.cpp 2014-06-26 18:57:41 +0000
@@ -103,7 +103,8 @@
103 new click::web::Client(namPtr));103 new click::web::Client(namPtr));
104 click::Index index(clientPtr);104 click::Index index(clientPtr);
105 click::Packages packages;105 click::Packages packages;
106 index.search("qr,architecture:armhf", [&, this](click::Packages found_packages){106 index.search("qr", [&, this](click::Packages found_packages,
107 click::Packages){
107 packages = found_packages;108 packages = found_packages;
108 Quit();109 Quit();
109 });110 });
110111
=== modified file 'scope/tests/test_query.cpp'
--- scope/tests/test_query.cpp 2014-06-23 10:25:44 +0000
+++ scope/tests/test_query.cpp 2014-06-26 18:57:41 +0000
@@ -58,9 +58,11 @@
5858
59class MockIndex : public click::Index {59class MockIndex : public click::Index {
60 click::Packages packages;60 click::Packages packages;
61 click::Packages recommends;
61 click::DepartmentList departments;62 click::DepartmentList departments;
62 click::DepartmentList bootstrap_departments;63 click::DepartmentList bootstrap_departments;
63 click::HighlightList bootstrap_highlights;64 click::HighlightList bootstrap_highlights;
65
64public:66public:
65 MockIndex(click::Packages packages = click::Packages(),67 MockIndex(click::Packages packages = click::Packages(),
66 click::DepartmentList departments = click::DepartmentList(),68 click::DepartmentList departments = click::DepartmentList(),
@@ -73,20 +75,23 @@
7375
74 }76 }
7577
76 click::web::Cancellable search(const std::string &query, std::function<void (click::Packages)> callback) override78 click::web::Cancellable search(const std::string &query, std::function<void (click::Packages, click::Packages)> callback) override
77 {79 {
78 do_search(query, callback);80 do_search(query, callback);
79 callback(packages);81 callback(packages, recommends);
80 return click::web::Cancellable();82 return click::web::Cancellable();
81 }83 }
8284
85
83 click::web::Cancellable bootstrap(std::function<void(const click::DepartmentList&, const click::HighlightList&, Error, int)> callback) override86 click::web::Cancellable bootstrap(std::function<void(const click::DepartmentList&, const click::HighlightList&, Error, int)> callback) override
84 {87 {
85 callback(bootstrap_departments, bootstrap_highlights, click::Index::Error::NoError, 0);88 callback(bootstrap_departments, bootstrap_highlights, click::Index::Error::NoError, 0);
86 return click::web::Cancellable();89 return click::web::Cancellable();
87 }90 }
8891
89 MOCK_METHOD2(do_search, void(const std::string&, std::function<void(click::Packages)>));92 MOCK_METHOD2(do_search,
93 void(const std::string&,
94 std::function<void(click::Packages, click::Packages)>));
90};95};
9196
92class MockQueryBase : public click::Query {97class MockQueryBase : public click::Query {
@@ -178,7 +183,7 @@
178183
179 scopes::CategoryRenderer renderer("{}");184 scopes::CategoryRenderer renderer("{}");
180 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);185 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
181 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));186 EXPECT_CALL(q, register_category(_, _, _, _, _)).Times(2).WillRepeatedly(Return(ptrCat));
182 q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE);187 q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE);
183}188}
184189
@@ -198,7 +203,7 @@
198203
199 scopes::CategoryRenderer renderer("{}");204 scopes::CategoryRenderer renderer("{}");
200 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);205 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
201 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));206 EXPECT_CALL(q, register_category(_, _, _, _, _)).Times(2).WillRepeatedly(Return(ptrCat));
202207
203 scopes::testing::MockSearchReply mock_reply;208 scopes::testing::MockSearchReply mock_reply;
204 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});209 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
@@ -224,7 +229,7 @@
224229
225 scopes::CategoryRenderer renderer("{}");230 scopes::CategoryRenderer renderer("{}");
226 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);231 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
227 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));232 EXPECT_CALL(q, register_category(_, _, _, _, _)).Times(2).WillRepeatedly(Return(ptrCat));
228233
229 scopes::testing::MockSearchReply mock_reply;234 scopes::testing::MockSearchReply mock_reply;
230 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});235 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
@@ -273,7 +278,7 @@
273278
274 scopes::CategoryRenderer renderer("{}");279 scopes::CategoryRenderer renderer("{}");
275 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);280 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
276 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));281 EXPECT_CALL(q, register_category(_, _, _, _, _)).Times(2).WillRepeatedly(Return(ptrCat));
277282
278 scopes::testing::MockSearchReply mock_reply;283 scopes::testing::MockSearchReply mock_reply;
279 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});284 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
@@ -303,7 +308,7 @@
303308
304 scopes::CategoryRenderer renderer("{}");309 scopes::CategoryRenderer renderer("{}");
305 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);310 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
306 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));311 EXPECT_CALL(q, register_category(_, _, _, _, _)).Times(2).WillRepeatedly(Return(ptrCat));
307312
308 scopes::testing::MockSearchReply mock_reply;313 scopes::testing::MockSearchReply mock_reply;
309 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});314 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});

Subscribers

People subscribed via source and target branches

to all changes: