cf12defd28
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
189 lines
6.6 KiB
C++
189 lines
6.6 KiB
C++
/*
|
|
This file is part of the KDE project
|
|
SPDX-FileCopyrightText: 2014 David Faure <faure@kde.org>
|
|
|
|
SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
|
*/
|
|
|
|
#include <QMenu>
|
|
#include <QSignalSpy>
|
|
#include <QTemporaryDir>
|
|
#include <QTest>
|
|
|
|
#include "jobuidelegatefactory.h"
|
|
#include "kiotesthelper.h"
|
|
#include <KConfigGroup>
|
|
#include <KFileCopyToMenu>
|
|
#include <KSharedConfig>
|
|
|
|
#include <KIO/CopyJob>
|
|
|
|
class KFileCopyToMenuTest : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private Q_SLOTS:
|
|
void initTestCase()
|
|
{
|
|
QStandardPaths::setTestModeEnabled(true);
|
|
qputenv("KIOWORKER_ENABLE_TESTMODE", "1"); // ensure the KIO workers call QStandardPaths::setTestModeEnabled too
|
|
|
|
QVERIFY(m_tempDir.isValid());
|
|
QVERIFY(m_tempDestDir.isValid());
|
|
QVERIFY(m_nonWritableTempDir.isValid());
|
|
QVERIFY(QFile(m_nonWritableTempDir.path()).setPermissions(QFile::ReadOwner | QFile::ReadUser | QFile::ExeOwner | QFile::ExeUser));
|
|
m_srcDir = m_tempDir.path();
|
|
m_destDir = m_tempDestDir.path();
|
|
|
|
m_srcFile = m_srcDir + QStringLiteral("/srcfile");
|
|
|
|
KIO::setDefaultJobUiDelegateFactory(nullptr); // no "skip" dialogs
|
|
|
|
// Set a recent dir
|
|
KConfigGroup recentDirsGroup(KSharedConfig::openConfig(), QStringLiteral("kuick-copy"));
|
|
m_recentDirs << m_destDir + QStringLiteral("/nonexistentsubdir") // will be action number count-3
|
|
<< m_nonWritableTempDir.path() // will be action number count-2
|
|
<< m_destDir; // will be action number count-1
|
|
recentDirsGroup.writeEntry("Paths", m_recentDirs);
|
|
|
|
m_lastActionCount = 0;
|
|
}
|
|
|
|
void cleanupTestCase()
|
|
{
|
|
QVERIFY(QFile(m_nonWritableTempDir.path())
|
|
.setPermissions(QFile::ReadOwner | QFile::ReadUser | QFile::WriteOwner | QFile::WriteUser | QFile::ExeOwner | QFile::ExeUser));
|
|
}
|
|
|
|
// Before every test method, ensure the test file m_srcFile exists
|
|
void init()
|
|
{
|
|
if (QFile::exists(m_srcFile)) {
|
|
QVERIFY(QFileInfo(m_srcFile).isWritable());
|
|
} else {
|
|
QFile srcFile(m_srcFile);
|
|
QVERIFY2(srcFile.open(QFile::WriteOnly), qPrintable(srcFile.errorString()));
|
|
srcFile.write("Hello world\n");
|
|
}
|
|
QVERIFY(QFileInfo(m_srcFile).isWritable());
|
|
}
|
|
|
|
void shouldHaveParentWidget()
|
|
{
|
|
KFileCopyToMenu generator(&m_parentWidget);
|
|
QCOMPARE(generator.parent(), &m_parentWidget);
|
|
}
|
|
|
|
void shouldAddActions()
|
|
{
|
|
KFileCopyToMenu generator(&m_parentWidget);
|
|
QMenu menu;
|
|
generator.addActionsTo(&menu);
|
|
QList<QUrl> urls;
|
|
urls << QUrl::fromLocalFile(m_srcFile);
|
|
generator.setUrls(urls);
|
|
QCOMPARE(extractActionNames(menu), QStringList() << QStringLiteral("copyTo_submenu") << QStringLiteral("moveTo_submenu"));
|
|
QAction *copyMenuAction = menu.actions().at(0);
|
|
|
|
// When
|
|
menu.setActiveAction(copyMenuAction);
|
|
menu.popup(QPoint(-100, -100));
|
|
|
|
// Then
|
|
const QStringList actionNames = extractActionNames(*copyMenuAction->menu());
|
|
QVERIFY(!actionNames.isEmpty());
|
|
QCOMPARE(actionNames.first(), QStringLiteral("home"));
|
|
QVERIFY(actionNames.contains(QLatin1String("browse")));
|
|
QCOMPARE(actionNames.at(actionNames.count() - 2), m_nonWritableTempDir.path());
|
|
QCOMPARE(actionNames.last(), m_destDir);
|
|
}
|
|
|
|
void shouldTryCopyingToRecentPath_data()
|
|
{
|
|
QTest::addColumn<int>("actionNumber"); // from the bottom of the menu, starting at 1; see the recentDirs list in initTestCase
|
|
QTest::addColumn<int>("expectedErrorCode");
|
|
|
|
QTest::newRow("working") << 1 << 0; // no error
|
|
QTest::newRow("non_writable") << 2 << int(KIO::ERR_WRITE_ACCESS_DENIED);
|
|
QTest::newRow("non_existing") << 3 << int(KIO::ERR_CANNOT_OPEN_FOR_WRITING);
|
|
}
|
|
|
|
void shouldTryCopyingToRecentPath()
|
|
{
|
|
QFETCH(int, actionNumber);
|
|
QFETCH(int, expectedErrorCode);
|
|
|
|
KFileCopyToMenu generator(&m_parentWidget);
|
|
QMenu menu;
|
|
QList<QUrl> urls;
|
|
urls << QUrl::fromLocalFile(m_srcFile);
|
|
generator.setUrls(urls);
|
|
generator.addActionsTo(&menu);
|
|
QAction *copyMenuAction = menu.actions().at(0);
|
|
menu.setActiveAction(copyMenuAction);
|
|
|
|
menu.popup(QPoint(-100, -100));
|
|
const QList<QAction *> actions = copyMenuAction->menu()->actions();
|
|
if (m_lastActionCount == 0) {
|
|
m_lastActionCount = actions.count();
|
|
} else {
|
|
QCOMPARE(actions.count(), m_lastActionCount); // should be stable, i.e. selecting a recent dir shouldn't duplicate it
|
|
}
|
|
QAction *copyAction = actions.at(actions.count() - actionNumber);
|
|
QSignalSpy spy(&generator, &KFileCopyToMenu::error);
|
|
|
|
// When
|
|
copyAction->trigger();
|
|
|
|
// Then
|
|
QTRY_COMPARE(spy.count(), expectedErrorCode ? 1 : 0);
|
|
if (expectedErrorCode) {
|
|
QCOMPARE(spy.at(0).at(0).toInt(), expectedErrorCode);
|
|
} else {
|
|
QTRY_VERIFY(QFile::exists(m_destDir + QStringLiteral("/srcfile")));
|
|
}
|
|
|
|
if (actionNumber == 1) { // This part only makes sense if the copy is going to work
|
|
QFile::remove(m_destDir + QStringLiteral("/srcfile"));
|
|
// Remove the recent dirs entry for m_destDir from the config
|
|
KConfigGroup group(KSharedConfig::openConfig(), QStringLiteral("kuick-copy"));
|
|
auto list = group.readEntry("Paths", QStringList{});
|
|
list.removeOne(m_destDir);
|
|
group.writeEntry("Paths", list);
|
|
group.sync();
|
|
// Triggering the action again, should insert a recent dirs corresponding
|
|
// to m_destDir, which calls KFileCopyToMainMenu::copyOrMoveTo(), which
|
|
// trims the recent dirs config to 10 urls, and _shouldn't_ crash
|
|
copyAction->trigger();
|
|
|
|
// Back to normal for the next tests to pass
|
|
group.writeEntry("Paths", m_recentDirs);
|
|
}
|
|
}
|
|
|
|
private:
|
|
static QStringList extractActionNames(const QMenu &menu)
|
|
{
|
|
QStringList ret;
|
|
const QList<QAction *> actionsList = menu.actions();
|
|
for (const QAction *action : actionsList) {
|
|
ret.append(action->objectName());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
QTemporaryDir m_tempDir;
|
|
QString m_srcDir;
|
|
QString m_srcFile;
|
|
QTemporaryDir m_tempDestDir;
|
|
QString m_destDir;
|
|
QTemporaryDir m_nonWritableTempDir;
|
|
QWidget m_parentWidget;
|
|
QStringList m_recentDirs;
|
|
int m_lastActionCount;
|
|
};
|
|
|
|
QTEST_MAIN(KFileCopyToMenuTest)
|
|
|
|
#include "kfilecopytomenutest.moc"
|