File indexing completed on 2024-12-01 09:52:41

0001 /*
0002     SPDX-FileCopyrightText: 2008 Peter Penz <peter.penz@gmx.at>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "kurlnavigatortest.h"
0008 #include <KFilePlacesModel>
0009 #include <KUser>
0010 #include <QDir>
0011 #include <QPushButton>
0012 #include <QStandardPaths>
0013 #include <QtTestWidgets>
0014 
0015 #include "kiotesthelper.h" // createTestDirectory(), createTestSymlink()
0016 #include "kurlcombobox.h"
0017 #include "kurlnavigator.h"
0018 #include <kprotocolinfo.h>
0019 
0020 QTEST_MAIN(KUrlNavigatorTest)
0021 
0022 void KUrlNavigatorTest::initTestCase()
0023 {
0024     QStandardPaths::setTestModeEnabled(true);
0025     m_navigator = new KUrlNavigator(nullptr, QUrl(QStringLiteral("file:///A")), nullptr);
0026 }
0027 
0028 void KUrlNavigatorTest::cleanupTestCase()
0029 {
0030     delete m_navigator;
0031     m_navigator = nullptr;
0032 }
0033 
0034 void KUrlNavigatorTest::testHistorySizeAndIndex()
0035 {
0036     QCOMPARE(m_navigator->historyIndex(), 0);
0037     QCOMPARE(m_navigator->historySize(), 1);
0038 
0039     m_navigator->setLocationUrl(QUrl(QStringLiteral("file:///A")));
0040 
0041     QCOMPARE(m_navigator->historyIndex(), 0);
0042     QCOMPARE(m_navigator->historySize(), 1);
0043 
0044     m_navigator->setLocationUrl(QUrl(QStringLiteral("file:///B")));
0045 
0046     QCOMPARE(m_navigator->historyIndex(), 0);
0047     QCOMPARE(m_navigator->historySize(), 2);
0048 
0049     m_navigator->setLocationUrl(QUrl(QStringLiteral("file:///C")));
0050 
0051     QCOMPARE(m_navigator->historyIndex(), 0);
0052     QCOMPARE(m_navigator->historySize(), 3);
0053 }
0054 
0055 void KUrlNavigatorTest::testGoBack()
0056 {
0057     QCOMPARE(m_navigator->historyIndex(), 0);
0058     QCOMPARE(m_navigator->historySize(), 3);
0059 
0060     bool ok = m_navigator->goBack();
0061 
0062     QVERIFY(ok);
0063     QCOMPARE(m_navigator->historyIndex(), 1);
0064     QCOMPARE(m_navigator->historySize(), 3);
0065 
0066     ok = m_navigator->goBack();
0067 
0068     QVERIFY(ok);
0069     QCOMPARE(m_navigator->historyIndex(), 2);
0070     QCOMPARE(m_navigator->historySize(), 3);
0071 
0072     ok = m_navigator->goBack();
0073 
0074     QVERIFY(!ok);
0075     QCOMPARE(m_navigator->historyIndex(), 2);
0076     QCOMPARE(m_navigator->historySize(), 3);
0077 }
0078 
0079 void KUrlNavigatorTest::testGoForward()
0080 {
0081     QCOMPARE(m_navigator->historyIndex(), 2);
0082     QCOMPARE(m_navigator->historySize(), 3);
0083 
0084     bool ok = m_navigator->goForward();
0085 
0086     QVERIFY(ok);
0087     QCOMPARE(m_navigator->historyIndex(), 1);
0088     QCOMPARE(m_navigator->historySize(), 3);
0089 
0090     ok = m_navigator->goForward();
0091 
0092     QVERIFY(ok);
0093     QCOMPARE(m_navigator->historyIndex(), 0);
0094     QCOMPARE(m_navigator->historySize(), 3);
0095 
0096     ok = m_navigator->goForward();
0097 
0098     QVERIFY(!ok);
0099     QCOMPARE(m_navigator->historyIndex(), 0);
0100     QCOMPARE(m_navigator->historySize(), 3);
0101 }
0102 
0103 void KUrlNavigatorTest::testHistoryInsert()
0104 {
0105     QCOMPARE(m_navigator->historyIndex(), 0);
0106     QCOMPARE(m_navigator->historySize(), 3);
0107 
0108     m_navigator->setLocationUrl(QUrl(QStringLiteral("file:///D")));
0109 
0110     QCOMPARE(m_navigator->historyIndex(), 0);
0111     QCOMPARE(m_navigator->historySize(), 4);
0112 
0113     bool ok = m_navigator->goBack();
0114     QVERIFY(ok);
0115     QCOMPARE(m_navigator->historyIndex(), 1);
0116     QCOMPARE(m_navigator->historySize(), 4);
0117 
0118     m_navigator->setLocationUrl(QUrl(QStringLiteral("file:///E")));
0119     QCOMPARE(m_navigator->historyIndex(), 0);
0120     QCOMPARE(m_navigator->historySize(), 4);
0121 
0122     m_navigator->setLocationUrl(QUrl(QStringLiteral("file:///F")));
0123     QCOMPARE(m_navigator->historyIndex(), 0);
0124     QCOMPARE(m_navigator->historySize(), 5);
0125 
0126     ok = m_navigator->goBack();
0127     QVERIFY(ok);
0128     ok = m_navigator->goBack();
0129     QVERIFY(ok);
0130     QCOMPARE(m_navigator->historyIndex(), 2);
0131     QCOMPARE(m_navigator->historySize(), 5);
0132 
0133     m_navigator->setLocationUrl(QUrl(QStringLiteral("file:///G")));
0134 
0135     QCOMPARE(m_navigator->historyIndex(), 0);
0136     QCOMPARE(m_navigator->historySize(), 4);
0137 
0138     // insert same URL as the current history index
0139     m_navigator->setLocationUrl(QUrl(QStringLiteral("file:///G")));
0140     QCOMPARE(m_navigator->historyIndex(), 0);
0141     QCOMPARE(m_navigator->historySize(), 4);
0142 
0143     // insert same URL with a trailing slash as the current history index
0144     m_navigator->setLocationUrl(QUrl(QStringLiteral("file:///G/")));
0145     QCOMPARE(m_navigator->historyIndex(), 0);
0146     QCOMPARE(m_navigator->historySize(), 4);
0147 
0148     // jump to "C" and insert same URL as the current history index
0149     ok = m_navigator->goBack();
0150     QVERIFY(ok);
0151     QCOMPARE(m_navigator->historyIndex(), 1);
0152     QCOMPARE(m_navigator->historySize(), 4);
0153 
0154     m_navigator->setLocationUrl(QUrl(QStringLiteral("file:///C")));
0155     QCOMPARE(m_navigator->historyIndex(), 1);
0156     QCOMPARE(m_navigator->historySize(), 4);
0157 }
0158 
0159 /**
0160  * When the current URL is inside an archive and the user goes "up", it is expected
0161  * that the new URL is that of the folder containing the archive (unless the URL was
0162  * in a subfolder inside the archive). Furthermore, the protocol should be "file".
0163  * An empty protocol would lead to problems in Dolphin, see
0164  *
0165  * https://bugs.kde.org/show_bug.cgi?id=251553
0166  */
0167 
0168 void KUrlNavigatorTest::bug251553_goUpFromArchive()
0169 {
0170     // TODO: write a dummy archive protocol handler to mock things in the test
0171     // or consider making kio_archive not a "kio-extra", but a default kio plugin
0172     if (!KProtocolInfo::isKnownProtocol(QStringLiteral("zip"))) {
0173         QSKIP("No zip protocol support installed (e.g. kio_archive or kio_krarc)");
0174     }
0175 
0176     m_navigator->setLocationUrl(QUrl(QStringLiteral("zip:/test/archive.zip")));
0177     QCOMPARE(m_navigator->locationUrl().path(), QLatin1String("/test/archive.zip"));
0178     QCOMPARE(m_navigator->locationUrl().scheme(), QLatin1String("zip"));
0179 
0180     bool ok = m_navigator->goUp();
0181     QVERIFY(ok);
0182     QCOMPARE(m_navigator->locationUrl().path(), QLatin1String("/test/"));
0183     QCOMPARE(m_navigator->locationUrl().scheme(), QLatin1String("file"));
0184 
0185     m_navigator->setLocationUrl(QUrl(QStringLiteral("tar:/test/archive.tar.gz")));
0186     QCOMPARE(m_navigator->locationUrl().path(), QLatin1String("/test/archive.tar.gz"));
0187     QCOMPARE(m_navigator->locationUrl().scheme(), QLatin1String("tar"));
0188 
0189     ok = m_navigator->goUp();
0190     QVERIFY(ok);
0191     QCOMPARE(m_navigator->locationUrl().path(), QLatin1String("/test/"));
0192     QCOMPARE(m_navigator->locationUrl().scheme(), QLatin1String("file"));
0193 }
0194 
0195 void KUrlNavigatorTest::testUrlParsing_data()
0196 {
0197     QTest::addColumn<QString>("input");
0198     QTest::addColumn<QUrl>("url");
0199     // due to a bug in the KF5 porting input such as '/home/foo/.config' was parsed as 'http:///home/foo/.config/'.
0200     QTest::newRow("hiddenFile") << QStringLiteral("/home/foo/.config") << QUrl::fromLocalFile(QStringLiteral("/home/foo/.config"));
0201     // TODO: test this on windows: e.g. 'C:/foo/.config' or 'C:\foo\.config'
0202     QTest::newRow("homeDir") << QStringLiteral("~") << QUrl::fromLocalFile(QDir::homePath());
0203     KUser user(KUser::UseRealUserID);
0204     QTest::newRow("userHomeDir") << (QStringLiteral("~") + user.loginName()) << QUrl::fromLocalFile(user.homeDir());
0205 }
0206 
0207 void KUrlNavigatorTest::testUrlParsing()
0208 {
0209     QFETCH(QString, input);
0210     QFETCH(QUrl, url);
0211 
0212     m_navigator->setLocationUrl(QUrl());
0213     m_navigator->setUrlEditable(true);
0214     m_navigator->editor()->setCurrentText(input);
0215     QCOMPARE(m_navigator->uncommittedUrl(), url);
0216     QTest::keyClick(m_navigator->editor(), Qt::Key_Enter);
0217     QCOMPARE(m_navigator->locationUrl(), url);
0218 }
0219 
0220 void KUrlNavigatorTest::testRelativePaths()
0221 {
0222     QTemporaryDir tempDir;
0223     const QString tempDirPath = tempDir.path();
0224     const QString dirA = tempDirPath + QLatin1String("/a");
0225     const QString dirB = tempDirPath + QLatin1String("/a/b");
0226     const QString dirC = tempDirPath + QLatin1String("/.c");
0227     const QString link = tempDirPath + QLatin1String("/l");
0228     createTestDirectory(dirA);
0229     createTestDirectory(dirB);
0230     createTestDirectory(dirC);
0231     createTestSymlink(link, dirA.toLatin1());
0232 
0233     QVERIFY(QFile::exists(dirA));
0234     QVERIFY(QFile::exists(dirB));
0235     QVERIFY(QFile::exists(dirC));
0236     QVERIFY(QFile::exists(link));
0237 
0238     const QUrl tempDirUrl = QUrl::fromLocalFile(tempDirPath);
0239     const QUrl dirAUrl = QUrl::fromLocalFile(dirA);
0240     const QUrl linkUrl = QUrl::fromLocalFile(link);
0241 
0242     // Change to tempDir
0243     m_navigator->setLocationUrl(tempDirUrl);
0244     m_navigator->setUrlEditable(true);
0245     QCOMPARE(m_navigator->locationUrl(), tempDirUrl);
0246 
0247     // QTRY_COMPARE because of waiting for the stat job in applyUncommittedUrl() to finish
0248 
0249     // Replace all the text with "a"
0250     m_navigator->editor()->setCurrentText(QStringLiteral("a"));
0251     QTest::keyClick(m_navigator->editor(), Qt::Key_Enter);
0252     QTRY_COMPARE(m_navigator->locationUrl(), dirAUrl);
0253 
0254     // Replace all the text with "b"
0255     m_navigator->editor()->setCurrentText(QStringLiteral("b"));
0256     QTest::keyClick(m_navigator->editor(), Qt::Key_Enter);
0257     QTRY_COMPARE(m_navigator->locationUrl(), QUrl::fromLocalFile(dirB));
0258 
0259     // Test "../", which should go up in the dir hierarchy
0260     m_navigator->editor()->setCurrentText(QStringLiteral("../"));
0261     QTest::keyClick(m_navigator->editor(), Qt::Key_Enter);
0262     QTRY_COMPARE(m_navigator->locationUrl().adjusted(QUrl::StripTrailingSlash), dirAUrl);
0263     // Test "..", which should go up in the dir hierarchy
0264     m_navigator->editor()->setCurrentText(QStringLiteral(".."));
0265     QTest::keyClick(m_navigator->editor(), Qt::Key_Enter);
0266     QTRY_COMPARE(m_navigator->locationUrl(), tempDirUrl);
0267 
0268     // Replace all the text with ".c"
0269     m_navigator->editor()->setCurrentText(QStringLiteral(".c"));
0270     QTest::keyClick(m_navigator->editor(), Qt::Key_Enter);
0271     QTRY_COMPARE(m_navigator->locationUrl(), QUrl::fromLocalFile(dirC));
0272 
0273     // Back to tempDir
0274     m_navigator->setLocationUrl(tempDirUrl);
0275     QCOMPARE(m_navigator->locationUrl(), tempDirUrl);
0276 
0277     // Replace all the text with "/a" - make sure this is handled as absolute path
0278     m_navigator->editor()->setCurrentText(QStringLiteral("/a"));
0279     QTest::keyClick(m_navigator->editor(), Qt::Key_Enter);
0280     QTRY_COMPARE(m_navigator->locationUrl(), QUrl::fromLocalFile("/a"));
0281 
0282     // Back to tempDir
0283     m_navigator->setLocationUrl(tempDirUrl);
0284     QCOMPARE(m_navigator->locationUrl(), tempDirUrl);
0285     // Replace all the text with "l" which is a symlink to dirA
0286     m_navigator->editor()->setCurrentText(QStringLiteral("l"));
0287     QTest::keyClick(m_navigator->editor(), Qt::Key_Enter);
0288     QTRY_COMPARE(m_navigator->locationUrl(), linkUrl);
0289 
0290     // Back to tempDir
0291     m_navigator->setLocationUrl(tempDirUrl);
0292     QCOMPARE(m_navigator->locationUrl(), tempDirUrl);
0293     // Replace all the text with "a/b"
0294     m_navigator->editor()->setCurrentText(QStringLiteral("a/b"));
0295     QTest::keyClick(m_navigator->editor(), Qt::Key_Enter);
0296     QTRY_COMPARE(m_navigator->locationUrl(), QUrl::fromLocalFile(dirB));
0297     // Now got to l "../../l"
0298     m_navigator->editor()->setCurrentText(QStringLiteral("../../l"));
0299     QTest::keyClick(m_navigator->editor(), Qt::Key_Enter);
0300     QTRY_COMPARE(m_navigator->locationUrl(), linkUrl);
0301 }
0302 
0303 void KUrlNavigatorTest::testFixUrlPath_data()
0304 {
0305     QTest::addColumn<QString>("input");
0306     QTest::addColumn<QUrl>("url");
0307     // ":local" KProtocols, a '/' is added so that the url "path" isn't empty
0308     QTest::newRow("trashKIO") << (QStringLiteral("trash:")) << QUrl(QStringLiteral("trash:/"));
0309     // QUrl setPath("/") results in "file:///"
0310     QTest::newRow("fileKIO") << (QStringLiteral("file:")) << QUrl(QStringLiteral("file:///"));
0311 }
0312 
0313 void KUrlNavigatorTest::testFixUrlPath()
0314 {
0315     QFETCH(QString, input);
0316     QFETCH(QUrl, url);
0317 
0318     m_navigator->setLocationUrl(QUrl());
0319     m_navigator->setUrlEditable(true);
0320     m_navigator->editor()->setCurrentText(input);
0321     QTest::keyClick(m_navigator->editor(), Qt::Key_Enter);
0322     QCOMPARE(m_navigator->locationUrl(), url);
0323 }
0324 
0325 #if KIOFILEWIDGETS_BUILD_DEPRECATED_SINCE(4, 5)
0326 void KUrlNavigatorTest::testButtonUrl_data()
0327 {
0328     QTest::addColumn<QUrl>("locationUrl");
0329     QTest::addColumn<int>("buttonIndex");
0330     QTest::addColumn<QUrl>("expectedButtonUrl");
0331 
0332     QTest::newRow("localPathButtonIndex3") << QUrl::fromLocalFile(QStringLiteral("/home/foo")) << 3
0333                                            << QUrl::fromLocalFile(QStringLiteral("/home/foo")); // out of range
0334     QTest::newRow("localPathButtonIndex2") << QUrl::fromLocalFile(QStringLiteral("/home/foo")) << 2 << QUrl::fromLocalFile(QStringLiteral("/home/foo"));
0335     QTest::newRow("localPathButtonIndex1") << QUrl::fromLocalFile(QStringLiteral("/home/foo")) << 1 << QUrl::fromLocalFile(QStringLiteral("/home"));
0336     QTest::newRow("localPathButtonIndex0") << QUrl::fromLocalFile(QStringLiteral("/home/foo")) << 0 << QUrl::fromLocalFile(QStringLiteral("/"));
0337 
0338     QTest::newRow("networkPathButtonIndex1") << QUrl::fromUserInput(QStringLiteral("network:/konqi.local/share")) << 1
0339                                              << QUrl::fromUserInput(QStringLiteral("network:/konqi.local"));
0340     QTest::newRow("networkPathButtonIndex0") << QUrl::fromUserInput(QStringLiteral("network:/konqi.local/share")) << 0
0341                                              << QUrl::fromUserInput(QStringLiteral("network:/"));
0342 
0343     QTest::newRow("ftpPathButtonIndex1") << QUrl::fromUserInput(QStringLiteral("ftp://kde.org/home/foo")) << 1
0344                                          << QUrl::fromUserInput(QStringLiteral("ftp://kde.org/home"));
0345     QTest::newRow("ftpPathButtonIndex0") << QUrl::fromUserInput(QStringLiteral("ftp://kde.org/home/foo")) << 0
0346                                          << QUrl::fromUserInput(QStringLiteral("ftp://kde.org/"));
0347 
0348     // bug 354678
0349     QTest::newRow("localPathWithPercentage") << QUrl::fromLocalFile(QStringLiteral("/home/foo %/test")) << 2
0350                                              << QUrl::fromLocalFile(QStringLiteral("/home/foo %"));
0351 }
0352 
0353 void KUrlNavigatorTest::testButtonUrl()
0354 {
0355     QFETCH(QUrl, locationUrl);
0356     QFETCH(int, buttonIndex);
0357     QFETCH(QUrl, expectedButtonUrl);
0358 
0359     // PREPARE
0360     m_navigator->setLocationUrl(locationUrl);
0361 
0362     // WHEN
0363     const QUrl buttonUrl = m_navigator->url(buttonIndex);
0364 
0365     // THEN
0366     QCOMPARE(buttonUrl, expectedButtonUrl);
0367 }
0368 #endif
0369 
0370 void KUrlNavigatorTest::testButtonText()
0371 {
0372     KFilePlacesModel model;
0373     const QUrl url = QUrl::fromLocalFile(QDir::currentPath());
0374     model.addPlace("&Here", url);
0375     KUrlNavigator navigator(&model, url, nullptr);
0376 
0377     QList<QPushButton *> buttons = navigator.findChildren<QPushButton *>();
0378     const auto it = std::find_if(buttons.cbegin(), buttons.cend(), [](QPushButton *button) {
0379         return button->text() == QLatin1String("&Here");
0380     });
0381     QVERIFY(it != buttons.cend());
0382     QCOMPARE((*it)->property("plainText").toString(), QStringLiteral("Here"));
0383 }
0384 
0385 void KUrlNavigatorTest::testInitWithRedundantPathSeparators()
0386 {
0387     KUrlNavigator temp_nav(nullptr, QUrl::fromLocalFile(QStringLiteral("/home/foo///test")), nullptr);
0388 
0389     const QUrl buttonUrl = temp_nav.locationUrl();
0390 
0391     QCOMPARE(buttonUrl, QUrl::fromLocalFile(QStringLiteral("/home/foo/test")));
0392 }
0393 
0394 #include "moc_kurlnavigatortest.cpp"