File indexing completed on 2025-01-05 05:00:01
0001 /* 0002 * SPDX-FileCopyrightText: 2015 Theo Vaucher <theo.vaucher@gmail.com> 0003 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 0006 0007 #include <testlib/qtest_zanshin.h> 0008 0009 #include <memory> 0010 0011 #include <QMimeData> 0012 0013 #include <testlib/fakejob.h> 0014 0015 #include "utils/datetime.h" 0016 #include "utils/mockobject.h" 0017 0018 #include "domain/taskqueries.h" 0019 #include "domain/taskrepository.h" 0020 #include "presentation/workdaypagemodel.h" 0021 #include "presentation/querytreemodelbase.h" 0022 0023 using namespace mockitopp; 0024 using namespace mockitopp::matcher; 0025 0026 class WorkdayPageModelTest : public QObject 0027 { 0028 Q_OBJECT 0029 private slots: 0030 void shouldListWorkdayInCentralListModel() 0031 { 0032 // GIVEN 0033 0034 const auto today = Utils::DateTime::currentDate(); 0035 0036 // Three tasks 0037 auto task1 = Domain::Task::Ptr::create(); 0038 task1->setTitle(QStringLiteral("task1")); 0039 task1->setStartDate(today.addDays(-10)); 0040 task1->setDueDate(today); 0041 auto task2 = Domain::Task::Ptr::create(); 0042 task2->setTitle(QStringLiteral("task2")); 0043 task2->setStartDate(today); 0044 task2->setDueDate(today.addDays(10)); 0045 auto task3 = Domain::Task::Ptr::create(); 0046 task3->setTitle(QStringLiteral("task3")); 0047 task3->setStartDate(today.addYears(-4)); 0048 task3->setDueDate(today.addYears(-3)); 0049 auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); 0050 auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider); 0051 taskProvider->append(task1); 0052 taskProvider->append(task2); 0053 taskProvider->append(task3); 0054 0055 // Two tasks under the task1 0056 auto childTask11 = Domain::Task::Ptr::create(); 0057 childTask11->setTitle(QStringLiteral("childTask11")); 0058 auto childTask12 = Domain::Task::Ptr::create(); 0059 childTask12->setTitle(QStringLiteral("childTask12")); 0060 childTask12->setStartDate(today); 0061 childTask12->setDueDate(today); 0062 auto childTaskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); 0063 auto childTaskResult = Domain::QueryResult<Domain::Task::Ptr>::create(childTaskProvider); 0064 taskProvider->append(childTask12); 0065 childTaskProvider->append(childTask11); 0066 childTaskProvider->append(childTask12); 0067 0068 // One project 0069 auto project = Domain::Project::Ptr::create(); 0070 project->setName("KDE"); 0071 auto projectProvider = Domain::QueryResultProvider<Domain::Project::Ptr>::Ptr::create(); 0072 auto projectResult = Domain::QueryResult<Domain::Project::Ptr>::create(projectProvider); 0073 projectProvider->append(project); 0074 0075 auto inboxProvider = Domain::QueryResultProvider<Domain::Project::Ptr>::Ptr::create(); 0076 auto inboxResult = Domain::QueryResult<Domain::Project::Ptr>::create(inboxProvider); 0077 0078 Utils::MockObject<Domain::TaskQueries> taskQueriesMock; 0079 taskQueriesMock(&Domain::TaskQueries::findWorkdayTopLevel).when().thenReturn(taskResult); 0080 taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(childTaskResult); 0081 taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); 0082 taskQueriesMock(&Domain::TaskQueries::findChildren).when(task3).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); 0083 taskQueriesMock(&Domain::TaskQueries::findChildren).when(childTask11).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); 0084 taskQueriesMock(&Domain::TaskQueries::findChildren).when(childTask12).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); 0085 0086 taskQueriesMock(&Domain::TaskQueries::findProject).when(task1).thenReturn(inboxResult); 0087 taskQueriesMock(&Domain::TaskQueries::findProject).when(task2).thenReturn(projectResult); 0088 taskQueriesMock(&Domain::TaskQueries::findProject).when(task3).thenReturn(inboxResult); 0089 taskQueriesMock(&Domain::TaskQueries::findProject).when(childTask11).thenReturn(inboxResult); 0090 taskQueriesMock(&Domain::TaskQueries::findProject).when(childTask12).thenReturn(inboxResult); 0091 0092 Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; 0093 0094 Presentation::WorkdayPageModel workday(taskQueriesMock.getInstance(), 0095 taskRepositoryMock.getInstance()); 0096 0097 // WHEN 0098 QAbstractItemModel *model = workday.centralListModel(); 0099 0100 // THEN 0101 const QModelIndex task1Index = model->index(0, 0); 0102 const QModelIndex task2Index = model->index(1, 0); 0103 const QModelIndex task3Index = model->index(2, 0); 0104 const QModelIndex taskChildTask12Index = model->index(3, 0); 0105 0106 const QModelIndex childTask11Index = model->index(0, 0, task1Index); 0107 const QModelIndex childTask12Index = model->index(1, 0, task1Index); 0108 0109 QCOMPARE(model->rowCount(), 4); 0110 QCOMPARE(model->rowCount(task1Index), 2); 0111 QCOMPARE(model->rowCount(task2Index), 0); 0112 QCOMPARE(model->rowCount(task3Index), 0); 0113 QCOMPARE(model->rowCount(taskChildTask12Index), 0); 0114 0115 QVERIFY(childTask11Index.isValid()); 0116 QVERIFY(childTask12Index.isValid()); 0117 QCOMPARE(model->rowCount(childTask11Index), 0); 0118 QCOMPARE(model->rowCount(childTask12Index), 0); 0119 0120 const Qt::ItemFlags defaultFlags = Qt::ItemIsSelectable 0121 | Qt::ItemIsEnabled 0122 | Qt::ItemIsEditable 0123 | Qt::ItemIsDragEnabled; 0124 QCOMPARE(model->flags(task1Index), defaultFlags | Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled); 0125 QCOMPARE(model->flags(childTask11Index), defaultFlags | Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled); 0126 QCOMPARE(model->flags(childTask12Index), defaultFlags | Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled); 0127 QCOMPARE(model->flags(task2Index), defaultFlags | Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled); 0128 QCOMPARE(model->flags(task3Index), defaultFlags | Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled); 0129 QCOMPARE(model->flags(taskChildTask12Index), defaultFlags | Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled); 0130 0131 QCOMPARE(model->data(task1Index).toString(), task1->title()); 0132 QCOMPARE(model->data(childTask11Index).toString(), childTask11->title()); 0133 QCOMPARE(model->data(childTask12Index).toString(), childTask12->title()); 0134 QCOMPARE(model->data(task2Index).toString(), task2->title()); 0135 QCOMPARE(model->data(task3Index).toString(), task3->title()); 0136 QCOMPARE(model->data(taskChildTask12Index).toString(), childTask12->title()); 0137 0138 QCOMPARE(model->data(task1Index, Qt::EditRole).toString(), task1->title()); 0139 QCOMPARE(model->data(childTask11Index, Qt::EditRole).toString(), childTask11->title()); 0140 QCOMPARE(model->data(childTask12Index, Qt::EditRole).toString(), childTask12->title()); 0141 QCOMPARE(model->data(task2Index, Qt::EditRole).toString(), task2->title()); 0142 QCOMPARE(model->data(task3Index, Qt::EditRole).toString(), task3->title()); 0143 QCOMPARE(model->data(taskChildTask12Index, Qt::EditRole).toString(), childTask12->title()); 0144 0145 QVERIFY(model->data(task1Index, Qt::CheckStateRole).isValid()); 0146 QVERIFY(model->data(childTask11Index, Qt::CheckStateRole).isValid()); 0147 QVERIFY(model->data(childTask12Index, Qt::CheckStateRole).isValid()); 0148 QVERIFY(model->data(task2Index, Qt::CheckStateRole).isValid()); 0149 QVERIFY(model->data(task3Index, Qt::CheckStateRole).isValid()); 0150 QVERIFY(model->data(taskChildTask12Index, Qt::CheckStateRole).isValid()); 0151 0152 QCOMPARE(model->data(task1Index, Qt::CheckStateRole).toBool(), task1->isDone()); 0153 QCOMPARE(model->data(childTask11Index, Qt::CheckStateRole).toBool(), childTask11->isDone()); 0154 QCOMPARE(model->data(childTask12Index, Qt::CheckStateRole).toBool(), childTask12->isDone()); 0155 QCOMPARE(model->data(task2Index, Qt::CheckStateRole).toBool(), task2->isDone()); 0156 QCOMPARE(model->data(task3Index, Qt::CheckStateRole).toBool(), task3->isDone()); 0157 QCOMPARE(model->data(taskChildTask12Index, Qt::CheckStateRole).toBool(), childTask12->isDone()); 0158 0159 QVERIFY(model->data(task1Index, Presentation::QueryTreeModelBase::ProjectRole).isValid()); 0160 QVERIFY(model->data(task2Index, Presentation::QueryTreeModelBase::ProjectRole).isValid()); 0161 QCOMPARE(model->data(task1Index, Presentation::QueryTreeModelBase::ProjectRole).toString(), QString()); 0162 QCOMPARE(model->data(task2Index, Presentation::QueryTreeModelBase::ProjectRole).toString(), QString("KDE")); 0163 QCOMPARE(model->data(task1Index, Presentation::QueryTreeModelBase::IsChildRole).toBool(), false); 0164 QCOMPARE(model->data(task2Index, Presentation::QueryTreeModelBase::IsChildRole).toBool(), false); 0165 QVERIFY(!model->data(childTask11Index, Presentation::QueryTreeModelBase::ProjectRole).isValid()); 0166 QVERIFY(!model->data(childTask12Index, Presentation::QueryTreeModelBase::ProjectRole).isValid()); 0167 QCOMPARE(model->data(childTask11Index, Presentation::QueryTreeModelBase::IsChildRole).toBool(), true); 0168 QCOMPARE(model->data(childTask12Index, Presentation::QueryTreeModelBase::IsChildRole).toBool(), true); 0169 0170 // WHEN 0171 taskRepositoryMock(&Domain::TaskRepository::update).when(task1).thenReturn(new FakeJob(this)); 0172 taskRepositoryMock(&Domain::TaskRepository::update).when(childTask11).thenReturn(new FakeJob(this)); 0173 taskRepositoryMock(&Domain::TaskRepository::update).when(childTask12).thenReturn(new FakeJob(this)); 0174 taskRepositoryMock(&Domain::TaskRepository::update).when(task2).thenReturn(new FakeJob(this)); 0175 taskRepositoryMock(&Domain::TaskRepository::update).when(task3).thenReturn(new FakeJob(this)); 0176 0177 QVERIFY(model->setData(task1Index, "newTask1")); 0178 QVERIFY(model->setData(childTask11Index, "newChildTask11")); 0179 QVERIFY(model->setData(task2Index, "newTask2")); 0180 QVERIFY(model->setData(task3Index, "newTask3")); 0181 QVERIFY(model->setData(taskChildTask12Index, "newChildTask12")); 0182 0183 QVERIFY(model->setData(task1Index, Qt::Unchecked, Qt::CheckStateRole)); 0184 QVERIFY(model->setData(childTask11Index, Qt::Unchecked, Qt::CheckStateRole)); 0185 QVERIFY(model->setData(task2Index, Qt::Checked, Qt::CheckStateRole)); 0186 QVERIFY(model->setData(task3Index, Qt::Unchecked, Qt::CheckStateRole)); 0187 QVERIFY(model->setData(taskChildTask12Index, Qt::Checked, Qt::CheckStateRole)); 0188 0189 // THEN 0190 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(task1).exactly(2)); 0191 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(childTask11).exactly(2)); 0192 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(childTask12).exactly(2)); 0193 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(task2).exactly(2)); 0194 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(task3).exactly(2)); 0195 0196 QCOMPARE(task1->title(), QStringLiteral("newTask1")); 0197 QCOMPARE(childTask11->title(), QStringLiteral("newChildTask11")); 0198 QCOMPARE(childTask12->title(), QStringLiteral("newChildTask12")); 0199 QCOMPARE(task2->title(), QStringLiteral("newTask2")); 0200 QCOMPARE(task3->title(), QStringLiteral("newTask3")); 0201 0202 QCOMPARE(task1->isDone(), false); 0203 QCOMPARE(childTask11->isDone(), false); 0204 QCOMPARE(childTask12->isDone(), true); 0205 QCOMPARE(task2->isDone(), true); 0206 QCOMPARE(task3->isDone(), false); 0207 0208 // WHEN 0209 auto data = std::unique_ptr<QMimeData>(model->mimeData(QModelIndexList() << childTask12Index)); 0210 0211 // THEN 0212 QVERIFY(data->hasFormat(QStringLiteral("application/x-zanshin-object"))); 0213 QCOMPARE(data->property("objects").value<Domain::Task::List>(), 0214 Domain::Task::List() << childTask12); 0215 0216 // WHEN 0217 auto childTask2 = Domain::Task::Ptr::create(); 0218 taskRepositoryMock(&Domain::TaskRepository::associate).when(childTask11, childTask2).thenReturn(new FakeJob(this)); 0219 data.reset(new QMimeData); 0220 data->setData(QStringLiteral("application/x-zanshin-object"), "object"); 0221 data->setProperty("objects", QVariant::fromValue(Domain::Task::List() << childTask2)); 0222 model->dropMimeData(data.get(), Qt::MoveAction, -1, -1, childTask11Index); 0223 0224 // THEN 0225 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::associate).when(childTask11, childTask2).exactly(1)); 0226 0227 0228 // WHEN 0229 auto childTask3 = Domain::Task::Ptr::create(); 0230 auto childTask4 = Domain::Task::Ptr::create(); 0231 taskRepositoryMock(&Domain::TaskRepository::associate).when(childTask12, childTask3).thenReturn(new FakeJob(this)); 0232 taskRepositoryMock(&Domain::TaskRepository::associate).when(childTask12, childTask4).thenReturn(new FakeJob(this)); 0233 data.reset(new QMimeData); 0234 data->setData(QStringLiteral("application/x-zanshin-object"), "object"); 0235 data->setProperty("objects", QVariant::fromValue(Domain::Task::List() << childTask3 << childTask4)); 0236 model->dropMimeData(data.get(), Qt::MoveAction, -1, -1, childTask12Index); 0237 0238 // THEN 0239 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::associate).when(childTask12, childTask3).exactly(1)); 0240 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::associate).when(childTask12, childTask4).exactly(1)); 0241 0242 // WHEN 0243 auto childTask5 = Domain::Task::Ptr::create(); 0244 QVERIFY(!childTask5->startDate().isValid()); 0245 taskRepositoryMock(&Domain::TaskRepository::dissociate).when(childTask5).thenReturn(new FakeJob(this)); 0246 data.reset(new QMimeData); 0247 data->setData(QStringLiteral("application/x-zanshin-object"), "object"); 0248 data->setProperty("objects", QVariant::fromValue(Domain::Task::List() << childTask5)); 0249 model->dropMimeData(data.get(), Qt::MoveAction, -1, -1, QModelIndex()); 0250 0251 // THEN 0252 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::dissociate).when(childTask5).exactly(1)); 0253 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(childTask5).exactly(0)); 0254 QCOMPARE(childTask5->startDate(), today); 0255 } 0256 0257 void shouldAddTasksInWorkdayPage() 0258 { 0259 // GIVEN 0260 0261 // ... in fact we won't list any model 0262 Utils::MockObject<Domain::TaskQueries> taskQueriesMock; 0263 0264 // We'll gladly create a task though 0265 Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; 0266 taskRepositoryMock(&Domain::TaskRepository::create).when(any<Domain::Task::Ptr>()).thenReturn(new FakeJob(this)); 0267 0268 Presentation::WorkdayPageModel workday(taskQueriesMock.getInstance(), 0269 taskRepositoryMock.getInstance()); 0270 0271 // WHEN 0272 auto title = QStringLiteral("New task"); 0273 auto today = Utils::DateTime::currentDate(); 0274 auto task = workday.addItem(title); 0275 0276 // THEN 0277 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::create).when(any<Domain::Task::Ptr>()).exactly(1)); 0278 0279 QVERIFY(task); 0280 QCOMPARE(task->title(), title); 0281 QCOMPARE(task->startDate(), today); 0282 } 0283 0284 void shouldAddChildTask() 0285 { 0286 // GIVEN 0287 0288 // Two tasks 0289 auto task1 = Domain::Task::Ptr::create(); 0290 auto task2 = Domain::Task::Ptr::create(); 0291 auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); 0292 auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider); 0293 taskProvider->append(task1); 0294 taskProvider->append(task2); 0295 0296 Utils::MockObject<Domain::TaskQueries> taskQueriesMock; 0297 taskQueriesMock(&Domain::TaskQueries::findWorkdayTopLevel).when().thenReturn(taskResult); 0298 taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); 0299 taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); 0300 taskQueriesMock(&Domain::TaskQueries::findProject).when(any<Domain::Task::Ptr>()).thenReturn(Domain::QueryResult<Domain::Project::Ptr>::Ptr()); 0301 0302 Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; 0303 taskRepositoryMock(&Domain::TaskRepository::createChild).when(any<Domain::Task::Ptr>(), 0304 any<Domain::Task::Ptr>()) 0305 .thenReturn(new FakeJob(this)); 0306 0307 Presentation::WorkdayPageModel workday(taskQueriesMock.getInstance(), 0308 taskRepositoryMock.getInstance()); 0309 0310 // WHEN 0311 const auto title = QStringLiteral("New task"); 0312 const auto parentIndex = workday.centralListModel()->index(0, 0); 0313 const auto createdTask = workday.addItem(title, parentIndex); 0314 0315 // THEN 0316 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::createChild).when(any<Domain::Task::Ptr>(), 0317 any<Domain::Task::Ptr>()) 0318 .exactly(1)); 0319 0320 QVERIFY(createdTask); 0321 QCOMPARE(createdTask->title(), title); 0322 QVERIFY(!createdTask->startDate().isValid()); 0323 } 0324 0325 void shouldDeleteItems() 0326 { 0327 // GIVEN 0328 0329 // Two tasks 0330 auto task1 = Domain::Task::Ptr::create(); 0331 auto task2 = Domain::Task::Ptr::create(); 0332 auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); 0333 auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider); 0334 taskProvider->append(task1); 0335 taskProvider->append(task2); 0336 0337 Utils::MockObject<Domain::TaskQueries> taskQueriesMock; 0338 taskQueriesMock(&Domain::TaskQueries::findWorkdayTopLevel).when().thenReturn(taskResult); 0339 taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); 0340 taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); 0341 taskQueriesMock(&Domain::TaskQueries::findProject).when(any<Domain::Task::Ptr>()).thenReturn(Domain::QueryResult<Domain::Project::Ptr>::Ptr()); 0342 0343 Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; 0344 taskRepositoryMock(&Domain::TaskRepository::remove).when(task2).thenReturn(new FakeJob(this)); 0345 0346 Presentation::WorkdayPageModel workday(taskQueriesMock.getInstance(), 0347 taskRepositoryMock.getInstance()); 0348 0349 // WHEN 0350 const QModelIndex index = workday.centralListModel()->index(1, 0); 0351 workday.removeItem(index); 0352 0353 // THEN 0354 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::remove).when(task2).exactly(1)); 0355 } 0356 0357 void shouldPromoteItem() 0358 { 0359 // GIVEN 0360 0361 // Two tasks 0362 auto task1 = Domain::Task::Ptr::create(); 0363 auto task2 = Domain::Task::Ptr::create(); 0364 auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); 0365 auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider); 0366 taskProvider->append(task1); 0367 taskProvider->append(task2); 0368 0369 Utils::MockObject<Domain::TaskQueries> taskQueriesMock; 0370 taskQueriesMock(&Domain::TaskQueries::findWorkdayTopLevel).when().thenReturn(taskResult); 0371 taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); 0372 taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); 0373 taskQueriesMock(&Domain::TaskQueries::findProject).when(any<Domain::Task::Ptr>()).thenReturn(Domain::QueryResult<Domain::Project::Ptr>::Ptr()); 0374 0375 Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; 0376 taskRepositoryMock(&Domain::TaskRepository::promoteToProject).when(task2).thenReturn(new FakeJob(this)); 0377 0378 Presentation::WorkdayPageModel workday(taskQueriesMock.getInstance(), 0379 taskRepositoryMock.getInstance()); 0380 0381 // WHEN 0382 const QModelIndex index = workday.centralListModel()->index(1, 0); 0383 workday.promoteItem(index); 0384 0385 // THEN 0386 QVERIFY(taskRepositoryMock(&Domain::TaskRepository::promoteToProject).when(task2).exactly(1)); 0387 } 0388 }; 0389 0390 ZANSHIN_TEST_MAIN(WorkdayPageModelTest) 0391 0392 #include "workdaypagemodeltest.moc"