testactivitydata.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. * Copyright (C) by Claudio Cambra <claudio.cambra@nextcloud.com>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. * for more details.
  13. */
  14. #include "gui/tray/activitydata.h"
  15. #include "account.h"
  16. #include "accountstate.h"
  17. #include "configfile.h"
  18. #include "syncenginetestutils.h"
  19. #include "syncfileitem.h"
  20. #include "folder.h"
  21. #include "folderman.h"
  22. #include "testhelper.h"
  23. #include <QTest>
  24. #include <QHash>
  25. namespace {
  26. constexpr auto events = 3;
  27. constexpr auto eventC = "event";
  28. constexpr auto calendarC = "calendar";
  29. constexpr auto nameC = "name";
  30. constexpr auto linkC = "link";
  31. constexpr auto typeC = "type";
  32. constexpr auto idC = "id";
  33. };
  34. class TestActivityData : public QObject
  35. {
  36. Q_OBJECT
  37. public:
  38. TestActivityData() = default;
  39. void createFilesActivityJsonData(QString fileFormat, QString mimeType)
  40. {
  41. const auto objectType = QStringLiteral("files");
  42. const auto subject = QStringLiteral("You created path/test.").append(fileFormat);
  43. const auto path = QStringLiteral("path/test.").append(fileFormat);
  44. const auto fileName = QStringLiteral("test.").append(fileFormat);
  45. const auto activityType = QStringLiteral("file");
  46. const auto activityId = 90000;
  47. const auto message = QString();
  48. const auto objectName = QStringLiteral("test.").append(fileFormat);
  49. const auto link = account->url().toString().append(QStringLiteral("/f/")).append(activityId);
  50. const auto datetime = QDateTime::currentDateTime().toString(Qt::ISODate);
  51. const auto icon = account->url().toString().append(QStringLiteral("/apps/files/img/add-color.svg"));
  52. const QJsonObject richStringData({
  53. {typeC, activityType},
  54. {idC, activityId},
  55. {linkC, link},
  56. {nameC, fileName},
  57. {QStringLiteral("path"), objectName}
  58. });
  59. const auto subjectRichString = QStringLiteral("You created {file1}");
  60. const auto subjectRichObj = QJsonObject({{QStringLiteral("file1"), richStringData}});
  61. const auto subjectRichData = QJsonArray({subjectRichString, subjectRichObj});
  62. const auto previewUrl = account->url().toString().append(QStringLiteral("/index.php/core/preview.png?file=/")).append(path);
  63. // Text file previews should be replaced by mimetype icon
  64. const QJsonObject previewData({
  65. {linkC, link},
  66. {QStringLiteral("mimeType"), mimeType},
  67. {QStringLiteral("fileId"), activityId},
  68. {QStringLiteral("filename"), fileName},
  69. {QStringLiteral("view"), QStringLiteral("files")},
  70. {QStringLiteral("source"), previewUrl},
  71. {QStringLiteral("isMimeTypeIcon"), false},
  72. });
  73. QJsonObject testData({
  74. {QStringLiteral("object_type"), objectType},
  75. {QStringLiteral("activity_id"), activityId},
  76. {typeC, activityType},
  77. {QStringLiteral("subject"), subject},
  78. {QStringLiteral("message"), message},
  79. {QStringLiteral("object_name"), objectName},
  80. {linkC, link},
  81. {QStringLiteral("datetime"), datetime},
  82. {QStringLiteral("icon"), icon},
  83. {QStringLiteral("subject_rich"), subjectRichData},
  84. {QStringLiteral("previews"), QJsonArray({previewData})},
  85. });
  86. QTest::addRow("data") << testData << fileFormat << mimeType << objectType << subject << path << fileName << activityType << activityId << message << objectName << link << datetime << icon << subjectRichString << subjectRichData << previewUrl;
  87. }
  88. void createCalendarActivityJsonData(QString name, QString event, QString calendar)
  89. {
  90. const auto objectType = calendarC;
  91. const auto subject = QStringLiteral("%1 updated event %2 in calendar %3").arg(name, event, calendar);
  92. const auto activityType = QStringLiteral("calendar_event");
  93. const auto activityId = 10000;
  94. const auto datetime = QDateTime::currentDateTime().toString(Qt::ISODate);
  95. const auto icon = account->url().toString().append(QStringLiteral("/core/img/places/calendar.svg"));
  96. const auto eventLink = QStringLiteral("/apps/calendar/dayGridMonth/now/edit/sidebar/A12bcD12AbcDEFgH456/next");
  97. const auto subjectRichString = QStringLiteral("{actor} updated event {event} in calendar {calendar}");
  98. const QJsonArray subjectRichData({
  99. subjectRichString,
  100. {{
  101. {objectType, {{
  102. {typeC, objectType},
  103. {idC, QString()},
  104. {linkC, QString()},
  105. {nameC, calendar},
  106. }}},
  107. {eventC, {{
  108. {typeC, QStringLiteral("calendar-event")},
  109. {idC, QStringLiteral("12AA3456-A1B2-A1B2-A1B2-AB12C34567D8")},
  110. {linkC, account->url().toString().append(eventLink)},
  111. {nameC, event},
  112. }}},
  113. {QStringLiteral("actor"), {{
  114. {typeC, QStringLiteral("user")},
  115. {idC, QStringLiteral("username")},
  116. {linkC, QString()},
  117. {nameC, name},
  118. }}},
  119. }},
  120. });
  121. QJsonObject testData({
  122. {QStringLiteral("object_type"), objectType},
  123. {QStringLiteral("subject"), subject},
  124. {typeC, activityType},
  125. {QStringLiteral("activity_id"), activityId},
  126. {QStringLiteral("object_name"), QString()},
  127. {QStringLiteral("datetime"), datetime},
  128. {QStringLiteral("icon"), icon},
  129. {QStringLiteral("subject_rich"), subjectRichData},
  130. });
  131. QTest::addRow("data") << testData << QString() << QString() << objectType << subject << QString() << QString() << activityType << activityId << QString() << QString() << QString() << datetime << icon << subjectRichString << subjectRichData << QString();
  132. }
  133. // We always "use" event. What you are observing comes from the event merging, e.g. if a user creates two events,
  134. // there will be only 1 activity entry saying "X created event A and B", but the mechanism is incremental and
  135. // when you only modified the same entry twice, you get "X updated event A" with A being event1 instead of event.
  136. void createCalendarEventMergedActivityJsonData(QString name, QString event, QString calendar, int mergedEvent)
  137. {
  138. const auto objectType = calendarC;
  139. const auto subject = QStringLiteral("%1 updated event %2 in calendar %3").arg(name, event, calendar);
  140. const auto activityType = QStringLiteral("calendar_event");
  141. const auto activityId = 10000;
  142. const auto datetime = QDateTime::currentDateTime().toString(Qt::ISODate);
  143. const auto icon = account->url().toString().append(QStringLiteral("/core/img/places/calendar.svg"));
  144. const auto eventLink = QStringLiteral("/apps/calendar/dayGridMonth/now/edit/sidebar/A12bcD12AbcDEFgH456/next");
  145. const auto subjectRichString = QStringLiteral("{actor} updated event {event%1} in calendar {calendar}").arg(mergedEvent);
  146. const QJsonArray subjectRichData({
  147. subjectRichString,
  148. {{
  149. {objectType, {{
  150. {typeC, objectType},
  151. {idC, QString()},
  152. {linkC, QString()},
  153. {nameC, calendar},
  154. }}},
  155. {QStringLiteral("event%1").arg(mergedEvent), {{
  156. {typeC, QStringLiteral("calendar-event")},
  157. {idC, QStringLiteral("12AA3456-A1B2-A1B2-A1B2-AB12C34567D8")},
  158. {linkC, account->url().toString().append(eventLink)},
  159. {nameC, event},
  160. }}},
  161. {QStringLiteral("actor"), {{
  162. {typeC, QStringLiteral("user")},
  163. {idC, QStringLiteral("username")},
  164. {linkC, QString()},
  165. {nameC, name},
  166. }}},
  167. }},
  168. });
  169. QJsonObject testData({
  170. {QStringLiteral("object_type"), objectType},
  171. {QStringLiteral("subject"), subject},
  172. {typeC, activityType},
  173. {QStringLiteral("activity_id"), activityId},
  174. {QStringLiteral("object_name"), QString()},
  175. {QStringLiteral("datetime"), datetime},
  176. {QStringLiteral("icon"), icon},
  177. {QStringLiteral("subject_rich"), subjectRichData},
  178. });
  179. QTest::addRow("data") << testData << QString() << QString() << objectType << subject << QString() << QString() << activityType << activityId << QString() << QString() << QString() << datetime << icon << subjectRichString << subjectRichData << QString();
  180. }
  181. QScopedPointer<FakeQNAM> fakeQnam;
  182. OCC::AccountPtr account;
  183. private slots:
  184. void initTestCase()
  185. {
  186. account = OCC::Account::create();
  187. account->setCredentials(new FakeCredentials{fakeQnam.data()});
  188. account->setUrl(QUrl(("http://example.de")));
  189. auto *cred = new HttpCredentialsTest("testuser", "secret");
  190. account->setCredentials(cred);
  191. }
  192. void testFromJson_data()
  193. {
  194. QTest::addColumn<QJsonObject>("activityJsonObject");
  195. QTest::addColumn<QString>("fileFormat");
  196. QTest::addColumn<QString>("mimeTypeExpected");
  197. QTest::addColumn<QString>("objectTypeExpected");
  198. QTest::addColumn<QString>("subjectExpected");
  199. QTest::addColumn<QString>("pathExpected");
  200. QTest::addColumn<QString>("fileNameExpected");
  201. QTest::addColumn<QString>("activityTypeExpected");
  202. QTest::addColumn<int>("activityIdExpected");
  203. QTest::addColumn<QString>("messageExpected");
  204. QTest::addColumn<QString>("objectNameExpected");
  205. QTest::addColumn<QString>("linkExpected");
  206. QTest::addColumn<QString>("datetimeExpected");
  207. QTest::addColumn<QString>("iconExpected");
  208. QTest::addColumn<QString>("subjectRichStringExpected");
  209. QTest::addColumn<QJsonArray>("subjectRichDataExpected");
  210. QTest::addColumn<QString>("previewUrlExpected");
  211. createFilesActivityJsonData(QStringLiteral("jpg"), QStringLiteral("image/jpg"));
  212. createFilesActivityJsonData(QStringLiteral("txt"), QStringLiteral("text/plain"));
  213. createFilesActivityJsonData(QStringLiteral("pdf"), QStringLiteral("application/pdf"));
  214. createCalendarActivityJsonData(account->displayName(), QStringLiteral("Event 1"), QStringLiteral("Calendar 1"));
  215. createCalendarActivityJsonData(account->displayName(), QStringLiteral("Event 2"), QStringLiteral("Calendar 2"));
  216. for (int i = 1; i <= events; i++) {
  217. createCalendarEventMergedActivityJsonData(account->displayName(), QStringLiteral("Event"), QStringLiteral("Calendar"), i);
  218. }
  219. }
  220. void testFromJson()
  221. {
  222. QFETCH(QJsonObject, activityJsonObject);
  223. QFETCH(QString, fileFormat);
  224. QFETCH(QString, mimeTypeExpected);
  225. QFETCH(QString, objectTypeExpected);
  226. QFETCH(QString, subjectExpected);
  227. QFETCH(QString, pathExpected);
  228. QFETCH(QString, fileNameExpected);
  229. QFETCH(QString, activityTypeExpected);
  230. QFETCH(int, activityIdExpected);
  231. QFETCH(QString, messageExpected);
  232. QFETCH(QString, objectNameExpected);
  233. QFETCH(QString, linkExpected);
  234. QFETCH(QString, datetimeExpected);
  235. QFETCH(QString, iconExpected);
  236. QFETCH(QString, subjectRichStringExpected);
  237. QFETCH(QJsonArray, subjectRichDataExpected);
  238. QFETCH(QString, previewUrlExpected);
  239. OCC::Activity activity = OCC::Activity::fromActivityJson(activityJsonObject, account);
  240. QCOMPARE(activity._type, OCC::Activity::ActivityType);
  241. QCOMPARE(activity._objectType, objectTypeExpected);
  242. QCOMPARE(activity._id, activityIdExpected);
  243. QCOMPARE(activity._fileAction, activityTypeExpected);
  244. QCOMPARE(activity._accName, account->displayName());
  245. QCOMPARE(activity._subject, subjectExpected);
  246. QCOMPARE(activity._message, messageExpected);
  247. QCOMPARE(activity._file, objectNameExpected);
  248. QCOMPARE(activity._dateTime, QDateTime::fromString(datetimeExpected, Qt::ISODate));
  249. QCOMPARE(activity._objectName, objectNameExpected);
  250. const auto richParams = activity._subjectRichParameters;
  251. if (objectTypeExpected != calendarC) {
  252. QCOMPARE(activity._link, linkExpected);
  253. QCOMPARE(richParams.count(), 1);
  254. QCOMPARE(activity._subjectDisplay, QStringLiteral("You created ").append(fileNameExpected));
  255. const auto previews = activity._previews;
  256. QCOMPARE(previews.count(), 1);
  257. auto icon = account->url().toString().append("/index.php/apps/theming/img/core/filetypes/%1.svg");
  258. const auto isMimeTypeIcon = true;
  259. if(fileFormat == "txt") {
  260. QCOMPARE(previews[0]._source, icon.arg("text"));
  261. QCOMPARE(previews[0]._isMimeTypeIcon, isMimeTypeIcon);
  262. } else if(fileFormat == "pdf") {
  263. QCOMPARE(previews[0]._source, icon.arg("application-pdf"));
  264. QCOMPARE(previews[0]._isMimeTypeIcon, isMimeTypeIcon);
  265. } else {
  266. QCOMPARE(previews[0]._source, previewUrlExpected);
  267. QCOMPARE(previews[0]._isMimeTypeIcon, !isMimeTypeIcon);
  268. }
  269. QCOMPARE(previews[0]._mimeType, mimeTypeExpected);
  270. } else {
  271. QCOMPARE(richParams.count(), 3);
  272. QCOMPARE(subjectRichDataExpected.count(), 2);
  273. QString eventName;
  274. QUrl eventLink;
  275. auto expectedParams = subjectRichDataExpected[1].toObject();
  276. for (auto i = expectedParams.begin(); i != expectedParams.end(); ++i) {
  277. if (i.key().startsWith(eventC)) {
  278. const auto expectedJsonObject = i.value().toObject();
  279. eventName = expectedJsonObject.value(nameC).toString();
  280. eventLink = expectedJsonObject.value(linkC).toString();
  281. break;
  282. }
  283. }
  284. QCOMPARE(activity._link, eventLink);
  285. QCOMPARE(activity._subjectDisplay, QStringLiteral("%1 updated event %2 in calendar %3").arg(account->displayName(),
  286. eventName,
  287. richParams[calendarC].value<OCC::Activity::RichSubjectParameter>().name));
  288. QCOMPARE(activity._icon, iconExpected);
  289. }
  290. }
  291. };
  292. QTEST_MAIN(TestActivityData)
  293. #include "testactivitydata.moc"