┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests')
-rw-r--r--src/tests/dolphinmainwindowtest.cpp110
-rw-r--r--src/tests/kfileitemmodeltest.cpp150
-rw-r--r--src/tests/testdir.cpp4
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();