File indexing completed on 2025-01-19 04:56:54

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Kevin Ottens <ervin@kde.org>
0003  SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 
0007 #include <testlib/qtest_zanshin.h>
0008 
0009 #include "utils/mockobject.h"
0010 
0011 #define ZANSHIN_I_SWEAR_I_AM_IN_A_PRESENTATION_TEST
0012 
0013 #include "domain/datasourcequeries.h"
0014 #include "domain/datasourcerepository.h"
0015 
0016 #include "presentation/availablesourcesmodel.h"
0017 #include "presentation/querytreemodelbase.h"
0018 #include "presentation/errorhandler.h"
0019 
0020 #include "testlib/fakejob.h"
0021 
0022 Q_DECLARE_METATYPE(QModelIndex);
0023 
0024 using namespace mockitopp;
0025 using namespace mockitopp::matcher;
0026 
0027 class FakeErrorHandler : public Presentation::ErrorHandler
0028 {
0029 public:
0030     void doDisplayMessage(const QString &message) override
0031     {
0032         m_message = message;
0033     }
0034 
0035     QString m_message;
0036 };
0037 
0038 class AvailableSourcesModelTest : public QObject
0039 {
0040     Q_OBJECT
0041 public:
0042     explicit AvailableSourcesModelTest(QObject *parent = nullptr)
0043         : QObject(parent)
0044     {
0045         qRegisterMetaType<QModelIndex>();
0046     }
0047 
0048 private slots:
0049     void shouldListAvailableSources()
0050     {
0051         // GIVEN
0052 
0053         // Two top level sources
0054         auto source1 = Domain::DataSource::Ptr::create();
0055         source1->setName(QStringLiteral("Source 1"));
0056         source1->setIconName(QStringLiteral("foo-icon"));
0057         source1->setSelected(true);
0058         auto source2 = Domain::DataSource::Ptr::create();
0059         source2->setName(QStringLiteral("Source 2"));
0060         source2->setSelected(false);
0061         source2->setContentTypes(Domain::DataSource::Tasks);
0062         auto topLevelProvider = Domain::QueryResultProvider<Domain::DataSource::Ptr>::Ptr::create();
0063         auto topLevelResult = Domain::QueryResult<Domain::DataSource::Ptr>::create(topLevelProvider);
0064         topLevelProvider->append(source1);
0065         topLevelProvider->append(source2);
0066 
0067         // Two other sources under source1
0068         auto source3 = Domain::DataSource::Ptr::create();
0069         source3->setName(QStringLiteral("Source 3"));
0070         source3->setSelected(false);
0071         source3->setContentTypes(Domain::DataSource::Tasks);
0072         auto source4 = Domain::DataSource::Ptr::create();
0073         source4->setSelected(true);
0074         source4->setName(QStringLiteral("Source 4"));
0075         source4->setContentTypes(Domain::DataSource::Tasks);
0076         auto source1Provider = Domain::QueryResultProvider<Domain::DataSource::Ptr>::Ptr::create();
0077         auto source1Result = Domain::QueryResult<Domain::DataSource::Ptr>::create(source1Provider);
0078         source1Provider->append(source3);
0079         source1Provider->append(source4);
0080 
0081         // Nothing under source2, source3 or source4
0082         auto source2Provider = Domain::QueryResultProvider<Domain::DataSource::Ptr>::Ptr::create();
0083         auto source2Result = Domain::QueryResult<Domain::DataSource::Ptr>::create(source2Provider);
0084         auto source3Provider = Domain::QueryResultProvider<Domain::DataSource::Ptr>::Ptr::create();
0085         auto source3Result = Domain::QueryResult<Domain::DataSource::Ptr>::create(source3Provider);
0086         auto source4Provider = Domain::QueryResultProvider<Domain::DataSource::Ptr>::Ptr::create();
0087         auto source4Result = Domain::QueryResult<Domain::DataSource::Ptr>::create(source4Provider);
0088 
0089 
0090         Utils::MockObject<Domain::DataSourceQueries> sourceQueriesMock;
0091         sourceQueriesMock(&Domain::DataSourceQueries::findTopLevel).when().thenReturn(topLevelResult);
0092         sourceQueriesMock(&Domain::DataSourceQueries::findChildren).when(source1).thenReturn(source1Result);
0093         sourceQueriesMock(&Domain::DataSourceQueries::findChildren).when(source2).thenReturn(source2Result);
0094         sourceQueriesMock(&Domain::DataSourceQueries::findChildren).when(source3).thenReturn(source3Result);
0095         sourceQueriesMock(&Domain::DataSourceQueries::findChildren).when(source4).thenReturn(source4Result);
0096         // We'll simulate a default source change later on
0097         sourceQueriesMock(&Domain::DataSourceQueries::isDefaultSource).when(source1).thenReturn(false);
0098         sourceQueriesMock(&Domain::DataSourceQueries::isDefaultSource).when(source2).thenReturn(true)
0099                                                                                     .thenReturn(false);
0100         sourceQueriesMock(&Domain::DataSourceQueries::isDefaultSource).when(source3).thenReturn(false);
0101         sourceQueriesMock(&Domain::DataSourceQueries::isDefaultSource).when(source4).thenReturn(false)
0102                                                                                     .thenReturn(false)
0103                                                                                     .thenReturn(true);
0104 
0105         Utils::MockObject<Domain::DataSourceRepository> sourceRepositoryMock;
0106 
0107         Presentation::AvailableSourcesModel sources(sourceQueriesMock.getInstance(),
0108                                                     sourceRepositoryMock.getInstance(),
0109                                                     nullptr);
0110 
0111         // WHEN
0112         QAbstractItemModel *model = sources.sourceListModel();
0113 
0114         // THEN
0115         const QModelIndex source1Index = model->index(0, 0);
0116         const QModelIndex source2Index = model->index(1, 0);
0117         const QModelIndex source3Index = model->index(0, 0, source1Index);
0118         const QModelIndex source4Index = model->index(1, 0, source1Index);
0119 
0120         QCOMPARE(model->rowCount(), 2);
0121         QCOMPARE(model->rowCount(source1Index), 2);
0122         QCOMPARE(model->rowCount(source2Index), 0);
0123         QCOMPARE(model->rowCount(source3Index), 0);
0124         QCOMPARE(model->rowCount(source4Index), 0);
0125 
0126         const Qt::ItemFlags defaultFlags = Qt::ItemIsSelectable
0127                                          | Qt::ItemIsEnabled;
0128         QCOMPARE(model->flags(source1Index), defaultFlags);
0129         QCOMPARE(model->flags(source2Index), defaultFlags | Qt::ItemIsUserCheckable);
0130         QCOMPARE(model->flags(source3Index), defaultFlags | Qt::ItemIsUserCheckable);
0131         QCOMPARE(model->flags(source4Index), defaultFlags | Qt::ItemIsUserCheckable);
0132 
0133         QCOMPARE(model->data(source1Index).toString(), source1->name());
0134         QCOMPARE(model->data(source2Index).toString(), source2->name());
0135         QCOMPARE(model->data(source3Index).toString(), source3->name());
0136         QCOMPARE(model->data(source4Index).toString(), source4->name());
0137 
0138         QCOMPARE(model->data(source1Index, Qt::EditRole).toString(), source1->name());
0139         QCOMPARE(model->data(source2Index, Qt::EditRole).toString(), source2->name());
0140         QCOMPARE(model->data(source3Index, Qt::EditRole).toString(), source3->name());
0141         QCOMPARE(model->data(source4Index, Qt::EditRole).toString(), source4->name());
0142 
0143         QVERIFY(!model->data(source1Index, Qt::CheckStateRole).isValid());
0144         QCOMPARE(model->data(source2Index, Qt::CheckStateRole).toBool(), source2->isSelected());
0145         QCOMPARE(model->data(source3Index, Qt::CheckStateRole).toBool(), source3->isSelected());
0146         QCOMPARE(model->data(source4Index, Qt::CheckStateRole).toBool(), source4->isSelected());
0147 
0148         QCOMPARE(model->data(source1Index, Presentation::QueryTreeModelBase::IconNameRole).toString(), source1->iconName());
0149         QCOMPARE(model->data(source2Index, Presentation::QueryTreeModelBase::IconNameRole).toString(), QStringLiteral("folder"));
0150         QCOMPARE(model->data(source3Index, Presentation::QueryTreeModelBase::IconNameRole).toString(), QStringLiteral("folder"));
0151         QCOMPARE(model->data(source4Index, Presentation::QueryTreeModelBase::IconNameRole).toString(), QStringLiteral("folder"));
0152 
0153         QCOMPARE(model->data(source1Index, Presentation::QueryTreeModelBase::IsDefaultRole).toBool(), false);
0154         QCOMPARE(model->data(source2Index, Presentation::QueryTreeModelBase::IsDefaultRole).toBool(), true);
0155         QCOMPARE(model->data(source3Index, Presentation::QueryTreeModelBase::IsDefaultRole).toBool(), false);
0156         QCOMPARE(model->data(source4Index, Presentation::QueryTreeModelBase::IsDefaultRole).toBool(), false);
0157 
0158         // WHEN
0159         sourceRepositoryMock(&Domain::DataSourceRepository::update).when(source2).thenReturn(new FakeJob(this));
0160         sourceRepositoryMock(&Domain::DataSourceRepository::update).when(source4).thenReturn(new FakeJob(this));
0161 
0162         QVERIFY(!model->setData(source1Index, Qt::Unchecked, Qt::CheckStateRole));
0163         QVERIFY(model->setData(source2Index, Qt::Checked, Qt::CheckStateRole));
0164         QVERIFY(model->setData(source4Index, Qt::Unchecked, Qt::CheckStateRole));
0165 
0166         // THEN
0167         QVERIFY(sourceRepositoryMock(&Domain::DataSourceRepository::update).when(source2).exactly(1));
0168         QVERIFY(sourceRepositoryMock(&Domain::DataSourceRepository::update).when(source4).exactly(1));
0169 
0170         QVERIFY(source2->isSelected());
0171         QVERIFY(!source4->isSelected());
0172 
0173         // WHEN
0174         QSignalSpy spy(model, &QAbstractItemModel::dataChanged);
0175         sourceQueriesMock(&Domain::DataSourceQueries::changeDefaultSource).when(source4).thenReturn();
0176         sources.setDefaultItem(source4Index);
0177 
0178         // THEN
0179         QCOMPARE(model->data(source1Index, Presentation::QueryTreeModelBase::IsDefaultRole).toBool(), false);
0180         QCOMPARE(model->data(source2Index, Presentation::QueryTreeModelBase::IsDefaultRole).toBool(), false);
0181         QCOMPARE(model->data(source3Index, Presentation::QueryTreeModelBase::IsDefaultRole).toBool(), false);
0182         QCOMPARE(model->data(source4Index, Presentation::QueryTreeModelBase::IsDefaultRole).toBool(), true);
0183 
0184         // Not overly efficient way of signaling the change, but doesn't happen often
0185         QCOMPARE(spy.count(), 4);
0186         QCOMPARE(spy.at(0).at(0).toModelIndex(), source1Index);
0187         QCOMPARE(spy.at(0).at(1).toModelIndex(), source1Index);
0188         QCOMPARE(spy.at(1).at(0).toModelIndex(), source3Index);
0189         QCOMPARE(spy.at(1).at(1).toModelIndex(), source3Index);
0190         QCOMPARE(spy.at(2).at(0).toModelIndex(), source4Index);
0191         QCOMPARE(spy.at(2).at(1).toModelIndex(), source4Index);
0192         QCOMPARE(spy.at(3).at(0).toModelIndex(), source2Index);
0193         QCOMPARE(spy.at(3).at(1).toModelIndex(), source2Index);
0194 
0195         QVERIFY(sourceQueriesMock(&Domain::DataSourceQueries::changeDefaultSource).when(source4).exactly(1));
0196     }
0197 
0198     void shouldGetAnErrorMessageWhenSetDataSourceFailed()
0199     {
0200         // GIVEN
0201 
0202         // Two top level sources
0203         auto source1 = Domain::DataSource::Ptr::create();
0204         source1->setName(QStringLiteral("Source 1"));
0205         source1->setIconName(QStringLiteral("foo-icon"));
0206         source1->setSelected(false);
0207         source1->setContentTypes(Domain::DataSource::Tasks);
0208         auto topLevelProvider = Domain::QueryResultProvider<Domain::DataSource::Ptr>::Ptr::create();
0209         auto topLevelResult = Domain::QueryResult<Domain::DataSource::Ptr>::create(topLevelProvider);
0210         topLevelProvider->append(source1);
0211 
0212         // Nothing under source1
0213         auto source1Provider = Domain::QueryResultProvider<Domain::DataSource::Ptr>::Ptr::create();
0214         auto source1Result = Domain::QueryResult<Domain::DataSource::Ptr>::create(source1Provider);
0215 
0216         Utils::MockObject<Domain::DataSourceQueries> sourceQueriesMock;
0217         sourceQueriesMock(&Domain::DataSourceQueries::findTopLevel).when().thenReturn(topLevelResult);
0218         sourceQueriesMock(&Domain::DataSourceQueries::findChildren).when(source1).thenReturn(source1Result);
0219 
0220         Utils::MockObject<Domain::DataSourceRepository> sourceRepositoryMock;
0221 
0222         Presentation::AvailableSourcesModel sources(sourceQueriesMock.getInstance(),
0223                                                     sourceRepositoryMock.getInstance(),
0224                                                     nullptr);
0225         FakeErrorHandler errorHandler;
0226         sources.setErrorHandler(&errorHandler);
0227 
0228         // WHEN
0229         QAbstractItemModel *model = sources.sourceListModel();
0230 
0231         // THEN
0232         const QModelIndex source1Index = model->index(0, 0);
0233 
0234         // WHEN
0235         auto job = new FakeJob(this);
0236         job->setExpectedError(KJob::KilledJobError, QStringLiteral("Foo"));
0237         sourceRepositoryMock(&Domain::DataSourceRepository::update).when(source1).thenReturn(job);
0238 
0239         QVERIFY(model->setData(source1Index, Qt::Unchecked, Qt::CheckStateRole));
0240 
0241         // THEN
0242         QTest::qWait(150);
0243         QCOMPARE(errorHandler.m_message, QStringLiteral("Cannot modify source Source 1: Foo"));
0244     }
0245 
0246     void shouldExecBackendSettingsDialog()
0247     {
0248         // GIVEN
0249         Utils::MockObject<Domain::DataSourceRepository> sourceRepositoryMock;
0250         sourceRepositoryMock(&Domain::DataSourceRepository::showConfigDialog).when().thenReturn();
0251 
0252         Presentation::AvailableSourcesModel sources(Domain::DataSourceQueries::Ptr(),
0253                                                     sourceRepositoryMock.getInstance());
0254 
0255         // WHEN
0256         sources.showConfigDialog();
0257 
0258         // THEN
0259         QVERIFY(sourceRepositoryMock(&Domain::DataSourceRepository::showConfigDialog).when().exactly(1));
0260     }
0261 };
0262 
0263 ZANSHIN_TEST_MAIN(AvailableSourcesModelTest)
0264 
0265 #include "availablesourcesmodeltest.moc"