Changeset View
Changeset View
Standalone View
Standalone View
tests/units/presentation/inboxpagemodeltest.cpp
Show All 21 Lines | |||||
22 | */ | 22 | */ | ||
23 | 23 | | |||
24 | #include <testlib/qtest_zanshin.h> | 24 | #include <testlib/qtest_zanshin.h> | ||
25 | 25 | | |||
26 | #include <memory> | 26 | #include <memory> | ||
27 | 27 | | |||
28 | #include <QMimeData> | 28 | #include <QMimeData> | ||
29 | 29 | | |||
30 | #include "utils/mockobject.h" | | |||
31 | 30 | | |||
32 | #include "domain/taskqueries.h" | 31 | #include "domain/taskqueries.h" | ||
33 | #include "domain/taskrepository.h" | 32 | #include "domain/taskrepository.h" | ||
34 | 33 | | |||
35 | #include "presentation/inboxpagemodel.h" | 34 | #include "presentation/inboxpagemodel.h" | ||
36 | #include "presentation/errorhandler.h" | 35 | #include "presentation/errorhandler.h" | ||
37 | #include "presentation/querytreemodelbase.h" | 36 | #include "presentation/querytreemodelbase.h" | ||
38 | 37 | | |||
39 | #include "akonadi/akonadiserializerinterface.h" | 38 | #include "akonadi/akonadiserializerinterface.h" | ||
40 | 39 | | |||
41 | #include "utils/dependencymanager.h" | 40 | #include "utils/dependencymanager.h" | ||
42 | #include "integration/dependencies.h" | 41 | #include "integration/dependencies.h" | ||
43 | 42 | | |||
44 | #include "testlib/fakejob.h" | 43 | #include "testlib/fakejob.h" | ||
45 | #include "testlib/akonadifakedata.h" | 44 | #include "testlib/akonadifakedata.h" | ||
46 | #include "testlib/gencollection.h" | 45 | #include "testlib/gencollection.h" | ||
47 | #include "testlib/gentodo.h" | 46 | #include "testlib/gentodo.h" | ||
48 | #include "testlib/testhelpers.h" | 47 | #include "testlib/testhelpers.h" | ||
49 | 48 | | |||
50 | using namespace Testlib; | 49 | using namespace Testlib; | ||
51 | using namespace mockitopp; | | |||
52 | using namespace mockitopp::matcher; | | |||
53 | 50 | | |||
54 | class FakeErrorHandler : public Presentation::ErrorHandler | 51 | class FakeErrorHandler : public Presentation::ErrorHandler | ||
55 | { | 52 | { | ||
56 | public: | 53 | public: | ||
57 | void doDisplayMessage(const QString &message) override | 54 | void doDisplayMessage(const QString &message) override | ||
58 | { | 55 | { | ||
59 | m_message = message; | 56 | m_message = message; | ||
60 | } | 57 | } | ||
61 | 58 | | |||
62 | QString m_message; | 59 | QString m_message; | ||
63 | }; | 60 | }; | ||
64 | 61 | | |||
65 | class InboxPageModelTest : public QObject | 62 | class InboxPageModelTest : public QObject | ||
66 | { | 63 | { | ||
67 | Q_OBJECT | 64 | Q_OBJECT | ||
68 | private slots: | 65 | private slots: | ||
66 | void cleanup() | ||||
67 | { | ||||
68 | // The first call to QueryTreeModelBase::data triggers fetchTaskExtraData which creates jobs. | ||||
69 | // Wait for these to finish so they don't mess up subsequent tests | ||||
70 | TestHelpers::waitForEmptyJobQueue(); | ||||
71 | } | ||||
72 | | ||||
69 | void shouldListInboxInCentralListModel() | 73 | void shouldListInboxInCentralListModel() | ||
70 | { | 74 | { | ||
71 | // GIVEN | 75 | // GIVEN | ||
72 | 76 | | |||
73 | AkonadiFakeData data; | 77 | AkonadiFakeData data; | ||
74 | auto deps = data.createDependencies(); | 78 | auto deps = data.createDependencies(); | ||
75 | Integration::initializeDefaultDomainDependencies(*deps.get()); | 79 | Integration::initializeDefaultDomainDependencies(*deps.get()); | ||
76 | 80 | | |||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Line(s) | |||||
191 | QCOMPARE(serializer->relatedUidFromItem(data.item(50)), QStringLiteral("1")); | 195 | QCOMPARE(serializer->relatedUidFromItem(data.item(50)), QStringLiteral("1")); | ||
192 | QCOMPARE(model->rowCount(), 1); | 196 | QCOMPARE(model->rowCount(), 1); | ||
193 | QCOMPARE(model->rowCount(rootTaskIndex), 4); | 197 | QCOMPARE(model->rowCount(rootTaskIndex), 4); | ||
194 | } | 198 | } | ||
195 | 199 | | |||
196 | void shouldAddTasksInInbox() | 200 | void shouldAddTasksInInbox() | ||
197 | { | 201 | { | ||
198 | // GIVEN | 202 | // GIVEN | ||
203 | AkonadiFakeData data; | ||||
204 | auto deps = data.createDependencies(); | ||||
205 | Integration::initializeDefaultDomainDependencies(*deps.get()); | ||||
206 | data.createCollection(GenCollection().withId(42).withRootAsParent().withTaskContent()); | ||||
199 | 207 | | |||
200 | // ... in fact we won't list any model | 208 | Presentation::InboxPageModel pageModel(deps->create<Domain::TaskQueries>(), | ||
201 | Utils::MockObject<Domain::TaskQueries> taskQueriesMock; | 209 | deps->create<Domain::TaskRepository>()); | ||
202 | 210 | QAbstractItemModel *model = pageModel.centralListModel(); | |||
203 | // We'll gladly create a task though | | |||
204 | Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; | | |||
205 | taskRepositoryMock(&Domain::TaskRepository::create).when(any<Domain::Task::Ptr>()).thenReturn(new FakeJob(this)); | | |||
206 | | ||||
207 | Presentation::InboxPageModel inbox(taskQueriesMock.getInstance(), | | |||
208 | taskRepositoryMock.getInstance()); | | |||
209 | 211 | | |||
210 | // WHEN | 212 | // WHEN | ||
211 | auto title = QStringLiteral("New task"); | 213 | auto title = QStringLiteral("New task"); | ||
212 | auto task = inbox.addItem(title); | 214 | auto createdTask = pageModel.addItem(title); | ||
215 | TestHelpers::waitForEmptyJobQueue(); | ||||
213 | 216 | | |||
214 | // THEN | 217 | // THEN | ||
215 | QVERIFY(taskRepositoryMock(&Domain::TaskRepository::create).when(any<Domain::Task::Ptr>()).exactly(1)); | 218 | QVERIFY(createdTask); | ||
216 | QVERIFY(task); | 219 | QCOMPARE(createdTask->title(), title); | ||
217 | QCOMPARE(task->title(), title); | 220 | QCOMPARE(model->rowCount(), 1); | ||
221 | auto taskInModel = model->data(model->index(0, 0), Presentation::QueryTreeModelBase::ObjectRole).value<Domain::Task::Ptr>(); | ||||
222 | QVERIFY(taskInModel); | ||||
223 | QCOMPARE(taskInModel->title(), createdTask->title()); | ||||
224 | QCOMPARE(taskInModel->startDate(), createdTask->startDate()); | ||||
225 | | ||||
226 | QCOMPARE(data.items().count(), 1); | ||||
227 | TestHelpers::waitForEmptyJobQueue(); | ||||
218 | } | 228 | } | ||
219 | 229 | | |||
220 | void shouldAddChildTask() | 230 | void shouldAddChildTask() | ||
221 | { | 231 | { | ||
222 | // GIVEN | 232 | // GIVEN | ||
233 | AkonadiFakeData data; | ||||
234 | auto deps = data.createDependencies(); | ||||
235 | Integration::initializeDefaultDomainDependencies(*deps.get()); | ||||
236 | data.createCollection(GenCollection().withId(42).withRootAsParent().withTaskContent()); | ||||
223 | 237 | | |||
224 | // Two tasks | 238 | // Two tasks | ||
225 | auto task1 = Domain::Task::Ptr::create(); | 239 | data.createItem(GenTodo().withId(42).withParent(42).withUid("42").withTitle(QStringLiteral("task1"))); | ||
226 | auto task2 = Domain::Task::Ptr::create(); | 240 | data.createItem(GenTodo().withId(43).withParent(42).withUid("43").withTitle(QStringLiteral("task2"))); | ||
227 | auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); | 241 | QCOMPARE(data.items().count(), 2); | ||
228 | auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider); | | |||
229 | taskProvider->append(task1); | | |||
230 | taskProvider->append(task2); | | |||
231 | | ||||
232 | Utils::MockObject<Domain::TaskQueries> taskQueriesMock; | | |||
233 | taskQueriesMock(&Domain::TaskQueries::findInboxTopLevel).when().thenReturn(taskResult); | | |||
234 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); | | |||
235 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); | | |||
236 | taskQueriesMock(&Domain::TaskQueries::findDataSource).when(any<Domain::Task::Ptr>()).thenReturn(Domain::QueryResult<Domain::DataSource::Ptr>::Ptr()); | | |||
237 | | ||||
238 | Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; | | |||
239 | taskRepositoryMock(&Domain::TaskRepository::createChild).when(any<Domain::Task::Ptr>(), | | |||
240 | any<Domain::Task::Ptr>()) | | |||
241 | .thenReturn(new FakeJob(this)); | | |||
242 | 242 | | |||
243 | Presentation::InboxPageModel inbox(taskQueriesMock.getInstance(), | 243 | Presentation::InboxPageModel pageModel(deps->create<Domain::TaskQueries>(), | ||
244 | taskRepositoryMock.getInstance()); | 244 | deps->create<Domain::TaskRepository>()); | ||
245 | QAbstractItemModel *model = pageModel.centralListModel(); | ||||
246 | TestHelpers::waitForEmptyJobQueue(); | ||||
247 | QCOMPARE(model->rowCount(), 2); | ||||
245 | 248 | | |||
246 | // WHEN | 249 | // WHEN | ||
247 | const auto title = QStringLiteral("New task"); | 250 | const auto title = QStringLiteral("New task"); | ||
248 | const auto parentIndex = inbox.centralListModel()->index(0, 0); | 251 | const auto parentIndex = model->index(0, 0); | ||
249 | const auto createdTask = inbox.addItem(title, parentIndex); | 252 | const auto createdTask = pageModel.addItem(title, parentIndex); | ||
253 | TestHelpers::waitForEmptyJobQueue(); | ||||
250 | 254 | | |||
251 | // THEN | 255 | // THEN | ||
252 | QVERIFY(taskRepositoryMock(&Domain::TaskRepository::createChild).when(any<Domain::Task::Ptr>(), | | |||
253 | any<Domain::Task::Ptr>()) | | |||
254 | .exactly(1)); | | |||
255 | QVERIFY(createdTask); | 256 | QVERIFY(createdTask); | ||
256 | QCOMPARE(createdTask->title(), title); | 257 | QCOMPARE(createdTask->title(), title); | ||
258 | | ||||
259 | QCOMPARE(model->rowCount(parentIndex), 1); | ||||
260 | auto taskInModel = model->data(model->index(0, 0, parentIndex), Presentation::QueryTreeModelBase::ObjectRole).value<Domain::Task::Ptr>(); | ||||
261 | QVERIFY(taskInModel); | ||||
262 | QCOMPARE(taskInModel->title(), createdTask->title()); | ||||
263 | QCOMPARE(taskInModel->startDate(), createdTask->startDate()); | ||||
264 | | ||||
265 | QCOMPARE(data.items().count(), 3); | ||||
266 | TestHelpers::waitForEmptyJobQueue(); | ||||
257 | } | 267 | } | ||
258 | 268 | | |||
259 | void shouldGetAnErrorMessageWhenAddTaskFailed() | 269 | void shouldGetAnErrorMessageWhenAddTaskFailed() | ||
260 | { | 270 | { | ||
261 | // GIVEN | 271 | // GIVEN | ||
272 | AkonadiFakeData data; | ||||
273 | auto deps = data.createDependencies(); | ||||
274 | Integration::initializeDefaultDomainDependencies(*deps.get()); | ||||
275 | data.createCollection(GenCollection().withId(42).withRootAsParent().withTaskContent()); | ||||
262 | 276 | | |||
263 | // ... in fact we won't list any model | 277 | Presentation::InboxPageModel pageModel(deps->create<Domain::TaskQueries>(), | ||
264 | Utils::MockObject<Domain::TaskQueries> taskQueriesMock; | 278 | deps->create<Domain::TaskRepository>()); | ||
265 | | ||||
266 | // We'll gladly create a task though | | |||
267 | Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; | | |||
268 | auto job = new FakeJob(this); | | |||
269 | job->setExpectedError(KJob::KilledJobError, QStringLiteral("Foo")); | | |||
270 | taskRepositoryMock(&Domain::TaskRepository::create).when(any<Domain::Task::Ptr>()).thenReturn(job); | | |||
271 | | ||||
272 | Presentation::InboxPageModel inbox(taskQueriesMock.getInstance(), | | |||
273 | taskRepositoryMock.getInstance()); | | |||
274 | 279 | | |||
275 | FakeErrorHandler errorHandler; | 280 | FakeErrorHandler errorHandler; | ||
276 | inbox.setErrorHandler(&errorHandler); | 281 | pageModel.setErrorHandler(&errorHandler); | ||
277 | 282 | | |||
278 | // WHEN | 283 | // WHEN | ||
279 | inbox.addItem(QStringLiteral("New task")); | 284 | data.storageBehavior().setCreateNextItemError(1, QStringLiteral("Foo")); | ||
285 | pageModel.addItem(QStringLiteral("New task")); | ||||
286 | TestHelpers::waitForEmptyJobQueue(); | ||||
280 | 287 | | |||
281 | // THEN | 288 | // THEN | ||
282 | QTest::qWait(150); | | |||
283 | QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot add task New task in Inbox: Foo")); | 289 | QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot add task New task in Inbox: Foo")); | ||
284 | } | 290 | } | ||
285 | 291 | | |||
286 | void shouldDeleteItems() | 292 | void shouldDeleteItems() | ||
287 | { | 293 | { | ||
288 | // GIVEN | 294 | // GIVEN | ||
295 | AkonadiFakeData data; | ||||
296 | auto deps = data.createDependencies(); | ||||
297 | Integration::initializeDefaultDomainDependencies(*deps.get()); | ||||
298 | data.createCollection(GenCollection().withId(42).withRootAsParent().withTaskContent()); | ||||
289 | 299 | | |||
290 | // Two tasks | 300 | // Two tasks | ||
291 | auto task1 = Domain::Task::Ptr::create(); | 301 | data.createItem(GenTodo().withId(42).withParent(42).withUid("42").withTitle(QStringLiteral("task1"))); | ||
292 | auto task2 = Domain::Task::Ptr::create(); | 302 | data.createItem(GenTodo().withId(43).withParent(42).withUid("43").withTitle(QStringLiteral("task2"))); | ||
293 | auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); | 303 | QCOMPARE(data.items().count(), 2); | ||
294 | auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider); | | |||
295 | taskProvider->append(task1); | | |||
296 | taskProvider->append(task2); | | |||
297 | | ||||
298 | Utils::MockObject<Domain::TaskQueries> taskQueriesMock; | | |||
299 | taskQueriesMock(&Domain::TaskQueries::findInboxTopLevel).when().thenReturn(taskResult); | | |||
300 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); | | |||
301 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); | | |||
302 | taskQueriesMock(&Domain::TaskQueries::findDataSource).when(any<Domain::Task::Ptr>()).thenReturn(Domain::QueryResult<Domain::DataSource::Ptr>::Ptr()); | | |||
303 | 304 | | |||
304 | Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; | 305 | Presentation::InboxPageModel pageModel(deps->create<Domain::TaskQueries>(), | ||
305 | taskRepositoryMock(&Domain::TaskRepository::remove).when(task2).thenReturn(new FakeJob(this)); | 306 | deps->create<Domain::TaskRepository>()); | ||
306 | 307 | QAbstractItemModel *model = pageModel.centralListModel(); | |||
307 | Presentation::InboxPageModel inbox(taskQueriesMock.getInstance(), | 308 | TestHelpers::waitForEmptyJobQueue(); | ||
308 | taskRepositoryMock.getInstance()); | 309 | QCOMPARE(model->rowCount(), 2); | ||
309 | 310 | | |||
310 | // WHEN | 311 | // WHEN | ||
311 | const QModelIndex index = inbox.centralListModel()->index(1, 0); | 312 | const QModelIndex index = model->index(1, 0); | ||
312 | inbox.removeItem(index); | 313 | QVERIFY(index.isValid()); | ||
314 | pageModel.removeItem(index); | ||||
315 | TestHelpers::waitForEmptyJobQueue(); | ||||
313 | 316 | | |||
314 | // THEN | 317 | // THEN | ||
315 | QVERIFY(taskRepositoryMock(&Domain::TaskRepository::remove).when(task2).exactly(1)); | 318 | QCOMPARE(model->rowCount(), 1); | ||
319 | QCOMPARE(data.items().count(), 1); | ||||
316 | } | 320 | } | ||
317 | 321 | | |||
318 | void shouldGetAnErrorMessageWhenDeleteItemsFailed() | 322 | void shouldGetAnErrorMessageWhenDeleteItemsFailed() | ||
319 | { | 323 | { | ||
320 | // GIVEN | 324 | // GIVEN | ||
325 | AkonadiFakeData data; | ||||
326 | auto deps = data.createDependencies(); | ||||
327 | Integration::initializeDefaultDomainDependencies(*deps.get()); | ||||
328 | data.createCollection(GenCollection().withId(42).withRootAsParent().withTaskContent()); | ||||
321 | 329 | | |||
322 | // Two tasks | 330 | // Two tasks | ||
323 | auto task1 = Domain::Task::Ptr::create(); | 331 | data.createItem(GenTodo().withId(42).withParent(42).withUid("42").withTitle(QStringLiteral("task1"))); | ||
324 | auto task2 = Domain::Task::Ptr::create(); | 332 | data.createItem(GenTodo().withId(43).withParent(42).withUid("43").withTitle(QStringLiteral("task2"))); | ||
325 | task2->setTitle(QStringLiteral("task2")); | 333 | QCOMPARE(data.items().count(), 2); | ||
326 | auto inboxProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); | 334 | | ||
327 | auto inboxResult = Domain::QueryResult<Domain::Task::Ptr>::create(inboxProvider); | 335 | Presentation::InboxPageModel pageModel(deps->create<Domain::TaskQueries>(), | ||
328 | inboxProvider->append(task1); | 336 | deps->create<Domain::TaskRepository>()); | ||
329 | inboxProvider->append(task2); | 337 | QAbstractItemModel *model = pageModel.centralListModel(); | ||
330 | 338 | TestHelpers::waitForEmptyJobQueue(); | |||
331 | Utils::MockObject<Domain::TaskQueries> taskQueriesMock; | 339 | QCOMPARE(model->rowCount(), 2); | ||
332 | taskQueriesMock(&Domain::TaskQueries::findInboxTopLevel).when().thenReturn(inboxResult); | | |||
333 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); | | |||
334 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); | | |||
335 | taskQueriesMock(&Domain::TaskQueries::findDataSource).when(any<Domain::Task::Ptr>()).thenReturn(Domain::QueryResult<Domain::DataSource::Ptr>::Ptr()); | | |||
336 | | ||||
337 | Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; | | |||
338 | auto job = new FakeJob(this); | | |||
339 | job->setExpectedError(KJob::KilledJobError, QStringLiteral("Foo")); | | |||
340 | taskRepositoryMock(&Domain::TaskRepository::remove).when(task2).thenReturn(job); | | |||
341 | 340 | | |||
342 | Presentation::InboxPageModel inbox(taskQueriesMock.getInstance(), | | |||
343 | taskRepositoryMock.getInstance()); | | |||
344 | FakeErrorHandler errorHandler; | 341 | FakeErrorHandler errorHandler; | ||
345 | inbox.setErrorHandler(&errorHandler); | 342 | pageModel.setErrorHandler(&errorHandler); | ||
346 | 343 | | |||
347 | // WHEN | 344 | // WHEN | ||
348 | const QModelIndex index = inbox.centralListModel()->index(1, 0); | 345 | data.storageBehavior().setDeleteNextItemError(1, QStringLiteral("Error deleting")); | ||
349 | inbox.removeItem(index); | 346 | const QModelIndex index = model->index(1, 0); | ||
347 | pageModel.removeItem(index); | ||||
348 | TestHelpers::waitForEmptyJobQueue(); | ||||
350 | 349 | | |||
351 | // THEN | 350 | // THEN | ||
352 | QTest::qWait(150); | 351 | QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot remove task task2 from Inbox: Error deleting")); | ||
353 | QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot remove task task2 from Inbox: Foo")); | | |||
354 | } | 352 | } | ||
355 | 353 | | |||
356 | void shouldPromoteItem() | 354 | void shouldPromoteItem() | ||
357 | { | 355 | { | ||
358 | // GIVEN | 356 | // GIVEN | ||
359 | 357 | | |||
358 | AkonadiFakeData data; | ||||
359 | auto deps = data.createDependencies(); | ||||
360 | Integration::initializeDefaultDomainDependencies(*deps.get()); | ||||
361 | data.createCollection(GenCollection().withId(42).withRootAsParent().withTaskContent()); | ||||
362 | | ||||
360 | // Two tasks | 363 | // Two tasks | ||
361 | auto task1 = Domain::Task::Ptr::create(); | 364 | data.createItem(GenTodo().withId(42).withParent(42).withUid("42").withTitle(QStringLiteral("task1"))); | ||
362 | auto task2 = Domain::Task::Ptr::create(); | 365 | data.createItem(GenTodo().withId(43).withParent(42).withUid("43").withTitle(QStringLiteral("task2"))); | ||
363 | auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); | 366 | QCOMPARE(data.items().count(), 2); | ||
364 | auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider); | | |||
365 | taskProvider->append(task1); | | |||
366 | taskProvider->append(task2); | | |||
367 | 367 | | |||
368 | Utils::MockObject<Domain::TaskQueries> taskQueriesMock; | 368 | auto serializer = deps->create<Akonadi::SerializerInterface>(); | ||
369 | taskQueriesMock(&Domain::TaskQueries::findInboxTopLevel).when().thenReturn(taskResult); | | |||
370 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); | | |||
371 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); | | |||
372 | taskQueriesMock(&Domain::TaskQueries::findDataSource).when(any<Domain::Task::Ptr>()).thenReturn(Domain::QueryResult<Domain::DataSource::Ptr>::Ptr()); | | |||
373 | 369 | | |||
374 | Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; | 370 | QVERIFY(!serializer->isProjectItem(data.items().at(1))); | ||
375 | taskRepositoryMock(&Domain::TaskRepository::promoteToProject).when(task2).thenReturn(new FakeJob(this)); | | |||
376 | 371 | | |||
377 | Presentation::InboxPageModel inbox(taskQueriesMock.getInstance(), | 372 | Presentation::InboxPageModel pageModel(deps->create<Domain::TaskQueries>(), | ||
378 | taskRepositoryMock.getInstance()); | 373 | deps->create<Domain::TaskRepository>()); | ||
374 | QAbstractItemModel *model = pageModel.centralListModel(); | ||||
375 | TestHelpers::waitForEmptyJobQueue(); | ||||
376 | QCOMPARE(model->rowCount(), 2); | ||||
379 | 377 | | |||
380 | // WHEN | 378 | // WHEN | ||
381 | const QModelIndex index = inbox.centralListModel()->index(1, 0); | 379 | const QModelIndex index = model->index(1, 0); | ||
382 | inbox.promoteItem(index); | 380 | pageModel.promoteItem(index); | ||
381 | TestHelpers::waitForEmptyJobQueue(); | ||||
383 | 382 | | |||
384 | // THEN | 383 | // THEN | ||
385 | QVERIFY(taskRepositoryMock(&Domain::TaskRepository::promoteToProject).when(task2).exactly(1)); | 384 | QCOMPARE(model->rowCount(), 1); | ||
385 | QCOMPARE(data.items().count(), 2); | ||||
386 | QVERIFY(serializer->isProjectItem(data.items().at(1))); | ||||
386 | } | 387 | } | ||
387 | 388 | | |||
388 | void shouldGetAnErrorMessageWhenPromoteItemFailed() | 389 | void shouldGetAnErrorMessageWhenPromoteItemFailed() | ||
389 | { | 390 | { | ||
390 | // GIVEN | 391 | // GIVEN | ||
392 | AkonadiFakeData data; | ||||
393 | auto deps = data.createDependencies(); | ||||
394 | Integration::initializeDefaultDomainDependencies(*deps.get()); | ||||
395 | data.createCollection(GenCollection().withId(42).withRootAsParent().withTaskContent()); | ||||
391 | 396 | | |||
392 | // Two tasks | 397 | // Two tasks | ||
393 | auto task1 = Domain::Task::Ptr::create(); | 398 | data.createItem(GenTodo().withId(42).withParent(42).withUid("42").withTitle(QStringLiteral("task1"))); | ||
394 | auto task2 = Domain::Task::Ptr::create(); | 399 | data.createItem(GenTodo().withId(43).withParent(42).withUid("43").withTitle(QStringLiteral("task2"))); | ||
395 | task2->setTitle(QStringLiteral("task2")); | 400 | QCOMPARE(data.items().count(), 2); | ||
396 | auto inboxProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); | 401 | | ||
397 | auto inboxResult = Domain::QueryResult<Domain::Task::Ptr>::create(inboxProvider); | 402 | Presentation::InboxPageModel pageModel(deps->create<Domain::TaskQueries>(), | ||
398 | inboxProvider->append(task1); | 403 | deps->create<Domain::TaskRepository>()); | ||
399 | inboxProvider->append(task2); | 404 | QAbstractItemModel *model = pageModel.centralListModel(); | ||
400 | 405 | TestHelpers::waitForEmptyJobQueue(); | |||
401 | Utils::MockObject<Domain::TaskQueries> taskQueriesMock; | 406 | QCOMPARE(model->rowCount(), 2); | ||
402 | taskQueriesMock(&Domain::TaskQueries::findInboxTopLevel).when().thenReturn(inboxResult); | | |||
403 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); | | |||
404 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); | | |||
405 | taskQueriesMock(&Domain::TaskQueries::findDataSource).when(any<Domain::Task::Ptr>()).thenReturn(Domain::QueryResult<Domain::DataSource::Ptr>::Ptr()); | | |||
406 | | ||||
407 | Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; | | |||
408 | auto job = new FakeJob(this); | | |||
409 | job->setExpectedError(KJob::KilledJobError, QStringLiteral("Foo")); | | |||
410 | taskRepositoryMock(&Domain::TaskRepository::promoteToProject).when(task2).thenReturn(job); | | |||
411 | 407 | | |||
412 | Presentation::InboxPageModel inbox(taskQueriesMock.getInstance(), | | |||
413 | taskRepositoryMock.getInstance()); | | |||
414 | FakeErrorHandler errorHandler; | 408 | FakeErrorHandler errorHandler; | ||
415 | inbox.setErrorHandler(&errorHandler); | 409 | pageModel.setErrorHandler(&errorHandler); | ||
416 | 410 | | |||
417 | // WHEN | 411 | // WHEN | ||
418 | const QModelIndex index = inbox.centralListModel()->index(1, 0); | 412 | data.storageBehavior().setUpdateNextItemError(44, QStringLiteral("Foo")); | ||
419 | inbox.promoteItem(index); | 413 | const QModelIndex index = model->index(1, 0); | ||
414 | pageModel.promoteItem(index); | ||||
415 | TestHelpers::waitForEmptyJobQueue(); | ||||
420 | 416 | | |||
421 | // THEN | 417 | // THEN | ||
422 | QTest::qWait(150); | | |||
423 | QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot promote task task2 to be a project: Foo")); | 418 | QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot promote task task2 to be a project: Foo")); | ||
424 | } | 419 | } | ||
425 | 420 | | |||
426 | void shouldGetAnErrorMessageWhenUpdateTaskFailed() | 421 | void shouldGetAnErrorMessageWhenUpdateTaskFailed() | ||
427 | { | 422 | { | ||
428 | // GIVEN | 423 | // GIVEN | ||
424 | AkonadiFakeData data; | ||||
425 | auto deps = data.createDependencies(); | ||||
426 | Integration::initializeDefaultDomainDependencies(*deps.get()); | ||||
427 | data.createCollection(GenCollection().withId(42).withRootAsParent().withTaskContent()); | ||||
429 | 428 | | |||
430 | // One task | 429 | // One task | ||
431 | auto rootTask = Domain::Task::Ptr::create(); | 430 | data.createItem(GenTodo().withId(42).withParent(42).withUid("42").withTitle(QStringLiteral("rootTask"))); | ||
432 | rootTask->setTitle(QStringLiteral("rootTask")); | | |||
433 | auto inboxProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); | | |||
434 | auto inboxResult = Domain::QueryResult<Domain::Task::Ptr>::create(inboxProvider); | | |||
435 | inboxProvider->append(rootTask); | | |||
436 | auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); | | |||
437 | auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider); | | |||
438 | | ||||
439 | Utils::MockObject<Domain::TaskQueries> taskQueriesMock; | | |||
440 | taskQueriesMock(&Domain::TaskQueries::findInboxTopLevel).when().thenReturn(inboxResult); | | |||
441 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(rootTask).thenReturn(taskResult); | | |||
442 | taskQueriesMock(&Domain::TaskQueries::findDataSource).when(any<Domain::Task::Ptr>()).thenReturn(Domain::QueryResult<Domain::DataSource::Ptr>::Ptr()); | | |||
443 | Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; | | |||
444 | 431 | | |||
445 | Presentation::InboxPageModel inbox(taskQueriesMock.getInstance(), | 432 | auto serializer = deps->create<Akonadi::SerializerInterface>(); | ||
446 | taskRepositoryMock.getInstance()); | 433 | Presentation::InboxPageModel pageModel(deps->create<Domain::TaskQueries>(), | ||
434 | deps->create<Domain::TaskRepository>()); | ||||
435 | QAbstractItemModel *model = pageModel.centralListModel(); | ||||
436 | TestHelpers::waitForEmptyJobQueue(); | ||||
447 | 437 | | |||
448 | QAbstractItemModel *model = inbox.centralListModel(); | | |||
449 | const QModelIndex rootTaskIndex = model->index(0, 0); | | |||
450 | FakeErrorHandler errorHandler; | 438 | FakeErrorHandler errorHandler; | ||
451 | inbox.setErrorHandler(&errorHandler); | 439 | pageModel.setErrorHandler(&errorHandler); | ||
452 | 440 | | |||
453 | // WHEN | 441 | const QModelIndex index = model->index(0, 0); | ||
454 | auto job = new FakeJob(this); | 442 | auto rootTask = model->data(index, Presentation::QueryTreeModelBase::ObjectRole).value<Domain::Task::Ptr>(); | ||
455 | job->setExpectedError(KJob::KilledJobError, QStringLiteral("Foo")); | | |||
456 | taskRepositoryMock(&Domain::TaskRepository::update).when(rootTask).thenReturn(job); | | |||
457 | 443 | | |||
458 | QVERIFY(model->setData(rootTaskIndex, "newRootTask")); | 444 | // WHEN | ||
445 | data.storageBehavior().setUpdateNextItemError(1, QStringLiteral("Update error")); | ||||
446 | QVERIFY(model->setData(index, "newRootTask")); | ||||
447 | TestHelpers::waitForEmptyJobQueue(); | ||||
459 | 448 | | |||
460 | // THEN | 449 | // THEN | ||
461 | QTest::qWait(150); | 450 | QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot modify task rootTask in Inbox: Update error")); | ||
462 | QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot modify task rootTask in Inbox: Foo")); | 451 | QCOMPARE(rootTask->title(), QStringLiteral("newRootTask")); // Note that the task *did* get updated | ||
452 | QCOMPARE(index.data().toString(), QStringLiteral("newRootTask")); // and therefore the model keeps showing the new value | ||||
453 | QCOMPARE(serializer->createTaskFromItem(data.item(42))->title(), QStringLiteral("rootTask")); // but the underlying data wasn't updated | ||||
463 | } | 454 | } | ||
464 | 455 | | |||
465 | void shouldGetAnErrorMessageWhenAssociateTaskFailed() | 456 | void shouldGetAnErrorMessageWhenAssociateTaskFailed() | ||
466 | { | 457 | { | ||
467 | // GIVEN | 458 | // GIVEN | ||
459 | AkonadiFakeData data; | ||||
460 | auto deps = data.createDependencies(); | ||||
461 | Integration::initializeDefaultDomainDependencies(*deps.get()); | ||||
462 | data.createCollection(GenCollection().withId(42).withRootAsParent().withTaskContent()); | ||||
468 | 463 | | |||
469 | // One task | 464 | // Three tasks | ||
470 | auto rootTask = Domain::Task::Ptr::create(); | 465 | data.createItem(GenTodo().withId(42).withParent(42).withUid("42").withTitle(QStringLiteral("task1"))); | ||
471 | rootTask->setTitle(QStringLiteral("rootTask")); | 466 | data.createItem(GenTodo().withId(43).withParent(42).withUid("43").withTitle(QStringLiteral("task2"))); | ||
472 | auto inboxProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); | 467 | data.createItem(GenTodo().withId(44).withParent(42).withUid("44").withTitle(QStringLiteral("task3"))); | ||
473 | auto inboxResult = Domain::QueryResult<Domain::Task::Ptr>::create(inboxProvider); | | |||
474 | inboxProvider->append(rootTask); | | |||
475 | auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); | | |||
476 | auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider); | | |||
477 | | ||||
478 | Utils::MockObject<Domain::TaskQueries> taskQueriesMock; | | |||
479 | taskQueriesMock(&Domain::TaskQueries::findInboxTopLevel).when().thenReturn(inboxResult); | | |||
480 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(rootTask).thenReturn(taskResult); | | |||
481 | taskQueriesMock(&Domain::TaskQueries::findDataSource).when(any<Domain::Task::Ptr>()).thenReturn(Domain::QueryResult<Domain::DataSource::Ptr>::Ptr()); | | |||
482 | Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; | | |||
483 | 468 | | |||
484 | Presentation::InboxPageModel inbox(taskQueriesMock.getInstance(), | 469 | Presentation::InboxPageModel pageModel(deps->create<Domain::TaskQueries>(), | ||
485 | taskRepositoryMock.getInstance()); | 470 | deps->create<Domain::TaskRepository>()); | ||
471 | QAbstractItemModel *model = pageModel.centralListModel(); | ||||
472 | TestHelpers::waitForEmptyJobQueue(); | ||||
473 | QCOMPARE(model->rowCount(), 3); | ||||
486 | 474 | | |||
487 | QAbstractItemModel *model = inbox.centralListModel(); | | |||
488 | const QModelIndex rootTaskIndex = model->index(0, 0); | | |||
489 | FakeErrorHandler errorHandler; | 475 | FakeErrorHandler errorHandler; | ||
490 | inbox.setErrorHandler(&errorHandler); | 476 | pageModel.setErrorHandler(&errorHandler); | ||
477 | const QModelIndex rootTaskIndex = model->index(0, 0); | ||||
478 | | ||||
479 | auto task2 = model->data(model->index(1, 0), Presentation::QueryTreeModelBase::ObjectRole).value<Domain::Task::Ptr>(); | ||||
480 | auto task3 = model->data(model->index(2, 0), Presentation::QueryTreeModelBase::ObjectRole).value<Domain::Task::Ptr>(); | ||||
491 | 481 | | |||
492 | // WHEN | 482 | // WHEN | ||
493 | auto childTask3 = Domain::Task::Ptr::create(); | 483 | data.storageBehavior().setUpdateNextItemError(1, QStringLiteral("Update error")); | ||
494 | childTask3->setTitle(QStringLiteral("childTask3")); | 484 | | ||
495 | auto childTask4 = Domain::Task::Ptr::create(); | 485 | auto mimeData = std::make_unique<QMimeData>(); | ||
496 | auto job = new FakeJob(this); | 486 | mimeData->setData(QStringLiteral("application/x-zanshin-object"), "object"); | ||
497 | job->setExpectedError(KJob::KilledJobError, QStringLiteral("Foo")); | 487 | mimeData->setProperty("objects", QVariant::fromValue(Domain::Task::List() << task2 << task3)); | ||
498 | taskRepositoryMock(&Domain::TaskRepository::associate).when(rootTask, childTask3).thenReturn(job); | 488 | QVERIFY(model->dropMimeData(mimeData.get(), Qt::MoveAction, -1, -1, rootTaskIndex)); | ||
499 | taskRepositoryMock(&Domain::TaskRepository::associate).when(rootTask, childTask4).thenReturn(new FakeJob(this)); | 489 | TestHelpers::waitForEmptyJobQueue(); | ||
500 | auto data = std::make_unique<QMimeData>(); | 490 | | ||
501 | data->setData(QStringLiteral("application/x-zanshin-object"), "object"); | 491 | // THEN | ||
502 | data->setProperty("objects", QVariant::fromValue(Domain::Task::List() << childTask3 << childTask4)); | 492 | QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot move task task2 as sub-task of task1: Update error")); | ||
503 | model->dropMimeData(data.get(), Qt::MoveAction, -1, -1, rootTaskIndex); | 493 | QCOMPARE(model->rowCount(), 2); // One failed, one succeeded | ||
504 | | ||||
505 | // THEN | | |||
506 | QTest::qWait(150); | | |||
507 | QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot move task childTask3 as sub-task of rootTask: Foo")); | | |||
508 | QVERIFY(taskRepositoryMock(&Domain::TaskRepository::associate).when(rootTask, childTask4).exactly(1)); | | |||
509 | } | 494 | } | ||
510 | 495 | | |||
511 | void shouldDeparentWhenNoErrorHappens() | 496 | void shouldDeparentWhenNoErrorHappens() | ||
512 | { | 497 | { | ||
513 | // GIVEN | 498 | // GIVEN | ||
499 | AkonadiFakeData data; | ||||
500 | auto deps = data.createDependencies(); | ||||
501 | Integration::initializeDefaultDomainDependencies(*deps.get()); | ||||
502 | data.createCollection(GenCollection().withId(42).withRootAsParent().withTaskContent()); | ||||
514 | 503 | | |||
515 | // One task, top level | 504 | // One task, top level | ||
516 | auto topLevelTask = Domain::Task::Ptr::create(); | 505 | data.createItem(GenTodo().withId(42).withParent(42).withUid("42").withTitle(QStringLiteral("topLevelTask"))); | ||
517 | topLevelTask->setTitle(QStringLiteral("topLevelTask")); | | |||
518 | auto inboxProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); | | |||
519 | auto inboxResult = Domain::QueryResult<Domain::Task::Ptr>::create(inboxProvider); | | |||
520 | inboxProvider->append(topLevelTask); | | |||
521 | 506 | | |||
522 | // Two tasks under the top level task | 507 | // Two tasks under the top level task | ||
523 | auto childTask = Domain::Task::Ptr::create(); | 508 | data.createItem(GenTodo().withId(43).withParent(42).withUid("43").withParentUid("42").withTitle(QStringLiteral("childTask")).done()); | ||
524 | childTask->setTitle(QStringLiteral("childTask")); | 509 | data.createItem(GenTodo().withId(44).withParent(42).withUid("44").withParentUid("42").withTitle(QStringLiteral("childTask2"))); | ||
525 | childTask->setDone(true); | | |||
526 | auto childTask2 = Domain::Task::Ptr::create(); | | |||
527 | childTask2->setTitle(QStringLiteral("childTask2")); | | |||
528 | childTask2->setDone(false); | | |||
529 | auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create(); | | |||
530 | auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider); | | |||
531 | taskProvider->append(childTask); | | |||
532 | taskProvider->append(childTask2); | | |||
533 | | ||||
534 | Utils::MockObject<Domain::TaskQueries> taskQueriesMock; | | |||
535 | taskQueriesMock(&Domain::TaskQueries::findInboxTopLevel).when().thenReturn(inboxResult); | | |||
536 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(topLevelTask).thenReturn(taskResult); | | |||
537 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(childTask).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); | | |||
538 | taskQueriesMock(&Domain::TaskQueries::findChildren).when(childTask2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr()); | | |||
539 | taskQueriesMock(&Domain::TaskQueries::findDataSource).when(childTask).thenReturn(Domain::QueryResult<Domain::DataSource::Ptr>::Ptr()); | | |||
540 | | ||||
541 | Utils::MockObject<Domain::TaskRepository> taskRepositoryMock; | | |||
542 | 510 | | |||
543 | Presentation::InboxPageModel inbox(taskQueriesMock.getInstance(), | 511 | Presentation::InboxPageModel pageModel(deps->create<Domain::TaskQueries>(), | ||
544 | taskRepositoryMock.getInstance()); | 512 | deps->create<Domain::TaskRepository>()); | ||
513 | QAbstractItemModel *model = pageModel.centralListModel(); | ||||
514 | TestHelpers::waitForEmptyJobQueue(); | ||||
545 | 515 | | |||
546 | QAbstractItemModel *model = inbox.centralListModel(); | | |||
547 | const QModelIndex emptyPartModel = QModelIndex(); // model root, drop on the empty part is equivalent | 516 | const QModelIndex emptyPartModel = QModelIndex(); // model root, drop on the empty part is equivalent | ||
548 | FakeErrorHandler errorHandler; | 517 | FakeErrorHandler errorHandler; | ||
549 | inbox.setErrorHandler(&errorHandler); | 518 | pageModel.setErrorHandler(&errorHandler); | ||
550 | 519 | | |||
551 | // WHEN | 520 | const auto topLevelIndex = model->index(0, 0); | ||
552 | auto job = new FakeJob(this); | 521 | QVERIFY(topLevelIndex.isValid()); | ||
553 | job->setExpectedError(KJob::KilledJobError, QStringLiteral("Foo")); | 522 | const auto childTask = model->data(model->index(0, 0, topLevelIndex), Presentation::QueryTreeModelBase::ObjectRole).value<Domain::Task::Ptr>(); | ||
523 | const auto childTask2 = model->data(model->index(1, 0, topLevelIndex), Presentation::QueryTreeModelBase::ObjectRole).value<Domain::Task::Ptr>(); | ||||
554 | 524 | | |||
555 | taskRepositoryMock(&Domain::TaskRepository::dissociate).when(childTask).thenReturn(job); | 525 | // WHEN | ||
556 | taskRepositoryMock(&Domain::TaskRepository::dissociate).when(childTask2).thenReturn(new FakeJob(this)); | 526 | data.storageBehavior().setUpdateNextItemError(1, QStringLiteral("Deparent error")); | ||
557 | 527 | | |||
558 | auto data = std::make_unique<QMimeData>(); | 528 | auto mimeData = std::make_unique<QMimeData>(); | ||
559 | data->setData(QStringLiteral("application/x-zanshin-object"), "object"); | 529 | mimeData->setData(QStringLiteral("application/x-zanshin-object"), "object"); | ||
560 | data->setProperty("objects", QVariant::fromValue(Domain::Task::List() << childTask << childTask2)); // both will be DnD on the empty part | 530 | mimeData->setProperty("objects", QVariant::fromValue(Domain::Task::List() << childTask << childTask2)); // both will be DnD on the empty part | ||
561 | model->dropMimeData(data.get(), Qt::MoveAction, -1, -1, emptyPartModel); | 531 | QVERIFY(model->dropMimeData(mimeData.get(), Qt::MoveAction, -1, -1, emptyPartModel)); | ||
532 | TestHelpers::waitForEmptyJobQueue(); | ||||
562 | 533 | | |||
563 | // THEN | 534 | // THEN | ||
564 | QTest::qWait(150); | 535 | QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot deparent task childTask from its parent: Deparent error")); | ||
565 | QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot deparent task childTask from its parent: Foo")); | 536 | QCOMPARE(model->rowCount(), 2); // One failed, one succeeded | ||
566 | QVERIFY(taskRepositoryMock(&Domain::TaskRepository::dissociate).when(childTask).exactly(1)); | | |||
567 | QVERIFY(taskRepositoryMock(&Domain::TaskRepository::dissociate).when(childTask2).exactly(1)); | | |||
568 | } | 537 | } | ||
569 | }; | 538 | }; | ||
570 | 539 | | |||
571 | ZANSHIN_TEST_MAIN(InboxPageModelTest) | 540 | ZANSHIN_TEST_MAIN(InboxPageModelTest) | ||
572 | 541 | | |||
573 | #include "inboxpagemodeltest.moc" | 542 | #include "inboxpagemodeltest.moc" |