diff options
Diffstat (limited to 'src/tests/placesitemmodeltest.cpp')
| -rw-r--r-- | src/tests/placesitemmodeltest.cpp | 850 |
1 files changed, 850 insertions, 0 deletions
diff --git a/src/tests/placesitemmodeltest.cpp b/src/tests/placesitemmodeltest.cpp new file mode 100644 index 000000000..a74b3ea6c --- /dev/null +++ b/src/tests/placesitemmodeltest.cpp @@ -0,0 +1,850 @@ +/*************************************************************************** + * Copyright (C) 2017 by Renato Araujo Oliveira <[email protected]> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include <QTest> +#include <QSignalSpy> +#include <QDebug> +#include <QList> +#include <QByteArray> +#include <QStandardPaths> +#include <QAction> +#include <QDBusInterface> +#include <QUrlQuery> + +#include <KBookmarkManager> +#include <KConfig> +#include <KConfigGroup> +#include <KAboutData> +#include <KFilePlacesModel> + +#include "panels/places/placesitemmodel.h" +#include "panels/places/placesitem.h" +#include "views/viewproperties.h" +#include "kitemviews/kitemrange.h" + +Q_DECLARE_METATYPE(KItemRangeList) +Q_DECLARE_METATYPE(KItemRange) + +#ifdef Q_OS_WIN +//c:\ as root for windows +#define KDE_ROOT_PATH "C:\\" +#else +#define KDE_ROOT_PATH "/" +#endif + +static QString bookmarksFile() +{ + return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/user-places.xbel"; +} + +class PlacesItemModelTest : public QObject +{ + Q_OBJECT + +private slots: + void init(); + void cleanup(); + + void initTestCase(); + void cleanupTestCase(); + + void testModelSort(); + void testGroups(); + void testDeletePlace(); + void testPlaceItem_data(); + void testPlaceItem(); + void testTearDownDevice(); + void testDefaultViewProperties_data(); + void testDefaultViewProperties(); + void testClear(); + void testHideItem(); + void testSystemItems(); + void testEditBookmark(); + void testEditAfterCreation(); + void testEditMetadata(); + void testRefresh(); + void testIcons_data(); + void testIcons(); + void testDragAndDrop(); + void testHideDevices(); + void testDuplicatedEntries(); + void renameAfterCreation(); + +private: + PlacesItemModel* m_model; + QSet<int> m_tobeRemoved; + QMap<QString, QDBusInterface *> m_interfacesMap; + + void setBalooEnabled(bool enabled); + int indexOf(const QUrl &url); + QDBusInterface *fakeManager(); + QDBusInterface *fakeDevice(const QString &udi); + QStringList placesUrls(PlacesItemModel *model = nullptr) const; + QStringList initialUrls() const; + void createPlaceItem(const QString &text, const QUrl &url, const QString &icon); + void removePlaceAfter(int index); + void cancelPlaceRemoval(int index); + void removeTestUserData(); + QMimeData *createMimeData(const QList<int> &indexes) const; +}; + +#define CHECK_PLACES_URLS(urls) \ + { \ + QStringList places = placesUrls(); \ + if (places != urls) { \ + qWarning() << "Expected:" << urls; \ + qWarning() << "Got:" << places; \ + QCOMPARE(places, urls); \ + } \ + } + +void PlacesItemModelTest::setBalooEnabled(bool enabled) +{ + KConfig config(QStringLiteral("baloofilerc")); + KConfigGroup basicSettings = config.group("Basic Settings"); + basicSettings.writeEntry("Indexing-Enabled", enabled); + config.sync(); +} + +int PlacesItemModelTest::indexOf(const QUrl &url) +{ + for (int r = 0; r < m_model->count(); r++) { + if (m_model->placesItem(r)->url() == url) { + return r; + } + } + return -1; +} + +QDBusInterface *PlacesItemModelTest::fakeManager() +{ + return fakeDevice(QStringLiteral("/org/kde/solid/fakehw")); +} + +QDBusInterface *PlacesItemModelTest::fakeDevice(const QString &udi) +{ + if (m_interfacesMap.contains(udi)) { + return m_interfacesMap[udi]; + } + + QDBusInterface *iface = new QDBusInterface(QDBusConnection::sessionBus().baseService(), udi); + m_interfacesMap[udi] = iface; + + return iface; +} + +QStringList PlacesItemModelTest::placesUrls(PlacesItemModel *model) const +{ + QStringList urls; + if (!model) { + model = m_model; + } + + for (int row = 0; row < model->count(); ++row) { + urls << model->placesItem(row)->url().toDisplayString(QUrl::PreferLocalFile); + } + return urls; +} + +QStringList PlacesItemModelTest::initialUrls() const +{ + static QStringList urls; + if (urls.isEmpty()) { + urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/") + << QStringLiteral("remote:/") + << QStringLiteral("timeline:/today") << QStringLiteral("timeline:/yesterday") << QStringLiteral("timeline:/thismonth") << QStringLiteral("timeline:/lastmonth") + << QStringLiteral("search:/documents") << QStringLiteral("search:/images") << QStringLiteral("search:/audio") << QStringLiteral("search:/videos") + << QStringLiteral("/media/nfs") << QStringLiteral("/foreign") + << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom"); + } + return urls; +} + +void PlacesItemModelTest::createPlaceItem(const QString &text, const QUrl &url, const QString &icon) +{ + m_model->createPlacesItem(text, url, icon); +} + +void PlacesItemModelTest::removePlaceAfter(int index) +{ + m_tobeRemoved.insert(index); +} + +void PlacesItemModelTest::cancelPlaceRemoval(int index) +{ + m_tobeRemoved.remove(index); +} + +void PlacesItemModelTest::removeTestUserData() +{ + // user hardcoded path to avoid removal of any user personal data + QDir dir(QStringLiteral("/home/renato/.qttest/share/placesitemmodeltest")); + if (dir.exists()) { + QVERIFY(dir.removeRecursively()); + } +} + +QMimeData *PlacesItemModelTest::createMimeData(const QList<int> &indexes) const +{ + QByteArray itemData; + QDataStream stream(&itemData, QIODevice::WriteOnly); + QList<QUrl> urls; + + for (int index : indexes) { + const QUrl itemUrl = m_model->placesItem(index)->url(); + if (itemUrl.isValid()) { + urls << itemUrl; + } + stream << index; + } + + QMimeData* mimeData = new QMimeData(); + mimeData->setUrls(urls); + // copied from PlacesItemModel::internalMimeType() + const QString internalMimeType = "application/x-dolphinplacesmodel-" + + QString::number((qptrdiff)m_model); + mimeData->setData(internalMimeType, itemData); + return mimeData; +} + +void PlacesItemModelTest::init() +{ + m_model = new PlacesItemModel(); + // WORKAROUND: need to wait for bookmark to load, check: PlacesItemModel::updateBookmarks + QTest::qWait(300); + QCOMPARE(m_model->count(), 17); +} + +void PlacesItemModelTest::cleanup() +{ + for (int i : m_tobeRemoved) { + int before = m_model->count(); + m_model->deleteItem(i); + QTRY_COMPARE(m_model->count(), before - 1); + } + m_tobeRemoved.clear(); + delete m_model; + m_model = nullptr; + removeTestUserData(); +} + +void PlacesItemModelTest::initTestCase() +{ + QStandardPaths::setTestModeEnabled(true); + // remove test user data + removeTestUserData(); + + const QString fakeHw = QFINDTESTDATA("data/fakecomputer.xml"); + QVERIFY(!fakeHw.isEmpty()); + qputenv("SOLID_FAKEHW", QFile::encodeName(fakeHw)); + + setBalooEnabled(true); + const QString bookmarsFileName = bookmarksFile(); + if (QFileInfo::exists(bookmarsFileName)) { + // Ensure we'll have a clean bookmark file to start + QVERIFY(QFile::remove(bookmarsFileName)); + } + + qRegisterMetaType<KItemRangeList>(); + qRegisterMetaType<KItemRange>(); +} + +void PlacesItemModelTest::cleanupTestCase() +{ + qDeleteAll(m_interfacesMap); + QFile::remove(bookmarksFile()); + + // Remove any previous properties file + removeTestUserData(); +} + +void PlacesItemModelTest::testModelSort() +{ + CHECK_PLACES_URLS(initialUrls()); +} + +void PlacesItemModelTest::testGroups() +{ + const auto groups = m_model->groups(); + + QCOMPARE(groups.size(), 6); + + QCOMPARE(groups.at(0).first, 0); + QCOMPARE(groups.at(0).second.toString(), QStringLiteral("Places")); + + QCOMPARE(groups.at(1).first, 3); + QCOMPARE(groups.at(1).second.toString(), QStringLiteral("Remote")); + + QCOMPARE(groups.at(2).first, 4); + QCOMPARE(groups.at(2).second.toString(), QStringLiteral("Recently Saved")); + + QCOMPARE(groups.at(3).first, 8); + QCOMPARE(groups.at(3).second.toString(), QStringLiteral("Search For")); + + QCOMPARE(groups.at(4).first, 12); + QCOMPARE(groups.at(4).second.toString(), QStringLiteral("Devices")); + + QCOMPARE(groups.at(5).first, 14); + QCOMPARE(groups.at(5).second.toString(), QStringLiteral("Removable Devices")); +} + +void PlacesItemModelTest::testPlaceItem_data() +{ + QTest::addColumn<QUrl>("url"); + QTest::addColumn<bool>("expectedIsHidden"); + QTest::addColumn<bool>("expectedIsSystemItem"); + QTest::addColumn<QString>("expectedGroup"); + QTest::addColumn<bool>("expectedStorageSetupNeeded"); + + // places + QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << false << true << QStringLiteral("Places") << false; + + // baloo -search + QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << false << true << QStringLiteral("Search For") << false; + + // baloo - timeline + QTest::newRow("Baloo - Last Month") << QUrl("timeline:/lastmonth") << false << true << QStringLiteral("Recently Saved") << false; + + // devices + QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << false << false << QStringLiteral("Removable Devices") << false; +} + +void PlacesItemModelTest::testPlaceItem() +{ + QFETCH(QUrl, url); + QFETCH(bool, expectedIsHidden); + QFETCH(bool, expectedIsSystemItem); + QFETCH(QString, expectedGroup); + QFETCH(bool, expectedStorageSetupNeeded); + + const int index = indexOf(url); + PlacesItem *item = m_model->placesItem(index); + QCOMPARE(item->url(), url); + QCOMPARE(item->isHidden(), expectedIsHidden); + QCOMPARE(item->isSystemItem(), expectedIsSystemItem); + QCOMPARE(item->group(), expectedGroup); + QCOMPARE(item->storageSetupNeeded(), expectedStorageSetupNeeded); +} + +void PlacesItemModelTest::testDeletePlace() +{ + const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation)); + QStringList urls = initialUrls(); + QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted); + QSignalSpy itemsRemovedSpy(m_model, &PlacesItemModel::itemsRemoved); + + PlacesItemModel *model = new PlacesItemModel(); + + // create a new place + createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString()); + urls.insert(3, tempUrl.toLocalFile()); + + // check if the new entry was created + QTRY_COMPARE(itemsInsertedSpy.count(), 1); + CHECK_PLACES_URLS(urls); + QTRY_COMPARE(model->count(), m_model->count()); + + // delete item + m_model->deleteItem(3); + + // make sure that the new item is removed + QTRY_COMPARE(itemsRemovedSpy.count(), 1); + QTRY_COMPARE(m_model->count(), 17); + CHECK_PLACES_URLS(initialUrls()); + QTRY_COMPARE(model->count(), m_model->count()); +} + +void PlacesItemModelTest::testTearDownDevice() +{ + const QUrl mediaUrl = QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4")); + int index = indexOf(mediaUrl); + QVERIFY(index != -1); + + auto ejectAction = m_model->ejectAction(index); + QVERIFY(!ejectAction); + + auto teardownAction = m_model->teardownAction(index); + QVERIFY(teardownAction); + + QCOMPARE(m_model->count(), 17); + + QSignalSpy spyItemsRemoved(m_model, &PlacesItemModel::itemsRemoved); + fakeManager()->call(QStringLiteral("unplug"), "/org/kde/solid/fakehw/volume_part1_size_993284096"); + QTRY_COMPARE(m_model->count(), 16); + QCOMPARE(spyItemsRemoved.count(), 1); + const QList<QVariant> spyItemsRemovedArgs = spyItemsRemoved.takeFirst(); + const KItemRangeList removedRange = spyItemsRemovedArgs.at(0).value<KItemRangeList>(); + QCOMPARE(removedRange.size(), 1); + QCOMPARE(removedRange.first().index, index); + QCOMPARE(removedRange.first().count, 1); + + QCOMPARE(indexOf(mediaUrl), -1); + + QSignalSpy spyItemsInserted(m_model, &PlacesItemModel::itemsInserted); + fakeManager()->call(QStringLiteral("plug"), "/org/kde/solid/fakehw/volume_part1_size_993284096"); + QTRY_COMPARE(m_model->count(), 17); + QCOMPARE(spyItemsInserted.count(), 1); + index = indexOf(mediaUrl); + + const QList<QVariant> args = spyItemsInserted.takeFirst(); + const KItemRangeList insertedRange = args.at(0).value<KItemRangeList>(); + QCOMPARE(insertedRange.size(), 1); + QCOMPARE(insertedRange.first().index, index); + QCOMPARE(insertedRange.first().count, 1); +} + +void PlacesItemModelTest::testDefaultViewProperties_data() +{ + QTest::addColumn<QUrl>("url"); + QTest::addColumn<DolphinView::Mode>("expectedViewMode"); + QTest::addColumn<bool>("expectedPreviewShow"); + QTest::addColumn<QList<QByteArray> >("expectedVisibleRole"); + + // places + QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << DolphinView::IconsView << true << QList<QByteArray>({"text"}); + + // baloo -search + QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << DolphinView::DetailsView << false << QList<QByteArray>({"text", "path"}); + + // audio files + QTest::newRow("Places - Audio") << QUrl("search:/audio") << DolphinView::DetailsView << false << QList<QByteArray>({"text", "artist", "album"}); + + // baloo - timeline + QTest::newRow("Baloo - Last Month") << QUrl("timeline:/lastmonth") << DolphinView::DetailsView << true << QList<QByteArray>({"text", "modificationtime"}); + + // devices + QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << DolphinView::IconsView << true << QList<QByteArray>({"text"}); + +} + +void PlacesItemModelTest::testDefaultViewProperties() +{ + QFETCH(QUrl, url); + QFETCH(DolphinView::Mode, expectedViewMode); + QFETCH(bool, expectedPreviewShow); + QFETCH(QList<QByteArray>, expectedVisibleRole); + + ViewProperties properties(KFilePlacesModel::convertedUrl(url)); + QCOMPARE(properties.viewMode(), expectedViewMode); + QCOMPARE(properties.previewsShown(), expectedPreviewShow); + QCOMPARE(properties.visibleRoles(), expectedVisibleRole); +} + +void PlacesItemModelTest::testClear() +{ + QCOMPARE(m_model->count(), 17); + m_model->clear(); + QCOMPARE(m_model->count(), 0); + QCOMPARE(m_model->hiddenCount(), 0); + m_model->refresh(); + QTRY_COMPARE(m_model->count(), 17); +} + +void PlacesItemModelTest::testHideItem() +{ + const QUrl mediaUrl = QUrl::fromLocalFile(QStringLiteral("/media/XO-Y4")); + const int index = indexOf(mediaUrl); + + PlacesItem *item = m_model->placesItem(index); + + QSignalSpy spyItemsRemoved(m_model, &PlacesItemModel::itemsRemoved); + QList<QVariant> spyItemsRemovedArgs; + KItemRangeList removedRange; + + QSignalSpy spyItemsInserted(m_model, &PlacesItemModel::itemsInserted); + QList<QVariant> spyItemsInsertedArgs; + KItemRangeList insertedRange; + QVERIFY(item); + + // hide an item + item->setHidden(true); + + // check if items removed was fired + QTRY_COMPARE(m_model->count(), 16); + QCOMPARE(spyItemsRemoved.count(), 1); + spyItemsRemovedArgs = spyItemsRemoved.takeFirst(); + removedRange = spyItemsRemovedArgs.at(0).value<KItemRangeList>(); + QCOMPARE(removedRange.size(), 1); + QCOMPARE(removedRange.first().index, index); + QCOMPARE(removedRange.first().count, 1); + + // allow model to show hidden items + m_model->setHiddenItemsShown(true); + + // check if the items inserted was fired + spyItemsInsertedArgs = spyItemsInserted.takeFirst(); + insertedRange = spyItemsInsertedArgs.at(0).value<KItemRangeList>(); + QCOMPARE(insertedRange.size(), 1); + QCOMPARE(insertedRange.first().index, index); + QCOMPARE(insertedRange.first().count, 1); + + // mark item as visible + item = m_model->placesItem(index); + item->setHidden(false); + + // mark model to hide invisible items + m_model->setHiddenItemsShown(true); + + QTRY_COMPARE(m_model->count(), 17); +} + +void PlacesItemModelTest::testSystemItems() +{ + QCOMPARE(m_model->count(), 17); + for (int r = 0; r < m_model->count(); r++) { + QCOMPARE(m_model->placesItem(r)->isSystemItem(), !m_model->placesItem(r)->device().isValid()); + } + + QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted); + + // create a new entry (non system item) + createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation)), QString()); + + // check if the new entry was created + QTRY_COMPARE(itemsInsertedSpy.count(), 1); + + // make sure the new place get removed + removePlaceAfter(3); + + QList<QVariant> args = itemsInsertedSpy.takeFirst(); + KItemRangeList range = args.at(0).value<KItemRangeList>(); + QCOMPARE(range.first().index, 3); + QCOMPARE(range.first().count, 1); + QVERIFY(!m_model->placesItem(3)->isSystemItem()); + QCOMPARE(m_model->count(), 18); + + QTest::qWait(300); + // check if the removal signal is correct + QSignalSpy itemsRemovedSpy(m_model, &PlacesItemModel::itemsRemoved); + m_model->deleteItem(3); + QTRY_COMPARE(itemsRemovedSpy.count(), 1); + args = itemsRemovedSpy.takeFirst(); + range = args.at(0).value<KItemRangeList>(); + QCOMPARE(range.first().index, 3); + QCOMPARE(range.first().count, 1); + QTRY_COMPARE(m_model->count(), 17); + + //cancel removal (it was removed above) + cancelPlaceRemoval(3); +} + +void PlacesItemModelTest::testEditBookmark() +{ + const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation)); + QScopedPointer<PlacesItemModel> other(new PlacesItemModel()); + + createPlaceItem(QStringLiteral("Temporary Dir"), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation)), QString()); + + // make sure that the new item will be removed later + removePlaceAfter(3); + + QSignalSpy itemsChangedSply(m_model, &PlacesItemModel::itemsChanged); + + // modify place text + m_model->item(3)->setText(QStringLiteral("Renamed place")); + m_model->refresh(); + + // check if the correct signal was fired + QTRY_COMPARE(itemsChangedSply.count(), 1); + QList<QVariant> args = itemsChangedSply.takeFirst(); + KItemRangeList range = args.at(0).value<KItemRangeList>(); + QCOMPARE(range.first().index, 3); + QCOMPARE(range.first().count, 1); + QSet<QByteArray> roles = args.at(1).value<QSet<QByteArray> >(); + QCOMPARE(roles.size(), 1); + QCOMPARE(*roles.begin(), QByteArrayLiteral("text")); + QCOMPARE(m_model->item(3)->text(), QStringLiteral("Renamed place")); + + // check if the item was updated in the other model + QTRY_COMPARE(other->item(3)->text(), QStringLiteral("Renamed place")); +} + +void PlacesItemModelTest::testEditAfterCreation() +{ + const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation)); + QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted); + + // create a new place + createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString()); + QTRY_COMPARE(itemsInsertedSpy.count(), 1); + + PlacesItemModel *model = new PlacesItemModel(); + QTRY_COMPARE(model->count(), m_model->count()); + + // make sure that the new item will be removed later + removePlaceAfter(3); + + // modify place text + PlacesItem *item = m_model->placesItem(3); + item->setText(QStringLiteral("Renamed place")); + m_model->refresh(); + + // check if the second model got the changes + QTRY_COMPARE(model->count(), m_model->count()); + QTRY_COMPARE(model->placesItem(3)->text(), m_model->placesItem(3)->text()); + QTRY_COMPARE(model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")), + m_model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp"))); + QTRY_COMPARE(model->placesItem(3)->icon(), m_model->placesItem(3)->icon()); + QTRY_COMPARE(model->placesItem(3)->url(), m_model->placesItem(3)->url()); +} + +void PlacesItemModelTest::testEditMetadata() +{ + const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation)); + QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted); + + // create a new place + createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString()); + QTRY_COMPARE(itemsInsertedSpy.count(), 1); + + // check if the new entry was created + PlacesItemModel *model = new PlacesItemModel(); + QTRY_COMPARE(model->count(), m_model->count()); + + // make sure that the new item will be removed later + removePlaceAfter(3); + + // modify place metadata + PlacesItem *item = m_model->placesItem(3); + item->bookmark().setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName()); + m_model->refresh(); + + // check if the place was modified in both models + QTRY_COMPARE(model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")), + KAboutData::applicationData().componentName()); + QTRY_COMPARE(model->placesItem(3)->text(), m_model->placesItem(3)->text()); + QTRY_COMPARE(model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")), + m_model->placesItem(3)->bookmark().metaDataItem(QStringLiteral("OnlyInApp"))); + QTRY_COMPARE(model->placesItem(3)->icon(), m_model->placesItem(3)->icon()); + QTRY_COMPARE(model->placesItem(3)->url(), m_model->placesItem(3)->url()); +} + +void PlacesItemModelTest::testRefresh() +{ + const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation)); + QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted); + + // create a new place + createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString()); + QTRY_COMPARE(itemsInsertedSpy.count(), 1); + + PlacesItemModel *model = new PlacesItemModel(); + QTRY_COMPARE(model->count(), m_model->count()); + + // make sure that the new item will be removed later + removePlaceAfter(3); + + PlacesItem *item = m_model->placesItem(3); + PlacesItem *sameItem = model->placesItem(3); + QCOMPARE(item->text(), sameItem->text()); + + // modify place text + item->setText(QStringLiteral("Renamed place")); + + // item from another model is not affected at the moment + QVERIFY(item->text() != sameItem->text()); + + // propagate change + m_model->refresh(); + + // item must be equal + QTRY_COMPARE(item->text(), sameItem->text()); +} + +void PlacesItemModelTest::testIcons_data() +{ + QTest::addColumn<QUrl>("url"); + QTest::addColumn<QString>("expectedIconName"); + + // places + QTest::newRow("Places - Home") << QUrl::fromLocalFile(QDir::homePath()) << QStringLiteral("user-home"); + + // baloo -search + QTest::newRow("Baloo - Documents") << QUrl("search:/documents") << QStringLiteral("folder-text"); + + // baloo - timeline + QTest::newRow("Baloo - Last Month") << QUrl("timeline:/lastmonth") << QStringLiteral("view-calendar-month"); + + // devices + QTest::newRow("Devices - Floppy") << QUrl("file:///media/floppy0") << QStringLiteral("blockdevice"); +} + +void PlacesItemModelTest::testIcons() +{ + QFETCH(QUrl, url); + QFETCH(QString, expectedIconName); + + PlacesItem *item = m_model->placesItem(indexOf(url)); + QCOMPARE(item->icon(), expectedIconName); + + for (int r = 0; r < m_model->count(); r++) { + QVERIFY(!m_model->placesItem(r)->icon().isEmpty()); + } +} + +void PlacesItemModelTest::testDragAndDrop() +{ + QList<QVariant> args; + KItemRangeList range; + QStringList urls = initialUrls(); + QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted); + QSignalSpy itemsRemovedSpy(m_model, &PlacesItemModel::itemsRemoved); + + CHECK_PLACES_URLS(initialUrls()); + // Move the KDE_ROOT_PATH at the end of the places list will case it to be moved to the end of the places group + QMimeData *dropData = createMimeData(QList<int>() << 1); + m_model->dropMimeDataBefore(m_model->count() - 1, dropData); + urls.move(1, 2); + delete dropData; + + QTRY_COMPARE(itemsInsertedSpy.count(), 1); + QTRY_COMPARE(itemsRemovedSpy.count(), 1); + + // remove item from actual position + args = itemsRemovedSpy.takeFirst(); + range = args.at(0).value<KItemRangeList>(); + QCOMPARE(range.size(), 1); + QCOMPARE(range.at(0).count, 1); + QCOMPARE(range.at(0).index, 1); + + // insert intem in his group + args = itemsInsertedSpy.takeFirst(); + range = args.at(0).value<KItemRangeList>(); + QCOMPARE(range.size(), 1); + QCOMPARE(range.at(0).count, 1); + QCOMPARE(range.at(0).index, 2); + + CHECK_PLACES_URLS(urls); + + itemsInsertedSpy.clear(); + itemsRemovedSpy.clear(); + + // Move the KDE_ROOT_PATH to his original position + dropData = createMimeData(QList<int>() << 2); + m_model->dropMimeDataBefore(1, dropData); + urls.move(2, 1); + delete dropData; + + QTRY_COMPARE(itemsInsertedSpy.count(), 1); + QTRY_COMPARE(itemsRemovedSpy.count(), 1); + + // remove item from actual position + args = itemsRemovedSpy.takeFirst(); + range = args.at(0).value<KItemRangeList>(); + QCOMPARE(range.size(), 1); + QCOMPARE(range.at(0).count, 1); + QCOMPARE(range.at(0).index, 2); + + // insert intem in the requested position + args = itemsInsertedSpy.takeFirst(); + range = args.at(0).value<KItemRangeList>(); + QCOMPARE(range.size(), 1); + QCOMPARE(range.at(0).count, 1); + QCOMPARE(range.at(0).index, 1); + + CHECK_PLACES_URLS(urls); +} + +void PlacesItemModelTest::testHideDevices() +{ + QSignalSpy itemsRemoved(m_model, &PlacesItemModel::itemsRemoved); + QStringList urls = initialUrls(); + + m_model->setGroupHidden(KFilePlacesModel::RemovableDevicesType, true); + QTRY_VERIFY(m_model->isGroupHidden(KFilePlacesModel::RemovableDevicesType)); + QTRY_COMPARE(itemsRemoved.count(), 3); + + // remove removable-devices + urls.removeOne(QStringLiteral("/media/floppy0")); + urls.removeOne(QStringLiteral("/media/XO-Y4")); + urls.removeOne(QStringLiteral("/media/cdrom")); + + // check if the correct urls was removed + CHECK_PLACES_URLS(urls); + + delete m_model; + m_model = new PlacesItemModel(); + QTRY_COMPARE(m_model->count(), urls.count()); + CHECK_PLACES_URLS(urls); + + // revert changes + m_model->setGroupHidden(KFilePlacesModel::RemovableDevicesType, false); + urls = initialUrls(); + QTRY_COMPARE(m_model->count(), urls.count()); + CHECK_PLACES_URLS(urls); +} + +void PlacesItemModelTest::testDuplicatedEntries() +{ + QStringList urls = initialUrls(); + // create a duplicated entry on bookmark + KBookmarkManager *bookmarkManager = KBookmarkManager::managerForFile(bookmarksFile(), QStringLiteral("kfilePlaces")); + KBookmarkGroup root = bookmarkManager->root(); + KBookmark bookmark = root.addBookmark(QStringLiteral("Duplicated Search Videos"), QUrl("search:/videos"), {}); + + const QString id = QUuid::createUuid().toString(); + bookmark.setMetaDataItem(QStringLiteral("ID"), id); + bookmark.setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName()); + bookmarkManager->emitChanged(bookmarkManager->root()); + + PlacesItemModel *newModel = new PlacesItemModel(); + QTRY_COMPARE(placesUrls(newModel).count(QStringLiteral("search:/videos")), 1); + QTRY_COMPARE(urls, placesUrls(newModel)); + delete newModel; +} + +void PlacesItemModelTest::renameAfterCreation() +{ + const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation)); + QStringList urls = initialUrls(); + PlacesItemModel *model = new PlacesItemModel(); + + CHECK_PLACES_URLS(urls); + QTRY_COMPARE(model->count(), m_model->count()); + + // create a new place + createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString()); + urls.insert(3, tempUrl.toLocalFile()); + + // make sure that the new item will be removed later + removePlaceAfter(3); + + CHECK_PLACES_URLS(urls); + QCOMPARE(model->count(), m_model->count()); + + + // modify place text + QSignalSpy changedSpy(m_model, &PlacesItemModel::itemsChanged); + + PlacesItem *item = m_model->placesItem(3); + item->setText(QStringLiteral("New Temporary Dir")); + item->setUrl(item->url()); + item->setIcon(item->icon()); + m_model->refresh(); + + QTRY_COMPARE(changedSpy.count(), 1); + + // check if the place was modified in both models + QTRY_COMPARE(m_model->placesItem(3)->text(), QStringLiteral("New Temporary Dir")); + QTRY_COMPARE(model->placesItem(3)->text(), QStringLiteral("New Temporary Dir")); +} + +QTEST_MAIN(PlacesItemModelTest) + +#include "placesitemmodeltest.moc" |
