void shouldRemoveANote()
    {
        // GIVEN
        Akonadi::Item item(42);
        Domain::Note::Ptr note(new Domain::Note);

        // A mock delete job
        auto itemDeleteJob = new FakeJob(this);

        // Storage mock returning the delete job
        Utils::MockObject<Akonadi::StorageInterface> storageMock;
        storageMock(&Akonadi::StorageInterface::removeItem).when(item)
                                                           .thenReturn(itemDeleteJob);

        // Serializer mock returning the item for the note
        Utils::MockObject<Akonadi::SerializerInterface> serializerMock;
        serializerMock(&Akonadi::SerializerInterface::createItemFromNote).when(note).thenReturn(item);

        // WHEN
        QScopedPointer<Akonadi::NoteRepository> repository(new Akonadi::NoteRepository(storageMock.getInstance(),
                                                                                       serializerMock.getInstance()));
        repository->remove(note)->exec();

        // THEN
        QVERIFY(serializerMock(&Akonadi::SerializerInterface::createItemFromNote).when(note).exactly(1));
        QVERIFY(storageMock(&Akonadi::StorageInterface::removeItem).when(item).exactly(1));
    }
    void shouldNoticeIfSourceIsNotDefault()
    {
        // GIVEN

        // A default collection for saving
        Akonadi::Collection defaultCol(42);
        Akonadi::StorageSettings::instance().setDefaultNoteCollection(defaultCol);

        // Another random collection
        Akonadi::Collection col(43);

        // The data source corresponding to the random collection
        auto source = Domain::DataSource::Ptr::create();

        // Storage mock sitting here doing nothing
        Utils::MockObject<Akonadi::StorageInterface> storageMock;

        // Serializer mock returning the collection for the source
        Utils::MockObject<Akonadi::SerializerInterface> serializerMock;
        serializerMock(&Akonadi::SerializerInterface::createCollectionFromDataSource).when(source).thenReturn(col);

        // WHEN
        QScopedPointer<Akonadi::NoteRepository> repository(new Akonadi::NoteRepository(storageMock.getInstance(),
                                                                                       serializerMock.getInstance()));

        // THEN
        QVERIFY(!repository->isDefaultSource(source));
        QVERIFY(serializerMock(&Akonadi::SerializerInterface::createCollectionFromDataSource).when(source).exactly(1));
    }
    void shouldStoreDefaultSourceInTheSettings()
    {
        // GIVEN

        // A value in the settings
        auto &settings = Akonadi::StorageSettings::instance();
        settings.setDefaultNoteCollection(Akonadi::Collection(21));

        // The new default data source we want
        auto source = Domain::DataSource::Ptr::create();

        // A collection corresponding to the data source
        Akonadi::Collection col(42);

        // Storage mock sitting here doing nothing
        Utils::MockObject<Akonadi::StorageInterface> storageMock;

        // Serializer mock returning the collection for the source
        Utils::MockObject<Akonadi::SerializerInterface> serializerMock;
        serializerMock(&Akonadi::SerializerInterface::createCollectionFromDataSource).when(source).thenReturn(col);

        // WHEN
        QScopedPointer<Akonadi::NoteRepository> repository(new Akonadi::NoteRepository(storageMock.getInstance(),
                                                                                       serializerMock.getInstance()));
        repository->setDefaultSource(source);

        // THEN
        QCOMPARE(settings.defaultNoteCollection(), col);
        QVERIFY(serializerMock(&Akonadi::SerializerInterface::createCollectionFromDataSource).when(source).exactly(1));
    }
    void shouldUpdateExistingItemsOnSave()
    {
        // GIVEN

        // A default collection for saving
        Akonadi::Collection col(42);

        // A note and its corresponding item already existing in storage
        Akonadi::Item item(42);
        Domain::Note::Ptr note(new Domain::Note);

        // A mock create job
        auto itemModifyJob = new FakeJob(this);

        // Storage mock returning the create job
        Utils::MockObject<Akonadi::StorageInterface> storageMock;
        storageMock(&Akonadi::StorageInterface::updateItem).when(item, Q_NULLPTR)
                                                           .thenReturn(itemModifyJob);

        // Serializer mock returning the item for the note
        Utils::MockObject<Akonadi::SerializerInterface> serializerMock;
        serializerMock(&Akonadi::SerializerInterface::createItemFromNote).when(note).thenReturn(item);

        // WHEN
        QScopedPointer<Akonadi::NoteRepository> repository(new Akonadi::NoteRepository(storageMock.getInstance(),
                                                                                       serializerMock.getInstance()));
        repository->save(note)->exec();

        // THEN
        QVERIFY(serializerMock(&Akonadi::SerializerInterface::createItemFromNote).when(note).exactly(1));
        QVERIFY(storageMock(&Akonadi::StorageInterface::updateItem).when(item, Q_NULLPTR).exactly(1));
    }
Ejemplo n.º 5
0
    void shouldUpdateExistingProject()
    {
        // GIVEN

        // A project and its corresponding item already existing in storage
        Akonadi::Item item(42);
        Domain::Project::Ptr project(new Domain::Project);

        // A mock modify job
        auto itemModifyJob = new FakeJob(this);

        // Storage mock returning the create job
        Utils::MockObject<Akonadi::StorageInterface> storageMock;
        storageMock(&Akonadi::StorageInterface::updateItem).when(item, Q_NULLPTR)
                                                           .thenReturn(itemModifyJob);

        // Serializer mock returning the item for the project
        Utils::MockObject<Akonadi::SerializerInterface> serializerMock;
        serializerMock(&Akonadi::SerializerInterface::createItemFromProject).when(project).thenReturn(item);

        // WHEN
        QScopedPointer<Akonadi::ProjectRepository> repository(new Akonadi::ProjectRepository(storageMock.getInstance(),
                                                                                             serializerMock.getInstance()));
        repository->update(project)->exec();

        // THEN
        QVERIFY(serializerMock(&Akonadi::SerializerInterface::createItemFromProject).when(project).exactly(1));
        QVERIFY(storageMock(&Akonadi::StorageInterface::updateItem).when(item, Q_NULLPTR).exactly(1));
    }
Ejemplo n.º 6
0
    void shouldRemoveItem()
    {
        // GIVEN

        // One domain tag
        auto tag = Domain::Tag::Ptr::create();

        // Two tasks
        Domain::Artifact::Ptr task1(new Domain::Task);
        Domain::Artifact::Ptr task2(new Domain::Task);
        Domain::Artifact::Ptr note(new Domain::Note);

        auto artifactProvider = Domain::QueryResultProvider<Domain::Artifact::Ptr>::Ptr::create();
        auto artifactResult = Domain::QueryResult<Domain::Artifact::Ptr>::create(artifactProvider);
        artifactProvider->append(task1);
        artifactProvider->append(task2);
        artifactProvider->append(note);

        Utils::MockObject<Domain::TagQueries> tagQueriesMock;
        tagQueriesMock(&Domain::TagQueries::findTopLevelArtifacts).when(tag).thenReturn(artifactResult);

        Utils::MockObject<Domain::TagRepository> tagRepositoryMock;
        tagRepositoryMock(&Domain::TagRepository::dissociate).when(tag, task2).thenReturn(new FakeJob(this));
        tagRepositoryMock(&Domain::TagRepository::dissociate).when(tag, note).thenReturn(new FakeJob(this));

        Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
        taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1.dynamicCast<Domain::Task>()).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
        taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2.dynamicCast<Domain::Task>()).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());

        Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
        Utils::MockObject<Domain::NoteRepository> noteRepositoryMock;

        Presentation::TagPageModel page(tag,
                                        tagQueriesMock.getInstance(),
                                        tagRepositoryMock.getInstance(),
                                        taskQueriesMock.getInstance(),
                                        taskRepositoryMock.getInstance(),
                                        noteRepositoryMock.getInstance());

        // WHEN
        const QModelIndex indexTask2 = page.centralListModel()->index(1, 0);
        page.removeItem(indexTask2);

        // THEN
        QVERIFY(tagRepositoryMock(&Domain::TagRepository::dissociate).when(tag, task2).exactly(1));

        // WHEN
        const QModelIndex indexNote = page.centralListModel()->index(2, 0);
        page.removeItem(indexNote);

        // THEN
        QVERIFY(tagRepositoryMock(&Domain::TagRepository::dissociate).when(tag, note).exactly(1));
    }
