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

Proposed by dobey
Status: Merged
Merged at revision: 299
Proposed branch: lp:~dobey/unity-scope-click/departments
Merge into: lp:unity-scope-click/devel
Prerequisite: lp:~dobey/unity-scope-click/search-haljson
Diff against target: 1375 lines (+808/-62)
18 files modified
scope/click/CMakeLists.txt (+2/-0)
scope/click/department-lookup.cpp (+84/-0)
scope/click/department-lookup.h (+58/-0)
scope/click/departments.cpp (+152/-0)
scope/click/departments.h (+78/-0)
scope/click/index.cpp (+39/-5)
scope/click/index.h (+5/-2)
scope/click/query.cpp (+89/-5)
scope/click/query.h (+5/-1)
scope/click/scope.cpp (+3/-1)
scope/click/scope.h (+5/-0)
scope/tests/CMakeLists.txt (+2/-1)
scope/tests/fake_json.h (+96/-0)
scope/tests/integration/webclient_integration.cpp (+3/-1)
scope/tests/mock_webclient.h (+2/-2)
scope/tests/test_departments.cpp (+108/-0)
scope/tests/test_index.cpp (+10/-10)
scope/tests/test_query.cpp (+67/-34)
To merge this branch: bzr merge lp:~dobey/unity-scope-click/departments
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Unity Team Pending
Review via email: mp+219593@code.launchpad.net

Commit message

Add support for departments.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'scope/click/CMakeLists.txt'
2--- scope/click/CMakeLists.txt 2014-05-13 19:32:29 +0000
3+++ scope/click/CMakeLists.txt 2014-05-14 20:14:25 +0000
4@@ -9,6 +9,8 @@
5 )
6
7 add_library(${SCOPE_LIB_UNVERSIONED} SHARED
8+ departments.cpp
9+ department-lookup.cpp
10 configuration.cpp
11 download-manager.cpp
12 index.cpp
13
14=== added file 'scope/click/department-lookup.cpp'
15--- scope/click/department-lookup.cpp 1970-01-01 00:00:00 +0000
16+++ scope/click/department-lookup.cpp 2014-05-14 20:14:25 +0000
17@@ -0,0 +1,84 @@
18+/*
19+ * Copyright (C) 2014 Canonical Ltd.
20+ *
21+ * This program is free software: you can redistribute it and/or modify it
22+ * under the terms of the GNU General Public License version 3, as published
23+ * by the Free Software Foundation.
24+ *
25+ * This program is distributed in the hope that it will be useful, but
26+ * WITHOUT ANY WARRANTY; without even the implied warranties of
27+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
28+ * PURPOSE. See the GNU General Public License for more details.
29+ *
30+ * You should have received a copy of the GNU General Public License along
31+ * with this program. If not, see <http://www.gnu.org/licenses/>.
32+ *
33+ * In addition, as a special exception, the copyright holders give
34+ * permission to link the code of portions of this program with the
35+ * OpenSSL library under certain conditions as described in each
36+ * individual source file, and distribute linked combinations
37+ * including the two.
38+ * You must obey the GNU General Public License in all respects
39+ * for all of the code used other than OpenSSL. If you modify
40+ * file(s) with this exception, you may extend this exception to your
41+ * version of the file(s), but you are not obligated to do so. If you
42+ * do not wish to do so, delete this exception statement from your
43+ * version. If you delete this exception statement from all source
44+ * files in the program, then also delete it here.
45+ */
46+
47+#include "department-lookup.h"
48+
49+namespace click
50+{
51+
52+DepartmentLookup::DepartmentLookup()
53+{
54+}
55+
56+void DepartmentLookup::rebuild(const Department::SPtr& dept)
57+{
58+ departments[dept->id()] = dept;
59+ for (auto const& subdep: dept->sub_departments())
60+ {
61+ parent_lut[subdep->id()] = dept;
62+ rebuild(subdep);
63+ }
64+}
65+
66+void DepartmentLookup::rebuild(const std::list<Department::SPtr>& root_departments)
67+{
68+ parent_lut.clear();
69+ departments.clear();
70+ for (auto const& dep: root_departments)
71+ {
72+ rebuild(dep);
73+ }
74+}
75+
76+Department::SPtr DepartmentLookup::get_parent(const std::string& department_id) const
77+{
78+ auto it = parent_lut.find(department_id);
79+ if (it != parent_lut.end())
80+ {
81+ return it->second;
82+ }
83+ return Department::SPtr(nullptr);
84+}
85+
86+Department::SPtr DepartmentLookup::get_department_info(const std::string& department_id) const
87+{
88+ auto it = departments.find(department_id);
89+ if (it != departments.end())
90+ {
91+ return it->second;
92+ }
93+ return nullptr;
94+}
95+
96+int DepartmentLookup::size() const
97+{
98+ return parent_lut.size();
99+}
100+
101+}
102
103=== added file 'scope/click/department-lookup.h'
104--- scope/click/department-lookup.h 1970-01-01 00:00:00 +0000
105+++ scope/click/department-lookup.h 2014-05-14 20:14:25 +0000
106@@ -0,0 +1,58 @@
107+/*
108+ * Copyright (C) 2014 Canonical Ltd.
109+ *
110+ * This program is free software: you can redistribute it and/or modify it
111+ * under the terms of the GNU General Public License version 3, as published
112+ * by the Free Software Foundation.
113+ *
114+ * This program is distributed in the hope that it will be useful, but
115+ * WITHOUT ANY WARRANTY; without even the implied warranties of
116+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
117+ * PURPOSE. See the GNU General Public License for more details.
118+ *
119+ * You should have received a copy of the GNU General Public License along
120+ * with this program. If not, see <http://www.gnu.org/licenses/>.
121+ *
122+ * In addition, as a special exception, the copyright holders give
123+ * permission to link the code of portions of this program with the
124+ * OpenSSL library under certain conditions as described in each
125+ * individual source file, and distribute linked combinations
126+ * including the two.
127+ * You must obey the GNU General Public License in all respects
128+ * for all of the code used other than OpenSSL. If you modify
129+ * file(s) with this exception, you may extend this exception to your
130+ * version of the file(s), but you are not obligated to do so. If you
131+ * do not wish to do so, delete this exception statement from your
132+ * version. If you delete this exception statement from all source
133+ * files in the program, then also delete it here.
134+ */
135+
136+#ifndef CLICK_DEPARTMENT_LOOKUP_H
137+#define CLICK_DEPARTMENT_LOOKUP_H
138+
139+#include "departments.h"
140+#include <string>
141+#include <memory>
142+#include <map>
143+
144+namespace click
145+{
146+
147+class DepartmentLookup
148+{
149+ public:
150+ DepartmentLookup();
151+ void rebuild(const std::list<Department::SPtr>& root_departments);
152+ Department::SPtr get_parent(const std::string& department_id) const;
153+ Department::SPtr get_department_info(const std::string& department_id) const;
154+ int size() const;
155+
156+ private:
157+ void rebuild(const Department::SPtr& dept);
158+ std::map<std::string, Department::SPtr> parent_lut;
159+ std::map<std::string, Department::SPtr> departments;
160+};
161+
162+}
163+
164+#endif
165
166=== added file 'scope/click/departments.cpp'
167--- scope/click/departments.cpp 1970-01-01 00:00:00 +0000
168+++ scope/click/departments.cpp 2014-05-14 20:14:25 +0000
169@@ -0,0 +1,152 @@
170+/*
171+ * Copyright (C) 2014 Canonical Ltd.
172+ *
173+ * This program is free software: you can redistribute it and/or modify it
174+ * under the terms of the GNU General Public License version 3, as published
175+ * by the Free Software Foundation.
176+ *
177+ * This program is distributed in the hope that it will be useful, but
178+ * WITHOUT ANY WARRANTY; without even the implied warranties of
179+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
180+ * PURPOSE. See the GNU General Public License for more details.
181+ *
182+ * You should have received a copy of the GNU General Public License along
183+ * with this program. If not, see <http://www.gnu.org/licenses/>.
184+ *
185+ * In addition, as a special exception, the copyright holders give
186+ * permission to link the code of portions of this program with the
187+ * OpenSSL library under certain conditions as described in each
188+ * individual source file, and distribute linked combinations
189+ * including the two.
190+ * You must obey the GNU General Public License in all respects
191+ * for all of the code used other than OpenSSL. If you modify
192+ * file(s) with this exception, you may extend this exception to your
193+ * version of the file(s), but you are not obligated to do so. If you
194+ * do not wish to do so, delete this exception statement from your
195+ * version. If you delete this exception statement from all source
196+ * files in the program, then also delete it here.
197+ */
198+
199+#include "departments.h"
200+#include <iostream>
201+
202+namespace click
203+{
204+
205+Department::Department(const std::string& id, const std::string& name)
206+ : id_(id),
207+ name_(name),
208+ has_children_flag_(false)
209+{
210+}
211+
212+Department::Department(const std::string& id, const std::string &name, bool has_children)
213+ : id_(id),
214+ name_(name),
215+ has_children_flag_(has_children)
216+{
217+}
218+
219+std::string Department::id() const
220+{
221+ return id_;
222+}
223+
224+std::string Department::name() const
225+{
226+ return name_;
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+std::list<Department::SPtr> Department::from_json_node(const Json::Value& node)
245+{
246+ std::list<Department::SPtr> deps;
247+
248+ for (uint i = 0; i < node.size(); i++)
249+ {
250+ auto const item = node[i];
251+ if (item.isObject() && item.isMember(Department::JsonKeys::name))
252+ {
253+ auto name = item[Department::JsonKeys::name].asString();
254+ const bool has_children = item.isMember(Department::JsonKeys::has_children) ? item[Department::JsonKeys::has_children].asBool() : false;
255+ auto dep = std::make_shared<Department>(name, name, has_children); //FIXME: id
256+ if (item.isObject() && item.isMember(Department::JsonKeys::embedded))
257+ {
258+ auto const emb = item[Department::JsonKeys::embedded];
259+ if (emb.isObject() && emb.isMember(Department::JsonKeys::department))
260+ {
261+ auto const ditem = emb[Department::JsonKeys::department];
262+ auto const subdeps = from_json_node(ditem);
263+ dep->set_subdepartments(subdeps);
264+ }
265+ }
266+ deps.push_back(dep);
267+ }
268+ }
269+
270+ return deps;
271+}
272+
273+std::list<Department::SPtr> Department::from_json_root_node(const Json::Value& root)
274+{
275+ if (root.isObject() && root.isMember(Department::JsonKeys::embedded))
276+ {
277+ auto const emb = root[Department::JsonKeys::embedded];
278+ if (emb.isObject() && emb.isMember(Department::JsonKeys::department))
279+ {
280+ auto const ditem = emb[Department::JsonKeys::department];
281+ return from_json_node(ditem);
282+ }
283+ }
284+
285+ return std::list<Department::SPtr>();
286+}
287+
288+std::list<Department::SPtr> Department::from_json(const std::string& json)
289+{
290+ Json::Reader reader;
291+ Json::Value root;
292+
293+ try
294+ {
295+ if (!reader.parse(json, root)) {
296+ throw std::runtime_error(reader.getFormattedErrorMessages());
297+ }
298+
299+ if (root.isObject() && root.isMember(Department::JsonKeys::embedded))
300+ {
301+ auto const emb = root[Department::JsonKeys::embedded];
302+ if (emb.isObject() && emb.isMember(Department::JsonKeys::department))
303+ {
304+ auto const ditem = emb[Department::JsonKeys::department];
305+ return from_json_node(ditem);
306+ }
307+ }
308+ }
309+ catch (const std::exception& e)
310+ {
311+ std::cerr << "Error parsing departments: " << e.what() << std::endl;
312+ }
313+ catch (...)
314+ {
315+ std::cerr << "Unknown error when parsing departments" << std::endl;
316+ }
317+
318+ return std::list<Department::SPtr>();
319+}
320+
321+}
322
323=== added file 'scope/click/departments.h'
324--- scope/click/departments.h 1970-01-01 00:00:00 +0000
325+++ scope/click/departments.h 2014-05-14 20:14:25 +0000
326@@ -0,0 +1,78 @@
327+/*
328+ * Copyright (C) 2014 Canonical Ltd.
329+ *
330+ * This program is free software: you can redistribute it and/or modify it
331+ * under the terms of the GNU General Public License version 3, as published
332+ * by the Free Software Foundation.
333+ *
334+ * This program is distributed in the hope that it will be useful, but
335+ * WITHOUT ANY WARRANTY; without even the implied warranties of
336+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
337+ * PURPOSE. See the GNU General Public License for more details.
338+ *
339+ * You should have received a copy of the GNU General Public License along
340+ * with this program. If not, see <http://www.gnu.org/licenses/>.
341+ *
342+ * In addition, as a special exception, the copyright holders give
343+ * permission to link the code of portions of this program with the
344+ * OpenSSL library under certain conditions as described in each
345+ * individual source file, and distribute linked combinations
346+ * including the two.
347+ * You must obey the GNU General Public License in all respects
348+ * for all of the code used other than OpenSSL. If you modify
349+ * file(s) with this exception, you may extend this exception to your
350+ * version of the file(s), but you are not obligated to do so. If you
351+ * do not wish to do so, delete this exception statement from your
352+ * version. If you delete this exception statement from all source
353+ * files in the program, then also delete it here.
354+ */
355+
356+#ifndef CLICK_DEPARTMENTS_H
357+#define CLICK_DEPARTMENTS_H
358+
359+#include <string>
360+#include <list>
361+#include <memory>
362+#include <json/json.h>
363+
364+namespace click
365+{
366+
367+class Department
368+{
369+ public:
370+ typedef std::shared_ptr<Department> SPtr;
371+ typedef std::shared_ptr<Department const> SCPtr;
372+
373+ struct JsonKeys
374+ {
375+ JsonKeys() = delete;
376+ constexpr static const char* name {"name"};
377+ constexpr static const char* embedded {"_embedded"};
378+ constexpr static const char* department {"clickindex:department"};
379+ constexpr static const char* has_children {"has_children"};
380+ };
381+
382+ Department(const std::string &id, const std::string &name);
383+ Department(const std::string &id, const std::string &name, bool has_children);
384+ std::string id() const;
385+ std::string name() const;
386+ bool has_children_flag() const;
387+ void set_subdepartments(const std::list<Department::SPtr>& deps);
388+ std::list<Department::SPtr> sub_departments() const;
389+ static std::list<Department::SPtr> from_json(const std::string& json);
390+ static std::list<Department::SPtr> from_json_root_node(const Json::Value& val);
391+
392+ private:
393+ static std::list<Department::SPtr> from_json_node(const Json::Value& val);
394+ std::string id_;
395+ std::string name_;
396+ bool has_children_flag_;
397+ std::list<Department::SPtr> sub_departments_;
398+};
399+
400+typedef std::list<Department::SPtr> DepartmentList;
401+
402+}
403+
404+#endif
405
406=== modified file 'scope/click/index.cpp'
407--- scope/click/index.cpp 2014-05-14 20:14:25 +0000
408+++ scope/click/index.cpp 2014-05-14 20:14:25 +0000
409@@ -87,11 +87,15 @@
410
411 }
412
413-std::string Index::build_index_query(const std::string& query)
414+std::string Index::build_index_query(const std::string& query, const std::string& department)
415 {
416 std::stringstream result;
417
418 result << query;
419+ if (!department.empty()) {
420+ result << ",department:" << department;
421+ }
422+
423 return result.str();
424 }
425
426@@ -109,10 +113,10 @@
427 };
428 }
429
430-click::web::Cancellable Index::search (const std::string& query, std::function<void(click::PackageList)> callback)
431+click::web::Cancellable Index::search (const std::string& query, const std::string& department, std::function<void(click::PackageList, click::DepartmentList)> callback)
432 {
433 click::web::CallParams params;
434- const std::string built_query(build_index_query(query));
435+ const std::string built_query(build_index_query(query, department));
436 params.add(click::QUERY_ARGNAME, built_query.c_str());
437 QSharedPointer<click::web::Response> response(client->call(
438 get_base_url() + click::SEARCH_PATH, "GET", false, build_headers(), "", params));
439@@ -122,22 +126,52 @@
440 Json::Value root;
441
442 click::PackageList pl;
443+ click::DepartmentList depts;
444 if (reader.parse(reply.toUtf8().constData(), root)) {
445 pl = click::package_list_from_json_node(root);
446 qDebug() << "found packages:" << pl.size();
447+ depts = click::Department::from_json_root_node(root);
448 }
449- callback(pl);
450+ callback(pl, depts);
451 });
452 QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/) {
453 qDebug() << "No packages found due to network error";
454 click::PackageList pl;
455+ click::DepartmentList depts; //TODO
456 qDebug() << "calling callback";
457- callback(pl);
458+ callback(pl, depts);
459 qDebug() << " ...Done!";
460 });
461 return click::web::Cancellable(response);
462 }
463
464+click::web::Cancellable Index::bootstrap(std::function<void(const click::DepartmentList&, Error)> callback)
465+{
466+ click::web::CallParams params;
467+ QSharedPointer<click::web::Response> response(client->call(
468+ get_base_url() + click::BOOTSTRAP_PATH, "GET", false, build_headers(), "", params));
469+
470+ QObject::connect(response.data(), &click::web::Response::finished, [=](QString reply) {
471+ qDebug() << "bootstrap request finished";
472+ Json::Reader reader;
473+ Json::Value root;
474+
475+ click::DepartmentList depts;
476+ if (reader.parse(reply.toUtf8().constData(), root)) {
477+ depts = Department::from_json_root_node(root);
478+ // TODO: highlights
479+ }
480+ callback(depts, click::Index::Error::NoError);
481+ });
482+ QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/) {
483+ qWarning() << "bootstrap call failed due to network error";
484+ const click::DepartmentList depts;
485+ qDebug() << "bootstrap: calling callback";
486+ callback(depts, click::Index::Error::NetworkError);
487+ });
488+ return click::web::Cancellable(response);
489+}
490+
491 click::web::Cancellable Index::get_details (const std::string& package_name, std::function<void(PackageDetails, click::Index::Error)> callback)
492 {
493 QSharedPointer<click::web::Response> response = client->call
494
495=== modified file 'scope/click/index.h'
496--- scope/click/index.h 2014-05-14 20:14:25 +0000
497+++ scope/click/index.h 2014-05-14 20:14:25 +0000
498@@ -37,6 +37,7 @@
499 #include "configuration.h"
500 #include "package.h"
501 #include "webclient.h"
502+#include "departments.h"
503
504
505 namespace click {
506@@ -46,6 +47,7 @@
507 const std::string SEARCH_BASE_URL_ENVVAR = "U1_SEARCH_BASE_URL";
508 const std::string SEARCH_BASE_URL = "https://search.apps.ubuntu.com/";
509 const std::string SEARCH_PATH = "api/v1/search";
510+const std::string BOOTSTRAP_PATH = "api/v1/departments";
511 const std::string SUPPORTED_FRAMEWORKS = "framework:ubuntu-sdk-13.10";
512 const std::string QUERY_ARGNAME = "q";
513 const std::string ARCHITECTURE = "architecture:";
514@@ -63,15 +65,16 @@
515 protected:
516 QSharedPointer<web::Client> client;
517 QSharedPointer<Configuration> configuration;
518- virtual std::string build_index_query(const std::string& query);
519+ virtual std::string build_index_query(const std::string& query, const std::string& department);
520 virtual std::map<std::string, std::string> build_headers();
521
522 public:
523 enum class Error {NoError, CredentialsError, NetworkError};
524 Index(const QSharedPointer<click::web::Client>& client,
525 const QSharedPointer<Configuration> configuration=QSharedPointer<Configuration>(new Configuration()));
526- virtual click::web::Cancellable search (const std::string& query, std::function<void(PackageList)> callback);
527+ virtual click::web::Cancellable search (const std::string& query, const std::string& department, std::function<void(PackageList, DepartmentList)> callback);
528 virtual click::web::Cancellable get_details(const std::string& package_name, std::function<void(PackageDetails, Error)> callback);
529+ virtual click::web::Cancellable bootstrap(std::function<void(const DepartmentList&, Error)> callback);
530 virtual ~Index();
531
532 static std::string get_base_url ();
533
534=== modified file 'scope/click/query.cpp'
535--- scope/click/query.cpp 2014-05-14 20:14:25 +0000
536+++ scope/click/query.cpp 2014-05-14 20:14:25 +0000
537@@ -37,6 +37,7 @@
538 #include <unity/scopes/Annotation.h>
539 #include <unity/scopes/CategoryRenderer.h>
540 #include <unity/scopes/CategorisedResult.h>
541+#include <unity/scopes/Department.h>
542 #include <unity/scopes/CannedQuery.h>
543 #include <unity/scopes/SearchReply.h>
544 #include <unity/scopes/SearchMetadata.h>
545@@ -117,20 +118,22 @@
546
547 struct click::Query::Private
548 {
549- Private(const unity::scopes::CannedQuery& query, click::Index& index, const scopes::SearchMetadata& metadata)
550+ Private(const unity::scopes::CannedQuery& query, click::Index& index, click::DepartmentLookup& depts, const scopes::SearchMetadata& metadata)
551 : query(query),
552 index(index),
553+ department_lookup(depts),
554 meta(metadata)
555 {
556 }
557 unity::scopes::CannedQuery query;
558 click::Index& index;
559+ click::DepartmentLookup& department_lookup;
560 scopes::SearchMetadata meta;
561 click::web::Cancellable search_operation;
562 };
563
564-click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata)
565- : impl(new Private(query, index, metadata))
566+click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, click::DepartmentLookup& depts, scopes::SearchMetadata const& metadata)
567+ : impl(new Private(query, index, depts, metadata))
568 {
569 }
570
571@@ -183,6 +186,57 @@
572 });
573 }
574
575+unity::scopes::DepartmentList click::Query::populate_departments(const click::DepartmentList& depts, const std::string& current_dep_id)
576+{
577+ unity::scopes::DepartmentList departments;
578+
579+ // create a list of subdepartments of current department
580+ foreach (auto d, depts)
581+ {
582+ unity::scopes::Department department(d->id(), impl->query, d->name());
583+ if (d->has_children_flag())
584+ {
585+ department.set_has_subdepartments();
586+ }
587+ departments.push_back(department);
588+ }
589+
590+ if (current_dep_id != "")
591+ {
592+ auto curr_dpt = impl->department_lookup.get_department_info(current_dep_id);
593+ if (curr_dpt != nullptr)
594+ {
595+ unity::scopes::Department cur(current_dep_id, impl->query, curr_dpt->name());
596+ if (departments.size() > 0) // this may be a leaf department
597+ {
598+ cur.set_subdepartments(departments);
599+ }
600+
601+ auto parent_info = impl->department_lookup.get_parent(current_dep_id);
602+ if (parent_info != nullptr)
603+ {
604+ unity::scopes::Department parent_dept(parent_info->id(), impl->query, parent_info->name());
605+ parent_dept.set_subdepartments({cur});
606+ return {parent_dept};
607+ }
608+ else
609+ {
610+ unity::scopes::Department root_dept("", impl->query, _("All departments"));
611+ root_dept.set_subdepartments({cur});
612+ return {root_dept};
613+ }
614+ }
615+ else
616+ {
617+ qWarning() << "Unknown department:" << QString::fromStdString(current_dep_id);
618+ }
619+ }
620+
621+ unity::scopes::Department root_dept("", impl->query, _("All departments"));
622+ root_dept.set_subdepartments(departments);
623+ return unity::scopes::DepartmentList({root_dept});
624+}
625+
626 void click::Query::add_available_apps(scopes::SearchReplyProxy const& searchReply,
627 const std::set<std::string>& locallyInstalledApps,
628 const std::string& categoryTemplate)
629@@ -195,11 +249,20 @@
630 return;
631 }
632
633+ assert(searchReply);
634+
635 run_under_qt([=]()
636 {
637- auto search_cb = [this, searchReply, category, locallyInstalledApps](PackageList packages) {
638+ auto search_cb = [this, searchReply, category, locallyInstalledApps](PackageList packages, DepartmentList depts) {
639 qDebug("search callback");
640
641+ // handle departments data
642+ auto click_depts = populate_departments(depts, impl->query.department_id());
643+ if (click_depts.size() > 0)
644+ {
645+ searchReply->register_departments(click_depts, impl->query.department_id());
646+ }
647+
648 // handle packages data
649 foreach (auto p, packages) {
650 qDebug() << "pushing result" << QString::fromStdString(p.name);
651@@ -226,8 +289,29 @@
652 this->finished(searchReply);
653 };
654
655+ if (impl->department_lookup.size() == 0)
656+ {
657+ qDebug() << "performing bootstrap request";
658+ impl->search_operation = impl->index.bootstrap([this, search_cb, searchReply](const DepartmentList& deps, click::Index::Error error) {
659+ if (error == click::Index::Error::NoError)
660+ {
661+ qDebug() << "bootstrap request completed";
662+ impl->department_lookup.rebuild(deps);
663+ qDebug() << "Total number of departments:" << impl->department_lookup.size();
664+ }
665+ else
666+ {
667+ qWarning() << "bootstrap request failed";
668+ }
669+ qDebug() << "starting search of" << QString::fromStdString(impl->query.query_string());
670+ impl->search_operation = impl->index.search(impl->query.query_string(), impl->query.department_id(), search_cb);
671+ });
672+ }
673+ else
674+ {
675 qDebug() << "starting search of" << QString::fromStdString(impl->query.query_string());
676- impl->search_operation = impl->index.search(impl->query.query_string(), search_cb);
677+ impl->search_operation = impl->index.search(impl->query.query_string(), impl->query.department_id(), search_cb);
678+ }
679 });
680 }
681
682
683=== modified file 'scope/click/query.h'
684--- scope/click/query.h 2014-05-14 20:14:25 +0000
685+++ scope/click/query.h 2014-05-14 20:14:25 +0000
686@@ -32,18 +32,21 @@
687
688
689 #include <unity/scopes/SearchQueryBase.h>
690+#include <unity/scopes/Department.h>
691
692 namespace scopes = unity::scopes;
693
694 #include <QSharedPointer>
695 #include <set>
696
697+#include "department-lookup.h"
698
699 namespace click
700 {
701
702 class Application;
703 class Index;
704+class DepartmentLookup;
705
706 class Query : public scopes::SearchQueryBase
707 {
708@@ -70,7 +73,7 @@
709 constexpr static const char* VERSION{"version"};
710 };
711
712- Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata);
713+ Query(unity::scopes::CannedQuery const& query, click::Index& index, click::DepartmentLookup& dept_lookup, scopes::SearchMetadata const& metadata);
714 virtual ~Query();
715
716 virtual void cancelled() override;
717@@ -78,6 +81,7 @@
718 virtual void run(scopes::SearchReplyProxy const& reply) override;
719
720 protected:
721+ virtual unity::scopes::DepartmentList populate_departments(const click::DepartmentList& depts, const std::string& current_department_id);
722 virtual void add_available_apps(const scopes::SearchReplyProxy &searchReply, const std::set<std::string> &locallyInstalledApps, const std::string &category);
723 virtual bool push_result(const scopes::SearchReplyProxy &searchReply, scopes::CategorisedResult const& res);
724 virtual void finished(const scopes::SearchReplyProxy &searchReply);
725
726=== modified file 'scope/click/scope.cpp'
727--- scope/click/scope.cpp 2014-05-14 20:14:25 +0000
728+++ scope/click/scope.cpp 2014-05-14 20:14:25 +0000
729@@ -33,6 +33,7 @@
730 #include "preview.h"
731 #include "network_access_manager.h"
732 #include "interface.h"
733+#include "department-lookup.h"
734 #include "scope_activation.h"
735
736 #include <QSharedPointer>
737@@ -55,6 +56,7 @@
738 nam.reset(new click::network::AccessManager());
739 client.reset(new click::web::Client(nam));
740 index.reset(new click::Index(client));
741+ depts.reset(new click::DepartmentLookup());
742 }
743
744 click::Scope::~Scope()
745@@ -88,7 +90,7 @@
746
747 scopes::SearchQueryBase::UPtr click::Scope::search(unity::scopes::CannedQuery const& q, scopes::SearchMetadata const& metadata)
748 {
749- return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, metadata));
750+ return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, *depts, metadata));
751 }
752
753
754
755=== modified file 'scope/click/scope.h'
756--- scope/click/scope.h 2014-04-29 03:17:38 +0000
757+++ scope/click/scope.h 2014-05-14 20:14:25 +0000
758@@ -30,6 +30,7 @@
759 #ifndef CLICK_SCOPE_H
760 #define CLICK_SCOPE_H
761
762+#include <memory>
763 #include <unity/scopes/ScopeBase.h>
764 #include <unity/scopes/QueryBase.h>
765 #include <unity/scopes/ActivationQueryBase.h>
766@@ -42,6 +43,9 @@
767
768 namespace click
769 {
770+
771+class DepartmentLookup;
772+
773 class Scope : public scopes::ScopeBase
774 {
775 public:
776@@ -63,6 +67,7 @@
777 QSharedPointer<click::network::AccessManager> nam;
778 QSharedPointer<click::web::Client> client;
779 QSharedPointer<click::Index> index;
780+ std::shared_ptr<click::DepartmentLookup> depts;
781
782 std::string installApplication(unity::scopes::Result const& result);
783 };
784
785=== modified file 'scope/tests/CMakeLists.txt'
786--- scope/tests/CMakeLists.txt 2014-05-13 19:32:29 +0000
787+++ scope/tests/CMakeLists.txt 2014-05-14 20:14:25 +0000
788@@ -35,6 +35,7 @@
789 test_reviews.cpp
790 test_smartconnect.cpp
791 test_webclient.cpp
792+ test_departments.cpp
793
794 ${CMAKE_CURRENT_BINARY_DIR}/test_data.cpp
795 )
796@@ -68,4 +69,4 @@
797
798 add_subdirectory(integration)
799 add_subdirectory(download_manager_tool)
800-add_subdirectory(click_interface_tool)
801\ No newline at end of file
802+add_subdirectory(click_interface_tool)
803
804=== modified file 'scope/tests/fake_json.h'
805--- scope/tests/fake_json.h 2014-05-14 20:14:25 +0000
806+++ scope/tests/fake_json.h 2014-05-14 20:14:25 +0000
807@@ -142,6 +142,102 @@
808 }
809 )foo";
810
811+const std::string FAKE_JSON_DEPARTMENTS_ONLY = R"(
812+ {
813+ "_links": {
814+ "self": {
815+ "href": "https://search.apps.ubuntu.com/api/v1/departments"
816+ },
817+ "curies": [
818+ {
819+ "name": "clickindex",
820+ "href": "https://search.apps.ubuntu.com/docs/v1/relations.html{#rel}",
821+ "templated": true
822+ }
823+ ]
824+ },
825+ "_embedded": {
826+ "clickindex:department": [
827+ {
828+ "name": "Games",
829+ "_links": {
830+ "self": {
831+ "href": "https://search.apps.ubuntu.com/api/v1/departments/Games"
832+ }
833+ },
834+ "_embedded": {
835+ "clickindex:department": [
836+ {
837+ "name": "Board Games",
838+ "_links": {
839+ "self": {
840+ "href": "https://search.apps.ubuntu.com/api/v1/departments/Games/Board+Games"
841+ }
842+ }
843+ }
844+ ]
845+ }
846+ },
847+ {
848+ "name": "Graphics",
849+ "_links": {
850+ "self": {
851+ "href": "https://search.apps.ubuntu.com/api/v1/departments/Graphics"
852+ }
853+ },
854+ "_embedded": {
855+ "clickindex:department": [
856+ {
857+ "name": "Drawing",
858+ "_links": {
859+ "self": {
860+ "href": "https://search.apps.ubuntu.com/api/v1/departments/Graphics/Drawing"
861+ }
862+ }
863+ }
864+ ]
865+ }
866+ },
867+ {
868+ "name": "Internet",
869+ "_links": {
870+ "self": {
871+ "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet"
872+ }
873+ },
874+ "_embedded": {
875+ "clickindex:department": [
876+ {
877+ "name": "Chat",
878+ "_links": {
879+ "self": {
880+ "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Chat"
881+ }
882+ }
883+ },
884+ {
885+ "name": "Mail",
886+ "_links": {
887+ "self": {
888+ "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Mail"
889+ }
890+ }
891+ },
892+ {
893+ "name": "Web Browsers",
894+ "_links": {
895+ "self": {
896+ "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Web+Browsers"
897+ }
898+ }
899+ }
900+ ]
901+ }
902+ }
903+ ]
904+ }
905+})";
906+
907 const std::string FAKE_JSON_MANIFEST_REMOVABLE = R"foo(
908 {
909 "_removable": 1,
910
911=== modified file 'scope/tests/integration/webclient_integration.cpp'
912--- scope/tests/integration/webclient_integration.cpp 2014-04-29 03:17:38 +0000
913+++ scope/tests/integration/webclient_integration.cpp 2014-05-14 20:14:25 +0000
914@@ -30,6 +30,7 @@
915 #include <click/network_access_manager.h>
916 #include <click/webclient.h>
917 #include <click/index.h>
918+#include <click/departments.h>
919
920 #include <QCoreApplication>
921 #include <QDebug>
922@@ -102,7 +103,8 @@
923 new click::web::Client(namPtr));
924 click::Index index(clientPtr);
925 click::PackageList packages;
926- index.search("qr,architecture:armhf", [&, this](click::PackageList found_packages){
927+ index.search("qr,architecture:armhf", "", [&, this](click::PackageList found_packages, click::DepartmentList){
928+ //TODO departments
929 packages = found_packages;
930 Quit();
931 });
932
933=== modified file 'scope/tests/mock_webclient.h'
934--- scope/tests/mock_webclient.h 2014-04-29 03:17:38 +0000
935+++ scope/tests/mock_webclient.h 2014-05-14 20:14:25 +0000
936@@ -86,7 +86,7 @@
937 const click::web::CallParams& params));
938 QSharedPointer<click::web::Response> call(
939 const std::string& iri,
940- const click::web::CallParams& params=click::web::CallParams()) {
941+ const click::web::CallParams& params=click::web::CallParams()) override {
942 return callImpl(iri, "GET", false,
943 std::map<std::string, std::string>(), "", params);
944 }
945@@ -96,7 +96,7 @@
946 bool sign = false,
947 const std::map<std::string, std::string>& headers = std::map<std::string, std::string>(),
948 const std::string& data = "",
949- const click::web::CallParams& params=click::web::CallParams()) {
950+ const click::web::CallParams& params=click::web::CallParams()) override {
951 return callImpl(iri, method, sign, headers, data, params);
952 }
953 };
954
955=== removed file 'scope/tests/test_data.cpp'
956=== added file 'scope/tests/test_departments.cpp'
957--- scope/tests/test_departments.cpp 1970-01-01 00:00:00 +0000
958+++ scope/tests/test_departments.cpp 2014-05-14 20:14:25 +0000
959@@ -0,0 +1,108 @@
960+/*
961+ * Copyright (C) 2014 Canonical Ltd.
962+ *
963+ * This program is free software: you can redistribute it and/or modify it
964+ * under the terms of the GNU General Public License version 3, as published
965+ * by the Free Software Foundation.
966+ *
967+ * This program is distributed in the hope that it will be useful, but
968+ * WITHOUT ANY WARRANTY; without even the implied warranties of
969+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
970+ * PURPOSE. See the GNU General Public License for more details.
971+ *
972+ * You should have received a copy of the GNU General Public License along
973+ * with this program. If not, see <http://www.gnu.org/licenses/>.
974+ *
975+ * In addition, as a special exception, the copyright holders give
976+ * permission to link the code of portions of this program with the
977+ * OpenSSL library under certain conditions as described in each
978+ * individual source file, and distribute linked combinations
979+ * including the two.
980+ * You must obey the GNU General Public License in all respects
981+ * for all of the code used other than OpenSSL. If you modify
982+ * file(s) with this exception, you may extend this exception to your
983+ * version of the file(s), but you are not obligated to do so. If you
984+ * do not wish to do so, delete this exception statement from your
985+ * version. If you delete this exception statement from all source
986+ * files in the program, then also delete it here.
987+ */
988+
989+#include <gtest/gtest.h>
990+#include "fake_json.h"
991+#include "click/departments.h"
992+#include "click/department-lookup.h"
993+
994+class DepartmentsTest : public ::testing::Test
995+{
996+ protected:
997+ void SetUp() override
998+ {
999+ }
1000+};
1001+
1002+TEST_F(DepartmentsTest, testParsing)
1003+{
1004+ const std::string jsonstr(FAKE_JSON_DEPARTMENTS_ONLY);
1005+ auto depts = click::Department::from_json(jsonstr);
1006+ EXPECT_EQ(3u, depts.size());
1007+ auto it = depts.cbegin();
1008+ {
1009+ auto dep = *it;
1010+ EXPECT_EQ("Games", dep->id());
1011+ EXPECT_EQ("Games", dep->name());
1012+ EXPECT_FALSE(dep->has_children_flag());
1013+ auto subdepts = dep->sub_departments();
1014+ EXPECT_EQ(1u, subdepts.size());
1015+ auto sit = subdepts.cbegin();
1016+ EXPECT_EQ("Board Games", (*sit)->name());
1017+ }
1018+ {
1019+ ++it;
1020+ auto dep = *it;
1021+ EXPECT_EQ("Graphics", dep->id());
1022+ EXPECT_EQ("Graphics", dep->name());
1023+ EXPECT_FALSE(dep->has_children_flag());
1024+ auto subdepts = dep->sub_departments();
1025+ EXPECT_EQ(1u, subdepts.size());
1026+ auto sit = subdepts.cbegin();
1027+ EXPECT_EQ("Drawing", (*sit)->name());
1028+ }
1029+ {
1030+ ++it;
1031+ auto dep = *it;
1032+ EXPECT_EQ("Internet", dep->id());
1033+ EXPECT_EQ("Internet", dep->name());
1034+ EXPECT_FALSE(dep->has_children_flag());
1035+ auto subdepts = dep->sub_departments();
1036+ EXPECT_EQ(3u, subdepts.size());
1037+ auto sit = subdepts.cbegin();
1038+ auto subdep = *sit;
1039+ EXPECT_EQ("Chat", subdep->name());
1040+ subdep = *(++sit);
1041+ EXPECT_EQ("Mail", subdep->name());
1042+ subdep = *(++sit);
1043+ EXPECT_EQ("Web Browsers", subdep->name());
1044+ }
1045+}
1046+
1047+TEST_F(DepartmentsTest, testLookup)
1048+{
1049+ auto dep_games = std::make_shared<click::Department>("games", "Games");
1050+ auto dep_rpg = std::make_shared<click::Department>("rpg", "RPG");
1051+ auto dep_strategy = std::make_shared<click::Department>("strategy", "Strategy");
1052+ const std::list<click::Department::SPtr> departments {dep_rpg, dep_strategy};
1053+ dep_games->set_subdepartments(departments);
1054+
1055+ const std::list<click::Department::SPtr> root {dep_games};
1056+ click::DepartmentLookup lut;
1057+ lut.rebuild(root);
1058+
1059+ EXPECT_EQ(2u, lut.size());
1060+ EXPECT_EQ("games", lut.get_parent("strategy")->id());
1061+ EXPECT_EQ("games", lut.get_parent("rpg")->id());
1062+ EXPECT_EQ(nullptr, lut.get_parent("games"));
1063+
1064+ lut.rebuild(root);
1065+ EXPECT_EQ(2u, lut.size());
1066+}
1067+
1068
1069=== modified file 'scope/tests/test_index.cpp'
1070--- scope/tests/test_index.cpp 2014-05-14 20:14:25 +0000
1071+++ scope/tests/test_index.cpp 2014-05-14 20:14:25 +0000
1072@@ -51,8 +51,8 @@
1073 click::Index(client, configuration)
1074 {
1075 }
1076- MOCK_METHOD1(build_index_query, std::string(const std::string&));
1077 MOCK_METHOD0(build_headers, std::map<std::string, std::string>());
1078+ MOCK_METHOD2(build_index_query, std::string(const std::string&, const std::string&));
1079 };
1080
1081 class MockConfiguration : public click::Configuration {
1082@@ -99,7 +99,7 @@
1083 .Times(1)
1084 .WillOnce(Return(response));
1085
1086- indexPtr->search("", [](click::PackageList) {});
1087+ indexPtr->search("", "", [](click::PackageList, click::DepartmentList) {});
1088 }
1089
1090 TEST_F(IndexTest, testSearchSendsBuiltQueryAsParam)
1091@@ -115,11 +115,11 @@
1092 .Times(1)
1093 .WillOnce(Return(response));
1094
1095- EXPECT_CALL(*indexPtr, build_index_query(FAKE_QUERY))
1096+ EXPECT_CALL(*indexPtr, build_index_query(FAKE_QUERY, ""))
1097 .Times(1)
1098 .WillOnce(Return(FAKE_BUILT_QUERY));
1099
1100- indexPtr->search(FAKE_QUERY, [](click::PackageList) {});
1101+ indexPtr->search(FAKE_QUERY, "", [](click::PackageList, click::DepartmentList) {});
1102 }
1103
1104 TEST_F(IndexTest, testSearchSendsRightPath)
1105@@ -132,7 +132,7 @@
1106 .Times(1)
1107 .WillOnce(Return(response));
1108
1109- indexPtr->search("", [](click::PackageList) {});
1110+ indexPtr->search("", "", [](click::PackageList, click::DepartmentList) {});
1111 }
1112
1113 TEST_F(IndexTest, testSearchCallbackIsCalled)
1114@@ -149,7 +149,7 @@
1115 .WillOnce(Return(response));
1116 EXPECT_CALL(*this, search_callback(_)).Times(1);
1117
1118- indexPtr->search("", [this](click::PackageList packages){
1119+ indexPtr->search("", "", [this](click::PackageList packages, click::DepartmentList){
1120 search_callback(packages);
1121 });
1122 response->replyFinished();
1123@@ -170,7 +170,7 @@
1124 click::PackageList empty_package_list;
1125 EXPECT_CALL(*this, search_callback(empty_package_list)).Times(1);
1126
1127- indexPtr->search("", [this](click::PackageList packages){
1128+ indexPtr->search("", "", [this](click::PackageList packages, click::DepartmentList){
1129 search_callback(packages);
1130 });
1131 response->replyFinished();
1132@@ -199,7 +199,7 @@
1133 };
1134 EXPECT_CALL(*this, search_callback(single_package_list)).Times(1);
1135
1136- indexPtr->search("", [this](click::PackageList packages){
1137+ indexPtr->search("", "", [this](click::PackageList packages, click::DepartmentList){
1138 search_callback(packages);
1139 });
1140 response->replyFinished();
1141@@ -214,7 +214,7 @@
1142 .Times(1)
1143 .WillOnce(Return(response));
1144
1145- auto search_operation = indexPtr->search("", [](click::PackageList) {});
1146+ auto search_operation = indexPtr->search("", "", [](click::PackageList, click::DepartmentList) {});
1147 EXPECT_CALL(reply.instance, abort()).Times(1);
1148 search_operation.cancel();
1149 }
1150@@ -233,7 +233,7 @@
1151 .Times(1)
1152 .WillOnce(Return(response));
1153 EXPECT_CALL(reply.instance, errorString()).Times(1).WillOnce(Return("fake error"));
1154- indexPtr->search("", [this](click::PackageList packages){
1155+ indexPtr->search("", "", [this](click::PackageList packages, click::DepartmentList){
1156 search_callback(packages);
1157 });
1158
1159
1160=== modified file 'scope/tests/test_query.cpp'
1161--- scope/tests/test_query.cpp 2014-05-14 20:14:25 +0000
1162+++ scope/tests/test_query.cpp 2014-05-14 20:14:25 +0000
1163@@ -45,6 +45,7 @@
1164 #include <unity/scopes/CannedQuery.h>
1165 #include <unity/scopes/ScopeBase.h>
1166 #include <unity/scopes/SearchReply.h>
1167+#include <unity/scopes/testing/MockSearchReply.h>
1168
1169 using namespace ::testing;
1170
1171@@ -56,30 +57,43 @@
1172
1173 class MockIndex : public click::Index {
1174 click::PackageList packages;
1175+ click::DepartmentList departments;
1176+ click::DepartmentList bootstrap_departments;
1177 public:
1178- MockIndex(click::PackageList packages = click::PackageList())
1179+ MockIndex(click::PackageList packages = click::PackageList(),
1180+ click::DepartmentList departments = click::DepartmentList(),
1181+ click::DepartmentList boot_departments = click::DepartmentList())
1182 : Index(QSharedPointer<click::web::Client>()),
1183- packages(packages)
1184- {
1185-
1186- }
1187-
1188- click::web::Cancellable search(const std::string &query, std::function<void (click::PackageList)> callback) override
1189- {
1190- do_search(query, callback);
1191- callback(packages);
1192- return click::web::Cancellable();
1193- }
1194-
1195- MOCK_METHOD2(do_search,
1196- void(const std::string&,
1197- std::function<void(click::PackageList)>));
1198+ packages(packages),
1199+ departments(departments),
1200+ bootstrap_departments(boot_departments)
1201+ {
1202+
1203+ }
1204+
1205+ click::web::Cancellable search(const std::string &query, const std::string& department, std::function<void (click::PackageList, click::DepartmentList)> callback) override
1206+ {
1207+ do_search(query, department, callback);
1208+ callback(packages, departments);
1209+ return click::web::Cancellable();
1210+ }
1211+
1212+ click::web::Cancellable bootstrap(std::function<void(const click::DepartmentList&, Error)> callback) override
1213+ {
1214+ callback(bootstrap_departments, click::Index::Error::NoError);
1215+ return click::web::Cancellable();
1216+ }
1217+
1218+ MOCK_METHOD3(do_search,
1219+ void(const std::string&, const std::string&,
1220+ std::function<void(click::PackageList, click::DepartmentList)>));
1221 };
1222
1223 class MockQueryBase : public click::Query {
1224 public:
1225 MockQueryBase(const unity::scopes::CannedQuery& query, click::Index& index,
1226- scopes::SearchMetadata const& metadata) : click::Query(query, index, metadata)
1227+ click::DepartmentLookup& depts,
1228+ scopes::SearchMetadata const& metadata) : click::Query(query, index, depts, metadata)
1229 {
1230
1231 }
1232@@ -93,7 +107,8 @@
1233 class MockQuery : public MockQueryBase {
1234 public:
1235 MockQuery(const unity::scopes::CannedQuery& query, click::Index& index,
1236- scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, metadata)
1237+ click::DepartmentLookup& depts,
1238+ scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, metadata)
1239 {
1240
1241 }
1242@@ -115,7 +130,8 @@
1243 class MockQueryRun : public MockQueryBase {
1244 public:
1245 MockQueryRun(const unity::scopes::CannedQuery& query, click::Index& index,
1246- scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, metadata)
1247+ click::DepartmentLookup& depts,
1248+ scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, metadata)
1249 {
1250
1251 }
1252@@ -143,12 +159,16 @@
1253 TEST(QueryTest, testAddAvailableAppsCallsClickIndex)
1254 {
1255 MockIndex mock_index;
1256+ click::DepartmentLookup dept_lookup;
1257 scopes::SearchMetadata metadata("en_EN", "phone");
1258 std::set<std::string> no_installed_packages;
1259 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
1260- MockQuery q(query, mock_index, metadata);
1261- EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(1);
1262- scopes::SearchReplyProxy reply;
1263+ MockQuery q(query, mock_index, dept_lookup, metadata);
1264+ EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _)).Times(1);
1265+
1266+ scopes::testing::MockSearchReply mock_reply;
1267+ scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
1268+ EXPECT_CALL(mock_reply, register_departments(_, _)).Times(1);
1269
1270 scopes::CategoryRenderer renderer("{}");
1271 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
1272@@ -162,17 +182,21 @@
1273 {"name", "title", 0.0, "", ""}
1274 };
1275 MockIndex mock_index(packages);
1276+ click::DepartmentLookup dept_lookup;
1277 scopes::SearchMetadata metadata("en_EN", "phone");
1278 std::set<std::string> no_installed_packages;
1279 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
1280- MockQuery q(query, mock_index, metadata);
1281- EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
1282+ MockQuery q(query, mock_index, dept_lookup, metadata);
1283+ EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _));
1284
1285 scopes::CategoryRenderer renderer("{}");
1286 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
1287 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
1288
1289- scopes::SearchReplyProxy reply;
1290+ scopes::testing::MockSearchReply mock_reply;
1291+ scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
1292+ EXPECT_CALL(mock_reply, register_departments(_, _)).Times(1);
1293+
1294 auto expected_title = packages.front().title;
1295 EXPECT_CALL(q, push_result(_, Property(&scopes::CategorisedResult::title, expected_title)));
1296 q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE);
1297@@ -184,17 +208,20 @@
1298 {"name", "title", 0.0, "", ""}
1299 };
1300 MockIndex mock_index(packages);
1301+ click::DepartmentLookup dept_lookup;
1302 scopes::SearchMetadata metadata("en_EN", "phone");
1303 std::set<std::string> no_installed_packages;
1304 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
1305- MockQuery q(query, mock_index, metadata);
1306- EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
1307+ MockQuery q(query, mock_index, dept_lookup, metadata);
1308+ EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _));
1309
1310 scopes::CategoryRenderer renderer("{}");
1311 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
1312 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
1313
1314- scopes::SearchReplyProxy reply;
1315+ scopes::testing::MockSearchReply mock_reply;
1316+ scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
1317+ EXPECT_CALL(mock_reply, register_departments(_, _)).Times(1);
1318 EXPECT_CALL(q, finished(_));
1319 q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE);
1320 }
1321@@ -205,11 +232,12 @@
1322 {"name", "title", 0.0, "", ""}
1323 };
1324 MockIndex mock_index(packages);
1325+ click::DepartmentLookup dept_lookup;
1326 scopes::SearchMetadata metadata("en_EN", "phone");
1327 std::set<std::string> no_installed_packages;
1328 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
1329- MockQuery q(query, mock_index, metadata);
1330- EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(0);
1331+ MockQuery q(query, mock_index, dept_lookup, metadata);
1332+ EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _)).Times(0);
1333
1334 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(nullptr));
1335
1336@@ -224,10 +252,11 @@
1337 {"name", "title", 0.0, "", ""}
1338 };
1339 MockIndex mock_index(packages);
1340+ click::DepartmentLookup dept_lookup;
1341 scopes::SearchMetadata metadata("en_EN", "phone");
1342 std::set<std::string> no_installed_packages;
1343 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
1344- MockQueryRun q(query, mock_index, metadata);
1345+ MockQueryRun q(query, mock_index, dept_lookup, metadata);
1346 auto reply = scopes::SearchReplyProxy();
1347 EXPECT_CALL(q, push_local_results(_, _, _));
1348 EXPECT_CALL(q, add_available_apps(reply, no_installed_packages, _));
1349@@ -244,19 +273,23 @@
1350 {"org.example.app2", "app title2", 0.0, "", ""}
1351 };
1352 MockIndex mock_index(packages);
1353+ click::DepartmentLookup dept_lookup;
1354 scopes::SearchMetadata metadata("en_EN", "phone");
1355 std::set<std::string> one_installed_package {
1356 "org.example.app2"
1357 };
1358 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
1359- MockQuery q(query, mock_index, metadata);
1360- EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
1361+ MockQuery q(query, mock_index, dept_lookup, metadata);
1362+ EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _));
1363
1364 scopes::CategoryRenderer renderer("{}");
1365 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
1366 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
1367
1368- scopes::SearchReplyProxy reply;
1369+ scopes::testing::MockSearchReply mock_reply;
1370+ scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
1371+ EXPECT_CALL(mock_reply, register_departments(_, _)).Times(1);
1372+
1373 auto expected_name = packages.front().name;
1374 EXPECT_CALL(q, push_result(_, HasPackageName(expected_name)));
1375 q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE);

Subscribers

People subscribed via source and target branches

to all changes: