File indexing completed on 2024-05-12 05:46:43

0001 /* This file is part of the KDE project
0002    Copyright (C) 2014 David Faure <faure@kde.org>
0003 
0004    This library is free software; you can redistribute it and/or modify
0005    it under the terms of the GNU Lesser General Public License as published by
0006    the Free Software Foundation; either version 2 of the License or ( at
0007    your option ) version 3 or, at the discretion of KDE e.V. ( which shall
0008    act as a proxy as in section 14 of the GPLv3 ), any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Lesser General Public License for more details.
0014 
0015    You should have received a copy of the GNU Lesser General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018    Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #include <qtest.h>
0022 #include <QSignalSpy>
0023 #include <QMenu>
0024 #include <QTemporaryDir>
0025 
0026 #include <KConfigGroup>
0027 #include <KSharedConfig>
0028 #include <KFileCopyToMenu>
0029 #include "kiotesthelper.h"
0030 #include "jobuidelegatefactory.h"
0031 
0032 #include <KIO/CopyJob>
0033 
0034 class KFileCopyToMenuTest : public QObject
0035 {
0036     Q_OBJECT
0037 
0038 private Q_SLOTS:
0039     void initTestCase()
0040     {
0041         QStandardPaths::setTestModeEnabled(true);
0042         qputenv("KIOSLAVE_ENABLE_TESTMODE", "1"); // ensure the ioslaves call QStandardPaths::setTestModeEnabled too
0043         qputenv("KDE_FORK_SLAVES", "yes"); // to avoid a runtime dependency on klauncher
0044 
0045         QVERIFY(m_tempDir.isValid());
0046         QVERIFY(m_tempDestDir.isValid());
0047         QVERIFY(m_nonWritableTempDir.isValid());
0048         QVERIFY(QFile(m_nonWritableTempDir.path()).setPermissions(QFile::ReadOwner | QFile::ReadUser | QFile::ExeOwner | QFile::ExeUser));
0049         m_srcDir = m_tempDir.path();
0050         m_destDir = m_tempDestDir.path();
0051 
0052         m_srcFile = m_srcDir + QStringLiteral("/srcfile");
0053 
0054         KIO::setDefaultJobUiDelegateExtension(nullptr); // no "skip" dialogs
0055 
0056         // Set a recent dir
0057         KConfigGroup recentDirsGroup(KSharedConfig::openConfig(), "kuick-copy");
0058         m_recentDirs
0059                 << m_destDir + QStringLiteral("/nonexistentsubdir") // will be action number count-3
0060                 << m_nonWritableTempDir.path() // will be action number count-2
0061                 << m_destDir; // will be action number count-1
0062         recentDirsGroup.writeEntry("Paths", m_recentDirs);
0063 
0064         m_lastActionCount = 0;
0065     }
0066 
0067     void cleanupTestCase()
0068     {
0069         QVERIFY(QFile(m_nonWritableTempDir.path()).setPermissions(QFile::ReadOwner | QFile::ReadUser | QFile::WriteOwner | QFile::WriteUser | QFile::ExeOwner | QFile::ExeUser));
0070     }
0071 
0072     // Before every test method, ensure the test file m_srcFile exists
0073     void init()
0074     {
0075         if (QFile::exists(m_srcFile)) {
0076             QVERIFY(QFileInfo(m_srcFile).isWritable());
0077         } else {
0078             QFile srcFile(m_srcFile);
0079             QVERIFY2(srcFile.open(QFile::WriteOnly), qPrintable(srcFile.errorString()));
0080             srcFile.write("Hello world\n");
0081         }
0082         QVERIFY(QFileInfo(m_srcFile).isWritable());
0083     }
0084 
0085     void shouldHaveParentWidget()
0086     {
0087         KFileCopyToMenu generator(&m_parentWidget);
0088         QCOMPARE(generator.parent(), &m_parentWidget);
0089     }
0090 
0091     void shouldAddActions()
0092     {
0093         KFileCopyToMenu generator(&m_parentWidget);
0094         QMenu menu;
0095         generator.addActionsTo(&menu);
0096         QList<QUrl> urls; urls << QUrl::fromLocalFile(m_srcFile);
0097         generator.setUrls(urls);
0098         QCOMPARE(extractActionNames(menu), QStringList() << QStringLiteral("copyTo_submenu") << QStringLiteral("moveTo_submenu"));
0099         //menu.popup(QPoint(-50, -50));
0100         QMenu *copyMenu = menu.actions().at(0)->menu(); // "copy" submenu
0101         QVERIFY(copyMenu);
0102 
0103         // When
0104         copyMenu->popup(QPoint(-100, -100));
0105 
0106         // Then
0107         const QStringList actionNames = extractActionNames(*copyMenu);
0108         QCOMPARE(actionNames.first(), QStringLiteral("home"));
0109         QVERIFY(actionNames.contains(QLatin1String("browse")));
0110         QCOMPARE(actionNames.at(actionNames.count() - 2), m_nonWritableTempDir.path());
0111         QCOMPARE(actionNames.last(), m_destDir);
0112     }
0113 
0114     void shouldTryCopyingToRecentPath_data()
0115     {
0116         QTest::addColumn<int>("actionNumber"); // from the bottom of the menu, starting at 1; see the recentDirs list in initTestCase
0117         QTest::addColumn<int>("expectedErrorCode");
0118 
0119         QTest::newRow("working") << 1 << 0; // no error
0120         QTest::newRow("non_writable") << 2 << int(KIO::ERR_WRITE_ACCESS_DENIED);
0121         QTest::newRow("non_existing") << 3 << int(KIO::ERR_CANNOT_OPEN_FOR_WRITING);
0122     }
0123 
0124     void shouldTryCopyingToRecentPath()
0125     {
0126         QFETCH(int, actionNumber);
0127         QFETCH(int, expectedErrorCode);
0128 
0129         KFileCopyToMenu generator(&m_parentWidget);
0130         QMenu menu;
0131         QList<QUrl> urls; urls << QUrl::fromLocalFile(m_srcFile);
0132         generator.setUrls(urls);
0133         generator.addActionsTo(&menu);
0134         QMenu *copyMenu = menu.actions().at(0)->menu();
0135         copyMenu->popup(QPoint(-100, -100));
0136         const QList<QAction *> actions = copyMenu->actions();
0137         if (m_lastActionCount == 0) {
0138             m_lastActionCount = actions.count();
0139         } else {
0140             QCOMPARE(actions.count(), m_lastActionCount); // should be stable, i.e. selecting a recent dir shouldn't duplicate it
0141         }
0142         QAction *copyAction = actions.at(actions.count() - actionNumber);
0143         QSignalSpy spy(&generator, SIGNAL(error(int,QString)));
0144 
0145         // When
0146         copyAction->trigger();
0147 
0148         // Then
0149         QTRY_COMPARE(spy.count(), expectedErrorCode ? 1 : 0);
0150         if (expectedErrorCode) {
0151             QCOMPARE(spy.at(0).at(0).toInt(), expectedErrorCode);
0152         } else {
0153             QTRY_VERIFY(QFile::exists(m_destDir + QStringLiteral("/srcfile")));
0154         }
0155     }
0156 
0157 private:
0158 
0159     static QStringList extractActionNames(const QMenu &menu)
0160     {
0161         QStringList ret;
0162         foreach (const QAction *action, menu.actions()) {
0163             ret.append(action->objectName());
0164         }
0165         return ret;
0166     }
0167 
0168     QTemporaryDir m_tempDir;
0169     QString m_srcDir;
0170     QString m_srcFile;
0171     QTemporaryDir m_tempDestDir;
0172     QString m_destDir;
0173     QTemporaryDir m_nonWritableTempDir;
0174     QWidget m_parentWidget;
0175     QStringList m_recentDirs;
0176     int m_lastActionCount;
0177 };
0178 
0179 QTEST_MAIN(KFileCopyToMenuTest)
0180 
0181 #include "kfilecopytomenutest.moc"
0182