Ejemplo n.º 7
0
    void shouldGetAnErrorMessageWhenUpdateTaskFailed()
    {
        // GIVEN

        // One Tag
        auto tag = Domain::Tag::Ptr::create();
        tag->setName("Tag1");

        // One note and one task
        auto rootTask = Domain::Task::Ptr::create();
        rootTask->setTitle("rootTask");
        auto artifactProvider = Domain::QueryResultProvider<Domain::Artifact::Ptr>::Ptr::create();
        auto artifactResult = Domain::QueryResult<Domain::Artifact::Ptr>::create(artifactProvider);
        artifactProvider->append(rootTask);

        Utils::MockObject<Domain::TagQueries> tagQueriesMock;
        tagQueriesMock(&Domain::TagQueries::findTopLevelArtifacts).when(tag).thenReturn(artifactResult);

        Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
        taskQueriesMock(&Domain::TaskQueries::findChildren).when(rootTask).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());

        Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
        Utils::MockObject<Domain::NoteRepository> noteRepositoryMock;
        Utils::MockObject<Domain::TagRepository> tagRepositoryMock;

        Presentation::TagPageModel page(tag,
                                        tagQueriesMock.getInstance(),
                                        tagRepositoryMock.getInstance(),
                                        taskQueriesMock.getInstance(),
                                        taskRepositoryMock.getInstance(),
                                        noteRepositoryMock.getInstance());

        QAbstractItemModel *model = page.centralListModel();
        const QModelIndex rootTaskIndex = model->index(0, 0);
        FakeErrorHandler errorHandler;
        page.setErrorHandler(&errorHandler);

        // WHEN
        auto job = new FakeJob(this);
        job->setExpectedError(KJob::KilledJobError, "Foo");
        taskRepositoryMock(&Domain::TaskRepository::update).when(rootTask).thenReturn(job);

        QVERIFY(model->setData(rootTaskIndex, "newRootTask"));

        // THEN
        QTest::qWait(150);
        QCOMPARE(errorHandler.m_message, QString("Cannot modify task rootTask in tag Tag1: Foo"));
    }
Ejemplo n.º 8
0
    void shouldDissociateAnArtifactFromItsProject()
    {
        // GIVEN
        QFETCH(Domain::Artifact::Ptr, child);
        QFETCH(Akonadi::Item, childItem);
        QFETCH(Testlib::AkonadiFakeItemFetchJob*, itemFetchJob);
        QFETCH(bool, fetchJobFailed);

        auto itemModifyJob = new FakeJob(this);

        // Storage mock returning the delete job
        Utils::MockObject<Akonadi::StorageInterface> storageMock;
        storageMock(&Akonadi::StorageInterface::updateItem).when(childItem, Q_NULLPTR)
                                                           .thenReturn(itemModifyJob);
        storageMock(&Akonadi::StorageInterface::fetchItem).when(childItem)
                                                          .thenReturn(itemFetchJob);

        // Serializer mock returning the item for the task
        Utils::MockObject<Akonadi::SerializerInterface> serializerMock;
        if (child.objectCast<Domain::Task>())
            serializerMock(&Akonadi::SerializerInterface::createItemFromTask).when(child.objectCast<Domain::Task>()).thenReturn(childItem);
        else
            serializerMock(&Akonadi::SerializerInterface::createItemFromNote).when(child.objectCast<Domain::Note>()).thenReturn(childItem);
        serializerMock(&Akonadi::SerializerInterface::removeItemParent).when(childItem).thenReturn();

        // WHEN
        QScopedPointer<Akonadi::ProjectRepository> repository(new Akonadi::ProjectRepository(storageMock.getInstance(),
                                                                                             serializerMock.getInstance()));
        repository->dissociate(child)->exec();

        // THEN
        if (child.objectCast<Domain::Task>())
            QVERIFY(serializerMock(&Akonadi::SerializerInterface::createItemFromTask).when(child.objectCast<Domain::Task>()).exactly(1));
        else
            QVERIFY(serializerMock(&Akonadi::SerializerInterface::createItemFromNote).when(child.objectCast<Domain::Note>()).exactly(1));

        QVERIFY(storageMock(&Akonadi::StorageInterface::fetchItem).when(childItem).exactly(1));
        if (!fetchJobFailed) {
            QVERIFY(serializerMock(&Akonadi::SerializerInterface::removeItemParent).when(childItem).exactly(1));;
            QVERIFY(storageMock(&Akonadi::StorageInterface::updateItem).when(childItem, Q_NULLPTR).exactly(1));
        }

        // Give a chance to job to delete themselves
        // in case of an error (since they use deleteLater() internally)
        QTest::qWait(10);
    }
