File indexing completed on 2024-11-10 04:40:22

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Daniel Vrátil <dvratil@kde.org>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  *
0006  */
0007 
0008 #include "qtest_akonadi.h"
0009 
0010 #include "shared/akscopeguard.h"
0011 #include "shared/aktest.h"
0012 
0013 #include "subscriptiondialog.h"
0014 #include "subscriptionjob_p.h"
0015 #include "subscriptionmodel_p.h"
0016 
0017 #include <QCheckBox>
0018 #include <QDialog>
0019 #include <QDialogButtonBox>
0020 #include <QLineEdit>
0021 #include <QPushButton>
0022 #include <QSignalSpy>
0023 #include <QTest>
0024 #include <QTreeView>
0025 
0026 #include <deque>
0027 #include <memory>
0028 
0029 using namespace Akonadi;
0030 
0031 class SubscriptionDialogTest : public QObject
0032 {
0033     Q_OBJECT
0034 
0035     struct TestSetup {
0036         enum {
0037             defaultCollectionCount = 7,
0038         };
0039 
0040         TestSetup()
0041             : widget(std::make_unique<SubscriptionDialog>(QStringList{Collection::mimeType(), QStringLiteral("application/octet-stream")}))
0042         {
0043             widget->setAttribute(Qt::WA_DeleteOnClose, false);
0044             widget->show();
0045 
0046             model = widget->findChild<SubscriptionModel *>();
0047             QVERIFY(model);
0048             QSignalSpy modelLoadedSpy(model, &SubscriptionModel::modelLoaded);
0049 
0050             buttonBox = widget->findChild<QDialogButtonBox *>();
0051             QVERIFY(buttonBox);
0052             QVERIFY(!buttonBox->button(QDialogButtonBox::Ok)->isEnabled());
0053             searchLineEdit = widget->findChild<QLineEdit *>(QStringLiteral("searchLineEdit"));
0054             QVERIFY(searchLineEdit);
0055             subscribedOnlyChkBox = widget->findChild<QCheckBox *>(QStringLiteral("subscribedOnlyCheckBox"));
0056             QVERIFY(subscribedOnlyChkBox);
0057             collectionView = widget->findChild<QTreeView *>(QStringLiteral("collectionView"));
0058             QVERIFY(collectionView);
0059             subscribeButton = widget->findChild<QPushButton *>(QStringLiteral("subscribeButton"));
0060             QVERIFY(subscribeButton);
0061             unsubscribeButton = widget->findChild<QPushButton *>(QStringLiteral("unsubscribeButton"));
0062             QVERIFY(unsubscribeButton);
0063 
0064             QVERIFY(QTest::qWaitForWindowActive(widget.get()));
0065             QVERIFY(modelLoadedSpy.wait());
0066             QTest::qWait(100);
0067 
0068             // Helps with testing :)
0069             collectionView->expandAll();
0070 
0071             // Post-setup conditions
0072             QCOMPARE(countTotalRows(), defaultCollectionCount);
0073             QVERIFY(buttonBox->button(QDialogButtonBox::Ok)->isEnabled());
0074 
0075             valid = true;
0076         }
0077 
0078         ~TestSetup()
0079         {
0080         }
0081 
0082         int countTotalRows(const QModelIndex &parent = {}) const
0083         {
0084             const auto count = collectionView->model()->rowCount(parent);
0085             int total = count;
0086             for (int i = 0; i < count; ++i) {
0087                 total += countTotalRows(collectionView->model()->index(i, 0, parent));
0088             }
0089             return total;
0090         }
0091 
0092         static bool unsubscribeCollection(const Collection &col)
0093         {
0094             return modifySubscription({}, {col});
0095         }
0096 
0097         static bool subscribeCollection(const Collection &col)
0098         {
0099             return modifySubscription({col}, {});
0100         }
0101 
0102         static bool modifySubscription(const Collection::List &subscribe, const Collection::List &unsubscribe)
0103         {
0104             auto job = new SubscriptionJob();
0105             job->subscribe(subscribe);
0106             job->unsubscribe(unsubscribe);
0107             bool ok = false;
0108             [job, &ok]() {
0109                 AKVERIFYEXEC(job);
0110                 ok = true;
0111             }();
0112             AKVERIFY(ok);
0113 
0114             return true;
0115         }
0116 
0117         bool selectCollection(const Collection &col) const
0118         {
0119             AKVERIFY(col.isValid());
0120             const QModelIndex colIdx = indexForCollection(col);
0121             AKVERIFY(colIdx.isValid());
0122 
0123             collectionView->scrollTo(colIdx);
0124             QTest::mouseClick(collectionView->viewport(), Qt::LeftButton, {}, collectionView->visualRect(colIdx).center());
0125 
0126             AKCOMPARE(collectionView->currentIndex(), colIdx);
0127             return true;
0128         }
0129 
0130         bool isCollectionChecked(const Collection &col) const
0131         {
0132             AKVERIFY(col.isValid());
0133             const auto colIdx = indexForCollection(col);
0134             AKVERIFY(colIdx.isValid());
0135 
0136             return collectionView->model()->data(colIdx, Qt::CheckStateRole).value<Qt::CheckState>() == Qt::Checked;
0137         }
0138 
0139         void acceptDialog() const
0140         {
0141             auto button = buttonBox->button(QDialogButtonBox::Ok);
0142             QTest::mouseClick(button, Qt::LeftButton);
0143         }
0144 
0145         QModelIndex indexForCollection(const Collection &col) const
0146         {
0147             auto collectionViewModel = collectionView->model();
0148             std::deque<QModelIndex> idxQueue;
0149             idxQueue.push_back(QModelIndex{});
0150             while (!idxQueue.empty()) {
0151                 const auto idx = idxQueue.front();
0152                 idxQueue.pop_front();
0153                 if (collectionViewModel->data(idx, EntityTreeModel::CollectionIdRole).value<qint64>() == col.id()) {
0154                     return idx;
0155                 }
0156                 for (int i = 0; i < collectionViewModel->rowCount(idx); ++i) {
0157                     idxQueue.push_back(collectionViewModel->index(i, 0, idx));
0158                 }
0159             }
0160             return {};
0161         }
0162 
0163         std::unique_ptr<SubscriptionDialog> widget;
0164         QDialogButtonBox *buttonBox = nullptr;
0165         QLineEdit *searchLineEdit = nullptr;
0166         QCheckBox *subscribedOnlyChkBox = nullptr;
0167         QTreeView *collectionView = nullptr;
0168         QPushButton *subscribeButton = nullptr;
0169         QPushButton *unsubscribeButton = nullptr;
0170         SubscriptionModel *model = nullptr;
0171 
0172         bool valid = false;
0173     };
0174 
0175 private Q_SLOTS:
0176     void initTestCase()
0177     {
0178         AkonadiTest::checkTestIsIsolated();
0179     }
0180 
0181     void testSearchFilter()
0182     {
0183         TestSetup test;
0184         QVERIFY(test.valid);
0185 
0186         QTest::keyClicks(test.searchLineEdit, QStringLiteral("foo"));
0187         QCOMPARE(test.countTotalRows(), 2);
0188     }
0189 
0190     void testSubscribedOnlyCheckbox()
0191     {
0192         const auto col = Collection{AkonadiTest::collectionIdFromPath(QStringLiteral("res1/foo/bla"))};
0193         const AkScopeGuard guard([col]() {
0194             TestSetup::subscribeCollection(col);
0195         });
0196 
0197         QVERIFY(TestSetup::unsubscribeCollection(col));
0198 
0199         TestSetup test;
0200         QVERIFY(test.valid);
0201 
0202         test.subscribedOnlyChkBox->setChecked(true);
0203 
0204         QTRY_COMPARE(test.countTotalRows(), test.defaultCollectionCount - 1);
0205 
0206         test.subscribedOnlyChkBox->setChecked(false);
0207 
0208         QTRY_COMPARE(test.countTotalRows(), test.defaultCollectionCount);
0209     }
0210 
0211     void testSubscribeButton()
0212     {
0213         const auto col = Collection{AkonadiTest::collectionIdFromPath(QStringLiteral("res1/foo/bla"))};
0214         const AkScopeGuard guard([col]() {
0215             TestSetup::subscribeCollection(col);
0216         });
0217 
0218         QVERIFY(TestSetup::unsubscribeCollection(col));
0219 
0220         TestSetup test;
0221         QVERIFY(test.valid);
0222 
0223         QVERIFY(test.selectCollection(col));
0224         QTest::mouseClick(test.subscribeButton, Qt::LeftButton);
0225         QVERIFY(test.isCollectionChecked(col));
0226 
0227         auto monitor = AkonadiTest::getTestMonitor();
0228         QSignalSpy monitorSpy(monitor.get(), &Monitor::collectionSubscribed);
0229         test.acceptDialog();
0230         QVERIFY(monitorSpy.wait());
0231     }
0232 
0233     void testUnsubscribeButton()
0234     {
0235         const auto col = Collection{AkonadiTest::collectionIdFromPath(QStringLiteral("res1/foo/bla"))};
0236 
0237         TestSetup test;
0238         QVERIFY(test.valid);
0239 
0240         QVERIFY(test.selectCollection(col));
0241         QTest::mouseClick(test.unsubscribeButton, Qt::LeftButton);
0242         QVERIFY(!test.isCollectionChecked(col));
0243 
0244         auto monitor = AkonadiTest::getTestMonitor();
0245         QSignalSpy monitorSpy(monitor.get(), &Monitor::collectionUnsubscribed);
0246         test.acceptDialog();
0247         QVERIFY(monitorSpy.wait());
0248     }
0249 };
0250 
0251 QTEST_AKONADIMAIN(SubscriptionDialogTest)
0252 
0253 #include "subscriptiondialogtest.moc"