File indexing completed on 2024-05-05 03:53:33

0001 /*
0002     This file is part of the KDE libraries
0003 
0004     SPDX-FileCopyrightText: 2007 David Faure <faure@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include <QClipboard>
0010 #include <QSignalSpy>
0011 #include <QTest>
0012 #include <QToolButton>
0013 #include <kcompletionbox.h>
0014 #include <klineedit.h>
0015 
0016 class KLineEdit_UnitTest : public QObject
0017 {
0018     Q_OBJECT
0019 
0020 private Q_SLOTS:
0021     void testReturnPressed()
0022     {
0023         KLineEdit w;
0024         w.setText(QStringLiteral("Hello world"));
0025         QSignalSpy qReturnPressedSpy(&w, &QLineEdit::returnPressed);
0026 
0027         QSignalSpy returnKeyPressedSpy(&w, &KLineEdit::returnKeyPressed);
0028 
0029         QTest::keyClick(&w, Qt::Key_Return);
0030         QCOMPARE(qReturnPressedSpy.count(), 1);
0031 
0032         QCOMPARE(returnKeyPressedSpy.count(), 1);
0033         QCOMPARE(returnKeyPressedSpy.at(0).at(0).toString(), QStringLiteral("Hello world"));
0034     }
0035 
0036     void testTextEditedSignals()
0037     {
0038         KLineEdit w;
0039         QVERIFY(!w.isModified());
0040 
0041         // setText emits textChanged and userTextChanged, but not textEdited
0042         QSignalSpy textChangedSpy(&w, &QLineEdit::textChanged);
0043         QSignalSpy textEditedSpy(&w, &QLineEdit::textEdited);
0044 
0045         w.setText(QStringLiteral("Hello worl"));
0046 
0047         QCOMPARE(textChangedSpy.count(), 1);
0048         QCOMPARE(textChangedSpy[0][0].toString(), w.text());
0049         QCOMPARE(textEditedSpy.count(), 0);
0050         QVERIFY(!w.isModified());
0051 
0052         textChangedSpy.clear();
0053         textEditedSpy.clear();
0054 
0055         // calling clear should emit textChanged and userTextChanged, but not textEdited
0056         w.clear();
0057         QCOMPARE(textChangedSpy.count(), 1);
0058         QCOMPARE(textEditedSpy.count(), 0);
0059 
0060         // if text box is already empty, calling clear() shouldn't emit
0061         // any more signals
0062         w.clear();
0063         QCOMPARE(textChangedSpy.count(), 1);
0064         QCOMPARE(textEditedSpy.count(), 0);
0065 
0066         // set the text back for further tests below
0067         w.setText(QStringLiteral("Hello worl"));
0068         textChangedSpy.clear();
0069         textEditedSpy.clear();
0070 
0071         // typing emits all three signals
0072         QTest::keyClick(&w, Qt::Key_D);
0073         QCOMPARE(w.text(), QString::fromLatin1("Hello world"));
0074         QCOMPARE(textChangedSpy.count(), 1);
0075         QCOMPARE(textChangedSpy[0][0].toString(), w.text());
0076         QCOMPARE(textEditedSpy.count(), 1);
0077         QCOMPARE(textEditedSpy[0][0].toString(), w.text());
0078         QVERIFY(w.isModified());
0079 
0080         w.setText(QStringLiteral("K")); // prepare for next test
0081 
0082         textChangedSpy.clear();
0083         textEditedSpy.clear();
0084         QVERIFY(!w.isModified());
0085 
0086         // the suggestion from auto completion emits textChanged but not userTextChanged nor textEdited
0087         w.setCompletionMode(KCompletion::CompletionAuto);
0088         KCompletion completion;
0089         completion.setSoundsEnabled(false);
0090         QStringList items;
0091         items << QStringLiteral("KDE is cool") << QStringLiteral("KDE is really cool");
0092         completion.setItems(items);
0093         w.setCompletionObject(&completion);
0094 
0095         w.doCompletion(w.text());
0096         QCOMPARE(w.text(), items.at(0));
0097 
0098         QCOMPARE(textChangedSpy.count(), 1);
0099         QCOMPARE(textChangedSpy[0][0].toString(), w.text());
0100         QCOMPARE(textEditedSpy.count(), 0);
0101         QVERIFY(!w.isModified());
0102         textChangedSpy.clear();
0103         textEditedSpy.clear();
0104 
0105         // accepting the completion suggestion now emits all three signals too
0106         QTest::keyClick(&w, Qt::Key_Right);
0107         QCOMPARE(w.text(), items.at(0));
0108 
0109         QCOMPARE(textChangedSpy.count(), 1);
0110         QCOMPARE(textChangedSpy[0][0].toString(), w.text());
0111         QCOMPARE(textEditedSpy.count(), 1);
0112         QCOMPARE(textEditedSpy[0][0].toString(), w.text());
0113         QVERIFY(w.isModified());
0114         textChangedSpy.clear();
0115         textEditedSpy.clear();
0116 
0117         // Now with popup completion
0118         w.setCompletionMode(KCompletion::CompletionPopup);
0119         w.setText(QStringLiteral("KDE"));
0120         QVERIFY(!w.isModified());
0121         textChangedSpy.clear();
0122         textEditedSpy.clear();
0123         w.doCompletion(w.text()); // popup appears
0124         QCOMPARE(w.text(), QString::fromLatin1("KDE"));
0125         QCOMPARE(textChangedSpy.count() + textEditedSpy.count(), 0);
0126         w.completionBox()->down(); // select 1st item
0127         QCOMPARE(w.text(), items.at(0));
0128         QVERIFY(w.isModified());
0129         w.completionBox()->down(); // select 2nd item
0130         QCOMPARE(w.text(), items.at(1));
0131 
0132         // Selecting an item in the popup completion changes the lineedit text
0133         // and emits textChanged and userTextChanged, but not textEdited.
0134         QCOMPARE(textChangedSpy.count(), 2);
0135         QCOMPARE(textEditedSpy.count(), 0);
0136         textChangedSpy.clear();
0137         textEditedSpy.clear();
0138 
0139         QTest::keyClick(&w, Qt::Key_Enter); // activate
0140         QVERIFY(!w.completionBox()->isVisible());
0141         QCOMPARE(w.text(), items.at(1));
0142         QVERIFY(w.isModified());
0143         // Nothing else happens, the text was already set in the lineedit
0144         QCOMPARE(textChangedSpy.count(), 0);
0145         QCOMPARE(textEditedSpy.count(), 0);
0146 
0147         // Now when using the mouse in the popup completion
0148         w.setText(QStringLiteral("KDE"));
0149         w.doCompletion(w.text()); // popup appears
0150         QCOMPARE(w.text(), QString::fromLatin1("KDE"));
0151         // Selecting an item in the popup completion changes the lineedit text and emits all 3 signals
0152         const QRect rect = w.completionBox()->visualRect(w.completionBox()->model()->index(1, 0));
0153 
0154         QSignalSpy textActivatedSpy(w.completionBox(), &KCompletionBox::textActivated);
0155 
0156         QTest::mouseClick(w.completionBox()->viewport(), Qt::LeftButton, Qt::NoModifier, rect.center());
0157 
0158         QCOMPARE(textActivatedSpy.count(), 1);
0159 
0160         QCOMPARE(w.text(), items.at(1));
0161         QVERIFY(w.isModified());
0162     }
0163 
0164     void testCompletionBox()
0165     {
0166         KLineEdit w;
0167         w.setText(QStringLiteral("/"));
0168         w.setCompletionMode(KCompletion::CompletionPopup);
0169         KCompletion completion;
0170         completion.setSoundsEnabled(false);
0171         w.setCompletionObject(&completion);
0172         QStringList items;
0173         items << QStringLiteral("/home/") << QStringLiteral("/hold/") << QStringLiteral("/hole/");
0174         completion.setItems(items);
0175         QTest::keyClick(&w, 'h');
0176         QCOMPARE(w.text(), QString::fromLatin1("/h"));
0177         QCOMPARE(w.completionBox()->currentRow(), -1);
0178         QCOMPARE(w.completionBox()->items(), items);
0179         QTest::keyClick(&w, 'o');
0180         QCOMPARE(w.text(), QString::fromLatin1("/ho"));
0181         QCOMPARE(w.completionBox()->currentRow(), -1);
0182         w.completionBox()->down(); // select 1st item
0183         QCOMPARE(w.text(), items.at(0));
0184         w.completionBox()->down(); // select 2nd item
0185         QCOMPARE(w.text(), items.at(1));
0186         w.completionBox()->up(); // select 1st item again
0187         QCOMPARE(w.text(), items.at(0));
0188         w.completionBox()->up(); // select last item
0189         QCOMPARE(w.text(), items.at(2));
0190         w.completionBox()->down(); // select 1st item again
0191         QCOMPARE(w.text(), items.at(0));
0192 
0193         QStringList newItems;
0194         newItems << QStringLiteral("/home/kde");
0195         completion.setItems(newItems);
0196         QTest::keyClick(&w, 'k');
0197         QCOMPARE(w.text(), QString("/home/k"));
0198         // QCOMPARE(w.completionBox()->currentRow(), -1); // #247552
0199         w.completionBox()->down(); // select the item
0200         QCOMPARE(w.completionBox()->items(), newItems);
0201         QCOMPARE(w.text(), newItems.at(0));
0202     }
0203 
0204     void testPaste()
0205     {
0206         const QString origText = QApplication::clipboard()->text();
0207         const QString pastedText = QStringLiteral("Test paste from klineedit_unittest");
0208         QApplication::clipboard()->setText(pastedText);
0209         KLineEdit w;
0210         w.setText(QStringLiteral("Hello world"));
0211         w.selectAll();
0212         QTest::keyClick(&w, Qt::Key_V, Qt::ControlModifier);
0213         QCOMPARE(w.text(), pastedText);
0214         QApplication::clipboard()->setText(origText);
0215     }
0216 
0217     void testClearButtonClicked()
0218     {
0219         KLineEdit w;
0220         w.setText(QStringLiteral("Hello world"));
0221         w.setClearButtonEnabled(true);
0222         w.setClearButtonEnabled(false);
0223         w.setClearButtonEnabled(true);
0224         QSignalSpy spy(&w, &KLineEdit::clearButtonClicked);
0225         QToolButton *tb = w.findChild<QToolButton *>();
0226         QTest::mouseClick(tb, Qt::LeftButton, Qt::NoModifier);
0227         QCOMPARE(w.text(), QString());
0228         QCOMPARE(spy.count(), 1);
0229     }
0230 };
0231 
0232 QTEST_MAIN(KLineEdit_UnitTest)
0233 
0234 #include "klineedit_unittest.moc"