File indexing completed on 2024-05-12 09:05:04

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         auto account2 = new MockAccount();
0053         AccountManager::instance().addAccount(account2, false);
0054 
0055         QCOMPARE(timelineModel.displayName(), QStringLiteral("Home (test)"));
0056 
0057         account->clearFakeIdentity();
0058     }
0059 
0060     void testStreamUpdate()
0061     {
0062         QFile statusExampleApi;
0063         statusExampleApi.setFileName(QLatin1String(DATA_DIR) + QLatin1Char('/') + "status.json"_L1);
0064         statusExampleApi.open(QIODevice::ReadOnly);
0065 
0066         MainTimelineModel timelineModel;
0067         timelineModel.setName(QStringLiteral("home"));
0068         QCOMPARE(timelineModel.rowCount({}), 0);
0069 
0070         account->streamingEvent(AbstractAccount::StreamingEventType::UpdateEvent, statusExampleApi.readAll());
0071         QCOMPARE(timelineModel.rowCount({}), 1);
0072     }
0073 
0074     void testFillTimelineMain()
0075     {
0076         account->registerGet(account->apiUrl(QStringLiteral("/api/v1/timelines/home")), new TestReply(QStringLiteral("statuses.json"), account));
0077         auto fetchMoreUrl = account->apiUrl(QStringLiteral("/api/v1/timelines/home"));
0078         fetchMoreUrl.setQuery(QUrlQuery{
0079             {QStringLiteral("max_id"), QStringLiteral("103270115826038975")},
0080         });
0081         account->registerGet(fetchMoreUrl, new TestReply(QStringLiteral("statuses.json"), account));
0082 
0083         MainTimelineModel timelineModel;
0084         timelineModel.setName(QStringLiteral("home"));
0085 
0086         QCOMPARE(timelineModel.rowCount({}), 5);
0087         QVERIFY(timelineModel.canFetchMore({}));
0088         timelineModel.fetchMore({});
0089         QCOMPARE(timelineModel.rowCount({}), 10);
0090     }
0091 
0092     void testTagModel()
0093     {
0094         account->registerGet(account->apiUrl(QStringLiteral("/api/v1/timelines/tag/home")), new TestReply(QStringLiteral("statuses.json"), account));
0095         auto fetchMoreUrl = account->apiUrl(QStringLiteral("/api/v1/timelines/tag/home"));
0096         fetchMoreUrl.setQuery(QUrlQuery{
0097             {QStringLiteral("max_id"), QStringLiteral("103270115826038975")},
0098         });
0099         account->registerGet(fetchMoreUrl, new TestReply(QStringLiteral("statuses.json"), account));
0100 
0101         TagsTimelineModel tagModel;
0102         tagModel.setHashtag(QStringLiteral("home"));
0103 
0104         QCOMPARE(tagModel.rowCount({}), 5);
0105         QVERIFY(tagModel.canFetchMore({}));
0106         tagModel.fetchMore({});
0107         QCOMPARE(tagModel.rowCount({}), 10);
0108     }
0109 
0110     void testThreadModel()
0111     {
0112         account->registerGet(account->apiUrl(QStringLiteral("/api/v1/statuses/103270115826048975")), new TestReply(QStringLiteral("status.json"), account));
0113         account->registerGet(account->apiUrl(QStringLiteral("/api/v1/statuses/103270115826048975/context")),
0114                              new TestReply(QStringLiteral("context.json"), account));
0115 
0116         ThreadModel threadModel;
0117         threadModel.setPostId(QStringLiteral("103270115826048975"));
0118         QCOMPARE(threadModel.rowCount({}), 4);
0119         QCOMPARE(threadModel.data(threadModel.index(1, 0), AbstractTimelineModel::SelectedRole).toBool(), true);
0120         QCOMPARE(threadModel.displayName(), QStringLiteral("Thread"));
0121         QCOMPARE(threadModel.postId(), QStringLiteral("103270115826048975"));
0122         QCOMPARE(threadModel.canFetchMore({}), false);
0123 
0124         // in_reply_to_account_id filled
0125         QCOMPARE(threadModel.data(threadModel.index(2, 0), AbstractTimelineModel::IsReplyRole).toBool(), true);
0126         QCOMPARE(threadModel.data(threadModel.index(2, 0), AbstractTimelineModel::AuthorIdentityRole).value<Identity *>()->username(),
0127                  QStringLiteral("Gargron"));
0128 
0129         // in_reply_to_account_id unfilled
0130         QCOMPARE(threadModel.data(threadModel.index(3, 0), AbstractTimelineModel::IsReplyRole).toBool(), true);
0131         QCOMPARE(threadModel.data(threadModel.index(3, 0), AbstractTimelineModel::AuthorIdentityRole).value<Identity *>()->username(),
0132                  QStringLiteral("Gargron"));
0133     }
0134 
0135     void testModelPoll()
0136     {
0137         MainTimelineModel timelineModel;
0138         timelineModel.setName(QStringLiteral("home"));
0139 
0140         QFile statusExampleApi;
0141         statusExampleApi.setFileName(QLatin1String(DATA_DIR) + QLatin1Char('/') + "status-poll.json"_L1);
0142         statusExampleApi.open(QIODevice::ReadOnly);
0143         account->streamingEvent(AbstractAccount::StreamingEventType::UpdateEvent, statusExampleApi.readAll());
0144         QCOMPARE(timelineModel.rowCount({}), 6);
0145 
0146         QCOMPARE(timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::IdRole).value<QString>(), QStringLiteral("103270115826048975"));
0147         QCOMPARE(timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::MentionsRole).value<QStringList>(), QStringList{});
0148         QCOMPARE(timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::ContentRole).value<QString>(), QStringLiteral("<p>LOREM</p>"));
0149         QCOMPARE(timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::AuthorIdentityRole).value<Identity *>()->id(), QStringLiteral("1"));
0150         QCOMPARE(timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::AuthorIdentityRole).value<Identity *>()->displayNameHtml(),
0151                  QStringLiteral("Eugen <img height=\"16\" align=\"middle\" width=\"16\" src=\"https://kde.org\">"));
0152         QCOMPARE(timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::IsBoostedRole).value<bool>(), false);
0153 
0154         const auto poll = timelineModel.data(timelineModel.index(0, 0), AbstractTimelineModel::PollRole).value<Poll>();
0155         QCOMPARE(poll.id(), QStringLiteral("34830"));
0156         QCOMPARE(poll.expiresAt().date().year(), 2019);
0157         QCOMPARE(poll.expired(), true);
0158         QCOMPARE(poll.multiple(), false);
0159         QCOMPARE(poll.votesCount(), 10);
0160         QCOMPARE(poll.votersCount(), -1);
0161         QCOMPARE(poll.voted(), true);
0162         QCOMPARE(poll.ownVotes().count(), 1);
0163         QCOMPARE(poll.ownVotes()[0], 1);
0164         QCOMPARE(poll.options().count(), 2);
0165         QCOMPARE(poll.options()[0]["title"_L1], QStringLiteral("accept"));
0166         QCOMPARE(poll.options()[0]["votesCount"_L1], 6);
0167         QCOMPARE(poll.options()[1]["title"_L1], QStringLiteral("deny <img height=\"16\" align=\"middle\" width=\"16\" src=\"https://kde.org\">"));
0168         QCOMPARE(poll.options()[1]["votesCount"_L1], 4);
0169 
0170         account->registerPost(QStringLiteral("/api/v1/polls/34830/votes"), new TestReply(QStringLiteral("poll.json"), account));
0171 
0172         QSignalSpy spy(&timelineModel, &QAbstractItemModel::dataChanged);
0173         QVERIFY(spy.isValid());
0174         timelineModel.actionVote(timelineModel.index(0, 0), {0});
0175         spy.wait(1000);
0176         QCOMPARE(spy.count(), 1);
0177         const auto arguments = spy.takeFirst();
0178         QCOMPARE(arguments[0].value<QModelIndex>().row(), 0);
0179         QCOMPARE(arguments[1].value<QModelIndex>().row(), 0);
0180         QCOMPARE(arguments[2].value<QList<int>>().count(), 1);
0181         QCOMPARE(arguments[2].value<QList<int>>()[0], AbstractTimelineModel::PollRole);
0182     }
0183 
0184     void testFillListTimeline()
0185     {
0186         account->registerGet(account->apiUrl(QStringLiteral("/api/v1/timelines/list/1")), new TestReply(QStringLiteral("statuses.json"), account));
0187         auto fetchMoreUrl = account->apiUrl(QStringLiteral("/api/v1/timelines/list/1"));
0188         fetchMoreUrl.setQuery(QUrlQuery{
0189             {QStringLiteral("max_id"), QStringLiteral("103270115826038975")},
0190         });
0191         account->registerGet(fetchMoreUrl, new TestReply(QStringLiteral("statuses.json"), account));
0192 
0193         MainTimelineModel timelineModel;
0194         timelineModel.setName(QStringLiteral("list"));
0195 
0196         // nothing should be loaded because we didn't give it a list id yet
0197         QCOMPARE(timelineModel.rowCount({}), 0);
0198 
0199         timelineModel.setListId(QStringLiteral("1"));
0200 
0201         QCOMPARE(timelineModel.rowCount({}), 5);
0202         QVERIFY(timelineModel.canFetchMore({}));
0203         timelineModel.fetchMore({});
0204         QCOMPARE(timelineModel.rowCount({}), 10);
0205     }
0206 
0207 private:
0208     MockAccount *account = nullptr;
0209 };
0210 
0211 QTEST_MAIN(TimelineTest)
0212 #include "timelinetest.moc"