Commit 527e5a76 authored by Claudio Cambra's avatar Claudio Cambra
Browse files

Add testing for IncidenceOccurrenceModel

This MR adds an autotest for the incidence occurrence model. it also simplifies this model, removing stuff we don't use and stuff that is provided automatically by QAbstractListModel.
parent 3ad8618e
Pipeline #126886 passed with stage
in 7 minutes and 27 seconds
......@@ -9,3 +9,4 @@ CMakeLists.txt.user
.clang-format
CMakeCache.txt
CMakeFiles
Testing/
......@@ -27,6 +27,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH})
include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(ECMAddTests)
include(ECMCoverageOption)
include(ECMQtDeclareLoggingCategory)
include(ECMSetupVersion)
include(ECMGenerateHeaders)
......@@ -43,7 +45,7 @@ ecm_setup_version(${PROJECT_VERSION}
)
################# Find dependencies #################
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Gui Qml QuickControls2 Svg Location DBus)
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Gui Qml QuickControls2 Svg Location DBus Test QuickTest)
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Kirigami2 DBusAddons I18n CalendarCore ConfigWidgets WindowSystem CoreAddons QQC2DesktopStyle Contacts ItemModels XmlGui Notifications IconThemes Service)
set_package_properties(KF5QQC2DesktopStyle PROPERTIES
TYPE RUNTIME
......@@ -71,6 +73,10 @@ add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x055800)
add_subdirectory(src)
add_subdirectory(kalendarac)
if (BUILD_TESTING)
add_subdirectory(autotests)
endif()
install(PROGRAMS org.kde.kalendar.desktop DESTINATION ${KDE_INSTALL_APPDIR})
install(FILES org.kde.kalendar.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR})
install(FILES org.kde.kalendar.svg DESTINATION ${KDE_INSTALL_FULL_ICONDIR}/hicolor/scalable/apps)
......
# SPDX-FileCopyrightText: (C) 2022 Claudio Cambra <claudio.cambra@gmail.com>
#
# SPDX-License-Identifier: BSD-2-Clause
enable_testing()
include_directories(${kalendar_CURRENT_BINARY_DIR})
include_directories(${kalendar_BINARY_DIR})
include_directories(${kalendar_BINARY_DIR}/src)
set(incidenceOccurrenceModelTest_SRCS
incidenceoccurrencemodeltest.cpp
../src/models/incidenceoccurrencemodel.cpp
)
ecm_qt_declare_logging_category(incidenceOccurrenceModelTest_SRCS HEADER kalendar_debug.h IDENTIFIER KALENDAR_LOG CATEGORY_NAME org.kde.kalendar DESCRIPTION "kalendar" EXPORT KALENDAR)
set (incidenceOccurrenceModelTest_LIBS
Qt::Test
Qt5::Core
KF5::ConfigCore
KF5::CalendarCore
KF5::AkonadiCore
KF5::AkonadiCalendar
)
add_akonadi_isolated_test_advanced(incidenceoccurrencemodeltest.cpp "${incidenceOccurrenceModelTest_SRCS}" "${incidenceOccurrenceModelTest_LIBS}")
// SPDX-FileCopyrightText: 2021 Claudio Cambra <claudio.cambra@gmail.com>
// SPDX-License-Identifier: LGPL-2.0-or-later
#include "../src/models/incidenceoccurrencemodel.h"
#include <Akonadi/Calendar/IncidenceChanger>
#include <KCalendarCore/Incidence>
#include <KCheckableProxyModel>
#include <KFormat>
#include <QAbstractItemModelTester>
#include <QSignalSpy>
#include <QTest>
#include <akonadi/qtest_akonadi.h>
class IncidenceOccurrenceModelTest : public QObject
{
Q_OBJECT
public:
IncidenceOccurrenceModelTest() = default;
~IncidenceOccurrenceModelTest() = default;
void checkAllItems(KCheckableProxyModel *model, const QModelIndex &parent = QModelIndex())
{
const int rowCount = model->rowCount(parent);
for (int row = 0; row < rowCount; ++row) {
QModelIndex index = model->index(row, 0, parent);
model->setData(index, Qt::Checked, Qt::CheckStateRole);
if (model->rowCount(index) > 0) {
checkAllItems(model, index);
}
}
}
signals:
void calendarLoaded();
private:
QScopedPointer<Akonadi::ETMCalendar> calendar;
IncidenceOccurrenceModel model;
QAbstractItemModelTester modelTester = QAbstractItemModelTester(&model);
QTimer loadedCheckTimer;
QDateTime now = QDate(2022, 01, 10).startOfDay();
private slots:
void initTestCase()
{
AkonadiTest::checkTestIsIsolated();
calendar.reset(new Akonadi::ETMCalendar);
QSignalSpy collectionsAdded(calendar.data(), &Akonadi::ETMCalendar::collectionsAdded);
QVERIFY(collectionsAdded.wait(10000));
loadedCheckTimer.setInterval(300);
loadedCheckTimer.setSingleShot(true);
connect(&loadedCheckTimer, &QTimer::timeout, this, [&]() {
if (calendar->isLoaded()) {
Q_EMIT calendarLoaded();
} else {
loadedCheckTimer.start();
}
});
QSignalSpy loaded(this, &IncidenceOccurrenceModelTest::calendarLoaded);
loaded.wait(10000);
checkAllItems(calendar->checkableProxyModel());
}
void testAddCalendar()
{
QVERIFY(calendar->isLoaded());
QVERIFY(calendar->items().count() > 0);
QSignalSpy fetchFinished(&model, &QAbstractItemModel::modelReset);
model.setStart(now.date());
QCOMPARE(model.start(), now.date());
model.setLength(7);
QCOMPARE(model.length(), 7);
model.setCalendar(calendar.data());
QCOMPARE(model.calendar()->id(), calendar->id());
fetchFinished.wait(10000);
// Our test calendar file has an event that recurs every day of the week.
// Since we are checking for 7 days, we should have an instance of this event
// 7 times.
QCOMPARE(model.rowCount(), 7);
}
void testData()
{
// Check everything is still there from the previous test
QCOMPARE(model.rowCount(), 7);
// Test that the data function gives us the event info we have in our calendar file
const auto index = model.index(0, 0);
QCOMPARE(index.data(IncidenceOccurrenceModel::Summary).toString(), QStringLiteral("Test event"));
QCOMPARE(index.data(IncidenceOccurrenceModel::Description).toString(), QStringLiteral("Big testing description"));
QCOMPARE(index.data(IncidenceOccurrenceModel::Location).toString(), QStringLiteral("Testing land"));
// It's an all day event
QDateTime eventStartTimeToday(now.date().startOfDay());
QCOMPARE(index.data(IncidenceOccurrenceModel::StartTime).toDateTime().toMSecsSinceEpoch(), eventStartTimeToday.toMSecsSinceEpoch());
QCOMPARE(index.data(IncidenceOccurrenceModel::EndTime).toDateTime().toMSecsSinceEpoch(), eventStartTimeToday.addDays(1).toMSecsSinceEpoch());
const auto duration = index.data(IncidenceOccurrenceModel::Duration).value<KCalendarCore::Duration>();
QCOMPARE(duration.asDays(), 1);
KFormat format;
QCOMPARE(index.data(IncidenceOccurrenceModel::DurationString).toString(), format.formatSpelloutDuration(duration.asSeconds() * 1000));
QVERIFY(index.data(IncidenceOccurrenceModel::Recurs).toBool());
QVERIFY(index.data(IncidenceOccurrenceModel::HasReminders).toBool());
QCOMPARE(index.data(IncidenceOccurrenceModel::Priority).toInt(), 0);
QVERIFY(index.data(IncidenceOccurrenceModel::AllDay).toBool());
// CalendarManager generates the colors for different collections so let's skip that check, since it will give invalid
QVERIFY(index.data(IncidenceOccurrenceModel::CollectionId).canConvert<qlonglong>());
QVERIFY(!index.data(IncidenceOccurrenceModel::TodoCompleted).toBool()); // An event should always return false for this
QVERIFY(!index.data(IncidenceOccurrenceModel::IsOverdue).toBool());
QVERIFY(!index.data(IncidenceOccurrenceModel::IsReadOnly).toBool());
QVERIFY(!index.data(IncidenceOccurrenceModel::IncidenceId).toString().isNull());
QCOMPARE(index.data(IncidenceOccurrenceModel::IncidenceType).toInt(), KCalendarCore::Incidence::TypeEvent);
QCOMPARE(index.data(IncidenceOccurrenceModel::IncidenceTypeStr).toString(), QStringLiteral("Event"));
QVERIFY(index.data(IncidenceOccurrenceModel::IncidencePtr).canConvert<KCalendarCore::Incidence::Ptr>());
QVERIFY(index.data(IncidenceOccurrenceModel::IncidenceOccurrence).canConvert<IncidenceOccurrenceModel::Occurrence>());
}
void testNewIncidenceAdded()
{
// Check everything is still there from the previous test
QCOMPARE(model.rowCount(), 7);
const auto collectionId = model.index(0, 0).data(IncidenceOccurrenceModel::CollectionId).toLongLong();
const auto collection = calendar->collection(collectionId);
QVERIFY(collection.isValid());
KCalendarCore::Todo::Ptr todo(new KCalendarCore::Todo);
todo->setSummary(QStringLiteral("Test todo"));
todo->setCompleted(true);
todo->setDtStart(now.addDays(1));
todo->setDtDue(now.addDays(1));
todo->setPriority(1);
todo->setCategories(QStringLiteral("Tag 2"));
QSignalSpy createFinished(calendar->incidenceChanger(), &Akonadi::IncidenceChanger::createFinished);
QVERIFY(calendar->incidenceChanger()->createIncidence(todo, collection) != -1);
QVERIFY(createFinished.wait(5000));
QSignalSpy loaded(this, &IncidenceOccurrenceModelTest::calendarLoaded);
loadedCheckTimer.start();
loaded.wait(10000);
QCOMPARE(model.rowCount(), 8);
}
void testTodoData()
{
QCOMPARE(model.rowCount(), 8);
QModelIndex todoIndex;
for (int i = 0; i < model.rowCount(); ++i) {
const auto index = model.index(i, 0);
if (index.data(IncidenceOccurrenceModel::IncidenceType).toInt() == KCalendarCore::Incidence::TypeTodo) {
todoIndex = index;
}
}
QVERIFY(todoIndex.data(IncidenceOccurrenceModel::TodoCompleted).toBool());
bool shouldBeOverDue = todoIndex.data(IncidenceOccurrenceModel::EndTime).toDateTime() > QDateTime::currentDateTime();
QCOMPARE(todoIndex.data(IncidenceOccurrenceModel::IsOverdue).toBool(), shouldBeOverDue);
QCOMPARE(todoIndex.data(IncidenceOccurrenceModel::Priority).toInt(), 1);
}
void testFilter()
{
QVariantMap filter;
filter[QStringLiteral("tags")] = QStringList(QStringLiteral("Tag 2"));
QSignalSpy fetchFinished(&model, &QAbstractItemModel::modelReset);
model.setFilter(filter);
QCOMPARE(model.filter(), filter);
fetchFinished.wait(10000);
QCOMPARE(model.rowCount(), 1);
model.setFilter({});
fetchFinished.wait(10000);
QCOMPARE(model.rowCount(), 8);
}
};
QTEST_MAIN(IncidenceOccurrenceModelTest)
#include "incidenceoccurrencemodeltest.moc"
<config>
<!--
SPDX-FileCopyrightText: 2021 Claudio Cambra <claudio.cambra@gmail.com>
SPDX-License-Identifier: CC0-1.0
-->
<datahome>xdglocal</datahome>
<agent synchronize="true">akonadi_ical_resource</agent>
<envvar name="AKONADI_DISABLE_AGENT_AUTOSTART">true</envvar>
</config>
[ProcessedDefaults]
defaultaddressbook=done
defaultcalendar=done
\ No newline at end of file
# SPDX-FileCopyrightText: 2021 Claudio Cambra <claudio.cambra@gmail.com>
# SPDX-License-Identifier: CC0-1.0
[General]
Path[$e]=$XDG_DATA_HOME/std0.ics
# SPDX-FileCopyrightText: 2021 Claudio Cambra <claudio.cambra@gmail.com>
# SPDX-License-Identifier: CC0-1.0
[Defaults]
Profile=Default
[PROFILE_Default]
EmailAddress=unittests@dev.nul
FullName=Unit Test User
Organization=KDE
ReplyAddr=
ServerType=
# SPDX-FileCopyrightText: 2021 Claudio Cambra <claudio.cambra@gmail.com>
# SPDX-License-Identifier: CC0-1.0
[$Version]
update_info=kmail.upd:3.3-move-identities-to-own-file,kmail.upd:3.3-aegypten-emailidentities-split-sign-encr-keys
[General]
Default Identity=1319040445
[Identity #0]
Dictionary=English (United States of America)
Email Address=unittests@dev.nul
Email Aliases= alias1@kde.org,alias2@kde.org
Identity=UnitTestUser
Image Location=
Inline Signature=
Name=Unit Test User
Organization=KDE
Preferred Crypto Message Format=auto
Signature Type=disabled
X-FaceEnabled=false
uoid=1319040445
[Identity #1]
Dictionary=English (United States of America)
Email Address=identity2@kde.org
Email Aliases=alias1@kde.org,alias2@kde.org
Identity=UnitTestUser
Image Location=
Inline Signature=
Name=Unit Test User ID2
Organization=KDE
Preferred Crypto Message Format=auto
Signature Type=disabled
X-FaceEnabled=false
uoid=1319040446
# SPDX-FileCopyrightText: 2021 Claudio Cambra <claudio.cambra@gmail.com>
# SPDX-License-Identifier: CC0-1.0
[$Version]
update_info=mailtransports.upd:initial-kmail-migration,mailtransports.upd:initial-knode-migration
[General]
default-transport=69372773
[Transport 69372773]
host=akonadi_mailtransport_dummy_resource_0
id=69372773
name=dummymailtransport
type=Akonadi
# SPDX-FileCopyrightText: 2021 Claudio Cambra <claudio.cambra@gmail.com>
# SPDX-License-Identifier: CC0-1.0
BEGIN:VCALENDAR
PRODID:-//K Desktop Environment//NONSGML libkcal 4.3//EN
VERSION:2.0
X-KDE-ICAL-IMPLEMENTATION-VERSION:1.0
BEGIN:VEVENT
DTSTAMP:20220116T150158Z
CREATED:20220115T134647Z
UID:0729311a-d9ad-40b5-a836-b4cc64c96727
SEQUENCE:9
LAST-MODIFIED:20220116T150158Z
DESCRIPTION:Big testing description
SUMMARY:Test event
LOCATION:Testing land
CATEGORIES:Tag 1
RRULE:FREQ=DAILY
DTSTART;VALUE=DATE:20140101
DTEND;VALUE=DATE:20140103
TRANSP:OPAQUE
BEGIN:VALARM
DESCRIPTION:
ACTION:DISPLAY
TRIGGER:-PT15M
X-KDE-KCALCORE-ENABLED:TRUE
END:VALARM
END:VEVENT
END:VCALENDAR
# SPDX-FileCopyrightText: 2021 Claudio Cambra <claudio.cambra@gmail.com>
# SPDX-License-Identifier: CC0-1.0
......@@ -3,57 +3,62 @@
# SPDX-License-Identifier: BSD-2-Clause
add_executable(kalendar)
target_sources(kalendar PRIVATE
set(kalendar_SRCS
about.cpp
about.h
actionsmodel.cpp
actionsmodel.h
models/actionsmodel.cpp
models/actionsmodel.h
agentconfiguration.cpp
agentconfiguration.h
attachmentsmodel.cpp
attachmentsmodel.h
attendeesmodel.cpp
attendeesmodel.h
models/attachmentsmodel.cpp
models/attachmentsmodel.h
models/attendeesmodel.cpp
models/attendeesmodel.h
calendarmanager.cpp
calendarmanager.h
commandbarfiltermodel.cpp
commandbarfiltermodel.h
models/commandbarfiltermodel.cpp
models/commandbarfiltermodel.h
contactsmanager.cpp
contactsmanager.h
extratodomodel.cpp
extratodomodel.h
hourlyincidencemodel.cpp
hourlyincidencemodel.h
incidenceoccurrencemodel.cpp
incidenceoccurrencemodel.h
models/extratodomodel.cpp
models/extratodomodel.h
models/hourlyincidencemodel.cpp
models/hourlyincidencemodel.h
models/incidenceoccurrencemodel.cpp
models/incidenceoccurrencemodel.h
incidencewrapper.cpp
incidencewrapper.h
infinitecalendarviewmodel.cpp
infinitecalendarviewmodel.h
itemtagsmodel.cpp
itemtagsmodel.h
models/infinitecalendarviewmodel.cpp
models/infinitecalendarviewmodel.h
models/itemtagsmodel.cpp
models/itemtagsmodel.h
kalendarapplication.cpp
kalendarapplication.h
main.cpp
monthmodel.cpp
monthmodel.h
multidayincidencemodel.cpp
multidayincidencemodel.h
recurrenceexceptionsmodel.cpp
recurrenceexceptionsmodel.h
remindersmodel.cpp
remindersmodel.h
models/monthmodel.cpp
models/monthmodel.h
models/multidayincidencemodel.cpp
models/multidayincidencemodel.h
models/recurrenceexceptionsmodel.cpp
models/recurrenceexceptionsmodel.h
models/remindersmodel.cpp
models/remindersmodel.h
tagmanager.cpp
tagmanager.h
timezonelistmodel.cpp
timezonelistmodel.h
todosortfilterproxymodel.cpp
todosortfilterproxymodel.h
resources.qrc)
models/timezonelistmodel.cpp
models/timezonelistmodel.h
models/todosortfilterproxymodel.cpp
models/todosortfilterproxymodel.h
resources.qrc
)
target_sources(kalendar PRIVATE
${kalendar_SRCS})
ecm_qt_declare_logging_category(kalendar HEADER kalendar_debug.h IDENTIFIER KALENDAR_LOG CATEGORY_NAME org.kde.kalendar DESCRIPTION "kalendar" EXPORT KALENDAR)
target_link_libraries(kalendar
set(kalendar_LIBS
Qt5::Core
Qt5::Gui
Qt5::Qml
......@@ -67,6 +72,7 @@ target_link_libraries(kalendar
KF5::DBusAddons
KF5::CalendarCore
KF5::AkonadiCore
KF5::AkonadiCalendar
KF5::AkonadiContact
KF5::AkonadiAgentBase
KF5::AkonadiXml
......@@ -78,13 +84,15 @@ target_link_libraries(kalendar
KF5::ItemModels
KF5::XmlGui
KF5::EventViews
)
target_link_libraries(kalendar
${kalendar_LIBS}
)
if (COMPILE_WITH_UNITY_CMAKE_SUPPORT)
set_target_properties(kalendar PROPERTIES UNITY_BUILD ON)
endif()
kconfig_add_kcfg_files(kalendar GENERATE_MOC kalendarconfig.kcfgc)
install(TARGETS kalendar ${KF5_INSTALL_TARGETS_DEFAULT_ARGS})
......@@ -16,7 +16,7 @@
#include <KConfigWatcher>
#include <KDescendantsProxyModel>
#include <incidencewrapper.h>
#include <todosortfilterproxymodel.h>
#include <models/todosortfilterproxymodel.h>
namespace Akonadi
{
......
......@@ -14,10 +14,10 @@
#include <Akonadi/ItemFetchJob>
#include <Akonadi/ItemFetchScope>
#include <Akonadi/ItemMonitor>
#include "attachmentsmodel.h"
#include "attendeesmodel.h"
#include "recurrenceexceptionsmodel.h"
#include "remindersmodel.h"
#include "models/attachmentsmodel.h"
#include "models/attendeesmodel.h"
#include "models/recurrenceexceptionsmodel.h"
#include "models/remindersmodel.h"
/**
* This class is a wrapper for a KCalendarCore::Incidence::Ptr object.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment