1 /*
2  * Copyright (C) by Felix Weilbach <felix.weilbach@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 
15 #include "userstatusconnector.h"
16 #include "userstatusselectormodel.h"
17 
18 #include <QTest>
19 #include <QSignalSpy>
20 #include <QDateTime>
21 
22 #include <memory>
23 
24 class FakeUserStatusConnector : public OCC::UserStatusConnector
25 {
26 public:
fetchUserStatus()27     void fetchUserStatus() override
28     {
29         if (_couldNotFetchUserStatus) {
30             emit error(Error::CouldNotFetchUserStatus);
31             return;
32         } else if (_userStatusNotSupported) {
33             emit error(Error::UserStatusNotSupported);
34             return;
35         } else if (_emojisNotSupported) {
36             emit error(Error::EmojisNotSupported);
37             return;
38         }
39 
40         emit userStatusFetched(_userStatus);
41     }
42 
fetchPredefinedStatuses()43     void fetchPredefinedStatuses() override
44     {
45         if (_couldNotFetchPredefinedUserStatuses) {
46             emit error(Error::CouldNotFetchPredefinedUserStatuses);
47             return;
48         }
49         emit predefinedStatusesFetched(_predefinedStatuses);
50     }
51 
setUserStatus(const OCC::UserStatus & userStatus)52     void setUserStatus(const OCC::UserStatus &userStatus) override
53     {
54         if (_couldNotSetUserStatusMessage) {
55             emit error(Error::CouldNotSetUserStatus);
56             return;
57         }
58 
59         _userStatusSetByCallerOfSetUserStatus = userStatus;
60         emit UserStatusConnector::userStatusSet();
61     }
62 
clearMessage()63     void clearMessage() override
64     {
65         if (_couldNotClearUserStatusMessage) {
66             emit error(Error::CouldNotClearMessage);
67         } else {
68             _isMessageCleared = true;
69         }
70     }
71 
userStatus() const72     OCC::UserStatus userStatus() const override
73     {
74         return {}; // Not implemented
75     }
76 
setFakeUserStatus(const OCC::UserStatus & userStatus)77     void setFakeUserStatus(const OCC::UserStatus &userStatus)
78     {
79         _userStatus = userStatus;
80     }
81 
setFakePredefinedStatuses(const std::vector<OCC::UserStatus> & statuses)82     void setFakePredefinedStatuses(
83         const std::vector<OCC::UserStatus> &statuses)
84     {
85         _predefinedStatuses = statuses;
86     }
87 
userStatusSetByCallerOfSetUserStatus() const88     OCC::UserStatus userStatusSetByCallerOfSetUserStatus() const { return _userStatusSetByCallerOfSetUserStatus; }
89 
messageCleared() const90     bool messageCleared() const { return _isMessageCleared; }
91 
setErrorCouldNotFetchPredefinedUserStatuses(bool value)92     void setErrorCouldNotFetchPredefinedUserStatuses(bool value)
93     {
94         _couldNotFetchPredefinedUserStatuses = value;
95     }
96 
setErrorCouldNotFetchUserStatus(bool value)97     void setErrorCouldNotFetchUserStatus(bool value)
98     {
99         _couldNotFetchUserStatus = value;
100     }
101 
setErrorCouldNotSetUserStatusMessage(bool value)102     void setErrorCouldNotSetUserStatusMessage(bool value)
103     {
104         _couldNotSetUserStatusMessage = value;
105     }
106 
setErrorUserStatusNotSupported(bool value)107     void setErrorUserStatusNotSupported(bool value)
108     {
109         _userStatusNotSupported = value;
110     }
111 
setErrorEmojisNotSupported(bool value)112     void setErrorEmojisNotSupported(bool value)
113     {
114         _emojisNotSupported = value;
115     }
116 
setErrorCouldNotClearUserStatusMessage(bool value)117     void setErrorCouldNotClearUserStatusMessage(bool value)
118     {
119         _couldNotClearUserStatusMessage = value;
120     }
121 
122 private:
123     OCC::UserStatus _userStatusSetByCallerOfSetUserStatus;
124     OCC::UserStatus _userStatus;
125     std::vector<OCC::UserStatus> _predefinedStatuses;
126     bool _isMessageCleared = false;
127     bool _couldNotFetchPredefinedUserStatuses = false;
128     bool _couldNotFetchUserStatus = false;
129     bool _couldNotSetUserStatusMessage = false;
130     bool _userStatusNotSupported = false;
131     bool _emojisNotSupported = false;
132     bool _couldNotClearUserStatusMessage = false;
133 };
134 
135 class FakeDateTimeProvider : public OCC::DateTimeProvider
136 {
137 public:
setCurrentDateTime(const QDateTime & dateTime)138     void setCurrentDateTime(const QDateTime &dateTime) { _dateTime = dateTime; }
139 
currentDateTime() const140     QDateTime currentDateTime() const override { return _dateTime; }
141 
currentDate() const142     QDate currentDate() const override { return _dateTime.date(); }
143 
144 private:
145     QDateTime _dateTime;
146 };
147 
148 static std::vector<OCC::UserStatus>
createFakePredefinedStatuses(const QDateTime & currentTime)149 createFakePredefinedStatuses(const QDateTime &currentTime)
150 {
151     std::vector<OCC::UserStatus> statuses;
152 
153     const QString userStatusId("fake-id");
154     const QString userStatusMessage("Predefined status");
155     const QString userStatusIcon("��");
156     const OCC::UserStatus::OnlineStatus userStatusState(OCC::UserStatus::OnlineStatus::Online);
157     const bool userStatusMessagePredefined(true);
158     OCC::Optional<OCC::ClearAt> userStatusClearAt;
159     OCC::ClearAt clearAt;
160     clearAt._type = OCC::ClearAtType::Timestamp;
161     clearAt._timestamp = currentTime.addSecs(60 * 60).toTime_t();
162     userStatusClearAt = clearAt;
163 
164     statuses.emplace_back(userStatusId, userStatusMessage, userStatusIcon,
165         userStatusState, userStatusMessagePredefined, userStatusClearAt);
166 
167     return statuses;
168 }
169 
createDateTime(int year=2021,int month=7,int day=27,int hour=12,int minute=0,int second=0)170 static QDateTime createDateTime(int year = 2021, int month = 7, int day = 27,
171     int hour = 12, int minute = 0, int second = 0)
172 {
173     QDate fakeDate(year, month, day);
174     QTime fakeTime(hour, minute, second);
175     QDateTime fakeDateTime;
176 
177     fakeDateTime.setDate(fakeDate);
178     fakeDateTime.setTime(fakeTime);
179 
180     return fakeDateTime;
181 }
182 
183 class TestSetUserStatusDialog : public QObject
184 {
185     Q_OBJECT
186 
187 private slots:
testCtor_fetchStatusAndPredefinedStatuses()188     void testCtor_fetchStatusAndPredefinedStatuses()
189     {
190         const QDateTime currentDateTime(QDateTime::currentDateTime());
191 
192         const QString userStatusId("fake-id");
193         const QString userStatusMessage("Some status");
194         const QString userStatusIcon("❤");
195         const OCC::UserStatus::OnlineStatus userStatusState(OCC::UserStatus::OnlineStatus::DoNotDisturb);
196         const bool userStatusMessagePredefined(false);
197         OCC::Optional<OCC::ClearAt> userStatusClearAt;
198         {
199             OCC::ClearAt clearAt;
200             clearAt._type = OCC::ClearAtType::Timestamp;
201             clearAt._timestamp = currentDateTime.addDays(1).toTime_t();
202             userStatusClearAt = clearAt;
203         }
204 
205         const OCC::UserStatus userStatus(userStatusId, userStatusMessage,
206             userStatusIcon, userStatusState, userStatusMessagePredefined, userStatusClearAt);
207 
208         const auto fakePredefinedStatuses = createFakePredefinedStatuses(createDateTime());
209 
210         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
211         auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
212         fakeDateTimeProvider->setCurrentDateTime(currentDateTime);
213         fakeUserStatusJob->setFakeUserStatus(userStatus);
214         fakeUserStatusJob->setFakePredefinedStatuses(fakePredefinedStatuses);
215         OCC::UserStatusSelectorModel model(fakeUserStatusJob, std::move(fakeDateTimeProvider));
216 
217         // Was user status set correctly?
218         QCOMPARE(model.userStatusMessage(), userStatusMessage);
219         QCOMPARE(model.userStatusEmoji(), userStatusIcon);
220         QCOMPARE(model.onlineStatus(), userStatusState);
221         QCOMPARE(model.clearAt(), tr("1 day"));
222 
223         // Were predefined statuses fetched correctly?
224         const auto predefinedStatusesCount = model.predefinedStatusesCount();
225         QCOMPARE(predefinedStatusesCount, fakePredefinedStatuses.size());
226         for (int i = 0; i < predefinedStatusesCount; ++i) {
227             const auto predefinedStatus = model.predefinedStatus(i);
228             QCOMPARE(predefinedStatus.id(),
229                 fakePredefinedStatuses[i].id());
230             QCOMPARE(predefinedStatus.message(),
231                 fakePredefinedStatuses[i].message());
232             QCOMPARE(predefinedStatus.icon(),
233                 fakePredefinedStatuses[i].icon());
234             QCOMPARE(predefinedStatus.messagePredefined(),
235                 fakePredefinedStatuses[i].messagePredefined());
236         }
237     }
238 
testCtor_noStatusSet_showSensibleDefaults()239     void testCtor_noStatusSet_showSensibleDefaults()
240     {
241         OCC::UserStatusSelectorModel model(nullptr, nullptr);
242 
243         QCOMPARE(model.userStatusMessage(), "");
244         QCOMPARE(model.userStatusEmoji(), "��");
245         QCOMPARE(model.clearAt(), tr("Don't clear"));
246     }
247 
testCtor_fetchStatusButNoStatusSet_showSensibleDefaults()248     void testCtor_fetchStatusButNoStatusSet_showSensibleDefaults()
249     {
250         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
251         fakeUserStatusJob->setFakeUserStatus({ "", "", "",
252             OCC::UserStatus::OnlineStatus::Offline, false, {} });
253         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
254 
255         QCOMPARE(model.onlineStatus(), OCC::UserStatus::OnlineStatus::Online);
256         QCOMPARE(model.userStatusMessage(), "");
257         QCOMPARE(model.userStatusEmoji(), "��");
258         QCOMPARE(model.clearAt(), tr("Don't clear"));
259     }
260 
testSetOnlineStatus_emitOnlineStatusChanged()261     void testSetOnlineStatus_emitOnlineStatusChanged()
262     {
263         const OCC::UserStatus::OnlineStatus onlineStatus(OCC::UserStatus::OnlineStatus::Invisible);
264         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
265         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
266         QSignalSpy onlineStatusChangedSpy(&model,
267             &OCC::UserStatusSelectorModel::onlineStatusChanged);
268 
269         model.setOnlineStatus(onlineStatus);
270 
271         QCOMPARE(onlineStatusChangedSpy.count(), 1);
272     }
273 
testSetUserStatus_setCustomMessage_userStatusSetCorrect()274     void testSetUserStatus_setCustomMessage_userStatusSetCorrect()
275     {
276         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
277         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
278         QSignalSpy finishedSpy(&model, &OCC::UserStatusSelectorModel::finished);
279 
280         const QString userStatusMessage("Some status");
281         const QString userStatusIcon("❤");
282         const OCC::UserStatus::OnlineStatus userStatusState(OCC::UserStatus::OnlineStatus::Online);
283 
284         model.setOnlineStatus(userStatusState);
285         model.setUserStatusMessage(userStatusMessage);
286         model.setUserStatusEmoji(userStatusIcon);
287         model.setClearAt(1);
288 
289         model.setUserStatus();
290         QCOMPARE(finishedSpy.count(), 1);
291 
292         const auto userStatusSet = fakeUserStatusJob->userStatusSetByCallerOfSetUserStatus();
293         QCOMPARE(userStatusSet.icon(), userStatusIcon);
294         QCOMPARE(userStatusSet.message(), userStatusMessage);
295         QCOMPARE(userStatusSet.state(), userStatusState);
296         QCOMPARE(userStatusSet.messagePredefined(), false);
297         const auto clearAt = userStatusSet.clearAt();
298         QVERIFY(clearAt.isValid());
299         QCOMPARE(clearAt->_type, OCC::ClearAtType::Period);
300         QCOMPARE(clearAt->_period, 60 * 30);
301     }
302 
testSetUserStatusMessage_predefinedStatusWasSet_userStatusSetCorrect()303     void testSetUserStatusMessage_predefinedStatusWasSet_userStatusSetCorrect()
304     {
305         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
306         fakeUserStatusJob->setFakePredefinedStatuses(createFakePredefinedStatuses(createDateTime()));
307         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
308         model.setPredefinedStatus(0);
309         QSignalSpy finishedSpy(&model, &OCC::UserStatusSelectorModel::finished);
310 
311         const QString userStatusMessage("Some status");
312         const OCC::UserStatus::OnlineStatus userStatusState(OCC::UserStatus::OnlineStatus::Online);
313 
314         model.setOnlineStatus(userStatusState);
315         model.setUserStatusMessage(userStatusMessage);
316         model.setClearAt(1);
317 
318         model.setUserStatus();
319         QCOMPARE(finishedSpy.count(), 1);
320 
321         const auto userStatusSet = fakeUserStatusJob->userStatusSetByCallerOfSetUserStatus();
322         QCOMPARE(userStatusSet.message(), userStatusMessage);
323         QCOMPARE(userStatusSet.state(), userStatusState);
324         QCOMPARE(userStatusSet.messagePredefined(), false);
325         const auto clearAt = userStatusSet.clearAt();
326         QVERIFY(clearAt.isValid());
327         QCOMPARE(clearAt->_type, OCC::ClearAtType::Period);
328         QCOMPARE(clearAt->_period, 60 * 30);
329     }
330 
testSetUserStatusEmoji_predefinedStatusWasSet_userStatusSetCorrect()331     void testSetUserStatusEmoji_predefinedStatusWasSet_userStatusSetCorrect()
332     {
333         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
334         fakeUserStatusJob->setFakePredefinedStatuses(createFakePredefinedStatuses(createDateTime()));
335         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
336         model.setPredefinedStatus(0);
337         QSignalSpy finishedSpy(&model, &OCC::UserStatusSelectorModel::finished);
338 
339         const QString userStatusIcon("❤");
340         const OCC::UserStatus::OnlineStatus userStatusState(OCC::UserStatus::OnlineStatus::Online);
341 
342         model.setOnlineStatus(userStatusState);
343         model.setUserStatusEmoji(userStatusIcon);
344         model.setClearAt(1);
345 
346         model.setUserStatus();
347         QCOMPARE(finishedSpy.count(), 1);
348 
349         const auto userStatusSet = fakeUserStatusJob->userStatusSetByCallerOfSetUserStatus();
350         QCOMPARE(userStatusSet.icon(), userStatusIcon);
351         QCOMPARE(userStatusSet.state(), userStatusState);
352         QCOMPARE(userStatusSet.messagePredefined(), false);
353         const auto clearAt = userStatusSet.clearAt();
354         QVERIFY(clearAt.isValid());
355         QCOMPARE(clearAt->_type, OCC::ClearAtType::Period);
356         QCOMPARE(clearAt->_period, 60 * 30);
357     }
358 
testSetPredefinedStatus_emitUserStatusChangedAndSetUserStatus()359     void testSetPredefinedStatus_emitUserStatusChangedAndSetUserStatus()
360     {
361         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
362         auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
363         const auto currentTime = createDateTime();
364         fakeDateTimeProvider->setCurrentDateTime(currentTime);
365         const auto fakePredefinedStatuses = createFakePredefinedStatuses(currentTime);
366         fakeUserStatusJob->setFakePredefinedStatuses(fakePredefinedStatuses);
367         OCC::UserStatusSelectorModel model(std::move(fakeUserStatusJob),
368             std::move(fakeDateTimeProvider));
369 
370         QSignalSpy userStatusChangedSpy(&model,
371             &OCC::UserStatusSelectorModel::userStatusChanged);
372         QSignalSpy clearAtChangedSpy(&model,
373             &OCC::UserStatusSelectorModel::clearAtChanged);
374 
375         const auto fakePredefinedUserStatusIndex = 0;
376         model.setPredefinedStatus(fakePredefinedUserStatusIndex);
377 
378         QCOMPARE(userStatusChangedSpy.count(), 1);
379         QCOMPARE(clearAtChangedSpy.count(), 1);
380 
381         // Was user status set correctly?
382         const auto fakePredefinedUserStatus = fakePredefinedStatuses[fakePredefinedUserStatusIndex];
383         QCOMPARE(model.userStatusMessage(), fakePredefinedUserStatus.message());
384         QCOMPARE(model.userStatusEmoji(), fakePredefinedUserStatus.icon());
385         QCOMPARE(model.onlineStatus(), fakePredefinedUserStatus.state());
386         QCOMPARE(model.clearAt(), tr("1 hour"));
387     }
388 
testSetClear_setClearAtStage0_emitClearAtChangedAndClearAtSet()389     void testSetClear_setClearAtStage0_emitClearAtChangedAndClearAtSet()
390     {
391         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
392         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
393         QSignalSpy clearAtChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtChanged);
394 
395         const auto clearAtIndex = 0;
396         model.setClearAt(clearAtIndex);
397 
398         QCOMPARE(clearAtChangedSpy.count(), 1);
399         QCOMPARE(model.clearAt(), tr("Don't clear"));
400     }
401 
testSetClear_setClearAtStage1_emitClearAtChangedAndClearAtSet()402     void testSetClear_setClearAtStage1_emitClearAtChangedAndClearAtSet()
403     {
404         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
405         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
406         QSignalSpy clearAtChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtChanged);
407 
408         const auto clearAtIndex = 1;
409         model.setClearAt(clearAtIndex);
410 
411         QCOMPARE(clearAtChangedSpy.count(), 1);
412         QCOMPARE(model.clearAt(), tr("30 minutes"));
413     }
414 
testSetClear_setClearAtStage2_emitClearAtChangedAndClearAtSet()415     void testSetClear_setClearAtStage2_emitClearAtChangedAndClearAtSet()
416     {
417         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
418         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
419         QSignalSpy clearAtChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtChanged);
420 
421         const auto clearAtIndex = 2;
422         model.setClearAt(clearAtIndex);
423 
424         QCOMPARE(clearAtChangedSpy.count(), 1);
425         QCOMPARE(model.clearAt(), tr("1 hour"));
426     }
427 
testSetClear_setClearAtStage3_emitClearAtChangedAndClearAtSet()428     void testSetClear_setClearAtStage3_emitClearAtChangedAndClearAtSet()
429     {
430         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
431         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
432         QSignalSpy clearAtChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtChanged);
433 
434         const auto clearAtIndex = 3;
435         model.setClearAt(clearAtIndex);
436 
437         QCOMPARE(clearAtChangedSpy.count(), 1);
438         QCOMPARE(model.clearAt(), tr("4 hours"));
439     }
440 
testSetClear_setClearAtStage4_emitClearAtChangedAndClearAtSet()441     void testSetClear_setClearAtStage4_emitClearAtChangedAndClearAtSet()
442     {
443         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
444         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
445         QSignalSpy clearAtChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtChanged);
446 
447         const auto clearAtIndex = 4;
448         model.setClearAt(clearAtIndex);
449 
450         QCOMPARE(clearAtChangedSpy.count(), 1);
451         QCOMPARE(model.clearAt(), tr("Today"));
452     }
453 
testSetClear_setClearAtStage5_emitClearAtChangedAndClearAtSet()454     void testSetClear_setClearAtStage5_emitClearAtChangedAndClearAtSet()
455     {
456         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
457         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
458         QSignalSpy clearAtChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtChanged);
459 
460         const auto clearAtIndex = 5;
461         model.setClearAt(clearAtIndex);
462 
463         QCOMPARE(clearAtChangedSpy.count(), 1);
464         QCOMPARE(model.clearAt(), tr("This week"));
465     }
466 
testClearAtStages()467     void testClearAtStages()
468     {
469         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
470         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
471 
472         QCOMPARE(model.clearAt(), tr("Don't clear"));
473         const auto clearAtValues = model.clearAtValues();
474         QCOMPARE(clearAtValues.count(), 6);
475 
476         QCOMPARE(clearAtValues[0], tr("Don't clear"));
477         QCOMPARE(clearAtValues[1], tr("30 minutes"));
478         QCOMPARE(clearAtValues[2], tr("1 hour"));
479         QCOMPARE(clearAtValues[3], tr("4 hours"));
480         QCOMPARE(clearAtValues[4], tr("Today"));
481         QCOMPARE(clearAtValues[5], tr("This week"));
482     }
483 
testClearAt_clearAtTimestamp()484     void testClearAt_clearAtTimestamp()
485     {
486         const auto currentTime = createDateTime();
487         {
488             OCC::UserStatus userStatus;
489             OCC::ClearAt clearAt;
490             clearAt._type = OCC::ClearAtType::Timestamp;
491             clearAt._timestamp = currentTime.addSecs(30).toTime_t();
492             userStatus.setClearAt(clearAt);
493 
494             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
495             fakeDateTimeProvider->setCurrentDateTime(currentTime);
496 
497             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
498 
499             QCOMPARE(model.clearAt(), tr("Less than a minute"));
500         }
501 
502         {
503             OCC::UserStatus userStatus;
504             OCC::ClearAt clearAt;
505             clearAt._type = OCC::ClearAtType::Timestamp;
506             clearAt._timestamp = currentTime.addSecs(60).toTime_t();
507             userStatus.setClearAt(clearAt);
508 
509             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
510             fakeDateTimeProvider->setCurrentDateTime(currentTime);
511 
512             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
513 
514             QCOMPARE(model.clearAt(), tr("1 minute"));
515         }
516 
517         {
518             OCC::UserStatus userStatus;
519             OCC::ClearAt clearAt;
520             clearAt._type = OCC::ClearAtType::Timestamp;
521             clearAt._timestamp = currentTime.addSecs(60 * 30).toTime_t();
522             userStatus.setClearAt(clearAt);
523 
524             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
525             fakeDateTimeProvider->setCurrentDateTime(currentTime);
526 
527             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
528 
529             QCOMPARE(model.clearAt(), tr("30 minutes"));
530         }
531 
532         {
533             OCC::UserStatus userStatus;
534             OCC::ClearAt clearAt;
535             clearAt._type = OCC::ClearAtType::Timestamp;
536             clearAt._timestamp = currentTime.addSecs(60 * 60).toTime_t();
537             userStatus.setClearAt(clearAt);
538 
539             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
540             fakeDateTimeProvider->setCurrentDateTime(currentTime);
541 
542             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
543 
544             QCOMPARE(model.clearAt(), tr("1 hour"));
545         }
546 
547         {
548             OCC::UserStatus userStatus;
549             OCC::ClearAt clearAt;
550             clearAt._type = OCC::ClearAtType::Timestamp;
551             clearAt._timestamp = currentTime.addSecs(60 * 60 * 4).toTime_t();
552             userStatus.setClearAt(clearAt);
553 
554             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
555             fakeDateTimeProvider->setCurrentDateTime(currentTime);
556 
557             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
558 
559             QCOMPARE(model.clearAt(), tr("4 hours"));
560         }
561 
562         {
563             OCC::UserStatus userStatus;
564             OCC::ClearAt clearAt;
565             clearAt._type = OCC::ClearAtType::Timestamp;
566             clearAt._timestamp = currentTime.addDays(1).toTime_t();
567             userStatus.setClearAt(clearAt);
568 
569             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
570             fakeDateTimeProvider->setCurrentDateTime(currentTime);
571 
572             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
573 
574             QCOMPARE(model.clearAt(), tr("1 day"));
575         }
576 
577         {
578             OCC::UserStatus userStatus;
579             OCC::ClearAt clearAt;
580             clearAt._type = OCC::ClearAtType::Timestamp;
581             clearAt._timestamp = currentTime.addDays(7).toTime_t();
582             userStatus.setClearAt(clearAt);
583 
584             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
585             fakeDateTimeProvider->setCurrentDateTime(currentTime);
586 
587             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
588 
589             QCOMPARE(model.clearAt(), tr("7 days"));
590         }
591     }
592 
testClearAt_clearAtEndOf()593     void testClearAt_clearAtEndOf()
594     {
595         {
596             OCC::UserStatus userStatus;
597             OCC::ClearAt clearAt;
598             clearAt._type = OCC::ClearAtType::EndOf;
599             clearAt._endof = "day";
600             userStatus.setClearAt(clearAt);
601 
602             OCC::UserStatusSelectorModel model(userStatus);
603 
604             QCOMPARE(model.clearAt(), tr("Today"));
605         }
606 
607         {
608             OCC::UserStatus userStatus;
609             OCC::ClearAt clearAt;
610             clearAt._type = OCC::ClearAtType::EndOf;
611             clearAt._endof = "week";
612             userStatus.setClearAt(clearAt);
613 
614             OCC::UserStatusSelectorModel model(userStatus);
615 
616             QCOMPARE(model.clearAt(), tr("This week"));
617         }
618     }
619 
testClearAt_clearAtAfterPeriod()620     void testClearAt_clearAtAfterPeriod()
621     {
622         {
623             OCC::UserStatus userStatus;
624             OCC::ClearAt clearAt;
625             clearAt._type = OCC::ClearAtType::Period;
626             clearAt._period = 60 * 30;
627             userStatus.setClearAt(clearAt);
628 
629             OCC::UserStatusSelectorModel model(userStatus);
630 
631             QCOMPARE(model.clearAt(), tr("30 minutes"));
632         }
633 
634         {
635             OCC::UserStatus userStatus;
636             OCC::ClearAt clearAt;
637             clearAt._type = OCC::ClearAtType::Period;
638             clearAt._period = 60 * 60;
639             userStatus.setClearAt(clearAt);
640 
641             OCC::UserStatusSelectorModel model(userStatus);
642 
643             QCOMPARE(model.clearAt(), tr("1 hour"));
644         }
645     }
646 
testClearUserStatus()647     void testClearUserStatus()
648     {
649         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
650         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
651 
652         model.clearUserStatus();
653 
654         QVERIFY(fakeUserStatusJob->messageCleared());
655     }
656 
testError_couldNotFetchPredefinedStatuses_emitError()657     void testError_couldNotFetchPredefinedStatuses_emitError()
658     {
659         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
660         fakeUserStatusJob->setErrorCouldNotFetchPredefinedUserStatuses(true);
661         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
662 
663         QCOMPARE(model.errorMessage(),
664             tr("Could not fetch predefined statuses. Make sure you are connected to the server."));
665     }
666 
testError_couldNotFetchUserStatus_emitError()667     void testError_couldNotFetchUserStatus_emitError()
668     {
669         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
670         fakeUserStatusJob->setErrorCouldNotFetchUserStatus(true);
671         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
672 
673         QCOMPARE(model.errorMessage(),
674             tr("Could not fetch user status. Make sure you are connected to the server."));
675     }
676 
testError_userStatusNotSupported_emitError()677     void testError_userStatusNotSupported_emitError()
678     {
679         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
680         fakeUserStatusJob->setErrorUserStatusNotSupported(true);
681         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
682 
683         QCOMPARE(model.errorMessage(),
684             tr("User status feature is not supported. You will not be able to set your user status."));
685     }
686 
testError_couldSetUserStatus_emitError()687     void testError_couldSetUserStatus_emitError()
688     {
689         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
690         fakeUserStatusJob->setErrorCouldNotSetUserStatusMessage(true);
691         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
692         model.setUserStatus();
693 
694         QCOMPARE(model.errorMessage(),
695             tr("Could not set user status. Make sure you are connected to the server."));
696     }
697 
testError_emojisNotSupported_emitError()698     void testError_emojisNotSupported_emitError()
699     {
700         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
701         fakeUserStatusJob->setErrorEmojisNotSupported(true);
702         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
703 
704         QCOMPARE(model.errorMessage(),
705             tr("Emojis feature is not supported. Some user status functionality may not work."));
706     }
707 
testError_couldNotClearMessage_emitError()708     void testError_couldNotClearMessage_emitError()
709     {
710         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
711         fakeUserStatusJob->setErrorCouldNotClearUserStatusMessage(true);
712         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
713         model.clearUserStatus();
714 
715         QCOMPARE(model.errorMessage(),
716             tr("Could not clear user status message. Make sure you are connected to the server."));
717     }
718 
testError_setUserStatus_clearErrorMessage()719     void testError_setUserStatus_clearErrorMessage()
720     {
721         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
722         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
723 
724         fakeUserStatusJob->setErrorCouldNotSetUserStatusMessage(true);
725         model.setUserStatus();
726         QVERIFY(!model.errorMessage().isEmpty());
727         fakeUserStatusJob->setErrorCouldNotSetUserStatusMessage(false);
728         model.setUserStatus();
729         QVERIFY(model.errorMessage().isEmpty());
730     }
731 
testError_clearUserStatus_clearErrorMessage()732     void testError_clearUserStatus_clearErrorMessage()
733     {
734         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
735         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
736 
737         fakeUserStatusJob->setErrorCouldNotSetUserStatusMessage(true);
738         model.setUserStatus();
739         QVERIFY(!model.errorMessage().isEmpty());
740         fakeUserStatusJob->setErrorCouldNotSetUserStatusMessage(false);
741         model.clearUserStatus();
742         QVERIFY(model.errorMessage().isEmpty());
743     }
744 };
745 
746 QTEST_GUILESS_MAIN(TestSetUserStatusDialog)
747 #include "testsetuserstatusdialog.moc"
748