@@ -24,6 +24,7 @@
24#include "launcheritem.h"
24#include "launcheritem.h"
25#include "launchermodel.h"
25#include "launchermodel.h"
26#include "dbusinterface.h"
26#include "dbusinterface.h"
27+#include "gsettings.h"
28#include <QtTest>
29#include <QtTest>
29#include <QDBusInterface>
30#include <QDBusInterface>
@@ -81,7 +82,15 @@ public:
81 return nullptr;
82 return nullptr;
83 unity::shell::application::ApplicationInfoInterface *startApplication(const QString &, const QStringList &) { return nullptr; }
84 unity::shell::application::ApplicationInfoInterface *startApplication(const QString &, const QStringList &) { return nullptr; }
84− bool stopApplication(const QString &) { return false; }
85+ bool stopApplication(const QString &appId) {
86+ Q_FOREACH(MockApp* app, m_list) {
87+ if (app->appId() == appId) {
88+ removeApplication(m_list.indexOf(app));
85 bool focusApplication(const QString &appId) {
94 bool focusApplication(const QString &appId) {
86 Q_FOREACH(MockApp* app, m_list) {
95 Q_FOREACH(MockApp* app, m_list) {
87 app->setFocused(app->appId() == appId);
96 app->setFocused(app->appId() == appId);
@@ -135,6 +144,8 @@ private Q_SLOTS:
136 appManager->addApplication(new MockApp("no-icon"));
145 appManager->addApplication(new MockApp("no-icon"));
137 QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
146 QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
148+ launcherModel->m_settings->setStoredApplications(QStringList());
140 // Removing apps from appmanager and launcher as pinned ones would stick
151 // Removing apps from appmanager and launcher as pinned ones would stick
@@ -170,14 +181,15 @@ private Q_SLOTS:
170 launcherModel->pin(launcherModel->get(0)->appId());
181 launcherModel->pin(launcherModel->get(0)->appId());
171 QCOMPARE(launcherModel->get(0)->pinned(), true);
182 QCOMPARE(launcherModel->get(0)->pinned(), true);
172 QCOMPARE(launcherModel->get(1)->pinned(), false);
183 QCOMPARE(launcherModel->get(1)->pinned(), false);
173− QCOMPARE(spy.count(), 1);
184+ QCOMPARE(spy.count() > 0, true);
174 QCOMPARE(spy.at(0).at(2).value<QVector<int>>().first(), (int)LauncherModelInterface::RolePinned);
185 QCOMPARE(spy.at(0).at(2).value<QVector<int>>().first(), (int)LauncherModelInterface::RolePinned);
176 launcherModel->requestRemove(launcherModel->get(0)->appId());
188 launcherModel->requestRemove(launcherModel->get(0)->appId());
177 QCOMPARE(launcherModel->get(0)->pinned(), false);
189 QCOMPARE(launcherModel->get(0)->pinned(), false);
178 QCOMPARE(launcherModel->get(1)->pinned(), false);
190 QCOMPARE(launcherModel->get(1)->pinned(), false);
179− QCOMPARE(spy.count(), 2);
191+ QCOMPARE(spy.count(), 1);
180− QCOMPARE(spy.at(1).at(2).value<QVector<int>>().first(), (int)LauncherModelInterface::RolePinned);
192+ QCOMPARE(spy.at(0).at(2).value<QVector<int>>().first(), (int)LauncherModelInterface::RolePinned);
183 void testRemove_data() {
195 void testRemove_data() {
@@ -186,7 +198,7 @@ private Q_SLOTS:
186 QTest::addColumn<bool>("running");
198 QTest::addColumn<bool>("running");
188 QTest::newRow("non-pinned, running") << false << true;
200 QTest::newRow("non-pinned, running") << false << true;
189− QTest::newRow("pinned, running") << true << false;
201+ QTest::newRow("pinned, running") << true << true;
190 QTest::newRow("pinned, non-running") << true << false;
202 QTest::newRow("pinned, non-running") << true << false;
@@ -199,23 +211,24 @@ private Q_SLOTS:
200 // pin one if required
212 // pin one if required
201 if (pinned) {
213 if (pinned) {
202− launcherModel->pin(launcherModel->get(1)->appId());
214+ launcherModel->pin("abs-icon");
205 // stop it if required
217 // stop it if required
206 if (!running) {
218 if (!running) {
207− appManager->removeApplication(1);
219+ appManager->stopApplication("abs-icon");
210 // Now remove it
222 // Now remove it
211− launcherModel->requestRemove(launcherModel->get(1)->appId());
223+ launcherModel->requestRemove("abs-icon");
213 if (running) {
225 if (running) {
214 // both apps are running, both apps must still be here
226 // both apps are running, both apps must still be here
215 QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
227 QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
217 // Item must be unpinned now
229 // Item must be unpinned now
230+ int index = launcherModel->findApplication("abs-icon");
218− QCOMPARE(launcherModel->get(1)->pinned(), false);
231+ QCOMPARE(launcherModel->get(index)->pinned(), false);
220 } else if (pinned) {
233 } else if (pinned) {
221 // Item 1 must go away, item 0 is here to stay
234 // Item 1 must go away, item 0 is here to stay
@@ -224,7 +237,7 @@ private Q_SLOTS:
225 // done our checks. now stop the app if was still running
238 // done our checks. now stop the app if was still running
226 if (running) {
239 if (running) {
227− appManager->removeApplication(1);
240+ appManager->stopApplication("abs-icon");
230 // It needs to go away in any case now
243 // It needs to go away in any case now
@@ -369,12 +382,81 @@ private Q_SLOTS:
369 QCOMPARE(launcherModel->get(index)->count(), 55);
382 QCOMPARE(launcherModel->get(index)->count(), 55);
372− void testRefresh() {
385+ void testRefreshAfterDeletedDesktopFiles_data() {
386+ QTest::addColumn<bool>("deleted");
387+ QTest::newRow("have .desktop files") << false;
388+ QTest::newRow("deleted .desktop files") << true;
391+ void testRefreshAfterDeletedDesktopFiles() {
392+ QFETCH(bool, deleted);
395+ launcherModel->pin("abs-icon");
396+ launcherModel->pin("no-icon");
398+ appManager->removeApplication(0);
399+ appManager->removeApplication(0);
401+ // "delete" the .desktop files
402+ QString oldCurrent = QDir::currentPath();
404+ // In testing mode, the launcher searches the current dir for the sample .desktop file
405+ // We can make that fail by changing the current dir
406+ QDir::setCurrent("..");
373 QDBusInterface interface("com.canonical.Unity.Launcher", "/com/canonical/Unity/Launcher", "com.canonical.Unity.Launcher");
410 QDBusInterface interface("com.canonical.Unity.Launcher", "/com/canonical/Unity/Launcher", "com.canonical.Unity.Launcher");
374 QDBusReply<void> reply = interface.call("Refresh");
411 QDBusReply<void> reply = interface.call("Refresh");
376 // Make sure the call to Refresh returned without error.
413 // Make sure the call to Refresh returned without error.
377 QCOMPARE(reply.isValid(), true);
414 QCOMPARE(reply.isValid(), true);
416+ QCOMPARE(launcherModel->rowCount(), deleted ? 0 : 2);
418+ // Restoring current dir
419+ QDir::setCurrent(oldCurrent);
422+ void testSettings_data() {
423+ QTest::addColumn<QStringList>("storedList");
425+ QTest::newRow("2 stored") << (QStringList() << "abs-icon" << "no-icon");
426+ QTest::newRow("1 stored") << (QStringList() << "abs-icon");
429+ void testSettings() {
430+ GSettings *settings = launcherModel->m_settings;
432+ // Nothing pinned at startup
433+ QCOMPARE(settings->storedApplications().count(), 0);
436+ launcherModel->pin("abs-icon");
437+ launcherModel->pin("no-icon");
439+ // Now settings should have 2 apps
440+ QCOMPARE(settings->storedApplications().count(), 2);
443+ appManager->removeApplication(0);
444+ appManager->removeApplication(0);
446+ // Now settings should have 2 apps
447+ QCOMPARE(settings->storedApplications().count(), 2);
449+ // Now remove 1 app through the backend, make sure one is still there
450+ settings->setStoredApplications(QStringList() << "abs-icon");
451+ QCOMPARE(settings->storedApplications().count(), 1);
453+ // Check if it disappeared from the frontend too
454+ QCOMPARE(launcherModel->rowCount(), 1);
457+ settings->setStoredApplications(QStringList() << "abs-icon" << "no-icon");
458+ QCOMPARE(launcherModel->rowCount(), 2);