File indexing completed on 2024-04-28 05:02:16

0001 // SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
0002 // SPDX-License-Identifier: GPL-3.0-or-later
0003 
0004 #include <QtTest/QtTest>
0005 
0006 #include "helperreply.h"
0007 #include "mockaccount.h"
0008 #include "timeline/maintimelinemodel.h"
0009 #include "timeline/tagstimelinemodel.h"
0010 #include "timeline/threadmodel.h"
0011 #include <KLocalizedString>
0012 
0013 using namespace Qt::Literals::StringLiterals;
0014 
0015 class TimelineTest : public QObject
0016 {
0017     Q_OBJECT
0018 
0019 private Q_SLOTS:
0020     void initTestCase()
0021     {
0022         account = new MockAccount();
0023         AccountManager::instance().addAccount(account, false);
0024         AccountManager::instance().selectAccount(account);
0025     }
0026 
0027     void cleanupTestCase()
0028     {
0029         AccountManager::instance().removeAccount(account);
0030     }
0031 
0032     void testMainDisplayName()
0033     {
0034         KLocalizedString::setApplicationDomain(QByteArrayLiteral("tokodon"));
0035         KLocalizedString::setLanguages(QStringList{QStringLiteral("C")});
0036         account->setUsername(QStringLiteral("test"));
0037 
0038         QJsonObject fakeIdentity;
0039         fakeIdentity["id"_L1] = QStringLiteral("1");
0040         fakeIdentity["display_name"_L1] = QStringLiteral("test");
0041 
0042         account->setFakeIdentity(fakeIdentity);
0043 
0044         MainTimelineModel timelineModel;
0045         timelineModel.setName(QStringLiteral("public"));
0046         QCOMPARE(timelineModel.displayName(), QStringLiteral("Local Timeline"));
0047         timelineModel.setName(QStringLiteral("federated"));
0048         QCOMPARE(timelineModel.displayName(), QStringLiteral("Global Timeline"));
0049         timelineModel.setName(QStringLiteral("home"));
0050         QCOMPARE(timelineModel.displayName(), QStringLiteral("Home"));
0051 
0052         account->clearFakeIdentity();
0053     }
0054 
0055     void testStreamUpdate()
0056     {
0057         QFile statusExampleApi;
0058         statusExampleApi.setFileName(QLatin1String(DATA_DIR) + QLatin1Char('/') + "status.json"_L1);
0059         statusExampleApi.open(QIODevice::ReadOnly);
0060 
0061         MainTimelineModel timelineModel;
0062         timelineModel.setName(QStringLiteral("home"));
0063         QCOMPARE(timelineModel.rowCount({}), 0);
0064 
0065         account->streamingEvent(AbstractAccount::StreamingEventType::UpdateEvent, statusExampleApi.readAll());
0066         QCOMPARE(timelineModel.rowCount({}), 1);
0067     }
0068 
0069     void testFillTimelineMain()
0070     {
0071         account->registerGet(account->apiUrl(QStringLiteral("/api/v1/timelines/home")), new TestReply(QStringLiteral("statuses.json"), account));
0072         auto fetchMoreUrl = account->apiUrl(QStringLiteral("/api/v1/timelines/home"));
0073         fetchMoreUrl.setQuery(QUrlQuery{
0074             {QStringLiteral("max_id"), QStringLiteral("103270115826038975")},
0075         });
0076         account->registerGet(fetchMoreUrl, new TestReply(QStringLiteral("statuses.json"), account));
0077 
0078         MainTimelineModel timelineModel;
0079         timelineModel.setName(QStringLiteral("home"));
0080 
0081         QCOMPARE(timelineModel.rowCount({}), 5);
0082         QVERIFY(timelineModel.canFetchMore({}));
0083         timelineModel.fetchMore({});
0084         QCOMPARE(timelineModel.rowCount({}), 10);
0085     }
0086 
0087     void testTagModel()
0088     {
0089         account->registerGet(account->apiUrl(QStringLiteral("/api/v1/timelines/tag/home")), new TestReply(QStringLiteral("statuses.json"), account));
0090         auto fetchMoreUrl = account->apiUrl(QStringLiteral("/api/v1/timelines/tag/home"));
0091         fetchMoreUrl.setQuery(QUrlQuery{
0092             {QStringLiteral("max_id"), QStringLiteral("103270115826038975")},
0093         });
0094         account->registerGet(fetchMoreUrl, new TestReply(QStringLiteral("statuses.json"), account));
0095 
0096         TagsTimelineModel tagModel;
0097         tagModel.setHashtag(QStringLiteral("home"));
0098 
0099         QCOMPARE(tagModel.rowCount({}), 5);
0100         QVERIFY(tagModel.canFetchMore({}));
0101         tagModel.fetchMore({});
0102         QCOMPARE(tagModel.rowCount({}), 10);
0103     }
0104 
0105     void testThreadModel()
0106     {
0107         account->registerGet(account->apiUrl(QStringLiteral("/api/v1/statuses/103270115826048975")), new TestReply(QStringLiteral("status.json"), account));
0108         account->registerGet(account->apiUrl(QStringLiteral("/api/v1/statuses/103270115826048975/context")),
0109                              new TestReply(QStringLiteral("context.json"), account));
0110 
0111         ThreadModel threadModel;
0112         threadModel.setPostId(QStringLiteral("103270115826048975"));
0113         QCOMPARE(threadModel.rowCount({}), 4);
0114         QCOMPARE(threadModel.data(threadModel.index(1, 0), AbstractTimelineModel::SelectedRole).toBool(), true);
0115         QCOMPARE(threadModel.displayName(), QStringLiteral("Thread"));
0116         QCOMPARE(threadModel.postId(), QStringLiteral("103270115826048975"));
0117         QCOMPARE(threadModel.canFetchMore({}), false);
0118 
0119         // in_reply_to_account_id filled
0120         QCOMPARE(threadModel.data(threadModel.index(2, 0), AbstractTimelineModel::IsReplyRole).toBool(), true);
0121         QCOMPARE(threadModel.data(threadModel.index(2, 0), AbstractTimelineModel::AuthorIdentityRole).value<Identity *>()->username(),
0122                  QStringLiteral("Gargron"));
0123 
0124         // in_reply_to_account_id unfilled
0125         QCOMPARE(threadModel.data(threadModel.index(3, 0), AbstractTimelineModel::IsReplyRole).toBool(), true);
0126         QCOMPARE(threadModel.data(threadModel.index(3, 0), AbstractTimelineModel::AuthorIdentityRole).value<Identity *>()->username(),
0127                  QStringLiteral("Gargron"));
0128     }
0129 
0130     void testModelPoll()
0131     {
0132         MainTimelineModel timelineModel;
0133         timelineModel.setName(QStringLiteral("home"));
0134 
0135         QFile statusExampleApi;
0136         statusExampleApi.setFileName(QLatin1String(DATA_DIR) + QLatin1Char('/') + "status-poll.json"_L1);
0137         statusExampleApi.open(QIODevice::ReadOnly);
0138         account->streamingEvent(AbstractAccount::StreamingEventType::UpdateEvent, statusExampleApi.readAll());
0139         QCOMPARE(timelineModel.rowCount({}), 6);
0140 
0141         QCOMPARE(timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::IdRole).value<QString>(), QStringLiteral("103270115826048975"));
0142         QCOMPARE(timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::MentionsRole).value<QStringList>(), QStringList{});
0143         QCOMPARE(timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::ContentRole).value<QString>(), QStringLiteral("<p>LOREM</p>"));
0144         QCOMPARE(timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::AuthorIdentityRole).value<Identity *>()->id(), QStringLiteral("1"));
0145         QCOMPARE(timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::AuthorIdentityRole).value<Identity *>()->displayNameHtml(),
0146                  QStringLiteral("Eugen <img height=\"16\" align=\"middle\" width=\"16\" src=\"https://kde.org\">"));
0147         QCOMPARE(timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::IsBoostedRole).value<bool>(), false);
0148 
0149         const auto poll = timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::PollRole).value<Poll>();
0150         QCOMPARE(poll.id(), QStringLiteral("34830"));
0151         QCOMPARE(poll.expiresAt().date().year(), 2019);
0152         QCOMPARE(poll.expired(), true);
0153         QCOMPARE(poll.multiple(), false);
0154         QCOMPARE(poll.votesCount(), 10);
0155         QCOMPARE(poll.votersCount(), -1);
0156         QCOMPARE(poll.voted(), true);
0157         QCOMPARE(poll.ownVotes().count(), 1);
0158         QCOMPARE(poll.ownVotes()[0], 1);
0159         QCOMPARE(poll.options().count(), 2);
0160         QCOMPARE(poll.options()[0]["title"_L1], QStringLiteral("accept"));
0161         QCOMPARE(poll.options()[0]["votesCount"_L1], 6);
0162         QCOMPARE(poll.options()[1]["title"_L1], QStringLiteral("deny <img height=\"16\" align=\"middle\" width=\"16\" src=\"https://kde.org\">"));
0163         QCOMPARE(poll.options()[1]["votesCount"_L1], 4);
0164 
0165         account->registerPost(QStringLiteral("/api/v1/polls/34830/votes"), new TestReply(QStringLiteral("poll.json"), account));
0166 
0167         QSignalSpy spy(&timelineModel, &QAbstractItemModel::dataChanged);
0168         QVERIFY(spy.isValid());
0169         timelineModel.actionVote(timelineModel.index(0, 0), {0});
0170         spy.wait(1000);
0171         QCOMPARE(spy.count(), 1);
0172         const auto arguments = spy.takeFirst();
0173         QCOMPARE(arguments[0].value<QModelIndex>().row(), 0);
0174         QCOMPARE(arguments[1].value<QModelIndex>().row(), 0);
0175         QCOMPARE(arguments[2].value<QList<int>>().count(), 1);
0176         QCOMPARE(arguments[2].value<QList<int>>()[0], AbstractTimelineModel::PollRole);
0177     }
0178 
0179     void testFillListTimeline()
0180     {
0181         account->registerGet(account->apiUrl(QStringLiteral("/api/v1/timelines/list/1")), new TestReply(QStringLiteral("statuses.json"), account));
0182         auto fetchMoreUrl = account->apiUrl(QStringLiteral("/api/v1/timelines/list/1"));
0183         fetchMoreUrl.setQuery(QUrlQuery{
0184             {QStringLiteral("max_id"), QStringLiteral("103270115826038975")},
0185         });
0186         account->registerGet(fetchMoreUrl, new TestReply(QStringLiteral("statuses.json"), account));
0187 
0188         MainTimelineModel timelineModel;
0189         timelineModel.setName(QStringLiteral("list"));
0190 
0191         // nothing should be loaded because we didn't give it a list id yet
0192         QCOMPARE(timelineModel.rowCount({}), 0);
0193 
0194         timelineModel.setListId(QStringLiteral("1"));
0195 
0196         QCOMPARE(timelineModel.rowCount({}), 5);
0197         QVERIFY(timelineModel.canFetchMore({}));
0198         timelineModel.fetchMore({});
0199         QCOMPARE(timelineModel.rowCount({}), 10);
0200     }
0201 
0202 private:
0203     MockAccount *account = nullptr;
0204 };
0205 
0206 QTEST_MAIN(TimelineTest)
0207 #include "timelinetest.moc"