File indexing completed on 2024-04-28 07:45:17

0001 /*
0002     SPDX-FileCopyrightText: 2016 Martin Klapetek <mklapetek@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include <QDBusConnection>
0008 #include <QObject>
0009 #include <QStandardPaths>
0010 #include <qtest.h>
0011 
0012 #include "../src/knotification.h"
0013 #include "fake_notifications_server.h"
0014 #include "qtest_dbus.h"
0015 
0016 class KNotificationTest : public QObject
0017 {
0018     Q_OBJECT
0019 
0020 private Q_SLOTS:
0021     void initTestCase();
0022     void cleanupTestCase();
0023     void gettersTest();
0024     void idTest();
0025     void immediateCloseTest();
0026     void serverCallTest();
0027     void serverCloseTest();
0028     void serverActionsTest();
0029     void noActionsTest();
0030 
0031 private:
0032     NotificationsServer *m_server;
0033 };
0034 
0035 void KNotificationTest::initTestCase()
0036 {
0037     QStandardPaths::setTestModeEnabled(true);
0038     const QString dataDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
0039     qDebug() << dataDir;
0040 
0041     QDir dir;
0042     bool pathOk = dir.mkpath(dataDir + QStringLiteral("/knotifications5/"));
0043 
0044     QVERIFY(pathOk);
0045 
0046     QFile testFile(QFINDTESTDATA(QStringLiteral("knotifications5/qttest.notifyrc")));
0047     bool fileOk = testFile.copy(dataDir + QStringLiteral("/knotifications5/qttest.notifyrc"));
0048 
0049     QVERIFY(fileOk);
0050 
0051     m_server = new NotificationsServer(this);
0052 
0053     bool rs = QDBusConnection::sessionBus().registerService(QStringLiteral("org.freedesktop.Notifications"));
0054     bool ro = QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/freedesktop/Notifications"), m_server, QDBusConnection::ExportAllContents);
0055 
0056     QVERIFY(rs);
0057     QVERIFY(ro);
0058 }
0059 
0060 void KNotificationTest::cleanupTestCase()
0061 {
0062     // Cleanup
0063     const QString dataDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
0064     QFile testFile(dataDir + QStringLiteral("/knotifications5/qttest.notifyrc"));
0065     bool fileRemoveOk = testFile.remove();
0066 
0067     QVERIFY(fileRemoveOk);
0068 
0069     QDir dir(dataDir + QStringLiteral("/knotifications5"));
0070     bool dirRemoveOk = dir.removeRecursively();
0071 
0072     QVERIFY(dirRemoveOk);
0073 }
0074 
0075 void KNotificationTest::gettersTest()
0076 {
0077     const QString testEvent = QStringLiteral("testEvent");
0078     const QString testText = QStringLiteral("Test");
0079 
0080     KNotification *n = new KNotification(testEvent);
0081     n->setText(QStringLiteral("Test"));
0082 
0083     QCOMPARE(n->id(), -1);
0084     QCOMPARE(n->eventId(), testEvent);
0085     QCOMPARE(n->text(), testText);
0086     QCOMPARE(n->title(), QString());
0087     QCOMPARE(n->appName(), QCoreApplication::applicationName());
0088 
0089     // DefaultEvent is reserved for Workspace events
0090     n->setFlags(KNotification::DefaultEvent);
0091     QCOMPARE(n->appName(), QStringLiteral("plasma_workspace"));
0092 
0093     n->setFlags(KNotification::CloseOnTimeout);
0094     n->setComponentName(QStringLiteral("testtest"));
0095     QCOMPARE(n->appName(), QStringLiteral("testtest"));
0096 
0097     QSignalSpy nClosedSpy(n, SIGNAL(closed()));
0098     QSignalSpy nDestroyedSpy(n, SIGNAL(destroyed(QObject *)));
0099 
0100     // Calling ref and deref simulates a Notification plugin
0101     // starting and ending an action, after the action has
0102     // finished, the notification should close itself
0103     n->ref();
0104     n->deref();
0105 
0106     QCOMPARE(nClosedSpy.size(), 1);
0107 
0108     // ...and delete itself too
0109     nDestroyedSpy.wait(500);
0110     QCOMPARE(nDestroyedSpy.size(), 1);
0111 }
0112 
0113 void KNotificationTest::idTest()
0114 {
0115     KNotification n(QStringLiteral("testEvent"));
0116 
0117     QCOMPARE(n.id(), -1);
0118 
0119     n.sendEvent();
0120 
0121     // The first id is 0; the previous test did not
0122     // call sendEvent() and therefore should not have
0123     // increased the id counter, which starts at 0
0124     QCOMPARE(n.id(), 0);
0125 
0126     // TODO
0127     // At this point there is no clean/sane way
0128     // to test the other id() changes throughout
0129     // the life of KNotification, ideally there
0130     // would be a signal sending out the changed
0131     // id values that would be caught by a signal spy
0132     // and then checked
0133 }
0134 
0135 void KNotificationTest::immediateCloseTest()
0136 {
0137     KNotification *n = new KNotification(QStringLiteral("testEvent"));
0138 
0139     QSignalSpy nClosedSpy(n, SIGNAL(closed()));
0140 
0141     n->close();
0142 
0143     nClosedSpy.wait(100);
0144 
0145     QCOMPARE(nClosedSpy.size(), 1);
0146 }
0147 
0148 void KNotificationTest::serverCallTest()
0149 {
0150     const QString testText = QStringLiteral("Test");
0151 
0152     QSignalSpy serverNewSpy(m_server, SIGNAL(newNotification()));
0153     QSignalSpy serverClosedSpy(m_server, SIGNAL(NotificationClosed(uint, uint)));
0154 
0155     KNotification n(QStringLiteral("testEvent"));
0156     n.setText(testText);
0157     n.setFlags(KNotification::Persistent);
0158 
0159     n.sendEvent();
0160 
0161     serverNewSpy.wait(500);
0162 
0163     QCOMPARE(m_server->notifications.last().body, testText);
0164     // timeout 0 is persistent notification
0165     QCOMPARE(m_server->notifications.last().timeout, 0);
0166 
0167     QCOMPARE(n.id(), 1);
0168 
0169     // Give the dbus communication some time to finish
0170     QTest::qWait(300);
0171 
0172     n.close();
0173 
0174     serverClosedSpy.wait(500);
0175     QCOMPARE(serverClosedSpy.size(), 1);
0176     QCOMPARE(m_server->notifications.size(), 0);
0177 }
0178 
0179 void KNotificationTest::serverCloseTest()
0180 {
0181     KNotification n(QStringLiteral("testEvent"));
0182     n.setText(QStringLiteral("Test"));
0183     n.setFlags(KNotification::Persistent);
0184     n.sendEvent();
0185 
0186     QSignalSpy nClosedSpy(&n, SIGNAL(closed()));
0187 
0188     // Give the dbus some time
0189     QTest::qWait(300);
0190 
0191     uint id = m_server->notifications.last().id;
0192 
0193     m_server->NotificationClosed(id, 2);
0194 
0195     nClosedSpy.wait(100);
0196 
0197     QCOMPARE(nClosedSpy.size(), 1);
0198 }
0199 
0200 void KNotificationTest::serverActionsTest()
0201 {
0202     KNotification n(QStringLiteral("testEvent"));
0203     n.setText(QStringLiteral("Test"));
0204     n.setActions(QStringList{QStringLiteral("a1"), QStringLiteral("a2")});
0205     n.sendEvent();
0206 
0207     QSignalSpy serverClosedSpy(m_server, SIGNAL(NotificationClosed(uint, uint)));
0208     QSignalSpy nClosedSpy(&n, SIGNAL(closed()));
0209     QSignalSpy nActivatedSpy(&n, SIGNAL(activated(uint)));
0210     QSignalSpy nActivated2Spy(&n, SIGNAL(action1Activated()));
0211 
0212     QTest::qWait(300);
0213 
0214     uint id = m_server->notifications.last().id;
0215 
0216     Q_EMIT m_server->ActionInvoked(id, QString::number(1));
0217 
0218     nActivatedSpy.wait(300);
0219     // After the notification action was invoked,
0220     // the notification should request closing
0221     serverClosedSpy.wait(300);
0222     nClosedSpy.wait(300);
0223 
0224     QCOMPARE(serverClosedSpy.size(), 1);
0225     QCOMPARE(nActivatedSpy.size(), 1);
0226     QCOMPARE(nActivated2Spy.size(), 1);
0227     // The argument must be 1, as was passed to the ActionInvoked
0228     QCOMPARE(nActivatedSpy.at(0).at(0).toInt(), 1);
0229     QCOMPARE(nClosedSpy.size(), 1);
0230 }
0231 
0232 void KNotificationTest::noActionsTest()
0233 {
0234     // event doesn't exist in config, meaning it has no actions
0235     QPointer<KNotification> n(new KNotification(QStringLiteral("noActionsEvent")));
0236     QSignalSpy nClosedSpy(n, SIGNAL(closed()));
0237     n->sendEvent();
0238 
0239     nClosedSpy.wait(100);
0240     QCOMPARE(nClosedSpy.size(), 1);
0241     QVERIFY(n.isNull());
0242 }
0243 
0244 QTEST_GUILESS_MAIN_SYSTEM_DBUS(KNotificationTest)
0245 #include "knotification_test.moc"