Files
RedBear-OS/local/recipes/kde/kf6-kio/source/autotests/kfilecopytomenutest.cpp
T
2026-04-14 10:51:06 +01:00

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"