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"