File indexing completed on 2024-11-10 04:40:23
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 #include "shared/aktest.h" 0010 0011 #include "monitor.h" 0012 #include "tag.h" 0013 #include "tagcreatejob.h" 0014 #include "tagdeletejob.h" 0015 #include "tagmodel.h" 0016 #include "tagselectiondialog.h" 0017 #include "tagwidget.h" 0018 0019 #include <QDialogButtonBox> 0020 #include <QLineEdit> 0021 #include <QPushButton> 0022 #include <QSignalSpy> 0023 #include <QTest> 0024 #include <QToolButton> 0025 0026 #include <memory> 0027 0028 using namespace Akonadi; 0029 using namespace std::chrono_literals; 0030 class TagWidgetTest : public QObject 0031 { 0032 Q_OBJECT 0033 0034 struct TestSetup { 0035 TestSetup() 0036 : widget(std::make_unique<TagWidget>()) 0037 { 0038 widget->show(); 0039 0040 monitor = widget->findChild<Monitor *>(); 0041 QVERIFY(monitor); 0042 model = widget->findChild<TagModel *>(); 0043 QVERIFY(model); 0044 QSignalSpy modelSpy(model, &TagModel::populated); 0045 QVERIFY(modelSpy.wait()); 0046 0047 QVERIFY(QTest::qWaitForWindowActive(widget.get())); 0048 0049 tagView = widget->findChild<QLineEdit *>(QStringLiteral("tagView")); 0050 QVERIFY(tagView); 0051 QVERIFY(tagView->isReadOnly()); // always read-only 0052 editButton = widget->findChild<QToolButton *>(QStringLiteral("editButton")); 0053 QVERIFY(editButton); 0054 0055 valid = true; 0056 } 0057 0058 ~TestSetup() 0059 { 0060 if (!createdTags.empty()) { 0061 auto deleteJob = new TagDeleteJob(createdTags); 0062 AKVERIFYEXEC(deleteJob); 0063 } 0064 } 0065 0066 bool createTags(int count) 0067 { 0068 const auto doCreateTags = [this, count]() { 0069 QSignalSpy monitorSpy(monitor, &Monitor::tagAdded); 0070 for (int i = 0; i < count; ++i) { 0071 auto job = new TagCreateJob(Tag(QStringLiteral("TestTag-%1").arg(i))); 0072 AKVERIFYEXEC(job); 0073 createdTags.push_back(job->tag()); 0074 } 0075 QTRY_COMPARE(monitorSpy.count(), count); 0076 }; 0077 doCreateTags(); 0078 return createdTags.size() == count; 0079 } 0080 0081 bool testSelectionMatches(QSignalSpy &selectionSpy, const Tag::List &selection) const 0082 { 0083 QStringList names; 0084 std::transform(selection.begin(), selection.end(), std::back_inserter(names), std::bind(&Tag::name, std::placeholders::_1)); 0085 0086 AKCOMPARE(widget->selection(), selection); 0087 AKCOMPARE(selectionSpy.size(), 1); 0088 0089 AKCOMPARE(selectionSpy.at(0).at(0).value<Tag::List>(), selection); 0090 AKCOMPARE(tagView->text(), names.join(QStringLiteral(", "))); 0091 return true; 0092 } 0093 0094 bool selectTagsInDialog(const Tag::List &selection) 0095 { 0096 const auto windows = QApplication::topLevelWidgets(); 0097 for (auto window : windows) { 0098 if (auto dlg = qobject_cast<TagSelectionDialog *>(window)) { 0099 // Set the selection through code, testing selecting tags with mouse is 0100 // out-of-scope for this test, there's a dedicated TagEditWidget test for that. 0101 dlg->setSelection(selection); 0102 auto button = dlg->buttons()->button(QDialogButtonBox::Ok); 0103 AKVERIFY(button); 0104 QTest::mouseClick(button, Qt::LeftButton); 0105 return true; 0106 } 0107 } 0108 0109 return false; 0110 } 0111 0112 std::unique_ptr<TagWidget> widget; 0113 Monitor *monitor = nullptr; 0114 TagModel *model = nullptr; 0115 0116 QLineEdit *tagView = nullptr; 0117 QToolButton *editButton = nullptr; 0118 0119 Tag::List createdTags; 0120 0121 bool valid = false; 0122 }; 0123 0124 private Q_SLOTS: 0125 void initTestCase() 0126 { 0127 AkonadiTest::checkTestIsIsolated(); 0128 } 0129 0130 void testInitialState() 0131 { 0132 TestSetup test; 0133 QVERIFY(test.valid); 0134 0135 QVERIFY(test.tagView->text().isEmpty()); 0136 QVERIFY(test.widget->selection().isEmpty()); 0137 } 0138 0139 void testSettingSelectionFromCode() 0140 { 0141 TestSetup test; 0142 QVERIFY(test.valid); 0143 QVERIFY(test.createTags(4)); 0144 0145 QSignalSpy selectionSpy(test.widget.get(), &TagWidget::selectionChanged); 0146 const auto selection = Tag::List{test.createdTags[1], test.createdTags[3]}; 0147 test.widget->setSelection(selection); 0148 0149 QVERIFY(test.testSelectionMatches(selectionSpy, selection)); 0150 } 0151 0152 void testSettingSelectionViaDialog() 0153 { 0154 TestSetup test; 0155 QVERIFY(test.valid); 0156 QVERIFY(test.createTags(4)); 0157 0158 QSignalSpy selectionSpy(test.widget.get(), &TagWidget::selectionChanged); 0159 const auto selection = Tag::List{test.createdTags[1], test.createdTags[3]}; 0160 0161 bool ok = false; 0162 // Clicking on the Edit button opens the dialog in a blocking way, so 0163 // we need to dispatch the test from event loop 0164 QTimer::singleShot(100ms, this, [&test, &selection, &ok]() { 0165 QVERIFY(test.selectTagsInDialog(selection)); 0166 ok = true; 0167 }); 0168 QTest::mouseClick(test.editButton, Qt::LeftButton); 0169 QVERIFY(ok); 0170 0171 QVERIFY(test.testSelectionMatches(selectionSpy, selection)); 0172 } 0173 0174 void testClearTagsFromCode() 0175 { 0176 TestSetup test; 0177 QVERIFY(test.valid); 0178 QVERIFY(test.createTags(4)); 0179 0180 const auto selection = Tag::List{test.createdTags[1], test.createdTags[3]}; 0181 test.widget->setSelection(selection); 0182 QCOMPARE(test.widget->selection(), selection); 0183 0184 QSignalSpy selectionSpy(test.widget.get(), &TagWidget::selectionChanged); 0185 test.widget->clearTags(); 0186 QVERIFY(test.widget->selection().isEmpty()); 0187 QCOMPARE(selectionSpy.size(), 1); 0188 QVERIFY(selectionSpy.at(0).at(0).value<Tag::List>().empty()); 0189 QVERIFY(test.tagView->text().isEmpty()); 0190 } 0191 }; 0192 0193 QTEST_AKONADIMAIN(TagWidgetTest) 0194 0195 #include "tagwidgettest.moc"