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

Proposed by Paweł Stołowski
Status: Superseded
Proposed branch: lp:~stolowski/unity-scope-click/departments
Merge into: lp:unity-scope-click/devel
Diff against target: 2394 lines (+1473/-114) (has conflicts)
33 files modified
CMakeLists.txt (+1/-1)
debian/control (+1/-1)
libclickscope/click/CMakeLists.txt (+3/-0)
libclickscope/click/department-lookup.cpp (+84/-0)
libclickscope/click/department-lookup.h (+58/-0)
libclickscope/click/departments.cpp (+164/-0)
libclickscope/click/departments.h (+83/-0)
libclickscope/click/highlights.cpp (+95/-0)
libclickscope/click/highlights.h (+72/-0)
libclickscope/click/index.cpp (+70/-5)
libclickscope/click/index.h (+7/-2)
libclickscope/click/package.h (+1/-0)
libclickscope/click/preview.cpp (+1/-0)
libclickscope/click/scope_activation.cpp (+11/-5)
libclickscope/click/scope_activation.h (+2/-2)
libclickscope/click/webclient.cpp (+2/-1)
libclickscope/click/webclient.h (+1/-1)
libclickscope/tests/CMakeLists.txt (+2/-0)
libclickscope/tests/fake_json.h (+236/-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 (+108/-0)
libclickscope/tests/test_index.cpp (+10/-10)
scope/clickapps/apps-query.cpp (+11/-12)
scope/clickapps/apps-scope.cpp (+5/-6)
scope/clickapps/apps-scope.h (+3/-3)
scope/clickstore/store-query.cpp (+233/-16)
scope/clickstore/store-query.h (+16/-3)
scope/clickstore/store-scope.cpp (+25/-5)
scope/clickstore/store-scope.h (+12/-2)
scope/tests/integration/webclient_integration.cpp (+3/-1)
scope/tests/test_query.cpp (+77/-36)
Text conflict in scope/clickstore/store-scope.cpp
To merge this branch: bzr merge lp:~stolowski/unity-scope-click/departments
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
dobey (community) Needs Fixing
Review via email: mp+219211@code.launchpad.net

This proposal has been superseded by a proposal from 2014-06-18.

Commit message

Add support for departments and highlights.

Description of the change

Add support for departments and highlights.

To post a comment you must log in.
Revision history for this message
dobey (dobey) wrote :

426 +std::map<std::string, std::string> Index::build_headers(const std::string& language)
438 + {"Accept-Language", language},
486 + QSharedPointer<click::web::Response> response(client->call(
487 + get_base_url() + click::BOOTSTRAP_PATH, "GET", false, build_headers("en"), "", params)); //TODO: language

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

review: Needs Fixing
Revision history for this message
dobey (dobey) wrote :

Can you also add a commit with --fixes=lp:1209224 to link that bug?

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
dobey (dobey) wrote :
review: Needs Fixing
255. By Paweł Stołowski

Forgot about highlights.

256. By Paweł Stołowski

Merged 0.5.0 update branch.

257. By Paweł Stołowski

Merged devel.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
258. By Paweł Stołowski

Reuse code between bootstrap and departments call.

259. By Paweł Stołowski

Cleanups. Check department href in tests.

260. By Paweł Stołowski

Test get_department_info().

261. By Paweł Stołowski

Added tests for broken departments json.

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2014-05-27 13:15:52 +0000
+++ CMakeLists.txt 2014-06-18 18:08:01 +0000
@@ -21,7 +21,7 @@
2121
22include(FindPkgConfig)22include(FindPkgConfig)
2323
24pkg_check_modules(UNITY_SCOPES REQUIRED libunity-scopes>=0.4.0 libunity-api>=0.1.3)24pkg_check_modules(UNITY_SCOPES REQUIRED libunity-scopes>=0.5.0 libunity-api>=0.1.3)
25add_definitions(${UNITY_SCOPES_CFLAGS} ${UNITY_SCOPES_CFLAGS_OTHER})25add_definitions(${UNITY_SCOPES_CFLAGS} ${UNITY_SCOPES_CFLAGS_OTHER})
2626
27find_package (PkgConfig REQUIRED)27find_package (PkgConfig REQUIRED)
2828
=== modified file 'debian/control'
--- debian/control 2014-06-13 15:21:16 +0000
+++ debian/control 2014-06-18 18:08:01 +0000
@@ -13,7 +13,7 @@
13 libubuntu-download-manager-common-dev (>= 0.3+14.10.20140430-0ubuntu1),13 libubuntu-download-manager-common-dev (>= 0.3+14.10.20140430-0ubuntu1),
14 libubuntuoneauth-2.0-dev,14 libubuntuoneauth-2.0-dev,
15 libunity-api-dev (>= 7.80.7),15 libunity-api-dev (>= 7.80.7),
16 libunity-scopes-dev (>= 0.4.0),16 libunity-scopes-dev (>= 0.5.0),
17 pkg-config,17 pkg-config,
18 python3-all,18 python3-all,
19Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>19Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
2020
=== modified file 'libclickscope/click/CMakeLists.txt'
--- libclickscope/click/CMakeLists.txt 2014-06-13 15:21:16 +0000
+++ libclickscope/click/CMakeLists.txt 2014-06-18 18:08:01 +0000
@@ -11,6 +11,9 @@
11add_library(${SCOPE_LIB_NAME} STATIC11add_library(${SCOPE_LIB_NAME} STATIC
12 configuration.cpp12 configuration.cpp
13 download-manager.cpp13 download-manager.cpp
14 department-lookup.cpp
15 departments.cpp
16 highlights.cpp
14 index.cpp17 index.cpp
15 interface.cpp18 interface.cpp
16 key_file_locator.cpp19 key_file_locator.cpp
1720
=== added file 'libclickscope/click/department-lookup.cpp'
--- libclickscope/click/department-lookup.cpp 1970-01-01 00:00:00 +0000
+++ libclickscope/click/department-lookup.cpp 2014-06-18 18:08:01 +0000
@@ -0,0 +1,84 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#include "department-lookup.h"
31
32namespace click
33{
34
35DepartmentLookup::DepartmentLookup()
36{
37}
38
39void DepartmentLookup::rebuild(const Department::SPtr& dept)
40{
41 departments[dept->id()] = dept;
42 for (auto const& subdep: dept->sub_departments())
43 {
44 parent_lut[subdep->id()] = dept;
45 rebuild(subdep);
46 }
47}
48
49void DepartmentLookup::rebuild(const std::list<Department::SPtr>& root_departments)
50{
51 parent_lut.clear();
52 departments.clear();
53 for (auto const& dep: root_departments)
54 {
55 rebuild(dep);
56 }
57}
58
59Department::SPtr DepartmentLookup::get_parent(const std::string& department_id) const
60{
61 auto it = parent_lut.find(department_id);
62 if (it != parent_lut.end())
63 {
64 return it->second;
65 }
66 return Department::SPtr(nullptr);
67}
68
69Department::SPtr DepartmentLookup::get_department_info(const std::string& department_id) const
70{
71 auto it = departments.find(department_id);
72 if (it != departments.end())
73 {
74 return it->second;
75 }
76 return nullptr;
77}
78
79int DepartmentLookup::size() const
80{
81 return parent_lut.size();
82}
83
84}
085
=== added file 'libclickscope/click/department-lookup.h'
--- libclickscope/click/department-lookup.h 1970-01-01 00:00:00 +0000
+++ libclickscope/click/department-lookup.h 2014-06-18 18:08:01 +0000
@@ -0,0 +1,58 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#ifndef CLICK_DEPARTMENT_LOOKUP_H
31#define CLICK_DEPARTMENT_LOOKUP_H
32
33#include "departments.h"
34#include <string>
35#include <memory>
36#include <map>
37
38namespace click
39{
40
41class DepartmentLookup
42{
43 public:
44 DepartmentLookup();
45 void rebuild(const std::list<Department::SPtr>& root_departments);
46 Department::SPtr get_parent(const std::string& department_id) const;
47 Department::SPtr get_department_info(const std::string& department_id) const;
48 int size() const;
49
50 private:
51 void rebuild(const Department::SPtr& dept);
52 std::map<std::string, Department::SPtr> parent_lut;
53 std::map<std::string, Department::SPtr> departments;
54};
55
56}
57
58#endif
059
=== added file 'libclickscope/click/departments.cpp'
--- libclickscope/click/departments.cpp 1970-01-01 00:00:00 +0000
+++ libclickscope/click/departments.cpp 2014-06-18 18:08:01 +0000
@@ -0,0 +1,164 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#include "departments.h"
31#include <iostream>
32
33namespace click
34{
35
36/*Department::Department(const std::string& id, const std::string& name)
37 : id_(id),
38 name_(name),
39 href_(""), //FIXME
40 has_children_flag_(false)
41{
42}*/
43
44Department::Department(const std::string& id, const std::string &name, const std::string& href, bool has_children)
45 : id_(id),
46 name_(name),
47 href_(href),
48 has_children_flag_(has_children)
49{
50}
51
52std::string Department::id() const
53{
54 return id_;
55}
56
57std::string Department::name() const
58{
59 return name_;
60}
61
62std::string Department::href() const
63{
64 return href_;
65}
66
67bool Department::has_children_flag() const
68{
69 return has_children_flag_;
70}
71
72void Department::set_subdepartments(const std::list<Department::SPtr>& deps)
73{
74 sub_departments_ = deps;
75}
76
77std::list<Department::SPtr> Department::sub_departments() const
78{
79 return sub_departments_;
80}
81
82std::list<Department::SPtr> Department::from_json_node(const Json::Value& node)
83{
84 std::list<Department::SPtr> deps;
85
86 for (uint i = 0; i < node.size(); i++)
87 {
88 auto const item = node[i];
89 if (item.isObject() && item.isMember(Department::JsonKeys::name))
90 {
91 auto name = item[Department::JsonKeys::name].asString();
92 const bool has_children = item.isMember(Department::JsonKeys::has_children) ? item[Department::JsonKeys::has_children].asBool() : false;
93
94 auto const links = item[Department::JsonKeys::links];
95 auto const self = links[Department::JsonKeys::self];
96 auto const href = self[Department::JsonKeys::href].asString();
97
98 auto dep = std::make_shared<Department>(name, name, href, has_children); //FIXME: id
99 if (item.isObject() && item.isMember(Department::JsonKeys::embedded))
100 {
101 auto const emb = item[Department::JsonKeys::embedded];
102 if (emb.isObject() && emb.isMember(Department::JsonKeys::department))
103 {
104 auto const ditem = emb[Department::JsonKeys::department];
105 auto const subdeps = from_json_node(ditem);
106 dep->set_subdepartments(subdeps);
107 }
108 }
109 deps.push_back(dep);
110 }
111 }
112
113 return deps;
114}
115
116std::list<Department::SPtr> Department::from_json_root_node(const Json::Value& root)
117{
118 if (root.isObject() && root.isMember(Department::JsonKeys::embedded))
119 {
120 auto const emb = root[Department::JsonKeys::embedded];
121 if (emb.isObject() && emb.isMember(Department::JsonKeys::department))
122 {
123 auto const ditem = emb[Department::JsonKeys::department];
124 return from_json_node(ditem);
125 }
126 }
127
128 return std::list<Department::SPtr>();
129}
130
131std::list<Department::SPtr> Department::from_json(const std::string& json)
132{
133 Json::Reader reader;
134 Json::Value root;
135
136 try
137 {
138 if (!reader.parse(json, root)) {
139 throw std::runtime_error(reader.getFormattedErrorMessages());
140 }
141
142 if (root.isObject() && root.isMember(Department::JsonKeys::embedded))
143 {
144 auto const emb = root[Department::JsonKeys::embedded];
145 if (emb.isObject() && emb.isMember(Department::JsonKeys::department))
146 {
147 auto const ditem = emb[Department::JsonKeys::department];
148 return from_json_node(ditem);
149 }
150 }
151 }
152 catch (const std::exception& e)
153 {
154 std::cerr << "Error parsing departments: " << e.what() << std::endl;
155 }
156 catch (...)
157 {
158 std::cerr << "Unknown error when parsing departments" << std::endl;
159 }
160
161 return std::list<Department::SPtr>();
162}
163
164}
0165
=== added file 'libclickscope/click/departments.h'
--- libclickscope/click/departments.h 1970-01-01 00:00:00 +0000
+++ libclickscope/click/departments.h 2014-06-18 18:08:01 +0000
@@ -0,0 +1,83 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#ifndef CLICK_DEPARTMENTS_H
31#define CLICK_DEPARTMENTS_H
32
33#include <string>
34#include <list>
35#include <memory>
36#include <json/json.h>
37
38namespace click
39{
40
41class Department
42{
43 public:
44 typedef std::shared_ptr<Department> SPtr;
45 typedef std::shared_ptr<Department const> SCPtr;
46
47 struct JsonKeys
48 {
49 JsonKeys() = delete;
50 constexpr static const char* name {"name"};
51 constexpr static const char* embedded {"_embedded"};
52 constexpr static const char* department {"clickindex:department"};
53 constexpr static const char* has_children {"has_children"};
54 constexpr static const char* links {"_links"};
55 constexpr static const char* self {"self"};
56 constexpr static const char* href {"href"};
57 };
58
59 //Department(const std::string &id, const std::string &name);
60 Department(const std::string &id, const std::string &name, const std::string& href, bool has_children);
61 std::string id() const;
62 std::string name() const;
63 std::string href() const;
64 bool has_children_flag() const;
65 void set_subdepartments(const std::list<Department::SPtr>& deps);
66 std::list<Department::SPtr> sub_departments() const;
67 static std::list<Department::SPtr> from_json(const std::string& json);
68 static std::list<Department::SPtr> from_json_root_node(const Json::Value& val);
69
70 private:
71 static std::list<Department::SPtr> from_json_node(const Json::Value& val);
72 std::string id_;
73 std::string name_;
74 std::string href_;
75 bool has_children_flag_;
76 std::list<Department::SPtr> sub_departments_;
77};
78
79typedef std::list<Department::SPtr> DepartmentList;
80
81}
82
83#endif
084
=== added file 'libclickscope/click/highlights.cpp'
--- libclickscope/click/highlights.cpp 1970-01-01 00:00:00 +0000
+++ libclickscope/click/highlights.cpp 2014-06-18 18:08:01 +0000
@@ -0,0 +1,95 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#include "highlights.h"
31#include <iostream>
32
33namespace click
34{
35
36Highlight::Highlight(const std::string& name)
37 : name_(name)
38{
39}
40
41Highlight::Highlight(const std::string& name, const Packages& pkgs)
42 : name_(name),
43 packages_(pkgs)
44{
45}
46
47void Highlight::add_package(const Package& pkg)
48{
49 packages_.push_back(pkg);
50}
51
52std::string Highlight::name() const
53{
54 return name_;
55}
56
57Packages Highlight::packages() const
58{
59 return packages_;
60}
61
62std::list<Highlight> Highlight::from_json_node(const Json::Value& node)
63{
64 std::list<Highlight> highlights;
65
66 for (uint i = 0; i < node.size(); i++)
67 {
68 auto const item = node[i];
69 if (item.isObject() && item.isMember(Highlight::JsonKeys::name))
70 {
71 auto name = item[Highlight::JsonKeys::name].asString();
72 auto pkgs = package_list_from_json_node(item);
73 highlights.push_back(Highlight(name, pkgs));
74 }
75 }
76
77 return highlights;
78}
79
80std::list<Highlight> Highlight::from_json_root_node(const Json::Value& root)
81{
82 if (root.isObject() && root.isMember(Highlight::JsonKeys::embedded))
83 {
84 auto const emb = root[Highlight::JsonKeys::embedded];
85 if (emb.isObject() && emb.isMember(Highlight::JsonKeys::highlight))
86 {
87 auto const hl = emb[Highlight::JsonKeys::highlight];
88 return from_json_node(hl);
89 }
90 }
91
92 return std::list<Highlight>();
93}
94
95}
096
=== added file 'libclickscope/click/highlights.h'
--- libclickscope/click/highlights.h 1970-01-01 00:00:00 +0000
+++ libclickscope/click/highlights.h 2014-06-18 18:08:01 +0000
@@ -0,0 +1,72 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#ifndef CLICK_HIGHLIGHTS_H
31#define CLICK_HIGHLIGHTS_H
32
33#include <string>
34#include <list>
35#include <json/json.h>
36#include <click/package.h>
37
38namespace click
39{
40
41class Highlight
42{
43public:
44 struct JsonKeys
45 {
46 JsonKeys() = delete;
47 constexpr static const char* name {"name"};
48 constexpr static const char* embedded {"_embedded"};
49 constexpr static const char* highlight {"clickindex:highlight"};
50 };
51
52 Highlight(const std::string& name);
53 Highlight(const std::string& name, const Packages& pkgs);
54 void add_package(const Package& pkg);
55
56 std::string name() const;
57 Packages packages() const;
58
59 static std::list<Highlight> from_json_root_node(const Json::Value& val);
60
61private:
62 static std::list<Highlight> from_json_node(const Json::Value& val);
63
64 std::string name_;
65 Packages packages_;
66};
67
68typedef std::list<Highlight> HighlightList;
69
70}
71
72#endif
073
=== modified file 'libclickscope/click/index.cpp'
--- libclickscope/click/index.cpp 2014-06-12 21:05:25 +0000
+++ libclickscope/click/index.cpp 2014-06-18 18:08:01 +0000
@@ -88,11 +88,15 @@
8888
89}89}
9090
91std::string Index::build_index_query(const std::string& query)91std::string Index::build_index_query(const std::string& query, const std::string& department)
92{92{
93 std::stringstream result;93 std::stringstream result;
9494
95 result << query;95 result << query;
96 if (!department.empty()) {
97 result << ",department:" << department;
98 }
99
96 return result.str();100 return result.str();
97}101}
98102
@@ -110,10 +114,10 @@
110 };114 };
111}115}
112116
113click::web::Cancellable Index::search (const std::string& query, std::function<void(click::Packages)> callback)117click::web::Cancellable Index::search (const std::string& query, const std::string& department, std::function<void(click::Packages, click::DepartmentList)> callback)
114{118{
115 click::web::CallParams params;119 click::web::CallParams params;
116 const std::string built_query(build_index_query(query));120 const std::string built_query(build_index_query(query, department));
117 params.add(click::QUERY_ARGNAME, built_query.c_str());121 params.add(click::QUERY_ARGNAME, built_query.c_str());
118 QSharedPointer<click::web::Response> response(client->call(122 QSharedPointer<click::web::Response> response(client->call(
119 get_base_url() + click::SEARCH_PATH, "GET", false, build_headers(), "", params));123 get_base_url() + click::SEARCH_PATH, "GET", false, build_headers(), "", params));
@@ -123,22 +127,83 @@
123 Json::Value root;127 Json::Value root;
124128
125 click::Packages pl;129 click::Packages pl;
130 click::DepartmentList depts;
126 if (reader.parse(reply.toUtf8().constData(), root)) {131 if (reader.parse(reply.toUtf8().constData(), root)) {
127 pl = click::package_list_from_json_node(root);132 pl = click::package_list_from_json_node(root);
128 qDebug() << "found packages:" << pl.size();133 qDebug() << "found packages:" << pl.size();
134 depts = click::Department::from_json_root_node(root);
129 }135 }
130 callback(pl);136 callback(pl, depts);
131 });137 });
132 QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/) {138 QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/) {
133 qDebug() << "No packages found due to network error";139 qDebug() << "No packages found due to network error";
134 click::Packages pl;140 click::Packages pl;
141 click::DepartmentList depts;
135 qDebug() << "calling callback";142 qDebug() << "calling callback";
136 callback(pl);143 callback(pl, depts);
137 qDebug() << " ...Done!";144 qDebug() << " ...Done!";
138 });145 });
139 return click::web::Cancellable(response);146 return click::web::Cancellable(response);
140}147}
141148
149click::web::Cancellable Index::bootstrap(std::function<void(const click::DepartmentList&, const click::HighlightList&, Error, int)> callback)
150{
151 click::web::CallParams params;
152 QSharedPointer<click::web::Response> response(client->call(
153 get_base_url() + click::BOOTSTRAP_PATH, "GET", false, build_headers(), "", params));
154
155 QObject::connect(response.data(), &click::web::Response::finished, [=](QString reply) {
156 qDebug() << "bootstrap request finished";
157 Json::Reader reader;
158 Json::Value root;
159
160 click::DepartmentList depts;
161 click::HighlightList highlights;
162 if (reader.parse(reply.toUtf8().constData(), root)) {
163 depts = Department::from_json_root_node(root);
164 highlights = Highlight::from_json_root_node(root);
165 }
166 callback(depts, highlights, click::Index::Error::NoError, 0);
167 });
168 QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/, int error_code) {
169 qWarning() << "bootstrap call failed due to network error, code" << error_code;
170 const click::DepartmentList depts;
171 const click::HighlightList highlights;
172 qDebug() << "bootstrap: calling callback";
173 callback(depts, highlights, click::Index::Error::NetworkError, error_code);
174 });
175 return click::web::Cancellable(response);
176}
177
178click::web::Cancellable Index::departments(const std::string& department_href, std::function<void(const DepartmentList&, const HighlightList&, Error)> callback)
179{
180 click::web::CallParams params;
181 QSharedPointer<click::web::Response> response(client->call(
182 department_href, "GET", false, build_headers(), "", params));
183
184 QObject::connect(response.data(), &click::web::Response::finished, [=](QString reply) {
185 qDebug() << "departments request finished";
186 Json::Reader reader;
187 Json::Value root;
188
189 click::DepartmentList depts;
190 click::HighlightList highlights;
191 if (reader.parse(reply.toUtf8().constData(), root)) {
192 depts = Department::from_json_root_node(root);
193 highlights = Highlight::from_json_root_node(root);
194 }
195 callback(depts, highlights, click::Index::Error::NoError);
196 });
197 QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/) {
198 qWarning() << "departments call failed due to network error";
199 const click::DepartmentList depts;
200 const click::HighlightList highlights;
201 qDebug() << "departments: calling callback";
202 callback(depts, highlights, click::Index::Error::NetworkError);
203 });
204 return click::web::Cancellable(response);
205}
206
142click::web::Cancellable Index::get_details (const std::string& package_name, std::function<void(PackageDetails, click::Index::Error)> callback)207click::web::Cancellable Index::get_details (const std::string& package_name, std::function<void(PackageDetails, click::Index::Error)> callback)
143{208{
144 QSharedPointer<click::web::Response> response = client->call209 QSharedPointer<click::web::Response> response = client->call
145210
=== modified file 'libclickscope/click/index.h'
--- libclickscope/click/index.h 2014-06-12 21:05:25 +0000
+++ libclickscope/click/index.h 2014-06-18 18:08:01 +0000
@@ -38,6 +38,8 @@
38#include <click/webclient.h>38#include <click/webclient.h>
3939
40#include "package.h"40#include "package.h"
41#include <click/departments.h>
42#include <click/highlights.h>
4143
4244
43namespace click {45namespace click {
@@ -47,6 +49,7 @@
47const std::string SEARCH_BASE_URL_ENVVAR = "U1_SEARCH_BASE_URL";49const std::string SEARCH_BASE_URL_ENVVAR = "U1_SEARCH_BASE_URL";
48const std::string SEARCH_BASE_URL = "https://search.apps.ubuntu.com/";50const std::string SEARCH_BASE_URL = "https://search.apps.ubuntu.com/";
49const std::string SEARCH_PATH = "api/v1/search";51const std::string SEARCH_PATH = "api/v1/search";
52const std::string BOOTSTRAP_PATH = "api/v1";
50const std::string SUPPORTED_FRAMEWORKS = "framework:ubuntu-sdk-13.10";53const std::string SUPPORTED_FRAMEWORKS = "framework:ubuntu-sdk-13.10";
51const std::string QUERY_ARGNAME = "q";54const std::string QUERY_ARGNAME = "q";
52const std::string ARCHITECTURE = "architecture:";55const std::string ARCHITECTURE = "architecture:";
@@ -64,15 +67,17 @@
64protected:67protected:
65 QSharedPointer<web::Client> client;68 QSharedPointer<web::Client> client;
66 QSharedPointer<Configuration> configuration;69 QSharedPointer<Configuration> configuration;
67 virtual std::string build_index_query(const std::string& query);70 virtual std::string build_index_query(const std::string& query, const std::string& department);
68 virtual std::map<std::string, std::string> build_headers();71 virtual std::map<std::string, std::string> build_headers();
6972
70public:73public:
71 enum class Error {NoError, CredentialsError, NetworkError};74 enum class Error {NoError, CredentialsError, NetworkError};
72 Index(const QSharedPointer<click::web::Client>& client,75 Index(const QSharedPointer<click::web::Client>& client,
73 const QSharedPointer<Configuration> configuration=QSharedPointer<Configuration>(new Configuration()));76 const QSharedPointer<Configuration> configuration=QSharedPointer<Configuration>(new Configuration()));
74 virtual click::web::Cancellable search (const std::string& query, std::function<void(Packages)> callback);77 virtual click::web::Cancellable search (const std::string& query, const std::string& department, std::function<void(Packages, DepartmentList)> callback);
75 virtual click::web::Cancellable get_details(const std::string& package_name, std::function<void(PackageDetails, Error)> callback);78 virtual click::web::Cancellable get_details(const std::string& package_name, std::function<void(PackageDetails, Error)> callback);
79 virtual click::web::Cancellable bootstrap(std::function<void(const DepartmentList&, const HighlightList&, Error, int)> callback);
80 virtual click::web::Cancellable departments(const std::string& department_href, std::function<void(const DepartmentList&, const HighlightList&, Error)> callback);
76 virtual ~Index();81 virtual ~Index();
7782
78 static std::string get_base_url ();83 static std::string get_base_url ();
7984
=== modified file 'libclickscope/click/package.h'
--- libclickscope/click/package.h 2014-06-13 22:42:02 +0000
+++ libclickscope/click/package.h 2014-06-18 18:08:01 +0000
@@ -34,6 +34,7 @@
34#include <string>34#include <string>
35#include <unordered_set>35#include <unordered_set>
36#include <vector>36#include <vector>
37#include <functional>
3738
38#include <json/json.h>39#include <json/json.h>
3940
4041
=== modified file 'libclickscope/click/preview.cpp'
--- libclickscope/click/preview.cpp 2014-06-17 21:05:05 +0000
+++ libclickscope/click/preview.cpp 2014-06-18 18:08:01 +0000
@@ -57,6 +57,7 @@
57 const unity::scopes::ActionMetadata& metadata,57 const unity::scopes::ActionMetadata& metadata,
58 const QSharedPointer<click::web::Client>& client,58 const QSharedPointer<click::web::Client>& client,
59 const QSharedPointer<click::network::AccessManager>& nam)59 const QSharedPointer<click::network::AccessManager>& nam)
60 : PreviewQueryBase(result, metadata)
60{61{
61 strategy.reset(choose_strategy(result, metadata, client, nam));62 strategy.reset(choose_strategy(result, metadata, client, nam));
62}63}
6364
=== modified file 'libclickscope/click/scope_activation.cpp'
--- libclickscope/click/scope_activation.cpp 2014-05-28 07:42:24 +0000
+++ libclickscope/click/scope_activation.cpp 2014-06-18 18:08:01 +0000
@@ -33,6 +33,11 @@
33#include <click/qtbridge.h>33#include <click/qtbridge.h>
34#include <unity/scopes/ActivationResponse.h>34#include <unity/scopes/ActivationResponse.h>
3535
36click::ScopeActivation::ScopeActivation(const unity::scopes::Result& result, const unity::scopes::ActionMetadata& metadata)
37 : unity::scopes::ActivationQueryBase(result, metadata)
38{
39}
40
36unity::scopes::ActivationResponse click::ScopeActivation::activate()41unity::scopes::ActivationResponse click::ScopeActivation::activate()
37{42{
38 auto response = unity::scopes::ActivationResponse(status_);43 auto response = unity::scopes::ActivationResponse(status_);
@@ -50,18 +55,19 @@
50 hints_[key] = value;55 hints_[key] = value;
51}56}
5257
53click::PerformUninstallAction::PerformUninstallAction(const unity::scopes::Result& result, const unity::scopes::ActivationResponse& response)58click::PerformUninstallAction::PerformUninstallAction(const unity::scopes::Result& result, const unity::scopes::ActionMetadata& metadata, const unity::scopes::ActivationResponse& response)
54 : result(result),59 : unity::scopes::ActivationQueryBase(result, metadata),
55 response(response)60 response(response)
56{61{
57}62}
5863
59unity::scopes::ActivationResponse click::PerformUninstallAction::activate()64unity::scopes::ActivationResponse click::PerformUninstallAction::activate()
60{65{
66 auto const res = result();
61 click::Package package;67 click::Package package;
62 package.title = result.title();68 package.title = res.title();
63 package.name = result["name"].get_string();69 package.name = res["name"].get_string();
64 package.version = result["version"].get_string();70 package.version = res["version"].get_string();
65 qt::core::world::enter_with_task([this, package] ()71 qt::core::world::enter_with_task([this, package] ()
66 {72 {
67 click::PackageManager manager;73 click::PackageManager manager;
6874
=== modified file 'libclickscope/click/scope_activation.h'
--- libclickscope/click/scope_activation.h 2014-05-28 07:42:24 +0000
+++ libclickscope/click/scope_activation.h 2014-06-18 18:08:01 +0000
@@ -40,11 +40,10 @@
40class PerformUninstallAction: public unity::scopes::ActivationQueryBase40class PerformUninstallAction: public unity::scopes::ActivationQueryBase
41{41{
42public:42public:
43 PerformUninstallAction(const unity::scopes::Result& result, const unity::scopes::ActivationResponse& response);43 PerformUninstallAction(const unity::scopes::Result& result, const unity::scopes::ActionMetadata& metadata, const unity::scopes::ActivationResponse& response);
44 unity::scopes::ActivationResponse activate() override;44 unity::scopes::ActivationResponse activate() override;
4545
46private:46private:
47 unity::scopes::Result result;
48 unity::scopes::ActivationResponse response;47 unity::scopes::ActivationResponse response;
49};48};
5049
@@ -53,6 +52,7 @@
53 unity::scopes::ActivationResponse activate() override;52 unity::scopes::ActivationResponse activate() override;
5453
55public:54public:
55 ScopeActivation(const unity::scopes::Result& result, const unity::scopes::ActionMetadata& metadata);
56 void setStatus(unity::scopes::ActivationResponse::Status status);56 void setStatus(unity::scopes::ActivationResponse::Status status);
57 void setHint(std::string key, unity::scopes::Variant value);57 void setHint(std::string key, unity::scopes::Variant value);
5858
5959
=== modified file 'libclickscope/click/webclient.cpp'
--- libclickscope/click/webclient.cpp 2014-05-23 18:45:01 +0000
+++ libclickscope/click/webclient.cpp 2014-06-18 18:08:01 +0000
@@ -176,7 +176,8 @@
176{176{
177 auto message = reply->errorString() + QString(" (%1)").arg(network_error);177 auto message = reply->errorString() + QString(" (%1)").arg(network_error);
178 qWarning() << "Network error:" << message << "\n" << reply->readAll();178 qWarning() << "Network error:" << message << "\n" << reply->readAll();
179 emit error(message);179 int error_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
180 emit error(message, error_code);
180}181}
181182
182void click::web::Response::abort()183void click::web::Response::abort()
183184
=== modified file 'libclickscope/click/webclient.h'
--- libclickscope/click/webclient.h 2014-05-23 18:45:01 +0000
+++ libclickscope/click/webclient.h 2014-06-18 18:08:01 +0000
@@ -84,7 +84,7 @@
8484
85signals:85signals:
86 void finished(QByteArray result);86 void finished(QByteArray result);
87 void error(QString description);87 void error(QString description, int error_code);
8888
89private:89private:
90 QSharedPointer<click::network::Reply> reply;90 QSharedPointer<click::network::Reply> reply;
9191
=== modified file 'libclickscope/tests/CMakeLists.txt'
--- libclickscope/tests/CMakeLists.txt 2014-05-26 14:27:31 +0000
+++ libclickscope/tests/CMakeLists.txt 2014-06-18 18:08:01 +0000
@@ -28,6 +28,8 @@
28 test_reviews.cpp28 test_reviews.cpp
29 test_smartconnect.cpp29 test_smartconnect.cpp
30 test_webclient.cpp30 test_webclient.cpp
31 test_bootstrap.cpp
32 test_departments.cpp
3133
32 ${CMAKE_CURRENT_BINARY_DIR}/test_data.cpp34 ${CMAKE_CURRENT_BINARY_DIR}/test_data.cpp
33)35)
3436
=== modified file 'libclickscope/tests/fake_json.h'
--- libclickscope/tests/fake_json.h 2014-06-13 23:18:41 +0000
+++ libclickscope/tests/fake_json.h 2014-06-18 18:08:01 +0000
@@ -150,6 +150,242 @@
150 }150 }
151)foo";151)foo";
152152
153const std::string FAKE_JSON_BOOTSTRAP = R"(
154 {
155 "_embedded": {
156 "clickindex:department": [
157 {
158 "has_children": false,
159 "_links": {
160 "self": {
161 "href": "https://search.apps.staging.ubuntu.com/api/v1/departments/fake-subdepartment"}
162 },
163 "name": "Fake Subdepartment", "slug": "fake-subdepartment"}
164 ],
165 "clickindex:highlight": [
166 {
167 "_embedded": {
168 "clickindex:package": [
169 {
170 "publisher": "Awesome Widget Company",
171 "name": "org.example.awesomelauncher",
172 "title": "Awesome Launcher",
173 "price": 1.99,
174 "_links": {
175 "self": {
176 "href": "https://search.apps.staging.ubuntu.com/api/v1/package/org.example.awesomelauncher"}
177 },
178 "icon": "http://example.org/media/org.example.awesomelauncher/icons/icon16.png"
179 },
180 {
181 "publisher": "Awesome Widget Company",
182 "name": "org.example.awesomewidget",
183 "title": "Awesome Widget", "price": 1.99,
184 "_links": {
185 "self": {
186 "href": "https://search.apps.staging.ubuntu.com/api/v1/package/org.example.awesomewidget"
187 }
188 },
189 "icon": "http://example.org/media/org.example.awesomewidget/icons/icon16.png"}
190 ]
191 },
192 "_links": {
193 "self": {
194 "href": "https://search.apps.staging.ubuntu.com/api/v1/highlights/top-apps"
195 }
196 },
197 "name": "Top Apps", "slug": "top-apps"
198 },
199 {
200 "_embedded": {
201 "clickindex:package": [
202 {
203 "publisher": "Awesome Widget Company",
204 "name": "org.example.awesomelauncher",
205 "title": "Awesome Launcher",
206 "price": 1.99,
207 "_links": {
208 "self": {
209 "href": "https://search.apps.staging.ubuntu.com/api/v1/package/org.example.awesomelauncher"
210 }
211 },
212 "icon": "http://example.org/media/org.example.awesomelauncher/icons/icon16.png"
213 },
214 {
215 "publisher": "Awesome Widget Company",
216 "name": "org.example.awesomewidget",
217 "title": "Awesome Widget",
218 "price": 1.99,
219 "_links": {
220 "self": {
221 "href": "https://search.apps.staging.ubuntu.com/api/v1/package/org.example.awesomewidget"
222 }
223 },
224 "icon": "http://example.org/media/org.example.awesomewidget/icons/icon16.png"
225 }
226 ]
227 },
228 "_links": {
229 "self": {
230 "href": "https://search.apps.staging.ubuntu.com/api/v1/highlights/most-purchased"
231 }
232 },
233 "name": "Most Purchased",
234 "slug": "most-purchased"
235 },
236 {
237 "_embedded": {
238 "clickindex:package": [
239 {
240 "publisher": "Awesome Widget Company",
241 "name": "org.example.awesomelauncher",
242 "title": "Awesome Launcher",
243 "price": 1.99,
244 "_links": {
245 "self": {
246 "href": "https://search.apps.staging.ubuntu.com/api/v1/package/org.example.awesomelauncher"
247 }
248 },
249 "icon": "http://example.org/media/org.example.awesomelauncher/icons/icon16.png"
250 },
251 {
252 "publisher": "Awesome Widget Company",
253 "name": "org.example.awesomewidget",
254 "title": "Awesome Widget",
255 "price": 1.99,
256 "_links": {
257 "self": {
258 "href": "https://search.apps.staging.ubuntu.com/api/v1/package/org.example.awesomewidget"
259 }
260 },
261 "icon": "http://example.org/media/org.example.awesomewidget/icons/icon16.png"
262 }
263 ]
264 },
265 "_links": {
266 "self": {
267 "href": "https://search.apps.staging.ubuntu.com/api/v1/highlights/new-releases"
268 }
269 },
270 "name": "New Releases",
271 "slug": "new-releases"
272 }
273 ]
274 }, "has_children": true,
275 "_links": {
276 "curies": [
277 {
278 "href": "https://search.apps.staging.ubuntu.com/docs/v1/relations.html{#rel}",
279 "name": "clickindex", "templated": true
280 }
281 ],
282 "self": {
283 "href": "https://search.apps.staging.ubuntu.com/api/v1/departments/fake-department-with-subdepartments"
284 },
285 "collection": {
286 "href": "https://search.apps.staging.ubuntu.com/api/v1/departments"
287 }
288 },
289 "name": "Fake Department With Subdepartments",
290 "slug": "fake-department-with-subdepartments"
291 })";
292
293const std::string FAKE_JSON_DEPARTMENTS_ONLY = R"(
294 {
295 "_links": {
296 "self": {
297 "href": "https://search.apps.ubuntu.com/api/v1/departments"
298 },
299 "curies": [
300 {
301 "name": "clickindex",
302 "href": "https://search.apps.ubuntu.com/docs/v1/relations.html{#rel}",
303 "templated": true
304 }
305 ]
306 },
307 "_embedded": {
308 "clickindex:department": [
309 {
310 "name": "Games",
311 "_links": {
312 "self": {
313 "href": "https://search.apps.ubuntu.com/api/v1/departments/Games"
314 }
315 },
316 "_embedded": {
317 "clickindex:department": [
318 {
319 "name": "Board Games",
320 "_links": {
321 "self": {
322 "href": "https://search.apps.ubuntu.com/api/v1/departments/Games/Board+Games"
323 }
324 }
325 }
326 ]
327 }
328 },
329 {
330 "name": "Graphics",
331 "_links": {
332 "self": {
333 "href": "https://search.apps.ubuntu.com/api/v1/departments/Graphics"
334 }
335 },
336 "_embedded": {
337 "clickindex:department": [
338 {
339 "name": "Drawing",
340 "_links": {
341 "self": {
342 "href": "https://search.apps.ubuntu.com/api/v1/departments/Graphics/Drawing"
343 }
344 }
345 }
346 ]
347 }
348 },
349 {
350 "name": "Internet",
351 "_links": {
352 "self": {
353 "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet"
354 }
355 },
356 "_embedded": {
357 "clickindex:department": [
358 {
359 "name": "Chat",
360 "_links": {
361 "self": {
362 "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Chat"
363 }
364 }
365 },
366 {
367 "name": "Mail",
368 "_links": {
369 "self": {
370 "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Mail"
371 }
372 }
373 },
374 {
375 "name": "Web Browsers",
376 "_links": {
377 "self": {
378 "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Web+Browsers"
379 }
380 }
381 }
382 ]
383 }
384 }
385 ]
386 }
387})";
388
153const std::string FAKE_JSON_MANIFEST_REMOVABLE = R"foo(389const std::string FAKE_JSON_MANIFEST_REMOVABLE = R"foo(
154 {390 {
155 "_removable": 1,391 "_removable": 1,
156392
=== modified file 'libclickscope/tests/mock_network_access_manager.h'
--- libclickscope/tests/mock_network_access_manager.h 2014-05-20 19:33:41 +0000
+++ libclickscope/tests/mock_network_access_manager.h 2014-06-18 18:08:01 +0000
@@ -48,6 +48,7 @@
48 {48 {
49 // Set a default value for QByteArray-returning mocked methods.49 // Set a default value for QByteArray-returning mocked methods.
50 ::testing::DefaultValue<QByteArray>::Set(QByteArray(""));50 ::testing::DefaultValue<QByteArray>::Set(QByteArray(""));
51 ON_CALL(*this, attribute(::testing::_)).WillByDefault(::testing::Return(0));
51 }52 }
5253
53 MOCK_METHOD0(abort, void());54 MOCK_METHOD0(abort, void());
5455
=== modified file 'libclickscope/tests/mock_webclient.h'
--- libclickscope/tests/mock_webclient.h 2014-05-23 18:45:01 +0000
+++ libclickscope/tests/mock_webclient.h 2014-06-18 18:08:01 +0000
@@ -86,7 +86,7 @@
86 const click::web::CallParams& params));86 const click::web::CallParams& params));
87 QSharedPointer<click::web::Response> call(87 QSharedPointer<click::web::Response> call(
88 const std::string& iri,88 const std::string& iri,
89 const click::web::CallParams& params=click::web::CallParams()) {89 const click::web::CallParams& params=click::web::CallParams()) override {
90 return callImpl(iri, "GET", false,90 return callImpl(iri, "GET", false,
91 std::map<std::string, std::string>(), "", params);91 std::map<std::string, std::string>(), "", params);
92 }92 }
@@ -96,7 +96,7 @@
96 bool sign = false,96 bool sign = false,
97 const std::map<std::string, std::string>& headers = std::map<std::string, std::string>(),97 const std::map<std::string, std::string>& headers = std::map<std::string, std::string>(),
98 const std::string& data = "",98 const std::string& data = "",
99 const click::web::CallParams& params=click::web::CallParams()) {99 const click::web::CallParams& params=click::web::CallParams()) override {
100 return callImpl(iri, method, sign, headers, data, params);100 return callImpl(iri, method, sign, headers, data, params);
101 }101 }
102};102};
103103
=== added file 'libclickscope/tests/test_bootstrap.cpp'
--- libclickscope/tests/test_bootstrap.cpp 1970-01-01 00:00:00 +0000
+++ libclickscope/tests/test_bootstrap.cpp 2014-06-18 18:08:01 +0000
@@ -0,0 +1,73 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#include <gtest/gtest.h>
31#include "fake_json.h"
32#include <json/reader.h>
33#include <json/value.h>
34#include <click/highlights.h>
35#include <click/departments.h>
36
37class BootstrapTest: public ::testing::Test
38{
39 protected:
40 void SetUp() override
41 {
42 }
43};
44
45TEST_F(BootstrapTest, testParsing)
46{
47 Json::Reader reader;
48 Json::Value root;
49
50 EXPECT_TRUE(reader.parse(FAKE_JSON_BOOTSTRAP, root));
51
52 {
53 auto highlights = click::Highlight::from_json_root_node(root);
54 EXPECT_EQ(3u, highlights.size());
55 auto it = highlights.begin();
56 EXPECT_EQ("Top Apps", it->name());
57 EXPECT_EQ(2u, it->packages().size());
58 ++it;
59 EXPECT_EQ("Most Purchased", it->name());
60 EXPECT_EQ(2u, it->packages().size());
61 ++it;
62 EXPECT_EQ("New Releases", it->name());
63 EXPECT_EQ(2u, it->packages().size());
64 }
65 {
66 auto depts = click::Department::from_json_root_node(root);
67 EXPECT_EQ(1u, depts.size());
68 auto it = depts.begin();
69 EXPECT_EQ("Fake Subdepartment", (*it)->name());
70 EXPECT_FALSE((*it)->has_children_flag());
71 EXPECT_EQ("https://search.apps.staging.ubuntu.com/api/v1/departments/fake-subdepartment", (*it)->href());
72 }
73}
074
=== removed file 'libclickscope/tests/test_data.cpp'
=== added file 'libclickscope/tests/test_departments.cpp'
--- libclickscope/tests/test_departments.cpp 1970-01-01 00:00:00 +0000
+++ libclickscope/tests/test_departments.cpp 2014-06-18 18:08:01 +0000
@@ -0,0 +1,108 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#include <gtest/gtest.h>
31#include "fake_json.h"
32#include <click/departments.h>
33#include <click/department-lookup.h>
34
35class DepartmentsTest : public ::testing::Test
36{
37 protected:
38 void SetUp() override
39 {
40 }
41};
42
43TEST_F(DepartmentsTest, testParsing)
44{
45 const std::string jsonstr(FAKE_JSON_DEPARTMENTS_ONLY);
46 auto depts = click::Department::from_json(jsonstr);
47 EXPECT_EQ(3u, depts.size());
48 auto it = depts.cbegin();
49 {
50 auto dep = *it;
51 EXPECT_EQ("Games", dep->id());
52 EXPECT_EQ("Games", dep->name());
53 EXPECT_FALSE(dep->has_children_flag());
54 auto subdepts = dep->sub_departments();
55 EXPECT_EQ(1u, subdepts.size());
56 auto sit = subdepts.cbegin();
57 EXPECT_EQ("Board Games", (*sit)->name());
58 }
59 {
60 ++it;
61 auto dep = *it;
62 EXPECT_EQ("Graphics", dep->id());
63 EXPECT_EQ("Graphics", dep->name());
64 EXPECT_FALSE(dep->has_children_flag());
65 auto subdepts = dep->sub_departments();
66 EXPECT_EQ(1u, subdepts.size());
67 auto sit = subdepts.cbegin();
68 EXPECT_EQ("Drawing", (*sit)->name());
69 }
70 {
71 ++it;
72 auto dep = *it;
73 EXPECT_EQ("Internet", dep->id());
74 EXPECT_EQ("Internet", dep->name());
75 EXPECT_FALSE(dep->has_children_flag());
76 auto subdepts = dep->sub_departments();
77 EXPECT_EQ(3u, subdepts.size());
78 auto sit = subdepts.cbegin();
79 auto subdep = *sit;
80 EXPECT_EQ("Chat", subdep->name());
81 subdep = *(++sit);
82 EXPECT_EQ("Mail", subdep->name());
83 subdep = *(++sit);
84 EXPECT_EQ("Web Browsers", subdep->name());
85 }
86}
87
88TEST_F(DepartmentsTest, testLookup)
89{
90 auto dep_games = std::make_shared<click::Department>("games", "Games", "", false);
91 auto dep_rpg = std::make_shared<click::Department>("rpg", "RPG", "", false);
92 auto dep_strategy = std::make_shared<click::Department>("strategy", "Strategy", "", false);
93 const std::list<click::Department::SPtr> departments {dep_rpg, dep_strategy};
94 dep_games->set_subdepartments(departments);
95
96 const std::list<click::Department::SPtr> root {dep_games};
97 click::DepartmentLookup lut;
98 lut.rebuild(root);
99
100 EXPECT_EQ(2u, lut.size());
101 EXPECT_EQ("games", lut.get_parent("strategy")->id());
102 EXPECT_EQ("games", lut.get_parent("rpg")->id());
103 EXPECT_EQ(nullptr, lut.get_parent("games"));
104
105 lut.rebuild(root);
106 EXPECT_EQ(2u, lut.size());
107}
108
0109
=== modified file 'libclickscope/tests/test_index.cpp'
--- libclickscope/tests/test_index.cpp 2014-06-12 21:05:25 +0000
+++ libclickscope/tests/test_index.cpp 2014-06-18 18:08:01 +0000
@@ -52,8 +52,8 @@
52 click::Index(client, configuration)52 click::Index(client, configuration)
53 {53 {
54 }54 }
55 MOCK_METHOD1(build_index_query, std::string(const std::string&));
56 MOCK_METHOD0(build_headers, std::map<std::string, std::string>());55 MOCK_METHOD0(build_headers, std::map<std::string, std::string>());
56 MOCK_METHOD2(build_index_query, std::string(const std::string&, const std::string&));
57};57};
5858
59class MockConfiguration : public click::Configuration {59class MockConfiguration : public click::Configuration {
@@ -100,7 +100,7 @@
100 .Times(1)100 .Times(1)
101 .WillOnce(Return(response));101 .WillOnce(Return(response));
102102
103 indexPtr->search("", [](click::Packages) {});103 indexPtr->search("", "", [](click::Packages, click::DepartmentList) {});
104}104}
105105
106TEST_F(IndexTest, testSearchSendsBuiltQueryAsParam)106TEST_F(IndexTest, testSearchSendsBuiltQueryAsParam)
@@ -116,11 +116,11 @@
116 .Times(1)116 .Times(1)
117 .WillOnce(Return(response));117 .WillOnce(Return(response));
118118
119 EXPECT_CALL(*indexPtr, build_index_query(FAKE_QUERY))119 EXPECT_CALL(*indexPtr, build_index_query(FAKE_QUERY, ""))
120 .Times(1)120 .Times(1)
121 .WillOnce(Return(FAKE_BUILT_QUERY));121 .WillOnce(Return(FAKE_BUILT_QUERY));
122122
123 indexPtr->search(FAKE_QUERY, [](click::Packages) {});123 indexPtr->search(FAKE_QUERY, "", [](click::Packages, click::DepartmentList) {});
124}124}
125125
126TEST_F(IndexTest, testSearchSendsRightPath)126TEST_F(IndexTest, testSearchSendsRightPath)
@@ -133,7 +133,7 @@
133 .Times(1)133 .Times(1)
134 .WillOnce(Return(response));134 .WillOnce(Return(response));
135135
136 indexPtr->search("", [](click::Packages) {});136 indexPtr->search("", "", [](click::Packages, click::DepartmentList) {});
137}137}
138138
139TEST_F(IndexTest, testSearchCallbackIsCalled)139TEST_F(IndexTest, testSearchCallbackIsCalled)
@@ -150,7 +150,7 @@
150 .WillOnce(Return(response));150 .WillOnce(Return(response));
151 EXPECT_CALL(*this, search_callback(_)).Times(1);151 EXPECT_CALL(*this, search_callback(_)).Times(1);
152152
153 indexPtr->search("", [this](click::Packages packages){153 indexPtr->search("", "", [this](click::Packages packages, click::DepartmentList){
154 search_callback(packages);154 search_callback(packages);
155 });155 });
156 response->replyFinished();156 response->replyFinished();
@@ -171,7 +171,7 @@
171 click::Packages empty_package_list;171 click::Packages empty_package_list;
172 EXPECT_CALL(*this, search_callback(empty_package_list)).Times(1);172 EXPECT_CALL(*this, search_callback(empty_package_list)).Times(1);
173173
174 indexPtr->search("", [this](click::Packages packages){174 indexPtr->search("", "", [this](click::Packages packages, click::DepartmentList){
175 search_callback(packages);175 search_callback(packages);
176 });176 });
177 response->replyFinished();177 response->replyFinished();
@@ -200,7 +200,7 @@
200 };200 };
201 EXPECT_CALL(*this, search_callback(single_package_list)).Times(1);201 EXPECT_CALL(*this, search_callback(single_package_list)).Times(1);
202202
203 indexPtr->search("", [this](click::Packages packages){203 indexPtr->search("", "", [this](click::Packages packages, click::DepartmentList){
204 search_callback(packages);204 search_callback(packages);
205 });205 });
206 response->replyFinished();206 response->replyFinished();
@@ -215,7 +215,7 @@
215 .Times(1)215 .Times(1)
216 .WillOnce(Return(response));216 .WillOnce(Return(response));
217217
218 auto search_operation = indexPtr->search("", [](click::Packages) {});218 auto search_operation = indexPtr->search("", "", [](click::Packages, click::DepartmentList) {});
219 EXPECT_CALL(reply.instance, abort()).Times(1);219 EXPECT_CALL(reply.instance, abort()).Times(1);
220 search_operation.cancel();220 search_operation.cancel();
221}221}
@@ -234,7 +234,7 @@
234 .Times(1)234 .Times(1)
235 .WillOnce(Return(response));235 .WillOnce(Return(response));
236 EXPECT_CALL(reply.instance, errorString()).Times(1).WillOnce(Return("fake error"));236 EXPECT_CALL(reply.instance, errorString()).Times(1).WillOnce(Return("fake error"));
237 indexPtr->search("", [this](click::Packages packages){237 indexPtr->search("", "", [this](click::Packages packages, click::DepartmentList){
238 search_callback(packages);238 search_callback(packages);
239 });239 });
240240
241241
=== modified file 'scope/clickapps/apps-query.cpp'
--- scope/clickapps/apps-query.cpp 2014-06-10 21:09:52 +0000
+++ scope/clickapps/apps-query.cpp 2014-06-18 18:08:01 +0000
@@ -128,25 +128,24 @@
128128
129struct click::Query::Private129struct click::Query::Private
130{130{
131 Private(const unity::scopes::CannedQuery& query, click::Index& index, const scopes::SearchMetadata& metadata)131 Private(click::Index& index, const scopes::SearchMetadata& metadata)
132 : query(query),132 : index(index),
133 index(index),
134 meta(metadata)133 meta(metadata)
135 {134 {
136 }135 }
137 unity::scopes::CannedQuery query;
138 click::Index& index;136 click::Index& index;
139 scopes::SearchMetadata meta;137 scopes::SearchMetadata meta;
140};138};
141139
142click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata)140click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata)
143 : impl(new Private(query, index, metadata))141 : unity::scopes::SearchQueryBase(query, metadata),
142 impl(new Private(index, metadata))
144{143{
145}144}
146145
147void click::Query::cancelled()146void click::Query::cancelled()
148{147{
149 qDebug() << "cancelling search of" << QString::fromStdString(impl->query.query_string());148 qDebug() << "cancelling search of" << QString::fromStdString(query().query_string());
150}149}
151150
152click::Query::~Query()151click::Query::~Query()
@@ -171,10 +170,10 @@
171 static const std::string title = _("Get more apps in Ubuntu store");170 static const std::string title = _("Get more apps in Ubuntu store");
172 auto name = title;171 auto name = title;
173172
174 std::string query = impl->query.query_string();173 std::string querystr = query().query_string();
175 std::transform(query.begin(), query.end(), query.begin(), ::tolower);174 std::transform(querystr.begin(), querystr.end(), querystr.begin(), ::tolower);
176 std::transform(name.begin(), name.end(), name.begin(), ::tolower);175 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
177 if (query.empty() || name.find(query) != std::string::npos)176 if (querystr.empty() || name.find(querystr) != std::string::npos)
178 {177 {
179 scopes::CategoryRenderer rdr(CATEGORY_STORE);178 scopes::CategoryRenderer rdr(CATEGORY_STORE);
180 auto cat = searchReply->register_category("store", "", "", rdr);179 auto cat = searchReply->register_category("store", "", "", rdr);
@@ -196,13 +195,13 @@
196195
197void click::Query::run(scopes::SearchReplyProxy const& searchReply)196void click::Query::run(scopes::SearchReplyProxy const& searchReply)
198{197{
199 auto query = impl->query.query_string();198 auto querystr = query().query_string();
200 std::string categoryTemplate = CATEGORY_APPS_SEARCH;199 std::string categoryTemplate = CATEGORY_APPS_SEARCH;
201 if (query.empty()) {200 if (querystr.empty()) {
202 categoryTemplate = CATEGORY_APPS_DISPLAY;201 categoryTemplate = CATEGORY_APPS_DISPLAY;
203 }202 }
204 auto localResults = clickInterfaceInstance().find_installed_apps(203 auto localResults = clickInterfaceInstance().find_installed_apps(
205 query);204 querystr);
206205
207 push_local_results(206 push_local_results(
208 searchReply,207 searchReply,
209208
=== modified file 'scope/clickapps/apps-scope.cpp'
--- scope/clickapps/apps-scope.cpp 2014-06-12 14:26:26 +0000
+++ scope/clickapps/apps-scope.cpp 2014-06-18 18:08:01 +0000
@@ -54,13 +54,11 @@
54{54{
55}55}
5656
57int click::Scope::start(std::string const&, scopes::RegistryProxy const&)57void click::Scope::start(std::string const&, scopes::RegistryProxy const&)
58{58{
59 setlocale(LC_ALL, "");59 setlocale(LC_ALL, "");
60 bindtextdomain(GETTEXT_PACKAGE, GETTEXT_LOCALEDIR);60 bindtextdomain(GETTEXT_PACKAGE, GETTEXT_LOCALEDIR);
61 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");61 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
62
63 return VERSION;
64}62}
6563
66void click::Scope::run()64void click::Scope::run()
@@ -91,14 +89,15 @@
91}89}
9290
9391
94unity::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)92unity::scopes::ActivationQueryBase::UPtr click::Scope::perform_action(unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata,
93 std::string const& /* widget_id */, std::string const& action_id)
95{94{
96 if (action_id == click::Preview::Actions::CONFIRM_UNINSTALL) {95 if (action_id == click::Preview::Actions::CONFIRM_UNINSTALL) {
97 const unity::scopes::CannedQuery cquery("clickscope");96 const unity::scopes::CannedQuery cquery("clickscope");
98 return scopes::ActivationQueryBase::UPtr(new PerformUninstallAction(result, unity::scopes::ActivationResponse(cquery)));97 return scopes::ActivationQueryBase::UPtr(new PerformUninstallAction(result, metadata, unity::scopes::ActivationResponse(cquery)));
99 }98 }
10099
101 auto activation = new ScopeActivation();100 auto activation = new ScopeActivation(result, metadata);
102 qDebug() << "perform_action called with action_id" << QString().fromStdString(action_id);101 qDebug() << "perform_action called with action_id" << QString().fromStdString(action_id);
103102
104 if (action_id == click::Preview::Actions::UNINSTALL_CLICK) {103 if (action_id == click::Preview::Actions::UNINSTALL_CLICK) {
105104
=== modified file 'scope/clickapps/apps-scope.h'
--- scope/clickapps/apps-scope.h 2014-05-27 06:57:52 +0000
+++ scope/clickapps/apps-scope.h 2014-06-18 18:08:01 +0000
@@ -49,14 +49,14 @@
49 Scope();49 Scope();
50 ~Scope();50 ~Scope();
5151
52 virtual int start(std::string const&, scopes::RegistryProxy const&) override;52 virtual void start(std::string const&, scopes::RegistryProxy const&) override;
5353
54 virtual void run() override;54 virtual void run() override;
55 virtual void stop() override;55 virtual void stop() override;
5656
57 virtual scopes::SearchQueryBase::UPtr search(scopes::CannedQuery const& q, scopes::SearchMetadata const&) override;57 virtual scopes::SearchQueryBase::UPtr search(scopes::CannedQuery const& q, scopes::SearchMetadata const& metadata) override;
58 unity::scopes::PreviewQueryBase::UPtr preview(const unity::scopes::Result&,58 unity::scopes::PreviewQueryBase::UPtr preview(const unity::scopes::Result&,
59 const unity::scopes::ActionMetadata&) override;59 const unity::scopes::ActionMetadata& hints) override;
6060
61 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;61 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;
6262
6363
=== modified file 'scope/clickstore/store-query.cpp'
--- scope/clickstore/store-query.cpp 2014-06-13 23:18:41 +0000
+++ scope/clickstore/store-query.cpp 2014-06-18 18:08:01 +0000
@@ -30,6 +30,7 @@
30#include <click/application.h>30#include <click/application.h>
31#include <click/interface.h>31#include <click/interface.h>
32#include "store-query.h"32#include "store-query.h"
33#include "store-scope.h"
33#include <click/qtbridge.h>34#include <click/qtbridge.h>
3435
35#include <click/key_file_locator.h>36#include <click/key_file_locator.h>
@@ -37,6 +38,7 @@
37#include <unity/scopes/Annotation.h>38#include <unity/scopes/Annotation.h>
38#include <unity/scopes/CategoryRenderer.h>39#include <unity/scopes/CategoryRenderer.h>
39#include <unity/scopes/CategorisedResult.h>40#include <unity/scopes/CategorisedResult.h>
41#include <unity/scopes/Department.h>
40#include <unity/scopes/CannedQuery.h>42#include <unity/scopes/CannedQuery.h>
41#include <unity/scopes/SearchReply.h>43#include <unity/scopes/SearchReply.h>
42#include <unity/scopes/SearchMetadata.h>44#include <unity/scopes/SearchMetadata.h>
@@ -93,20 +95,26 @@
9395
94struct click::Query::Private96struct click::Query::Private
95{97{
96 Private(const unity::scopes::CannedQuery& query, click::Index& index, const scopes::SearchMetadata& metadata)98 Private(click::Index& index, click::DepartmentLookup& depts,
97 : query(query),99 click::HighlightList& highlights, const scopes::SearchMetadata& metadata)
98 index(index),100 : index(index),
101 department_lookup(depts),
102 highlights(highlights),
99 meta(metadata)103 meta(metadata)
100 {104 {
101 }105 }
102 unity::scopes::CannedQuery query;
103 click::Index& index;106 click::Index& index;
107 click::DepartmentLookup& department_lookup;
108 click::HighlightList& highlights;
104 scopes::SearchMetadata meta;109 scopes::SearchMetadata meta;
105 click::web::Cancellable search_operation;110 click::web::Cancellable search_operation;
106};111};
107112
108click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata)113click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, click::DepartmentLookup& depts,
109 : impl(new Private(query, index, metadata))114 click::HighlightList& highlights,
115 scopes::SearchMetadata const& metadata)
116 : unity::scopes::SearchQueryBase(query, metadata),
117 impl(new Private(index, depts, highlights, metadata))
110{118{
111}119}
112120
@@ -117,7 +125,7 @@
117125
118void click::Query::cancelled()126void click::Query::cancelled()
119{127{
120 qDebug() << "cancelling search of" << QString::fromStdString(impl->query.query_string());128 qDebug() << "cancelling search of" << QString::fromStdString(query().query_string());
121 impl->search_operation.cancel();129 impl->search_operation.cancel();
122}130}
123131
@@ -155,6 +163,166 @@
155 });163 });
156}164}
157165
166//
167// creates department menu with narrowed-down list of subdepartments of current department, as
168// returned by server call
169void click::Query::populate_departments(const click::DepartmentList& subdepts, const std::string& current_dep_id, unity::scopes::Department::SPtr &root)
170{
171 unity::scopes::DepartmentList departments;
172
173 // create a list of subdepartments of current department
174 foreach (auto d, subdepts)
175 {
176 unity::scopes::Department::SPtr department = unity::scopes::Department::create(d->id(), query(), d->name());
177 if (d->has_children_flag())
178 {
179 department->set_has_subdepartments();
180 }
181 departments.push_back(department);
182 }
183
184 if (current_dep_id != "")
185 {
186 auto curr_dpt = impl->department_lookup.get_department_info(current_dep_id);
187 if (curr_dpt != nullptr)
188 {
189 unity::scopes::Department::SPtr current = unity::scopes::Department::create(current_dep_id, query(), curr_dpt->name());
190 if (departments.size() > 0) // this may be a leaf department
191 {
192 current->set_subdepartments(departments);
193 }
194
195 auto parent_info = impl->department_lookup.get_parent(current_dep_id);
196 if (parent_info != nullptr)
197 {
198 root = unity::scopes::Department::create(parent_info->id(), query(), parent_info->name());
199 root->set_subdepartments({current});
200 return;
201 }
202 else
203 {
204 root = unity::scopes::Department::create("", query(), _("All departments"));
205 root->set_subdepartments({current});
206 return;
207 }
208 }
209 else
210 {
211 qWarning() << "Unknown department:" << QString::fromStdString(current_dep_id);
212 }
213 }
214
215 root = unity::scopes::Department::create("", query(), _("All departments"));
216 root->set_subdepartments(departments);
217}
218
219void click::Query::push_package(const scopes::SearchReplyProxy& searchReply, scopes::Category::SCPtr category, const PackageSet &installedPackages, const Package& pkg)
220{
221 qDebug() << "pushing result" << QString::fromStdString(pkg.name);
222 try {
223 scopes::CategorisedResult res(category);
224 res.set_title(pkg.title);
225 res.set_art(pkg.icon_url);
226 res.set_uri(pkg.url);
227 res[click::Query::ResultKeys::NAME] = pkg.name;
228 auto installed = installedPackages.find(pkg);
229 if (installed != installedPackages.end()) {
230 res[click::Query::ResultKeys::INSTALLED] = true;
231 res["subtitle"] = _("✔ INSTALLED");
232 res[click::Query::ResultKeys::VERSION] = installed->version;
233 } else {
234 res[click::Query::ResultKeys::INSTALLED] = false;
235 // TODO: get the real price from the webservice (upcoming branch)
236 res["subtitle"] = _("FREE");
237 }
238
239 this->push_result(searchReply, res);
240 } catch(const std::exception& e){
241 qDebug() << "PackageDetails::loadJson: Exception thrown while decoding JSON: " << e.what() ;
242 } catch(...){
243 qDebug() << "no reason to catch";
244 }
245}
246
247void click::Query::push_highlights(const scopes::SearchReplyProxy& searchReply, const HighlightList& highlights, const PackageSet &locallyInstalledApps)
248{
249 std::string categoryTemplate = CATEGORY_APPS_DISPLAY; //FIXME
250 scopes::CategoryRenderer renderer(categoryTemplate);
251
252 for (auto const& hl: highlights)
253 {
254 auto category = register_category(searchReply, hl.name(), hl.name(), "", renderer); //FIXME: highlight slug
255 for (auto const& pkg: hl.packages())
256 {
257 push_package(searchReply, category, locallyInstalledApps, pkg);
258 }
259 }
260 qDebug() << "Highlights pushed";
261}
262
263void click::Query::push_departments(const scopes::SearchReplyProxy& searchReply, const scopes::Department::SCPtr& root)
264{
265 if (root != nullptr)
266 {
267 try
268 {
269 qDebug() << "pushing departments";
270 searchReply->register_departments(root);
271 }
272 catch (const std::exception& e)
273 {
274 qWarning() << "Failed to register departments for query " << QString::fromStdString(query().query_string()) <<
275 ", current department " << QString::fromStdString(query().department_id()) << ": " << e.what();
276 }
277 }
278 else
279 {
280 qWarning() << "No departments data for query " << QString::fromStdString(query().query_string()) <<
281 "', current department " << QString::fromStdString(query().department_id());
282 }
283}
284
285//
286// push highlights and departments
287// use cached highlights for root department, otherwise run an async job for highlights of current department.
288void click::Query::add_highlights(scopes::SearchReplyProxy const& searchReply, const PackageSet& locallyInstalledApps)
289{
290 auto curdep = impl->department_lookup.get_department_info(query().department_id());
291 assert(curdep);
292 auto subdepts = curdep->sub_departments();
293 if (query().department_id() == "") // top-level departments
294 {
295 unity::scopes::Department::SPtr root;
296 populate_departments(subdepts, query().department_id(), root);
297 push_departments(searchReply, root);
298
299 qDebug() << "pushing cached highlights";
300 push_highlights(searchReply, impl->highlights, locallyInstalledApps);
301 this->finished(searchReply); //FIXME: this shouldn't be needed
302 }
303 else
304 {
305 qDebug() << "starting departments call for department" << QString::fromStdString(curdep->id()) << ", href" << QString::fromStdString(curdep->href());
306 impl->search_operation = impl->index.departments(curdep->href(), [this, locallyInstalledApps, searchReply](const DepartmentList& depts,
307 const HighlightList& highlights, Index::Error error)
308 {
309 if (error == click::Index::Error::NoError)
310 {
311 qDebug() << "departments call completed";
312 unity::scopes::Department::SPtr root;
313 populate_departments(depts, query().department_id(), root);
314 push_departments(searchReply, root);
315 push_highlights(searchReply, highlights, locallyInstalledApps);
316 }
317 else
318 {
319 qWarning() << "departments call failed";
320 }
321 this->finished(searchReply); //FIXME: this shouldn't be needed
322 });
323 }
324}
325
158void click::Query::add_available_apps(scopes::SearchReplyProxy const& searchReply,326void click::Query::add_available_apps(scopes::SearchReplyProxy const& searchReply,
159 const PackageSet& installedPackages,327 const PackageSet& installedPackages,
160 const std::string& categoryTemplate)328 const std::string& categoryTemplate)
@@ -162,12 +330,14 @@
162 scopes::CategoryRenderer categoryRenderer(categoryTemplate);330 scopes::CategoryRenderer categoryRenderer(categoryTemplate);
163 auto category = register_category(searchReply, "appstore", _("Available"), "", categoryRenderer);331 auto category = register_category(searchReply, "appstore", _("Available"), "", categoryRenderer);
164332
333 assert(searchReply);
334
165 run_under_qt([=]()335 run_under_qt([=]()
166 {336 {
167 auto search_cb = [this, searchReply, category, installedPackages](Packages packages) {337 auto search_cb = [this, searchReply, category, installedPackages](Packages packages, DepartmentList) {
168 qDebug("search callback");338 qDebug("search callback");
169339
170 // handle packages data340 // handle packages data; FIXME: use push_package()
171 foreach (auto p, packages) {341 foreach (auto p, packages) {
172 qDebug() << "pushing result" << QString::fromStdString(p.name);342 qDebug() << "pushing result" << QString::fromStdString(p.name);
173 try {343 try {
@@ -195,11 +365,58 @@
195 }365 }
196 }366 }
197 qDebug() << "search completed";367 qDebug() << "search completed";
198 this->finished(searchReply);368 this->finished(searchReply); //FIXME: this shouldn't be needed
199 };369 };
200370
201 qDebug() << "starting search of" << QString::fromStdString(impl->query.query_string());371 // this is the case when we do bootstrap for the first time, or it failed last time
202 impl->search_operation = impl->index.search(impl->query.query_string(), search_cb);372 if (impl->department_lookup.size() == 0 && !click::Scope::use_old_api())
373 {
374 qDebug() << "performing bootstrap request";
375 impl->search_operation = impl->index.bootstrap([this, search_cb, searchReply, installedPackages](const DepartmentList& deps, const
376 HighlightList& highlights, click::Index::Error error, int error_code) {
377 if (error == click::Index::Error::NoError)
378 {
379 qDebug() << "bootstrap request completed";
380 auto root = std::make_shared<click::Department>("", "All Departments", "", true);
381 root->set_subdepartments(deps);
382 DepartmentList rdeps { root };
383 impl->department_lookup.rebuild(rdeps);
384 impl->highlights = highlights;
385 qDebug() << "Total number of departments:" << impl->department_lookup.size() << ", highlights:" << highlights.size();
386 }
387 else
388 {
389 qWarning() << "bootstrap request failed";
390 if (error_code == 405) // method not allowed
391 {
392 qDebug() << "bootstrap not available, using old API";
393 click::Scope::set_use_old_api();
394 }
395 }
396
397 if (query().query_string().empty() && !click::Scope::use_old_api())
398 {
399 add_highlights(searchReply, installedPackages);
400 }
401 else
402 {
403 qDebug() << "starting search of" << QString::fromStdString(query().query_string());
404 impl->search_operation = impl->index.search(query().query_string(), query().department_id(), search_cb);
405 }
406 });
407 }
408 else
409 {
410 if (query().query_string().empty() && !click::Scope::use_old_api())
411 {
412 add_highlights(searchReply, installedPackages);
413 }
414 else // normal search
415 {
416 qDebug() << "starting search of" << QString::fromStdString(query().query_string());
417 impl->search_operation = impl->index.search(query().query_string(), query().department_id(), search_cb);
418 }
419 }
203 });420 });
204}421}
205422
@@ -222,9 +439,9 @@
222439
223void click::Query::run(scopes::SearchReplyProxy const& searchReply)440void click::Query::run(scopes::SearchReplyProxy const& searchReply)
224{441{
225 auto query = impl->query.query_string();442 auto q = query().query_string();
226 std::string categoryTemplate = CATEGORY_APPS_SEARCH;443 std::string categoryTemplate = CATEGORY_APPS_SEARCH;
227 if (query.empty()) {444 if (q.empty()) {
228 categoryTemplate = CATEGORY_APPS_DISPLAY;445 categoryTemplate = CATEGORY_APPS_DISPLAY;
229 }446 }
230447
231448
=== modified file 'scope/clickstore/store-query.h'
--- scope/clickstore/store-query.h 2014-06-16 14:09:21 +0000
+++ scope/clickstore/store-query.h 2014-06-18 18:08:01 +0000
@@ -32,10 +32,16 @@
3232
3333
34#include <unity/scopes/SearchQueryBase.h>34#include <unity/scopes/SearchQueryBase.h>
35#include <unity/scopes/Department.h>
3536
36namespace scopes = unity::scopes;37namespace scopes = unity::scopes;
3738
38#include <QSharedPointer>39#include <QSharedPointer>
40#include <set>
41
42#include <click/department-lookup.h>
43#include <click/package.h>
44#include <click/highlights.h>
39#include <click/interface.h>45#include <click/interface.h>
4046
41namespace click47namespace click
@@ -43,6 +49,7 @@
4349
44class Application;50class Application;
45class Index;51class Index;
52class DepartmentLookup;
4653
47class Query : public scopes::SearchQueryBase54class Query : public scopes::SearchQueryBase
48{55{
@@ -69,7 +76,8 @@
69 constexpr static const char* VERSION{"version"};76 constexpr static const char* VERSION{"version"};
70 };77 };
7178
72 Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata);79 Query(unity::scopes::CannedQuery const& query, click::Index& index, click::DepartmentLookup& dept_lookup, click::HighlightList& highlights,
80 scopes::SearchMetadata const& metadata);
73 virtual ~Query();81 virtual ~Query();
7482
75 virtual void cancelled() override;83 virtual void cancelled() override;
@@ -77,8 +85,10 @@
77 virtual void run(scopes::SearchReplyProxy const& reply) override;85 virtual void run(scopes::SearchReplyProxy const& reply) override;
7886
79protected:87protected:
80 virtual void add_available_apps(const scopes::SearchReplyProxy &searchReply,88 virtual void populate_departments(const click::DepartmentList& depts, const std::string& current_department_id, unity::scopes::Department::SPtr &root);
81 const PackageSet &installedPackages, const std::string &category);89 virtual void push_departments(const scopes::SearchReplyProxy& searchReply, const scopes::Department::SCPtr& root);
90 virtual void add_highlights(scopes::SearchReplyProxy const& searchReply, const PackageSet& installedPackages);
91 virtual void add_available_apps(const scopes::SearchReplyProxy &searchReply, const PackageSet &installedPackages, const std::string &category);
82 virtual click::Interface& clickInterfaceInstance();92 virtual click::Interface& clickInterfaceInstance();
83 virtual PackageSet get_installed_packages();93 virtual PackageSet get_installed_packages();
84 virtual bool push_result(const scopes::SearchReplyProxy &searchReply, scopes::CategorisedResult const& res);94 virtual bool push_result(const scopes::SearchReplyProxy &searchReply, scopes::CategorisedResult const& res);
@@ -88,6 +98,9 @@
88 std::string const& title,98 std::string const& title,
89 std::string const& icon,99 std::string const& icon,
90 scopes::CategoryRenderer const& renderer_template);100 scopes::CategoryRenderer const& renderer_template);
101 virtual void push_package(const scopes::SearchReplyProxy& searchReply, scopes::Category::SCPtr category, const PackageSet &locallyInstalledApps,
102 const click::Package& pkg);
103 virtual void push_highlights(const scopes::SearchReplyProxy& searchReply, const HighlightList& highlights, const PackageSet &locallyInstalledApps);
91 virtual void run_under_qt(const std::function<void()> &task);104 virtual void run_under_qt(const std::function<void()> &task);
92105
93private:106private:
94107
=== modified file 'scope/clickstore/store-scope.cpp'
--- scope/clickstore/store-scope.cpp 2014-06-17 21:32:44 +0000
+++ scope/clickstore/store-scope.cpp 2014-06-18 18:08:01 +0000
@@ -28,6 +28,7 @@
28 */28 */
2929
30#include <click/qtbridge.h>30#include <click/qtbridge.h>
31#include <click/department-lookup.h>
31#include "store-scope.h"32#include "store-scope.h"
32#include "store-query.h"33#include "store-query.h"
33#include <click/preview.h>34#include <click/preview.h>
@@ -42,27 +43,38 @@
4243
43#include <logging.h>44#include <logging.h>
4445
46bool click::Scope::old_api = false;
4547
46click::Scope::Scope()48click::Scope::Scope()
47{49{
48 nam.reset(new click::network::AccessManager());50 nam.reset(new click::network::AccessManager());
49 client.reset(new click::web::Client(nam));51 client.reset(new click::web::Client(nam));
50 index.reset(new click::Index(client));52 index.reset(new click::Index(client));
53 depts.reset(new click::DepartmentLookup());
54 highlights.reset(new click::HighlightList());
51}55}
5256
53click::Scope::~Scope()57click::Scope::~Scope()
54{58{
55}59}
5660
57int click::Scope::start(std::string const&, scopes::RegistryProxy const&)61void click::Scope::set_use_old_api()
62{
63 old_api = true;
64}
65
66bool click::Scope::use_old_api()
67{
68 return old_api;
69}
70
71void click::Scope::start(std::string const&, scopes::RegistryProxy const&)
58{72{
59 setlocale(LC_ALL, "");73 setlocale(LC_ALL, "");
60 // FIXME: This is wrong, but needed for json-cpp workaround.74 // FIXME: This is wrong, but needed for json-cpp workaround.
61 setlocale(LC_MONETARY, "C");75 setlocale(LC_MONETARY, "C");
62 bindtextdomain(GETTEXT_PACKAGE, GETTEXT_LOCALEDIR);76 bindtextdomain(GETTEXT_PACKAGE, GETTEXT_LOCALEDIR);
63 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");77 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
64
65 return VERSION;
66}78}
6779
68void click::Scope::run()80void click::Scope::run()
@@ -70,7 +82,6 @@
70 static const int zero = 0;82 static const int zero = 0;
71 auto emptyCb = [this]()83 auto emptyCb = [this]()
72 {84 {
73
74 };85 };
7586
76 qt::core::world::build_and_run(zero, nullptr, emptyCb);87 qt::core::world::build_and_run(zero, nullptr, emptyCb);
@@ -83,7 +94,7 @@
8394
84scopes::SearchQueryBase::UPtr click::Scope::search(unity::scopes::CannedQuery const& q, scopes::SearchMetadata const& metadata)95scopes::SearchQueryBase::UPtr click::Scope::search(unity::scopes::CannedQuery const& q, scopes::SearchMetadata const& metadata)
85{96{
86 return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, metadata));97 return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, *depts, *highlights, metadata));
87}98}
8899
89100
@@ -93,12 +104,21 @@
93 return scopes::PreviewQueryBase::UPtr{new click::Preview(result, metadata, client, nam)};104 return scopes::PreviewQueryBase::UPtr{new click::Preview(result, metadata, client, nam)};
94}105}
95106
107<<<<<<< TREE
96unity::scopes::ActivationQueryBase::UPtr click::Scope::perform_action(unity::scopes::Result const& /* result */, unity::scopes::ActionMetadata const& metadata,108unity::scopes::ActivationQueryBase::UPtr click::Scope::perform_action(unity::scopes::Result const& /* result */, unity::scopes::ActionMetadata const& metadata,
97 std::string const& widget_id, std::string const& _action_id)109 std::string const& widget_id, std::string const& _action_id)
110=======
111unity::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)
112>>>>>>> MERGE-SOURCE
98{113{
114<<<<<<< TREE
99 std::string action_id = _action_id;115 std::string action_id = _action_id;
100 auto activation = new ScopeActivation();116 auto activation = new ScopeActivation();
101 qDebug() << "perform_action called with widget_id" << QString::fromStdString(widget_id) << "and action_id:" << QString::fromStdString(action_id);117 qDebug() << "perform_action called with widget_id" << QString::fromStdString(widget_id) << "and action_id:" << QString::fromStdString(action_id);
118=======
119 auto activation = new ScopeActivation(result, metadata);
120 qDebug() << "perform_action called with action_id" << QString().fromStdString(action_id);
121>>>>>>> MERGE-SOURCE
102122
103 // if the purchase is completed, do the install123 // if the purchase is completed, do the install
104 if (action_id == "purchaseCompleted") {124 if (action_id == "purchaseCompleted") {
105125
=== modified file 'scope/clickstore/store-scope.h'
--- scope/clickstore/store-scope.h 2014-05-27 06:57:52 +0000
+++ scope/clickstore/store-scope.h 2014-06-18 18:08:01 +0000
@@ -30,6 +30,7 @@
30#ifndef CLICK_SCOPE_H30#ifndef CLICK_SCOPE_H
31#define CLICK_SCOPE_H31#define CLICK_SCOPE_H
3232
33#include <memory>
33#include <click/network_access_manager.h>34#include <click/network_access_manager.h>
34#include <click/webclient.h>35#include <click/webclient.h>
3536
@@ -43,29 +44,38 @@
4344
44namespace click45namespace click
45{46{
47
48class DepartmentLookup;
49
46class Scope : public scopes::ScopeBase50class Scope : public scopes::ScopeBase
47{51{
48public:52public:
49 Scope();53 Scope();
50 ~Scope();54 ~Scope();
5155
52 virtual int start(std::string const&, scopes::RegistryProxy const&) override;56 virtual void start(std::string const&, scopes::RegistryProxy const&) override;
5357
54 virtual void run() override;58 virtual void run() override;
55 virtual void stop() override;59 virtual void stop() override;
5660
57 virtual scopes::SearchQueryBase::UPtr search(scopes::CannedQuery const& q, scopes::SearchMetadata const&) override;61 virtual scopes::SearchQueryBase::UPtr search(scopes::CannedQuery const& q, scopes::SearchMetadata const& metadata) override;
58 unity::scopes::PreviewQueryBase::UPtr preview(const unity::scopes::Result&,62 unity::scopes::PreviewQueryBase::UPtr preview(const unity::scopes::Result&,
59 const unity::scopes::ActionMetadata&) override;63 const unity::scopes::ActionMetadata&) override;
6064
61 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;65 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;
6266
67 static void set_use_old_api();
68 static bool use_old_api();
69
63private:70private:
64 QSharedPointer<click::network::AccessManager> nam;71 QSharedPointer<click::network::AccessManager> nam;
65 QSharedPointer<click::web::Client> client;72 QSharedPointer<click::web::Client> client;
66 QSharedPointer<click::Index> index;73 QSharedPointer<click::Index> index;
74 std::shared_ptr<click::DepartmentLookup> depts;
75 std::shared_ptr<click::HighlightList> highlights;
6776
68 std::string installApplication(unity::scopes::Result const& result);77 std::string installApplication(unity::scopes::Result const& result);
78 static bool old_api;
69};79};
70}80}
71#endif // CLICK_SCOPE_H81#endif // CLICK_SCOPE_H
7282
=== modified file 'scope/tests/integration/webclient_integration.cpp'
--- scope/tests/integration/webclient_integration.cpp 2014-06-12 21:05:25 +0000
+++ scope/tests/integration/webclient_integration.cpp 2014-06-18 18:08:01 +0000
@@ -30,6 +30,7 @@
30#include <click/network_access_manager.h>30#include <click/network_access_manager.h>
31#include <click/webclient.h>31#include <click/webclient.h>
32#include <click/index.h>32#include <click/index.h>
33#include <click/departments.h>
3334
34#include <QCoreApplication>35#include <QCoreApplication>
35#include <QDebug>36#include <QDebug>
@@ -102,7 +103,8 @@
102 new click::web::Client(namPtr));103 new click::web::Client(namPtr));
103 click::Index index(clientPtr);104 click::Index index(clientPtr);
104 click::Packages packages;105 click::Packages packages;
105 index.search("qr,architecture:armhf", [&, this](click::Packages found_packages){106 index.search("qr,architecture:armhf", "", [&, this](click::Packages found_packages, click::DepartmentList){
107 //TODO departments
106 packages = found_packages;108 packages = found_packages;
107 Quit();109 Quit();
108 });110 });
109111
=== modified file 'scope/tests/test_query.cpp'
--- scope/tests/test_query.cpp 2014-06-12 22:17:42 +0000
+++ scope/tests/test_query.cpp 2014-06-18 18:08:01 +0000
@@ -45,6 +45,7 @@
45#include <unity/scopes/CannedQuery.h>45#include <unity/scopes/CannedQuery.h>
46#include <unity/scopes/ScopeBase.h>46#include <unity/scopes/ScopeBase.h>
47#include <unity/scopes/SearchReply.h>47#include <unity/scopes/SearchReply.h>
48#include <unity/scopes/testing/MockSearchReply.h>
4849
49using namespace ::testing;50using namespace ::testing;
50using namespace click;51using namespace click;
@@ -57,30 +58,45 @@
5758
58class MockIndex : public click::Index {59class MockIndex : public click::Index {
59 click::Packages packages;60 click::Packages packages;
61 click::DepartmentList departments;
62 click::DepartmentList bootstrap_departments;
63 click::HighlightList bootstrap_highlights;
60public:64public:
61 MockIndex(click::Packages packages = click::Packages())65 MockIndex(click::Packages packages = click::Packages(),
66 click::DepartmentList departments = click::DepartmentList(),
67 click::DepartmentList boot_departments = click::DepartmentList())
62 : Index(QSharedPointer<click::web::Client>()),68 : Index(QSharedPointer<click::web::Client>()),
63 packages(packages)69 packages(packages),
64 {70 departments(departments),
6571 bootstrap_departments(boot_departments)
66 }72 {
6773
68 click::web::Cancellable search(const std::string &query, std::function<void (click::Packages)> callback) override74 }
69 {75
70 do_search(query, callback);76 click::web::Cancellable search(const std::string &query, const std::string& department, std::function<void (click::Packages, click::DepartmentList)> callback) override
71 callback(packages);77 {
72 return click::web::Cancellable();78 do_search(query, department, callback);
73 }79 callback(packages, departments);
7480 return click::web::Cancellable();
75 MOCK_METHOD2(do_search,81 }
76 void(const std::string&,82
77 std::function<void(click::Packages)>));83 click::web::Cancellable bootstrap(std::function<void(const click::DepartmentList&, const click::HighlightList&, Error, int)> callback) override
84 {
85 callback(bootstrap_departments, bootstrap_highlights, click::Index::Error::NoError, 0);
86 return click::web::Cancellable();
87 }
88
89 MOCK_METHOD3(do_search,
90 void(const std::string&, const std::string&,
91 std::function<void(click::Packages, click::DepartmentList)>));
78};92};
7993
80class MockQueryBase : public click::Query {94class MockQueryBase : public click::Query {
81public:95public:
82 MockQueryBase(const unity::scopes::CannedQuery& query, click::Index& index,96 MockQueryBase(const unity::scopes::CannedQuery& query, click::Index& index,
83 scopes::SearchMetadata const& metadata) : click::Query(query, index, metadata)97 click::DepartmentLookup& depts,
98 click::HighlightList& highlights,
99 scopes::SearchMetadata const& metadata) : click::Query(query, index, depts, highlights, metadata)
84 {100 {
85101
86 }102 }
@@ -94,7 +110,9 @@
94class MockQuery : public MockQueryBase {110class MockQuery : public MockQueryBase {
95public:111public:
96 MockQuery(const unity::scopes::CannedQuery& query, click::Index& index,112 MockQuery(const unity::scopes::CannedQuery& query, click::Index& index,
97 scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, metadata)113 click::DepartmentLookup& depts,
114 click::HighlightList& highlights,
115 scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, highlights, metadata)
98 {116 {
99117
100 }118 }
@@ -118,7 +136,9 @@
118class MockQueryRun : public MockQueryBase {136class MockQueryRun : public MockQueryBase {
119public:137public:
120 MockQueryRun(const unity::scopes::CannedQuery& query, click::Index& index,138 MockQueryRun(const unity::scopes::CannedQuery& query, click::Index& index,
121 scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, metadata)139 click::DepartmentLookup& depts,
140 click::HighlightList& highlights,
141 scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, highlights, metadata)
122 {142 {
123143
124 }144 }
@@ -147,12 +167,16 @@
147TEST(QueryTest, testAddAvailableAppsCallsClickIndex)167TEST(QueryTest, testAddAvailableAppsCallsClickIndex)
148{168{
149 MockIndex mock_index;169 MockIndex mock_index;
170 click::DepartmentLookup dept_lookup;
171 click::HighlightList highlights;
150 scopes::SearchMetadata metadata("en_EN", "phone");172 scopes::SearchMetadata metadata("en_EN", "phone");
151 PackageSet no_installed_packages;173 PackageSet no_installed_packages;
152 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");174 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
153 MockQuery q(query, mock_index, metadata);175 MockQuery q(query, mock_index, dept_lookup, highlights, metadata);
154 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(1);176 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _)).Times(1);
155 scopes::SearchReplyProxy reply;177
178 scopes::testing::MockSearchReply mock_reply;
179 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
156180
157 scopes::CategoryRenderer renderer("{}");181 scopes::CategoryRenderer renderer("{}");
158 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);182 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
@@ -166,17 +190,21 @@
166 {"name", "title", 0.0, "icon", "uri"}190 {"name", "title", 0.0, "icon", "uri"}
167 };191 };
168 MockIndex mock_index(packages);192 MockIndex mock_index(packages);
193 click::DepartmentLookup dept_lookup;
194 click::HighlightList highlights;
169 scopes::SearchMetadata metadata("en_EN", "phone");195 scopes::SearchMetadata metadata("en_EN", "phone");
170 PackageSet no_installed_packages;196 PackageSet no_installed_packages;
171 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");197 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
172 MockQuery q(query, mock_index, metadata);198 MockQuery q(query, mock_index, dept_lookup, highlights, metadata);
173 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));199 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _));
174200
175 scopes::CategoryRenderer renderer("{}");201 scopes::CategoryRenderer renderer("{}");
176 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);202 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
177 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));203 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
178204
179 scopes::SearchReplyProxy reply;205 scopes::testing::MockSearchReply mock_reply;
206 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
207
180 auto expected_title = packages.front().title;208 auto expected_title = packages.front().title;
181 EXPECT_CALL(q, push_result(_, Property(&scopes::CategorisedResult::title, expected_title)));209 EXPECT_CALL(q, push_result(_, Property(&scopes::CategorisedResult::title, expected_title)));
182 q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE);210 q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE);
@@ -188,17 +216,20 @@
188 {"name", "title", 0.0, "icon", "uri"}216 {"name", "title", 0.0, "icon", "uri"}
189 };217 };
190 MockIndex mock_index(packages);218 MockIndex mock_index(packages);
219 click::DepartmentLookup dept_lookup;
220 click::HighlightList highlights;
191 scopes::SearchMetadata metadata("en_EN", "phone");221 scopes::SearchMetadata metadata("en_EN", "phone");
192 PackageSet no_installed_packages;222 PackageSet no_installed_packages;
193 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");223 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
194 MockQuery q(query, mock_index, metadata);224 MockQuery q(query, mock_index, dept_lookup, highlights, metadata);
195 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));225 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _));
196226
197 scopes::CategoryRenderer renderer("{}");227 scopes::CategoryRenderer renderer("{}");
198 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);228 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
199 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));229 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
200230
201 scopes::SearchReplyProxy reply;231 scopes::testing::MockSearchReply mock_reply;
232 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
202 EXPECT_CALL(q, finished(_));233 EXPECT_CALL(q, finished(_));
203 q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE);234 q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE);
204}235}
@@ -209,10 +240,12 @@
209 {"name", "title", 0.0, "icon", "uri"}240 {"name", "title", 0.0, "icon", "uri"}
210 };241 };
211 MockIndex mock_index(packages);242 MockIndex mock_index(packages);
243 click::DepartmentLookup dept_lookup;
244 click::HighlightList highlights;
212 scopes::SearchMetadata metadata("en_EN", "phone");245 scopes::SearchMetadata metadata("en_EN", "phone");
213 PackageSet no_installed_packages;246 PackageSet no_installed_packages;
214 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");247 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
215 MockQueryRun q(query, mock_index, metadata);248 MockQueryRun q(query, mock_index, dept_lookup, highlights, metadata);
216 auto reply = scopes::SearchReplyProxy();249 auto reply = scopes::SearchReplyProxy();
217 EXPECT_CALL(q, get_installed_packages()).WillOnce(Return(no_installed_packages));250 EXPECT_CALL(q, get_installed_packages()).WillOnce(Return(no_installed_packages));
218 EXPECT_CALL(q, add_available_apps(reply, no_installed_packages, _));251 EXPECT_CALL(q, add_available_apps(reply, no_installed_packages, _));
@@ -234,15 +267,18 @@
234 PackageSet one_installed_package {267 PackageSet one_installed_package {
235 {"org.example.app2", "0.2"}268 {"org.example.app2", "0.2"}
236 };269 };
270 click::DepartmentLookup dept_lookup;
271 click::HighlightList highlights;
237 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");272 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
238 MockQuery q(query, mock_index, metadata);273 MockQuery q(query, mock_index, dept_lookup, highlights, metadata);
239 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));274 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _));
240275
241 scopes::CategoryRenderer renderer("{}");276 scopes::CategoryRenderer renderer("{}");
242 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);277 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
243 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));278 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
244279
245 scopes::SearchReplyProxy reply;280 scopes::testing::MockSearchReply mock_reply;
281 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
246 auto expected_name1 = packages.front().name;282 auto expected_name1 = packages.front().name;
247 EXPECT_CALL(q, push_result(_, HasPackageName(expected_name1)));283 EXPECT_CALL(q, push_result(_, HasPackageName(expected_name1)));
248 auto expected_name2 = packages.back().name;284 auto expected_name2 = packages.back().name;
@@ -261,15 +297,18 @@
261 PackageSet one_installed_package {297 PackageSet one_installed_package {
262 {"org.example.app2", "0.2"}298 {"org.example.app2", "0.2"}
263 };299 };
300 click::DepartmentLookup dept_lookup;
301 click::HighlightList highlights;
264 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");302 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
265 MockQuery q(query, mock_index, metadata);303 MockQuery q(query, mock_index, dept_lookup, highlights, metadata);
266 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));304 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _));
267305
268 scopes::CategoryRenderer renderer("{}");306 scopes::CategoryRenderer renderer("{}");
269 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);307 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
270 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));308 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
271309
272 scopes::SearchReplyProxy reply;310 scopes::testing::MockSearchReply mock_reply;
311 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
273 EXPECT_CALL(q, push_result(_, IsInstalled(true)));312 EXPECT_CALL(q, push_result(_, IsInstalled(true)));
274 EXPECT_CALL(q, push_result(_, IsInstalled(false)));313 EXPECT_CALL(q, push_result(_, IsInstalled(false)));
275 q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE);314 q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE);
@@ -288,8 +327,10 @@
288 };327 };
289 MockIndex mock_index(uninstalled_packages);328 MockIndex mock_index(uninstalled_packages);
290 scopes::SearchMetadata metadata("en_EN", "phone");329 scopes::SearchMetadata metadata("en_EN", "phone");
330 click::DepartmentLookup dept_lookup;
331 click::HighlightList highlights;
291 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");332 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
292 MockQuery q(query, mock_index, metadata);333 MockQuery q(query, mock_index, dept_lookup, highlights, metadata);
293 PackageSet installed_packages{{"package_1", "0.1"}};334 PackageSet installed_packages{{"package_1", "0.1"}};
294335
295 FakeInterface fake_interface;336 FakeInterface fake_interface;

Subscribers

People subscribed via source and target branches

to all changes: