diff --git a/src/presentation/artifacteditormodel.h b/src/presentation/artifacteditormodel.h --- a/src/presentation/artifacteditormodel.h +++ b/src/presentation/artifacteditormodel.h @@ -28,8 +28,9 @@ #include #include -#include "domain/noterepository.h" -#include "domain/taskrepository.h" +#include + +#include "domain/task.h" #include "presentation/errorhandlingmodelbase.h" @@ -49,14 +50,21 @@ Q_PROPERTY(QString delegateText READ delegateText NOTIFY delegateTextChanged) Q_PROPERTY(bool hasTaskProperties READ hasTaskProperties NOTIFY hasTaskPropertiesChanged) public: - explicit ArtifactEditorModel(const Domain::TaskRepository::Ptr &taskRepository, - const Domain::NoteRepository::Ptr ¬eRepository, - QObject *parent = Q_NULLPTR); + typedef std::function SaveFunction; + typedef std::function DelegateFunction; + + explicit ArtifactEditorModel(QObject *parent = Q_NULLPTR); ~ArtifactEditorModel(); Domain::Artifact::Ptr artifact() const; void setArtifact(const Domain::Artifact::Ptr &artifact); + bool hasSaveFunction() const; + void setSaveFunction(const SaveFunction &function); + + bool hasDelegateFunction() const; + void setDelegateFunction(const DelegateFunction &function); + bool hasTaskProperties() const; QString text() const; @@ -100,10 +108,9 @@ void setSaveNeeded(bool needed); bool isSaveNeeded() const; - Domain::TaskRepository::Ptr m_taskRepository; - Domain::NoteRepository::Ptr m_noteRepository; - Domain::Artifact::Ptr m_artifact; + SaveFunction m_saveFunction; + DelegateFunction m_delegateFunction; QString m_text; QString m_title; diff --git a/src/presentation/artifacteditormodel.cpp b/src/presentation/artifacteditormodel.cpp --- a/src/presentation/artifacteditormodel.cpp +++ b/src/presentation/artifacteditormodel.cpp @@ -27,19 +27,12 @@ #include #include "domain/task.h" -#include "domain/taskrepository.h" -#include "domain/note.h" -#include "domain/noterepository.h" #include "errorhandler.h" using namespace Presentation; -ArtifactEditorModel::ArtifactEditorModel(const Domain::TaskRepository::Ptr &taskRepository, - const Domain::NoteRepository::Ptr ¬eRepository, - QObject *parent) +ArtifactEditorModel::ArtifactEditorModel(QObject *parent) : QObject(parent), - m_taskRepository(taskRepository), - m_noteRepository(noteRepository), m_done(false), m_saveTimer(new QTimer(this)), m_saveNeeded(false) @@ -112,6 +105,26 @@ emit artifactChanged(m_artifact); } +bool ArtifactEditorModel::hasSaveFunction() const +{ + return bool(m_saveFunction); +} + +void ArtifactEditorModel::setSaveFunction(const SaveFunction &function) +{ + m_saveFunction = function; +} + +bool ArtifactEditorModel::hasDelegateFunction() const +{ + return bool(m_delegateFunction); +} + +void ArtifactEditorModel::setDelegateFunction(const DelegateFunction &function) +{ + m_delegateFunction = function; +} + bool ArtifactEditorModel::hasTaskProperties() const { return m_artifact.objectCast(); @@ -197,7 +210,7 @@ auto task = m_artifact.objectCast(); Q_ASSERT(task); auto delegate = Domain::Task::Delegate(name, email); - m_taskRepository->delegate(task, delegate); + m_delegateFunction(task, delegate); } void ArtifactEditorModel::onTextChanged(const QString &text) @@ -251,15 +264,10 @@ task->setDone(m_done); task->setStartDate(m_start); task->setDueDate(m_due); - const auto job = m_taskRepository->update(task); - installHandler(job, tr("Cannot modify task %1").arg(currentTitle)); - } else { - auto note = m_artifact.objectCast(); - Q_ASSERT(note); - const auto job = m_noteRepository->update(note); - installHandler(job, tr("Cannot modify note %1").arg(currentTitle)); } + const auto job = m_saveFunction(m_artifact); + installHandler(job, tr("Cannot modify task %1").arg(currentTitle)); setSaveNeeded(false); } diff --git a/src/renku/app/dependencies.cpp b/src/renku/app/dependencies.cpp --- a/src/renku/app/dependencies.cpp +++ b/src/renku/app/dependencies.cpp @@ -117,9 +117,16 @@ Akonadi::MessagingInterface*)>(); - deps.add(); + deps.add([] (Utils::DependencyManager *deps) { + auto model = new Presentation::ArtifactEditorModel; + auto repository = deps->create(); + model->setSaveFunction([repository] (const Domain::Artifact::Ptr &artifact) { + auto note = artifact.objectCast(); + Q_ASSERT(note); + return repository->update(note); + }); + return model; + }); deps.add(); - deps.add(); + deps.add([] (Utils::DependencyManager *deps) { + auto model = new Presentation::ArtifactEditorModel; + auto repository = deps->create(); + model->setSaveFunction([repository] (const Domain::Artifact::Ptr &artifact) { + auto task = artifact.objectCast(); + Q_ASSERT(task); + return repository->update(task); + }); + model->setDelegateFunction([repository] (const Domain::Task::Ptr &task, const Domain::Task::Delegate &delegate) { + return repository->delegate(task, delegate); + }); + return model; + }); deps.add(); Utils::DependencyManager::globalInstance().add( [] (Utils::DependencyManager *) { - return new Presentation::ArtifactEditorModel(Domain::TaskRepository::Ptr(), - Domain::NoteRepository::Ptr()); + return new Presentation::ArtifactEditorModel; }); Utils::DependencyManager::globalInstance().add( [] (Utils::DependencyManager *) { diff --git a/tests/units/presentation/artifacteditormodeltest.cpp b/tests/units/presentation/artifacteditormodeltest.cpp --- a/tests/units/presentation/artifacteditormodeltest.cpp +++ b/tests/units/presentation/artifacteditormodeltest.cpp @@ -30,9 +30,7 @@ #include "testlib/fakejob.h" #include "domain/task.h" -#include "domain/taskrepository.h" #include "domain/note.h" -#include "domain/noterepository.h" #include "presentation/artifacteditormodel.h" #include "presentation/errorhandler.h" @@ -57,10 +55,7 @@ void shouldHaveEmptyDefaultState() { // GIVEN - auto taskRepository = Domain::TaskRepository::Ptr(); - auto noteRepository = Domain::NoteRepository::Ptr(); - Presentation::ArtifactEditorModel model(taskRepository, - noteRepository); + Presentation::ArtifactEditorModel model; // WHEN // Nothing @@ -74,15 +69,14 @@ QVERIFY(model.startDate().isNull()); QVERIFY(model.dueDate().isNull()); QVERIFY(model.delegateText().isNull()); + QVERIFY(!model.hasSaveFunction()); + QVERIFY(!model.hasDelegateFunction()); } void shouldHaveTaskProperties() { // GIVEN - auto taskRepository = Domain::TaskRepository::Ptr(); - auto noteRepository = Domain::NoteRepository::Ptr(); - Presentation::ArtifactEditorModel model(taskRepository, - noteRepository); + Presentation::ArtifactEditorModel model; QSignalSpy textSpy(&model, SIGNAL(textChanged(QString))); QSignalSpy titleSpy(&model, SIGNAL(titleChanged(QString))); QSignalSpy doneSpy(&model, SIGNAL(doneChanged(bool))); @@ -138,10 +132,7 @@ void shouldHaveNoteProperties() { // GIVEN - auto taskRepository = Domain::TaskRepository::Ptr(); - auto noteRepository = Domain::NoteRepository::Ptr(); - Presentation::ArtifactEditorModel model(taskRepository, - noteRepository); + Presentation::ArtifactEditorModel model; QSignalSpy textSpy(&model, SIGNAL(textChanged(QString))); QSignalSpy titleSpy(&model, SIGNAL(titleChanged(QString))); QSignalSpy doneSpy(&model, SIGNAL(doneChanged(bool))); @@ -238,10 +229,7 @@ QFETCH(QVariant, propertyValue); QFETCH(QByteArray, signal); - auto taskRepository = Domain::TaskRepository::Ptr(); - auto noteRepository = Domain::NoteRepository::Ptr(); - Presentation::ArtifactEditorModel model(taskRepository, - noteRepository); + Presentation::ArtifactEditorModel model; model.setArtifact(artifact); QSignalSpy spy(&model, signal.constData()); @@ -258,10 +246,7 @@ { // GIVEN auto task = Domain::Task::Ptr::create(); - auto taskRepository = Domain::TaskRepository::Ptr(); - auto noteRepository = Domain::NoteRepository::Ptr(); - Presentation::ArtifactEditorModel model(taskRepository, - noteRepository); + Presentation::ArtifactEditorModel model; model.setArtifact(task); QSignalSpy spy(&model, SIGNAL(delegateTextChanged(QString))); @@ -287,16 +272,14 @@ QFETCH(QVariant, propertyValue); QFETCH(QByteArray, signal); - auto task = artifact.objectCast(); - auto note = artifact.objectCast(); + auto savedArtifact = Domain::Artifact::Ptr(); + auto save = [this, &savedArtifact] (const Domain::Artifact::Ptr &artifact) { + savedArtifact = artifact; + return new FakeJob(this); + }; - Utils::MockObject taskRepositoryMock; - taskRepositoryMock(&Domain::TaskRepository::update).when(task).thenReturn(new FakeJob(this)); - Utils::MockObject noteRepositoryMock; - noteRepositoryMock(&Domain::NoteRepository::update).when(note).thenReturn(new FakeJob(this)); - - Presentation::ArtifactEditorModel model(taskRepositoryMock.getInstance(), - noteRepositoryMock.getInstance()); + Presentation::ArtifactEditorModel model; + model.setSaveFunction(save); model.setArtifact(artifact); QSignalSpy spy(&model, signal.constData()); @@ -308,19 +291,14 @@ QCOMPARE(spy.takeFirst().takeFirst(), propertyValue); QCOMPARE(model.property(propertyName), propertyValue); QVERIFY(artifact->property(propertyName) != propertyValue); - QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(task).exactly(0)); - QVERIFY(noteRepositoryMock(&Domain::NoteRepository::update).when(note).exactly(0)); + QVERIFY(!savedArtifact); // WHEN (apply after delay) QTest::qWait(model.autoSaveDelay() + 50); // THEN + QCOMPARE(savedArtifact, artifact); QCOMPARE(artifact->property(propertyName), propertyValue); - if (task) { - QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(task).exactly(1)); - } else { - QVERIFY(noteRepositoryMock(&Domain::NoteRepository::update).when(note).exactly(1)); - } } void shouldApplyChangesImmediatelyIfANewArtifactIsSet_data() @@ -336,16 +314,15 @@ QFETCH(QVariant, propertyValue); QFETCH(QByteArray, signal); - auto task = artifact.objectCast(); - auto note = artifact.objectCast(); - - Utils::MockObject taskRepositoryMock; - taskRepositoryMock(&Domain::TaskRepository::update).when(task).thenReturn(new FakeJob(this)); - Utils::MockObject noteRepositoryMock; - noteRepositoryMock(&Domain::NoteRepository::update).when(note).thenReturn(new FakeJob(this)); + auto savedArtifact = Domain::Artifact::Ptr(); + auto save = [this, &savedArtifact] (const Domain::Artifact::Ptr &artifact) { + savedArtifact = artifact; + return new FakeJob(this); + }; - Presentation::ArtifactEditorModel model(taskRepositoryMock.getInstance(), - noteRepositoryMock.getInstance()); + Presentation::ArtifactEditorModel model; + model.setSaveFunction(save); + QVERIFY(model.hasSaveFunction()); model.setArtifact(artifact); QSignalSpy spy(&model, signal.constData()); @@ -357,30 +334,22 @@ QCOMPARE(spy.takeFirst().takeFirst(), propertyValue); QCOMPARE(model.property(propertyName), propertyValue); QVERIFY(artifact->property(propertyName) != propertyValue); - QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(task).exactly(0)); - QVERIFY(noteRepositoryMock(&Domain::NoteRepository::update).when(note).exactly(0)); + QVERIFY(!savedArtifact); // WHEN (apply immediately) model.setArtifact(Domain::Task::Ptr::create()); // THEN + QCOMPARE(savedArtifact, artifact); QCOMPARE(artifact->property(propertyName), propertyValue); - if (task) { - QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(task).exactly(1)); - } else { - QVERIFY(noteRepositoryMock(&Domain::NoteRepository::update).when(note).exactly(1)); - } + savedArtifact.clear(); // WHEN (nothing else happens after a delay) QTest::qWait(model.autoSaveDelay() + 50); // THEN + QVERIFY(!savedArtifact); QCOMPARE(artifact->property(propertyName), propertyValue); - if (task) { - QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(task).exactly(1)); - } else { - QVERIFY(noteRepositoryMock(&Domain::NoteRepository::update).when(note).exactly(1)); - } } void shouldApplyChangesImmediatelyIfDeleted_data() @@ -396,16 +365,15 @@ QFETCH(QVariant, propertyValue); QFETCH(QByteArray, signal); - auto task = artifact.objectCast(); - auto note = artifact.objectCast(); - - Utils::MockObject taskRepositoryMock; - taskRepositoryMock(&Domain::TaskRepository::update).when(task).thenReturn(new FakeJob(this)); - Utils::MockObject noteRepositoryMock; - noteRepositoryMock(&Domain::NoteRepository::update).when(note).thenReturn(new FakeJob(this)); + auto savedArtifact = Domain::Artifact::Ptr(); + auto save = [this, &savedArtifact] (const Domain::Artifact::Ptr &artifact) { + savedArtifact = artifact; + return new FakeJob(this); + }; - auto model = new Presentation::ArtifactEditorModel(taskRepositoryMock.getInstance(), - noteRepositoryMock.getInstance()); + auto model = new Presentation::ArtifactEditorModel; + model->setSaveFunction(save); + QVERIFY(model->hasSaveFunction()); model->setArtifact(artifact); QSignalSpy spy(model, signal.constData()); @@ -417,55 +385,61 @@ QCOMPARE(spy.takeFirst().takeFirst(), propertyValue); QCOMPARE(model->property(propertyName), propertyValue); QVERIFY(artifact->property(propertyName) != propertyValue); - QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(task).exactly(0)); - QVERIFY(noteRepositoryMock(&Domain::NoteRepository::update).when(note).exactly(0)); + QVERIFY(!savedArtifact); // WHEN (apply immediately) delete model; // THEN + QCOMPARE(savedArtifact, artifact); QCOMPARE(artifact->property(propertyName), propertyValue); - if (task) { - QVERIFY(taskRepositoryMock(&Domain::TaskRepository::update).when(task).exactly(1)); - } else { - QVERIFY(noteRepositoryMock(&Domain::NoteRepository::update).when(note).exactly(1)); - } } void shouldLaunchDelegation() { // GIVEN auto task = Domain::Task::Ptr::create(); auto expectedDelegate = Domain::Task::Delegate("John Doe", "john@doe.com"); - Utils::MockObject taskRepositoryMock; - taskRepositoryMock(&Domain::TaskRepository::delegate).when(task, expectedDelegate).thenReturn(new FakeJob(this)); - - Presentation::ArtifactEditorModel model(taskRepositoryMock.getInstance(), - Domain::NoteRepository::Ptr()); + auto delegatedTask = Domain::Task::Ptr(); + auto delegate = Domain::Task::Delegate(); + auto delegateFunction = [this, &delegatedTask, &delegate] (const Domain::Task::Ptr &task, const Domain::Task::Delegate &d) { + delegatedTask = task; + delegate = d; + return new FakeJob(this); + }; + + Presentation::ArtifactEditorModel model; + model.setDelegateFunction(delegateFunction); + QVERIFY(model.hasDelegateFunction()); model.setArtifact(task); // WHEN model.delegate("John Doe", "john@doe.com"); // THEN - QVERIFY(taskRepositoryMock(&Domain::TaskRepository::delegate).when(task, expectedDelegate).exactly(1)); + QCOMPARE(delegatedTask, task); + QCOMPARE(delegate, expectedDelegate); QVERIFY(!task->delegate().isValid()); } - void shouldGetAnErrorMessageWhenUpdateTaskFailed() + void shouldGetAnErrorMessageWhenSaveFailed() { // GIVEN auto task = Domain::Task::Ptr::create(); task->setTitle("Task 1"); - auto job = new FakeJob(this); - job->setExpectedError(KJob::KilledJobError, "Foo"); - Utils::MockObject taskRepositoryMock; - taskRepositoryMock(&Domain::TaskRepository::update).when(task).thenReturn(job); - Utils::MockObject noteRepositoryMock; - - auto model = new Presentation::ArtifactEditorModel(taskRepositoryMock.getInstance(), - noteRepositoryMock.getInstance()); + + auto savedArtifact = Domain::Artifact::Ptr(); + auto save = [this, &savedArtifact] (const Domain::Artifact::Ptr &artifact) { + savedArtifact = artifact; + auto job = new FakeJob(this); + job->setExpectedError(KJob::KilledJobError, "Foo"); + return job; + }; + + auto model = new Presentation::ArtifactEditorModel; + model->setSaveFunction(save); + QVERIFY(model->hasSaveFunction()); FakeErrorHandler errorHandler; model->setErrorHandler(&errorHandler); model->setArtifact(task); @@ -478,32 +452,6 @@ QTest::qWait(150); QCOMPARE(errorHandler.m_message, QString("Cannot modify task Task 1: Foo")); } - - void shouldGetAnErrorMessageWhenUpdateNoteFailed() - { - // GIVEN - auto note = Domain::Note::Ptr::create(); - note->setTitle("Note 1"); - auto job = new FakeJob(this); - job->setExpectedError(KJob::KilledJobError, "Foo"); - Utils::MockObject taskRepositoryMock; - Utils::MockObject noteRepositoryMock; - noteRepositoryMock(&Domain::NoteRepository::update).when(note).thenReturn(job); - - auto model = new Presentation::ArtifactEditorModel(taskRepositoryMock.getInstance(), - noteRepositoryMock.getInstance()); - FakeErrorHandler errorHandler; - model->setErrorHandler(&errorHandler); - model->setArtifact(note); - - // WHEN - model->setProperty("title", "Foo"); - delete model; - - // THEN - QTest::qWait(150); - QCOMPARE(errorHandler.m_message, QString("Cannot modify note Note 1: Foo")); - } }; QTEST_MAIN(ArtifactEditorModelTest)