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"