#include "testdir.h"
#include <KActionCollection>
+#include <KConfig>
+#include <KConfigGui>
+#include <QAccessible>
+#include <QFileSystemWatcher>
#include <QScopedPointer>
#include <QSignalSpy>
#include <QStandardPaths>
#include <QTest>
+#include <set>
+
class DolphinMainWindowTest : public QObject
{
Q_OBJECT
void testWindowTitle();
void testPlacesPanelWidthResistance();
void testGoActions();
+ void testOpenFiles();
+ void testAccessibilityAncestorTree();
+ void testAutoSaveSession();
void cleanupTestCase();
-
private:
QScopedPointer<DolphinMainWindow> m_mainWindow;
};
// See https://bugs.kde.org/show_bug.cgi?id=379135
void DolphinMainWindowTest::testClosingTabsWithSearchBoxVisible()
{
- m_mainWindow->openDirectories({ QUrl::fromLocalFile(QDir::homePath()) }, false);
+ m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false);
m_mainWindow->show();
// Without this call the searchbox doesn't get FocusIn events.
QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data()));
QVERIFY(m_mainWindow->isVisible());
- auto tabWidget = m_mainWindow->findChild<DolphinTabWidget*>("tabWidget");
+ auto tabWidget = m_mainWindow->findChild<DolphinTabWidget *>("tabWidget");
QVERIFY(tabWidget);
// Show search box on first tab.
void DolphinMainWindowTest::testActiveViewAfterClosingSplitView()
{
- m_mainWindow->openDirectories({ QUrl::fromLocalFile(QDir::homePath()) }, false);
+ 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");
+ auto tabWidget = m_mainWindow->findChild<DolphinTabWidget *>("tabWidget");
QVERIFY(tabWidget);
QVERIFY(tabWidget->currentTabPage()->primaryViewContainer());
QVERIFY(!tabWidget->currentTabPage()->secondaryViewContainer());
// Test case for bug #385111
void DolphinMainWindowTest::testUpdateWindowTitleAfterClosingSplitView()
{
- m_mainWindow->openDirectories({ QUrl::fromLocalFile(QDir::homePath()) }, false);
+ 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");
+ auto tabWidget = m_mainWindow->findChild<DolphinTabWidget *>("tabWidget");
QVERIFY(tabWidget);
QVERIFY(tabWidget->currentTabPage()->primaryViewContainer());
QVERIFY(!tabWidget->currentTabPage()->secondaryViewContainer());
// Test case for bug #402641
void DolphinMainWindowTest::testUpdateWindowTitleAfterChangingSplitView()
{
- m_mainWindow->openDirectories({ QUrl::fromLocalFile(QDir::homePath()) }, false);
+ 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");
+ auto tabWidget = m_mainWindow->findChild<DolphinTabWidget *>("tabWidget");
QVERIFY(tabWidget);
// Open split view.
// Test case for bug #397910
void DolphinMainWindowTest::testOpenInNewTabTitle()
{
- m_mainWindow->openDirectories({ QUrl::fromLocalFile(QDir::homePath()) }, false);
+ 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");
+ auto tabWidget = m_mainWindow->findChild<DolphinTabWidget *>("tabWidget");
QVERIFY(tabWidget);
tabWidget->openNewTab(QUrl::fromLocalFile(QDir::tempPath()));
void DolphinMainWindowTest::testNewFileMenuEnabled()
{
QFETCH(QUrl, activeViewUrl);
- m_mainWindow->openDirectories({ activeViewUrl }, false);
+ m_mainWindow->openDirectories({activeViewUrl}, false);
m_mainWindow->show();
QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data()));
QVERIFY(m_mainWindow->isVisible());
- auto newFileMenu = m_mainWindow->findChild<DolphinNewFileMenu*>("new_menu");
+ auto newFileMenu = m_mainWindow->findChild<DolphinNewFileMenu *>("new_menu");
QVERIFY(newFileMenu);
QFETCH(bool, expectedEnabled);
void DolphinMainWindowTest::testWindowTitle()
{
QFETCH(QUrl, activeViewUrl);
- m_mainWindow->openDirectories({ activeViewUrl }, false);
+ m_mainWindow->openDirectories({activeViewUrl}, false);
m_mainWindow->show();
QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data()));
QVERIFY(m_mainWindow->isVisible());
*/
void DolphinMainWindowTest::testPlacesPanelWidthResistance()
{
- m_mainWindow->openDirectories({ QUrl::fromLocalFile(QDir::homePath()) }, false);
+ m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false);
m_mainWindow->show();
+ m_mainWindow->resize(800, m_mainWindow->height()); // make sure the size is sufficient so a places panel resize shouldn't be necessary.
QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data()));
QVERIFY(m_mainWindow->isVisible());
QWidget *placesPanel = reinterpret_cast<QWidget *>(m_mainWindow->m_placesPanel);
- QVERIFY2(QTest::qWaitFor([&](){ return placesPanel && placesPanel->isVisible() && placesPanel->width() > 0; }, 5000), "The test couldn't be initialised properly. The places panel should be visible.");
+ QVERIFY2(QTest::qWaitFor(
+ [&]() {
+ return placesPanel && placesPanel->isVisible() && placesPanel->width() > 0;
+ },
+ 5000),
+ "The test couldn't be initialised properly. The places panel should be visible.");
QTest::qWait(100);
const int initialPlacesPanelWidth = placesPanel->width();
m_mainWindow->actionCollection()->action(QStringLiteral("show_filter_bar"))->trigger();
QCOMPARE(placesPanel->width(), initialPlacesPanelWidth);
+ // Make all selection mode bars appear and test for each that this doesn't affect the places panel's width.
+ // One of the bottom bars (SelectionMode::BottomBar::GeneralContents) only shows up when at least one item is selected so we do that before we begin iterating.
+ m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::SelectAll))->trigger();
+ for (int selectionModeStates = SelectionMode::BottomBar::CopyContents; selectionModeStates != SelectionMode::BottomBar::RenameContents;
+ selectionModeStates++) {
+ const auto contents = static_cast<SelectionMode::BottomBar::Contents>(selectionModeStates);
+ m_mainWindow->slotSetSelectionMode(true, contents);
+ QTest::qWait(20); // give time for a paint/resize
+ QCOMPARE(placesPanel->width(), initialPlacesPanelWidth);
+ }
+
m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::Find))->trigger();
QCOMPARE(placesPanel->width(), initialPlacesPanelWidth);
testDir->createFile("b/b-2");
testDir->createDir("c");
QUrl childDirUrl(QDir::cleanPath(testDir->url().toString() + "/b"));
- m_mainWindow->openDirectories({ childDirUrl }, false); // Open "b" dir
+ m_mainWindow->openDirectories({childDirUrl}, false); // Open "b" dir
m_mainWindow->show();
QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data()));
QVERIFY(m_mainWindow->isVisible());
*/
QSignalSpy spyDirectoryLoadingCompleted(m_mainWindow->m_activeViewContainer->view(), &DolphinView::directoryLoadingCompleted);
QVERIFY(spyDirectoryLoadingCompleted.wait());
- QVERIFY(QTest::qWaitFor([&](){ return !m_mainWindow->actionCollection()->action(QStringLiteral("stop"))->isEnabled(); })); // "Stop" command should be disabled because it finished loading
+ QVERIFY(QTest::qWaitFor([&]() {
+ return !m_mainWindow->actionCollection()->action(QStringLiteral("stop"))->isEnabled();
+ })); // "Stop" command should be disabled because it finished loading
QTest::qWait(500); // Somehow the item we emerged from doesn't have keyboard focus yet if we don't wait a split second.
const QUrl parentDirUrl = m_mainWindow->activeViewContainer()->url();
QVERIFY(parentDirUrl != childDirUrl);
QVERIFY(m_mainWindow->actionCollection()->action(QStringLiteral("undo_close_tab"))->isEnabled());
}
+void DolphinMainWindowTest::testOpenFiles()
+{
+ QScopedPointer<TestDir> testDir{new TestDir()};
+ QString testDirUrl(QDir::cleanPath(testDir->url().toString()));
+ testDir->createDir("a");
+ testDir->createDir("a/b");
+ testDir->createDir("a/b/c");
+ testDir->createDir("a/b/c/d");
+ m_mainWindow->openDirectories({testDirUrl}, false);
+ m_mainWindow->show();
+
+ // We only see the unselected "a" folder in the test dir. There are no other tabs.
+ QVERIFY(m_mainWindow->isUrlOpen(testDirUrl));
+ QVERIFY(m_mainWindow->isItemVisibleInAnyView(testDirUrl + "/a"));
+ QVERIFY(!m_mainWindow->isUrlOpen(testDirUrl + "/a"));
+ QVERIFY(!m_mainWindow->isItemVisibleInAnyView(testDirUrl + "/a/b"));
+ QCOMPARE(m_mainWindow->m_tabWidget->count(), 1);
+ QCOMPARE(m_mainWindow->m_tabWidget->currentIndex(), 0);
+ QCOMPARE(m_mainWindow->m_activeViewContainer->view()->selectedItems().count(), 0);
+
+ // "a" is already in view, so "opening" "a" should simply select it without opening a new tab.
+ m_mainWindow->openFiles({testDirUrl + "/a"}, false);
+ QTRY_COMPARE(m_mainWindow->m_activeViewContainer->view()->selectedItems().count(), 1);
+ QCOMPARE(m_mainWindow->m_tabWidget->count(), 1);
+ QVERIFY(m_mainWindow->isItemVisibleInAnyView(testDirUrl + "/a"));
+
+ // "b" is not in view, so "opening" "b" should open a new active tab of the parent folder "a" and select "b" there.
+ m_mainWindow->openFiles({testDirUrl + "/a/b"}, false);
+ QTRY_VERIFY(m_mainWindow->isUrlOpen(testDirUrl + "/a"));
+ QCOMPARE(m_mainWindow->m_tabWidget->count(), 2);
+ QCOMPARE(m_mainWindow->m_tabWidget->currentIndex(), 1);
+ QTRY_VERIFY(m_mainWindow->isItemVisibleInAnyView(testDirUrl + "/a/b"));
+ QVERIFY2(!m_mainWindow->isUrlOpen(testDirUrl + "/a/b"), "The directory b is supposed to be visible but not open in its own tab.");
+ QTRY_COMPARE(m_mainWindow->m_activeViewContainer->view()->selectedItems().count(), 1);
+
+ QVERIFY(m_mainWindow->isUrlOpen(testDirUrl));
+ QVERIFY(m_mainWindow->isItemVisibleInAnyView(testDirUrl + "/a"));
+ // "a" is still in view in the first tab, so "opening" "a" should switch to the first tab and select "a" there.
+ m_mainWindow->openFiles({testDirUrl + "/a"}, false);
+ QCOMPARE(m_mainWindow->m_tabWidget->count(), 2);
+ QCOMPARE(m_mainWindow->m_tabWidget->currentIndex(), 0);
+ QVERIFY(m_mainWindow->isUrlOpen(testDirUrl));
+ QVERIFY(m_mainWindow->isUrlOpen(testDirUrl + "/a"));
+
+ // Directory "a" is already open in the second tab in which "b" is selected, so opening the directory "a" should switch to that tab.
+ m_mainWindow->openDirectories({testDirUrl + "/a"}, false);
+ QCOMPARE(m_mainWindow->m_tabWidget->count(), 2);
+ QCOMPARE(m_mainWindow->m_tabWidget->currentIndex(), 1);
+
+ // In the details view mode directories can be expanded, which changes if openFiles() needs to open a new tab or not to open a file.
+ m_mainWindow->actionCollection()->action(QStringLiteral("details"))->trigger();
+ QTRY_VERIFY(m_mainWindow->activeViewContainer()->view()->itemsExpandable());
+
+ // Expand the already selected "b" with the right arrow key. This should make "c" visible.
+ QVERIFY2(!m_mainWindow->isItemVisibleInAnyView(testDirUrl + "/a/b/c"), "The parent folder wasn't expanded yet, so c shouldn't be visible.");
+ QTest::keyClick(m_mainWindow->activeViewContainer()->view()->m_container, Qt::Key::Key_Right);
+ QTRY_VERIFY(m_mainWindow->isItemVisibleInAnyView(testDirUrl + "/a/b/c"));
+ QVERIFY2(!m_mainWindow->isUrlOpen(testDirUrl + "/a/b"), "b is supposed to be expanded, however it shouldn't be open in its own tab.");
+ QVERIFY(m_mainWindow->isUrlOpen(testDirUrl + "/a"));
+
+ // Switch to first tab by opening it even though it is already open.
+ m_mainWindow->openDirectories({testDirUrl}, false);
+ QCOMPARE(m_mainWindow->m_tabWidget->count(), 2);
+ QCOMPARE(m_mainWindow->m_tabWidget->currentIndex(), 0);
+
+ // "c" is in view in the second tab because "b" is expanded there, so "opening" "c" should switch to that tab and select "c" there.
+ m_mainWindow->openFiles({testDirUrl + "/a/b/c"}, false);
+ QCOMPARE(m_mainWindow->m_tabWidget->count(), 2);
+ QCOMPARE(m_mainWindow->m_tabWidget->currentIndex(), 1);
+ QTRY_COMPARE(m_mainWindow->m_activeViewContainer->view()->selectedItems().count(), 1);
+ QVERIFY(m_mainWindow->isUrlOpen(testDirUrl));
+ QVERIFY(m_mainWindow->isUrlOpen(testDirUrl + "/a"));
+
+ // Opening the directory "c" on the other hand will open it in a new tab even though it is already visible in the view
+ // because openDirecories() and openFiles() serve different purposes. One opens views at urls, the other selects files within views.
+ m_mainWindow->openDirectories({testDirUrl + "/a/b/c/d", testDirUrl + "/a/b/c"}, true);
+ QCOMPARE(m_mainWindow->m_tabWidget->count(), 3);
+ QCOMPARE(m_mainWindow->m_tabWidget->currentIndex(), 2);
+ QVERIFY(m_mainWindow->m_tabWidget->currentTabPage()->splitViewEnabled());
+ QVERIFY(m_mainWindow->isItemVisibleInAnyView(testDirUrl + "/a/b/c")); // It should still be visible in the second tab.
+ QTRY_COMPARE(m_mainWindow->m_activeViewContainer->view()->selectedItems().count(), 0);
+ QVERIFY(m_mainWindow->isUrlOpen(testDirUrl + "/a/b/c/d"));
+ QVERIFY(m_mainWindow->isUrlOpen(testDirUrl + "/a/b/c"));
+
+ // "c" is in view in the second tab because "b" is expanded there,
+ // so "opening" "c" should switch to that tab even though "c" as a directory is open in the current tab.
+ m_mainWindow->openFiles({testDirUrl + "/a/b/c"}, false);
+ QCOMPARE(m_mainWindow->m_tabWidget->count(), 3);
+ QCOMPARE(m_mainWindow->m_tabWidget->currentIndex(), 1);
+ QVERIFY2(m_mainWindow->isItemVisibleInAnyView(testDirUrl + "/a/b/c/d"), "It should be visible in the secondary view of the third tab.");
+
+ // Select "b" and un-expand it with the left arrow key. This should make "c" invisible.
+ m_mainWindow->openFiles({testDirUrl + "/a/b"}, false);
+ QTest::keyClick(m_mainWindow->activeViewContainer()->view()->m_container, Qt::Key::Key_Left);
+ QTRY_VERIFY(!m_mainWindow->isItemVisibleInAnyView(testDirUrl + "/a/b/c"));
+
+ // "d" is in view in the third tab in the secondary view, so "opening" "d" should select that view.
+ m_mainWindow->openFiles({testDirUrl + "/a/b/c/d"}, false);
+ QCOMPARE(m_mainWindow->m_tabWidget->count(), 3);
+ QCOMPARE(m_mainWindow->m_tabWidget->currentIndex(), 2);
+ QVERIFY(m_mainWindow->m_tabWidget->currentTabPage()->secondaryViewContainer()->isActive());
+ QTRY_COMPARE(m_mainWindow->m_activeViewContainer->view()->selectedItems().count(), 1);
+}
+
+void DolphinMainWindowTest::testAccessibilityAncestorTree()
+{
+ m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false);
+ m_mainWindow->show();
+ QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data()));
+ QVERIFY(m_mainWindow->isVisible());
+
+ std::set<const QObject *> testedObjects; // Makes sure we stop testing if we arrive at an item that was already tested.
+ QAccessibleInterface *accessibleInterfaceOfMainWindow = QAccessible::queryAccessibleInterface(m_mainWindow.get());
+ Q_CHECK_PTR(accessibleInterfaceOfMainWindow);
+
+ // We will do accessibility checks for every object that gets focus. Focus will be changed using the Tab key.
+ while (qApp->focusObject() && !testedObjects.count(qApp->focusObject())) {
+ const auto currentlyFocusedObject = qApp->focusObject();
+ QAccessibleInterface *accessibleInterface = QAccessible::queryAccessibleInterface(currentlyFocusedObject);
+
+ // The accessibleInterfaces of focused objects might themselves have children.
+ // We go down that hierarchy as far as possible and then test the ancestor tree from there.
+ while (accessibleInterface->childCount() > 0) {
+ accessibleInterface = accessibleInterface->child(0);
+ }
+ while (accessibleInterface != accessibleInterfaceOfMainWindow) {
+ QVERIFY2(accessibleInterface,
+ qPrintable(QString("%1's accessibleInterface or one of its accessible children doesn't have the main window as an ancestor.")
+ .arg(currentlyFocusedObject->metaObject()->className())));
+ accessibleInterface = accessibleInterface->parent();
+ }
+
+ testedObjects.insert(currentlyFocusedObject); // Add it to testedObjects so we won't test it again later.
+ QTest::keyClick(m_mainWindow.get(), Qt::Key::Key_Tab, Qt::ShiftModifier); // ShiftModifier because the Tab cycle is currently broken going forward.
+ }
+}
+
+void DolphinMainWindowTest::testAutoSaveSession()
+{
+ m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false);
+ m_mainWindow->show();
+ QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data()));
+ QVERIFY(m_mainWindow->isVisible());
+
+ // Create config file
+ KConfigGui::setSessionConfig(QStringLiteral("dolphin"), QStringLiteral("dolphin"));
+ KConfig *config = KConfigGui::sessionConfig();
+ m_mainWindow->saveGlobalProperties(config);
+ m_mainWindow->savePropertiesInternal(config, 1);
+ config->sync();
+
+ // Setup watcher for config file changes
+ const QString configFileName = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/" + KConfigGui::sessionConfig()->name();
+ QFileSystemWatcher *configWatcher = new QFileSystemWatcher({configFileName}, this);
+ QSignalSpy spySessionSaved(configWatcher, &QFileSystemWatcher::fileChanged);
+
+ // Enable session autosave.
+ m_mainWindow->setSessionAutoSaveEnabled(true);
+
+ // Open a new tab
+ auto tabWidget = m_mainWindow->findChild<DolphinTabWidget *>("tabWidget");
+ QVERIFY(tabWidget);
+ tabWidget->openNewActivatedTab(QUrl::fromLocalFile(QDir::tempPath()));
+ QCOMPARE(tabWidget->count(), 2);
+
+ // Wait till a session save occurs
+ QVERIFY(spySessionSaved.wait(60000));
+
+ // Disable session autosave.
+ m_mainWindow->setSessionAutoSaveEnabled(false);
+}
+
void DolphinMainWindowTest::cleanupTestCase()
{
m_mainWindow->showNormal();
m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::Quit))->trigger();
}
-
QTEST_MAIN(DolphinMainWindowTest)
#include "dolphinmainwindowtest.moc"