Merge lp:~stolowski/unity-scope-click/departments into lp:unity-scope-click/devel
- departments
- Merge into devel
Status: | Superseded |
---|---|
Proposed branch: | lp:~stolowski/unity-scope-click/departments |
Merge into: | lp:unity-scope-click/devel |
Prerequisite: | lp:~stolowski/unity-scope-click/update-for-api-0.5.0 |
Diff against target: |
2069 lines (+1475/-36) (has conflicts) 25 files modified
libclickscope/click/CMakeLists.txt (+3/-0) libclickscope/click/department-lookup.cpp (+84/-0) libclickscope/click/department-lookup.h (+58/-0) libclickscope/click/departments.cpp (+173/-0) libclickscope/click/departments.h (+83/-0) libclickscope/click/highlights.cpp (+95/-0) libclickscope/click/highlights.h (+72/-0) libclickscope/click/index.cpp (+40/-2) libclickscope/click/index.h (+6/-1) libclickscope/click/package.h (+1/-0) libclickscope/click/webclient.cpp (+2/-1) libclickscope/click/webclient.h (+1/-1) libclickscope/tests/CMakeLists.txt (+2/-0) libclickscope/tests/fake_json.h (+271/-0) libclickscope/tests/mock_network_access_manager.h (+1/-0) libclickscope/tests/mock_webclient.h (+2/-2) libclickscope/tests/test_bootstrap.cpp (+73/-0) libclickscope/tests/test_departments.cpp (+151/-0) libclickscope/tests/test_index.cpp (+2/-2) scope/clickstore/store-query.cpp (+238/-1) scope/clickstore/store-query.h (+16/-3) scope/clickstore/store-scope.cpp (+31/-3) scope/clickstore/store-scope.h (+10/-0) scope/tests/integration/webclient_integration.cpp (+1/-0) scope/tests/test_query.cpp (+59/-20) Text conflict in scope/clickstore/store-query.cpp Text conflict in scope/clickstore/store-scope.cpp |
To merge this branch: | bzr merge lp:~stolowski/unity-scope-click/departments |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Alejandro J. Cura (community) | Needs Fixing | ||
dobey | Pending | ||
Review via email: mp+223629@code.launchpad.net |
This proposal supersedes a proposal from 2014-05-12.
This proposal has been superseded by a proposal from 2014-06-23.
Commit message
Description of the change
Add support for departments and highlights.
dobey (dobey) wrote : Posted in a previous version of this proposal | # |
dobey (dobey) wrote : Posted in a previous version of this proposal | # |
Can you also add a commit with --fixes=lp:1209224 to link that bug?
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:254
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
dobey (dobey) wrote : Posted in a previous version of this proposal | # |
This conflicts with the changes in https:/
Paweł Stołowski (stolowski) wrote : | # |
That should have been fixed now.
- 257. By Paweł Stołowski
-
Merged devel.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:255
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:257
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Alejandro J. Cura (alecu) wrote : | # |
On one hand, I like this branch.
I've run it on my desktop against testing, and it's showing the highlights as expected, and seems to be working fine otherwise, so kudos for that.
On the other, I'm a bit disappointed with the length, and a bit more that the unit testing for it seems lacking. Here's a list of what I've found is missing:
- tests for methods in departments.cpp (eg: from_json_
- tests for failures in departments json parsing
- tests for DepartmentLooku
- tests for parsing Highlights, and for failing to parse them
- tests for Index::bootstrap and Index::departments
- test_query has fixes for existing "search" tests, but it has no new tests for Highlights, Departments
Also, I think Index::bootstrap() could be rewritten as just a call to Index::
Before approving I'd like to have jenkins build a proper package to test on the device.
After that, and since we are so close to feature freeze, I'll propose to land this, and to open a bug for the missing tests.
- 258. By Paweł Stołowski
-
Reuse code between bootstrap and departments call.
- 259. By Paweł Stołowski
-
Cleanups. Check department href in tests.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:259
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 260. By Paweł Stołowski
-
Test get_department_
info().
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:260
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 261. By Paweł Stołowski
-
Added tests for broken departments json.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:261
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 262. By Paweł Stołowski
-
Don't pass departments with search.
- 263. By Paweł Stołowski
-
Test for invalid highlights. Cleanups.
- 264. By Paweł Stołowski
-
Reuse push_package().
- 265. By Paweł Stołowski
-
Fixed comment.
- 266. By Paweł Stołowski
-
Test bootstrap call.
- 267. By Paweł Stołowski
-
Merged devel.
Unmerged revisions
Preview Diff
1 | === modified file 'libclickscope/click/CMakeLists.txt' |
2 | --- libclickscope/click/CMakeLists.txt 2014-06-20 20:00:53 +0000 |
3 | +++ libclickscope/click/CMakeLists.txt 2014-06-23 10:26:18 +0000 |
4 | @@ -12,6 +12,9 @@ |
5 | add_library(${SCOPE_LIB_NAME} STATIC |
6 | configuration.cpp |
7 | download-manager.cpp |
8 | + department-lookup.cpp |
9 | + departments.cpp |
10 | + highlights.cpp |
11 | index.cpp |
12 | interface.cpp |
13 | key_file_locator.cpp |
14 | |
15 | === added file 'libclickscope/click/department-lookup.cpp' |
16 | --- libclickscope/click/department-lookup.cpp 1970-01-01 00:00:00 +0000 |
17 | +++ libclickscope/click/department-lookup.cpp 2014-06-23 10:26:18 +0000 |
18 | @@ -0,0 +1,84 @@ |
19 | +/* |
20 | + * Copyright (C) 2014 Canonical Ltd. |
21 | + * |
22 | + * This program is free software: you can redistribute it and/or modify it |
23 | + * under the terms of the GNU General Public License version 3, as published |
24 | + * by the Free Software Foundation. |
25 | + * |
26 | + * This program is distributed in the hope that it will be useful, but |
27 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
28 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
29 | + * PURPOSE. See the GNU General Public License for more details. |
30 | + * |
31 | + * You should have received a copy of the GNU General Public License along |
32 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
33 | + * |
34 | + * In addition, as a special exception, the copyright holders give |
35 | + * permission to link the code of portions of this program with the |
36 | + * OpenSSL library under certain conditions as described in each |
37 | + * individual source file, and distribute linked combinations |
38 | + * including the two. |
39 | + * You must obey the GNU General Public License in all respects |
40 | + * for all of the code used other than OpenSSL. If you modify |
41 | + * file(s) with this exception, you may extend this exception to your |
42 | + * version of the file(s), but you are not obligated to do so. If you |
43 | + * do not wish to do so, delete this exception statement from your |
44 | + * version. If you delete this exception statement from all source |
45 | + * files in the program, then also delete it here. |
46 | + */ |
47 | + |
48 | +#include "department-lookup.h" |
49 | + |
50 | +namespace click |
51 | +{ |
52 | + |
53 | +DepartmentLookup::DepartmentLookup() |
54 | +{ |
55 | +} |
56 | + |
57 | +void DepartmentLookup::rebuild(const Department::SPtr& dept) |
58 | +{ |
59 | + departments[dept->id()] = dept; |
60 | + for (auto const& subdep: dept->sub_departments()) |
61 | + { |
62 | + parent_lut[subdep->id()] = dept; |
63 | + rebuild(subdep); |
64 | + } |
65 | +} |
66 | + |
67 | +void DepartmentLookup::rebuild(const std::list<Department::SPtr>& root_departments) |
68 | +{ |
69 | + parent_lut.clear(); |
70 | + departments.clear(); |
71 | + for (auto const& dep: root_departments) |
72 | + { |
73 | + rebuild(dep); |
74 | + } |
75 | +} |
76 | + |
77 | +Department::SPtr DepartmentLookup::get_parent(const std::string& department_id) const |
78 | +{ |
79 | + auto it = parent_lut.find(department_id); |
80 | + if (it != parent_lut.end()) |
81 | + { |
82 | + return it->second; |
83 | + } |
84 | + return Department::SPtr(nullptr); |
85 | +} |
86 | + |
87 | +Department::SPtr DepartmentLookup::get_department_info(const std::string& department_id) const |
88 | +{ |
89 | + auto it = departments.find(department_id); |
90 | + if (it != departments.end()) |
91 | + { |
92 | + return it->second; |
93 | + } |
94 | + return nullptr; |
95 | +} |
96 | + |
97 | +int DepartmentLookup::size() const |
98 | +{ |
99 | + return parent_lut.size(); |
100 | +} |
101 | + |
102 | +} |
103 | |
104 | === added file 'libclickscope/click/department-lookup.h' |
105 | --- libclickscope/click/department-lookup.h 1970-01-01 00:00:00 +0000 |
106 | +++ libclickscope/click/department-lookup.h 2014-06-23 10:26:18 +0000 |
107 | @@ -0,0 +1,58 @@ |
108 | +/* |
109 | + * Copyright (C) 2014 Canonical Ltd. |
110 | + * |
111 | + * This program is free software: you can redistribute it and/or modify it |
112 | + * under the terms of the GNU General Public License version 3, as published |
113 | + * by the Free Software Foundation. |
114 | + * |
115 | + * This program is distributed in the hope that it will be useful, but |
116 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
117 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
118 | + * PURPOSE. See the GNU General Public License for more details. |
119 | + * |
120 | + * You should have received a copy of the GNU General Public License along |
121 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
122 | + * |
123 | + * In addition, as a special exception, the copyright holders give |
124 | + * permission to link the code of portions of this program with the |
125 | + * OpenSSL library under certain conditions as described in each |
126 | + * individual source file, and distribute linked combinations |
127 | + * including the two. |
128 | + * You must obey the GNU General Public License in all respects |
129 | + * for all of the code used other than OpenSSL. If you modify |
130 | + * file(s) with this exception, you may extend this exception to your |
131 | + * version of the file(s), but you are not obligated to do so. If you |
132 | + * do not wish to do so, delete this exception statement from your |
133 | + * version. If you delete this exception statement from all source |
134 | + * files in the program, then also delete it here. |
135 | + */ |
136 | + |
137 | +#ifndef CLICK_DEPARTMENT_LOOKUP_H |
138 | +#define CLICK_DEPARTMENT_LOOKUP_H |
139 | + |
140 | +#include "departments.h" |
141 | +#include <string> |
142 | +#include <memory> |
143 | +#include <map> |
144 | + |
145 | +namespace click |
146 | +{ |
147 | + |
148 | +class DepartmentLookup |
149 | +{ |
150 | + public: |
151 | + DepartmentLookup(); |
152 | + void rebuild(const std::list<Department::SPtr>& root_departments); |
153 | + Department::SPtr get_parent(const std::string& department_id) const; |
154 | + Department::SPtr get_department_info(const std::string& department_id) const; |
155 | + int size() const; |
156 | + |
157 | + private: |
158 | + void rebuild(const Department::SPtr& dept); |
159 | + std::map<std::string, Department::SPtr> parent_lut; |
160 | + std::map<std::string, Department::SPtr> departments; |
161 | +}; |
162 | + |
163 | +} |
164 | + |
165 | +#endif |
166 | |
167 | === added file 'libclickscope/click/departments.cpp' |
168 | --- libclickscope/click/departments.cpp 1970-01-01 00:00:00 +0000 |
169 | +++ libclickscope/click/departments.cpp 2014-06-23 10:26:18 +0000 |
170 | @@ -0,0 +1,173 @@ |
171 | +/* |
172 | + * Copyright (C) 2014 Canonical Ltd. |
173 | + * |
174 | + * This program is free software: you can redistribute it and/or modify it |
175 | + * under the terms of the GNU General Public License version 3, as published |
176 | + * by the Free Software Foundation. |
177 | + * |
178 | + * This program is distributed in the hope that it will be useful, but |
179 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
180 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
181 | + * PURPOSE. See the GNU General Public License for more details. |
182 | + * |
183 | + * You should have received a copy of the GNU General Public License along |
184 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
185 | + * |
186 | + * In addition, as a special exception, the copyright holders give |
187 | + * permission to link the code of portions of this program with the |
188 | + * OpenSSL library under certain conditions as described in each |
189 | + * individual source file, and distribute linked combinations |
190 | + * including the two. |
191 | + * You must obey the GNU General Public License in all respects |
192 | + * for all of the code used other than OpenSSL. If you modify |
193 | + * file(s) with this exception, you may extend this exception to your |
194 | + * version of the file(s), but you are not obligated to do so. If you |
195 | + * do not wish to do so, delete this exception statement from your |
196 | + * version. If you delete this exception statement from all source |
197 | + * files in the program, then also delete it here. |
198 | + */ |
199 | + |
200 | +#include "departments.h" |
201 | +#include <iostream> |
202 | + |
203 | +namespace click |
204 | +{ |
205 | + |
206 | +Department::Department(const std::string& id, const std::string &name, const std::string& href, bool has_children) |
207 | + : id_(id), |
208 | + name_(name), |
209 | + href_(href), |
210 | + has_children_flag_(has_children) |
211 | +{ |
212 | +} |
213 | + |
214 | +std::string Department::id() const |
215 | +{ |
216 | + return id_; |
217 | +} |
218 | + |
219 | +std::string Department::name() const |
220 | +{ |
221 | + return name_; |
222 | +} |
223 | + |
224 | +std::string Department::href() const |
225 | +{ |
226 | + return href_; |
227 | +} |
228 | + |
229 | +bool Department::has_children_flag() const |
230 | +{ |
231 | + return has_children_flag_; |
232 | +} |
233 | + |
234 | +void Department::set_subdepartments(const std::list<Department::SPtr>& deps) |
235 | +{ |
236 | + sub_departments_ = deps; |
237 | +} |
238 | + |
239 | +std::list<Department::SPtr> Department::sub_departments() const |
240 | +{ |
241 | + return sub_departments_; |
242 | +} |
243 | + |
244 | +Json::Value Department::check_mandatory_attribute(const Json::Value& item, const std::string& name, Json::ValueType valtype) |
245 | +{ |
246 | + if (!item.isMember(name)) { |
247 | + throw std::runtime_error("Missing '" + name + "' node"); |
248 | + } |
249 | + auto const val = item[name]; |
250 | + if (val.type() != valtype) { |
251 | + throw std::runtime_error("Invalid type of '" + name + "' node"); |
252 | + } |
253 | + return val; |
254 | +} |
255 | + |
256 | +std::list<Department::SPtr> Department::from_json_node(const Json::Value& node) |
257 | +{ |
258 | + std::list<Department::SPtr> deps; |
259 | + |
260 | + for (uint i = 0; i < node.size(); i++) |
261 | + { |
262 | + try |
263 | + { |
264 | + auto const item = node[i]; |
265 | + |
266 | + auto name = check_mandatory_attribute(item, Department::JsonKeys::name, Json::ValueType::stringValue).asString(); |
267 | + const bool has_children = item.isMember(Department::JsonKeys::has_children) ? item[Department::JsonKeys::has_children].asBool() : false; |
268 | + |
269 | + auto const links = check_mandatory_attribute(item, Department::JsonKeys::links, Json::ValueType::objectValue); |
270 | + auto const self = check_mandatory_attribute(links, Department::JsonKeys::self, Json::ValueType::objectValue); |
271 | + auto const href = check_mandatory_attribute(self, Department::JsonKeys::href, Json::ValueType::stringValue).asString(); |
272 | + |
273 | + auto dep = std::make_shared<Department>(name, name, href, has_children); //FIXME: id |
274 | + if (item.isObject() && item.isMember(Department::JsonKeys::embedded)) |
275 | + { |
276 | + auto const emb = item[Department::JsonKeys::embedded]; |
277 | + if (emb.isObject() && emb.isMember(Department::JsonKeys::department)) |
278 | + { |
279 | + auto const ditem = emb[Department::JsonKeys::department]; |
280 | + auto const subdeps = from_json_node(ditem); |
281 | + dep->set_subdepartments(subdeps); |
282 | + } |
283 | + } |
284 | + deps.push_back(dep); |
285 | + } |
286 | + catch (const std::runtime_error& e) |
287 | + { |
288 | + std::cerr << "Invalid department #" << i << std::endl; |
289 | + } |
290 | + } |
291 | + |
292 | + return deps; |
293 | +} |
294 | + |
295 | +std::list<Department::SPtr> Department::from_json_root_node(const Json::Value& root) |
296 | +{ |
297 | + if (root.isObject() && root.isMember(Department::JsonKeys::embedded)) |
298 | + { |
299 | + auto const emb = root[Department::JsonKeys::embedded]; |
300 | + if (emb.isObject() && emb.isMember(Department::JsonKeys::department)) |
301 | + { |
302 | + auto const ditem = emb[Department::JsonKeys::department]; |
303 | + return from_json_node(ditem); |
304 | + } |
305 | + } |
306 | + |
307 | + return std::list<Department::SPtr>(); |
308 | +} |
309 | + |
310 | +std::list<Department::SPtr> Department::from_json(const std::string& json) |
311 | +{ |
312 | + Json::Reader reader; |
313 | + Json::Value root; |
314 | + |
315 | + try |
316 | + { |
317 | + if (!reader.parse(json, root)) { |
318 | + throw std::runtime_error(reader.getFormattedErrorMessages()); |
319 | + } |
320 | + |
321 | + if (root.isObject() && root.isMember(Department::JsonKeys::embedded)) |
322 | + { |
323 | + auto const emb = root[Department::JsonKeys::embedded]; |
324 | + if (emb.isObject() && emb.isMember(Department::JsonKeys::department)) |
325 | + { |
326 | + auto const ditem = emb[Department::JsonKeys::department]; |
327 | + return from_json_node(ditem); |
328 | + } |
329 | + } |
330 | + } |
331 | + catch (const std::exception& e) |
332 | + { |
333 | + std::cerr << "Error parsing departments: " << e.what() << std::endl; |
334 | + } |
335 | + catch (...) |
336 | + { |
337 | + std::cerr << "Unknown error when parsing departments" << std::endl; |
338 | + } |
339 | + |
340 | + return std::list<Department::SPtr>(); |
341 | +} |
342 | + |
343 | +} |
344 | |
345 | === added file 'libclickscope/click/departments.h' |
346 | --- libclickscope/click/departments.h 1970-01-01 00:00:00 +0000 |
347 | +++ libclickscope/click/departments.h 2014-06-23 10:26:18 +0000 |
348 | @@ -0,0 +1,83 @@ |
349 | +/* |
350 | + * Copyright (C) 2014 Canonical Ltd. |
351 | + * |
352 | + * This program is free software: you can redistribute it and/or modify it |
353 | + * under the terms of the GNU General Public License version 3, as published |
354 | + * by the Free Software Foundation. |
355 | + * |
356 | + * This program is distributed in the hope that it will be useful, but |
357 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
358 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
359 | + * PURPOSE. See the GNU General Public License for more details. |
360 | + * |
361 | + * You should have received a copy of the GNU General Public License along |
362 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
363 | + * |
364 | + * In addition, as a special exception, the copyright holders give |
365 | + * permission to link the code of portions of this program with the |
366 | + * OpenSSL library under certain conditions as described in each |
367 | + * individual source file, and distribute linked combinations |
368 | + * including the two. |
369 | + * You must obey the GNU General Public License in all respects |
370 | + * for all of the code used other than OpenSSL. If you modify |
371 | + * file(s) with this exception, you may extend this exception to your |
372 | + * version of the file(s), but you are not obligated to do so. If you |
373 | + * do not wish to do so, delete this exception statement from your |
374 | + * version. If you delete this exception statement from all source |
375 | + * files in the program, then also delete it here. |
376 | + */ |
377 | + |
378 | +#ifndef CLICK_DEPARTMENTS_H |
379 | +#define CLICK_DEPARTMENTS_H |
380 | + |
381 | +#include <string> |
382 | +#include <list> |
383 | +#include <memory> |
384 | +#include <json/json.h> |
385 | + |
386 | +namespace click |
387 | +{ |
388 | + |
389 | +class Department |
390 | +{ |
391 | + public: |
392 | + typedef std::shared_ptr<Department> SPtr; |
393 | + typedef std::shared_ptr<Department const> SCPtr; |
394 | + |
395 | + struct JsonKeys |
396 | + { |
397 | + JsonKeys() = delete; |
398 | + constexpr static const char* name {"name"}; |
399 | + constexpr static const char* embedded {"_embedded"}; |
400 | + constexpr static const char* department {"clickindex:department"}; |
401 | + constexpr static const char* has_children {"has_children"}; |
402 | + constexpr static const char* links {"_links"}; |
403 | + constexpr static const char* self {"self"}; |
404 | + constexpr static const char* href {"href"}; |
405 | + }; |
406 | + |
407 | + Department(const std::string &id, const std::string &name, const std::string& href, bool has_children); |
408 | + std::string id() const; |
409 | + std::string name() const; |
410 | + std::string href() const; |
411 | + bool has_children_flag() const; |
412 | + void set_subdepartments(const std::list<Department::SPtr>& deps); |
413 | + std::list<Department::SPtr> sub_departments() const; |
414 | + static std::list<Department::SPtr> from_json(const std::string& json); |
415 | + static std::list<Department::SPtr> from_json_root_node(const Json::Value& val); |
416 | + |
417 | + private: |
418 | + static std::list<Department::SPtr> from_json_node(const Json::Value& val); |
419 | + static Json::Value check_mandatory_attribute(const Json::Value& item, const std::string& name, Json::ValueType valtype); |
420 | + std::string id_; |
421 | + std::string name_; |
422 | + std::string href_; |
423 | + bool has_children_flag_; |
424 | + std::list<Department::SPtr> sub_departments_; |
425 | +}; |
426 | + |
427 | +typedef std::list<Department::SPtr> DepartmentList; |
428 | + |
429 | +} |
430 | + |
431 | +#endif |
432 | |
433 | === added file 'libclickscope/click/highlights.cpp' |
434 | --- libclickscope/click/highlights.cpp 1970-01-01 00:00:00 +0000 |
435 | +++ libclickscope/click/highlights.cpp 2014-06-23 10:26:18 +0000 |
436 | @@ -0,0 +1,95 @@ |
437 | +/* |
438 | + * Copyright (C) 2014 Canonical Ltd. |
439 | + * |
440 | + * This program is free software: you can redistribute it and/or modify it |
441 | + * under the terms of the GNU General Public License version 3, as published |
442 | + * by the Free Software Foundation. |
443 | + * |
444 | + * This program is distributed in the hope that it will be useful, but |
445 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
446 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
447 | + * PURPOSE. See the GNU General Public License for more details. |
448 | + * |
449 | + * You should have received a copy of the GNU General Public License along |
450 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
451 | + * |
452 | + * In addition, as a special exception, the copyright holders give |
453 | + * permission to link the code of portions of this program with the |
454 | + * OpenSSL library under certain conditions as described in each |
455 | + * individual source file, and distribute linked combinations |
456 | + * including the two. |
457 | + * You must obey the GNU General Public License in all respects |
458 | + * for all of the code used other than OpenSSL. If you modify |
459 | + * file(s) with this exception, you may extend this exception to your |
460 | + * version of the file(s), but you are not obligated to do so. If you |
461 | + * do not wish to do so, delete this exception statement from your |
462 | + * version. If you delete this exception statement from all source |
463 | + * files in the program, then also delete it here. |
464 | + */ |
465 | + |
466 | +#include "highlights.h" |
467 | +#include <iostream> |
468 | + |
469 | +namespace click |
470 | +{ |
471 | + |
472 | +Highlight::Highlight(const std::string& name) |
473 | + : name_(name) |
474 | +{ |
475 | +} |
476 | + |
477 | +Highlight::Highlight(const std::string& name, const Packages& pkgs) |
478 | + : name_(name), |
479 | + packages_(pkgs) |
480 | +{ |
481 | +} |
482 | + |
483 | +void Highlight::add_package(const Package& pkg) |
484 | +{ |
485 | + packages_.push_back(pkg); |
486 | +} |
487 | + |
488 | +std::string Highlight::name() const |
489 | +{ |
490 | + return name_; |
491 | +} |
492 | + |
493 | +Packages Highlight::packages() const |
494 | +{ |
495 | + return packages_; |
496 | +} |
497 | + |
498 | +std::list<Highlight> Highlight::from_json_node(const Json::Value& node) |
499 | +{ |
500 | + std::list<Highlight> highlights; |
501 | + |
502 | + for (uint i = 0; i < node.size(); i++) |
503 | + { |
504 | + auto const item = node[i]; |
505 | + if (item.isObject() && item.isMember(Highlight::JsonKeys::name)) |
506 | + { |
507 | + auto name = item[Highlight::JsonKeys::name].asString(); |
508 | + auto pkgs = package_list_from_json_node(item); |
509 | + highlights.push_back(Highlight(name, pkgs)); |
510 | + } |
511 | + } |
512 | + |
513 | + return highlights; |
514 | +} |
515 | + |
516 | +std::list<Highlight> Highlight::from_json_root_node(const Json::Value& root) |
517 | +{ |
518 | + if (root.isObject() && root.isMember(Highlight::JsonKeys::embedded)) |
519 | + { |
520 | + auto const emb = root[Highlight::JsonKeys::embedded]; |
521 | + if (emb.isObject() && emb.isMember(Highlight::JsonKeys::highlight)) |
522 | + { |
523 | + auto const hl = emb[Highlight::JsonKeys::highlight]; |
524 | + return from_json_node(hl); |
525 | + } |
526 | + } |
527 | + |
528 | + return std::list<Highlight>(); |
529 | +} |
530 | + |
531 | +} |
532 | |
533 | === added file 'libclickscope/click/highlights.h' |
534 | --- libclickscope/click/highlights.h 1970-01-01 00:00:00 +0000 |
535 | +++ libclickscope/click/highlights.h 2014-06-23 10:26:18 +0000 |
536 | @@ -0,0 +1,72 @@ |
537 | +/* |
538 | + * Copyright (C) 2014 Canonical Ltd. |
539 | + * |
540 | + * This program is free software: you can redistribute it and/or modify it |
541 | + * under the terms of the GNU General Public License version 3, as published |
542 | + * by the Free Software Foundation. |
543 | + * |
544 | + * This program is distributed in the hope that it will be useful, but |
545 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
546 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
547 | + * PURPOSE. See the GNU General Public License for more details. |
548 | + * |
549 | + * You should have received a copy of the GNU General Public License along |
550 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
551 | + * |
552 | + * In addition, as a special exception, the copyright holders give |
553 | + * permission to link the code of portions of this program with the |
554 | + * OpenSSL library under certain conditions as described in each |
555 | + * individual source file, and distribute linked combinations |
556 | + * including the two. |
557 | + * You must obey the GNU General Public License in all respects |
558 | + * for all of the code used other than OpenSSL. If you modify |
559 | + * file(s) with this exception, you may extend this exception to your |
560 | + * version of the file(s), but you are not obligated to do so. If you |
561 | + * do not wish to do so, delete this exception statement from your |
562 | + * version. If you delete this exception statement from all source |
563 | + * files in the program, then also delete it here. |
564 | + */ |
565 | + |
566 | +#ifndef CLICK_HIGHLIGHTS_H |
567 | +#define CLICK_HIGHLIGHTS_H |
568 | + |
569 | +#include <string> |
570 | +#include <list> |
571 | +#include <json/json.h> |
572 | +#include <click/package.h> |
573 | + |
574 | +namespace click |
575 | +{ |
576 | + |
577 | +class Highlight |
578 | +{ |
579 | +public: |
580 | + struct JsonKeys |
581 | + { |
582 | + JsonKeys() = delete; |
583 | + constexpr static const char* name {"name"}; |
584 | + constexpr static const char* embedded {"_embedded"}; |
585 | + constexpr static const char* highlight {"clickindex:highlight"}; |
586 | + }; |
587 | + |
588 | + Highlight(const std::string& name); |
589 | + Highlight(const std::string& name, const Packages& pkgs); |
590 | + void add_package(const Package& pkg); |
591 | + |
592 | + std::string name() const; |
593 | + Packages packages() const; |
594 | + |
595 | + static std::list<Highlight> from_json_root_node(const Json::Value& val); |
596 | + |
597 | +private: |
598 | + static std::list<Highlight> from_json_node(const Json::Value& val); |
599 | + |
600 | + std::string name_; |
601 | + Packages packages_; |
602 | +}; |
603 | + |
604 | +typedef std::list<Highlight> HighlightList; |
605 | + |
606 | +} |
607 | + |
608 | +#endif |
609 | |
610 | === modified file 'libclickscope/click/index.cpp' |
611 | --- libclickscope/click/index.cpp 2014-06-12 21:05:25 +0000 |
612 | +++ libclickscope/click/index.cpp 2014-06-23 10:26:18 +0000 |
613 | @@ -88,11 +88,15 @@ |
614 | |
615 | } |
616 | |
617 | -std::string Index::build_index_query(const std::string& query) |
618 | +std::string Index::build_index_query(const std::string& query, const std::string& department) |
619 | { |
620 | std::stringstream result; |
621 | |
622 | result << query; |
623 | + if (!department.empty()) { |
624 | + result << ",department:" << department; |
625 | + } |
626 | + |
627 | return result.str(); |
628 | } |
629 | |
630 | @@ -113,7 +117,7 @@ |
631 | click::web::Cancellable Index::search (const std::string& query, std::function<void(click::Packages)> callback) |
632 | { |
633 | click::web::CallParams params; |
634 | - const std::string built_query(build_index_query(query)); |
635 | + const std::string built_query(build_index_query(query, "")); |
636 | params.add(click::QUERY_ARGNAME, built_query.c_str()); |
637 | QSharedPointer<click::web::Response> response(client->call( |
638 | get_base_url() + click::SEARCH_PATH, "GET", false, build_headers(), "", params)); |
639 | @@ -139,6 +143,40 @@ |
640 | return click::web::Cancellable(response); |
641 | } |
642 | |
643 | +click::web::Cancellable Index::bootstrap(std::function<void(const click::DepartmentList&, const click::HighlightList&, Error, int)> callback) |
644 | +{ |
645 | + return departments(get_base_url() + click::BOOTSTRAP_PATH, callback); |
646 | +} |
647 | + |
648 | +click::web::Cancellable Index::departments(const std::string& department_href, std::function<void(const DepartmentList&, const HighlightList&, Error, int)> callback) |
649 | +{ |
650 | + click::web::CallParams params; |
651 | + QSharedPointer<click::web::Response> response(client->call( |
652 | + department_href, "GET", false, build_headers(), "", params)); |
653 | + |
654 | + QObject::connect(response.data(), &click::web::Response::finished, [=](QString reply) { |
655 | + qDebug() << "departments request finished"; |
656 | + Json::Reader reader; |
657 | + Json::Value root; |
658 | + |
659 | + click::DepartmentList depts; |
660 | + click::HighlightList highlights; |
661 | + if (reader.parse(reply.toUtf8().constData(), root)) { |
662 | + depts = Department::from_json_root_node(root); |
663 | + highlights = Highlight::from_json_root_node(root); |
664 | + } |
665 | + callback(depts, highlights, click::Index::Error::NoError, 0); |
666 | + }); |
667 | + QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/, int error_code) { |
668 | + qWarning() << "departments call failed due to network error"; |
669 | + const click::DepartmentList depts; |
670 | + const click::HighlightList highlights; |
671 | + qDebug() << "departments: calling callback"; |
672 | + callback(depts, highlights, click::Index::Error::NetworkError, error_code); |
673 | + }); |
674 | + return click::web::Cancellable(response); |
675 | +} |
676 | + |
677 | click::web::Cancellable Index::get_details (const std::string& package_name, std::function<void(PackageDetails, click::Index::Error)> callback) |
678 | { |
679 | QSharedPointer<click::web::Response> response = client->call |
680 | |
681 | === modified file 'libclickscope/click/index.h' |
682 | --- libclickscope/click/index.h 2014-06-12 21:05:25 +0000 |
683 | +++ libclickscope/click/index.h 2014-06-23 10:26:18 +0000 |
684 | @@ -38,6 +38,8 @@ |
685 | #include <click/webclient.h> |
686 | |
687 | #include "package.h" |
688 | +#include <click/departments.h> |
689 | +#include <click/highlights.h> |
690 | |
691 | |
692 | namespace click { |
693 | @@ -47,6 +49,7 @@ |
694 | const std::string SEARCH_BASE_URL_ENVVAR = "U1_SEARCH_BASE_URL"; |
695 | const std::string SEARCH_BASE_URL = "https://search.apps.ubuntu.com/"; |
696 | const std::string SEARCH_PATH = "api/v1/search"; |
697 | +const std::string BOOTSTRAP_PATH = "api/v1"; |
698 | const std::string SUPPORTED_FRAMEWORKS = "framework:ubuntu-sdk-13.10"; |
699 | const std::string QUERY_ARGNAME = "q"; |
700 | const std::string ARCHITECTURE = "architecture:"; |
701 | @@ -64,7 +67,7 @@ |
702 | protected: |
703 | QSharedPointer<web::Client> client; |
704 | QSharedPointer<Configuration> configuration; |
705 | - virtual std::string build_index_query(const std::string& query); |
706 | + virtual std::string build_index_query(const std::string& query, const std::string& department); |
707 | virtual std::map<std::string, std::string> build_headers(); |
708 | |
709 | public: |
710 | @@ -73,6 +76,8 @@ |
711 | const QSharedPointer<Configuration> configuration=QSharedPointer<Configuration>(new Configuration())); |
712 | virtual click::web::Cancellable search (const std::string& query, std::function<void(Packages)> callback); |
713 | virtual click::web::Cancellable get_details(const std::string& package_name, std::function<void(PackageDetails, Error)> callback); |
714 | + virtual click::web::Cancellable bootstrap(std::function<void(const DepartmentList&, const HighlightList&, Error, int)> callback); |
715 | + virtual click::web::Cancellable departments(const std::string& department_href, std::function<void(const DepartmentList&, const HighlightList&, Error, int)> callback); |
716 | virtual ~Index(); |
717 | |
718 | static std::string get_base_url (); |
719 | |
720 | === modified file 'libclickscope/click/package.h' |
721 | --- libclickscope/click/package.h 2014-06-13 22:42:02 +0000 |
722 | +++ libclickscope/click/package.h 2014-06-23 10:26:18 +0000 |
723 | @@ -34,6 +34,7 @@ |
724 | #include <string> |
725 | #include <unordered_set> |
726 | #include <vector> |
727 | +#include <functional> |
728 | |
729 | #include <json/json.h> |
730 | |
731 | |
732 | === modified file 'libclickscope/click/webclient.cpp' |
733 | --- libclickscope/click/webclient.cpp 2014-05-23 18:45:01 +0000 |
734 | +++ libclickscope/click/webclient.cpp 2014-06-23 10:26:18 +0000 |
735 | @@ -176,7 +176,8 @@ |
736 | { |
737 | auto message = reply->errorString() + QString(" (%1)").arg(network_error); |
738 | qWarning() << "Network error:" << message << "\n" << reply->readAll(); |
739 | - emit error(message); |
740 | + int error_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); |
741 | + emit error(message, error_code); |
742 | } |
743 | |
744 | void click::web::Response::abort() |
745 | |
746 | === modified file 'libclickscope/click/webclient.h' |
747 | --- libclickscope/click/webclient.h 2014-05-23 18:45:01 +0000 |
748 | +++ libclickscope/click/webclient.h 2014-06-23 10:26:18 +0000 |
749 | @@ -84,7 +84,7 @@ |
750 | |
751 | signals: |
752 | void finished(QByteArray result); |
753 | - void error(QString description); |
754 | + void error(QString description, int error_code); |
755 | |
756 | private: |
757 | QSharedPointer<click::network::Reply> reply; |
758 | |
759 | === modified file 'libclickscope/tests/CMakeLists.txt' |
760 | --- libclickscope/tests/CMakeLists.txt 2014-05-26 14:27:31 +0000 |
761 | +++ libclickscope/tests/CMakeLists.txt 2014-06-23 10:26:18 +0000 |
762 | @@ -28,6 +28,8 @@ |
763 | test_reviews.cpp |
764 | test_smartconnect.cpp |
765 | test_webclient.cpp |
766 | + test_bootstrap.cpp |
767 | + test_departments.cpp |
768 | |
769 | ${CMAKE_CURRENT_BINARY_DIR}/test_data.cpp |
770 | ) |
771 | |
772 | === modified file 'libclickscope/tests/fake_json.h' |
773 | --- libclickscope/tests/fake_json.h 2014-06-13 23:18:41 +0000 |
774 | +++ libclickscope/tests/fake_json.h 2014-06-23 10:26:18 +0000 |
775 | @@ -150,6 +150,277 @@ |
776 | } |
777 | )foo"; |
778 | |
779 | +const std::string FAKE_JSON_BOOTSTRAP = R"( |
780 | + { |
781 | + "_embedded": { |
782 | + "clickindex:department": [ |
783 | + { |
784 | + "has_children": false, |
785 | + "_links": { |
786 | + "self": { |
787 | + "href": "https://search.apps.staging.ubuntu.com/api/v1/departments/fake-subdepartment"} |
788 | + }, |
789 | + "name": "Fake Subdepartment", "slug": "fake-subdepartment"} |
790 | + ], |
791 | + "clickindex:highlight": [ |
792 | + { |
793 | + "_embedded": { |
794 | + "clickindex:package": [ |
795 | + { |
796 | + "publisher": "Awesome Widget Company", |
797 | + "name": "org.example.awesomelauncher", |
798 | + "title": "Awesome Launcher", |
799 | + "price": 1.99, |
800 | + "_links": { |
801 | + "self": { |
802 | + "href": "https://search.apps.staging.ubuntu.com/api/v1/package/org.example.awesomelauncher"} |
803 | + }, |
804 | + "icon": "http://example.org/media/org.example.awesomelauncher/icons/icon16.png" |
805 | + }, |
806 | + { |
807 | + "publisher": "Awesome Widget Company", |
808 | + "name": "org.example.awesomewidget", |
809 | + "title": "Awesome Widget", "price": 1.99, |
810 | + "_links": { |
811 | + "self": { |
812 | + "href": "https://search.apps.staging.ubuntu.com/api/v1/package/org.example.awesomewidget" |
813 | + } |
814 | + }, |
815 | + "icon": "http://example.org/media/org.example.awesomewidget/icons/icon16.png"} |
816 | + ] |
817 | + }, |
818 | + "_links": { |
819 | + "self": { |
820 | + "href": "https://search.apps.staging.ubuntu.com/api/v1/highlights/top-apps" |
821 | + } |
822 | + }, |
823 | + "name": "Top Apps", "slug": "top-apps" |
824 | + }, |
825 | + { |
826 | + "_embedded": { |
827 | + "clickindex:package": [ |
828 | + { |
829 | + "publisher": "Awesome Widget Company", |
830 | + "name": "org.example.awesomelauncher", |
831 | + "title": "Awesome Launcher", |
832 | + "price": 1.99, |
833 | + "_links": { |
834 | + "self": { |
835 | + "href": "https://search.apps.staging.ubuntu.com/api/v1/package/org.example.awesomelauncher" |
836 | + } |
837 | + }, |
838 | + "icon": "http://example.org/media/org.example.awesomelauncher/icons/icon16.png" |
839 | + }, |
840 | + { |
841 | + "publisher": "Awesome Widget Company", |
842 | + "name": "org.example.awesomewidget", |
843 | + "title": "Awesome Widget", |
844 | + "price": 1.99, |
845 | + "_links": { |
846 | + "self": { |
847 | + "href": "https://search.apps.staging.ubuntu.com/api/v1/package/org.example.awesomewidget" |
848 | + } |
849 | + }, |
850 | + "icon": "http://example.org/media/org.example.awesomewidget/icons/icon16.png" |
851 | + } |
852 | + ] |
853 | + }, |
854 | + "_links": { |
855 | + "self": { |
856 | + "href": "https://search.apps.staging.ubuntu.com/api/v1/highlights/most-purchased" |
857 | + } |
858 | + }, |
859 | + "name": "Most Purchased", |
860 | + "slug": "most-purchased" |
861 | + }, |
862 | + { |
863 | + "_embedded": { |
864 | + "clickindex:package": [ |
865 | + { |
866 | + "publisher": "Awesome Widget Company", |
867 | + "name": "org.example.awesomelauncher", |
868 | + "title": "Awesome Launcher", |
869 | + "price": 1.99, |
870 | + "_links": { |
871 | + "self": { |
872 | + "href": "https://search.apps.staging.ubuntu.com/api/v1/package/org.example.awesomelauncher" |
873 | + } |
874 | + }, |
875 | + "icon": "http://example.org/media/org.example.awesomelauncher/icons/icon16.png" |
876 | + }, |
877 | + { |
878 | + "publisher": "Awesome Widget Company", |
879 | + "name": "org.example.awesomewidget", |
880 | + "title": "Awesome Widget", |
881 | + "price": 1.99, |
882 | + "_links": { |
883 | + "self": { |
884 | + "href": "https://search.apps.staging.ubuntu.com/api/v1/package/org.example.awesomewidget" |
885 | + } |
886 | + }, |
887 | + "icon": "http://example.org/media/org.example.awesomewidget/icons/icon16.png" |
888 | + } |
889 | + ] |
890 | + }, |
891 | + "_links": { |
892 | + "self": { |
893 | + "href": "https://search.apps.staging.ubuntu.com/api/v1/highlights/new-releases" |
894 | + } |
895 | + }, |
896 | + "name": "New Releases", |
897 | + "slug": "new-releases" |
898 | + } |
899 | + ] |
900 | + }, "has_children": true, |
901 | + "_links": { |
902 | + "curies": [ |
903 | + { |
904 | + "href": "https://search.apps.staging.ubuntu.com/docs/v1/relations.html{#rel}", |
905 | + "name": "clickindex", "templated": true |
906 | + } |
907 | + ], |
908 | + "self": { |
909 | + "href": "https://search.apps.staging.ubuntu.com/api/v1/departments/fake-department-with-subdepartments" |
910 | + }, |
911 | + "collection": { |
912 | + "href": "https://search.apps.staging.ubuntu.com/api/v1/departments" |
913 | + } |
914 | + }, |
915 | + "name": "Fake Department With Subdepartments", |
916 | + "slug": "fake-department-with-subdepartments" |
917 | + })"; |
918 | + |
919 | +const std::string FAKE_JSON_DEPARTMENTS_ONLY = R"( |
920 | + { |
921 | + "_links": { |
922 | + "self": { |
923 | + "href": "https://search.apps.ubuntu.com/api/v1/departments" |
924 | + }, |
925 | + "curies": [ |
926 | + { |
927 | + "name": "clickindex", |
928 | + "href": "https://search.apps.ubuntu.com/docs/v1/relations.html{#rel}", |
929 | + "templated": true |
930 | + } |
931 | + ] |
932 | + }, |
933 | + "_embedded": { |
934 | + "clickindex:department": [ |
935 | + { |
936 | + "name": "Games", |
937 | + "_links": { |
938 | + "self": { |
939 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Games" |
940 | + } |
941 | + }, |
942 | + "_embedded": { |
943 | + "clickindex:department": [ |
944 | + { |
945 | + "name": "Board Games", |
946 | + "_links": { |
947 | + "self": { |
948 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Games/Board+Games" |
949 | + } |
950 | + } |
951 | + } |
952 | + ] |
953 | + } |
954 | + }, |
955 | + { |
956 | + "name": "Graphics", |
957 | + "_links": { |
958 | + "self": { |
959 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Graphics" |
960 | + } |
961 | + }, |
962 | + "_embedded": { |
963 | + "clickindex:department": [ |
964 | + { |
965 | + "name": "Drawing", |
966 | + "_links": { |
967 | + "self": { |
968 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Graphics/Drawing" |
969 | + } |
970 | + } |
971 | + } |
972 | + ] |
973 | + } |
974 | + }, |
975 | + { |
976 | + "name": "Internet", |
977 | + "_links": { |
978 | + "self": { |
979 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet" |
980 | + } |
981 | + }, |
982 | + "_embedded": { |
983 | + "clickindex:department": [ |
984 | + { |
985 | + "name": "Chat", |
986 | + "_links": { |
987 | + "self": { |
988 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Chat" |
989 | + } |
990 | + } |
991 | + }, |
992 | + { |
993 | + "name": "Mail", |
994 | + "_links": { |
995 | + "self": { |
996 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Mail" |
997 | + } |
998 | + } |
999 | + }, |
1000 | + { |
1001 | + "name": "Web Browsers", |
1002 | + "_links": { |
1003 | + "self": { |
1004 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Web+Browsers" |
1005 | + } |
1006 | + } |
1007 | + } |
1008 | + ] |
1009 | + } |
1010 | + } |
1011 | + ] |
1012 | + } |
1013 | +})"; |
1014 | + |
1015 | +const std::string FAKE_JSON_BROKEN_DEPARTMENTS = R"( |
1016 | + { |
1017 | + "_links": { |
1018 | + "self": { |
1019 | + "href": "https://search.apps.ubuntu.com/api/v1/departments" |
1020 | + }, |
1021 | + "curies": [ |
1022 | + { |
1023 | + "name": "clickindex", |
1024 | + "href": "https://search.apps.ubuntu.com/docs/v1/relations.html{#rel}", |
1025 | + "templated": true |
1026 | + } |
1027 | + ] |
1028 | + }, |
1029 | + "_embedded": { |
1030 | + "clickindex:department": [ |
1031 | + { |
1032 | + "name": "Games", |
1033 | + "_links": { |
1034 | + "self": { |
1035 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Games" |
1036 | + } |
1037 | + }, |
1038 | + "_embedded": { |
1039 | + "clickindex:department": [ |
1040 | + { |
1041 | + "name": "Broken department" |
1042 | + } |
1043 | + ] |
1044 | + } |
1045 | + } |
1046 | + ] |
1047 | + } |
1048 | + })"; |
1049 | + |
1050 | const std::string FAKE_JSON_MANIFEST_REMOVABLE = R"foo( |
1051 | { |
1052 | "_removable": 1, |
1053 | |
1054 | === modified file 'libclickscope/tests/mock_network_access_manager.h' |
1055 | --- libclickscope/tests/mock_network_access_manager.h 2014-05-20 19:33:41 +0000 |
1056 | +++ libclickscope/tests/mock_network_access_manager.h 2014-06-23 10:26:18 +0000 |
1057 | @@ -48,6 +48,7 @@ |
1058 | { |
1059 | // Set a default value for QByteArray-returning mocked methods. |
1060 | ::testing::DefaultValue<QByteArray>::Set(QByteArray("")); |
1061 | + ON_CALL(*this, attribute(::testing::_)).WillByDefault(::testing::Return(0)); |
1062 | } |
1063 | |
1064 | MOCK_METHOD0(abort, void()); |
1065 | |
1066 | === modified file 'libclickscope/tests/mock_webclient.h' |
1067 | --- libclickscope/tests/mock_webclient.h 2014-05-23 18:45:01 +0000 |
1068 | +++ libclickscope/tests/mock_webclient.h 2014-06-23 10:26:18 +0000 |
1069 | @@ -86,7 +86,7 @@ |
1070 | const click::web::CallParams& params)); |
1071 | QSharedPointer<click::web::Response> call( |
1072 | const std::string& iri, |
1073 | - const click::web::CallParams& params=click::web::CallParams()) { |
1074 | + const click::web::CallParams& params=click::web::CallParams()) override { |
1075 | return callImpl(iri, "GET", false, |
1076 | std::map<std::string, std::string>(), "", params); |
1077 | } |
1078 | @@ -96,7 +96,7 @@ |
1079 | bool sign = false, |
1080 | const std::map<std::string, std::string>& headers = std::map<std::string, std::string>(), |
1081 | const std::string& data = "", |
1082 | - const click::web::CallParams& params=click::web::CallParams()) { |
1083 | + const click::web::CallParams& params=click::web::CallParams()) override { |
1084 | return callImpl(iri, method, sign, headers, data, params); |
1085 | } |
1086 | }; |
1087 | |
1088 | === added file 'libclickscope/tests/test_bootstrap.cpp' |
1089 | --- libclickscope/tests/test_bootstrap.cpp 1970-01-01 00:00:00 +0000 |
1090 | +++ libclickscope/tests/test_bootstrap.cpp 2014-06-23 10:26:18 +0000 |
1091 | @@ -0,0 +1,73 @@ |
1092 | +/* |
1093 | + * Copyright (C) 2014 Canonical Ltd. |
1094 | + * |
1095 | + * This program is free software: you can redistribute it and/or modify it |
1096 | + * under the terms of the GNU General Public License version 3, as published |
1097 | + * by the Free Software Foundation. |
1098 | + * |
1099 | + * This program is distributed in the hope that it will be useful, but |
1100 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1101 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1102 | + * PURPOSE. See the GNU General Public License for more details. |
1103 | + * |
1104 | + * You should have received a copy of the GNU General Public License along |
1105 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1106 | + * |
1107 | + * In addition, as a special exception, the copyright holders give |
1108 | + * permission to link the code of portions of this program with the |
1109 | + * OpenSSL library under certain conditions as described in each |
1110 | + * individual source file, and distribute linked combinations |
1111 | + * including the two. |
1112 | + * You must obey the GNU General Public License in all respects |
1113 | + * for all of the code used other than OpenSSL. If you modify |
1114 | + * file(s) with this exception, you may extend this exception to your |
1115 | + * version of the file(s), but you are not obligated to do so. If you |
1116 | + * do not wish to do so, delete this exception statement from your |
1117 | + * version. If you delete this exception statement from all source |
1118 | + * files in the program, then also delete it here. |
1119 | + */ |
1120 | + |
1121 | +#include <gtest/gtest.h> |
1122 | +#include "fake_json.h" |
1123 | +#include <json/reader.h> |
1124 | +#include <json/value.h> |
1125 | +#include <click/highlights.h> |
1126 | +#include <click/departments.h> |
1127 | + |
1128 | +class BootstrapTest: public ::testing::Test |
1129 | +{ |
1130 | + protected: |
1131 | + void SetUp() override |
1132 | + { |
1133 | + } |
1134 | +}; |
1135 | + |
1136 | +TEST_F(BootstrapTest, testParsing) |
1137 | +{ |
1138 | + Json::Reader reader; |
1139 | + Json::Value root; |
1140 | + |
1141 | + EXPECT_TRUE(reader.parse(FAKE_JSON_BOOTSTRAP, root)); |
1142 | + |
1143 | + { |
1144 | + auto highlights = click::Highlight::from_json_root_node(root); |
1145 | + EXPECT_EQ(3u, highlights.size()); |
1146 | + auto it = highlights.begin(); |
1147 | + EXPECT_EQ("Top Apps", it->name()); |
1148 | + EXPECT_EQ(2u, it->packages().size()); |
1149 | + ++it; |
1150 | + EXPECT_EQ("Most Purchased", it->name()); |
1151 | + EXPECT_EQ(2u, it->packages().size()); |
1152 | + ++it; |
1153 | + EXPECT_EQ("New Releases", it->name()); |
1154 | + EXPECT_EQ(2u, it->packages().size()); |
1155 | + } |
1156 | + { |
1157 | + auto depts = click::Department::from_json_root_node(root); |
1158 | + EXPECT_EQ(1u, depts.size()); |
1159 | + auto it = depts.begin(); |
1160 | + EXPECT_EQ("Fake Subdepartment", (*it)->name()); |
1161 | + EXPECT_FALSE((*it)->has_children_flag()); |
1162 | + EXPECT_EQ("https://search.apps.staging.ubuntu.com/api/v1/departments/fake-subdepartment", (*it)->href()); |
1163 | + } |
1164 | +} |
1165 | |
1166 | === added file 'libclickscope/tests/test_departments.cpp' |
1167 | --- libclickscope/tests/test_departments.cpp 1970-01-01 00:00:00 +0000 |
1168 | +++ libclickscope/tests/test_departments.cpp 2014-06-23 10:26:18 +0000 |
1169 | @@ -0,0 +1,151 @@ |
1170 | +/* |
1171 | + * Copyright (C) 2014 Canonical Ltd. |
1172 | + * |
1173 | + * This program is free software: you can redistribute it and/or modify it |
1174 | + * under the terms of the GNU General Public License version 3, as published |
1175 | + * by the Free Software Foundation. |
1176 | + * |
1177 | + * This program is distributed in the hope that it will be useful, but |
1178 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1179 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1180 | + * PURPOSE. See the GNU General Public License for more details. |
1181 | + * |
1182 | + * You should have received a copy of the GNU General Public License along |
1183 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1184 | + * |
1185 | + * In addition, as a special exception, the copyright holders give |
1186 | + * permission to link the code of portions of this program with the |
1187 | + * OpenSSL library under certain conditions as described in each |
1188 | + * individual source file, and distribute linked combinations |
1189 | + * including the two. |
1190 | + * You must obey the GNU General Public License in all respects |
1191 | + * for all of the code used other than OpenSSL. If you modify |
1192 | + * file(s) with this exception, you may extend this exception to your |
1193 | + * version of the file(s), but you are not obligated to do so. If you |
1194 | + * do not wish to do so, delete this exception statement from your |
1195 | + * version. If you delete this exception statement from all source |
1196 | + * files in the program, then also delete it here. |
1197 | + */ |
1198 | + |
1199 | +#include <gtest/gtest.h> |
1200 | +#include "fake_json.h" |
1201 | +#include <click/departments.h> |
1202 | +#include <click/department-lookup.h> |
1203 | + |
1204 | +class DepartmentsTest : public ::testing::Test |
1205 | +{ |
1206 | + protected: |
1207 | + void SetUp() override |
1208 | + { |
1209 | + } |
1210 | +}; |
1211 | + |
1212 | +TEST_F(DepartmentsTest, testParsing) |
1213 | +{ |
1214 | + const std::string jsonstr(FAKE_JSON_DEPARTMENTS_ONLY); |
1215 | + auto depts = click::Department::from_json(jsonstr); |
1216 | + EXPECT_EQ(3u, depts.size()); |
1217 | + auto it = depts.cbegin(); |
1218 | + { |
1219 | + auto dep = *it; |
1220 | + EXPECT_EQ("Games", dep->id()); |
1221 | + EXPECT_EQ("Games", dep->name()); |
1222 | + EXPECT_EQ("https://search.apps.ubuntu.com/api/v1/departments/Games", dep->href()); |
1223 | + EXPECT_FALSE(dep->has_children_flag()); |
1224 | + auto subdepts = dep->sub_departments(); |
1225 | + EXPECT_EQ(1u, subdepts.size()); |
1226 | + auto sit = subdepts.cbegin(); |
1227 | + EXPECT_EQ("Board Games", (*sit)->name()); |
1228 | + } |
1229 | + { |
1230 | + ++it; |
1231 | + auto dep = *it; |
1232 | + EXPECT_EQ("Graphics", dep->id()); |
1233 | + EXPECT_EQ("Graphics", dep->name()); |
1234 | + EXPECT_EQ("https://search.apps.ubuntu.com/api/v1/departments/Graphics", dep->href()); |
1235 | + EXPECT_FALSE(dep->has_children_flag()); |
1236 | + auto subdepts = dep->sub_departments(); |
1237 | + EXPECT_EQ(1u, subdepts.size()); |
1238 | + auto sit = subdepts.cbegin(); |
1239 | + EXPECT_EQ("Drawing", (*sit)->name()); |
1240 | + } |
1241 | + { |
1242 | + ++it; |
1243 | + auto dep = *it; |
1244 | + EXPECT_EQ("Internet", dep->id()); |
1245 | + EXPECT_EQ("Internet", dep->name()); |
1246 | + EXPECT_EQ("https://search.apps.ubuntu.com/api/v1/departments/Internet", dep->href()); |
1247 | + EXPECT_FALSE(dep->has_children_flag()); |
1248 | + auto subdepts = dep->sub_departments(); |
1249 | + EXPECT_EQ(3u, subdepts.size()); |
1250 | + auto sit = subdepts.cbegin(); |
1251 | + auto subdep = *sit; |
1252 | + EXPECT_EQ("Chat", subdep->name()); |
1253 | + EXPECT_EQ("https://search.apps.ubuntu.com/api/v1/departments/Internet/Chat", subdep->href()); |
1254 | + subdep = *(++sit); |
1255 | + EXPECT_EQ("Mail", subdep->name()); |
1256 | + EXPECT_EQ("https://search.apps.ubuntu.com/api/v1/departments/Internet/Mail", subdep->href()); |
1257 | + subdep = *(++sit); |
1258 | + EXPECT_EQ("Web Browsers", subdep->name()); |
1259 | + EXPECT_EQ("https://search.apps.ubuntu.com/api/v1/departments/Internet/Web+Browsers", subdep->href()); |
1260 | + } |
1261 | +} |
1262 | + |
1263 | +TEST_F(DepartmentsTest, testParsingErrors) |
1264 | +{ |
1265 | + // invalid json |
1266 | + { |
1267 | + const std::string jsonstr("{{{"); |
1268 | + auto depts = click::Department::from_json(jsonstr); |
1269 | + EXPECT_EQ(0, depts.size()); |
1270 | + } |
1271 | + // one of the departments is invalid |
1272 | + { |
1273 | + const std::string jsonstr(FAKE_JSON_BROKEN_DEPARTMENTS); |
1274 | + auto depts = click::Department::from_json(jsonstr); |
1275 | + EXPECT_EQ(1, depts.size()); |
1276 | + } |
1277 | +} |
1278 | + |
1279 | +TEST_F(DepartmentsTest, testLookup) |
1280 | +{ |
1281 | + auto dep_games = std::make_shared<click::Department>("games", "Games", "http://foobar.com/", false); |
1282 | + auto dep_rpg = std::make_shared<click::Department>("rpg", "RPG", "http://ubuntu.com/", false); |
1283 | + auto dep_strategy = std::make_shared<click::Department>("strategy", "Strategy", "", false); |
1284 | + const std::list<click::Department::SPtr> departments {dep_rpg, dep_strategy}; |
1285 | + dep_games->set_subdepartments(departments); |
1286 | + |
1287 | + const std::list<click::Department::SPtr> root {dep_games}; |
1288 | + click::DepartmentLookup lut; |
1289 | + lut.rebuild(root); |
1290 | + |
1291 | + { |
1292 | + EXPECT_EQ(2u, lut.size()); |
1293 | + EXPECT_EQ("games", lut.get_parent("strategy")->id()); |
1294 | + EXPECT_EQ("games", lut.get_parent("rpg")->id()); |
1295 | + EXPECT_EQ(nullptr, lut.get_parent("games")); |
1296 | + } |
1297 | + { |
1298 | + auto info = lut.get_department_info("games"); |
1299 | + EXPECT_EQ("games", info->id()); |
1300 | + EXPECT_EQ("Games", info->name()); |
1301 | + EXPECT_EQ("http://foobar.com/", info->href()); |
1302 | + EXPECT_EQ(false, info->has_children_flag()); |
1303 | + |
1304 | + auto sub = info->sub_departments(); |
1305 | + EXPECT_EQ(2u, sub.size()); |
1306 | + |
1307 | + auto it = sub.begin(); |
1308 | + EXPECT_EQ("rpg", (*it)->id()); |
1309 | + EXPECT_EQ("RPG", (*it)->name()); |
1310 | + EXPECT_EQ("http://ubuntu.com/", (*it)->href()); |
1311 | + ++it; |
1312 | + EXPECT_EQ("strategy", (*it)->id()); |
1313 | + EXPECT_EQ("Strategy", (*it)->name()); |
1314 | + } |
1315 | + { |
1316 | + lut.rebuild(root); |
1317 | + EXPECT_EQ(2u, lut.size()); |
1318 | + } |
1319 | +} |
1320 | + |
1321 | |
1322 | === modified file 'libclickscope/tests/test_index.cpp' |
1323 | --- libclickscope/tests/test_index.cpp 2014-06-12 21:05:25 +0000 |
1324 | +++ libclickscope/tests/test_index.cpp 2014-06-23 10:26:18 +0000 |
1325 | @@ -52,8 +52,8 @@ |
1326 | click::Index(client, configuration) |
1327 | { |
1328 | } |
1329 | - MOCK_METHOD1(build_index_query, std::string(const std::string&)); |
1330 | MOCK_METHOD0(build_headers, std::map<std::string, std::string>()); |
1331 | + MOCK_METHOD2(build_index_query, std::string(const std::string&, const std::string&)); |
1332 | }; |
1333 | |
1334 | class MockConfiguration : public click::Configuration { |
1335 | @@ -116,7 +116,7 @@ |
1336 | .Times(1) |
1337 | .WillOnce(Return(response)); |
1338 | |
1339 | - EXPECT_CALL(*indexPtr, build_index_query(FAKE_QUERY)) |
1340 | + EXPECT_CALL(*indexPtr, build_index_query(FAKE_QUERY, "")) |
1341 | .Times(1) |
1342 | .WillOnce(Return(FAKE_BUILT_QUERY)); |
1343 | |
1344 | |
1345 | === modified file 'scope/clickstore/store-query.cpp' |
1346 | --- scope/clickstore/store-query.cpp 2014-06-18 16:23:50 +0000 |
1347 | +++ scope/clickstore/store-query.cpp 2014-06-23 10:26:18 +0000 |
1348 | @@ -30,6 +30,7 @@ |
1349 | #include <click/application.h> |
1350 | #include <click/interface.h> |
1351 | #include "store-query.h" |
1352 | +#include "store-scope.h" |
1353 | #include <click/qtbridge.h> |
1354 | |
1355 | #include <click/key_file_locator.h> |
1356 | @@ -37,6 +38,7 @@ |
1357 | #include <unity/scopes/Annotation.h> |
1358 | #include <unity/scopes/CategoryRenderer.h> |
1359 | #include <unity/scopes/CategorisedResult.h> |
1360 | +#include <unity/scopes/Department.h> |
1361 | #include <unity/scopes/CannedQuery.h> |
1362 | #include <unity/scopes/SearchReply.h> |
1363 | #include <unity/scopes/SearchMetadata.h> |
1364 | @@ -93,19 +95,37 @@ |
1365 | |
1366 | struct click::Query::Private |
1367 | { |
1368 | +<<<<<<< TREE |
1369 | Private(click::Index& index, const scopes::SearchMetadata& metadata) |
1370 | : index(index), |
1371 | +======= |
1372 | + Private(click::Index& index, click::DepartmentLookup& depts, |
1373 | + click::HighlightList& highlights, const scopes::SearchMetadata& metadata) |
1374 | + : index(index), |
1375 | + department_lookup(depts), |
1376 | + highlights(highlights), |
1377 | +>>>>>>> MERGE-SOURCE |
1378 | meta(metadata) |
1379 | { |
1380 | } |
1381 | click::Index& index; |
1382 | + click::DepartmentLookup& department_lookup; |
1383 | + click::HighlightList& highlights; |
1384 | scopes::SearchMetadata meta; |
1385 | click::web::Cancellable search_operation; |
1386 | }; |
1387 | |
1388 | +<<<<<<< TREE |
1389 | click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata) |
1390 | : unity::scopes::SearchQueryBase(query, metadata), |
1391 | impl(new Private(index, metadata)) |
1392 | +======= |
1393 | +click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, click::DepartmentLookup& depts, |
1394 | + click::HighlightList& highlights, |
1395 | + scopes::SearchMetadata const& metadata) |
1396 | + : unity::scopes::SearchQueryBase(query, metadata), |
1397 | + impl(new Private(index, depts, highlights, metadata)) |
1398 | +>>>>>>> MERGE-SOURCE |
1399 | { |
1400 | } |
1401 | |
1402 | @@ -154,6 +174,166 @@ |
1403 | }); |
1404 | } |
1405 | |
1406 | +// |
1407 | +// creates department menu with narrowed-down list of subdepartments of current department, as |
1408 | +// returned by server call |
1409 | +void click::Query::populate_departments(const click::DepartmentList& subdepts, const std::string& current_dep_id, unity::scopes::Department::SPtr &root) |
1410 | +{ |
1411 | + unity::scopes::DepartmentList departments; |
1412 | + |
1413 | + // create a list of subdepartments of current department |
1414 | + foreach (auto d, subdepts) |
1415 | + { |
1416 | + unity::scopes::Department::SPtr department = unity::scopes::Department::create(d->id(), query(), d->name()); |
1417 | + if (d->has_children_flag()) |
1418 | + { |
1419 | + department->set_has_subdepartments(); |
1420 | + } |
1421 | + departments.push_back(department); |
1422 | + } |
1423 | + |
1424 | + if (current_dep_id != "") |
1425 | + { |
1426 | + auto curr_dpt = impl->department_lookup.get_department_info(current_dep_id); |
1427 | + if (curr_dpt != nullptr) |
1428 | + { |
1429 | + unity::scopes::Department::SPtr current = unity::scopes::Department::create(current_dep_id, query(), curr_dpt->name()); |
1430 | + if (departments.size() > 0) // this may be a leaf department |
1431 | + { |
1432 | + current->set_subdepartments(departments); |
1433 | + } |
1434 | + |
1435 | + auto parent_info = impl->department_lookup.get_parent(current_dep_id); |
1436 | + if (parent_info != nullptr) |
1437 | + { |
1438 | + root = unity::scopes::Department::create(parent_info->id(), query(), parent_info->name()); |
1439 | + root->set_subdepartments({current}); |
1440 | + return; |
1441 | + } |
1442 | + else |
1443 | + { |
1444 | + root = unity::scopes::Department::create("", query(), _("All departments")); |
1445 | + root->set_subdepartments({current}); |
1446 | + return; |
1447 | + } |
1448 | + } |
1449 | + else |
1450 | + { |
1451 | + qWarning() << "Unknown department:" << QString::fromStdString(current_dep_id); |
1452 | + } |
1453 | + } |
1454 | + |
1455 | + root = unity::scopes::Department::create("", query(), _("All departments")); |
1456 | + root->set_subdepartments(departments); |
1457 | +} |
1458 | + |
1459 | +void click::Query::push_package(const scopes::SearchReplyProxy& searchReply, scopes::Category::SCPtr category, const PackageSet &installedPackages, const Package& pkg) |
1460 | +{ |
1461 | + qDebug() << "pushing result" << QString::fromStdString(pkg.name); |
1462 | + try { |
1463 | + scopes::CategorisedResult res(category); |
1464 | + res.set_title(pkg.title); |
1465 | + res.set_art(pkg.icon_url); |
1466 | + res.set_uri(pkg.url); |
1467 | + res[click::Query::ResultKeys::NAME] = pkg.name; |
1468 | + auto installed = installedPackages.find(pkg); |
1469 | + if (installed != installedPackages.end()) { |
1470 | + res[click::Query::ResultKeys::INSTALLED] = true; |
1471 | + res["subtitle"] = _("✔ INSTALLED"); |
1472 | + res[click::Query::ResultKeys::VERSION] = installed->version; |
1473 | + } else { |
1474 | + res[click::Query::ResultKeys::INSTALLED] = false; |
1475 | + // TODO: get the real price from the webservice (upcoming branch) |
1476 | + res["subtitle"] = _("FREE"); |
1477 | + } |
1478 | + |
1479 | + this->push_result(searchReply, res); |
1480 | + } catch(const std::exception& e){ |
1481 | + qDebug() << "PackageDetails::loadJson: Exception thrown while decoding JSON: " << e.what() ; |
1482 | + } catch(...){ |
1483 | + qDebug() << "no reason to catch"; |
1484 | + } |
1485 | +} |
1486 | + |
1487 | +void click::Query::push_highlights(const scopes::SearchReplyProxy& searchReply, const HighlightList& highlights, const PackageSet &locallyInstalledApps) |
1488 | +{ |
1489 | + std::string categoryTemplate = CATEGORY_APPS_DISPLAY; //FIXME |
1490 | + scopes::CategoryRenderer renderer(categoryTemplate); |
1491 | + |
1492 | + for (auto const& hl: highlights) |
1493 | + { |
1494 | + auto category = register_category(searchReply, hl.name(), hl.name(), "", renderer); //FIXME: highlight slug |
1495 | + for (auto const& pkg: hl.packages()) |
1496 | + { |
1497 | + push_package(searchReply, category, locallyInstalledApps, pkg); |
1498 | + } |
1499 | + } |
1500 | + qDebug() << "Highlights pushed"; |
1501 | +} |
1502 | + |
1503 | +void click::Query::push_departments(const scopes::SearchReplyProxy& searchReply, const scopes::Department::SCPtr& root) |
1504 | +{ |
1505 | + if (root != nullptr) |
1506 | + { |
1507 | + try |
1508 | + { |
1509 | + qDebug() << "pushing departments"; |
1510 | + searchReply->register_departments(root); |
1511 | + } |
1512 | + catch (const std::exception& e) |
1513 | + { |
1514 | + qWarning() << "Failed to register departments for query " << QString::fromStdString(query().query_string()) << |
1515 | + ", current department " << QString::fromStdString(query().department_id()) << ": " << e.what(); |
1516 | + } |
1517 | + } |
1518 | + else |
1519 | + { |
1520 | + qWarning() << "No departments data for query " << QString::fromStdString(query().query_string()) << |
1521 | + "', current department " << QString::fromStdString(query().department_id()); |
1522 | + } |
1523 | +} |
1524 | + |
1525 | +// |
1526 | +// push highlights and departments |
1527 | +// use cached highlights for root department, otherwise run an async job for highlights of current department. |
1528 | +void click::Query::add_highlights(scopes::SearchReplyProxy const& searchReply, const PackageSet& locallyInstalledApps) |
1529 | +{ |
1530 | + auto curdep = impl->department_lookup.get_department_info(query().department_id()); |
1531 | + assert(curdep); |
1532 | + auto subdepts = curdep->sub_departments(); |
1533 | + if (query().department_id() == "") // top-level departments |
1534 | + { |
1535 | + unity::scopes::Department::SPtr root; |
1536 | + populate_departments(subdepts, query().department_id(), root); |
1537 | + push_departments(searchReply, root); |
1538 | + |
1539 | + qDebug() << "pushing cached highlights"; |
1540 | + push_highlights(searchReply, impl->highlights, locallyInstalledApps); |
1541 | + this->finished(searchReply); //FIXME: this shouldn't be needed |
1542 | + } |
1543 | + else |
1544 | + { |
1545 | + qDebug() << "starting departments call for department" << QString::fromStdString(curdep->id()) << ", href" << QString::fromStdString(curdep->href()); |
1546 | + impl->search_operation = impl->index.departments(curdep->href(), [this, locallyInstalledApps, searchReply](const DepartmentList& depts, |
1547 | + const HighlightList& highlights, Index::Error error, int) |
1548 | + { |
1549 | + if (error == click::Index::Error::NoError) |
1550 | + { |
1551 | + qDebug() << "departments call completed"; |
1552 | + unity::scopes::Department::SPtr root; |
1553 | + populate_departments(depts, query().department_id(), root); |
1554 | + push_departments(searchReply, root); |
1555 | + push_highlights(searchReply, highlights, locallyInstalledApps); |
1556 | + } |
1557 | + else |
1558 | + { |
1559 | + qWarning() << "departments call failed"; |
1560 | + } |
1561 | + this->finished(searchReply); //FIXME: this shouldn't be needed |
1562 | + }); |
1563 | + } |
1564 | +} |
1565 | + |
1566 | void click::Query::add_available_apps(scopes::SearchReplyProxy const& searchReply, |
1567 | const PackageSet& installedPackages, |
1568 | const std::string& categoryTemplate) |
1569 | @@ -161,12 +341,14 @@ |
1570 | scopes::CategoryRenderer categoryRenderer(categoryTemplate); |
1571 | auto category = register_category(searchReply, "appstore", _("Available"), "", categoryRenderer); |
1572 | |
1573 | + assert(searchReply); |
1574 | + |
1575 | run_under_qt([=]() |
1576 | { |
1577 | auto search_cb = [this, searchReply, category, installedPackages](Packages packages) { |
1578 | qDebug("search callback"); |
1579 | |
1580 | - // handle packages data |
1581 | + // handle packages data; FIXME: use push_package() |
1582 | foreach (auto p, packages) { |
1583 | qDebug() << "pushing result" << QString::fromStdString(p.name); |
1584 | try { |
1585 | @@ -194,11 +376,66 @@ |
1586 | } |
1587 | } |
1588 | qDebug() << "search completed"; |
1589 | +<<<<<<< TREE |
1590 | this->finished(searchReply); |
1591 | }; |
1592 | |
1593 | qDebug() << "starting search of" << QString::fromStdString(query().query_string()); |
1594 | impl->search_operation = impl->index.search(query().query_string(), search_cb); |
1595 | +======= |
1596 | + this->finished(searchReply); //FIXME: this shouldn't be needed |
1597 | + }; |
1598 | + |
1599 | + // this is the case when we do bootstrap for the first time, or it failed last time |
1600 | + if (impl->department_lookup.size() == 0 && !click::Scope::use_old_api()) |
1601 | + { |
1602 | + qDebug() << "performing bootstrap request"; |
1603 | + impl->search_operation = impl->index.bootstrap([this, search_cb, searchReply, installedPackages](const DepartmentList& deps, const |
1604 | + HighlightList& highlights, click::Index::Error error, int error_code) { |
1605 | + if (error == click::Index::Error::NoError) |
1606 | + { |
1607 | + qDebug() << "bootstrap request completed"; |
1608 | + auto root = std::make_shared<click::Department>("", "All Departments", "", true); |
1609 | + root->set_subdepartments(deps); |
1610 | + DepartmentList rdeps { root }; |
1611 | + impl->department_lookup.rebuild(rdeps); |
1612 | + impl->highlights = highlights; |
1613 | + qDebug() << "Total number of departments:" << impl->department_lookup.size() << ", highlights:" << highlights.size(); |
1614 | + } |
1615 | + else |
1616 | + { |
1617 | + qWarning() << "bootstrap request failed"; |
1618 | + if (error_code == 405) // method not allowed |
1619 | + { |
1620 | + qDebug() << "bootstrap not available, using old API"; |
1621 | + click::Scope::set_use_old_api(); |
1622 | + } |
1623 | + } |
1624 | + |
1625 | + if (query().query_string().empty() && !click::Scope::use_old_api()) |
1626 | + { |
1627 | + add_highlights(searchReply, installedPackages); |
1628 | + } |
1629 | + else |
1630 | + { |
1631 | + qDebug() << "starting search of" << QString::fromStdString(query().query_string()); |
1632 | + impl->search_operation = impl->index.search(query().query_string(), search_cb); |
1633 | + } |
1634 | + }); |
1635 | + } |
1636 | + else |
1637 | + { |
1638 | + if (query().query_string().empty() && !click::Scope::use_old_api()) |
1639 | + { |
1640 | + add_highlights(searchReply, installedPackages); |
1641 | + } |
1642 | + else // normal search |
1643 | + { |
1644 | + qDebug() << "starting search of" << QString::fromStdString(query().query_string()); |
1645 | + impl->search_operation = impl->index.search(query().query_string(), search_cb); |
1646 | + } |
1647 | + } |
1648 | +>>>>>>> MERGE-SOURCE |
1649 | }); |
1650 | } |
1651 | |
1652 | |
1653 | === modified file 'scope/clickstore/store-query.h' |
1654 | --- scope/clickstore/store-query.h 2014-06-16 14:09:21 +0000 |
1655 | +++ scope/clickstore/store-query.h 2014-06-23 10:26:18 +0000 |
1656 | @@ -32,10 +32,16 @@ |
1657 | |
1658 | |
1659 | #include <unity/scopes/SearchQueryBase.h> |
1660 | +#include <unity/scopes/Department.h> |
1661 | |
1662 | namespace scopes = unity::scopes; |
1663 | |
1664 | #include <QSharedPointer> |
1665 | +#include <set> |
1666 | + |
1667 | +#include <click/department-lookup.h> |
1668 | +#include <click/package.h> |
1669 | +#include <click/highlights.h> |
1670 | #include <click/interface.h> |
1671 | |
1672 | namespace click |
1673 | @@ -43,6 +49,7 @@ |
1674 | |
1675 | class Application; |
1676 | class Index; |
1677 | +class DepartmentLookup; |
1678 | |
1679 | class Query : public scopes::SearchQueryBase |
1680 | { |
1681 | @@ -69,7 +76,8 @@ |
1682 | constexpr static const char* VERSION{"version"}; |
1683 | }; |
1684 | |
1685 | - Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata); |
1686 | + Query(unity::scopes::CannedQuery const& query, click::Index& index, click::DepartmentLookup& dept_lookup, click::HighlightList& highlights, |
1687 | + scopes::SearchMetadata const& metadata); |
1688 | virtual ~Query(); |
1689 | |
1690 | virtual void cancelled() override; |
1691 | @@ -77,8 +85,10 @@ |
1692 | virtual void run(scopes::SearchReplyProxy const& reply) override; |
1693 | |
1694 | protected: |
1695 | - virtual void add_available_apps(const scopes::SearchReplyProxy &searchReply, |
1696 | - const PackageSet &installedPackages, const std::string &category); |
1697 | + virtual void populate_departments(const click::DepartmentList& depts, const std::string& current_department_id, unity::scopes::Department::SPtr &root); |
1698 | + virtual void push_departments(const scopes::SearchReplyProxy& searchReply, const scopes::Department::SCPtr& root); |
1699 | + virtual void add_highlights(scopes::SearchReplyProxy const& searchReply, const PackageSet& installedPackages); |
1700 | + virtual void add_available_apps(const scopes::SearchReplyProxy &searchReply, const PackageSet &installedPackages, const std::string &category); |
1701 | virtual click::Interface& clickInterfaceInstance(); |
1702 | virtual PackageSet get_installed_packages(); |
1703 | virtual bool push_result(const scopes::SearchReplyProxy &searchReply, scopes::CategorisedResult const& res); |
1704 | @@ -88,6 +98,9 @@ |
1705 | std::string const& title, |
1706 | std::string const& icon, |
1707 | scopes::CategoryRenderer const& renderer_template); |
1708 | + virtual void push_package(const scopes::SearchReplyProxy& searchReply, scopes::Category::SCPtr category, const PackageSet &locallyInstalledApps, |
1709 | + const click::Package& pkg); |
1710 | + virtual void push_highlights(const scopes::SearchReplyProxy& searchReply, const HighlightList& highlights, const PackageSet &locallyInstalledApps); |
1711 | virtual void run_under_qt(const std::function<void()> &task); |
1712 | |
1713 | private: |
1714 | |
1715 | === modified file 'scope/clickstore/store-scope.cpp' |
1716 | --- scope/clickstore/store-scope.cpp 2014-06-19 17:05:34 +0000 |
1717 | +++ scope/clickstore/store-scope.cpp 2014-06-23 10:26:18 +0000 |
1718 | @@ -28,6 +28,7 @@ |
1719 | */ |
1720 | |
1721 | #include <click/qtbridge.h> |
1722 | +#include <click/department-lookup.h> |
1723 | #include "store-scope.h" |
1724 | #include "store-query.h" |
1725 | #include <click/preview.h> |
1726 | @@ -42,19 +43,36 @@ |
1727 | |
1728 | #include <logging.h> |
1729 | |
1730 | +bool click::Scope::old_api = false; |
1731 | |
1732 | click::Scope::Scope() |
1733 | { |
1734 | nam.reset(new click::network::AccessManager()); |
1735 | client.reset(new click::web::Client(nam)); |
1736 | index.reset(new click::Index(client)); |
1737 | + depts.reset(new click::DepartmentLookup()); |
1738 | + highlights.reset(new click::HighlightList()); |
1739 | } |
1740 | |
1741 | click::Scope::~Scope() |
1742 | { |
1743 | } |
1744 | |
1745 | -void click::Scope::start(std::string const&, scopes::RegistryProxy const&) |
1746 | +<<<<<<< TREE |
1747 | +void click::Scope::start(std::string const&, scopes::RegistryProxy const&) |
1748 | +======= |
1749 | +void click::Scope::set_use_old_api() |
1750 | +{ |
1751 | + old_api = true; |
1752 | +} |
1753 | + |
1754 | +bool click::Scope::use_old_api() |
1755 | +{ |
1756 | + return old_api; |
1757 | +} |
1758 | + |
1759 | +void click::Scope::start(std::string const&, scopes::RegistryProxy const&) |
1760 | +>>>>>>> MERGE-SOURCE |
1761 | { |
1762 | setlocale(LC_ALL, ""); |
1763 | // FIXME: This is wrong, but needed for json-cpp workaround. |
1764 | @@ -68,7 +86,6 @@ |
1765 | static const int zero = 0; |
1766 | auto emptyCb = [this]() |
1767 | { |
1768 | - |
1769 | }; |
1770 | |
1771 | qt::core::world::build_and_run(zero, nullptr, emptyCb); |
1772 | @@ -81,7 +98,7 @@ |
1773 | |
1774 | scopes::SearchQueryBase::UPtr click::Scope::search(unity::scopes::CannedQuery const& q, scopes::SearchMetadata const& metadata) |
1775 | { |
1776 | - return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, metadata)); |
1777 | + return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, *depts, *highlights, metadata)); |
1778 | } |
1779 | |
1780 | |
1781 | @@ -91,10 +108,21 @@ |
1782 | return scopes::PreviewQueryBase::UPtr{new click::Preview(result, metadata, client, nam)}; |
1783 | } |
1784 | |
1785 | +<<<<<<< TREE |
1786 | unity::scopes::ActivationQueryBase::UPtr click::Scope::perform_action(unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata, std::string const& /* widget_id */, std::string const& action_id) |
1787 | +======= |
1788 | +unity::scopes::ActivationQueryBase::UPtr click::Scope::perform_action(unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata, |
1789 | + std::string const& widget_id, std::string const& _action_id) |
1790 | +>>>>>>> MERGE-SOURCE |
1791 | { |
1792 | +<<<<<<< TREE |
1793 | auto activation = new ScopeActivation(result, metadata); |
1794 | qDebug() << "perform_action called with action_id" << QString().fromStdString(action_id); |
1795 | +======= |
1796 | + std::string action_id = _action_id; |
1797 | + qDebug() << "perform_action called with widget_id" << QString::fromStdString(widget_id) << "and action_id:" << QString::fromStdString(action_id); |
1798 | + auto activation = new ScopeActivation(result, metadata); |
1799 | +>>>>>>> MERGE-SOURCE |
1800 | |
1801 | // if the purchase is completed, do the install |
1802 | if (action_id == "purchaseCompleted") { |
1803 | |
1804 | === modified file 'scope/clickstore/store-scope.h' |
1805 | --- scope/clickstore/store-scope.h 2014-06-18 14:42:47 +0000 |
1806 | +++ scope/clickstore/store-scope.h 2014-06-23 10:26:18 +0000 |
1807 | @@ -30,6 +30,7 @@ |
1808 | #ifndef CLICK_SCOPE_H |
1809 | #define CLICK_SCOPE_H |
1810 | |
1811 | +#include <memory> |
1812 | #include <click/network_access_manager.h> |
1813 | #include <click/webclient.h> |
1814 | |
1815 | @@ -43,6 +44,9 @@ |
1816 | |
1817 | namespace click |
1818 | { |
1819 | + |
1820 | +class DepartmentLookup; |
1821 | + |
1822 | class Scope : public scopes::ScopeBase |
1823 | { |
1824 | public: |
1825 | @@ -60,12 +64,18 @@ |
1826 | |
1827 | virtual unity::scopes::ActivationQueryBase::UPtr perform_action(unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata, std::string const& widget_id, std::string const& action_id) override; |
1828 | |
1829 | + static void set_use_old_api(); |
1830 | + static bool use_old_api(); |
1831 | + |
1832 | private: |
1833 | QSharedPointer<click::network::AccessManager> nam; |
1834 | QSharedPointer<click::web::Client> client; |
1835 | QSharedPointer<click::Index> index; |
1836 | + std::shared_ptr<click::DepartmentLookup> depts; |
1837 | + std::shared_ptr<click::HighlightList> highlights; |
1838 | |
1839 | std::string installApplication(unity::scopes::Result const& result); |
1840 | + static bool old_api; |
1841 | }; |
1842 | } |
1843 | #endif // CLICK_SCOPE_H |
1844 | |
1845 | === modified file 'scope/tests/integration/webclient_integration.cpp' |
1846 | --- scope/tests/integration/webclient_integration.cpp 2014-06-12 21:05:25 +0000 |
1847 | +++ scope/tests/integration/webclient_integration.cpp 2014-06-23 10:26:18 +0000 |
1848 | @@ -30,6 +30,7 @@ |
1849 | #include <click/network_access_manager.h> |
1850 | #include <click/webclient.h> |
1851 | #include <click/index.h> |
1852 | +#include <click/departments.h> |
1853 | |
1854 | #include <QCoreApplication> |
1855 | #include <QDebug> |
1856 | |
1857 | === modified file 'scope/tests/test_query.cpp' |
1858 | --- scope/tests/test_query.cpp 2014-06-12 22:17:42 +0000 |
1859 | +++ scope/tests/test_query.cpp 2014-06-23 10:26:18 +0000 |
1860 | @@ -45,6 +45,7 @@ |
1861 | #include <unity/scopes/CannedQuery.h> |
1862 | #include <unity/scopes/ScopeBase.h> |
1863 | #include <unity/scopes/SearchReply.h> |
1864 | +#include <unity/scopes/testing/MockSearchReply.h> |
1865 | |
1866 | using namespace ::testing; |
1867 | using namespace click; |
1868 | @@ -57,10 +58,17 @@ |
1869 | |
1870 | class MockIndex : public click::Index { |
1871 | click::Packages packages; |
1872 | + click::DepartmentList departments; |
1873 | + click::DepartmentList bootstrap_departments; |
1874 | + click::HighlightList bootstrap_highlights; |
1875 | public: |
1876 | - MockIndex(click::Packages packages = click::Packages()) |
1877 | + MockIndex(click::Packages packages = click::Packages(), |
1878 | + click::DepartmentList departments = click::DepartmentList(), |
1879 | + click::DepartmentList boot_departments = click::DepartmentList()) |
1880 | : Index(QSharedPointer<click::web::Client>()), |
1881 | - packages(packages) |
1882 | + packages(packages), |
1883 | + departments(departments), |
1884 | + bootstrap_departments(boot_departments) |
1885 | { |
1886 | |
1887 | } |
1888 | @@ -72,15 +80,21 @@ |
1889 | return click::web::Cancellable(); |
1890 | } |
1891 | |
1892 | - MOCK_METHOD2(do_search, |
1893 | - void(const std::string&, |
1894 | - std::function<void(click::Packages)>)); |
1895 | + click::web::Cancellable bootstrap(std::function<void(const click::DepartmentList&, const click::HighlightList&, Error, int)> callback) override |
1896 | + { |
1897 | + callback(bootstrap_departments, bootstrap_highlights, click::Index::Error::NoError, 0); |
1898 | + return click::web::Cancellable(); |
1899 | + } |
1900 | + |
1901 | + MOCK_METHOD2(do_search, void(const std::string&, std::function<void(click::Packages)>)); |
1902 | }; |
1903 | |
1904 | class MockQueryBase : public click::Query { |
1905 | public: |
1906 | MockQueryBase(const unity::scopes::CannedQuery& query, click::Index& index, |
1907 | - scopes::SearchMetadata const& metadata) : click::Query(query, index, metadata) |
1908 | + click::DepartmentLookup& depts, |
1909 | + click::HighlightList& highlights, |
1910 | + scopes::SearchMetadata const& metadata) : click::Query(query, index, depts, highlights, metadata) |
1911 | { |
1912 | |
1913 | } |
1914 | @@ -94,7 +108,9 @@ |
1915 | class MockQuery : public MockQueryBase { |
1916 | public: |
1917 | MockQuery(const unity::scopes::CannedQuery& query, click::Index& index, |
1918 | - scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, metadata) |
1919 | + click::DepartmentLookup& depts, |
1920 | + click::HighlightList& highlights, |
1921 | + scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, highlights, metadata) |
1922 | { |
1923 | |
1924 | } |
1925 | @@ -118,7 +134,9 @@ |
1926 | class MockQueryRun : public MockQueryBase { |
1927 | public: |
1928 | MockQueryRun(const unity::scopes::CannedQuery& query, click::Index& index, |
1929 | - scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, metadata) |
1930 | + click::DepartmentLookup& depts, |
1931 | + click::HighlightList& highlights, |
1932 | + scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, highlights, metadata) |
1933 | { |
1934 | |
1935 | } |
1936 | @@ -147,12 +165,16 @@ |
1937 | TEST(QueryTest, testAddAvailableAppsCallsClickIndex) |
1938 | { |
1939 | MockIndex mock_index; |
1940 | + click::DepartmentLookup dept_lookup; |
1941 | + click::HighlightList highlights; |
1942 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1943 | PackageSet no_installed_packages; |
1944 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1945 | - MockQuery q(query, mock_index, metadata); |
1946 | + MockQuery q(query, mock_index, dept_lookup, highlights, metadata); |
1947 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(1); |
1948 | - scopes::SearchReplyProxy reply; |
1949 | + |
1950 | + scopes::testing::MockSearchReply mock_reply; |
1951 | + scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){}); |
1952 | |
1953 | scopes::CategoryRenderer renderer("{}"); |
1954 | auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer); |
1955 | @@ -166,17 +188,21 @@ |
1956 | {"name", "title", 0.0, "icon", "uri"} |
1957 | }; |
1958 | MockIndex mock_index(packages); |
1959 | + click::DepartmentLookup dept_lookup; |
1960 | + click::HighlightList highlights; |
1961 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1962 | PackageSet no_installed_packages; |
1963 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1964 | - MockQuery q(query, mock_index, metadata); |
1965 | + MockQuery q(query, mock_index, dept_lookup, highlights, metadata); |
1966 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1967 | |
1968 | scopes::CategoryRenderer renderer("{}"); |
1969 | auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer); |
1970 | EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat)); |
1971 | |
1972 | - scopes::SearchReplyProxy reply; |
1973 | + scopes::testing::MockSearchReply mock_reply; |
1974 | + scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){}); |
1975 | + |
1976 | auto expected_title = packages.front().title; |
1977 | EXPECT_CALL(q, push_result(_, Property(&scopes::CategorisedResult::title, expected_title))); |
1978 | q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE); |
1979 | @@ -188,17 +214,20 @@ |
1980 | {"name", "title", 0.0, "icon", "uri"} |
1981 | }; |
1982 | MockIndex mock_index(packages); |
1983 | + click::DepartmentLookup dept_lookup; |
1984 | + click::HighlightList highlights; |
1985 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1986 | PackageSet no_installed_packages; |
1987 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1988 | - MockQuery q(query, mock_index, metadata); |
1989 | + MockQuery q(query, mock_index, dept_lookup, highlights, metadata); |
1990 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1991 | |
1992 | scopes::CategoryRenderer renderer("{}"); |
1993 | auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer); |
1994 | EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat)); |
1995 | |
1996 | - scopes::SearchReplyProxy reply; |
1997 | + scopes::testing::MockSearchReply mock_reply; |
1998 | + scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){}); |
1999 | EXPECT_CALL(q, finished(_)); |
2000 | q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE); |
2001 | } |
2002 | @@ -209,10 +238,12 @@ |
2003 | {"name", "title", 0.0, "icon", "uri"} |
2004 | }; |
2005 | MockIndex mock_index(packages); |
2006 | + click::DepartmentLookup dept_lookup; |
2007 | + click::HighlightList highlights; |
2008 | scopes::SearchMetadata metadata("en_EN", "phone"); |
2009 | PackageSet no_installed_packages; |
2010 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
2011 | - MockQueryRun q(query, mock_index, metadata); |
2012 | + MockQueryRun q(query, mock_index, dept_lookup, highlights, metadata); |
2013 | auto reply = scopes::SearchReplyProxy(); |
2014 | EXPECT_CALL(q, get_installed_packages()).WillOnce(Return(no_installed_packages)); |
2015 | EXPECT_CALL(q, add_available_apps(reply, no_installed_packages, _)); |
2016 | @@ -234,15 +265,18 @@ |
2017 | PackageSet one_installed_package { |
2018 | {"org.example.app2", "0.2"} |
2019 | }; |
2020 | + click::DepartmentLookup dept_lookup; |
2021 | + click::HighlightList highlights; |
2022 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
2023 | - MockQuery q(query, mock_index, metadata); |
2024 | + MockQuery q(query, mock_index, dept_lookup, highlights, metadata); |
2025 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
2026 | |
2027 | scopes::CategoryRenderer renderer("{}"); |
2028 | auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer); |
2029 | EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat)); |
2030 | |
2031 | - scopes::SearchReplyProxy reply; |
2032 | + scopes::testing::MockSearchReply mock_reply; |
2033 | + scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){}); |
2034 | auto expected_name1 = packages.front().name; |
2035 | EXPECT_CALL(q, push_result(_, HasPackageName(expected_name1))); |
2036 | auto expected_name2 = packages.back().name; |
2037 | @@ -261,15 +295,18 @@ |
2038 | PackageSet one_installed_package { |
2039 | {"org.example.app2", "0.2"} |
2040 | }; |
2041 | + click::DepartmentLookup dept_lookup; |
2042 | + click::HighlightList highlights; |
2043 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
2044 | - MockQuery q(query, mock_index, metadata); |
2045 | + MockQuery q(query, mock_index, dept_lookup, highlights, metadata); |
2046 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
2047 | |
2048 | scopes::CategoryRenderer renderer("{}"); |
2049 | auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer); |
2050 | EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat)); |
2051 | |
2052 | - scopes::SearchReplyProxy reply; |
2053 | + scopes::testing::MockSearchReply mock_reply; |
2054 | + scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){}); |
2055 | EXPECT_CALL(q, push_result(_, IsInstalled(true))); |
2056 | EXPECT_CALL(q, push_result(_, IsInstalled(false))); |
2057 | q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE); |
2058 | @@ -288,8 +325,10 @@ |
2059 | }; |
2060 | MockIndex mock_index(uninstalled_packages); |
2061 | scopes::SearchMetadata metadata("en_EN", "phone"); |
2062 | + click::DepartmentLookup dept_lookup; |
2063 | + click::HighlightList highlights; |
2064 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
2065 | - MockQuery q(query, mock_index, metadata); |
2066 | + MockQuery q(query, mock_index, dept_lookup, highlights, metadata); |
2067 | PackageSet installed_packages{{"package_1", "0.1"}}; |
2068 | |
2069 | FakeInterface fake_interface; |
426 +std::map< std::string, std::string> Index:: build_headers( const std::string& language) click:: web::Response> response( client- >call( BOOTSTRAP_ PATH, "GET", false, build_headers( "en"), "", params)); //TODO: language
438 + {"Accept-Language", language},
486 + QSharedPointer<
487 + get_base_url() + click::
You don't need to do all this work to pass the language around or set Accept-Language manually. It is already added automatically in web::Client::cal().