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

Proposed by Paweł Stołowski
Status: Merged
Approved by: Ted Gould
Approved revision: 401
Merged at revision: 407
Proposed branch: lp:~stolowski/unity-scope-click/no-empty-departments
Merge into: lp:unity-scope-click/devel
Diff against target: 517 lines (+217/-34)
9 files modified
libclickscope/click/application.h (+5/-2)
libclickscope/click/departments-db.cpp (+60/-4)
libclickscope/click/departments-db.h (+7/-1)
libclickscope/click/interface.cpp (+32/-5)
libclickscope/tests/test_departments-db.cpp (+34/-2)
scope/clickapps/apps-query.cpp (+55/-13)
scope/clickapps/apps-query.h (+1/-1)
scope/tests/test_apps_query.cpp (+21/-6)
scope/tests/test_helpers.h (+2/-0)
To merge this branch: bzr merge lp:~stolowski/unity-scope-click/no-empty-departments
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Ted Gould (community) Approve
dobey (community) Approve
Review via email: mp+230077@code.launchpad.net

Commit message

Exclude empty departments from the departments tree in Apps.

Description of the change

Exclude empty departments from the departments tree in Apps.

When building and filtering the list of installed apps in find_installed_apps, set a real_department attribute of every app. That attribute is later used when populating departments to create a helper lookup of all non-empty subdepartments of current department.

Note: due to a bug in shell plugin https://bugs.launchpad.net/unity-scopes-shell/+bug/1354362 department doesn't disappear when scopes stops returning it (so, after removing last application from a department, an emmpty department stays until reboot).

To post a comment you must log in.
398. By Paweł Stołowski

Minor test updates.

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

Make methods virtual.

400. By Paweł Stołowski

Enhance the test to use an app that is deeper in the departments hierarchy.

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

Merged devel.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
dobey (dobey) :
review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Ted Gould (ted) wrote :