Ejemplo n.º 9
0
    void shouldDeleteItems()
    {
        // GIVEN

        // Two tasks
        auto task1 = Domain::Task::Ptr::create();
        auto task2 = Domain::Task::Ptr::create();
        auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create();
        auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider);
        taskProvider->append(task1);
        taskProvider->append(task2);

        Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
        taskQueriesMock(&Domain::TaskQueries::findWorkdayTopLevel).when().thenReturn(taskResult);
        taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
        taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());

        Utils::MockObject<Domain::NoteRepository> noteRepositoryMock;

        Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
        taskRepositoryMock(&Domain::TaskRepository::remove).when(task2).thenReturn(new FakeJob(this));

        Presentation::WorkdayPageModel workday(taskQueriesMock.getInstance(),
                                               taskRepositoryMock.getInstance(),
                                               noteRepositoryMock.getInstance());

        // WHEN
        const QModelIndex index = workday.centralListModel()->index(1, 0);
        workday.removeItem(index);

        // THEN
        QVERIFY(taskRepositoryMock(&Domain::TaskRepository::remove).when(task2).exactly(1));
    }
Ejemplo n.º 10
0
    void shouldGetAnErrorMessageWhenAddTaskFailed()
    {
        // GIVEN

        // One Tag
        auto tag = Domain::Tag::Ptr::create();
        tag->setName("Tag1");

        // ... in fact we won't list any model
        Utils::MockObject<Domain::TagQueries> tagQueriesMock;
        Utils::MockObject<Domain::TaskQueries> taskQueriesMock;

        // Nor create notes...
        Utils::MockObject<Domain::NoteRepository> noteRepositoryMock;
        Utils::MockObject<Domain::TagRepository> tagRepositoryMock;

        // We'll gladly create a task though
        Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
        auto job = new FakeJob(this);
        job->setExpectedError(KJob::KilledJobError, "Foo");
        taskRepositoryMock(&Domain::TaskRepository::createInTag).when(any<Domain::Task::Ptr>(),
                                                                          any<Domain::Tag::Ptr>())
                                                                    .thenReturn(job);

        Presentation::TagPageModel page(tag,
                                        tagQueriesMock.getInstance(),
                                        tagRepositoryMock.getInstance(),
                                        taskQueriesMock.getInstance(),
                                        taskRepositoryMock.getInstance(),
                                        noteRepositoryMock.getInstance());
        FakeErrorHandler errorHandler;
        page.setErrorHandler(&errorHandler);

        // WHEN
        page.addTask("New task");

        // THEN
        QTest::qWait(150);
        QCOMPARE(errorHandler.m_message, QString("Cannot add task New task in tag Tag1: Foo"));
    }
