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"