File indexing completed on 2024-05-12 15:33:58

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 #if KCOMPLETION_BUILD_DEPRECATED_SINCE(5, 83)
0022     void testPassword()
0023     {
0024         KLineEdit w;
0025         w.setPasswordMode(true);
0026         QTest::keyClick(&w, Qt::Key_1);
0027         QTest::keyClick(&w, Qt::Key_2);
0028         QTest::keyClick(&w, Qt::Key_3);
0029         QCOMPARE(w.text(), QString("123"));
0030     }
0031 #endif
0032 
0033     void testReturnPressed()
0034     {
0035         KLineEdit w;
0036         w.setText(QStringLiteral("Hello world"));
0037         QSignalSpy qReturnPressedSpy(&w, &QLineEdit::returnPressed);
0038 
0039 #if KCOMPLETION_BUILD_DEPRECATED_SINCE(5, 81)
0040         QSignalSpy kReturnPressedSpy(&w, qOverload<const QString &>(&KLineEdit::returnPressed));
0041 #endif
0042         QSignalSpy returnKeyPressedSpy(&w, &KLineEdit::returnKeyPressed);
0043 
0044         QTest::keyClick(&w, Qt::Key_Return);
0045         QCOMPARE(qReturnPressedSpy.count(), 1);
0046 
0047 #if KCOMPLETION_BUILD_DEPRECATED_SINCE(5, 81)
0048         QCOMPARE(kReturnPressedSpy.count(), 1);
0049         QCOMPARE(kReturnPressedSpy[0][0].toString(), QString("Hello world"));
0050 #endif
0051         QCOMPARE(returnKeyPressedSpy.count(), 1);
0052         QCOMPARE(returnKeyPressedSpy.at(0).at(0).toString(), QStringLiteral("Hello world"));
0053     }
0054 
0055     void testTextEditedSignals()
0056     {
0057         KLineEdit w;
0058         QVERIFY(!w.isModified());
0059 
0060         // setText emits textChanged and userTextChanged, but not textEdited
0061         QSignalSpy textChangedSpy(&w, &QLineEdit::textChanged);
0062         QSignalSpy textEditedSpy(&w, &QLineEdit::textEdited);
0063 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0064         QSignalSpy userTextChangedSpy(&w, &KLineEdit::userTextChanged);
0065 #endif
0066         w.setText(QStringLiteral("Hello worl"));
0067 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0068         QCOMPARE(userTextChangedSpy.count(), 1);
0069         QCOMPARE(userTextChangedSpy[0][0].toString(), w.text());
0070 #endif
0071         QCOMPARE(textChangedSpy.count(), 1);
0072         QCOMPARE(textChangedSpy[0][0].toString(), w.text());
0073         QCOMPARE(textEditedSpy.count(), 0);
0074         QVERIFY(!w.isModified());
0075 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0076         userTextChangedSpy.clear();
0077 #endif
0078         textChangedSpy.clear();
0079         textEditedSpy.clear();
0080 
0081         // calling clear should emit textChanged and userTextChanged, but not textEdited
0082         w.clear();
0083         QCOMPARE(textChangedSpy.count(), 1);
0084         QCOMPARE(textEditedSpy.count(), 0);
0085 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0086         QCOMPARE(userTextChangedSpy.count(), 1);
0087 #endif
0088 
0089         // if text box is already empty, calling clear() shouldn't emit
0090         // any more signals
0091         w.clear();
0092         QCOMPARE(textChangedSpy.count(), 1);
0093         QCOMPARE(textEditedSpy.count(), 0);
0094 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0095         QCOMPARE(userTextChangedSpy.count(), 1);
0096 #endif
0097 
0098         // set the text back for further tests below
0099         w.setText(QStringLiteral("Hello worl"));
0100 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0101         userTextChangedSpy.clear();
0102 #endif
0103         textChangedSpy.clear();
0104         textEditedSpy.clear();
0105 
0106         // typing emits all three signals
0107         QTest::keyClick(&w, Qt::Key_D);
0108         QCOMPARE(w.text(), QString::fromLatin1("Hello world"));
0109 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0110         QCOMPARE(userTextChangedSpy.count(), 1);
0111         QCOMPARE(userTextChangedSpy[0][0].toString(), w.text());
0112 #endif
0113         QCOMPARE(textChangedSpy.count(), 1);
0114         QCOMPARE(textChangedSpy[0][0].toString(), w.text());
0115         QCOMPARE(textEditedSpy.count(), 1);
0116         QCOMPARE(textEditedSpy[0][0].toString(), w.text());
0117         QVERIFY(w.isModified());
0118 
0119         w.setText(QStringLiteral("K")); // prepare for next test
0120 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0121         userTextChangedSpy.clear();
0122 #endif
0123         textChangedSpy.clear();
0124         textEditedSpy.clear();
0125         QVERIFY(!w.isModified());
0126 
0127         // the suggestion from auto completion emits textChanged but not userTextChanged nor textEdited
0128         w.setCompletionMode(KCompletion::CompletionAuto);
0129         KCompletion completion;
0130         completion.setSoundsEnabled(false);
0131         QStringList items;
0132         items << QStringLiteral("KDE is cool") << QStringLiteral("KDE is really cool");
0133         completion.setItems(items);
0134         w.setCompletionObject(&completion);
0135 
0136         w.doCompletion(w.text());
0137         QCOMPARE(w.text(), items.at(0));
0138 
0139 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0140         QCOMPARE(userTextChangedSpy.count(), 0);
0141 #endif
0142         QCOMPARE(textChangedSpy.count(), 1);
0143         QCOMPARE(textChangedSpy[0][0].toString(), w.text());
0144         QCOMPARE(textEditedSpy.count(), 0);
0145         QVERIFY(!w.isModified());
0146 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0147         userTextChangedSpy.clear();
0148 #endif
0149         textChangedSpy.clear();
0150         textEditedSpy.clear();
0151 
0152         // accepting the completion suggestion now emits all three signals too
0153         QTest::keyClick(&w, Qt::Key_Right);
0154         QCOMPARE(w.text(), items.at(0));
0155 
0156 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0157         QCOMPARE(userTextChangedSpy.count(), 1);
0158         QCOMPARE(userTextChangedSpy[0][0].toString(), w.text());
0159 #endif
0160         QCOMPARE(textChangedSpy.count(), 1);
0161         QCOMPARE(textChangedSpy[0][0].toString(), w.text());
0162         QCOMPARE(textEditedSpy.count(), 1);
0163         QCOMPARE(textEditedSpy[0][0].toString(), w.text());
0164         QVERIFY(w.isModified());
0165 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0166         userTextChangedSpy.clear();
0167 #endif
0168         textChangedSpy.clear();
0169         textEditedSpy.clear();
0170 
0171         // Now with popup completion
0172         w.setCompletionMode(KCompletion::CompletionPopup);
0173         w.setText(QStringLiteral("KDE"));
0174         QVERIFY(!w.isModified());
0175 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0176         userTextChangedSpy.clear();
0177 #endif
0178         textChangedSpy.clear();
0179         textEditedSpy.clear();
0180         w.doCompletion(w.text()); // popup appears
0181         QCOMPARE(w.text(), QString::fromLatin1("KDE"));
0182 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0183         QCOMPARE(textChangedSpy.count() + userTextChangedSpy.count() + textEditedSpy.count(), 0);
0184 #else
0185         QCOMPARE(textChangedSpy.count() + textEditedSpy.count(), 0);
0186 #endif
0187         w.completionBox()->down(); // select 1st item
0188         QCOMPARE(w.text(), items.at(0));
0189         QVERIFY(w.isModified());
0190         w.completionBox()->down(); // select 2nd item
0191         QCOMPARE(w.text(), items.at(1));
0192 
0193         // Selecting an item in the popup completion changes the lineedit text
0194         // and emits textChanged and userTextChanged, but not textEdited.
0195 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0196         QCOMPARE(userTextChangedSpy.count(), 2);
0197 #endif
0198         QCOMPARE(textChangedSpy.count(), 2);
0199         QCOMPARE(textEditedSpy.count(), 0);
0200 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0201         userTextChangedSpy.clear();
0202 #endif
0203         textChangedSpy.clear();
0204         textEditedSpy.clear();
0205 
0206         QTest::keyClick(&w, Qt::Key_Enter); // activate
0207         QVERIFY(!w.completionBox()->isVisible());
0208         QCOMPARE(w.text(), items.at(1));
0209         QVERIFY(w.isModified());
0210         // Nothing else happens, the text was already set in the lineedit
0211         QCOMPARE(textChangedSpy.count(), 0);
0212         QCOMPARE(textEditedSpy.count(), 0);
0213 #if KCOMPLETION_ENABLE_DEPRECATED_SINCE(4, 5)
0214         QCOMPARE(userTextChangedSpy.count(), 0);
0215 #endif
0216 
0217         // Now when using the mouse in the popup completion
0218         w.setText(QStringLiteral("KDE"));
0219         w.doCompletion(w.text()); // popup appears
0220         QCOMPARE(w.text(), QString::fromLatin1("KDE"));
0221         // Selecting an item in the popup completion changes the lineedit text and emits all 3 signals
0222         const QRect rect = w.completionBox()->visualRect(w.completionBox()->model()->index(1, 0));
0223 
0224 #if KCOMPLETION_BUILD_DEPRECATED_SINCE(5, 81)
0225         QSignalSpy activatedSpy(w.completionBox(), qOverload<const QString &>(&KCompletionBox::activated));
0226 #endif
0227         QSignalSpy textActivatedSpy(w.completionBox(), &KCompletionBox::textActivated);
0228 
0229         QTest::mouseClick(w.completionBox()->viewport(), Qt::LeftButton, Qt::NoModifier, rect.center());
0230 
0231 #if KCOMPLETION_BUILD_DEPRECATED_SINCE(5, 81)
0232         QCOMPARE(activatedSpy.count(), 1);
0233 #endif
0234         QCOMPARE(textActivatedSpy.count(), 1);
0235 
0236         QCOMPARE(w.text(), items.at(1));
0237         QVERIFY(w.isModified());
0238     }
0239 
0240     void testCompletionBox()
0241     {
0242         KLineEdit w;
0243         w.setText(QStringLiteral("/"));
0244         w.setCompletionMode(KCompletion::CompletionPopup);
0245         KCompletion completion;
0246         completion.setSoundsEnabled(false);
0247         w.setCompletionObject(&completion);
0248         QStringList items;
0249         items << QStringLiteral("/home/") << QStringLiteral("/hold/") << QStringLiteral("/hole/");
0250         completion.setItems(items);
0251         QTest::keyClick(&w, 'h');
0252         QCOMPARE(w.text(), QString::fromLatin1("/h"));
0253         QCOMPARE(w.completionBox()->currentRow(), -1);
0254         QCOMPARE(w.completionBox()->items(), items);
0255         QTest::keyClick(&w, 'o');
0256         QCOMPARE(w.text(), QString::fromLatin1("/ho"));
0257         QCOMPARE(w.completionBox()->currentRow(), -1);
0258         w.completionBox()->down(); // select 1st item
0259         QCOMPARE(w.text(), items.at(0));
0260         w.completionBox()->down(); // select 2nd item
0261         QCOMPARE(w.text(), items.at(1));
0262         w.completionBox()->up(); // select 1st item again
0263         QCOMPARE(w.text(), items.at(0));
0264         w.completionBox()->up(); // select last item
0265         QCOMPARE(w.text(), items.at(2));
0266         w.completionBox()->down(); // select 1st item again
0267         QCOMPARE(w.text(), items.at(0));
0268 
0269         QStringList newItems;
0270         newItems << QStringLiteral("/home/kde");
0271         completion.setItems(newItems);
0272         QTest::keyClick(&w, 'k');
0273         QCOMPARE(w.text(), QString("/home/k"));
0274         // QCOMPARE(w.completionBox()->currentRow(), -1); // #247552
0275         w.completionBox()->down(); // select the item
0276         QCOMPARE(w.completionBox()->items(), newItems);
0277         QCOMPARE(w.text(), newItems.at(0));
0278     }
0279 
0280     void testPaste()
0281     {
0282         const QString origText = QApplication::clipboard()->text();
0283         const QString pastedText = QStringLiteral("Test paste from klineedit_unittest");
0284         QApplication::clipboard()->setText(pastedText);
0285         KLineEdit w;
0286         w.setText(QStringLiteral("Hello world"));
0287         w.selectAll();
0288         QTest::keyClick(&w, Qt::Key_V, Qt::ControlModifier);
0289         QCOMPARE(w.text(), pastedText);
0290         QApplication::clipboard()->setText(origText);
0291     }
0292 
0293     void testClearButtonClicked()
0294     {
0295         KLineEdit w;
0296         w.setText(QStringLiteral("Hello world"));
0297         w.setClearButtonEnabled(true);
0298         w.setClearButtonEnabled(false);
0299         w.setClearButtonEnabled(true);
0300         QSignalSpy spy(&w, &KLineEdit::clearButtonClicked);
0301         QToolButton *tb = w.findChild<QToolButton *>();
0302         QTest::mouseClick(tb, Qt::LeftButton, Qt::NoModifier);
0303         QCOMPARE(w.text(), QString());
0304         QCOMPARE(spy.count(), 1);
0305     }
0306 };
0307 
0308 QTEST_MAIN(KLineEdit_UnitTest)
0309 
0310 #include "klineedit_unittest.moc"