File indexing completed on 2024-04-28 05:11:29

0001 /*
0002   SPDX-FileCopyrightText: 2020, 2022 Glen Ditchfield <GJDitchfield@acm.org>
0003 
0004   SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include <QObject>
0008 #include <QTest>
0009 
0010 #include "combinedincidenceeditor.h"
0011 #include "incidencedatetime.h"
0012 #include "incidencedialog.h"
0013 #include "ui_dialogdesktop.h"
0014 
0015 using namespace IncidenceEditorNG;
0016 
0017 class IncidenceDateTimeTest : public QObject
0018 {
0019     Q_OBJECT
0020 
0021     IncidenceDialog *mDialog;
0022     QCheckBox *mAllDay;
0023     QCheckBox *mStartCheck;
0024     QCheckBox *mEndCheck;
0025     KDateComboBox *mStartDate;
0026     KTimeComboBox *mStartTime;
0027     KTimeZoneComboBox *mStartZone;
0028     KDateComboBox *mEndDate;
0029     KTimeComboBox *mEndTime;
0030     KTimeZoneComboBox *mEndZone;
0031     IncidenceEditor *mEditor;
0032 
0033 public:
0034     IncidenceDateTimeTest()
0035     {
0036         mDialog = new IncidenceDialog();
0037         mAllDay = mDialog->findChild<QCheckBox *>(QStringLiteral("mWholeDayCheck"));
0038         QVERIFY2(mAllDay, "Couldn't find the 'All Day' checkbox.");
0039         mStartCheck = mDialog->findChild<QCheckBox *>(QStringLiteral("mStartCheck"));
0040         QVERIFY2(mStartCheck, "Couldn't find the 'Start' checkbox.");
0041         mEndCheck = mDialog->findChild<QCheckBox *>(QStringLiteral("mEndCheck"));
0042         QVERIFY2(mEndCheck, "Couldn't find the 'End' checkbox.");
0043         mStartDate = mDialog->findChild<KDateComboBox *>(QStringLiteral("mStartDateEdit"));
0044         QVERIFY2(mStartDate, "Couldn't find start date field.");
0045         mStartTime = mDialog->findChild<KTimeComboBox *>(QStringLiteral("mStartTimeEdit"));
0046         QVERIFY2(mStartTime, "Couldn't find start time field.");
0047         mStartZone = mDialog->findChild<KTimeZoneComboBox *>(QStringLiteral("mTimeZoneComboStart"));
0048         QVERIFY2(mStartZone, "Couldn't find start time zone field.");
0049         mEndDate = mDialog->findChild<KDateComboBox *>(QStringLiteral("mEndDateEdit"));
0050         QVERIFY2(mEndDate, "Couldn't find end date field.");
0051         mEndTime = mDialog->findChild<KTimeComboBox *>(QStringLiteral("mEndTimeEdit"));
0052         QVERIFY2(mEndTime, "Couldn't find end time field.");
0053         mEndZone = mDialog->findChild<KTimeZoneComboBox *>(QStringLiteral("mTimeZoneComboEnd"));
0054         QVERIFY2(mEndZone, "Couldn't find end time zone field.");
0055         mEditor = mDialog->findChild<IncidenceEditor *>();
0056         QVERIFY2(mEditor, "Couldn't find the combined editor.");
0057     }
0058 
0059 private Q_SLOTS:
0060 
0061     void initTestCase()
0062     {
0063         qputenv("TZ", "Asia/Tokyo");
0064     }
0065 
0066     void testEventTimeValidation()
0067     {
0068         QLocale currentLocale;
0069         QLocale::setDefault(QLocale::c());
0070 
0071         const QDate date{2022, 04, 11};
0072         const QTime time{10, 11, 12};
0073         const QTimeZone zone{"Etc/UTC"};
0074         const QDateTime dt{date, time, zone};
0075 
0076         // Put the dialog into a known, valid state.
0077         KCalendarCore::Event::Ptr event(new KCalendarCore::Event);
0078         event->setSummary(QStringLiteral("e"));
0079         event->setDtStart(dt);
0080         event->setDtEnd(dt);
0081         event->setAllDay(false);
0082         Akonadi::Item item;
0083         item.setPayload<KCalendarCore::Event::Ptr>(event);
0084         mDialog->load(item);
0085         QVERIFY(mEditor->isValid());
0086 
0087         auto validDate = mStartDate->currentText();
0088         auto invalidDate = mStartDate->currentText().replace(QStringLiteral("11"), QStringLiteral("31"));
0089         mStartDate->setCurrentText(invalidDate);
0090         QVERIFY2(!mEditor->isValid(), qPrintable(QStringLiteral("Didn't detect invalid start date ").append(invalidDate)));
0091         mStartDate->setCurrentText(validDate);
0092         QVERIFY2(mEditor->isValid(), qPrintable(validDate.append(QStringLiteral(" considered invalid."))));
0093 
0094         auto validTime = mStartTime->currentText();
0095         auto invalidTime = mStartTime->currentText().replace(QStringLiteral("11"), QStringLiteral("61"));
0096         mStartTime->setCurrentText(invalidTime);
0097         QVERIFY2(!mEditor->isValid(), qPrintable(QStringLiteral("Didn't detect invalid start time ").append(invalidTime)));
0098         mStartTime->setCurrentText(validTime);
0099         QVERIFY2(mEditor->isValid(), qPrintable(validTime.append(QStringLiteral(" considered invalid."))));
0100 
0101         validDate = mEndDate->currentText();
0102         invalidDate = mEndDate->currentText().replace(QStringLiteral("11"), QStringLiteral("31"));
0103         mEndDate->setCurrentText(invalidDate);
0104         QVERIFY2(!mEditor->isValid(), qPrintable(QStringLiteral("Didn't detect invalid end date ").append(invalidDate)));
0105         mEndDate->setCurrentText(validDate);
0106         QVERIFY2(mEditor->isValid(), qPrintable(validDate.append(QStringLiteral(" considered invalid."))));
0107 
0108         validTime = mEndTime->currentText();
0109         invalidTime = mEndTime->currentText().replace(QStringLiteral("11"), QStringLiteral("61"));
0110         mEndTime->setCurrentText(invalidTime);
0111         QVERIFY2(!mEditor->isValid(), qPrintable(QStringLiteral("Didn't detect invalid end time ").append(invalidTime)));
0112         mEndTime->setCurrentText(validTime);
0113         QVERIFY2(mEditor->isValid(), qPrintable(validTime.append(QStringLiteral(" considered invalid."))));
0114     }
0115 
0116     void testEventTimeOrdering()
0117     {
0118         QLocale currentLocale;
0119         QLocale::setDefault(QLocale::c());
0120 
0121         const QDate date{2022, 04, 11};
0122         const QTime time{10, 11, 12};
0123         const QTimeZone zone{"Africa/Abidjan"}; // UTC+0.
0124         const QDateTime dt{date, time, zone};
0125 
0126         // Put the dialog into a known, valid state.
0127         KCalendarCore::Event::Ptr event(new KCalendarCore::Event);
0128         event->setSummary(QStringLiteral("e"));
0129         event->setDtStart(dt);
0130         event->setDtEnd(dt);
0131         event->setAllDay(false);
0132         Akonadi::Item item;
0133         item.setPayload<KCalendarCore::Event::Ptr>(event);
0134         mDialog->load(item);
0135         QVERIFY(mEditor->isValid());
0136 
0137         mEndDate->setDate(mStartDate->date().addDays(-1));
0138         mEndTime->setTime(mStartTime->time());
0139         QVERIFY2(!mEditor->isValid(), "Didn't detect end date < start date");
0140         mEndDate->setDate(mStartDate->date());
0141         QVERIFY(mEditor->isValid());
0142         mEndTime->setTime(mStartTime->time().addSecs(-60));
0143         QVERIFY2(!mEditor->isValid(), "Didn't detect end time < start time");
0144         mEndTime->setTime(mStartTime->time());
0145         QVERIFY(mEditor->isValid());
0146         mEndZone->selectTimeZone(QTimeZone("Africa/Addis_Ababa")); // UTC+3; causes 3-hour shift in effective end time.
0147         QVERIFY2(!mEditor->isValid(), "Didn't detect end time < start time in different time zone");
0148 
0149         QLocale::setDefault(currentLocale);
0150     }
0151 
0152     void testLoadingTimelessTodo()
0153     {
0154         KCalendarCore::Todo::Ptr todo{new KCalendarCore::Todo};
0155         todo->setDtStart(QDateTime());
0156         todo->setDtDue(QDateTime());
0157         todo->setAllDay(false);
0158         Akonadi::Item item;
0159         item.setPayload<KCalendarCore::Todo::Ptr>(todo);
0160         mDialog->load(item);
0161 
0162         QVERIFY(!mAllDay->isEnabled());
0163         QVERIFY(mAllDay->isVisible());
0164         QVERIFY(mStartCheck->isEnabled());
0165         QVERIFY(mStartCheck->isVisible());
0166         QCOMPARE(mStartCheck->checkState(), Qt::Unchecked);
0167         QVERIFY(mEndCheck->isEnabled());
0168         QVERIFY(mEndCheck->isVisible());
0169         QCOMPARE(mEndCheck->checkState(), Qt::Unchecked);
0170     }
0171 
0172     void testLoadingTimedTodo()
0173     {
0174         const QDate date{2022, 04, 01};
0175         const QTime time{00, 00, 00};
0176         const QTimeZone zone{"Africa/Abidjan"};
0177         const QDateTime dt{date, time, zone};
0178 
0179         KCalendarCore::Todo::Ptr todo{new KCalendarCore::Todo};
0180         todo->setDtStart(dt);
0181         todo->setDtDue(dt);
0182         todo->setAllDay(false);
0183         Akonadi::Item item;
0184         item.setPayload<KCalendarCore::Todo::Ptr>(todo);
0185         mDialog->load(item);
0186 
0187         QVERIFY(mAllDay->isEnabled());
0188         QVERIFY(mAllDay->isVisible());
0189         QCOMPARE(mAllDay->checkState(), Qt::Unchecked);
0190         QVERIFY(mStartCheck->isEnabled());
0191         QVERIFY(mStartCheck->isVisible());
0192         QCOMPARE(mStartCheck->checkState(), Qt::Checked);
0193         QCOMPARE(mStartDate->date(), date);
0194         QCOMPARE(mStartTime->time(), time);
0195         QCOMPARE(mStartZone->selectedTimeZone(), zone);
0196         QVERIFY(mEndCheck->isEnabled());
0197         QVERIFY(mEndCheck->isVisible());
0198         QCOMPARE(mEndCheck->checkState(), Qt::Checked);
0199         QCOMPARE(mEndDate->date(), date);
0200         QCOMPARE(mEndTime->time(), time);
0201         QCOMPARE(mEndZone->selectedTimeZone(), zone);
0202     }
0203 
0204     void testLoadingAlldayTodo()
0205     {
0206         const QDate date{2022, 04, 01};
0207         const QTime time{00, 00, 00};
0208         const QTimeZone zone{"Africa/Abidjan"};
0209         const QDateTime dt{date, time, zone};
0210 
0211         KCalendarCore::Todo::Ptr todo{new KCalendarCore::Todo};
0212         todo->setDtStart(dt);
0213         todo->setDtDue(dt);
0214         todo->setAllDay(true);
0215         Akonadi::Item item;
0216         item.setPayload<KCalendarCore::Todo::Ptr>(todo);
0217         mDialog->load(item);
0218 
0219         QCOMPARE(mAllDay->isEnabled(), true);
0220         QVERIFY(mAllDay->isVisible());
0221         QCOMPARE(mAllDay->checkState(), Qt::Checked);
0222         QVERIFY(mStartCheck->isEnabled());
0223         QVERIFY(mStartCheck->isVisible());
0224         QCOMPARE(mStartCheck->checkState(), Qt::Checked);
0225         QCOMPARE(mStartDate->date(), date);
0226         QVERIFY(!mStartTime->isEnabled());
0227         QVERIFY(!mStartZone->isVisible());
0228         QVERIFY(mEndCheck->isEnabled());
0229         QVERIFY(mEndCheck->isVisible());
0230         QCOMPARE(mEndCheck->checkState(), Qt::Checked);
0231         QVERIFY(!mEndTime->isEnabled());
0232         QVERIFY(!mEndZone->isVisible());
0233     }
0234 };
0235 
0236 QTEST_MAIN(IncidenceDateTimeTest)
0237 #include "incidencedatetimetest.moc"