File indexing completed on 2025-01-19 10:00:10
0001 /* 0002 SPDX-FileCopyrightText: 2014, 2015 Gregor Mi <codestruct@posteo.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include <../src/kmoretools/kmoretools.h> 0008 #include <../src/kmoretools/kmoretools_p.h> 0009 #include <../src/kmoretools/kmoretoolspresets.h> 0010 0011 #include <QPushButton> 0012 #include <QRegularExpression> 0013 #include <QStandardPaths> 0014 #include <QTest> 0015 0016 class KMoreToolsTest : public QObject 0017 { 0018 Q_OBJECT 0019 0020 private Q_SLOTS: 0021 void initTestCase(); 0022 0023 // corner, error cases and impl details: 0024 void testDesktopFileWithNoExec(); 0025 void testDesktopFileWithInvalidHeader(); 0026 void testDesktopFileWithNoName(); 0027 void testDesktopFileNotProvided(); 0028 void testDetectByExecLineButNoFileProvided(); 0029 void testRegisterServiceTwice(); 0030 void testMenuBuilderWithConfigPostfix(); 0031 0032 // use cases: 0033 void testNotInstalledAppStructure(); 0034 void testNotInstalledAppIcon(); 0035 void testUniqueItemIdForOwnActions(); 0036 void test_buildMenu_PruneDuplicateNotInstalledService(); 0037 void test_KMoreToolsPresets_registerServicesByGrouping(); 0038 0039 // kmoretools_p.h tests: 0040 void testMenuItemIdGen(); 0041 void test_MenuItemDto_removeMenuAmpersand(); 0042 void test_MenuStructureDto_sortListBySection(); 0043 void test_MenuStructureDto_serialize(); 0044 void test_MenuStructureDto_deserialize(); 0045 void test_KmtUrlUtil_localFileAbsoluteDir(); 0046 }; 0047 0048 void KMoreToolsTest::initTestCase() 0049 { 0050 QStandardPaths::setTestModeEnabled(true); 0051 0052 const QString dest = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kf5/kmoretools/unittest-kmoretools/1/"); 0053 QVERIFY(QDir(dest).removeRecursively()); 0054 QVERIFY(QDir().mkpath(dest)); 0055 for (const QString &fileName : {QStringLiteral("a.desktop"), QStringLiteral("b.desktop"), QStringLiteral("c.desktop")}) { 0056 const QString srcFile = QFINDTESTDATA("1/" + fileName + ".notranslate"); 0057 QVERIFY(!srcFile.isEmpty()); 0058 QVERIFY(QFile::copy(srcFile, dest + fileName)); 0059 } 0060 0061 const QString dest2 = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kf5/kmoretools/unittest-kmoretools/2/"); 0062 QVERIFY(QDir(dest2).removeRecursively()); 0063 QVERIFY(QDir().mkpath(dest2)); 0064 const auto fileNames = {QStringLiteral("org.kde.kate.desktop"), 0065 QStringLiteral("org.kde.kate.png"), 0066 QStringLiteral("mynotinstalledapp.desktop"), 0067 QStringLiteral("mynotinstalledapp.png"), 0068 QStringLiteral("mynotinstapp2.desktop")}; 0069 for (const QString &fileName : fileNames) { 0070 const QString origFile = fileName.endsWith(QLatin1String("desktop")) ? fileName + _(".notranslate") : fileName; 0071 const QString srcFile = QFINDTESTDATA("2/" + origFile); 0072 QVERIFY(!srcFile.isEmpty()); 0073 QVERIFY(QFile::copy(srcFile, dest2 + fileName)); 0074 } 0075 } 0076 0077 /** 0078 * no Exec line => not a usable desktop file 0079 */ 0080 void KMoreToolsTest::testDesktopFileWithNoExec() 0081 { 0082 KMoreTools kmt(_("unittest-kmoretools/1")); 0083 auto aApp = kmt.registerServiceByDesktopEntryName(_("a")); 0084 QVERIFY(!aApp); 0085 } 0086 0087 /** 0088 * invalid header? => Exec line not found 0089 */ 0090 void KMoreToolsTest::testDesktopFileWithInvalidHeader() 0091 { 0092 KMoreTools kmt(_("unittest-kmoretools/1")); 0093 auto bApp = kmt.registerServiceByDesktopEntryName(_("b")); 0094 QVERIFY(!bApp); 0095 } 0096 0097 /** 0098 * no Name line => name() will be filled automatically, everything will be ok 0099 */ 0100 void KMoreToolsTest::testDesktopFileWithNoName() 0101 { 0102 KMoreTools kmt(_("unittest-kmoretools/1")); 0103 auto cApp = kmt.registerServiceByDesktopEntryName(_("c")); 0104 QVERIFY(cApp); 0105 QCOMPARE(cApp->desktopEntryName(), _("c")); 0106 QVERIFY(cApp->kmtProvidedService()); 0107 QCOMPARE(cApp->kmtProvidedService()->exec(), _("hallo")); 0108 } 0109 0110 /** 0111 * desktop file not present => warning 0112 */ 0113 void KMoreToolsTest::testDesktopFileNotProvided() 0114 { 0115 KMoreTools kmt(_("unittest-kmoretools/1")); 0116 auto eeeApp = kmt.registerServiceByDesktopEntryName(_("eee")); 0117 QVERIFY(eeeApp); 0118 QCOMPARE(eeeApp->desktopEntryName(), _("eee")); 0119 } 0120 0121 void KMoreToolsTest::testDetectByExecLineButNoFileProvided() 0122 { 0123 KMoreTools kmt(_("unittest-kmoretools/1")); 0124 auto eeeApp = kmt.registerServiceByDesktopEntryName(_("eee"), QString(), KMoreTools::ServiceLocatingMode_ByProvidedExecLine); 0125 QVERIFY(!eeeApp); 0126 } 0127 0128 void KMoreToolsTest::testRegisterServiceTwice() 0129 { 0130 KMoreTools kmt(_("unittest-kmoretools/1")); 0131 /*auto eeeApp1 = */ kmt.registerServiceByDesktopEntryName(_("eee")); 0132 /*auto eeeApp2 = */ kmt.registerServiceByDesktopEntryName(_("eee")); 0133 // todo: verify that there is only the last item in the internal service list 0134 } 0135 0136 void KMoreToolsTest::testMenuBuilderWithConfigPostfix() 0137 { 0138 KMoreTools kmt(_("unittest-kmoretools/1")); 0139 auto menuBuilder1 = kmt.menuBuilder(); 0140 auto menuBuilder2 = kmt.menuBuilder(); 0141 auto menuBuilder3 = kmt.menuBuilder(_("postfix")); 0142 auto menuBuilder4 = kmt.menuBuilder(_("postfix")); 0143 0144 QVERIFY(menuBuilder1 == menuBuilder2); 0145 QVERIFY(menuBuilder3 != menuBuilder1); 0146 QVERIFY(menuBuilder3 == menuBuilder4); 0147 } 0148 0149 void KMoreToolsTest::testNotInstalledAppStructure() 0150 { 0151 KMoreTools kmt(_("unittest-kmoretools/2")); 0152 const auto mynotInstalledApp = kmt.registerServiceByDesktopEntryName(_("mynotinstalledapp")); 0153 const auto menuBuilder = kmt.menuBuilder(); 0154 menuBuilder->addMenuItem(mynotInstalledApp); 0155 QString s = menuBuilder->menuStructureAsString(false); 0156 qDebug() << s; 0157 QCOMPARE(s, _("|main|:|more|:|notinstalled|:mynotinstalledapp.")); 0158 } 0159 0160 void KMoreToolsTest::testNotInstalledAppIcon() 0161 { 0162 KMoreTools kmt(_("unittest-kmoretools/2")); 0163 const auto mynotInstalledApp = kmt.registerServiceByDesktopEntryName(_("mynotinstalledapp")); 0164 QVERIFY(!mynotInstalledApp->icon().isNull()); 0165 } 0166 0167 void KMoreToolsTest::testUniqueItemIdForOwnActions() 0168 { 0169 KMoreTools kmt(_("unittest-kmoretools/1")); 0170 auto menuBuilder = kmt.menuBuilder(); 0171 QAction a1(_("a"), nullptr); 0172 auto item1 = menuBuilder->addMenuItem(&a1, _("aaa")); 0173 QAction a2(_("b"), nullptr); 0174 auto item2 = menuBuilder->addMenuItem(&a2, _("aaa")); // same id to see if it will be made unique 0175 0176 QCOMPARE(item1->id(), _("aaa0")); 0177 QCOMPARE(item2->id(), _("aaa1")); 0178 } 0179 0180 bool menuAtLeastOneActionWithText(const QMenu *menu, const QString &text) 0181 { 0182 const auto lstActions = menu->actions(); 0183 for (auto a : lstActions) { 0184 if (a->text() == text) { 0185 return true; 0186 } 0187 } 0188 0189 return false; 0190 } 0191 0192 bool menuAtLeastNoActionWithText(const QMenu *menu, const QString &text) 0193 { 0194 const auto lstActions = menu->actions(); 0195 for (auto a : lstActions) { 0196 if (a->text() == text) { 0197 qDebug() << a->text(); 0198 return false; 0199 } 0200 } 0201 0202 return true; 0203 } 0204 0205 void KMoreToolsTest::test_buildMenu_PruneDuplicateNotInstalledService() 0206 { 0207 KMoreTools kmt(_("unittest-kmoretools/2")); 0208 const auto mynotInstalledApp = kmt.registerServiceByDesktopEntryName(_("mynotinstalledapp")); 0209 const auto menuBuilder = kmt.menuBuilder(); 0210 menuBuilder->addMenuItem(mynotInstalledApp); 0211 menuBuilder->addMenuItem(mynotInstalledApp); // duplicate (which can make sense if the service will be called with different arguments) 0212 QMenu menu; 0213 menuBuilder->buildByAppendingToMenu(&menu); 0214 QCOMPARE(menu.actions().count(), 4); // "Not installed section", "Not installed app" (only once), "Separator", "Configure menu..." 0215 } 0216 0217 void KMoreToolsTest::test_KMoreToolsPresets_registerServicesByGrouping() 0218 { 0219 KMoreTools kmt(_("unittest-kmoretools/3")); 0220 auto list = KMoreToolsPresets::registerServicesByGroupingNames(&kmt, {_("screenshot-take")}); 0221 0222 if (std::find_if(list.begin(), 0223 list.end(), 0224 [](KMoreToolsService *s) { 0225 return s->desktopEntryName() == _("org.kde.spectacle"); 0226 }) 0227 != list.end()) { 0228 QVERIFY(true); // at least spectacle should currently be present 0229 } else { 0230 QVERIFY(false); 0231 } 0232 } 0233 0234 void KMoreToolsTest::testMenuItemIdGen() 0235 { 0236 KmtMenuItemIdGen idGen; 0237 QCOMPARE(idGen.getId(_("a")), _("a0")); 0238 QCOMPARE(idGen.getId(_("a")), _("a1")); 0239 QCOMPARE(idGen.getId(_("b")), _("b0")); 0240 QCOMPARE(idGen.getId(_("a")), _("a2")); 0241 } 0242 0243 QDebug operator<<(QDebug d, const KmtMenuItemDto &m) 0244 { 0245 d << "id:" << m.id << ", section:" << m.menuSection << ", isInstalled:" << m.isInstalled; 0246 return d; 0247 } 0248 0249 void KMoreToolsTest::test_MenuItemDto_removeMenuAmpersand() 0250 { 0251 QCOMPARE(KmtMenuItemDto::removeMenuAmpersand(_("&Hallo")), _("Hallo")); 0252 QCOMPARE(KmtMenuItemDto::removeMenuAmpersand(_("Hall&o")), _("Hallo")); 0253 QCOMPARE(KmtMenuItemDto::removeMenuAmpersand(_("H&all&o")), _("Hallo")); // is this ok for menus items? 0254 QCOMPARE(KmtMenuItemDto::removeMenuAmpersand(_("&&Hallo")), _("&Hallo")); 0255 QCOMPARE(KmtMenuItemDto::removeMenuAmpersand(_("&Hall&&o")), _("Hall&o")); 0256 } 0257 0258 // Support method for KMoreToolsTest::test_MenuStructureDto_sortListBySection, 0259 // generates a list of menu items ordered by the passed-in indexes; this 0260 // helps test multiple permutations of the same list. Don't try *all* 0261 // permutations, since it's a stable sort -- items inside a section 0262 // must remain in the same relative order. 0263 // 0264 static void sortListBySection(int indexes[5]) 0265 { 0266 KmtMenuStructureDto mstruct; 0267 0268 KmtMenuItemDto ma1; 0269 ma1.id = QStringLiteral("main1"); 0270 ma1.menuSection = KMoreTools::MenuSection_Main; 0271 0272 KmtMenuItemDto mo1; 0273 mo1.id = QStringLiteral("more1"); 0274 mo1.menuSection = KMoreTools::MenuSection_More; 0275 0276 KmtMenuItemDto ma3; 0277 ma3.id = QStringLiteral("main3_ni"); 0278 ma3.menuSection = KMoreTools::MenuSection_Main; 0279 ma3.isInstalled = false; // !!! 0280 0281 KmtMenuItemDto mo2; 0282 mo2.id = QStringLiteral("more2"); 0283 mo2.menuSection = KMoreTools::MenuSection_More; 0284 0285 KmtMenuItemDto ma2; 0286 ma2.id = QStringLiteral("main2"); 0287 ma2.menuSection = KMoreTools::MenuSection_Main; 0288 0289 KmtMenuItemDto *items[5] = {&ma1, &mo1, &ma3, &mo2, &ma2}; 0290 0291 mstruct.list.clear(); 0292 for (unsigned int i = 0; i < 5; ++i) { 0293 mstruct.list.append(*items[indexes[i]]); 0294 } 0295 mstruct.stableSortListBySection(); 0296 0297 QCOMPARE(mstruct.list[0].id, _("main1")); // 1. main 0298 QCOMPARE(mstruct.list[1].id, _("main2")); 0299 QCOMPARE(mstruct.list[2].id, _("more1")); // 2. more 0300 QCOMPARE(mstruct.list[3].id, _("more2")); 0301 QCOMPARE(mstruct.list[4].id, _("main3_ni")); // 3. not installed 0302 } 0303 0304 void KMoreToolsTest::test_MenuStructureDto_sortListBySection() 0305 { 0306 int indexes_plain[5] = {0, 1, 2, 3, 4}; // In normal order 0307 int indexes_presorted[5] = {0, 4, 1, 3, 2}; 0308 int indexes_interleave[5] = {0, 1, 3, 4, 2}; 0309 int indexes_morefirst[5] = {1, 3, 0, 4, 2}; 0310 int indexes_uninstalledfirst[5] = {2, 1, 0, 4, 3}; 0311 // Permutations of where the uninstalled item is inserted 0312 int indexes_uninstalled_p0[5] = {2, 0, 1, 3, 4}; 0313 int indexes_uninstalled_p1[5] = {0, 2, 1, 3, 4}; 0314 int indexes_uninstalled_p2[5] = {0, 1, 2, 3, 4}; 0315 int indexes_uninstalled_p3[5] = {0, 1, 3, 2, 4}; 0316 int indexes_uninstalled_p4[5] = {0, 1, 3, 4, 2}; 0317 0318 qDebug() << "Plain"; 0319 sortListBySection(indexes_plain); 0320 qDebug() << "Presorted"; 0321 sortListBySection(indexes_presorted); 0322 qDebug() << "Interleaved"; 0323 sortListBySection(indexes_interleave); 0324 qDebug() << "'More' first"; 0325 sortListBySection(indexes_morefirst); 0326 qDebug() << "'Uninstalled' first"; 0327 sortListBySection(indexes_uninstalledfirst); 0328 qDebug() << "'Uninstalled' first, p0"; 0329 sortListBySection(indexes_uninstalled_p0); 0330 qDebug() << "'Uninstalled' first, p1"; 0331 sortListBySection(indexes_uninstalled_p1); 0332 qDebug() << "'Uninstalled' first, p2"; 0333 sortListBySection(indexes_uninstalled_p2); 0334 qDebug() << "'Uninstalled' first, p3"; 0335 sortListBySection(indexes_uninstalled_p3); 0336 qDebug() << "'Uninstalled' first, p4"; 0337 sortListBySection(indexes_uninstalled_p4); 0338 } 0339 0340 void KMoreToolsTest::test_MenuStructureDto_serialize() 0341 { 0342 KmtMenuStructureDto mstruct; 0343 0344 KmtMenuItemDto ma1; 0345 ma1.id = QStringLiteral("main1"); 0346 ma1.menuSection = KMoreTools::MenuSection_Main; 0347 mstruct.list.append(ma1); 0348 0349 KmtMenuItemDto mo1; 0350 mo1.id = QStringLiteral("more1"); 0351 mo1.menuSection = KMoreTools::MenuSection_More; 0352 mstruct.list.append(mo1); 0353 0354 QString json = mstruct.serialize(); 0355 QCOMPARE(json, 0356 QString(_("{\"menuitemlist\":[{\"id\":\"main1\",\"isInstalled\":true,\"menuSection\":\"main\"},{\"id\":\"more1\",\"isInstalled\":true," 0357 "\"menuSection\":\"more\"}]}"))); 0358 } 0359 0360 void KMoreToolsTest::test_MenuStructureDto_deserialize() 0361 { 0362 QString jsonStr( 0363 _("{\"menuitemlist\":[{\"id\":\"main1\",\"isInstalled\":true,\"menuSection\":\"main\"},{\"id\":\"more1\",\"isInstalled\":true,\"menuSection\":\"more\"}" 0364 "]}")); 0365 KmtMenuStructureDto mstruct; 0366 mstruct.deserialize(jsonStr); 0367 QCOMPARE(mstruct.list.count(), 2); 0368 KmtMenuItemDto ma1 = mstruct.list[0]; 0369 QCOMPARE(ma1.id, _("main1")); 0370 QCOMPARE(ma1.menuSection, KMoreTools::MenuSection_Main); 0371 QCOMPARE(ma1.isInstalled, true); 0372 } 0373 0374 void KMoreToolsTest::test_KmtUrlUtil_localFileAbsoluteDir() 0375 { 0376 { 0377 auto urlIn = QUrl::fromLocalFile(QStringLiteral("/etc/bash.bashrc")); 0378 QCOMPARE(urlIn.toString(), QString(_("file:///etc/bash.bashrc"))); 0379 0380 auto urlOut = KmtUrlUtil::localFileAbsoluteDir(urlIn); 0381 #ifdef Q_OS_WINDOWS 0382 QCOMPARE(urlOut.toString(), QString(_("file:///C:/etc"))); 0383 #else 0384 QCOMPARE(urlOut.toString(), QString(_("file:///etc"))); 0385 #endif 0386 } 0387 0388 { 0389 auto urlIn = QUrl::fromLocalFile(QStringLiteral("/home/u1/dev/kf5/src/kde/applications/dolphin/.reviewboardrc")); 0390 QCOMPARE(urlIn.toString(), QString(_("file:///home/u1/dev/kf5/src/kde/applications/dolphin/.reviewboardrc"))); 0391 0392 auto urlOut = KmtUrlUtil::localFileAbsoluteDir(urlIn); 0393 #ifdef Q_OS_WINDOWS 0394 QCOMPARE(urlOut.toString(), QString(_("file:///C:/home/u1/dev/kf5/src/kde/applications/dolphin"))); 0395 #else 0396 QCOMPARE(urlOut.toString(), QString(_("file:///home/u1/dev/kf5/src/kde/applications/dolphin"))); 0397 #endif 0398 } 0399 0400 { 0401 auto urlIn2 = QUrl::fromLocalFile(QStringLiteral("aaa/bbb")); 0402 QCOMPARE(urlIn2.toString(), QString(_("file:aaa/bbb"))); 0403 } 0404 } 0405 0406 QTEST_MAIN(KMoreToolsTest) 0407 0408 #include "kmoretoolstest.moc"