File indexing completed on 2025-01-19 04:46:59

0001 /*
0002  * SPDX-FileCopyrightText: 2016 Daniel Vrátil <dvratil@kde.org>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  *
0006  */
0007 
0008 #include "pimeventsplugintest.h"
0009 #include "../pimeventsplugin.h"
0010 #include "fakepimdatasource.h"
0011 #include "testdataparser.h"
0012 #include "testutils.h"
0013 
0014 #include <QSignalSpy>
0015 #include <QTest>
0016 
0017 Q_DECLARE_METATYPE(DateEventDataHash)
0018 Q_DECLARE_METATYPE(CalendarEvents::EventData)
0019 
0020 void PimEventsPluginTest::initTestCase()
0021 {
0022     qputenv("TZ", "Europe/Berlin");
0023     qRegisterMetaType<DateEventDataHash>("QMultiHash<QDate, CalendarEvents::EventData>");
0024     qRegisterMetaType<CalendarEvents::EventData>("CalendarEvents::EventData");
0025 }
0026 
0027 bool PimEventsPluginTest::compareEventDataHashes(const DateEventDataHash &actual, const DateEventDataHash &expected)
0028 {
0029     COMPARE(actual.size(), expected.size());
0030     for (const QDate &resultKey : actual.uniqueKeys()) {
0031         VERIFY(expected.contains(resultKey));
0032         auto resultValues = actual.values(resultKey);
0033         auto expectedValues = expected.values(resultKey);
0034         COMPARE(resultValues.size(), expectedValues.size());
0035         std::sort(resultValues.begin(), resultValues.end(), std::less<CalendarEvents::EventData>());
0036         std::sort(expectedValues.begin(), expectedValues.end(), std::less<CalendarEvents::EventData>());
0037         COMPARE(resultValues, expectedValues);
0038     }
0039     return true;
0040 }
0041 
0042 DateEventDataHash PimEventsPluginTest::populateCalendar(FakePimDataSource *source, bool uniqueEventData)
0043 {
0044     const QStringList allData = TestDataParser::allTestData();
0045     DateEventDataHash expectedData;
0046     for (const QString &data : allData) {
0047         TestDataParser parser(data, true);
0048         if (parser.rangeEnd() < QDate(2016, 5, 1) || parser.rangeStart() > QDate(2016, 5, 31)) {
0049             continue;
0050         }
0051         const KCalendarCore::Event::Ptr event = parser.incidence().dynamicCast<KCalendarCore::Event>();
0052         if (event) {
0053             source->setAkonadiIdForIncidence(event, parser.akonadiId());
0054             source->calendar()->addEvent(event);
0055             for (const CalendarEvents::EventData &dt : parser.eventData()) {
0056                 if (uniqueEventData) {
0057                     expectedData.insert(dt.startDateTime().date(), dt);
0058                 } else {
0059                     QDate d = dt.startDateTime().date();
0060                     while (d <= dt.endDateTime().date()) {
0061                         expectedData.insert(d, dt);
0062                         d = d.addDays(1);
0063                     }
0064                 }
0065             }
0066         }
0067     }
0068 
0069     return expectedData;
0070 }
0071 
0072 QList<CalendarEvents::EventData> PimEventsPluginTest::findEventData(const KCalendarCore::Event::Ptr &event, const DateEventDataHash &allData)
0073 {
0074     QList<CalendarEvents::EventData> data;
0075     for (auto it = allData.cbegin(), end = allData.cend(); it != end; ++it) {
0076         // This is a very naive check
0077         if (it->title() == event->summary() && it->description() == event->description() && it->isAllDay() == event->allDay()) {
0078             data.push_back((*it));
0079         }
0080     }
0081 
0082     return data;
0083 }
0084 
0085 void PimEventsPluginTest::testLoadEventsForDataRange()
0086 {
0087     FakePimDataSource source;
0088     const DateEventDataHash expectedData = populateCalendar(&source, false);
0089 
0090     PimEventsPlugin plugin(&source);
0091     QSignalSpy dataReadySpy(&plugin, &PimEventsPlugin::dataReady);
0092     QVERIFY(dataReadySpy.isValid());
0093 
0094     plugin.loadEventsForDateRange(QDate(2016, 5, 1), QDate(2016, 5, 31));
0095     QCOMPARE(dataReadySpy.size(), 1);
0096     const auto results = dataReadySpy.takeFirst().constFirst().value<DateEventDataHash>();
0097     QVERIFY(compareEventDataHashes(results, expectedData));
0098 
0099     plugin.loadEventsForDateRange(QDate(2016, 1, 1), QDate(2016, 1, 30));
0100     QCOMPARE(dataReadySpy.size(), 0);
0101 }
0102 
0103 void PimEventsPluginTest::testEventAdded()
0104 {
0105     const QStringList allData = TestDataParser::allTestData();
0106 
0107     FakePimDataSource source;
0108 
0109     PimEventsPlugin plugin(&source);
0110     QSignalSpy dataReadySpy(&plugin, &PimEventsPlugin::dataReady);
0111     QVERIFY(dataReadySpy.isValid());
0112 
0113     plugin.loadEventsForDateRange(QDate(2016, 5, 1), QDate(2016, 5, 31));
0114     QCOMPARE(dataReadySpy.size(), 0);
0115 
0116     for (const QString &data : allData) {
0117         TestDataParser parser(data, true);
0118         if (parser.rangeEnd() < QDate(2016, 5, 1) || parser.rangeStart() > QDate(2016, 5, 31)) {
0119             continue;
0120         }
0121         const KCalendarCore::Event::Ptr event = parser.incidence().dynamicCast<KCalendarCore::Event>();
0122         if (event) {
0123             source.setAkonadiIdForIncidence(event, parser.akonadiId());
0124             source.calendar()->addEvent(event);
0125             DateEventDataHash expectedData;
0126             for (const CalendarEvents::EventData &dt : parser.eventData()) {
0127                 QDate d = dt.startDateTime().date();
0128                 while (d <= dt.endDateTime().date()) {
0129                     expectedData.insert(d, dt);
0130                     d = d.addDays(1);
0131                 }
0132             }
0133 
0134             QCOMPARE(dataReadySpy.size(), 1);
0135             const auto results = dataReadySpy.takeFirst().first().value<DateEventDataHash>();
0136             QVERIFY(compareEventDataHashes(results, expectedData));
0137         }
0138     }
0139 }
0140 
0141 void PimEventsPluginTest::testEventModified()
0142 {
0143     FakePimDataSource source;
0144 
0145     PimEventsPlugin plugin(&source);
0146     QSignalSpy eventModifiedSpy(&plugin, &PimEventsPlugin::eventModified);
0147     QVERIFY(eventModifiedSpy.isValid());
0148 
0149     // Populate model
0150     const auto allData = populateCalendar(&source, true);
0151 
0152     // We don't care about the result of this, we just need to have mStart and
0153     // mEnd set
0154     plugin.loadEventsForDateRange(QDate(2016, 5, 1), QDate(2016, 5, 31));
0155 
0156     // Non-recurring event
0157     {
0158         QVERIFY(eventModifiedSpy.isEmpty());
0159         KCalendarCore::Event::Ptr event = source.calendar()->event(QStringLiteral("4d7fdd2c-2d3a-4ecf-8964-00eb92225209"));
0160         QVERIFY(event);
0161         const auto expectedData = findEventData(event, allData);
0162         QCOMPARE(expectedData.size(), 1);
0163         event->setSummary(QStringLiteral("TEST"));
0164 
0165         QVERIFY(source.calendar()->addEvent(event));
0166 
0167         QCOMPARE(eventModifiedSpy.size(), 1);
0168         const auto result = eventModifiedSpy.takeFirst().constFirst().value<CalendarEvents::EventData>();
0169         // TODO: Test for other property changes too?
0170         QCOMPARE(result.title(), event->summary());
0171         QCOMPARE(result.uid(), expectedData[0].uid());
0172     }
0173 
0174     // Recurring event
0175     {
0176         QVERIFY(eventModifiedSpy.isEmpty());
0177         KCalendarCore::Event::Ptr event = source.calendar()->event(QStringLiteral("69971015-fe9c-4800-a20e-d46bafa24e41"));
0178         QVERIFY(event);
0179         auto expectedData = findEventData(event, allData);
0180         event->setSummary(QStringLiteral("TEST2"));
0181         QVERIFY(source.calendar()->addEvent(event));
0182 
0183         QCOMPARE(eventModifiedSpy.size(), expectedData.size());
0184         while (!eventModifiedSpy.isEmpty()) {
0185             const auto args = eventModifiedSpy.takeFirst();
0186             const auto &resultData = args[0].value<CalendarEvents::EventData>();
0187             const auto expected = std::find_if(expectedData.begin(), expectedData.end(), [resultData](const CalendarEvents::EventData &e) {
0188                 return e.uid() == resultData.uid();
0189             });
0190             QVERIFY(expected != expectedData.end());
0191             expectedData.erase(expected);
0192             QCOMPARE(resultData.title(), QString::fromLatin1("TEST2"));
0193         }
0194         QVERIFY(expectedData.isEmpty());
0195     }
0196 }
0197 
0198 void PimEventsPluginTest::testEventRemoved()
0199 {
0200     FakePimDataSource source;
0201 
0202     PimEventsPlugin plugin(&source);
0203     QSignalSpy eventRemovedSpy(&plugin, &PimEventsPlugin::eventRemoved);
0204     QVERIFY(eventRemovedSpy.isValid());
0205 
0206     const auto allData = populateCalendar(&source, true);
0207 
0208     // We don't care about the result of this, we just need to have mStart and
0209     // mEnd set
0210     plugin.loadEventsForDateRange(QDate(2016, 5, 1), QDate(2016, 5, 31));
0211 
0212     // Non-recurring event
0213     {
0214         QVERIFY(eventRemovedSpy.isEmpty());
0215         const KCalendarCore::Event::Ptr event = source.calendar()->event(QStringLiteral("4d7fdd2c-2d3a-4ecf-8964-00eb92225209"));
0216         QVERIFY(event);
0217         const auto expectedData = findEventData(event, allData);
0218         QCOMPARE(expectedData.size(), 1);
0219 
0220         QVERIFY(source.calendar()->deleteEvent(event));
0221 
0222         QCOMPARE(eventRemovedSpy.size(), 1);
0223         const auto result = eventRemovedSpy.takeFirst().first().toString();
0224         QCOMPARE(result, expectedData[0].uid());
0225     }
0226 
0227     // Recurring event
0228     {
0229         QVERIFY(eventRemovedSpy.isEmpty());
0230         KCalendarCore::Event::Ptr event = source.calendar()->event(QStringLiteral("69971015-fe9c-4800-a20e-d46bafa24e41"));
0231         QVERIFY(event);
0232         auto expectedData = findEventData(event, allData);
0233 
0234         QVERIFY(source.calendar()->deleteEvent(event));
0235 
0236         QCOMPARE(eventRemovedSpy.size(), expectedData.size());
0237         while (!eventRemovedSpy.isEmpty()) {
0238             const QString resultUid = eventRemovedSpy.takeFirst().first().toString();
0239             const auto expected = std::find_if(expectedData.begin(), expectedData.end(), [resultUid](const CalendarEvents::EventData &e) {
0240                 return e.uid() == resultUid;
0241             });
0242             QVERIFY(expected != expectedData.end());
0243             expectedData.erase(expected);
0244         }
0245         QVERIFY(expectedData.isEmpty());
0246     }
0247 }
0248 
0249 QTEST_MAIN(PimEventsPluginTest)
0250 
0251 #include "moc_pimeventsplugintest.cpp"