File indexing completed on 2024-12-01 04:35:25
0001 /* 0002 SPDX-FileCopyrightText: 2017-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "messagesmodeltest.h" 0008 #include "model/messagesmodel.h" 0009 #include "rocketchataccount.h" 0010 #include "ruqola.h" 0011 #include "test_model_helpers.h" 0012 #include <QStandardPaths> 0013 #include <QTest> 0014 0015 QTEST_GUILESS_MAIN(MessagesModelTest) 0016 0017 MessagesModelTest::MessagesModelTest(QObject *parent) 0018 : QObject(parent) 0019 { 0020 } 0021 0022 void MessagesModelTest::initTestCase() 0023 { 0024 QStandardPaths::setTestModeEnabled(true); 0025 auto *rcAccount = Ruqola::self()->rocketChatAccount(); 0026 QVERIFY(rcAccount); 0027 rcAccount->settings()->setUserId(QStringLiteral("userid1")); 0028 } 0029 0030 void MessagesModelTest::shouldHaveDefaultValue() 0031 { 0032 MessagesModel w(QStringLiteral("roomId"), Ruqola::self()->rocketChatAccount()); 0033 QCOMPARE(w.rowCount(), 0); 0034 QVERIFY(w.searchText().isEmpty()); 0035 } 0036 0037 static void fillTestMessage(Message &input) 0038 { 0039 input.setRoomId(QStringLiteral("room2")); 0040 input.setText(QStringLiteral("message1")); 0041 input.setTimeStamp(QDateTime::currentMSecsSinceEpoch()); 0042 input.setUsername(QStringLiteral("user1")); 0043 input.setUserId(QStringLiteral("userid1")); 0044 input.setUpdatedAt(45); 0045 input.setEditedAt(89); 0046 input.setEditedByUsername(QStringLiteral("editeduser1")); 0047 input.setEditedByUserId(QStringLiteral("editedbyid1")); 0048 input.setAlias(QStringLiteral("ali")); 0049 input.setAvatar(QStringLiteral("avatar1")); 0050 input.setSystemMessageType(QStringLiteral("type")); 0051 input.setGroupable(true); 0052 input.setParseUrls(true); 0053 input.setMessageType(Message::MessageType::NormalText); 0054 } 0055 0056 void MessagesModelTest::shouldAddMessage() 0057 { 0058 MessagesModel w; 0059 Message input; 0060 fillTestMessage(input); 0061 input.setMessageId(QStringLiteral("ff")); 0062 w.addMessages({input}); 0063 0064 QCOMPARE(w.rowCount(), 1); 0065 // Don't create duplicates 0066 w.addMessages({input}); 0067 QCOMPARE(w.rowCount(), 1); 0068 0069 // Add other messageId 0070 input.setMessageId(QStringLiteral("ff2")); 0071 input.setTimeStamp(43); 0072 w.addMessages({input}); 0073 QCOMPARE(w.rowCount(), 2); 0074 0075 input.setMessageId(QStringLiteral("ff3")); 0076 input.setTimeStamp(44); 0077 w.addMessages({input}); 0078 QCOMPARE(w.rowCount(), 3); 0079 0080 input.setMessageId(QStringLiteral("ff4")); 0081 input.setTimeStamp(45); 0082 w.addMessages({input}); 0083 QCOMPARE(w.rowCount(), 4); 0084 0085 input.setMessageId(QStringLiteral("ff2")); 0086 input.setTimeStamp(43); 0087 w.addMessages({input}); 0088 QCOMPARE(w.rowCount(), 4); 0089 } 0090 0091 void MessagesModelTest::shouldRemoveMessage() 0092 { 0093 MessagesModel w; 0094 Message input; 0095 fillTestMessage(input); 0096 0097 QSignalSpy rowInsertedSpy(&w, &MessagesModel::rowsInserted); 0098 QSignalSpy rowABTInserted(&w, &MessagesModel::rowsAboutToBeInserted); 0099 QSignalSpy rowRemovedSpy(&w, &MessagesModel::rowsRemoved); 0100 QSignalSpy rowABTRemoved(&w, &MessagesModel::rowsAboutToBeRemoved); 0101 0102 const QString messageId = QStringLiteral("ff"); 0103 input.setMessageId(messageId); 0104 w.addMessages({input}); 0105 0106 QCOMPARE(w.rowCount(), 1); 0107 // Remove existing message 0108 0109 QCOMPARE(rowInsertedSpy.count(), 1); 0110 QCOMPARE(rowABTInserted.count(), 1); 0111 QCOMPARE(rowRemovedSpy.count(), 0); 0112 QCOMPARE(rowABTRemoved.count(), 0); 0113 QCOMPARE(TestModelHelpers::rowSpyToText(rowInsertedSpy), QStringLiteral("0,0")); 0114 QCOMPARE(TestModelHelpers::rowSpyToText(rowABTInserted), QStringLiteral("0,0")); 0115 0116 rowInsertedSpy.clear(); 0117 rowABTInserted.clear(); 0118 rowRemovedSpy.clear(); 0119 rowABTRemoved.clear(); 0120 0121 w.deleteMessage(messageId); 0122 0123 QCOMPARE(rowInsertedSpy.count(), 0); 0124 QCOMPARE(rowABTInserted.count(), 0); 0125 QCOMPARE(rowRemovedSpy.count(), 1); 0126 QCOMPARE(rowABTRemoved.count(), 1); 0127 QCOMPARE(TestModelHelpers::rowSpyToText(rowRemovedSpy), QStringLiteral("0,0")); 0128 QCOMPARE(TestModelHelpers::rowSpyToText(rowABTRemoved), QStringLiteral("0,0")); 0129 0130 QCOMPARE(w.rowCount(), 0); 0131 0132 rowInsertedSpy.clear(); 0133 rowABTInserted.clear(); 0134 rowRemovedSpy.clear(); 0135 rowABTRemoved.clear(); 0136 0137 w.addMessages({input}); 0138 QCOMPARE(w.rowCount(), 1); 0139 QCOMPARE(rowABTInserted.count(), 1); 0140 QCOMPARE(rowRemovedSpy.count(), 0); 0141 QCOMPARE(rowABTRemoved.count(), 0); 0142 QCOMPARE(TestModelHelpers::rowSpyToText(rowInsertedSpy), QStringLiteral("0,0")); 0143 QCOMPARE(TestModelHelpers::rowSpyToText(rowABTInserted), QStringLiteral("0,0")); 0144 } 0145 0146 void MessagesModelTest::shouldRemoveNotExistingMessage() 0147 { 0148 MessagesModel w; 0149 Message input; 0150 fillTestMessage(input); 0151 const QString messageId = QStringLiteral("ff"); 0152 input.setMessageId(messageId); 0153 w.addMessages({input}); 0154 0155 QCOMPARE(w.rowCount(), 1); 0156 // Remove non-existing message 0157 w.deleteMessage(QStringLiteral("Bla")); 0158 QCOMPARE(w.rowCount(), 1); 0159 0160 input.setMessageId(QStringLiteral("ff3")); 0161 w.addMessages({input}); 0162 QCOMPARE(w.rowCount(), 2); 0163 0164 input.setMessageId(QStringLiteral("ff4")); 0165 w.addMessages({input}); 0166 QCOMPARE(w.rowCount(), 3); 0167 0168 // Remove 3th element 0169 w.deleteMessage(QStringLiteral("ff3")); 0170 QCOMPARE(w.rowCount(), 2); 0171 } 0172 0173 void MessagesModelTest::shouldDetectDateChange() 0174 { 0175 MessagesModel model; 0176 Message first; 0177 first.setMessageId(QStringLiteral("first")); 0178 first.setTimeStamp(QDateTime(QDate(2019, 6, 7), QTime(23, 50, 50)).toMSecsSinceEpoch()); 0179 model.addMessages({first}); 0180 QVERIFY(model.index(0, 0).data(MessagesModel::DateDiffersFromPrevious).toBool()); // first message 0181 0182 Message second; 0183 second.setMessageId(QStringLiteral("second")); 0184 second.setTimeStamp(QDateTime(QDate(2019, 6, 8), QTime(1, 2, 3)).toMSecsSinceEpoch()); 0185 model.addMessages({second}); 0186 QCOMPARE(model.rowCount(), 2); 0187 QVERIFY(model.index(1, 0).data(MessagesModel::DateDiffersFromPrevious).toBool()); // next day 0188 0189 Message third; 0190 third.setTimeStamp(QDateTime(QDate(2019, 6, 8), QTime(1, 4, 3)).toMSecsSinceEpoch()); 0191 third.setMessageId(QStringLiteral("third")); 0192 model.addMessages({third}); 0193 QCOMPARE(model.rowCount(), 3); 0194 QVERIFY(!model.index(2, 0).data(MessagesModel::DateDiffersFromPrevious).toBool()); // same day 0195 } 0196 0197 static QByteArrayList extractMessageIds(MessagesModel &m) 0198 { 0199 QByteArrayList ret; 0200 const int count = m.rowCount(); 0201 ret.reserve(count); 0202 for (int row = 0; row < count; ++row) { 0203 ret << m.index(row, 0).data(MessagesModel::MessageId).toString().toLatin1(); 0204 } 0205 return ret; 0206 } 0207 0208 void MessagesModelTest::shouldAddMessages() 0209 { 0210 MessagesModel model; 0211 Message input; 0212 fillTestMessage(input); 0213 QVector<Message> messages; 0214 auto makeMessage = [&](const char *id, qint64 timestamp) { 0215 input.setMessageId(QString::fromLatin1(id)); 0216 input.setTimeStamp(timestamp); 0217 return input; 0218 }; 0219 messages << makeMessage("msgA", 8); 0220 messages << makeMessage("msgB", 4); 0221 messages << makeMessage("msgC", 6); 0222 messages << makeMessage("msgD", 2); 0223 model.addMessages(messages); 0224 QCOMPARE(model.rowCount(), 4); 0225 QCOMPARE(extractMessageIds(model), 0226 QByteArrayList() << "msgD" 0227 << "msgB" 0228 << "msgC" 0229 << "msgA"); 0230 0231 messages.clear(); 0232 messages << makeMessage("msgE", 1); 0233 messages << makeMessage("msgF", 3); 0234 messages << makeMessage("msgG", 9); 0235 messages << makeMessage("msgH", 5); 0236 input.setText(QStringLiteral("modified")); 0237 messages << makeMessage("msgA", 8); // update 0238 model.addMessages(messages); 0239 QCOMPARE(model.rowCount(), 8); 0240 QCOMPARE(extractMessageIds(model), 0241 QByteArrayList() << "msgE" 0242 << "msgD" 0243 << "msgF" 0244 << "msgB" 0245 << "msgH" 0246 << "msgC" 0247 << "msgA" 0248 << "msgG"); 0249 QCOMPARE(model.index(6, 0).data(MessagesModel::OriginalMessage).toString(), QStringLiteral("modified")); 0250 } 0251 0252 void MessagesModelTest::shouldUpdateFirstMessage() 0253 { 0254 MessagesModel model; 0255 Message input; 0256 fillTestMessage(input); 0257 model.addMessages({input}); 0258 QCOMPARE(model.rowCount(), 1); 0259 input.setText(QStringLiteral("modified")); 0260 model.addMessages({input}); 0261 QCOMPARE(model.index(0, 0).data(MessagesModel::OriginalMessage).toString(), QStringLiteral("modified")); 0262 } 0263 0264 void MessagesModelTest::shouldAllowEditing() 0265 { 0266 // GIVEN a message from me 0267 MessagesModel model(QStringLiteral("roomId"), Ruqola::self()->rocketChatAccount()); 0268 RuqolaServerConfig::ServerConfigFeatureTypes settings; 0269 settings |= RuqolaServerConfig::ServerConfigFeatureType::AllowEditingMessage; 0270 settings |= RuqolaServerConfig::ServerConfigFeatureType::AllowMessageDeleting; 0271 Ruqola::self()->rocketChatAccount()->ruqolaServerConfig()->setServerConfigFeatureTypes(settings); 0272 Message input; 0273 fillTestMessage(input); 0274 model.addMessages({input}); 0275 QCOMPARE(model.rowCount(), 1); 0276 0277 // THEN 0278 QVERIFY(model.index(0, 0).data(MessagesModel::CanDeleteMessage).toBool()); 0279 QVERIFY(model.index(0, 0).data(MessagesModel::CanEditMessage).toBool()); 0280 0281 // GIVEN a message from someone else 0282 input.setMessageId(QStringLiteral("msg2")); 0283 input.setUserId(QStringLiteral("someone_else")); 0284 model.addMessages({input}); 0285 0286 // THEN 0287 QVERIFY(!model.index(1, 0).data(MessagesModel::CanEditMessage).toBool()); 0288 QVERIFY(!model.index(1, 0).data(MessagesModel::CanDeleteMessage).toBool()); 0289 } 0290 0291 void MessagesModelTest::shouldFindPrevNextMessage() 0292 { 0293 // GIVEN an empty model 0294 MessagesModel model(QStringLiteral("roomId"), Ruqola::self()->rocketChatAccount()); 0295 0296 auto isByMe = [](const Message &msg) { 0297 return msg.userId() == QLatin1String("userid1"); 0298 }; 0299 0300 // THEN there is no prev/next message 0301 QCOMPARE(model.findNextMessageAfter(QString(), isByMe).messageId(), QString()); 0302 QCOMPARE(model.findLastMessageBefore(QString(), isByMe).messageId(), QString()); 0303 QCOMPARE(model.findNextMessageAfter(QStringLiteral("doesnotexist"), isByMe).messageId(), QString()); 0304 QCOMPARE(model.findLastMessageBefore(QStringLiteral("doesnotexist"), isByMe).messageId(), QString()); 0305 0306 // GIVEN a non-empty model 0307 Message input; 0308 fillTestMessage(input); 0309 QVector<Message> messages; 0310 auto makeMessage = [&](const char *id, const char *userId) { 0311 input.setMessageId(QString::fromLatin1(id)); 0312 input.setUserId(QString::fromLatin1(userId)); 0313 static int timestamp = 1; 0314 input.setTimeStamp(timestamp); 0315 return input; 0316 }; 0317 messages << makeMessage("msgA", "userid1"); 0318 messages << makeMessage("msgB", "userid2"); 0319 messages << makeMessage("msgC", "userid1"); 0320 model.addMessages(messages); 0321 0322 // WHEN/THEN 0323 QCOMPARE(model.findLastMessageBefore(QString(), isByMe).messageId(), QStringLiteral("msgC")); 0324 QCOMPARE(model.findLastMessageBefore(QStringLiteral("msgC"), isByMe).messageId(), QStringLiteral("msgA")); 0325 QCOMPARE(model.findLastMessageBefore(QStringLiteral("msgA"), isByMe).messageId(), QString()); 0326 QCOMPARE(model.findNextMessageAfter(QString(), isByMe).messageId(), QString()); 0327 QCOMPARE(model.findNextMessageAfter(QStringLiteral("msgC"), isByMe).messageId(), QString()); 0328 QCOMPARE(model.findNextMessageAfter(QStringLiteral("msgA"), isByMe).messageId(), QStringLiteral("msgC")); 0329 } 0330 0331 #include "moc_messagesmodeltest.cpp"