Ejemplo n.º 11
0
    void shouldAddTasks()
    {
        // GIVEN

        // One Tag
        auto tag = Domain::Tag::Ptr::create();

        // ... in fact we won't list any model
        Utils::MockObject<Domain::TagQueries> tagQueriesMock;
        Utils::MockObject<Domain::TaskQueries> taskQueriesMock;

        // Nor create notes...
        Utils::MockObject<Domain::NoteRepository> noteRepositoryMock;
        Utils::MockObject<Domain::TagRepository> tagRepositoryMock;

        // We'll gladly create a task though
        Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
        taskRepositoryMock(&Domain::TaskRepository::createInTag).when(any<Domain::Task::Ptr>(),
                                                                          any<Domain::Tag::Ptr>())
                                                                    .thenReturn(new FakeJob(this));

        Presentation::TagPageModel page(tag,
                                        tagQueriesMock.getInstance(),
                                        tagRepositoryMock.getInstance(),
                                        taskQueriesMock.getInstance(),
                                        taskRepositoryMock.getInstance(),
                                        noteRepositoryMock.getInstance());

        // WHEN
        auto title = QString("New task");
        auto task = page.addTask(title);

        // THEN
        QVERIFY(taskRepositoryMock(&Domain::TaskRepository::createInTag).when(any<Domain::Task::Ptr>(),
                                                                                  any<Domain::Tag::Ptr>())
                                                                            .exactly(1));
        QCOMPARE(task->title(), title);
    }
Ejemplo n.º 12
0
    void shouldGetAnErrorMessageWhenAssociateTaskFailed()
    {
        // GIVEN

        // One Tag
        auto tag = Domain::Tag::Ptr::create();
        tag->setName("Tag1");

        // One note and one task
        auto rootTask = Domain::Task::Ptr::create();
        rootTask->setTitle("rootTask");
        auto artifactProvider = Domain::QueryResultProvider<Domain::Artifact::Ptr>::Ptr::create();
        auto artifactResult = Domain::QueryResult<Domain::Artifact::Ptr>::create(artifactProvider);
        artifactProvider->append(rootTask);

        // One task under the root task
        auto childTask = Domain::Task::Ptr::create();
        childTask->setTitle("childTask");
        childTask->setDone(true);
        auto taskProvider = Domain::QueryResultProvider<Domain::Task::Ptr>::Ptr::create();
        auto taskResult = Domain::QueryResult<Domain::Task::Ptr>::create(taskProvider);
        taskProvider->append(childTask);

        Utils::MockObject<Domain::TagQueries> tagQueriesMock;
        tagQueriesMock(&Domain::TagQueries::findTopLevelArtifacts).when(tag).thenReturn(artifactResult);

        Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
        taskQueriesMock(&Domain::TaskQueries::findChildren).when(rootTask).thenReturn(taskResult);
        taskQueriesMock(&Domain::TaskQueries::findChildren).when(childTask).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());

        Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
        Utils::MockObject<Domain::NoteRepository> noteRepositoryMock;
        Utils::MockObject<Domain::TagRepository> tagRepositoryMock;

        Presentation::TagPageModel page(tag,
                                        tagQueriesMock.getInstance(),
                                        tagRepositoryMock.getInstance(),
                                        taskQueriesMock.getInstance(),
                                        taskRepositoryMock.getInstance(),
                                        noteRepositoryMock.getInstance());

        QAbstractItemModel *model = page.centralListModel();
        const QModelIndex rootTaskIndex = model->index(0, 0);
        FakeErrorHandler errorHandler;
        page.setErrorHandler(&errorHandler);

        // WHEN
        auto childTask2 = Domain::Task::Ptr::create();
        childTask2->setTitle("childTask2");
        auto job = new FakeJob(this);
        job->setExpectedError(KJob::KilledJobError, "Foo");
        taskRepositoryMock(&Domain::TaskRepository::associate).when(rootTask, childTask2).thenReturn(job);
        auto data = new QMimeData;
        data->setData("application/x-zanshin-object", "object");
        data->setProperty("objects", QVariant::fromValue(Domain::Artifact::List() << childTask2));
        model->dropMimeData(data, Qt::MoveAction, -1, -1, rootTaskIndex);

        // THEN
        QTest::qWait(150);
        QCOMPARE(errorHandler.m_message, QString("Cannot move task childTask2 as sub-task of rootTask: Foo"));
    }
