File indexing completed on 2024-05-12 17:09:58
0001 /* 0002 SPDX-FileCopyrightText: 2017 David Edmundson <davidedmundson@kde.org> 0003 SPDX-FileCopyrightText: 2020 Kai Uwe Broulik <kde@broulik.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include <QDebug> 0009 #include <QObject> 0010 #include <QtTest> 0011 0012 #include "notification.h" 0013 #include "notificationsmodel.h" 0014 #include "server.h" 0015 0016 namespace NotificationManager 0017 { 0018 class NotificationTest : public QObject 0019 { 0020 Q_OBJECT 0021 public: 0022 NotificationTest() 0023 { 0024 } 0025 private Q_SLOTS: 0026 void parse_data(); 0027 void parse(); 0028 0029 void compressNotificationRemoval(); 0030 }; 0031 0032 void NotificationTest::parse_data() 0033 { 0034 QTest::addColumn<QString>("messageIn"); 0035 QTest::addColumn<QString>("expectedOut"); 0036 0037 // clang-format off 0038 QTest::newRow("basic no HTML") << "I am a notification" << "I am a notification"; 0039 QTest::newRow("whitespace") << " I am a notification " << "I am a notification"; 0040 0041 QTest::newRow("basic html") << "I am <b>the</b> notification" << "I am <b>the</b> notification"; 0042 QTest::newRow("nested html") << "I am <i><b>the</b></i> notification" << "I am <i><b>the</b></i> notification"; 0043 0044 QTest::newRow("no extra tags") << "I am <blink>the</blink> notification" << "I am the notification"; 0045 QTest::newRow("no extra attrs") << "I am <b style=\"font-weight:20\">the</b> notification" << "I am <b>the</b> notification"; 0046 0047 QTest::newRow("newlines") << "I am\nthe\nnotification" << "I am<br/>the<br/>notification"; 0048 QTest::newRow("multinewlines") << "I am\n\nthe\n\n\nnotification" << "I am<br/>the<br/>notification"; 0049 0050 QTest::newRow("amp") << "me&you" << "me&you"; 0051 QTest::newRow("double escape") << "foo & <bar>" << "foo & <bar>"; 0052 0053 QTest::newRow("quotes") << "'foo'" << "'foo'";//as label can't handle this normally valid entity 0054 0055 QTest::newRow("image normal") << "This is <img src=\"file:://foo/boo.png\" alt=\"cheese\"/> and more text" << "This is <img src=\"file:://foo/boo.png\" alt=\"cheese\"/> and more text"; 0056 0057 //this input is technically wrong, so the output is also wrong, but QTextHtmlParser does the "right" thing 0058 QTest::newRow("image normal no close") << "This is <img src=\"file:://foo/boo.png\" alt=\"cheese\"> and more text" << "This is <img src=\"file:://foo/boo.png\" alt=\"cheese\"> and more text</img>"; 0059 0060 QTest::newRow("image remote URL") << "This is <img src=\"http://foo.com/boo.png\" alt=\"cheese\" /> and more text" << "This is <img alt=\"cheese\"/> and more text"; 0061 0062 //more bad formatted options. To some extent actual output doesn't matter. Garbage in, garbage out. 0063 //the important thing is that it doesn't contain anything that could be parsed as the remote URL 0064 QTest::newRow("image remote URL no close") << "This is <img src=\"http://foo.com/boo.png>\" alt=\"cheese\"> and more text" << "This is <img alt=\"cheese\"> and more text</img>"; 0065 QTest::newRow("image remote URL double open") << "This is <<img src=\"http://foo.com/boo.png>\" and more text" << "This is "; 0066 QTest::newRow("image remote URL no entity close") << "This is <img src=\"http://foo.com/boo.png\" and more text" << "This is "; 0067 QTest::newRow("image remote URL space in element name") << "This is < img src=\"http://foo.com/boo.png\" alt=\"cheese\" /> and more text" << "This is "; 0068 0069 QTest::newRow("link") << "This is a link <a href=\"http://foo.com/boo\"/> and more text" << "This is a link <a href=\"http://foo.com/boo\"/> and more text"; 0070 // clang-format on 0071 } 0072 0073 void NotificationTest::parse() 0074 { 0075 QFETCH(QString, messageIn); 0076 QFETCH(QString, expectedOut); 0077 0078 NotificationManager::Notification notification; 0079 notification.setBody(messageIn); 0080 0081 expectedOut = "<?xml version=\"1.0\"?><html>" + expectedOut + "</html>\n"; 0082 0083 QCOMPARE(notification.body(), expectedOut); 0084 } 0085 0086 void NotificationTest::compressNotificationRemoval() 0087 { 0088 const int notificationCount = 10; 0089 const int gapId = 4; 0090 0091 auto model = NotificationsModel::createNotificationsModel(); 0092 0093 QSignalSpy rowsRemovedSpy(model.data(), &QAbstractItemModel::rowsRemoved); 0094 QVERIFY(rowsRemovedSpy.isValid()); 0095 0096 for (uint i = 1; i <= notificationCount; ++i) { 0097 Notification notification{i}; 0098 notification.setSummary(QStringLiteral("Notification %1").arg(i)); 0099 model->onNotificationAdded(notification); 0100 } 0101 0102 QCOMPARE(model->rowCount(), notificationCount); 0103 0104 for (uint i = 1; i <= notificationCount; ++i) { 0105 // Leave a gap inbetween 0106 if (i != gapId) { 0107 model->onNotificationRemoved(i, Server::CloseReason::Revoked); 0108 } 0109 } 0110 0111 // We should have two ranges that we ended up removing 0112 QTRY_COMPARE(rowsRemovedSpy.count(), 2); 0113 0114 // The fact that it emits row removal in reverse order is an implementation detail 0115 // We only really care that the number of rows emitted matches our expectation 0116 int removedCount = 0; 0117 for (const auto &removedEmission : rowsRemovedSpy) { 0118 const int from = removedEmission.at(1).toInt(); 0119 const int to = removedEmission.at(2).toInt(); 0120 removedCount += (to - from) + 1; 0121 } 0122 0123 QCOMPARE(removedCount, notificationCount - 1); 0124 QCOMPARE(model->rowCount(), 1); 0125 0126 rowsRemovedSpy.clear(); 0127 0128 // Removing a random non-existing notification should noop 0129 model->onNotificationRemoved(3, Server::CloseReason::Revoked); 0130 QTRY_COMPARE(rowsRemovedSpy.count(), 0); 0131 QCOMPARE(model->rowCount(), 1); 0132 rowsRemovedSpy.clear(); 0133 0134 // Now remove the last one 0135 model->onNotificationRemoved(gapId, Server::CloseReason::Revoked); 0136 QTRY_COMPARE(rowsRemovedSpy.count(), 1); 0137 QCOMPARE(rowsRemovedSpy.at(0).at(1), 0); // from 0138 QCOMPARE(rowsRemovedSpy.at(0).at(2), 0); // to 0139 QCOMPARE(model->rowCount(), 0); 0140 } 0141 0142 } // namespace NotificationManager 0143 0144 QTEST_GUILESS_MAIN(NotificationManager::NotificationTest) 0145 0146 #include "notifications_test.moc"