File indexing completed on 2024-05-12 04:38:20

0001 /*
0002     SPDX-FileCopyrightText: 2015 Milian Wolff <mail@milianw.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "test_ktexteditorpluginintegration.h"
0008 
0009 #include <QTest>
0010 #include <QLoggingCategory>
0011 #include <QSignalSpy>
0012 
0013 #include <tests/autotestshell.h>
0014 #include <tests/testcore.h>
0015 
0016 #include <shell/plugincontroller.h>
0017 #include <shell/uicontroller.h>
0018 
0019 #include <KTextEditor/Application>
0020 #include <KTextEditor/Editor>
0021 #include <KTextEditor/MainWindow>
0022 #include <KTextEditor/Plugin>
0023 #include <KTextEditor/View>
0024 #include <KTextEditor/Document>
0025 
0026 using namespace KDevelop;
0027 
0028 namespace {
0029 template<typename T>
0030 QPointer<T> makeQPointer(T *ptr)
0031 {
0032     return {ptr};
0033 }
0034 
0035 IToolViewFactory *findToolView(const QString &id)
0036 {
0037     const auto uiController = Core::self()->uiControllerInternal();
0038     const auto map = uiController->factoryDocuments();
0039     for (auto it = map.begin(); it != map.end(); ++it) {
0040         if (it.key()->id() == id) {
0041             return it.key();
0042         }
0043     }
0044     return nullptr;
0045 }
0046 
0047 class TestPlugin : public KTextEditor::Plugin
0048 {
0049     Q_OBJECT
0050 public:
0051     explicit TestPlugin(QObject *parent)
0052         : Plugin(parent)
0053     {
0054     }
0055 
0056     QObject *createView(KTextEditor::MainWindow * mainWindow) override
0057     {
0058         return new QObject(mainWindow);
0059     }
0060 };
0061 }
0062 
0063 void TestKTextEditorPluginIntegration::initTestCase()
0064 {
0065     QLoggingCategory::setFilterRules(QStringLiteral("*.debug=false\ndefault.debug=true\n"));
0066     AutoTestShell::init({QStringLiteral("katesnippetsplugin")});
0067     TestCore::initialize();
0068     QVERIFY(KTextEditor::Editor::instance());
0069 }
0070 
0071 void TestKTextEditorPluginIntegration::cleanupTestCase()
0072 {
0073     auto controller = Core::self()->pluginController();
0074     const auto id = QStringLiteral("katesnippetsplugin");
0075     auto plugin = makeQPointer(controller->loadPlugin(id));
0076 
0077     const auto editor = makeQPointer(KTextEditor::Editor::instance());
0078     const auto application = makeQPointer(editor->application());
0079     const auto window = makeQPointer(application->activeMainWindow());
0080 
0081     TestCore::shutdown();
0082 
0083     QVERIFY(!plugin);
0084     QVERIFY(!window);
0085     QVERIFY(!application);
0086 
0087     // editor lives by design until QCoreApplication terminates, then autodeletes
0088 }
0089 
0090 void TestKTextEditorPluginIntegration::testApplication()
0091 {
0092     auto app = KTextEditor::Editor::instance()->application();
0093     QVERIFY(app);
0094     QVERIFY(app->parent());
0095     QCOMPARE(app->parent()->metaObject()->className(), "KTextEditorIntegration::Application");
0096     QVERIFY(app->activeMainWindow());
0097     QCOMPARE(app->mainWindows().size(), 1);
0098     QVERIFY(app->mainWindows().contains(app->activeMainWindow()));
0099 }
0100 
0101 void TestKTextEditorPluginIntegration::testMainWindow()
0102 {
0103     auto window = KTextEditor::Editor::instance()->application()->activeMainWindow();
0104     QVERIFY(window);
0105     QVERIFY(window->parent());
0106     QCOMPARE(window->parent()->metaObject()->className(), "KTextEditorIntegration::MainWindow");
0107 
0108     const auto id = QStringLiteral("kte_integration_toolview");
0109     const auto icon = QIcon::fromTheme(QStringLiteral("kdevelop"));
0110     const auto text = QStringLiteral("some text");
0111     QVERIFY(!findToolView(id));
0112 
0113     auto plugin = new TestPlugin(this);
0114     auto toolView = makeQPointer(window->createToolView(plugin, id, KTextEditor::MainWindow::Bottom, icon, text));
0115     QVERIFY(toolView);
0116 
0117     auto factory = findToolView(id);
0118     QVERIFY(factory);
0119 
0120     // we reuse the same view
0121     QWidget parent;
0122     auto kdevToolView = makeQPointer(factory->create(&parent));
0123     QCOMPARE(kdevToolView->parentWidget(), &parent);
0124     QCOMPARE(toolView->parentWidget(), kdevToolView.data());
0125 
0126     // the children are kept alive when the tool view gets destroyed
0127     delete kdevToolView;
0128     QVERIFY(toolView);
0129     kdevToolView = factory->create(&parent);
0130     // and we reuse the ktexteditor tool view for the new kdevelop tool view
0131     QCOMPARE(toolView->parentWidget(), kdevToolView.data());
0132 
0133     delete toolView;
0134     delete kdevToolView;
0135 
0136     delete plugin;
0137     QVERIFY(!findToolView(id));
0138 }
0139 
0140 void TestKTextEditorPluginIntegration::testPlugin()
0141 {
0142     auto controller = Core::self()->pluginController();
0143     const auto id = QStringLiteral("katesnippetsplugin");
0144     auto plugin = makeQPointer(controller->loadPlugin(id));
0145     if (!plugin) {
0146         QSKIP("Cannot continue without katesnippetsplugin, install Kate");
0147     }
0148 
0149     auto app = KTextEditor::Editor::instance()->application();
0150     auto ktePlugin = makeQPointer(app->plugin(id));
0151     QVERIFY(ktePlugin);
0152 
0153     auto view = makeQPointer(app->activeMainWindow()->pluginView(id));
0154     QVERIFY(view);
0155     const auto rawView = view.data();
0156 
0157     QSignalSpy spy(app->activeMainWindow(), &KTextEditor::MainWindow::pluginViewDeleted);
0158     QVERIFY(controller->unloadPlugin(id));
0159     QVERIFY(!ktePlugin);
0160     QCOMPARE(spy.count(), 1);
0161     QCOMPARE(spy.first().count(), 2);
0162     QCOMPARE(spy.first().at(0), QVariant::fromValue(id));
0163     QCOMPARE(spy.first().at(1), QVariant::fromValue(rawView));
0164     QVERIFY(!view);
0165 }
0166 
0167 void TestKTextEditorPluginIntegration::testPluginUnload()
0168 {
0169     auto controller = Core::self()->pluginController();
0170     const auto id = QStringLiteral("katesnippetsplugin");
0171     auto plugin = makeQPointer(controller->loadPlugin(id));
0172     if (!plugin) {
0173         QSKIP("Cannot continue without katesnippetsplugin, install Kate");
0174     }
0175 
0176     auto app = KTextEditor::Editor::instance()->application();
0177     auto ktePlugin = makeQPointer(app->plugin(id));
0178     QVERIFY(ktePlugin);
0179     delete ktePlugin;
0180     // don't crash
0181     plugin->unload();
0182 }
0183 
0184 QTEST_MAIN(TestKTextEditorPluginIntegration)
0185 
0186 #include <test_ktexteditorpluginintegration.moc>
0187 #include "moc_test_ktexteditorpluginintegration.cpp"