Minor comment. Not sure I understand the SQL but as a backup reviewer it should be fine.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libclickscope/click/application.h'
2--- libclickscope/click/application.h 2014-07-18 10:35:52 +0000
3+++ libclickscope/click/application.h 2014-08-12 10:55:35 +0000
4@@ -43,11 +43,13 @@
5 std::string url,
6 std::string description,
7 std::string main_screenshot,
8- std::string default_department
9+ std::string default_department,
10+ std::string real_department = ""
11 ) : Package {name, title, price, icon_url, url},
12 description(description),
13 main_screenshot(main_screenshot),
14- default_department(default_department)
15+ default_department(default_department),
16+ real_department(real_department)
17 {
18
19 }
20@@ -58,6 +60,7 @@
21 std::vector<std::string> keywords;
22 std::string main_screenshot;
23 std::string default_department;
24+ std::string real_department;
25 time_t installed_time;
26 };
27
28
29=== modified file 'libclickscope/click/departments-db.cpp'
30--- libclickscope/click/departments-db.cpp 2014-08-05 14:16:26 +0000
31+++ libclickscope/click/departments-db.cpp 2014-08-12 10:55:35 +0000
32@@ -81,11 +81,14 @@
33 insert_dept_id_query_.reset(new QSqlQuery(db_));
34 insert_dept_name_query_.reset(new QSqlQuery(db_));
35 select_pkgs_by_dept_.reset(new QSqlQuery(db_));
36+ select_dept_for_pkg_.reset(new QSqlQuery(db_));
37 select_pkg_by_pkgid_.reset(new QSqlQuery(db_));
38 select_pkgs_by_dept_recursive_.reset(new QSqlQuery(db_));
39+ select_pkgs_count_in_dept_recursive_.reset(new QSqlQuery(db_));
40 select_parent_dept_.reset(new QSqlQuery(db_));
41 select_children_depts_.reset(new QSqlQuery(db_));
42 select_dept_name_.reset(new QSqlQuery(db_));
43+ select_is_descendant_of_dept_.reset(new QSqlQuery(db_));
44
45 delete_pkgmap_query_->prepare("DELETE FROM pkgmap WHERE pkgid=:pkgid");
46 delete_depts_query_->prepare("DELETE FROM depts");
47@@ -94,11 +97,14 @@
48 insert_dept_id_query_->prepare("INSERT OR REPLACE INTO depts (deptid, parentid) VALUES (:deptid, :parentid)");
49 insert_dept_name_query_->prepare("INSERT OR REPLACE INTO deptnames (deptid, locale, name) VALUES (:deptid, :locale, :name)");
50 select_pkgs_by_dept_->prepare("SELECT pkgid FROM pkgmap WHERE deptid=:deptid");
51- select_pkgs_by_dept_recursive_->prepare("WITH RECURSIVE recdepts(deptid) AS (SELECT deptid FROM depts WHERE deptid=:deptid UNION SELECT depts.deptid FROM recdepts,depts WHERE recdepts.deptid=depts.parentid) SELECT pkgid FROM pkgmap NATURAL JOIN recdepts");
52+ select_pkgs_by_dept_recursive_->prepare("WITH RECURSIVE recdepts(deptid) AS (SELECT deptid FROM depts WHERE deptid=:deptid OR parentid=:deptid UNION SELECT depts.deptid FROM recdepts,depts WHERE recdepts.deptid=depts.parentid) SELECT pkgid FROM pkgmap NATURAL JOIN recdepts");
53+ select_dept_for_pkg_->prepare("SELECT deptid from pkgmap WHERE pkgid=:pkgid");
54+ select_pkgs_count_in_dept_recursive_->prepare("WITH RECURSIVE recdepts(deptid) AS (SELECT deptid FROM depts WHERE deptid=:deptid OR parentid=:deptid UNION SELECT depts.deptid FROM recdepts,depts WHERE recdepts.deptid=depts.parentid) SELECT COUNT(pkgid) FROM pkgmap NATURAL JOIN recdepts");
55 select_pkg_by_pkgid_->prepare("SELECT pkgid FROM pkgmap WHERE pkgid=:pkgid");
56 select_children_depts_->prepare("SELECT deptid,(SELECT COUNT(1) from depts AS inner WHERE inner.parentid=outer.deptid) FROM depts AS outer WHERE parentid=:parentid");
57 select_parent_dept_->prepare("SELECT parentid FROM depts WHERE deptid=:deptid");
58 select_dept_name_->prepare("SELECT name FROM deptnames WHERE deptid=:deptid AND locale=:locale");
59+ select_is_descendant_of_dept_->prepare("WITH RECURSIVE recdepts(deptid) AS (SELECT deptid FROM depts WHERE parentid=:parentid UNION SELECT depts.deptid FROM recdepts,depts WHERE recdepts.deptid=depts.parentid) SELECT COUNT(1) FROM recdepts WHERE deptid=:deptid");
60 }
61
62 DepartmentsDb::~DepartmentsDb()
63@@ -205,7 +211,6 @@
64
65 std::list<DepartmentsDb::DepartmentInfo> DepartmentsDb::get_children_departments(const std::string& department_id)
66 {
67- // FIXME: this should only return departments that have results, and set 'has_children' flag on the same basis.
68 select_children_depts_->bindValue(":parentid", QVariant(QString::fromStdString(department_id)));
69 if (!select_children_depts_->exec())
70 {
71@@ -215,14 +220,47 @@
72 std::list<DepartmentInfo> depts;
73 while (select_children_depts_->next())
74 {
75- const DepartmentInfo inf(select_children_depts_->value(0).toString().toStdString(), select_children_depts_->value(1).toBool());
76- depts.push_back(inf);
77+ auto const child_id = select_children_depts_->value(0).toString().toStdString();
78+ // only return child department if it's not empty
79+ if (!is_empty(child_id))
80+ {
81+ const DepartmentInfo inf(child_id, select_children_depts_->value(1).toBool());
82+ depts.push_back(inf);
83+ }
84 }
85
86 select_children_depts_->finish();
87+
88 return depts;
89 }
90
91+bool DepartmentsDb::is_descendant_of_department(const std::string& department_id, const std::string& parent_department_id)
92+{
93+ select_is_descendant_of_dept_->bindValue(":deptid", QVariant(QString::fromStdString(department_id)));
94+ select_is_descendant_of_dept_->bindValue(":parentid", QVariant(QString::fromStdString(parent_department_id)));
95+
96+ if (!select_is_descendant_of_dept_->exec() || !select_is_descendant_of_dept_->next())
97+ {
98+ report_db_error(select_is_descendant_of_dept_->lastError(), "Failed to query for package count of department " + department_id);
99+ }
100+ auto cnt = select_is_descendant_of_dept_->value(0).toInt();
101+ select_is_descendant_of_dept_->finish();
102+
103+ return cnt > 0;
104+}
105+
106+bool DepartmentsDb::is_empty(const std::string& department_id)
107+{
108+ select_pkgs_count_in_dept_recursive_->bindValue(":deptid", QVariant(QString::fromStdString(department_id)));
109+ if (!select_pkgs_count_in_dept_recursive_->exec() || !select_pkgs_count_in_dept_recursive_->next())
110+ {
111+ report_db_error(select_pkgs_count_in_dept_recursive_->lastError(), "Failed to query for package count of department " + department_id);
112+ }
113+ auto cnt = select_pkgs_count_in_dept_recursive_->value(0).toInt();
114+ select_pkgs_count_in_dept_recursive_->finish();
115+ return cnt == 0;
116+}
117+
118 std::unordered_set<std::string> DepartmentsDb::get_packages_for_department(const std::string& department_id, bool recursive)
119 {
120 std::unordered_set<std::string> pkgs;
121@@ -240,6 +278,24 @@
122 return pkgs;
123 }
124
125+std::string DepartmentsDb::get_department_for_package(const std::string& package_id)
126+{
127+ select_dept_for_pkg_->bindValue(":pkgid", QVariant(QString::fromStdString(package_id)));
128+ if (!select_dept_for_pkg_->exec())
129+ {
130+ report_db_error(select_dept_for_pkg_->lastError(), "Failed to query for department of package " + package_id);
131+ }
132+ if (!select_dept_for_pkg_->next())
133+ {
134+ select_dept_for_pkg_->finish();
135+ throw std::logic_error("Unknown package '" + package_id + "'");
136+ }
137+ auto const res = select_dept_for_pkg_->value(0).toString().toStdString();
138+ select_dept_for_pkg_->finish();
139+ return res;
140+
141+}
142+
143 bool DepartmentsDb::has_package(const std::string& package_id)
144 {
145 select_pkg_by_pkgid_->bindValue(":pkgid", QVariant(QString::fromStdString(package_id)));
146
147=== modified file 'libclickscope/click/departments-db.h'
148--- libclickscope/click/departments-db.h 2014-07-22 20:07:28 +0000
149+++ libclickscope/click/departments-db.h 2014-08-12 10:55:35 +0000
150@@ -66,9 +66,12 @@
151
152 virtual std::string get_department_name(const std::string& department_id, const std::list<std::string>& locales);
153 virtual std::unordered_set<std::string> get_packages_for_department(const std::string& department_id, bool recursive = true);
154+ virtual std::string get_department_for_package(const std::string& package_id);
155+ virtual bool is_empty(const std::string& department_id);
156 virtual bool has_package(const std::string& package_id);
157 virtual std::string get_parent_department_id(const std::string& department_id);
158 virtual std::list<DepartmentInfo> get_children_departments(const std::string& department_id);
159+ virtual bool is_descendant_of_department(const std::string& department_id, const std::string& parent_department_id);
160
161 virtual void store_package_mapping(const std::string& package_id, const std::string& department_id);
162 virtual void store_department_mapping(const std::string& department_id, const std::string& parent_department_id);
163@@ -79,7 +82,7 @@
164 virtual int package_count() const;
165 virtual int department_name_count() const;
166
167- void store_departments(const click::DepartmentList& depts, const std::string& locale);
168+ virtual void store_departments(const click::DepartmentList& depts, const std::string& locale);
169
170 static std::unique_ptr<DepartmentsDb> open(bool create = true);
171
172@@ -96,11 +99,14 @@
173 std::unique_ptr<QSqlQuery> insert_dept_id_query_;
174 std::unique_ptr<QSqlQuery> insert_dept_name_query_;
175 std::unique_ptr<QSqlQuery> select_pkgs_by_dept_;
176+ std::unique_ptr<QSqlQuery> select_dept_for_pkg_;
177 std::unique_ptr<QSqlQuery> select_pkg_by_pkgid_;
178 std::unique_ptr<QSqlQuery> select_pkgs_by_dept_recursive_;
179+ std::unique_ptr<QSqlQuery> select_pkgs_count_in_dept_recursive_;
180 std::unique_ptr<QSqlQuery> select_parent_dept_;
181 std::unique_ptr<QSqlQuery> select_children_depts_;
182 std::unique_ptr<QSqlQuery> select_dept_name_;
183+ std::unique_ptr<QSqlQuery> select_is_descendant_of_dept_;
184 };
185
186 }
187
188=== modified file 'libclickscope/click/interface.cpp'
189--- libclickscope/click/interface.cpp 2014-07-23 16:22:19 +0000
190+++ libclickscope/click/interface.cpp 2014-08-12 10:55:35 +0000
191@@ -277,12 +277,13 @@
192 || Interface::is_non_click_app(QString::fromStdString(filename))) {
193 auto app = load_app_from_desktop(keyFile, filename);
194
195+ // app from click package has non-empty name; for non-click apps use desktop filename
196+ const std::string department_key = app.name.empty() ? filename : app.name;
197+
198 // check if apps is present in current department
199 if (apply_department_filter)
200 {
201- // app from click package has non-empty name; for non-click apps use desktop filename
202- const std::string key = app.name.empty() ? filename : app.name;
203- if (packages_in_department.find(key) == packages_in_department.end())
204+ if (packages_in_department.find(department_key) == packages_in_department.end())
205 {
206 if (app.default_department.empty())
207 {
208@@ -293,7 +294,7 @@
209 {
210 // default department not empty: check if this app is in a different
211 // department in the db (i.e. got moved from the default department);
212- if (depts_db->has_package(key))
213+ if (depts_db->has_package(department_key))
214 {
215 // app is now in a different department
216 return;
217@@ -303,12 +304,38 @@
218 {
219 return;
220 }
221-
222 // else - this package is in current department
223 }
224 }
225 }
226
227+ //
228+ // the packages_in_department set contains packages from
229+ // all its subdepartments; we need to find actual department now
230+ // to update app.real_department.
231+ if (depts_db)
232+ {
233+ if (depts_db->has_package(department_key))
234+ {
235+ try
236+ {
237+ app.real_department = depts_db->get_department_for_package(department_key);
238+ }
239+ catch (const std::exception &e)
240+ {
241+ qWarning() << "Failed to get department of package:" << QString::fromStdString(department_key);
242+ }
243+ }
244+ else
245+ {
246+ app.real_department = app.default_department;
247+ if (app.real_department.empty())
248+ {
249+ qWarning() << "No default department set in the .desktop file and no entry in the database for" << QString::fromStdString(department_key);
250+ }
251+ }
252+ }
253+
254 if (search_query.empty()) {
255 result.push_back(app);
256 } else {
257
258=== modified file 'libclickscope/tests/test_departments-db.cpp'
259--- libclickscope/tests/test_departments-db.cpp 2014-08-05 14:16:26 +0000
260+++ libclickscope/tests/test_departments-db.cpp 2014-08-12 10:55:35 +0000
261@@ -53,10 +53,13 @@
262 EXPECT_FALSE(insert_dept_name_query_->isActive());
263 EXPECT_FALSE(select_pkgs_by_dept_->isActive());
264 EXPECT_FALSE(select_pkgs_by_dept_recursive_->isActive());
265+ EXPECT_FALSE(select_dept_for_pkg_->isActive());
266+ EXPECT_FALSE(select_pkgs_count_in_dept_recursive_->isActive());
267 EXPECT_FALSE(select_pkg_by_pkgid_->isActive());
268 EXPECT_FALSE(select_parent_dept_->isActive());
269 EXPECT_FALSE(select_children_depts_->isActive());
270 EXPECT_FALSE(select_dept_name_->isActive());
271+ EXPECT_FALSE(select_is_descendant_of_dept_->isActive());
272 }
273 };
274
275@@ -112,6 +115,35 @@
276 }
277 }
278
279+TEST_F(DepartmentsDbTest, testDepartmentForPackageLookup)
280+{
281+ EXPECT_EQ("rpg", db->get_department_for_package("game1"));
282+ EXPECT_EQ("fps", db->get_department_for_package("game2"));
283+ EXPECT_EQ("office", db->get_department_for_package("app2"));
284+ EXPECT_EQ("tools", db->get_department_for_package("app1"));
285+ EXPECT_THROW(db->get_department_for_package("foobar"), std::logic_error);
286+}
287+
288+TEST_F(DepartmentsDbTest, testIsDepartmentEmpty)
289+{
290+ EXPECT_TRUE(db->is_empty("card"));
291+ EXPECT_FALSE(db->is_empty(""));
292+ EXPECT_FALSE(db->is_empty("games"));
293+ EXPECT_FALSE(db->is_empty("office"));
294+ EXPECT_FALSE(db->is_empty("tools"));
295+}
296+
297+TEST_F(DepartmentsDbTest, testIsDescendantOfDepartment)
298+{
299+ EXPECT_TRUE(db->is_descendant_of_department("rpg", "games"));
300+ EXPECT_TRUE(db->is_descendant_of_department("office", "tools"));
301+ EXPECT_TRUE(db->is_descendant_of_department("office", ""));
302+ EXPECT_TRUE(db->is_descendant_of_department("rpg", ""));
303+ EXPECT_TRUE(db->is_descendant_of_department("games", ""));
304+ EXPECT_FALSE(db->is_descendant_of_department("games", "office"));
305+ EXPECT_FALSE(db->is_descendant_of_department("", "games"));
306+}
307+
308 TEST_F(DepartmentsDbTest, testDepartmentNameUpdates)
309 {
310 {
311@@ -156,10 +188,10 @@
312 }
313 {
314 auto depts = db->get_children_departments("games");
315- EXPECT_EQ(3u, depts.size());
316+ EXPECT_EQ(2u, depts.size());
317 EXPECT_TRUE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("rpg", false)) != depts.end());
318 EXPECT_TRUE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("fps", false)) != depts.end());
319- EXPECT_TRUE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("card", false)) != depts.end());
320+ EXPECT_FALSE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("card", false)) != depts.end());
321 }
322 }
323
324
325=== modified file 'scope/clickapps/apps-query.cpp'
326--- scope/clickapps/apps-query.cpp 2014-08-06 17:30:55 +0000
327+++ scope/clickapps/apps-query.cpp 2014-08-12 10:55:35 +0000
328@@ -291,11 +291,22 @@
329 searchReply->push(res);
330 }
331
332-void click::apps::Query::push_local_departments(scopes::SearchReplyProxy const& replyProxy)
333+void click::apps::Query::push_local_departments(scopes::SearchReplyProxy const& replyProxy, const std::vector<Application>& apps)
334 {
335 auto const current_dep_id = query().department_id();
336 const std::list<std::string> locales = { search_metadata().locale(), "en_US" };
337
338+ //
339+ // create helper lookup of all departments of currently installed apps.
340+ // note that apps that are passed here are supposed to be already filterd by current department
341+ // that means we only have subdepartments of current department (or subdepartment(s) of subdepartment(s)
342+ // and so on of current department, as the hierarchy may be of arbitrary depth.
343+ std::unordered_set<std::string> all_subdepartments;
344+ for (auto const app: apps)
345+ {
346+ all_subdepartments.insert(app.real_department);
347+ }
348+
349 unity::scopes::Department::SPtr root;
350
351 try
352@@ -309,17 +320,48 @@
353 // attach subdepartments to it
354 for (auto const& subdep: impl->depts_db->get_children_departments(current_dep_id))
355 {
356- // if single supdepartment fails, then ignore it and continue with others
357- try
358- {
359- name = impl->depts_db->get_department_name(subdep.id, locales);
360- unity::scopes::Department::SPtr dep = unity::scopes::Department::create(subdep.id, query(), name);
361- dep->set_has_subdepartments(subdep.has_children);
362- current->add_subdepartment(dep);
363- }
364- catch (const std::exception &e)
365- {
366- qWarning() << "Failed to create subdeparment:" << QString::fromStdString(e.what());
367+ //
368+ // check if this subdepartment either directly matches a subdepartment of installed app,
369+ // or is any of the departments of installed apps is a descendant of current subdepartment.
370+ // the latter means we have app somewhere in the subtree of the current subdepartment, so it
371+ // needs to be shown.
372+ bool show_subdepartment = false;
373+ auto it = all_subdepartments.find(subdep.id);
374+ if (it != all_subdepartments.end())
375+ {
376+ // subdepartment id matches directly one of the ids from all_subdepartments
377+ show_subdepartment = true;
378+ all_subdepartments.erase(it);
379+ }
380+ else
381+ {
382+ // no direct match - we need to check descendants of this subdepartment
383+ // by querying the db
384+ for (auto it = all_subdepartments.begin(); it != all_subdepartments.end(); it++)
385+ {
386+ if (impl->depts_db->is_descendant_of_department(*it, subdep.id))
387+ {
388+ show_subdepartment = true;
389+ all_subdepartments.erase(it);
390+ break;
391+ }
392+ }
393+ }
394+
395+ if (show_subdepartment)
396+ {
397+ // if single supdepartment fails, then ignore it and continue with others
398+ try
399+ {
400+ name = impl->depts_db->get_department_name(subdep.id, locales);
401+ unity::scopes::Department::SPtr dep = unity::scopes::Department::create(subdep.id, query(), name);
402+ dep->set_has_subdepartments(subdep.has_children);
403+ current->add_subdepartment(dep);
404+ }
405+ catch (const std::exception &e)
406+ {
407+ qWarning() << "Failed to create subdeparment:" << QString::fromStdString(e.what());
408+ }
409 }
410 }
411
412@@ -357,7 +399,7 @@
413 if (querystr.empty()) {
414 if (impl->depts_db)
415 {
416- push_local_departments(searchReply);
417+ push_local_departments(searchReply, localResults);
418 }
419 }
420
421
422=== modified file 'scope/clickapps/apps-query.h'
423--- scope/clickapps/apps-query.h 2014-07-22 13:17:28 +0000
424+++ scope/clickapps/apps-query.h 2014-08-12 10:55:35 +0000
425@@ -74,7 +74,7 @@
426
427 virtual void add_fake_store_app(scopes::SearchReplyProxy const &replyProxy);
428
429- virtual void push_local_departments(scopes::SearchReplyProxy const& replyProxy);
430+ virtual void push_local_departments(scopes::SearchReplyProxy const& replyProxy, const std::vector<Application>& apps);
431
432 protected:
433 virtual click::Interface& clickInterfaceInstance();
434
435=== modified file 'scope/tests/test_apps_query.cpp'
436--- scope/tests/test_apps_query.cpp 2014-08-05 14:16:26 +0000
437+++ scope/tests/test_apps_query.cpp 2014-08-12 10:55:35 +0000
438@@ -192,7 +192,10 @@
439
440 class DepartmentsTest : public ::testing::Test {
441 protected:
442- const std::vector<click::Application> installed_apps = {{"app1", "App1", 0.0f, "icon", "url", "descr", "scrshot", ""}};
443+ const std::vector<click::Application> installed_apps = {
444+ {"app1", "App1", 0.0f, "icon", "url", "descr", "scrshot", "", "games-rpg"},
445+ {"app2", "App2", 0.0f, "icon", "url", "descr", "scrshot", "", "video"}
446+ };
447 const scopes::SearchMetadata metadata{"en_EN", "phone"};
448 const scopes::CategoryRenderer renderer{"{}"};
449 const std::list<std::string> expected_locales {"en_EN", "en_US"};
450@@ -214,6 +217,7 @@
451 scopes::testing::MockSearchReply mock_reply;
452 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
453
454+ // no apps in 'books' department, thus excluded
455 std::list<std::string> expected_departments({{"", "games", "video"}});
456
457 EXPECT_CALL(*clickif, find_installed_apps(_, _, _)).WillOnce(Return(installed_apps));
458@@ -222,14 +226,25 @@
459 EXPECT_CALL(mock_reply, register_category("store", _, _, _)).WillOnce(Return(ptrCat));
460 EXPECT_CALL(mock_reply, register_departments(MatchesDepartments(expected_departments)));
461
462- EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(2).WillRepeatedly(Return(true));
463+ EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(3).WillRepeatedly(Return(true));
464+
465+ ON_CALL(*depts_db, is_descendant_of_department(_, _)).WillByDefault(Return(false));
466+ ON_CALL(*depts_db, is_descendant_of_department("games", "")).WillByDefault(Return(true));
467+ ON_CALL(*depts_db, is_descendant_of_department("games-rpg", "games")).WillByDefault(Return(true));
468+ ON_CALL(*depts_db, is_descendant_of_department("books", "")).WillByDefault(Return(true));
469+ ON_CALL(*depts_db, is_descendant_of_department("video", "")).WillByDefault(Return(true));
470
471 EXPECT_CALL(*depts_db, get_department_name("games", expected_locales)).WillOnce(Return("Games"));
472 EXPECT_CALL(*depts_db, get_department_name("video", expected_locales)).WillOnce(Return("Video"));
473+ EXPECT_CALL(*depts_db, is_empty("games")).WillRepeatedly(Return(false));
474+ EXPECT_CALL(*depts_db, is_empty("video")).WillRepeatedly(Return(false));
475+ EXPECT_CALL(*depts_db, is_empty("books")).WillRepeatedly(Return(false));
476+ EXPECT_CALL(*depts_db, is_descendant_of_department(_, _)).Times(AnyNumber());
477 EXPECT_CALL(*depts_db, get_children_departments("")).WillOnce(Return(
478 std::list<click::DepartmentsDb::DepartmentInfo>({
479- {"games", false},
480- {"video", true}
481+ {"games", true},
482+ {"video", true},
483+ {"books", true}
484 }))
485 );
486
487@@ -259,7 +274,7 @@
488 EXPECT_CALL(mock_reply, register_category("store", _, _, _)).WillOnce(Return(ptrCat));
489 EXPECT_CALL(mock_reply, register_departments(MatchesDepartments(expected_departments)));
490
491- EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(2).WillRepeatedly(Return(true));
492+ EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(3).WillRepeatedly(Return(true));
493
494 EXPECT_CALL(*depts_db, get_parent_department_id("games")).WillOnce(Return(""));
495 EXPECT_CALL(*depts_db, get_department_name("games", expected_locales)).WillOnce(Return("Games"));
496@@ -290,7 +305,7 @@
497 EXPECT_CALL(mock_reply, register_category("local", StrEq(""), _, _)).WillOnce(Return(ptrCat));
498 EXPECT_CALL(mock_reply, register_category("store", _, _, _)).WillOnce(Return(ptrCat));
499
500- EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(2).WillRepeatedly(Return(true));
501+ EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(3).WillRepeatedly(Return(true));
502
503 q.run(reply);
504 }
505
506=== modified file 'scope/tests/test_helpers.h'
507--- scope/tests/test_helpers.h 2014-07-18 15:01:41 +0000
508+++ scope/tests/test_helpers.h 2014-08-12 10:55:35 +0000
509@@ -65,6 +65,8 @@
510 MOCK_METHOD2(get_packages_for_department, std::unordered_set<std::string>(const std::string&, bool));
511 MOCK_METHOD1(get_parent_department_id, std::string(const std::string&));
512 MOCK_METHOD1(get_children_departments, std::list<click::DepartmentsDb::DepartmentInfo>(const std::string&));
513+ MOCK_METHOD1(is_empty, bool(const std::string&));
514+ MOCK_METHOD2(is_descendant_of_department, bool(const std::string&, const std::string&));
515
516 MOCK_METHOD2(store_package_mapping, void(const std::string&, const std::string&));
517 MOCK_METHOD2(store_department_mapping, void(const std::string&, const std::string&));

Subscribers

People subscribed via source and target branches

to all changes: