/* This file is part of the KDE Frameworks SPDX-FileCopyrightText: 2008, 2016 David Faure SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include #include #include #include #include #include #include #include /* IMPORTANT: Because this unittest interacts with the file dialog, remember to run it both with plugins/platformthemes/KDEPlasmaPlatformTheme.so (to use KFileWidget) and without it (to use the builtin QFileDialog code) */ class KUrlRequesterTest : public QObject { Q_OBJECT private Q_SLOTS: void testUrlRequester(); void testComboRequester(); void testComboRequester_data(); void testNameFilters(); void testNameFilters_data(); private: bool createTestFile(const QString &fileName) { QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return false; } file.write("Hello world\n"); return true; } }; // Same as in kfiledialog_unittest.cpp static KFileWidget *findFileWidget() { QList widgets; const QList widgetsList = QApplication::topLevelWidgets(); for (QWidget *widget : widgetsList) { KFileWidget *fw = widget->findChild(); if (fw) { widgets.append(fw); } } return (widgets.count() == 1) ? widgets.first() : nullptr; } void KUrlRequesterTest::testUrlRequester() { KUrlRequester req; req.setFileDialogModality(Qt::NonModal); const QString fileName = QStringLiteral("some_test_file"); QVERIFY(createTestFile(fileName)); QTemporaryFile tempFile; QVERIFY(tempFile.open()); const QString filePath2 = tempFile.fileName(); QVERIFY(QFile::exists(filePath2)); // Set start dir const QUrl dirUrl = QUrl::fromLocalFile(QDir::currentPath()); req.setStartDir(dirUrl); QCOMPARE(req.startDir().toString(), dirUrl.toString()); // Click the button req.button()->click(); QFileDialog *fileDialog = req.findChild(); QVERIFY(fileDialog); // Find out if we're using KFileDialog or QFileDialog KFileWidget *fw = findFileWidget(); // Wait for directory listing if (fw) { QSignalSpy spy(fw->dirOperator(), &KDirOperator::finishedLoading); QVERIFY(spy.wait()); } // Select file const QString filePath = dirUrl.toLocalFile() + '/' + fileName; fileDialog->selectFile(fileName); // Click OK, check URLRequester shows and returns selected file QKeyEvent keyPressEv(QKeyEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); qApp->sendEvent(fw ? static_cast(fw) : static_cast(fileDialog), &keyPressEv); QCOMPARE(fileDialog->result(), static_cast(QDialog::Accepted)); QCOMPARE(fileDialog->selectedFiles(), QStringList{filePath}); QCOMPARE(req.url().toLocalFile(), filePath); // Check there is no longer any file dialog visible QVERIFY(fileDialog->isHidden()); // Click KUrlRequester button again. This time the filedialog is initialized with a file URL req.button()->click(); fileDialog = req.findChild(); QVERIFY(fileDialog); fw = findFileWidget(); if (fw) { // no need to wait for dir listing again, but we need it to be visible at least (for Key_Return to accept) // QVERIFY(QTest::qWaitForWindowExposed(fw->window())); // doesn't seem to be enough QTRY_VERIFY(fw->isVisible()); } // Select file 2 fileDialog->selectFile(filePath2); // Click OK, check URLRequester shows and returns selected file qApp->sendEvent(fw ? static_cast(fw) : static_cast(fileDialog), &keyPressEv); QCOMPARE(fileDialog->result(), static_cast(QDialog::Accepted)); QCOMPARE(fileDialog->selectedFiles(), QStringList{filePath2}); QCOMPARE(req.url().toLocalFile(), filePath2); } void KUrlRequesterTest::testComboRequester() { QFETCH(bool, editable); KUrlComboRequester req; req.show(); QList lineEdits = req.findChildren(); QVERIFY(lineEdits.isEmpty()); // no lineedits, only a readonly combo QSignalSpy textSpy(&req, &KUrlComboRequester::textChanged); QSignalSpy editSpy(&req, &KUrlComboRequester::textEdited); QSignalSpy returnWithTextSpy(&req, &KUrlComboRequester::returnPressed); QVERIFY(!req.comboBox()->isEditable()); if (editable) { req.comboBox()->setEditable(true); const auto text = QStringLiteral("foobar"); QTest::keyClicks(req.comboBox(), text, Qt::NoModifier); QCOMPARE(textSpy.size(), text.size()); QCOMPARE(editSpy.size(), text.size()); QCOMPARE(textSpy.last().first().toString(), text); QCOMPARE(editSpy.last().first().toString(), text); QCOMPARE(returnWithTextSpy.size(), 0); QTest::keyEvent(QTest::Click, req.comboBox(), Qt::Key_Return); QCOMPARE(returnWithTextSpy.size(), 1); QCOMPARE(returnWithTextSpy.last().first().toString(), text); } else { const auto url1 = QUrl("file:///foo/bar/1"); const auto url2 = QUrl("file:///foo/bar/2"); req.comboBox()->addUrl(url1); QCOMPARE(textSpy.size(), 1); QCOMPARE(textSpy.last().first().toUrl(), url1); req.comboBox()->addUrl(url2); QCOMPARE(textSpy.size(), 1); QTest::keyEvent(QTest::Click, req.comboBox(), Qt::Key_Down); QCOMPARE(textSpy.size(), 2); QCOMPARE(textSpy.last().first().toUrl(), url2); // only editable combo boxes get the edit and return signals emitted QCOMPARE(editSpy.size(), 0); QCOMPARE(returnWithTextSpy.size(), 0); } } void KUrlRequesterTest::testComboRequester_data() { QTest::addColumn("editable"); QTest::newRow("read-only") << false; QTest::newRow("editable") << true; } void KUrlRequesterTest::testNameFilters() { QFETCH(QString, nameFilter); QFETCH(QStringList, nameFilters); KUrlRequester req; req.setFileDialogModality(Qt::NonModal); // Click the button to get the filedialog req.button()->click(); QFileDialog *fileDialog = req.findChild(); QVERIFY(fileDialog); // set name filter req.setNameFilter(nameFilter); // check all QCOMPARE(req.nameFilters(), nameFilters); QCOMPARE(fileDialog->nameFilters(), nameFilters); // set name filters req.setNameFilters(nameFilters); // check all QCOMPARE(req.nameFilters(), nameFilters); QCOMPARE(fileDialog->nameFilters(), nameFilters); } void KUrlRequesterTest::testNameFilters_data() { QTest::addColumn("nameFilter"); QTest::addColumn("nameFilters"); /* clang-format off */ QTest::newRow("singleglob-comment") << QStringLiteral("Comment (*.foo)") << QStringList{QStringLiteral("Comment (*.foo)")}; QTest::newRow("singleglob-nocomment") << QStringLiteral("*.foo") << QStringList{QStringLiteral("*.foo")}; QTest::newRow("multiglob-comment") << QStringLiteral("Comment (*.foo *.bar)") << QStringList{QStringLiteral("Comment (*.foo *.bar)")}; QTest::newRow("multiglob-nocomment") << QStringLiteral("*.foo *.bar") << QStringList{QStringLiteral("*.foo *.bar")}; QTest::newRow("multilines-comment") << QStringLiteral("Comment (*.foo *.bar);;Comment2 (*.kde)") << QStringList{QStringLiteral("Comment (*.foo *.bar)"), QStringLiteral("Comment2 (*.kde)")}; QTest::newRow("multilines-nocomment") << QStringLiteral("*.foo *.bar;;*.kde") << QStringList{QStringLiteral("*.foo *.bar"), QStringLiteral("*.kde")}; QTest::newRow("multilines-commentmixed") << QStringLiteral("Comment (*.foo *.bar);;*.kde") << QStringList{QStringLiteral("Comment (*.foo *.bar)"), QStringLiteral("*.kde")}; /* clang-format on */ } QTEST_MAIN(KUrlRequesterTest) #include "kurlrequestertest.moc"