Ejemplo n.º 13
0
    void shouldGetAnErrorMessageWhenRemoveArtifactFailed()
    {
        // GIVEN

        // One domain tag
        auto tag = Domain::Tag::Ptr::create();
        tag->setName("Tag1");

        // Two tasks
        Domain::Artifact::Ptr task1(new Domain::Task);
        task1->setTitle("Task 1");
        Domain::Artifact::Ptr task2(new Domain::Task);
        task2->setTitle("Task 2");
        Domain::Artifact::Ptr note(new Domain::Note);
        note->setTitle("Note 1");

        auto artifactProvider = Domain::QueryResultProvider<Domain::Artifact::Ptr>::Ptr::create();
        auto artifactResult = Domain::QueryResult<Domain::Artifact::Ptr>::create(artifactProvider);
        artifactProvider->append(task1);
        artifactProvider->append(task2);
        artifactProvider->append(note);

        Utils::MockObject<Domain::TagQueries> tagQueriesMock;
        tagQueriesMock(&Domain::TagQueries::findTopLevelArtifacts).when(tag).thenReturn(artifactResult);

        Utils::MockObject<Domain::TagRepository> tagRepositoryMock;
        auto job = new FakeJob(this);
        job->setExpectedError(KJob::KilledJobError, "Foo");
        tagRepositoryMock(&Domain::TagRepository::dissociate).when(tag, task2).thenReturn(job);

        Utils::MockObject<Domain::TaskQueries> taskQueriesMock;
        taskQueriesMock(&Domain::TaskQueries::findChildren).when(task1.dynamicCast<Domain::Task>()).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());
        taskQueriesMock(&Domain::TaskQueries::findChildren).when(task2.dynamicCast<Domain::Task>()).thenReturn(Domain::QueryResult<Domain::Task::Ptr>::Ptr());

        Utils::MockObject<Domain::TaskRepository> taskRepositoryMock;
        Utils::MockObject<Domain::NoteRepository> noteRepositoryMock;

        Presentation::TagPageModel page(tag,
                                        tagQueriesMock.getInstance(),
                                        tagRepositoryMock.getInstance(),
                                        taskQueriesMock.getInstance(),
                                        taskRepositoryMock.getInstance(),
                                        noteRepositoryMock.getInstance());
        FakeErrorHandler errorHandler;
        page.setErrorHandler(&errorHandler);

        // WHEN
        const QModelIndex indexTask2 = page.centralListModel()->index(1, 0);
        page.removeItem(indexTask2);

        // THEN
        QTest::qWait(150);
        QCOMPARE(errorHandler.m_message, QString("Cannot remove task Task 2 from tag Tag1: Foo"));

        // WHEN
        auto job2 = new FakeJob(this);
        job->setExpectedError(KJob::KilledJobError, "Foo");
        tagRepositoryMock(&Domain::TagRepository::dissociate).when(tag, note).thenReturn(job2);
        const QModelIndex indexNote = page.centralListModel()->index(2, 0);
        page.removeItem(indexNote);

        // THEN
        QTest::qWait(150);
        QCOMPARE(errorHandler.m_message, QString("Cannot remove note Note 1 from tag Tag1: Foo"));
    }
