/* SPDX-FileCopyrightText: 2014, 2015 Gregor Mi SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include <../src/kmoretools.h> #include <../src/kmoretools_p.h> #include <../src/kmoretoolspresets.h> #include #include #include #include class KMoreToolsTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); // corner, error cases and impl details: void testDesktopFileWithNoExec(); void testDesktopFileWithInvalidHeader(); void testDesktopFileWithNoName(); void testDesktopFileNotProvided(); void testDetectByExecLineButNoFileProvided(); void testRegisterServiceTwice(); void testMenuBuilderWithConfigPostfix(); // use cases: void testNotInstalledAppStructure(); void testNotInstalledAppIcon(); void testUniqueItemIdForOwnActions(); void test_buildMenu_PruneDuplicateNotInstalledService(); void test_KMoreToolsPresets_registerServicesByGrouping(); // kmoretools_p.h tests: void testMenuItemIdGen(); void test_MenuItemDto_removeMenuAmpersand(); void test_MenuStructureDto_sortListBySection(); void test_MenuStructureDto_serialize(); void test_MenuStructureDto_deserialize(); void test_KmtUrlUtil_localFileAbsoluteDir(); }; void KMoreToolsTest::initTestCase() { QStandardPaths::setTestModeEnabled(true); const QString dest = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kf6/kmoretools/unittest-kmoretools/1/"); QVERIFY(QDir(dest).removeRecursively()); QVERIFY(QDir().mkpath(dest)); for (const QString &fileName : {QStringLiteral("a.desktop"), QStringLiteral("b.desktop"), QStringLiteral("c.desktop")}) { const QString srcFile = QFINDTESTDATA("1/" + fileName + ".notranslate"); QVERIFY(!srcFile.isEmpty()); QVERIFY(QFile::copy(srcFile, dest + fileName)); } const QString dest2 = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kf6/kmoretools/unittest-kmoretools/2/"); QVERIFY(QDir(dest2).removeRecursively()); QVERIFY(QDir().mkpath(dest2)); const auto fileNames = {QStringLiteral("org.kde.kate.desktop"), QStringLiteral("org.kde.kate.png"), QStringLiteral("mynotinstalledapp.desktop"), QStringLiteral("mynotinstalledapp.png"), QStringLiteral("mynotinstapp2.desktop")}; for (const QString &fileName : fileNames) { const QString origFile = fileName.endsWith(QLatin1String("desktop")) ? fileName + _(".notranslate") : fileName; const QString srcFile = QFINDTESTDATA("2/" + origFile); QVERIFY(!srcFile.isEmpty()); QVERIFY(QFile::copy(srcFile, dest2 + fileName)); } } /** * no Exec line => not a usable desktop file */ void KMoreToolsTest::testDesktopFileWithNoExec() { KMoreTools kmt(_("unittest-kmoretools/1")); auto aApp = kmt.registerServiceByDesktopEntryName(_("a")); QVERIFY(!aApp); } /** * invalid header? => Exec line not found */ void KMoreToolsTest::testDesktopFileWithInvalidHeader() { KMoreTools kmt(_("unittest-kmoretools/1")); auto bApp = kmt.registerServiceByDesktopEntryName(_("b")); QVERIFY(!bApp); } /** * no Name line => name() will be filled automatically, everything will be ok */ void KMoreToolsTest::testDesktopFileWithNoName() { KMoreTools kmt(_("unittest-kmoretools/1")); auto cApp = kmt.registerServiceByDesktopEntryName(_("c")); QVERIFY(cApp); QCOMPARE(cApp->desktopEntryName(), _("c")); QVERIFY(cApp->kmtProvidedService()); QCOMPARE(cApp->kmtProvidedService()->exec(), _("hallo")); } /** * desktop file not present => warning */ void KMoreToolsTest::testDesktopFileNotProvided() { KMoreTools kmt(_("unittest-kmoretools/1")); auto eeeApp = kmt.registerServiceByDesktopEntryName(_("eee")); QVERIFY(eeeApp); QCOMPARE(eeeApp->desktopEntryName(), _("eee")); } void KMoreToolsTest::testDetectByExecLineButNoFileProvided() { KMoreTools kmt(_("unittest-kmoretools/1")); auto eeeApp = kmt.registerServiceByDesktopEntryName(_("eee"), QString(), KMoreTools::ServiceLocatingMode_ByProvidedExecLine); QVERIFY(!eeeApp); } void KMoreToolsTest::testRegisterServiceTwice() { KMoreTools kmt(_("unittest-kmoretools/1")); /*auto eeeApp1 = */ kmt.registerServiceByDesktopEntryName(_("eee")); /*auto eeeApp2 = */ kmt.registerServiceByDesktopEntryName(_("eee")); // todo: verify that there is only the last item in the internal service list } void KMoreToolsTest::testMenuBuilderWithConfigPostfix() { KMoreTools kmt(_("unittest-kmoretools/1")); auto menuBuilder1 = kmt.menuBuilder(); auto menuBuilder2 = kmt.menuBuilder(); auto menuBuilder3 = kmt.menuBuilder(_("postfix")); auto menuBuilder4 = kmt.menuBuilder(_("postfix")); QVERIFY(menuBuilder1 == menuBuilder2); QVERIFY(menuBuilder3 != menuBuilder1); QVERIFY(menuBuilder3 == menuBuilder4); } void KMoreToolsTest::testNotInstalledAppStructure() { KMoreTools kmt(_("unittest-kmoretools/2")); const auto mynotInstalledApp = kmt.registerServiceByDesktopEntryName(_("mynotinstalledapp")); const auto menuBuilder = kmt.menuBuilder(); menuBuilder->addMenuItem(mynotInstalledApp); QString s = menuBuilder->menuStructureAsString(false); qDebug() << s; QCOMPARE(s, _("|main|:|more|:|notinstalled|:mynotinstalledapp.")); } void KMoreToolsTest::testNotInstalledAppIcon() { KMoreTools kmt(_("unittest-kmoretools/2")); const auto mynotInstalledApp = kmt.registerServiceByDesktopEntryName(_("mynotinstalledapp")); QVERIFY(!mynotInstalledApp->icon().isNull()); } void KMoreToolsTest::testUniqueItemIdForOwnActions() { KMoreTools kmt(_("unittest-kmoretools/1")); auto menuBuilder = kmt.menuBuilder(); QAction a1(_("a"), nullptr); auto item1 = menuBuilder->addMenuItem(&a1, _("aaa")); QAction a2(_("b"), nullptr); auto item2 = menuBuilder->addMenuItem(&a2, _("aaa")); // same id to see if it will be made unique QCOMPARE(item1->id(), _("aaa0")); QCOMPARE(item2->id(), _("aaa1")); } bool menuAtLeastOneActionWithText(const QMenu *menu, const QString &text) { const auto lstActions = menu->actions(); for (auto a : lstActions) { if (a->text() == text) { return true; } } return false; } bool menuAtLeastNoActionWithText(const QMenu *menu, const QString &text) { const auto lstActions = menu->actions(); for (auto a : lstActions) { if (a->text() == text) { qDebug() << a->text(); return false; } } return true; } void KMoreToolsTest::test_buildMenu_PruneDuplicateNotInstalledService() { KMoreTools kmt(_("unittest-kmoretools/2")); const auto mynotInstalledApp = kmt.registerServiceByDesktopEntryName(_("mynotinstalledapp")); const auto menuBuilder = kmt.menuBuilder(); menuBuilder->addMenuItem(mynotInstalledApp); menuBuilder->addMenuItem(mynotInstalledApp); // duplicate (which can make sense if the service will be called with different arguments) QMenu menu; menuBuilder->buildByAppendingToMenu(&menu); QCOMPARE(menu.actions().count(), 4); // "Not installed section", "Not installed app" (only once), "Separator", "Configure menu..." } void KMoreToolsTest::test_KMoreToolsPresets_registerServicesByGrouping() { KMoreTools kmt(_("unittest-kmoretools/3")); auto list = KMoreToolsPresets::registerServicesByGroupingNames(&kmt, {_("screenshot-take")}); if (std::find_if(list.begin(), list.end(), [](KMoreToolsService *s) { return s->desktopEntryName() == _("org.kde.spectacle"); }) != list.end()) { QVERIFY(true); // at least spectacle should currently be present } else { QVERIFY(false); } } void KMoreToolsTest::testMenuItemIdGen() { KmtMenuItemIdGen idGen; QCOMPARE(idGen.getId(_("a")), _("a0")); QCOMPARE(idGen.getId(_("a")), _("a1")); QCOMPARE(idGen.getId(_("b")), _("b0")); QCOMPARE(idGen.getId(_("a")), _("a2")); } QDebug operator<<(QDebug d, const KmtMenuItemDto &m) { d << "id:" << m.id << ", section:" << m.menuSection << ", isInstalled:" << m.isInstalled; return d; } void KMoreToolsTest::test_MenuItemDto_removeMenuAmpersand() { QCOMPARE(KmtMenuItemDto::removeMenuAmpersand(_("&Hallo")), _("Hallo")); QCOMPARE(KmtMenuItemDto::removeMenuAmpersand(_("Hall&o")), _("Hallo")); QCOMPARE(KmtMenuItemDto::removeMenuAmpersand(_("H&all&o")), _("Hallo")); // is this ok for menus items? QCOMPARE(KmtMenuItemDto::removeMenuAmpersand(_("&&Hallo")), _("&Hallo")); QCOMPARE(KmtMenuItemDto::removeMenuAmpersand(_("&Hall&&o")), _("Hall&o")); } // Support method for KMoreToolsTest::test_MenuStructureDto_sortListBySection, // generates a list of menu items ordered by the passed-in indexes; this // helps test multiple permutations of the same list. Don't try *all* // permutations, since it's a stable sort -- items inside a section // must remain in the same relative order. // static void sortListBySection(int indexes[5]) { KmtMenuStructureDto mstruct; KmtMenuItemDto ma1; ma1.id = QStringLiteral("main1"); ma1.menuSection = KMoreTools::MenuSection_Main; KmtMenuItemDto mo1; mo1.id = QStringLiteral("more1"); mo1.menuSection = KMoreTools::MenuSection_More; KmtMenuItemDto ma3; ma3.id = QStringLiteral("main3_ni"); ma3.menuSection = KMoreTools::MenuSection_Main; ma3.isInstalled = false; // !!! KmtMenuItemDto mo2; mo2.id = QStringLiteral("more2"); mo2.menuSection = KMoreTools::MenuSection_More; KmtMenuItemDto ma2; ma2.id = QStringLiteral("main2"); ma2.menuSection = KMoreTools::MenuSection_Main; KmtMenuItemDto *items[5] = {&ma1, &mo1, &ma3, &mo2, &ma2}; mstruct.list.clear(); for (unsigned int i = 0; i < 5; ++i) { mstruct.list.append(*items[indexes[i]]); } mstruct.stableSortListBySection(); QCOMPARE(mstruct.list[0].id, _("main1")); // 1. main QCOMPARE(mstruct.list[1].id, _("main2")); QCOMPARE(mstruct.list[2].id, _("more1")); // 2. more QCOMPARE(mstruct.list[3].id, _("more2")); QCOMPARE(mstruct.list[4].id, _("main3_ni")); // 3. not installed } void KMoreToolsTest::test_MenuStructureDto_sortListBySection() { int indexes_plain[5] = {0, 1, 2, 3, 4}; // In normal order int indexes_presorted[5] = {0, 4, 1, 3, 2}; int indexes_interleave[5] = {0, 1, 3, 4, 2}; int indexes_morefirst[5] = {1, 3, 0, 4, 2}; int indexes_uninstalledfirst[5] = {2, 1, 0, 4, 3}; // Permutations of where the uninstalled item is inserted int indexes_uninstalled_p0[5] = {2, 0, 1, 3, 4}; int indexes_uninstalled_p1[5] = {0, 2, 1, 3, 4}; int indexes_uninstalled_p2[5] = {0, 1, 2, 3, 4}; int indexes_uninstalled_p3[5] = {0, 1, 3, 2, 4}; int indexes_uninstalled_p4[5] = {0, 1, 3, 4, 2}; qDebug() << "Plain"; sortListBySection(indexes_plain); qDebug() << "Presorted"; sortListBySection(indexes_presorted); qDebug() << "Interleaved"; sortListBySection(indexes_interleave); qDebug() << "'More' first"; sortListBySection(indexes_morefirst); qDebug() << "'Uninstalled' first"; sortListBySection(indexes_uninstalledfirst); qDebug() << "'Uninstalled' first, p0"; sortListBySection(indexes_uninstalled_p0); qDebug() << "'Uninstalled' first, p1"; sortListBySection(indexes_uninstalled_p1); qDebug() << "'Uninstalled' first, p2"; sortListBySection(indexes_uninstalled_p2); qDebug() << "'Uninstalled' first, p3"; sortListBySection(indexes_uninstalled_p3); qDebug() << "'Uninstalled' first, p4"; sortListBySection(indexes_uninstalled_p4); } void KMoreToolsTest::test_MenuStructureDto_serialize() { KmtMenuStructureDto mstruct; KmtMenuItemDto ma1; ma1.id = QStringLiteral("main1"); ma1.menuSection = KMoreTools::MenuSection_Main; mstruct.list.append(ma1); KmtMenuItemDto mo1; mo1.id = QStringLiteral("more1"); mo1.menuSection = KMoreTools::MenuSection_More; mstruct.list.append(mo1); QString json = mstruct.serialize(); QCOMPARE(json, QString(_("{\"menuitemlist\":[{\"id\":\"main1\",\"isInstalled\":true,\"menuSection\":\"main\"},{\"id\":\"more1\",\"isInstalled\":true," "\"menuSection\":\"more\"}]}"))); } void KMoreToolsTest::test_MenuStructureDto_deserialize() { QString jsonStr( _("{\"menuitemlist\":[{\"id\":\"main1\",\"isInstalled\":true,\"menuSection\":\"main\"},{\"id\":\"more1\",\"isInstalled\":true,\"menuSection\":\"more\"}" "]}")); KmtMenuStructureDto mstruct; mstruct.deserialize(jsonStr); QCOMPARE(mstruct.list.count(), 2); KmtMenuItemDto ma1 = mstruct.list[0]; QCOMPARE(ma1.id, _("main1")); QCOMPARE(ma1.menuSection, KMoreTools::MenuSection_Main); QCOMPARE(ma1.isInstalled, true); } void KMoreToolsTest::test_KmtUrlUtil_localFileAbsoluteDir() { { auto urlIn = QUrl::fromLocalFile(QStringLiteral("/etc/bash.bashrc")); QCOMPARE(urlIn.toString(), QString(_("file:///etc/bash.bashrc"))); auto urlOut = KmtUrlUtil::localFileAbsoluteDir(urlIn); #ifdef Q_OS_WINDOWS QCOMPARE(urlOut.toString(), QString(_("file:///C:/etc"))); #else QCOMPARE(urlOut.toString(), QString(_("file:///etc"))); #endif } { auto urlIn = QUrl::fromLocalFile(QStringLiteral("/home/u1/dev/kf5/src/kde/applications/dolphin/.reviewboardrc")); QCOMPARE(urlIn.toString(), QString(_("file:///home/u1/dev/kf5/src/kde/applications/dolphin/.reviewboardrc"))); auto urlOut = KmtUrlUtil::localFileAbsoluteDir(urlIn); #ifdef Q_OS_WINDOWS QCOMPARE(urlOut.toString(), QString(_("file:///C:/home/u1/dev/kf5/src/kde/applications/dolphin"))); #else QCOMPARE(urlOut.toString(), QString(_("file:///home/u1/dev/kf5/src/kde/applications/dolphin"))); #endif } { auto urlIn2 = QUrl::fromLocalFile(QStringLiteral("aaa/bbb")); QCOMPARE(urlIn2.toString(), QString(_("file:aaa/bbb"))); } } QTEST_MAIN(KMoreToolsTest) #include "kmoretoolstest.moc"