File indexing completed on 2025-01-19 04:56:56

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Kevin Ottens <ervin@kde.org>
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 "utils/mockobject.h"
0014 
0015 #include "presentation/projectpagemodel.h"
0016 #include "presentation/errorhandler.h"
0017 
0018 #include "testlib/fakejob.h"
0019 
0020 using namespace mockitopp;
0021 using namespace mockitopp::matcher;
0022 
0023 class FakeErrorHandler : public Presentation::ErrorHandler
0024 {
0025 public:
0026     void doDisplayMessage(const QString &message) override
0027     {
0028         m_message = message;
0029     }
0030 
0031     QString m_message;
0032 };
0033 
0034 class ProjectPageModelTest : public QObject
0035 {
0036     Q_OBJECT
0037 private slots:
0038     void shouldListProjectInCentralListModel()
0039     {
0040         // GIVEN
0041 
0042         // One project
0043         auto project = Domain::Project::Ptr::create();
0044 
0045         // One task
0046         auto rootTask = Domain::Task::Ptr::create();
0047         rootTask->setTitle(QStringLiteral("rootTask"));
0048         auto topLevelProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create();
0049         auto topLevelResult = Domain::QueryResult<Domain::Task::Ptr>::create(topLevelProvider);
0050         topLevelProvider->append(rootTask);
0051 
0052         // One task under the root task
0053         auto childTask = Domain::Task::Ptr::create();
0054         childTask->setTitle(QStringLiteral("childTask"));
0055         childTask->setDone(true);
0056         auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create();
0057         auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider);
0058         taskProvider->append(childTask);
0059 
0060         Utils::MockObject<Domain::ProjectQueries> projectQueriesMock;
0061         projectQueriesMock(&Domain::ProjectQueries::findTopLevel).when(project).thenReturn(topLevelResult);
0062 
0063         Utils::MockObject<Domain::ProjectRepository> projectRepositoryMock;
0064 
0065         Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
0066         taskQueriesMock(&Domain::TaskQueries::findChildren).when(rootTask).thenReturn(taskResult);
0067         taskQueriesMock(&Domain::TaskQueries::findChildren).when(childTask).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0068 
0069         Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
0070 
0071         Presentation::ProjectPageModel page(project,
0072                                             projectQueriesMock.getInstance(),
0073                                             projectRepositoryMock.getInstance(),
0074                                             taskQueriesMock.getInstance(),
0075                                             taskRepositoryMock.getInstance());
0076 
0077         // WHEN
0078         QAbstractItemModel *model = page.centralListModel();
0079 
0080         // THEN
0081         const QModelIndex rootTaskIndex = model->index(0, 0);
0082         const QModelIndex childTaskIndex = model->index(0, 0, rootTaskIndex);
0083 
0084         QCOMPARE(page.project(), project);
0085 
0086         QCOMPARE(model->rowCount(), 1);
0087         QCOMPARE(model->rowCount(rootTaskIndex), 1);
0088         QCOMPARE(model->rowCount(childTaskIndex), 0);
0089 
0090         const Qt::ItemFlags defaultFlags = Qt::ItemIsSelectable
0091                                          | Qt::ItemIsEnabled
0092                                          | Qt::ItemIsEditable
0093                                          | Qt::ItemIsDragEnabled
0094                                          | Qt::ItemIsUserCheckable
0095                                          | Qt::ItemIsDropEnabled;
0096         QCOMPARE(model->flags(rootTaskIndex), defaultFlags);
0097         QCOMPARE(model->flags(childTaskIndex), defaultFlags);
0098 
0099         QCOMPARE(model->data(rootTaskIndex).toString(), rootTask->title());
0100         QCOMPARE(model->data(childTaskIndex).toString(), childTask->title());
0101 
0102         QCOMPARE(model->data(rootTaskIndex, Qt::EditRole).toString(), rootTask->title());
0103         QCOMPARE(model->data(childTaskIndex, Qt::EditRole).toString(), childTask->title());
0104 
0105         QVERIFY(model->data(rootTaskIndex, Qt::CheckStateRole).isValid());
0106         QVERIFY(model->data(childTaskIndex, Qt::CheckStateRole).isValid());
0107 
0108         QCOMPARE(model->data(rootTaskIndex, Qt::CheckStateRole).toBool(), rootTask->isDone());
0109         QCOMPARE(model->data(childTaskIndex, Qt::CheckStateRole).toBool(), childTask->isDone());
0110 
0111         // WHEN
0112         taskRepositoryMock(&Domain::TaskRepository::update).when(rootTask).thenReturn(new FakeJob(this));
0113         taskRepositoryMock(&Domain::TaskRepository::update).when(childTask).thenReturn(new FakeJob(this));
0114 
0115         QVERIFY(model->setData(rootTaskIndex, "newRootTask"));
0116         QVERIFY(model->setData(childTaskIndex, "newChildTask"));
0117 
0118         QVERIFY(model->setData(rootTaskIndex, Qt::Checked, Qt::CheckStateRole));
0119         QVERIFY(model->setData(childTaskIndex, Qt::Unchecked, Qt::CheckStateRole));
0120 
0121         // THEN
0122         QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(rootTask).exactly(2));
0123         QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(childTask).exactly(2));
0124 
0125         QCOMPARE(rootTask->title(), QStringLiteral("newRootTask"));
0126         QCOMPARE(childTask->title(), QStringLiteral("newChildTask"));
0127 
0128         QCOMPARE(rootTask->isDone(), true);
0129         QCOMPARE(childTask->isDone(), false);
0130 
0131         // WHEN
0132         auto data = std::unique_ptr<QMimeData>(model->mimeData(QModelIndexList() << childTaskIndex));
0133 
0134         // THEN
0135         QVERIFY(data->hasFormat(QStringLiteral("application/x-zanshin-object")));
0136         QCOMPARE(data->property("objects").value<Domain::Task::List>(),
0137                  Domain::Task::List() << childTask);
0138 
0139         // WHEN
0140         auto childTask2 = Domain::Task::Ptr::create();
0141         taskRepositoryMock(&Domain::TaskRepository::associate).when(rootTask, childTask2).thenReturn(new FakeJob(this));
0142         data.reset(new QMimeData);
0143         data->setData(QStringLiteral("application/x-zanshin-object"), "object");
0144         data->setProperty("objects", QVariant::fromValue(Domain::Task::List() << childTask2));
0145         model->dropMimeData(data.get(), Qt::MoveAction, -1, -1, rootTaskIndex);
0146 
0147         // THEN
0148         QVERIFY(taskRepositoryMock(&Domain::TaskRepository::associate).when(rootTask, childTask2).exactly(1));
0149 
0150 
0151         // WHEN
0152         auto childTask3 = Domain::Task::Ptr::create();
0153         auto childTask4 = Domain::Task::Ptr::create();
0154         taskRepositoryMock(&Domain::TaskRepository::associate).when(rootTask, childTask3).thenReturn(new FakeJob(this));
0155         taskRepositoryMock(&Domain::TaskRepository::associate).when(rootTask, childTask4).thenReturn(new FakeJob(this));
0156         data.reset(new QMimeData);
0157         data->setData(QStringLiteral("application/x-zanshin-object"), "object");
0158         data->setProperty("objects", QVariant::fromValue(Domain::Task::List() << childTask3 << childTask4));
0159         model->dropMimeData(data.get(), Qt::MoveAction, -1, -1, rootTaskIndex);
0160 
0161         // THEN
0162         QVERIFY(taskRepositoryMock(&Domain::TaskRepository::associate).when(rootTask, childTask3).exactly(1));
0163         QVERIFY(taskRepositoryMock(&Domain::TaskRepository::associate).when(rootTask, childTask4).exactly(1));
0164     }
0165 
0166     void shouldAddTasksInProject()
0167     {
0168         // GIVEN
0169 
0170         // One project
0171         auto project = Domain::Project::Ptr::create();
0172 
0173         // ... in fact we won't list any model
0174         Utils::MockObject<Domain::ProjectQueries> projectQueriesMock;
0175         Utils::MockObject<Domain::ProjectRepository> projectRepositoryMock;
0176         Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
0177 
0178         // We'll gladly create a task though
0179         Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
0180         taskRepositoryMock(&Domain::TaskRepository::createInProject).when(any<Domain::Task::Ptr>(),
0181                                                                           any<Domain::Project::Ptr>())
0182                                                                     .thenReturn(new FakeJob(this));
0183 
0184         Presentation::ProjectPageModel page(project,
0185                                             projectQueriesMock.getInstance(),
0186                                             projectRepositoryMock.getInstance(),
0187                                             taskQueriesMock.getInstance(),
0188                                             taskRepositoryMock.getInstance());
0189 
0190         // WHEN
0191         auto title = QStringLiteral("New task");
0192         auto task = page.addItem(title);
0193 
0194         // THEN
0195         QVERIFY(taskRepositoryMock(&Domain::TaskRepository::createInProject).when(any<Domain::Task::Ptr>(),
0196                                                                                   any<Domain::Project::Ptr>())
0197                                                                             .exactly(1));
0198         QVERIFY(task);
0199         QCOMPARE(task->title(), title);
0200     }
0201 
0202     void shouldAddChildTask()
0203     {
0204         // GIVEN
0205 
0206         // One project
0207         auto project = Domain::Project::Ptr::create();
0208 
0209         // Two tasks
0210         auto task1 = Domain::Task::Ptr::create();
0211         auto task2 = Domain::Task::Ptr::create();
0212         auto topLevelProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create();
0213         auto topLevelResult = Domain::QueryResult<Domain::Task::Ptr>::create(topLevelProvider);
0214         topLevelProvider->append(task1);
0215         topLevelProvider->append(task2);
0216 
0217         Utils::MockObject<Domain::ProjectQueries> projectQueriesMock;
0218         projectQueriesMock(&Domain::ProjectQueries::findTopLevel).when(project).thenReturn(topLevelResult);
0219 
0220         Utils::MockObject<Domain::ProjectRepository> projectRepositoryMock;
0221 
0222         Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
0223         taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0224         taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0225 
0226         Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
0227         taskRepositoryMock(&Domain::TaskRepository::createChild).when(any<Domain::Task::Ptr>(),
0228                                                                       any<Domain::Task::Ptr>())
0229                                                                 .thenReturn(new FakeJob(this));
0230 
0231         Presentation::ProjectPageModel page(project,
0232                                             projectQueriesMock.getInstance(),
0233                                             projectRepositoryMock.getInstance(),
0234                                             taskQueriesMock.getInstance(),
0235                                             taskRepositoryMock.getInstance());
0236 
0237         // WHEN
0238         const auto title = QStringLiteral("New task");
0239         const auto parentIndex = page.centralListModel()->index(0, 0);
0240         const auto createdTask = page.addItem(title, parentIndex);
0241 
0242         // THEN
0243         QVERIFY(taskRepositoryMock(&Domain::TaskRepository::createChild).when(any<Domain::Task::Ptr>(),
0244                                                                               any<Domain::Task::Ptr>())
0245                                                                         .exactly(1));
0246         QVERIFY(createdTask);
0247         QCOMPARE(createdTask->title(), title);
0248     }
0249 
0250     void shouldGetAnErrorMessageWhenAddTaskFailed()
0251     {
0252         // GIVEN
0253 
0254         // One project
0255         auto project = Domain::Project::Ptr::create();
0256         project->setName(QStringLiteral("Project1"));
0257 
0258         // ... in fact we won't list any model
0259         Utils::MockObject<Domain::ProjectQueries> projectQueriesMock;
0260         Utils::MockObject<Domain::ProjectRepository> projectRepositoryMock;
0261         Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
0262 
0263         // We'll gladly create a task though
0264         Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
0265         auto job = new FakeJob(this);
0266         job->setExpectedError(KJob::KilledJobError, QStringLiteral("Foo"));
0267         taskRepositoryMock(&Domain::TaskRepository::createInProject).when(any<Domain::Task::Ptr>(),
0268                                                                           any<Domain::Project::Ptr>())
0269                                                                     .thenReturn(job);
0270 
0271         Presentation::ProjectPageModel page(project,
0272                                             projectQueriesMock.getInstance(),
0273                                             projectRepositoryMock.getInstance(),
0274                                             taskQueriesMock.getInstance(),
0275                                             taskRepositoryMock.getInstance());
0276         FakeErrorHandler errorHandler;
0277         page.setErrorHandler(&errorHandler);
0278 
0279         // WHEN
0280         page.addItem(QStringLiteral("New task"));
0281 
0282         // THEN
0283         QTest::qWait(150);
0284         QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot add task New task in project Project1: Foo"));
0285     }
0286 
0287     void shouldDeleteItems()
0288     {
0289         // GIVEN
0290 
0291         // One project
0292         auto project = Domain::Project::Ptr::create();
0293 
0294         // Two tasks
0295         auto task1 = Domain::Task::Ptr::create();
0296         auto task2 = Domain::Task::Ptr::create();
0297         auto topLevelProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create();
0298         auto topLevelResult = Domain::QueryResult<Domain::Task::Ptr>::create(topLevelProvider);
0299         topLevelProvider->append(task1);
0300         topLevelProvider->append(task2);
0301 
0302         Utils::MockObject<Domain::ProjectQueries> projectQueriesMock;
0303         projectQueriesMock(&Domain::ProjectQueries::findTopLevel).when(project).thenReturn(topLevelResult);
0304 
0305         Utils::MockObject<Domain::ProjectRepository> projectRepositoryMock;
0306 
0307         Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
0308         taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0309         taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0310 
0311         Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
0312         taskRepositoryMock(&Domain::TaskRepository::remove).when(task2).thenReturn(new FakeJob(this));
0313 
0314         Presentation::ProjectPageModel page(project,
0315                                             projectQueriesMock.getInstance(),
0316                                             projectRepositoryMock.getInstance(),
0317                                             taskQueriesMock.getInstance(),
0318                                             taskRepositoryMock.getInstance());
0319 
0320         // WHEN
0321         const QModelIndex index = page.centralListModel()->index(1, 0);
0322         page.removeItem(index);
0323 
0324         // THEN
0325         QVERIFY(taskRepositoryMock(&Domain::TaskRepository::remove).when(task2).exactly(1));
0326     }
0327 
0328     void shouldGetAnErrorMessageWhenDeleteItemsFailed()
0329     {
0330         // GIVEN
0331 
0332         // One project
0333         auto project = Domain::Project::Ptr::create();
0334         project->setName(QStringLiteral("Project1"));
0335 
0336         // Two tasks
0337         auto task1 = Domain::Task::Ptr::create();
0338         auto task2 = Domain::Task::Ptr::create();
0339         task2->setTitle(QStringLiteral("Task2"));
0340         auto topLevelProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create();
0341         auto topLevelResult = Domain::QueryResult<Domain::Task::Ptr>::create(topLevelProvider);
0342         topLevelProvider->append(task1);
0343         topLevelProvider->append(task2);
0344 
0345         Utils::MockObject<Domain::ProjectQueries> projectQueriesMock;
0346         projectQueriesMock(&Domain::ProjectQueries::findTopLevel).when(project).thenReturn(topLevelResult);
0347 
0348         Utils::MockObject<Domain::ProjectRepository> projectRepositoryMock;
0349 
0350         Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
0351         taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0352         taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0353 
0354         Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
0355         auto job = new FakeJob(this);
0356         job->setExpectedError(KJob::KilledJobError, QStringLiteral("Foo"));
0357         taskRepositoryMock(&Domain::TaskRepository::remove).when(task2).thenReturn(job);
0358 
0359         Presentation::ProjectPageModel page(project,
0360                                             projectQueriesMock.getInstance(),
0361                                             projectRepositoryMock.getInstance(),
0362                                             taskQueriesMock.getInstance(),
0363                                             taskRepositoryMock.getInstance());
0364         FakeErrorHandler errorHandler;
0365         page.setErrorHandler(&errorHandler);
0366 
0367         // WHEN
0368         const QModelIndex index = page.centralListModel()->index(1, 0);
0369         page.removeItem(index);
0370 
0371         // THEN
0372         QTest::qWait(150);
0373         QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot remove task Task2 from project Project1: Foo"));
0374     }
0375 
0376     void shouldPromoteItem()
0377     {
0378         // GIVEN
0379 
0380         // One project
0381         auto project = Domain::Project::Ptr::create();
0382 
0383         // Two tasks
0384         auto task1 = Domain::Task::Ptr::create();
0385         auto task2 = Domain::Task::Ptr::create();
0386         auto topLevelProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create();
0387         auto topLevelResult = Domain::QueryResult<Domain::Task::Ptr>::create(topLevelProvider);
0388         topLevelProvider->append(task1);
0389         topLevelProvider->append(task2);
0390 
0391         Utils::MockObject<Domain::ProjectQueries> projectQueriesMock;
0392         projectQueriesMock(&Domain::ProjectQueries::findTopLevel).when(project).thenReturn(topLevelResult);
0393 
0394         Utils::MockObject<Domain::ProjectRepository> projectRepositoryMock;
0395 
0396         Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
0397         taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0398         taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0399 
0400         Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
0401         taskRepositoryMock(&Domain::TaskRepository::promoteToProject).when(task2).thenReturn(new FakeJob(this));
0402 
0403         Presentation::ProjectPageModel page(project,
0404                                             projectQueriesMock.getInstance(),
0405                                             projectRepositoryMock.getInstance(),
0406                                             taskQueriesMock.getInstance(),
0407                                             taskRepositoryMock.getInstance());
0408 
0409         // WHEN
0410         const QModelIndex index = page.centralListModel()->index(1, 0);
0411         page.promoteItem(index);
0412 
0413         // THEN
0414         QVERIFY(taskRepositoryMock(&Domain::TaskRepository::promoteToProject).when(task2).exactly(1));
0415     }
0416 
0417     void shouldGetAnErrorMessageWhenPromoteItemFailed()
0418     {
0419         // GIVEN
0420 
0421         // One project
0422         auto project = Domain::Project::Ptr::create();
0423         project->setName(QStringLiteral("Project1"));
0424 
0425         // Two tasks
0426         auto task1 = Domain::Task::Ptr::create();
0427         auto task2 = Domain::Task::Ptr::create();
0428         task2->setTitle(QStringLiteral("Task2"));
0429         auto topLevelProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create();
0430         auto topLevelResult = Domain::QueryResult<Domain::Task::Ptr>::create(topLevelProvider);
0431         topLevelProvider->append(task1);
0432         topLevelProvider->append(task2);
0433 
0434         Utils::MockObject<Domain::ProjectQueries> projectQueriesMock;
0435         projectQueriesMock(&Domain::ProjectQueries::findTopLevel).when(project).thenReturn(topLevelResult);
0436 
0437         Utils::MockObject<Domain::ProjectRepository> projectRepositoryMock;
0438 
0439         Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
0440         taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0441         taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0442 
0443         Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
0444         auto job = new FakeJob(this);
0445         job->setExpectedError(KJob::KilledJobError, QStringLiteral("Foo"));
0446         taskRepositoryMock(&Domain::TaskRepository::promoteToProject).when(task2).thenReturn(job);
0447 
0448         Presentation::ProjectPageModel page(project,
0449                                             projectQueriesMock.getInstance(),
0450                                             projectRepositoryMock.getInstance(),
0451                                             taskQueriesMock.getInstance(),
0452                                             taskRepositoryMock.getInstance());
0453         FakeErrorHandler errorHandler;
0454         page.setErrorHandler(&errorHandler);
0455 
0456         // WHEN
0457         const QModelIndex index = page.centralListModel()->index(1, 0);
0458         page.promoteItem(index);
0459 
0460         // THEN
0461         QTest::qWait(150);
0462         QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot promote task Task2 to be a project: Foo"));
0463     }
0464 
0465     void shouldGetAnErrorMessageWhenUpdateTaskFailed()
0466     {
0467         // GIVEN
0468 
0469         // One project
0470         auto project = Domain::Project::Ptr::create();
0471         project->setName(QStringLiteral("Project1"));
0472 
0473         // One task
0474         auto rootTask = Domain::Task::Ptr::create();
0475         rootTask->setTitle(QStringLiteral("rootTask"));
0476         auto topLevelProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create();
0477         auto topLevelResult = Domain::QueryResult<Domain::Task::Ptr>::create(topLevelProvider);
0478         topLevelProvider->append(rootTask);
0479 
0480         Utils::MockObject<Domain::ProjectQueries> projectQueriesMock;
0481         projectQueriesMock(&Domain::ProjectQueries::findTopLevel).when(project).thenReturn(topLevelResult);
0482 
0483         Utils::MockObject<Domain::ProjectRepository> projectRepositoryMock;
0484 
0485         Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
0486         taskQueriesMock(&Domain::TaskQueries::findChildren).when(rootTask).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0487 
0488         Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
0489 
0490         Presentation::ProjectPageModel page(project,
0491                                             projectQueriesMock.getInstance(),
0492                                             projectRepositoryMock.getInstance(),
0493                                             taskQueriesMock.getInstance(),
0494                                             taskRepositoryMock.getInstance());
0495 
0496         QAbstractItemModel *model = page.centralListModel();
0497         const QModelIndex rootTaskIndex = model->index(0, 0);
0498         FakeErrorHandler errorHandler;
0499         page.setErrorHandler(&errorHandler);
0500 
0501         // WHEN
0502         auto job = new FakeJob(this);
0503         job->setExpectedError(KJob::KilledJobError, QStringLiteral("Foo"));
0504         taskRepositoryMock(&Domain::TaskRepository::update).when(rootTask).thenReturn(job);
0505 
0506         QVERIFY(model->setData(rootTaskIndex, "newRootTask"));
0507 
0508         // THEN
0509         QTest::qWait(150);
0510         QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot modify task rootTask in project Project1: Foo"));
0511     }
0512 
0513     void shouldGetAnErrorMessageWhenAssociateTaskFailed()
0514     {
0515         // GIVEN
0516 
0517         // One project
0518         auto project = Domain::Project::Ptr::create();
0519         project->setName(QStringLiteral("Project1"));
0520 
0521         // One task
0522         auto rootTask = Domain::Task::Ptr::create();
0523         rootTask->setTitle(QStringLiteral("rootTask"));
0524         auto topLevelProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create();
0525         auto topLevelResult = Domain::QueryResult<Domain::Task::Ptr>::create(topLevelProvider);
0526         topLevelProvider->append(rootTask);
0527 
0528         Utils::MockObject<Domain::ProjectQueries> projectQueriesMock;
0529         projectQueriesMock(&Domain::ProjectQueries::findTopLevel).when(project).thenReturn(topLevelResult);
0530 
0531         Utils::MockObject<Domain::ProjectRepository> projectRepositoryMock;
0532 
0533         Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
0534         taskQueriesMock(&Domain::TaskQueries::findChildren).when(rootTask).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0535 
0536         Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
0537 
0538         Presentation::ProjectPageModel page(project,
0539                                             projectQueriesMock.getInstance(),
0540                                             projectRepositoryMock.getInstance(),
0541                                             taskQueriesMock.getInstance(),
0542                                             taskRepositoryMock.getInstance());
0543 
0544         QAbstractItemModel *model = page.centralListModel();
0545         const QModelIndex rootTaskIndex = model->index(0, 0);
0546         FakeErrorHandler errorHandler;
0547         page.setErrorHandler(&errorHandler);
0548 
0549         // WHEN
0550         auto childTask3 = Domain::Task::Ptr::create();
0551         childTask3->setTitle(QStringLiteral("childTask3"));
0552         auto childTask4 = Domain::Task::Ptr::create();
0553         auto job = new FakeJob(this);
0554         job->setExpectedError(KJob::KilledJobError, QStringLiteral("Foo"));
0555         taskRepositoryMock(&Domain::TaskRepository::associate).when(rootTask, childTask3).thenReturn(job);
0556         taskRepositoryMock(&Domain::TaskRepository::associate).when(rootTask, childTask4).thenReturn(new FakeJob(this));
0557         auto data = std::make_unique<QMimeData>();
0558         data->setData(QStringLiteral("application/x-zanshin-object"), "object");
0559         data->setProperty("objects", QVariant::fromValue(Domain::Task::List() << childTask3 << childTask4));
0560         model->dropMimeData(data.get(), Qt::MoveAction, -1, -1, rootTaskIndex);
0561 
0562         // THEN
0563         QTest::qWait(150);
0564         QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot move task childTask3 as a sub-task of rootTask: Foo"));
0565         QVERIFY(taskRepositoryMock(&Domain::TaskRepository::associate).when(rootTask, childTask4).exactly(1));
0566     }
0567 
0568     void shouldAssociateToProjectWhenDroppingOnEmptyArea()
0569     {
0570         // GIVEN
0571 
0572         // One project
0573         auto project = Domain::Project::Ptr::create();
0574         project->setName(QStringLiteral("Project"));
0575 
0576         // One top level task
0577         auto topLevelTask = Domain::Task::Ptr::create();
0578         topLevelTask->setTitle(QStringLiteral("rootTask"));
0579         auto topLevelProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create();
0580         auto topLevelResult = Domain::QueryResult<Domain::Task::Ptr>::create(topLevelProvider);
0581         topLevelProvider->append(topLevelTask);
0582 
0583         // Two tasks under the top level task
0584         auto childTask1 = Domain::Task::Ptr::create();
0585         childTask1->setTitle(QStringLiteral("childTask1"));
0586         childTask1->setDone(true);
0587         auto childTask2 = Domain::Task::Ptr::create();
0588         childTask2->setTitle(QStringLiteral("childTask2"));
0589         childTask2->setDone(false);
0590         auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create();
0591         auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider);
0592         taskProvider->append(childTask1);
0593         taskProvider->append(childTask2);
0594 
0595         Utils::MockObject<Domain::ProjectQueries> projectQueriesMock;
0596         projectQueriesMock(&Domain::ProjectQueries::findTopLevel).when(project).thenReturn(topLevelResult);
0597 
0598         Utils::MockObject<Domain::ProjectRepository> projectRepositoryMock;
0599 
0600         Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
0601         taskQueriesMock(&Domain::TaskQueries::findChildren).when(topLevelTask).thenReturn(taskResult);
0602         taskQueriesMock(&Domain::TaskQueries::findChildren).when(childTask1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0603         taskQueriesMock(&Domain::TaskQueries::findChildren).when(childTask2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
0604 
0605         Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
0606 
0607         Presentation::ProjectPageModel page(project,
0608                                             projectQueriesMock.getInstance(),
0609                                             projectRepositoryMock.getInstance(),
0610                                             taskQueriesMock.getInstance(),
0611                                             taskRepositoryMock.getInstance());
0612 
0613         auto model = page.centralListModel();
0614 
0615         // WHEN
0616         projectRepositoryMock(&Domain::ProjectRepository::associate).when(project, childTask1).thenReturn(new FakeJob(this));
0617         projectRepositoryMock(&Domain::ProjectRepository::associate).when(project, childTask2).thenReturn(new FakeJob(this));
0618 
0619         auto data = std::make_unique<QMimeData>();
0620         data->setData(QStringLiteral("application/x-zanshin-object"), "object");
0621         data->setProperty("objects", QVariant::fromValue(Domain::Task::List() << childTask1 << childTask2)); // both will be DnD on the empty part
0622         model->dropMimeData(data.get(), Qt::MoveAction, -1, -1, QModelIndex());
0623 
0624         // THEN
0625         QTest::qWait(150);
0626         QVERIFY(projectRepositoryMock(&Domain::ProjectRepository::associate).when(project, childTask1).exactly(1));
0627         QVERIFY(projectRepositoryMock(&Domain::ProjectRepository::associate).when(project, childTask2).exactly(1));
0628     }
0629 };
0630 
0631 ZANSHIN_TEST_MAIN(ProjectPageModelTest)
0632 
0633 #include "projectpagemodeltest.moc"