Ejemplo n.º 14
0
    void shouldAssociateAnArtifactToAProject()
    {
        // GIVEN
        QFETCH(Akonadi::Item, childItem);
        QFETCH(Akonadi::Item, parentItem);
        QFETCH(Domain::Artifact::Ptr, child);
        QFETCH(Domain::Project::Ptr, parent);
        QFETCH(Testlib::AkonadiFakeItemFetchJob*, itemFetchJob1);
        QFETCH(Testlib::AkonadiFakeItemFetchJob*, itemFetchJob2);
        QFETCH(Testlib::AkonadiFakeItemFetchJob*, itemFetchJob3);
        QFETCH(bool, execJob);
        QFETCH(bool, execParentJob);
        QFETCH(Akonadi::Item::List, list);

        // A mock create job
        auto itemModifyJob = new FakeJob(this);
        auto transactionJob = new FakeJob(this);
        auto itemsMoveJob = new FakeJob(this);

        Akonadi::Item::List movedList;
        movedList << childItem << list;

        // Storage mock returning the create job
        Utils::MockObject<Akonadi::StorageInterface> storageMock;
        storageMock(&Akonadi::StorageInterface::fetchItem).when(childItem)
                                                          .thenReturn(itemFetchJob1);
        storageMock(&Akonadi::StorageInterface::fetchItem).when(parentItem)
                                                          .thenReturn(itemFetchJob2);
        if (child.objectCast<Domain::Task>()
         && parentItem.parentCollection().id() != childItem.parentCollection().id()) {
            storageMock(&Akonadi::StorageInterface::fetchItems).when(childItem.parentCollection())
                                                               .thenReturn(itemFetchJob3);
            storageMock(&Akonadi::StorageInterface::createTransaction).when().thenReturn(transactionJob);
            storageMock(&Akonadi::StorageInterface::updateItem).when(childItem, transactionJob)
                                                               .thenReturn(itemModifyJob);
            storageMock(&Akonadi::StorageInterface::moveItems).when(movedList, parentItem.parentCollection(), transactionJob)
                                                              .thenReturn(itemsMoveJob);
        } else {
            storageMock(&Akonadi::StorageInterface::updateItem).when(childItem, Q_NULLPTR)
                                                               .thenReturn(itemModifyJob);
        }

        // Serializer mock returning the item for the task
        Utils::MockObject<Akonadi::SerializerInterface> serializerMock;
        serializerMock(&Akonadi::SerializerInterface::createItemFromTask).when(child.objectCast<Domain::Task>()).thenReturn(childItem);
        serializerMock(&Akonadi::SerializerInterface::createItemFromNote).when(child.objectCast<Domain::Note>()).thenReturn(childItem);
        serializerMock(&Akonadi::SerializerInterface::createItemFromProject).when(parent).thenReturn(parentItem);
        serializerMock(&Akonadi::SerializerInterface::updateItemProject).when(childItem, parent).thenReturn();
        if (execParentJob)
            serializerMock(&Akonadi::SerializerInterface::filterDescendantItems).when(list, childItem).thenReturn(list);

        // WHEN
        QScopedPointer<Akonadi::ProjectRepository> repository(new Akonadi::ProjectRepository(storageMock.getInstance(),
                                                                                             serializerMock.getInstance()));
        auto associateJob = repository->associate(parent, child);
        if (execJob)
            associateJob->exec();

        // THEN
        QVERIFY(storageMock(&Akonadi::StorageInterface::fetchItem).when(childItem).exactly(1));
        if (execJob) {
            QVERIFY(serializerMock(&Akonadi::SerializerInterface::updateItemProject).when(childItem, parent).exactly(1));
            QVERIFY(serializerMock(&Akonadi::SerializerInterface::createItemFromProject).when(parent).exactly(1));
            QVERIFY(storageMock(&Akonadi::StorageInterface::fetchItem).when(parentItem).exactly(1));
            if (execParentJob) {
                if (child.objectCast<Domain::Task>()
                 && parentItem.parentCollection().id() != childItem.parentCollection().id()) {
                    QVERIFY(storageMock(&Akonadi::StorageInterface::fetchItems).when(childItem.parentCollection()).exactly(1));
                    QVERIFY(storageMock(&Akonadi::StorageInterface::createTransaction).when().thenReturn(transactionJob).exactly(1));
                    QVERIFY(storageMock(&Akonadi::StorageInterface::updateItem).when(childItem, transactionJob).exactly(1));
                    QVERIFY(storageMock(&Akonadi::StorageInterface::moveItems).when(movedList, parentItem.parentCollection(), transactionJob).exactly(1));
                } else {
                    QVERIFY(storageMock(&Akonadi::StorageInterface::updateItem).when(childItem, Q_NULLPTR).exactly(1));
                }
            }
        }
    }