From e06e1dad4a4570e5c1181d05ab6ed7a5d74c6c91 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Tue, 3 May 2016 20:24:09 +0200 Subject: A save-as-draft action & action results This patch introduces tracking of actions, so they can be tested. It also provides a save-as-draft action, that looks for the draft folder, and stores the mail accordingly. --- framework/domain/CMakeLists.txt | 4 +- framework/domain/actions/sinkactions.cpp | 101 +++++++++++----------- framework/domain/actions/tests/CMakeLists.txt | 6 ++ framework/domain/actions/tests/sinkactiontest.cpp | 60 +++++++++++++ framework/domain/composercontroller.cpp | 5 +- framework/domain/maillistmodel.cpp | 2 +- 6 files changed, 125 insertions(+), 53 deletions(-) create mode 100644 framework/domain/actions/tests/CMakeLists.txt create mode 100644 framework/domain/actions/tests/sinkactiontest.cpp (limited to 'framework/domain') diff --git a/framework/domain/CMakeLists.txt b/framework/domain/CMakeLists.txt index b3d47750..29385b39 100644 --- a/framework/domain/CMakeLists.txt +++ b/framework/domain/CMakeLists.txt @@ -27,7 +27,9 @@ include_directories(${CURL_INCLUDE_DIRS}) add_library(mailplugin SHARED ${mailplugin_SRCS}) qt5_use_modules(mailplugin Core Quick Qml WebKitWidgets) -target_link_libraries(mailplugin actionplugin settingsplugin sink KF5::MimeTreeParser KF5::Codecs KF5::Package ${CURL_LIBRARIES}) +target_link_libraries(mailplugin actionplugin settingsplugin sink KF5::MimeTreeParser KF5::Codecs KF5::Package KF5::Async ${CURL_LIBRARIES}) + +add_subdirectory(actions/tests) install(TARGETS mailplugin DESTINATION ${QML_INSTALL_DIR}/org/kube/framework/domain) install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kube/framework/domain) diff --git a/framework/domain/actions/sinkactions.cpp b/framework/domain/actions/sinkactions.cpp index dea6fc72..5dbe623c 100644 --- a/framework/domain/actions/sinkactions.cpp +++ b/framework/domain/actions/sinkactions.cpp @@ -81,16 +81,7 @@ static ActionHandlerHelper sendMailHandler("org.kde.kube.actions.sendmail", }, [](Context *context) { auto accountId = context->property("accountId").value(); - //For ssl use "smtps://mainserver.example.net - // QByteArray cacert; // = "/path/to/certificate.pem"; auto message = context->property("message").value(); - auto mimeMessage = Sink::Store::getTemporaryFilePath(); - QFile file(mimeMessage); - if (!file.open(QIODevice::ReadWrite)) { - qWarning() << "Failed to open the file: " << file.errorString() << mimeMessage; - return; - } - file.write(message->encodedContent()); qWarning() << "Sending a mail: "; Sink::Query query; @@ -98,53 +89,63 @@ static ActionHandlerHelper sendMailHandler("org.kde.kube.actions.sendmail", query += Sink::Query::PropertyFilter("account", QVariant::fromValue(accountId)); Sink::Store::fetchAll(query) .then>([=](const QList &resources) { - if (resources.isEmpty()) { - qWarning() << "Failed to find a mailtransport resource"; - } else { + if (!resources.isEmpty()) { auto resourceId = resources[0]->identifier(); qDebug() << "Sending message via resource: " << resourceId; Sink::ApplicationDomain::Mail mail(resourceId); - mail.setProperty("mimeMessage", mimeMessage); - Sink::Store::create(mail).exec(); - // return Sink::Store::create(mail); + mail.setBlobProperty("mimeMessage", message->encodedContent()); + return Sink::Store::create(mail); } + qWarning() << "Failed to find a mailtransport resource"; return KAsync::error(0, "Failed to find a MailTransport resource."); }).exec(); } ); -// static ActionHandlerHelper saveAsDraft("org.kde.kube.actions.save-as-draft", -// [](Context *context) -> bool { -// return context->property("mail").isValid(); -// }, -// [](Context *context) { -// Sink::Query query; -// query += Sink::Query::RequestedProperties(QByteArrayList() << "name") -// //FIXME do something like specialuse? -// query += Sink::Query::PropertyFilter("name", "Drafts"); -// // query += Sink::Query::PropertyContainsFilter("specialuser", "drafts"); -// query += Sink::Query::PropertyFilter("drafts", true); -// //TODO Use drafts folder of that specific account -// Sink::Store::fetchAll(query) -// .then>([](const QList folders) { -// if (folders.isEmpty()) { -// return KAsync::start([]() { -// //If message is already existing, modify, otherwise create -// }); -// } -// }); -// //TODO -// // * Find drafts folder -// // * Store KMime::Message on disk for use in blob property -// // * Check if message is already existing and either create or update -// // * -// // auto mail = context->property("mail").value(); -// // if (!mail) { -// // qWarning() << "Failed to get the mail mail: " << context->property("mail"); -// // return; -// // } -// // mail->setProperty("unread", false); -// // qDebug() << "Mark as read " << mail->identifier(); -// // Sink::Store::modify(*mail).exec(); -// } -// ); +static ActionHandlerHelper saveAsDraft("org.kde.kube.actions.save-as-draft", + [](Context *context) -> bool { + auto accountId = context->property("accountId").value(); + auto message = context->property("message").value(); + return !accountId.isEmpty() && message; + }, + ActionHandlerHelper::JobHandler([](Context *context) -> KAsync::Job { + qWarning() << "executing save as draft"; + const auto accountId = context->property("accountId").value(); + const auto message = context->property("message").value(); + auto existingMail = context->property("existingMail").value(); + if (!message) { + qWarning() << "Failed to get the mail: " << context->property("mail"); + return KAsync::error(1, "Failed to get the mail: " + context->property("mail").toString()); + } + + if (existingMail.identifier().isEmpty()) { + Sink::Query query; + query += Sink::Query::RequestedProperties(QByteArrayList() << "name"); + query += Sink::Query::PropertyContainsFilter("specialpurpose", "drafts"); + query += Sink::Query::AccountFilter(accountId); + qWarning() << "fetching the drafts folder"; + return Sink::Store::fetchAll(query) + .then>([=](const QList folders) { + qWarning() << "fetched a drafts folder" << folders.size(); + if (folders.isEmpty()) { + return KAsync::error(1, "Failed to find a drafts folder."); + } + if (folders.size() > 1) { + qWarning() << "Found too many draft folders (taking the first): " << folders; + } + const auto folder = folders.first(); + Sink::ApplicationDomain::Mail mail(folder->resourceInstanceIdentifier()); + mail.setProperty("folder", folder->identifier()); + mail.setBlobProperty("mimeMessage", message->encodedContent()); + return Sink::Store::create(mail); + }) + .then([](){ + qWarning() << "done"; + }); + } else { + qWarning() << "Modifying an existing mail"; + existingMail.setBlobProperty("mimeMessage", message->encodedContent()); + return Sink::Store::modify(existingMail); + } + }) +); diff --git a/framework/domain/actions/tests/CMakeLists.txt b/framework/domain/actions/tests/CMakeLists.txt new file mode 100644 index 00000000..dc9d01b1 --- /dev/null +++ b/framework/domain/actions/tests/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +cmake_policy(SET CMP0063 NEW) +add_executable(sinkactiontest sinkactiontest.cpp) +add_test(sinkactiontest sinkactiontest) +qt5_use_modules(sinkactiontest Core Test Concurrent) +target_link_libraries(sinkactiontest sink actionplugin KF5::Mime mailplugin) diff --git a/framework/domain/actions/tests/sinkactiontest.cpp b/framework/domain/actions/tests/sinkactiontest.cpp new file mode 100644 index 00000000..3e4567fd --- /dev/null +++ b/framework/domain/actions/tests/sinkactiontest.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace Sink; + +class SinkActionTest : public QObject +{ + Q_OBJECT +private slots: + + void initTestCase() + { + Sink::Test::initTest(); + Sink::Log::setDebugOutputLevel(Sink::Log::Trace); + } + + void testSaveAsDraftFail() + { + Kube::Context context; + auto future = Kube::Action("org.kde.kube.actions.save-as-draft", context).execute(); + + QTRY_VERIFY(future.isDone()); + //because of empty context + QVERIFY(future.error()); + } + + void testSaveAsDraftNew() + { + auto message = KMime::Message::Ptr::create(); + message->subject(true)->fromUnicodeString(QString::fromLatin1("Foobar"), "utf8"); + message->assemble(); + + auto &&account = Test::TestAccount::registerAccount(); + auto folder = account.createEntity(); + folder->setProperty("specialpurpose", QVariant::fromValue(QByteArrayList() << "drafts")); + + Kube::Context context; + context.setProperty("message", QVariant::fromValue(message)); + context.setProperty("accountId", QVariant::fromValue(account.identifier)); + auto future = Kube::Action("org.kde.kube.actions.save-as-draft", context).execute(); + + QTRY_VERIFY(future.isDone()); + QVERIFY(!future.error()); + auto mails = account.entities(); + QCOMPARE(mails.size(), 1); + auto mail = mails.first(); + QCOMPARE(mail->getProperty("folder").toByteArray(), folder->identifier()); + } +}; + +QTEST_GUILESS_MAIN(SinkActionTest) +#include "sinkactiontest.moc" diff --git a/framework/domain/composercontroller.cpp b/framework/domain/composercontroller.cpp index bca90d33..0cf61442 100644 --- a/framework/domain/composercontroller.cpp +++ b/framework/domain/composercontroller.cpp @@ -185,9 +185,12 @@ void ComposerController::send() void ComposerController::saveAsDraft() { auto mail = assembleMessage(); + auto currentAccountId = identityModel()->index(m_currentAccountIndex, 0).data(IdentitiesModel::AccountId).toByteArray(); + Kube::Context context; context.setProperty("message", QVariant::fromValue(mail)); - Kube::Action("org.kde.kube.actions.saveasdraft", context).execute(); + context.setProperty("accountId", QVariant::fromValue(currentAccountId)); + Kube::Action("org.kde.kube.actions.save-as-draft", context).execute(); clear(); } diff --git a/framework/domain/maillistmodel.cpp b/framework/domain/maillistmodel.cpp index 7cbc5587..2df3ecbc 100644 --- a/framework/domain/maillistmodel.cpp +++ b/framework/domain/maillistmodel.cpp @@ -111,10 +111,10 @@ void MailListModel::setParentFolder(const QVariant &parentFolder) Sink::Query query; query.liveQuery = true; query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important" << "folder"; - query.propertyFilter.insert("folder", folder->identifier()); query.resources << folder->resourceInstanceIdentifier(); query.sortProperty = "date"; query.limit = 100; + query += Sink::Query::PropertyFilter("folder", *folder); qWarning() << "Running folder query: " << folder->resourceInstanceIdentifier() << folder->identifier(); runQuery(query); } -- cgit v1.2.3