diff options
Diffstat (limited to 'src/tests')
| -rw-r--r-- | src/tests/dolphinmainwindowtest.cpp | 110 | ||||
| -rw-r--r-- | src/tests/kfileitemmodeltest.cpp | 150 | ||||
| -rw-r--r-- | src/tests/testdir.cpp | 4 |
3 files changed, 262 insertions, 2 deletions
diff --git a/src/tests/dolphinmainwindowtest.cpp b/src/tests/dolphinmainwindowtest.cpp index f68f07cbc..21e48f246 100644 --- a/src/tests/dolphinmainwindowtest.cpp +++ b/src/tests/dolphinmainwindowtest.cpp @@ -16,9 +16,11 @@ #include "kitemviews/kitemlistcontroller.h" #include "kitemviews/kitemlistselectionmanager.h" #include "kitemviews/kitemlistwidget.h" +#include "settings/viewmodes/viewmodesettings.h" #include "testdir.h" #include "views/dolphinitemlistview.h" #include "views/viewproperties.h" +#include "views/zoomlevelinfo.h" #include <KActionCollection> #include <KConfig> @@ -69,6 +71,7 @@ private Q_SLOTS: void testThumbnailAfterRename(); void testViewModeAfterDynamicView(); void testActivationAndTabTitleAfterRenameOpeningFolder(); + void testActiveViewAfterTabSwitchWithSplitView(); void cleanupTestCase(); private: @@ -935,7 +938,7 @@ void DolphinMainWindowTest::testAccessibilityTree() // after going forwards which is probably not intended. } } - QCOMPARE_GE(testedObjectsSizeAfterTraversingForwards, 11); // The test did not reach many objects while using the Tab key to move through Dolphin. Did the + QCOMPARE_GE(testedObjectsSizeAfterTraversingForwards, 10); // The test did not reach many objects while using the Tab key to move through Dolphin. Did the // test run correctly? } @@ -1077,6 +1080,7 @@ void DolphinMainWindowTest::testThumbnailAfterRename() void DolphinMainWindowTest::testViewModeAfterDynamicView() { GeneralSettings *settings = GeneralSettings::self(); + settings->setGlobalViewProps(true); settings->setDynamicView(true); settings->save(); @@ -1144,6 +1148,9 @@ void DolphinMainWindowTest::testViewModeAfterDynamicView() QCOMPARE(view->m_mode, DolphinView::DetailsView); QVERIFY(!ViewProperties(view->viewPropertiesUrl()).dynamicViewPassed()); + // store parent current zoom level + const int parentZoomLevel = view->zoomLevel(); + // go to child folder and make sure view mode change to "Details" is permanent m_mainWindow->openFiles({testDirUrl + "/a"}, false); view->m_model->loadDirectory(QUrl(testDirUrl + "/a")); @@ -1151,6 +1158,60 @@ void DolphinMainWindowTest::testViewModeAfterDynamicView() QVERIFY(modelDirectoryLoadingCompletedSpy.wait()); QCOMPARE(view->m_mode, DolphinView::DetailsView); QVERIFY(ViewProperties(view->viewPropertiesUrl()).dynamicViewPassed()); + + // still on child, change view zoom level + const int childZoomLevel = view->zoomLevel() + 2; + view->setZoomLevel(childZoomLevel); + + // go back to parent folder and check for zoom level + m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::Back))->trigger(); + view->m_model->loadDirectory(testDir->url()); + view->setUrl(testDir->url()); + QVERIFY(modelDirectoryLoadingCompletedSpy.wait()); + QCOMPARE(view->zoomLevel(), parentZoomLevel); + QVERIFY(!ViewProperties(view->viewPropertiesUrl()).dynamicViewPassed()); + + // go to child and check if zoom level is permanent + m_mainWindow->openFiles({testDirUrl + "/a"}, false); + view->m_model->loadDirectory(QUrl(testDirUrl + "/a")); + view->setUrl(QUrl(testDirUrl + "/a")); + QVERIFY(modelDirectoryLoadingCompletedSpy.wait()); + QCOMPARE(view->zoomLevel(), childZoomLevel); + QVERIFY(ViewProperties(view->viewPropertiesUrl()).dynamicViewPassed()); + + // test for global views + settings->setGlobalViewProps(true); + settings->save(); + QVERIFY(GeneralSettings::globalViewProps()); + + // go back to parent folder and set zoom level + m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::Back))->trigger(); + view->m_model->loadDirectory(testDir->url()); + view->setUrl(testDir->url()); + QVERIFY(modelDirectoryLoadingCompletedSpy.wait()); + + // zoom isn't changed + QCOMPARE(view->zoomLevel(), childZoomLevel); + + // change the zoom + view->setZoomLevel(parentZoomLevel + 1); + QCOMPARE(view->zoomLevel(), parentZoomLevel + 1); + QVERIFY(!ViewProperties(view->viewPropertiesUrl()).dynamicViewPassed()); + + // go to child and check if zoom level remains the same + m_mainWindow->openFiles({testDirUrl + "/a"}, false); + view->m_model->loadDirectory(QUrl(testDirUrl + "/a")); + view->setUrl(QUrl(testDirUrl + "/a")); + QVERIFY(modelDirectoryLoadingCompletedSpy.wait()); + + ViewModeSettings modeDefaultSettings{DolphinView::IconsView}; + auto defaultPreviewIconSize = modeDefaultSettings.previewSize(); + auto defaultPreviewZoom = ZoomLevelInfo::zoomLevelForIconSize(QSize(defaultPreviewIconSize, defaultPreviewIconSize)); + // dynamic view works + QCOMPARE(view->m_mode, DolphinView::IconsView); + QCOMPARE(view->zoomLevel(), defaultPreviewZoom); + // that's the global settings, no dynamicViewPassed saved + QVERIFY(!ViewProperties(view->viewPropertiesUrl()).dynamicViewPassed()); } void DolphinMainWindowTest::testActivationAndTabTitleAfterRenameOpeningFolder() @@ -1232,6 +1293,53 @@ void DolphinMainWindowTest::testActivationAndTabTitleAfterRenameOpeningFolder() QCOMPARE(tabWidget->tabText(1), expectedNewTab1Title); } +// Test that switching tabs does not spuriously toggle which split-view pane is active. +// Regression test for the bug where DolphinTabPage::setActive(true) during tab switch +// caused DolphinView::activated() to reach slotViewActivated(), which toggled +// m_primaryViewActive and connected MainWindow signals to the wrong view container. +void DolphinMainWindowTest::testActiveViewAfterTabSwitchWithSplitView() +{ + m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false); + m_mainWindow->show(); + QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); + QVERIFY(m_mainWindow->isVisible()); + + auto tabWidget = m_mainWindow->findChild<DolphinTabWidget *>("tabWidget"); + QVERIFY(tabWidget); + + // Enable split view on the first tab. After this, the secondary (right) pane + // becomes active via slotViewActivated(), so primaryViewActive() is false. + m_mainWindow->actionCollection()->action(QStringLiteral("split_view"))->trigger(); + QVERIFY(tabWidget->currentTabPage()->splitViewEnabled()); + QVERIFY(!tabWidget->currentTabPage()->primaryViewActive()); + auto firstTabPage = tabWidget->currentTabPage(); + auto firstTabSecondary = firstTabPage->secondaryViewContainer(); + QVERIFY(firstTabSecondary->isActive()); + + // Open a second tab and switch to it. + tabWidget->openNewActivatedTab(QUrl::fromLocalFile(QDir::homePath())); + QCOMPARE(tabWidget->count(), 2); + QCOMPARE(tabWidget->currentIndex(), 1); + + // Spy on activeViewChanged to count emissions during the tab switch back. + QSignalSpy activeViewChangedSpy(tabWidget, &DolphinTabWidget::activeViewChanged); + + // Switch back to the first tab. + tabWidget->setCurrentIndex(0); + QCOMPARE(tabWidget->currentTabPage(), firstTabPage); + + // activeViewChanged must be emitted exactly once — by currentTabChanged itself. + // A spurious second emission would indicate slotViewActivated() fired during + // the programmatic setActive(true) and toggled m_primaryViewActive. + QCOMPARE(activeViewChangedSpy.count(), 1); + + // The secondary pane must still be the designated active one. + QVERIFY(!firstTabPage->primaryViewActive()); + QCOMPARE(firstTabPage->activeViewContainer(), firstTabSecondary); + QVERIFY(firstTabSecondary->isActive()); + QVERIFY(!firstTabPage->primaryViewContainer()->isActive()); +} + void DolphinMainWindowTest::cleanupTestCase() { m_mainWindow->showNormal(); diff --git a/src/tests/kfileitemmodeltest.cpp b/src/tests/kfileitemmodeltest.cpp index b8e0e9893..f61bc246f 100644 --- a/src/tests/kfileitemmodeltest.cpp +++ b/src/tests/kfileitemmodeltest.cpp @@ -70,6 +70,8 @@ private Q_SLOTS: void testRemoveFilteredExpandedItems(); void testSorting(); void testNaturalSorting(); + void testStringCompare_data(); + void testStringCompare(); void testIndexForKeyboardSearch(); void testNameFilter(); void testEmptyPath(); @@ -94,6 +96,7 @@ private Q_SLOTS: void testInsertAfterExpand(); void testCurrentDirRemoved(); void testSizeSortingAfterRefresh(); + void testFilterModesAndCaseSensitivity(); private: QStringList itemsInModel() const; @@ -1356,6 +1359,41 @@ void KFileItemModelTest::testNaturalSorting() QCOMPARE(itemsMovedSpy.takeFirst().at(1).value<QList<int>>(), QList<int>() << 4 << 6 << 1 << 2 << 3 << 5); } +void KFileItemModelTest::testStringCompare_data() +{ + QTest::addColumn<QString>("left"); + QTest::addColumn<QString>("right"); + QTest::addColumn<bool>("naturalSorting"); + QTest::addColumn<int>("expectedResult"); + + QTest::newRow("decimal") << QStringLiteral("0.09") << QStringLiteral("0.1") << true << -1; + QTest::newRow("version-patch") << QStringLiteral("v1.2.3") << QStringLiteral("v1.2.10") << true << -1; + QTest::newRow("version-patch-reversed") << QStringLiteral("v1.2.10") << QStringLiteral("v1.2.3") << true << 1; + QTest::newRow("version-minor") << QStringLiteral("v1.2.10") << QStringLiteral("v1.10.1") << true << -1; + QTest::newRow("numeric-basename-before-extension") << QStringLiteral("1.09.txt") << QStringLiteral("1.1.txt") << true << -1; + QTest::newRow("leading-dot-is-not-decimal") << QStringLiteral(".1") << QStringLiteral(".09") << true << -1; + QTest::newRow("natural-sorting-disabled") << QStringLiteral("v1.2.10") << QStringLiteral("v1.2.3") << false << -1; +} + +void KFileItemModelTest::testStringCompare() +{ + QFETCH(QString, left); + QFETCH(QString, right); + QFETCH(bool, naturalSorting); + QFETCH(int, expectedResult); + + QCollator collator; + collator.setNumericMode(true); + + m_model->m_naturalSorting = naturalSorting; + + const int result = m_model->stringCompare(left, right, collator); + QCOMPARE(result < 0 ? -1 : result > 0 ? 1 : 0, expectedResult); + + const int reverseResult = m_model->stringCompare(right, left, collator); + QCOMPARE(reverseResult < 0 ? -1 : reverseResult > 0 ? 1 : 0, -expectedResult); +} + void KFileItemModelTest::testIndexForKeyboardSearch() { QSignalSpy itemsInsertedSpy(m_model, &KFileItemModel::itemsInserted); @@ -2712,6 +2750,118 @@ void KFileItemModelTest::testCurrentDirRemoved() QCOMPARE(m_model->count(), 0); } +void KFileItemModelTest::testFilterModesAndCaseSensitivity() +{ + QSignalSpy itemsInsertedSpy(m_model, &KFileItemModel::itemsInserted); + + m_testDir->createFiles({"1_abc.txt", "2_aBc.txt", "3_a[b]c.txt", "4_test.txt", "5_test.cpp"}); + + m_model->loadDirectory(m_testDir->url()); + QVERIFY(itemsInsertedSpy.wait()); + + m_model->setSortRole("text"); + QCOMPARE(itemsInModel(), + QStringList() << "1_abc.txt" + << "2_aBc.txt" + << "3_a[b]c.txt" + << "4_test.txt" + << "5_test.cpp"); + + // Glob + case insensitive + // no need to set the these options here as they are the default ones + m_model->setNameFilter("*a?c*"); + QCOMPARE(itemsInModel(), QStringList() << "1_abc.txt" << "2_aBc.txt"); + + m_model->setNameFilter("*.txt"); + QCOMPARE(itemsInModel(), QStringList() << "1_abc.txt" << "2_aBc.txt" << "3_a[b]c.txt" << "4_test.txt"); + + m_model->setNameFilter("*a*c*"); + QCOMPARE(itemsInModel(), QStringList() << "1_abc.txt" << "2_aBc.txt" << "3_a[b]c.txt"); + + // Glob + case sensitive + m_model->setFilterCaseSensitive(true); + + m_model->setNameFilter("*bc*"); + QCOMPARE(itemsInModel(), QStringList() << "1_abc.txt"); + + m_model->setNameFilter("*Bc*"); + QCOMPARE(itemsInModel(), QStringList() << "2_aBc.txt"); + + m_model->setNameFilter("*.TXT"); + QCOMPARE(itemsInModel(), QStringList()); + + // PlainText + case insensitive + m_model->setFilterMode(KFileItemModelFilter::PlainText); + m_model->setFilterCaseSensitive(false); + + m_model->setNameFilter("bc"); + QCOMPARE(itemsInModel(), QStringList() << "1_abc.txt" << "2_aBc.txt"); + + m_model->setNameFilter("[b]"); + QCOMPARE(itemsInModel(), QStringList() << "3_a[b]c.txt"); + + // PlainText + case sensitive + m_model->setFilterCaseSensitive(true); + + m_model->setNameFilter("bc"); + QCOMPARE(itemsInModel(), QStringList() << "1_abc.txt"); + + m_model->setNameFilter("Bc"); + QCOMPARE(itemsInModel(), QStringList() << "2_aBc.txt"); + + m_model->setNameFilter("[b]"); + QCOMPARE(itemsInModel(), QStringList() << "3_a[b]c.txt"); + + // Regex + case insensitive + m_model->setFilterMode(KFileItemModelFilter::Regex); + m_model->setFilterCaseSensitive(false); + + m_model->setNameFilter("a.c"); + QCOMPARE(itemsInModel(), QStringList() << "1_abc.txt" << "2_aBc.txt"); + + m_model->setNameFilter("a[a-z]c"); + QCOMPARE(itemsInModel(), QStringList() << "1_abc.txt" << "2_aBc.txt"); + + m_model->setNameFilter("a.*c"); + QCOMPARE(itemsInModel(), QStringList() << "1_abc.txt" << "2_aBc.txt" << "3_a[b]c.txt"); + + m_model->setNameFilter("\\.txt$"); + QCOMPARE(itemsInModel(), QStringList() << "1_abc.txt" << "2_aBc.txt" << "3_a[b]c.txt" << "4_test.txt"); + + // Regex + case sensitive + m_model->setFilterCaseSensitive(true); + + m_model->setNameFilter("a[a-z]c"); + QCOMPARE(itemsInModel(), QStringList() << "1_abc.txt"); + + m_model->setNameFilter("a[A-Z]c"); + QCOMPARE(itemsInModel(), QStringList() << "2_aBc.txt"); + + m_model->setNameFilter("a\\[b\\]c"); + QCOMPARE(itemsInModel(), QStringList() << "3_a[b]c.txt"); + + // Invalid Glob + m_model->setFilterMode(KFileItemModelFilter::Glob); + + m_model->setNameFilter("a["); + QCOMPARE(itemsInModel(), QStringList()); + + // Invalid Regex + m_model->setFilterMode(KFileItemModelFilter::Regex); + + m_model->setNameFilter("(abc"); + QCOMPARE(itemsInModel(), QStringList()); + + // Clear filter, very that all the items reappear + m_model->setNameFilter(QString()); + QCOMPARE(itemsInModel(), + QStringList() << "1_abc.txt" + << "2_aBc.txt" + << "3_a[b]c.txt" + << "4_test.txt" + << "5_test.cpp"); +} + QStringList KFileItemModelTest::itemsInModel() const { QStringList items; diff --git a/src/tests/testdir.cpp b/src/tests/testdir.cpp index 30ca6632e..453a29784 100644 --- a/src/tests/testdir.cpp +++ b/src/tests/testdir.cpp @@ -48,7 +48,9 @@ void TestDir::createFile(const QString &path, const QByteArray &data, const QDat makePathAbsoluteAndCreateParents(absolutePath); QFile f(absolutePath); - f.open(QIODevice::WriteOnly); + if (!f.open(QIODevice::WriteOnly)) { + qFatal() << "could not open" << absolutePath; + } f.write(data); f.close(); |
