You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
258 lines
10 KiB
258 lines
10 KiB
/* |
|
SPDX-FileCopyrightText: 2016 David Faure <faure@kde.org> |
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later |
|
*/ |
|
|
|
#undef QT_NO_CAST_FROM_ASCII |
|
|
|
#include <qtest_akonadi.h> |
|
|
|
#include <AkonadiCore/Collection> |
|
#include <AkonadiCore/Item> |
|
#include <AkonadiCore/ItemFetchScope> |
|
|
|
#include <AkonadiCore/AgentInstanceCreateJob> |
|
#include <AkonadiCore/AgentManager> |
|
#include <AkonadiCore/AgentType> |
|
#include <AkonadiCore/CollectionCreateJob> |
|
#include <AkonadiCore/CollectionDeleteJob> |
|
#include <AkonadiCore/CollectionFetchJob> |
|
#include <AkonadiCore/CollectionMoveJob> |
|
#include <AkonadiCore/EntityOrderProxyModel> |
|
#include <AkonadiCore/SearchCreateJob> |
|
#include <AkonadiCore/SearchQuery> |
|
|
|
#include <KMime/Message> |
|
|
|
#include "folder/entitycollectionorderproxymodel.h" |
|
#include <MailCommon/FolderTreeView> |
|
#include <MailCommon/FolderTreeWidget> |
|
#include <MailCommon/MailKernel> |
|
|
|
#include <QDebug> |
|
#include <QStandardPaths> |
|
#include <QTest> |
|
#include <QTreeView> |
|
|
|
#include "dummykernel.cpp" |
|
|
|
// #define SHOW_WIDGET |
|
|
|
using namespace Akonadi; |
|
|
|
class FolderTreeWidgetTest : public QObject |
|
{ |
|
Q_OBJECT |
|
private Q_SLOTS: |
|
void initTestCase() |
|
{ |
|
AkonadiTest::checkTestIsIsolated(); |
|
|
|
auto kernel = new DummyKernel(nullptr); |
|
CommonKernel->registerKernelIf(kernel); |
|
CommonKernel->registerSettingsIf(kernel); |
|
|
|
mFolderTreeWidget = new MailCommon::FolderTreeWidget(nullptr); |
|
const QStringList resourceOrder{"akonadi_knut_resource_2", "akonadi_knut_resource_0"}; // _1 isn't specified so it goes at the end |
|
mFolderTreeWidget->entityOrderProxy()->setTopLevelOrder(resourceOrder); |
|
|
|
mCollectionModel = KernelIf->collectionModel(); |
|
mTopModel = mFolderTreeWidget->folderTreeView()->model(); |
|
|
|
// One knut resource is already defined in the unittestenv, so that it's below "Search" in the ETM. |
|
QTRY_COMPARE(mCollectionModel->rowCount(), 2); |
|
QCOMPARE(mTopModel->rowCount(), 1); // Search doesn't appear yet |
|
mFolderNames = QStringList{"res1"}; |
|
QCOMPARE(collectNames(mTopModel), mFolderNames); |
|
} |
|
|
|
void createAndDeleteSearchCollection() |
|
{ |
|
#ifdef SHOW_WIDGET |
|
mFolderTreeWidget->resize(1000, 1000); |
|
mFolderTreeWidget->show(); |
|
#endif |
|
|
|
// Create search folder |
|
Akonadi::SearchQuery query; |
|
query.addTerm(Akonadi::SearchTerm(QStringLiteral("plugin"), 1)); |
|
auto create = new SearchCreateJob(QStringLiteral("search123456"), query, this); |
|
create->setSearchMimeTypes({KMime::Message::mimeType()}); |
|
create->setRemoteSearchEnabled(false); |
|
AKVERIFYEXEC(create); |
|
const Collection searchCol = create->createdCollection(); |
|
QVERIFY(searchCol.isValid()); |
|
|
|
// Check it appeared in the tree, under a Search toplevel item |
|
QTRY_COMPARE(mCollectionModel->rowCount(), 2); |
|
QTRY_COMPARE(mTopModel->rowCount(), 2); |
|
const QStringList names = collectNames(mTopModel); |
|
QCOMPARE(names, |
|
QStringList() << "res1" |
|
<< "Search"); |
|
const int rowOfSearch = names.indexOf("Search"); |
|
const QModelIndex searchParent = mTopModel->index(rowOfSearch, 0); |
|
QCOMPARE(mTopModel->rowCount(searchParent), 1); // the actual child search folder |
|
|
|
#ifdef SHOW_WIDGET |
|
QTest::qWait(500); |
|
#endif |
|
|
|
QSignalSpy rATBRSpy_CollectionModel(mCollectionModel, &QAbstractItemModel::rowsAboutToBeRemoved); |
|
QSignalSpy rATBRSpy_FolderTreeProxyModel(mFolderTreeWidget->folderTreeWidgetProxyModel(), &QAbstractItemModel::rowsAboutToBeRemoved); |
|
QSignalSpy rATBRSpy_TopModel(mTopModel, &QAbstractItemModel::rowsAboutToBeRemoved); |
|
|
|
// Now delete it |
|
auto delJob = new Akonadi::CollectionDeleteJob(searchCol); |
|
AKVERIFYEXEC(delJob); |
|
|
|
// Check it disappeared from the tree, as well as the toplevel item |
|
QTRY_COMPARE(mTopModel->rowCount(), 1); |
|
QCOMPARE(collectNames(mTopModel), mFolderNames); |
|
QCOMPARE(collectNames(mFolderTreeWidget->entityOrderProxy()), mFolderNames); |
|
|
|
QCOMPARE(rATBRSpy_CollectionModel.count(), 2); // one for the child, one for the parent |
|
QCOMPARE(rATBRSpy_FolderTreeProxyModel.count(), 2); // one for the child, one for the parent |
|
QCOMPARE(rATBRSpy_TopModel.count(), 2); // one for the child, one for the parent |
|
|
|
checkMailFolders(mTopModel->index(0, 0)); |
|
|
|
#ifdef SHOW_WIDGET |
|
QTest::qWait(1000); |
|
#endif |
|
} |
|
|
|
void testCreateResources() |
|
{ |
|
// Test creating more knut resources. |
|
// This tests that ETM and proxies on top update correctly, and it tests toplevel collection order. |
|
const QVector<int> numFolders{1, 5, 2}; |
|
QVector<Collection> topLevelCollections; |
|
const AgentType agentType = AgentManager::self()->type(QStringLiteral("akonadi_knut_resource")); |
|
QVERIFY(agentType.isValid()); |
|
mFolderNames = QStringList{"res3", "res1", "res2"}; // according to resourceOrder above (the folder names are defined in testdata-res*.xml) |
|
|
|
// Create resources |
|
const int numResources = numFolders.count(); |
|
for (int i = 1 /*first one already created*/; i < numResources; ++i) { |
|
auto agentCreateJob = new AgentInstanceCreateJob(agentType); |
|
AKVERIFYEXEC(agentCreateJob); |
|
const QString identifier = agentCreateJob->instance().identifier(); |
|
|
|
QTRY_COMPARE(mCollectionModel->rowCount(), i + 1); |
|
QTRY_COMPARE(mTopModel->rowCount(), i + 1); |
|
|
|
Collection topLevelCollection; |
|
QTRY_VERIFY((topLevelCollection = topLevelCollectionForResource(identifier)).isValid()); |
|
topLevelCollections.append(topLevelCollection); |
|
|
|
// Now create some folders |
|
for (int number = 0; number < numFolders[i]; ++number) { |
|
Collection mailCollection; |
|
mailCollection.setParentCollection(topLevelCollection); |
|
mailCollection.setName(QStringLiteral("mailCollection_%1_%2").arg(i).arg(number)); |
|
auto collCreateJob = new CollectionCreateJob(mailCollection); |
|
AKVERIFYEXEC(collCreateJob); |
|
} |
|
const int resourceRow = collectNames(mTopModel).indexOf("res" + QString::number(i + 1)); |
|
QModelIndex parent = mTopModel->index(resourceRow, 0); |
|
QTRY_COMPARE(mTopModel->rowCount(parent), numFolders[i]); |
|
|
|
checkMailFolders(parent); |
|
} |
|
QCOMPARE(collectNames(mTopModel), mFolderNames); |
|
} |
|
|
|
void testMoveFolder() |
|
{ |
|
// Given a source folder with 2 levels of parents (res1/sub1/sub2) |
|
const QStringList folderNames = collectNames(mCollectionModel); |
|
const QModelIndex res1Index = mCollectionModel->index(folderNames.indexOf("res1"), 0, QModelIndex()); |
|
const auto topLevelCollection = res1Index.data(EntityTreeModel::CollectionRole).value<Collection>(); |
|
QCOMPARE(topLevelCollection.name(), QStringLiteral("res1")); |
|
const int parentCount = 2; |
|
Collection currentColl = topLevelCollection; |
|
for (int number = 0; number < parentCount; ++number) { |
|
Collection mailCollection; |
|
mailCollection.setParentCollection(currentColl); |
|
mailCollection.setName(QStringLiteral("sub%1").arg(number + 1)); |
|
auto collCreateJob = new CollectionCreateJob(mailCollection); |
|
AKVERIFYEXEC(collCreateJob); |
|
currentColl = collCreateJob->collection(); |
|
} |
|
QTRY_COMPARE(mCollectionModel->rowCount(res1Index), 1); |
|
|
|
// ... and a dest folder in another resource |
|
const QPersistentModelIndex res2Index = mCollectionModel->index(folderNames.indexOf("res2"), 0, QModelIndex()); |
|
const int origRowCount = mCollectionModel->rowCount(res2Index); |
|
const auto newParentCollection = res2Index.data(EntityTreeModel::CollectionRole).value<Collection>(); |
|
QCOMPARE(newParentCollection.name(), QStringLiteral("res2")); |
|
|
|
QTest::qWait(100); // #### akonadi bug? Without this, a warning "Only resources can modify remote identifiers" appears |
|
|
|
// When moving the source folder (sub2) to the dest folder |
|
auto collMoveJob = new CollectionMoveJob(currentColl, newParentCollection); |
|
AKVERIFYEXEC(collMoveJob); |
|
|
|
// wait for Akonadi::Monitor::collectionMoved |
|
QTRY_COMPARE(mCollectionModel->rowCount(res2Index), origRowCount + 1); |
|
|
|
#ifdef SHOW_WIDGET |
|
QTest::qWait(1000); |
|
#endif |
|
} |
|
|
|
private: |
|
static Collection topLevelCollectionForResource(const QString &identifier) |
|
{ |
|
// Find out the collection for the resource (as defined in unittestenv/xdglocal/testdata-res*.xml) |
|
auto job = new CollectionFetchJob(Collection::root(), CollectionFetchJob::FirstLevel); |
|
if (job->exec()) { |
|
const Collection::List collections = job->collections(); |
|
for (const Collection &col : collections) { |
|
// qDebug() << col.resource() << col.mimeType(); |
|
if (col.resource() == identifier) { |
|
return col; |
|
} |
|
} |
|
} else { |
|
qWarning() << job->errorString(); |
|
} |
|
return Collection(); |
|
} |
|
|
|
// Check that every child of @p parent has a valid CollectionRole. |
|
static void checkMailFolders(const QModelIndex &parent) |
|
{ |
|
const QAbstractItemModel *model = parent.model(); |
|
QVERIFY(model); |
|
for (int row = 0; row < model->rowCount(parent); ++row) { |
|
QModelIndex idx = model->index(row, 0, parent); |
|
QModelIndex col1idx = model->index(row, 1, parent); |
|
QCOMPARE(col1idx.sibling(col1idx.row(), 0), idx); |
|
auto collection = idx.data(EntityTreeModel::CollectionRole).value<Collection>(); |
|
QVERIFY2(collection.isValid(), qPrintable(idx.data().toString())); |
|
} |
|
} |
|
|
|
static QStringList collectNames(QAbstractItemModel *model); |
|
EntityMimeTypeFilterModel *mCollectionModel = nullptr; |
|
QAbstractItemModel *mTopModel = nullptr; |
|
MailCommon::FolderTreeWidget *mFolderTreeWidget = nullptr; |
|
QStringList mFolderNames; |
|
}; |
|
|
|
QStringList FolderTreeWidgetTest::collectNames(QAbstractItemModel *model) |
|
{ |
|
QStringList ret; |
|
ret.reserve(model->rowCount()); |
|
for (int row = 0; row < model->rowCount(); ++row) { |
|
ret.append(model->index(row, 0).data().toString()); |
|
} |
|
return ret; |
|
} |
|
|
|
QTEST_AKONADIMAIN(FolderTreeWidgetTest) |
|
|
|
#include "foldertreewidgettest.moc"
|
|
|