]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/tests/placesitemmodeltest.cpp
Add Flatpak patches to Dolphin depending on CMake definition
[dolphin.git] / src / tests / placesitemmodeltest.cpp
index ef24292ed42ea2137306397c512cc37058bf9256..15a494691db6bdd603571ad5c1f59f31f0f21296 100644 (file)
@@ -1,53 +1,30 @@
-/***************************************************************************
- *   Copyright (C) 2017 by Renato Araujo Oliveira <renato.araujo@kdab.com> *
- *                                                                         *
- *   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            *
- ***************************************************************************/
+/*
+ * SPDX-FileCopyrightText: 2017 Renato Araujo Oliveira <renato.araujo@kdab.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
 
 #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 <KProtocolInfo>
 
+#include "dolphin_generalsettings.h"
 #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";
@@ -57,7 +34,7 @@ class PlacesItemModelTest : public QObject
 {
     Q_OBJECT
 
-private slots:
+private Q_SLOTS:
     void init();
     void cleanup();
 
@@ -83,11 +60,20 @@ private slots:
     void testIcons();
     void testDragAndDrop();
     void testHideDevices();
+    void testDuplicatedEntries();
+    void renameAfterCreation();
 
 private:
     PlacesItemModel* m_model;
     QSet<int> m_tobeRemoved;
     QMap<QString, QDBusInterface *> m_interfacesMap;
+    int m_expectedModelCount = 14;
+    bool m_hasDesktopFolder = false;
+    bool m_hasDocumentsFolder = false;
+    bool m_hasDownloadsFolder = false;
+    bool m_hasMusicFolder = false;
+    bool m_hasPicturesFolder = false;
+    bool m_hasVideosFolder = false;
 
     void setBalooEnabled(bool enabled);
     int indexOf(const QUrl &url);
@@ -96,10 +82,11 @@ private:
     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 schedulePlaceRemoval(int index);
     void cancelPlaceRemoval(int index);
-    void removeTestUserData();
     QMimeData *createMimeData(const QList<int> &indexes) const;
+    void increaseIndexIfNeeded(int &index) const;
+    QTemporaryDir m_tempHomeDir;
 };
 
 #define CHECK_PLACES_URLS(urls)                                             \
@@ -164,11 +151,46 @@ QStringList PlacesItemModelTest::initialUrls() const
 {
     static QStringList urls;
     if (urls.isEmpty()) {
-        urls << QDir::homePath() << QStringLiteral(KDE_ROOT_PATH) << QStringLiteral("trash:/")
+        urls << QDir::homePath();
+
+        if (m_hasDesktopFolder) {
+            urls << QDir::homePath() + QStringLiteral("/Desktop");
+        }
+
+        if (m_hasDocumentsFolder) {
+            urls << QDir::homePath() + QStringLiteral("/Documents");
+        }
+
+        if (m_hasDownloadsFolder) {
+            urls << QDir::homePath() + QStringLiteral("/Downloads");
+        }
+
+        if (m_hasMusicFolder) {
+            urls << QDir::homePath() + QStringLiteral("/Music");
+        }
+
+        if (m_hasPicturesFolder) {
+            urls << QDir::homePath() + QStringLiteral("/Pictures");
+        }
+
+        if (m_hasVideosFolder) {
+            urls << QDir::homePath() + QStringLiteral("/Videos");
+        }
+
+        urls << 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/nfs");
+
+        if (qEnvironmentVariableIsSet("KDE_FULL_SESSION") && KProtocolInfo::isKnownProtocol(QStringLiteral("recentlyused"))) {
+            urls << QStringLiteral("recentlyused:/files");
+            urls << QStringLiteral("recentlyused:/locations");
+        } else {
+            urls << QStringLiteral("timeline:/today")
+                 << QStringLiteral("timeline:/yesterday");
+        }
+
+        urls << QStringLiteral("search:/documents") << QStringLiteral("search:/images") << QStringLiteral("search:/audio") << QStringLiteral("search:/videos")
+             << QStringLiteral("/foreign")
              << QStringLiteral("/media/floppy0") << QStringLiteral("/media/XO-Y4") << QStringLiteral("/media/cdrom");
     }
     return urls;
@@ -179,7 +201,7 @@ void PlacesItemModelTest::createPlaceItem(const QString &text, const QUrl &url,
     m_model->createPlacesItem(text, url, icon);
 }
 
-void PlacesItemModelTest::removePlaceAfter(int index)
+void PlacesItemModelTest::schedulePlaceRemoval(int index)
 {
     m_tobeRemoved.insert(index);
 }
@@ -189,15 +211,6 @@ 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;
@@ -221,17 +234,40 @@ QMimeData *PlacesItemModelTest::createMimeData(const QList<int> &indexes) const
     return mimeData;
 }
 
+void PlacesItemModelTest::increaseIndexIfNeeded(int &index) const
+{
+    if (m_hasDesktopFolder) {
+        index++;
+    }
+    if (m_hasDocumentsFolder) {
+        index++;
+    }
+    if (m_hasDownloadsFolder) {
+        index++;
+    }
+    if (m_hasMusicFolder) {
+        index++;
+    }
+    if (m_hasPicturesFolder) {
+        index++;
+    }
+    if (m_hasVideosFolder) {
+        index++;
+    }
+}
+
 void PlacesItemModelTest::init()
 {
     m_model = new PlacesItemModel();
-    // WORKAROUND: need to wait for bookmark to load, check: PlacesItemModel::updateBookmarks
+    // WORKAROUND: need to wait for bookmark to load
     QTest::qWait(300);
-    QCOMPARE(m_model->count(), 17);
+    QCOMPARE(m_model->count(), m_expectedModelCount);
 }
 
 void PlacesItemModelTest::cleanup()
 {
-    for (int i : m_tobeRemoved) {
+    const auto tobeRemoved = m_tobeRemoved;
+    for (const int i : tobeRemoved) {
         int before = m_model->count();
         m_model->deleteItem(i);
         QTRY_COMPARE(m_model->count(), before - 1);
@@ -239,14 +275,15 @@ void PlacesItemModelTest::cleanup()
     m_tobeRemoved.clear();
     delete m_model;
     m_model = nullptr;
-    removeTestUserData();
 }
 
 void PlacesItemModelTest::initTestCase()
 {
+    QVERIFY(m_tempHomeDir.isValid());
+    QVERIFY(qputenv("HOME", m_tempHomeDir.path().toUtf8()));
+    QVERIFY(qputenv("KDE_FORK_SLAVES", "yes"));
+
     QStandardPaths::setTestModeEnabled(true);
-    // remove test user data
-    removeTestUserData();
 
     const QString fakeHw = QFINDTESTDATA("data/fakecomputer.xml");
     QVERIFY(!fakeHw.isEmpty());
@@ -259,6 +296,36 @@ void PlacesItemModelTest::initTestCase()
         QVERIFY(QFile::remove(bookmarsFileName));
     }
 
+    if (QDir(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)).exists()) {
+        m_hasDesktopFolder = true;
+        m_expectedModelCount++;
+    }
+
+    if (QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)).exists()) {
+        m_hasDocumentsFolder = true;
+        m_expectedModelCount++;
+    }
+
+    if (QDir(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)).exists()) {
+        m_hasDownloadsFolder = true;
+        m_expectedModelCount++;
+    }
+
+    if (QDir(QStandardPaths::writableLocation(QStandardPaths::MusicLocation)).exists()) {
+        m_hasMusicFolder = true;
+        m_expectedModelCount++;
+    }
+
+    if (QDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)).exists()) {
+        m_hasPicturesFolder = true;
+        m_expectedModelCount++;
+    }
+
+    if (QDir(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation)).exists()) {
+        m_hasVideosFolder = true;
+        m_expectedModelCount++;
+    }
+
     qRegisterMetaType<KItemRangeList>();
     qRegisterMetaType<KItemRange>();
 }
@@ -267,9 +334,6 @@ void PlacesItemModelTest::cleanupTestCase()
 {
     qDeleteAll(m_interfacesMap);
     QFile::remove(bookmarksFile());
-
-    // Remove any previous properties file
-    removeTestUserData();
 }
 
 void PlacesItemModelTest::testModelSort()
@@ -280,25 +344,27 @@ void PlacesItemModelTest::testModelSort()
 void PlacesItemModelTest::testGroups()
 {
     const auto groups = m_model->groups();
+    int expectedRemoteIndex = 2;
+    increaseIndexIfNeeded(expectedRemoteIndex);
 
     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).first, expectedRemoteIndex);
     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(2).first, expectedRemoteIndex + 2);
+    QCOMPARE(groups.at(2).second.toString(), QStringLiteral("Recent"));
 
-    QCOMPARE(groups.at(3).first, 8);
+    QCOMPARE(groups.at(3).first, expectedRemoteIndex + 4);
     QCOMPARE(groups.at(3).second.toString(), QStringLiteral("Search For"));
 
-    QCOMPARE(groups.at(4).first, 12);
+    QCOMPARE(groups.at(4).first, expectedRemoteIndex + 8);
     QCOMPARE(groups.at(4).second.toString(), QStringLiteral("Devices"));
 
-    QCOMPARE(groups.at(5).first, 14);
+    QCOMPARE(groups.at(5).first, expectedRemoteIndex + 9);
     QCOMPARE(groups.at(5).second.toString(), QStringLiteral("Removable Devices"));
 }
 
@@ -316,9 +382,6 @@ void PlacesItemModelTest::testPlaceItem_data()
     // 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;
 }
@@ -349,9 +412,12 @@ void PlacesItemModelTest::testDeletePlace()
 
     PlacesItemModel *model = new PlacesItemModel();
 
+    int tempDirIndex = 2;
+    increaseIndexIfNeeded(tempDirIndex);
+
     // create a new place
     createPlaceItem(QStringLiteral("Temporary Dir"), tempUrl, QString());
-    urls.insert(3, tempUrl.toLocalFile());
+    urls.insert(tempDirIndex, tempUrl.toLocalFile());
 
     // check if the new entry was created
     QTRY_COMPARE(itemsInsertedSpy.count(), 1);
@@ -359,11 +425,11 @@ void PlacesItemModelTest::testDeletePlace()
     QTRY_COMPARE(model->count(), m_model->count());
 
     // delete item
-    m_model->deleteItem(3);
+    m_model->deleteItem(tempDirIndex);
 
     // make sure that the new item is removed
     QTRY_COMPARE(itemsRemovedSpy.count(), 1);
-    QTRY_COMPARE(m_model->count(), 17);
+    QTRY_COMPARE(m_model->count(), m_expectedModelCount);
     CHECK_PLACES_URLS(initialUrls());
     QTRY_COMPARE(model->count(), m_model->count());
 }
@@ -380,11 +446,11 @@ void PlacesItemModelTest::testTearDownDevice()
     auto teardownAction = m_model->teardownAction(index);
     QVERIFY(teardownAction);
 
-    QCOMPARE(m_model->count(), 17);
+    QCOMPARE(m_model->count(), m_expectedModelCount);
 
     QSignalSpy spyItemsRemoved(m_model, &PlacesItemModel::itemsRemoved);
     fakeManager()->call(QStringLiteral("unplug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
-    QTRY_COMPARE(m_model->count(), 16);
+    QTRY_COMPARE(m_model->count(), m_expectedModelCount - 1);
     QCOMPARE(spyItemsRemoved.count(), 1);
     const QList<QVariant> spyItemsRemovedArgs = spyItemsRemoved.takeFirst();
     const KItemRangeList removedRange = spyItemsRemovedArgs.at(0).value<KItemRangeList>();
@@ -396,7 +462,7 @@ void PlacesItemModelTest::testTearDownDevice()
 
     QSignalSpy spyItemsInserted(m_model, &PlacesItemModel::itemsInserted);
     fakeManager()->call(QStringLiteral("plug"), "/org/kde/solid/fakehw/volume_part1_size_993284096");
-    QTRY_COMPARE(m_model->count(), 17);
+    QTRY_COMPARE(m_model->count(), m_expectedModelCount);
     QCOMPARE(spyItemsInserted.count(), 1);
     index = indexOf(mediaUrl);
 
@@ -423,9 +489,6 @@ void PlacesItemModelTest::testDefaultViewProperties_data()
     // 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"});
 
@@ -438,20 +501,30 @@ void PlacesItemModelTest::testDefaultViewProperties()
     QFETCH(bool, expectedPreviewShow);
     QFETCH(QList<QByteArray>, expectedVisibleRole);
 
+    // In order to test the default view properties, turn off the global view properties and re-init the test to reload the model.
+    GeneralSettings* settings = GeneralSettings::self();
+    settings->setGlobalViewProps(false);
+    settings->save();
+    cleanup();
+    init();
+
     ViewProperties properties(KFilePlacesModel::convertedUrl(url));
     QCOMPARE(properties.viewMode(), expectedViewMode);
     QCOMPARE(properties.previewsShown(), expectedPreviewShow);
     QCOMPARE(properties.visibleRoles(), expectedVisibleRole);
+
+    settings->setGlobalViewProps(true);
+    settings->save();
 }
 
 void PlacesItemModelTest::testClear()
 {
-    QCOMPARE(m_model->count(), 17);
+    QCOMPARE(m_model->count(), m_expectedModelCount);
     m_model->clear();
     QCOMPARE(m_model->count(), 0);
     QCOMPARE(m_model->hiddenCount(), 0);
     m_model->refresh();
-    QTRY_COMPARE(m_model->count(), 17);
+    QTRY_COMPARE(m_model->count(), m_expectedModelCount);
 }
 
 void PlacesItemModelTest::testHideItem()
@@ -474,7 +547,7 @@ void PlacesItemModelTest::testHideItem()
     item->setHidden(true);
 
     // check if items removed was fired
-    QTRY_COMPARE(m_model->count(), 16);
+    QTRY_COMPARE(m_model->count(), m_expectedModelCount - 1);
     QCOMPARE(spyItemsRemoved.count(), 1);
     spyItemsRemovedArgs = spyItemsRemoved.takeFirst();
     removedRange = spyItemsRemovedArgs.at(0).value<KItemRangeList>();
@@ -499,12 +572,15 @@ void PlacesItemModelTest::testHideItem()
      // mark model to hide invisible items
     m_model->setHiddenItemsShown(true);
 
-    QTRY_COMPARE(m_model->count(), 17);
+    QTRY_COMPARE(m_model->count(), m_expectedModelCount);
 }
 
 void PlacesItemModelTest::testSystemItems()
 {
-    QCOMPARE(m_model->count(), 17);
+    int tempDirIndex = 2;
+    increaseIndexIfNeeded(tempDirIndex);
+
+    QCOMPARE(m_model->count(), m_expectedModelCount);
     for (int r = 0; r < m_model->count(); r++) {
         QCOMPARE(m_model->placesItem(r)->isSystemItem(), !m_model->placesItem(r)->device().isValid());
     }
@@ -518,63 +594,68 @@ void PlacesItemModelTest::testSystemItems()
     QTRY_COMPARE(itemsInsertedSpy.count(), 1);
 
     // make sure the new place get removed
-    removePlaceAfter(3);
+    schedulePlaceRemoval(tempDirIndex);
 
     QList<QVariant> args = itemsInsertedSpy.takeFirst();
     KItemRangeList range = args.at(0).value<KItemRangeList>();
-    QCOMPARE(range.first().index, 3);
+    QCOMPARE(range.first().index, tempDirIndex);
     QCOMPARE(range.first().count, 1);
-    QVERIFY(!m_model->placesItem(3)->isSystemItem());
-    QCOMPARE(m_model->count(), 18);
+    QVERIFY(!m_model->placesItem(tempDirIndex)->isSystemItem());
+    QCOMPARE(m_model->count(), m_expectedModelCount + 1);
 
     QTest::qWait(300);
     // check if the removal signal is correct
     QSignalSpy itemsRemovedSpy(m_model, &PlacesItemModel::itemsRemoved);
-    m_model->deleteItem(3);
+    m_model->deleteItem(tempDirIndex);
     QTRY_COMPARE(itemsRemovedSpy.count(), 1);
     args = itemsRemovedSpy.takeFirst();
     range = args.at(0).value<KItemRangeList>();
-    QCOMPARE(range.first().index, 3);
+    QCOMPARE(range.first().index, tempDirIndex);
     QCOMPARE(range.first().count, 1);
-    QTRY_COMPARE(m_model->count(), 17);
+    QTRY_COMPARE(m_model->count(), m_expectedModelCount);
 
     //cancel removal (it was removed above)
-    cancelPlaceRemoval(3);
+    cancelPlaceRemoval(tempDirIndex);
 }
 
 void PlacesItemModelTest::testEditBookmark()
 {
-    const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
+    int tempDirIndex = 2;
+    increaseIndexIfNeeded(tempDirIndex);
+
     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);
+    schedulePlaceRemoval(tempDirIndex);
 
     QSignalSpy itemsChangedSply(m_model, &PlacesItemModel::itemsChanged);
 
     // modify place text
-    m_model->item(3)->setText(QStringLiteral("Renamed place"));
+    m_model->item(tempDirIndex)->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().index, tempDirIndex);
     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"));
+    QCOMPARE(m_model->item(tempDirIndex)->text(), QStringLiteral("Renamed place"));
 
     // check if the item was updated in the other model
-    QTRY_COMPARE(other->item(3)->text(), QStringLiteral("Renamed place"));
+    QTRY_COMPARE(other->item(tempDirIndex)->text(), QStringLiteral("Renamed place"));
 }
 
 void PlacesItemModelTest::testEditAfterCreation()
 {
+    int tempDirIndex = 2;
+    increaseIndexIfNeeded(tempDirIndex);
+
     const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
     QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
 
@@ -586,24 +667,27 @@ void PlacesItemModelTest::testEditAfterCreation()
     QTRY_COMPARE(model->count(), m_model->count());
 
     // make sure that the new item will be removed later
-    removePlaceAfter(3);
+    schedulePlaceRemoval(tempDirIndex);
 
     // modify place text
-    PlacesItem *item = m_model->placesItem(3);
+    PlacesItem *item = m_model->placesItem(tempDirIndex);
     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());
+    QTRY_COMPARE(model->placesItem(tempDirIndex)->text(), m_model->placesItem(tempDirIndex)->text());
+    QTRY_COMPARE(model->placesItem(tempDirIndex)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
+                 m_model->placesItem(tempDirIndex)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
+    QTRY_COMPARE(model->placesItem(tempDirIndex)->icon(), m_model->placesItem(tempDirIndex)->icon());
+    QTRY_COMPARE(model->placesItem(tempDirIndex)->url(), m_model->placesItem(tempDirIndex)->url());
 }
 
 void PlacesItemModelTest::testEditMetadata()
 {
+    int tempDirIndex = 2;
+    increaseIndexIfNeeded(tempDirIndex);
+
     const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
     QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
 
@@ -616,25 +700,28 @@ void PlacesItemModelTest::testEditMetadata()
     QTRY_COMPARE(model->count(), m_model->count());
 
     // make sure that the new item will be removed later
-    removePlaceAfter(3);
+    schedulePlaceRemoval(tempDirIndex);
 
     // modify place metadata
-    PlacesItem *item = m_model->placesItem(3);
-    item->bookmark().setMetaDataItem(QStringLiteral("OnlyInApp"), KAboutData::applicationData().componentName());
+    auto bookmark = m_model->placesItem(tempDirIndex)->bookmark();
+    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")),
+    QTRY_COMPARE(model->placesItem(tempDirIndex)->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());
+    QTRY_COMPARE(model->placesItem(tempDirIndex)->text(), m_model->placesItem(tempDirIndex)->text());
+    QTRY_COMPARE(model->placesItem(tempDirIndex)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")),
+                 m_model->placesItem(tempDirIndex)->bookmark().metaDataItem(QStringLiteral("OnlyInApp")));
+    QTRY_COMPARE(model->placesItem(tempDirIndex)->icon(), m_model->placesItem(tempDirIndex)->icon());
+    QTRY_COMPARE(model->placesItem(tempDirIndex)->url(), m_model->placesItem(tempDirIndex)->url());
 }
 
 void PlacesItemModelTest::testRefresh()
 {
+    int tempDirIndex = 2;
+    increaseIndexIfNeeded(tempDirIndex);
+
     const QUrl tempUrl = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
     QSignalSpy itemsInsertedSpy(m_model, &PlacesItemModel::itemsInserted);
 
@@ -646,10 +733,10 @@ void PlacesItemModelTest::testRefresh()
     QTRY_COMPARE(model->count(), m_model->count());
 
     // make sure that the new item will be removed later
-    removePlaceAfter(3);
+    schedulePlaceRemoval(tempDirIndex);
 
-    PlacesItem *item = m_model->placesItem(3);
-    PlacesItem *sameItem = model->placesItem(3);
+    PlacesItem *item = m_model->placesItem(tempDirIndex);
+    PlacesItem *sameItem = model->placesItem(tempDirIndex);
     QCOMPARE(item->text(), sameItem->text());
 
     // modify place text
@@ -676,9 +763,6 @@ void PlacesItemModelTest::testIcons_data()
     // 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");
 }
@@ -698,17 +782,21 @@ void PlacesItemModelTest::testIcons()
 
 void PlacesItemModelTest::testDragAndDrop()
 {
+    int lastIndex = 1; // last index of places group
+    increaseIndexIfNeeded(lastIndex);
+
     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);
+    // Move the home directory to the end of the places group
+    QMimeData *dropData = createMimeData(QList<int>() << 0);
     m_model->dropMimeDataBefore(m_model->count() - 1, dropData);
-    urls.move(1, 2);
+    urls.move(0, lastIndex);
     delete dropData;
 
     QTRY_COMPARE(itemsInsertedSpy.count(), 1);
@@ -719,24 +807,24 @@ void PlacesItemModelTest::testDragAndDrop()
     range = args.at(0).value<KItemRangeList>();
     QCOMPARE(range.size(), 1);
     QCOMPARE(range.at(0).count, 1);
-    QCOMPARE(range.at(0).index, 1);
+    QCOMPARE(range.at(0).index, 0);
 
     // 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);
+    QCOMPARE(range.at(0).index, lastIndex);
 
     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);
+    // Move home directory item back to its original position
+    dropData = createMimeData(QList<int>() << lastIndex);
+    m_model->dropMimeDataBefore(0, dropData);
+    urls.move(lastIndex, 0);
     delete dropData;
 
     QTRY_COMPARE(itemsInsertedSpy.count(), 1);
@@ -747,14 +835,14 @@ void PlacesItemModelTest::testDragAndDrop()
     range = args.at(0).value<KItemRangeList>();
     QCOMPARE(range.size(), 1);
     QCOMPARE(range.at(0).count, 1);
-    QCOMPARE(range.at(0).index, 2);
+    QCOMPARE(range.at(0).index, lastIndex);
 
     // 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);
+    QCOMPARE(range.at(0).index, 0);
 
     CHECK_PLACES_URLS(urls);
 }
@@ -780,6 +868,70 @@ void PlacesItemModelTest::testHideDevices()
     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()
+{
+    int tempDirIndex = 2;
+    increaseIndexIfNeeded(tempDirIndex);
+
+    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(tempDirIndex, tempUrl.toLocalFile());
+
+    // make sure that the new item will be removed later
+    schedulePlaceRemoval(tempDirIndex);
+
+    CHECK_PLACES_URLS(urls);
+    QCOMPARE(model->count(), m_model->count());
+
+
+    // modify place text
+    QSignalSpy changedSpy(m_model, &PlacesItemModel::itemsChanged);
+
+    PlacesItem *item = m_model->placesItem(tempDirIndex);
+    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(tempDirIndex)->text(), QStringLiteral("New Temporary Dir"));
+    QTRY_COMPARE(model->placesItem(tempDirIndex)->text(), QStringLiteral("New Temporary Dir"));
 }
 
 QTEST_MAIN(PlacesItemModelTest)