File indexing completed on 2024-04-28 15:29:18

0001 /*
0002     SPDX-FileCopyrightText: 2007 David Faure <faure@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "parttest.h"
0008 #include <qtest_widgets.h>
0009 
0010 #include <KSharedConfig>
0011 #include <QSignalSpy>
0012 #include <QTest>
0013 #include <QWidget>
0014 #include <kparts/openurlarguments.h>
0015 #include <kparts/readonlypart.h>
0016 
0017 QTEST_MAIN(PartTest)
0018 
0019 class TestPart : public KParts::ReadOnlyPart
0020 {
0021 public:
0022     TestPart(QObject *parent, QWidget *parentWidget)
0023         : KParts::ReadOnlyPart(parent)
0024         , m_openFileCalled(false)
0025     {
0026         setWidget(new QWidget(parentWidget));
0027         connect(this, &KParts::ReadOnlyPart::urlChanged, this, &TestPart::logUrlChanged);
0028     }
0029 
0030     bool openFileCalled() const
0031     {
0032         return m_openFileCalled;
0033     }
0034 
0035     void logUrlChanged(const QUrl &url)
0036     {
0037         qDebug() << "url changed: " << url;
0038     }
0039 
0040 protected:
0041     bool openFile() override
0042     {
0043         m_openFileCalled = true;
0044         return true;
0045     }
0046 
0047 private:
0048     bool m_openFileCalled;
0049 };
0050 
0051 void PartTest::testAutoDeletePart()
0052 {
0053     KParts::Part *part = new TestPart(nullptr, nullptr);
0054     QPointer<KParts::Part> partPointer(part);
0055     delete part->widget();
0056     QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
0057     QVERIFY(partPointer.isNull());
0058 }
0059 
0060 void PartTest::testAutoDeleteWidget()
0061 {
0062     KParts::Part *part = new TestPart(nullptr, nullptr);
0063     QPointer<KParts::Part> partPointer(part);
0064     QPointer<QWidget> widgetPointer(part->widget());
0065     delete part;
0066     QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
0067     QVERIFY(widgetPointer.isNull());
0068 }
0069 
0070 void PartTest::testNoAutoDeletePart()
0071 {
0072     KParts::Part *part = new TestPart(nullptr, nullptr);
0073     part->setAutoDeletePart(false);
0074     QPointer<KParts::Part> partPointer(part);
0075     delete part->widget();
0076     QVERIFY(part->widget() == nullptr);
0077     QCOMPARE(static_cast<KParts::Part *>(partPointer), part);
0078     delete part;
0079 }
0080 
0081 void PartTest::testNoAutoDeleteWidget()
0082 {
0083     KParts::Part *part = new TestPart(nullptr, nullptr);
0084     part->setAutoDeleteWidget(false);
0085     QWidget *widget = part->widget();
0086     QVERIFY(widget);
0087     QPointer<QWidget> widgetPointer(part->widget());
0088     delete part;
0089     QCOMPARE(static_cast<QWidget *>(widgetPointer), widget);
0090     delete widget;
0091 }
0092 
0093 // There is no operator== in OpenUrlArguments because it's only useful in unit tests
0094 static bool compareArgs(const KParts::OpenUrlArguments &arg1, const KParts::OpenUrlArguments &arg2)
0095 {
0096     return arg1.mimeType() == arg2.mimeType() && //
0097         arg1.xOffset() == arg2.xOffset() && //
0098         arg1.yOffset() == arg2.yOffset() && //
0099         arg1.reload() == arg2.reload();
0100 }
0101 
0102 void PartTest::testOpenUrlArguments()
0103 {
0104     TestPart *part = new TestPart(nullptr, nullptr);
0105     QVERIFY(part->closeUrl()); // nothing to do, no error
0106     QVERIFY(part->arguments().mimeType().isEmpty());
0107     KParts::OpenUrlArguments args;
0108     args.setMimeType(QStringLiteral("application/xml"));
0109     args.setXOffset(50);
0110     args.setYOffset(10);
0111     args.setReload(true);
0112     part->setArguments(args);
0113     QVERIFY(compareArgs(args, part->arguments()));
0114     part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("parttest.cpp")));
0115     QVERIFY(part->openFileCalled());
0116     QVERIFY(compareArgs(args, part->arguments()));
0117 
0118     // Explicit call to closeUrl: arguments are cleared
0119     part->closeUrl();
0120     QVERIFY(part->arguments().mimeType().isEmpty());
0121 
0122     // Calling openUrl with local file: mimetype is determined
0123     part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("parttest.cpp")));
0124     QCOMPARE(part->arguments().mimeType(), QStringLiteral("text/x-c++src"));
0125     // (for a remote url it would be determined during downloading)
0126 
0127     delete part;
0128 }
0129 
0130 void PartTest::testAutomaticMimeType()
0131 {
0132     TestPart *part = new TestPart(nullptr, nullptr);
0133     QVERIFY(part->closeUrl()); // nothing to do, no error
0134     QVERIFY(part->arguments().mimeType().isEmpty());
0135     // open a file, and test the detected mimetype
0136     part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("notepad.desktop")));
0137     QCOMPARE(part->arguments().mimeType(), QString::fromLatin1("application/x-desktop"));
0138 
0139     // manually closing, no mimetype should be stored now
0140     part->closeUrl();
0141     QVERIFY(part->arguments().mimeType().isEmpty());
0142 
0143     // open a new file, and test again its (autdetected) mimetype
0144     part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("parttest.cpp")));
0145     QCOMPARE(part->arguments().mimeType(), QStringLiteral("text/x-c++src"));
0146 
0147     // open a new file, but without explicitly close the first
0148     part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("notepad.desktop")));
0149     // test again its (autdetected) mimetype
0150     QCOMPARE(part->arguments().mimeType(), QString::fromLatin1("application/x-desktop"));
0151 
0152     // open a new file, but manually forcing a mimetype
0153     KParts::OpenUrlArguments args;
0154     args.setMimeType(QStringLiteral("application/xml"));
0155     part->setArguments(args);
0156     QVERIFY(compareArgs(args, part->arguments()));
0157     part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("parttest.cpp")));
0158     QCOMPARE(part->arguments().mimeType(), QString::fromLatin1("application/xml"));
0159 
0160     // clear the args and open a new file, reactivating the automatic mimetype detection again
0161     part->setArguments(KParts::OpenUrlArguments());
0162     part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("notepad.desktop")));
0163     // test again its (autdetected) mimetype
0164     QCOMPARE(part->arguments().mimeType(), QString::fromLatin1("application/x-desktop"));
0165 
0166     delete part;
0167 }
0168 
0169 void PartTest::testEmptyUrlAfterCloseUrl()
0170 {
0171     TestPart *part = new TestPart(nullptr, nullptr);
0172 
0173     QVERIFY(part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("notepad.desktop"))));
0174     QSignalSpy spy(part, &KParts::ReadOnlyPart::urlChanged);
0175     QVERIFY(part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("parttest.cpp"))));
0176     QVERIFY(!part->url().isEmpty());
0177     QCOMPARE(spy.count(), 1);
0178     spy.clear();
0179     QVERIFY(part->closeUrl());
0180     QVERIFY(part->url().isEmpty());
0181     QCOMPARE(spy.count(), 1);
0182 
0183     delete part;
0184 }
0185 
0186 #include <KConfigGroup>
0187 #include <KToggleToolBarAction>
0188 #include <KToolBar>
0189 #include <kparts/mainwindow.h>
0190 class MyMainWindow : public KParts::MainWindow
0191 {
0192 public:
0193     MyMainWindow()
0194         : KParts::MainWindow()
0195     {
0196         tb = new KToolBar(this);
0197         tb->setObjectName(QStringLiteral("testtbvisibility"));
0198     }
0199 
0200     // createGUI and saveAutoSaveSettings are protected, so the whole test is here:
0201     void testToolbarVisibility()
0202     {
0203         QVERIFY(tb->isVisible());
0204 
0205         TestPart *part = new TestPart(nullptr, nullptr);
0206         // TODO define xml with a toolbar for the part
0207         // and put some saved settings into qttestrc in order to test
0208         // r347935+r348051, i.e. the fact that KParts::MainWindow::createGUI
0209         // will apply the toolbar settings (and that they won't have been
0210         // erased by the previous call to saveMainWindowSettings...)
0211         this->createGUI(part);
0212 
0213         QVERIFY(tb->isVisible());
0214         this->saveAutoSaveSettings();
0215 
0216         // Hide the toolbar using the action (so that setSettingsDirty is called, too)
0217         KToggleToolBarAction action(tb, QString(), nullptr);
0218         action.trigger();
0219         QVERIFY(!tb->isVisible());
0220 
0221         // Switch the active part, and check that
0222         // the toolbar doesn't magically reappear,
0223         // as it did when createGUI was calling applyMainWindowSettings
0224         this->createGUI(nullptr);
0225         QVERIFY(!tb->isVisible());
0226         this->createGUI(part);
0227         QVERIFY(!tb->isVisible());
0228 
0229         // All ok, show it again so that test can be run again :)
0230         action.trigger();
0231         QVERIFY(tb->isVisible());
0232         close();
0233     }
0234 
0235 private:
0236     KToolBar *tb;
0237 };
0238 
0239 // A KParts::MainWindow unit test
0240 void PartTest::testToolbarVisibility()
0241 {
0242     // The bug was: hide a toolbar in konqueror,
0243     // then switch tabs -> the toolbar shows again
0244     // (unless you waited for the autosave timer to kick in)
0245     MyMainWindow window;
0246     KConfigGroup cg(KSharedConfig::openConfig(), "kxmlgui_unittest");
0247     window.setAutoSaveSettings(cg.name());
0248     window.show();
0249     window.testToolbarVisibility();
0250 }
0251 
0252 void PartTest::testShouldNotCrashAfterDelete()
0253 {
0254     TestPart *part = new TestPart(nullptr, nullptr);
0255     QVERIFY(part->openUrl(QUrl::fromLocalFile(QFINDTESTDATA("notepad.desktop"))));
0256     QVERIFY(part->openFileCalled());
0257     delete part;
0258 }
0259 
0260 #include "moc_parttest.cpp"