File indexing completed on 2024-12-01 03:39:53

0001 /*
0002     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0003     SPDX-FileCopyrightText: 2020 David Redondo <kde@david-redondo.de>
0004 */
0005 
0006 #include "kkeysequencerecordertest.h"
0007 
0008 #include "kkeysequencerecorder.h"
0009 
0010 #include <QSignalSpy>
0011 #include <QTest>
0012 #include <QWindow>
0013 
0014 QTEST_MAIN(KKeySequenceRecorderTest)
0015 
0016 void KKeySequenceRecorderTest::initTestCase()
0017 {
0018     m_window = new QWindow;
0019 }
0020 
0021 void KKeySequenceRecorderTest::cleanupTestCase()
0022 {
0023     delete m_window;
0024 }
0025 
0026 void KKeySequenceRecorderTest::testValidWindow()
0027 {
0028     KKeySequenceRecorder recorder(nullptr);
0029     QSignalSpy recordingSpy(&recorder, &KKeySequenceRecorder::recordingChanged);
0030 
0031     recorder.startRecording();
0032     QCOMPARE(recordingSpy.count(), 0);
0033     QVERIFY(!recorder.isRecording());
0034 
0035     recorder.setWindow(m_window);
0036     recorder.startRecording();
0037     QCOMPARE(recordingSpy.count(), 2);
0038     QVERIFY(recorder.isRecording());
0039 }
0040 
0041 void KKeySequenceRecorderTest::testRecording()
0042 {
0043     KKeySequenceRecorder recorder(m_window);
0044     QSignalSpy recordingSpy(&recorder, &KKeySequenceRecorder::recordingChanged);
0045     QSignalSpy sequenceSpy(&recorder, &KKeySequenceRecorder::currentKeySequenceChanged);
0046     QSignalSpy resultSpy(&recorder, &KKeySequenceRecorder::gotKeySequence);
0047 
0048     recorder.startRecording();
0049     QVERIFY(recorder.isRecording());
0050     QCOMPARE(recordingSpy.count(), 1);
0051     QCOMPARE(sequenceSpy.count(), 1);
0052 
0053     QTest::keyClick(m_window, Qt::Key_A, Qt::ControlModifier);
0054     QVERIFY(recorder.isRecording());
0055     QCOMPARE(recordingSpy.count(), 1);
0056     QCOMPARE(sequenceSpy.count(), 4); // two key events + modifier release
0057     QCOMPARE(resultSpy.count(), 0);
0058     QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::Key_A | Qt::ControlModifier));
0059 
0060     QTest::qWait(800);
0061     QCOMPARE(sequenceSpy.count(), 4);
0062     QCOMPARE(recordingSpy.count(), 2);
0063     QVERIFY(!recorder.isRecording());
0064     QCOMPARE(resultSpy.count(), 1);
0065     QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::Key_A | Qt::ControlModifier));
0066     QCOMPARE(resultSpy.takeFirst().at(0).value<QKeySequence>(), QKeySequence(Qt::Key_A | Qt::ControlModifier));
0067 }
0068 
0069 void KKeySequenceRecorderTest::testModifiers()
0070 {
0071     KKeySequenceRecorder recorder(m_window);
0072     QSignalSpy recordingSpy(&recorder, &KKeySequenceRecorder::recordingChanged);
0073     QSignalSpy sequenceSpy(&recorder, &KKeySequenceRecorder::currentKeySequenceChanged);
0074     QSignalSpy resultSpy(&recorder, &KKeySequenceRecorder::gotKeySequence);
0075 
0076     recorder.startRecording();
0077     QCOMPARE(sequenceSpy.count(), 1);
0078     QCOMPARE(recordingSpy.count(), 1);
0079     QVERIFY(recorder.isRecording());
0080 
0081     QTest::keyPress(m_window, Qt::Key_Control);
0082     QCOMPARE(sequenceSpy.count(), 2);
0083     QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::ControlModifier));
0084 
0085     // Releasing a different key because when releasing Key_Meta, QTest sends a KeyRelease event
0086     // with MetaModifier even though modifieres should be empty
0087     QTest::keyRelease(m_window, Qt::Key_A, Qt::NoModifier);
0088     QCOMPARE(sequenceSpy.count(), 3);
0089     QCOMPARE(recorder.currentKeySequence(), QKeySequence());
0090     QCOMPARE(recordingSpy.count(), 1);
0091     QVERIFY(recorder.isRecording());
0092 
0093     QTRY_VERIFY_WITH_TIMEOUT(recorder.isRecording(), 800);
0094 
0095     QTest::keyPress(m_window, Qt::Key_Control);
0096     QCOMPARE(sequenceSpy.count(), 4);
0097     QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::ControlModifier));
0098 
0099     QTest::keyPress(m_window, Qt::Key_Alt, Qt::ControlModifier);
0100     QCOMPARE(sequenceSpy.count(), 6); // QTest sends two key events, one for each modifier
0101     QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::AltModifier | Qt::ControlModifier));
0102 
0103     QCOMPARE(resultSpy.count(), 0); // modifierless not allowed
0104 }
0105 
0106 void KKeySequenceRecorderTest::testModifierless()
0107 {
0108     KKeySequenceRecorder recorder(m_window);
0109     QSignalSpy resultSpy(&recorder, &KKeySequenceRecorder::gotKeySequence);
0110     QSignalSpy sequenceSpy(&recorder, &KKeySequenceRecorder::currentKeySequenceChanged);
0111 
0112     recorder.startRecording();
0113     QVERIFY(recorder.isRecording());
0114     QCOMPARE(sequenceSpy.count(), 1);
0115 
0116     recorder.setModifierlessAllowed(false);
0117     QTest::keyPress(m_window, Qt::Key_A);
0118     QTRY_VERIFY_WITH_TIMEOUT(recorder.isRecording(), 800);
0119     QCOMPARE(sequenceSpy.count(), 1);
0120     QCOMPARE(resultSpy.count(), 0);
0121     QCOMPARE(recorder.currentKeySequence(), QKeySequence());
0122 
0123     recorder.setModifierlessAllowed(true);
0124     QTest::keyClick(m_window, Qt::Key_A);
0125     QTRY_VERIFY_WITH_TIMEOUT(!recorder.isRecording(), 800);
0126     QCOMPARE(sequenceSpy.count(), 2);
0127     QCOMPARE(resultSpy.count(), 1);
0128     QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::Key_A));
0129 }
0130 
0131 void KKeySequenceRecorderTest::testModifierOnly()
0132 {
0133     KKeySequenceRecorder recorder(m_window);
0134     recorder.setModifierOnlyAllowed(true);
0135     recorder.setModifierlessAllowed(true);
0136     QSignalSpy resultSpy(&recorder, &KKeySequenceRecorder::gotKeySequence);
0137     QSignalSpy recordingSpy(&recorder, &KKeySequenceRecorder::recordingChanged);
0138     QSignalSpy sequenceSpy(&recorder, &KKeySequenceRecorder::currentKeySequenceChanged);
0139 
0140     recorder.startRecording();
0141     QVERIFY(recorder.isRecording());
0142     QCOMPARE(sequenceSpy.count(), 1);
0143 
0144     QTest::keyClick(m_window, Qt::Key_Shift);
0145     recordingSpy.wait();
0146     QVERIFY(!recorder.isRecording());
0147     QCOMPARE(sequenceSpy.count(), 3);
0148     QCOMPARE(resultSpy.count(), 1);
0149     QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::Key_Shift));
0150 }
0151 
0152 void KKeySequenceRecorderTest::testModifierOnlyDisabled()
0153 {
0154     KKeySequenceRecorder recorder(m_window);
0155     recorder.setModifierOnlyAllowed(false);
0156     recorder.setModifierlessAllowed(true);
0157     QSignalSpy resultSpy(&recorder, &KKeySequenceRecorder::gotKeySequence);
0158     QSignalSpy recordingSpy(&recorder, &KKeySequenceRecorder::recordingChanged);
0159     QSignalSpy sequenceSpy(&recorder, &KKeySequenceRecorder::currentKeySequenceChanged);
0160 
0161     recorder.startRecording();
0162     QVERIFY(recorder.isRecording());
0163     QCOMPARE(sequenceSpy.count(), 1);
0164 
0165     QTest::keyClick(m_window, Qt::Key_Shift);
0166     recordingSpy.wait();
0167     QVERIFY(recorder.isRecording());
0168     recorder.cancelRecording();
0169     QCOMPARE(sequenceSpy.count(), 3);
0170     QCOMPARE(resultSpy.count(), 0);
0171     QCOMPARE(recorder.currentKeySequence(), QKeySequence());
0172 }
0173 
0174 void KKeySequenceRecorderTest::testMultiKeyAllowed()
0175 {
0176     KKeySequenceRecorder recorder(m_window);
0177     QSignalSpy recordingSpy(&recorder, &KKeySequenceRecorder::recordingChanged);
0178     QSignalSpy resultSpy(&recorder, &KKeySequenceRecorder::gotKeySequence);
0179 
0180     recorder.startRecording();
0181 
0182     recorder.setMultiKeyShortcutsAllowed(true);
0183     int keys[4] = {0};
0184     for (int i = 0; i < 4; ++i) {
0185         QVERIFY(recorder.isRecording());
0186         QCOMPARE(recordingSpy.count(), 1);
0187         QCOMPARE(resultSpy.count(), 0);
0188         keys[i] = (Qt::Key_A | Qt::ControlModifier).toCombined();
0189         QKeySequence result(keys[0], keys[1], keys[2], keys[3]);
0190         QTest::keyPress(m_window, Qt::Key_A, Qt::ControlModifier);
0191         QTest::keyRelease(m_window, Qt::Key_A, Qt::ControlModifier);
0192         QCOMPARE(recorder.currentKeySequence(), QKeySequence(keys[0], keys[1], keys[2], keys[3]));
0193     }
0194     QVERIFY(!recorder.isRecording());
0195     QCOMPARE(recordingSpy.count(), 2);
0196     QCOMPARE(resultSpy.count(), 1);
0197     QCOMPARE(resultSpy.takeFirst().at(0).value<QKeySequence>(), QKeySequence(keys[0], keys[1], keys[2], keys[3]));
0198 
0199     recorder.setMultiKeyShortcutsAllowed(false);
0200     recorder.startRecording();
0201     QVERIFY(recorder.isRecording());
0202     QCOMPARE(recordingSpy.count(), 3);
0203     QTest::keyPress(m_window, Qt::Key_A, Qt::ControlModifier);
0204     QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::Key_A | Qt::ControlModifier));
0205     QVERIFY(!recorder.isRecording());
0206     QCOMPARE(recordingSpy.count(), 4);
0207     QCOMPARE(resultSpy.count(), 1);
0208     QCOMPARE(resultSpy.takeAt(0).at(0).value<QKeySequence>(), QKeySequence(Qt::Key_A | Qt::ControlModifier));
0209 }
0210 
0211 void KKeySequenceRecorderTest::testKeyNonLetterNoModifier()
0212 {
0213     KKeySequenceRecorder recorder(m_window);
0214     QSignalSpy resultSpy(&recorder, &KKeySequenceRecorder::gotKeySequence);
0215     QSignalSpy sequenceSpy(&recorder, &KKeySequenceRecorder::currentKeySequenceChanged);
0216 
0217     recorder.startRecording();
0218     QVERIFY(recorder.isRecording());
0219     QCOMPARE(sequenceSpy.count(), 1);
0220 
0221     recorder.setModifierlessAllowed(false);
0222     QTest::keyPress(m_window, Qt::Key_Insert);
0223     QTRY_VERIFY_WITH_TIMEOUT(recorder.isRecording(), 800);
0224     QCOMPARE(sequenceSpy.count(), 2);
0225     QCOMPARE(resultSpy.count(), 0);
0226     QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::Key_Insert));
0227 
0228     recorder.setModifierlessAllowed(true);
0229     QTest::keyClick(m_window, Qt::Key_Insert);
0230     QTRY_VERIFY_WITH_TIMEOUT(!recorder.isRecording(), 800);
0231     QCOMPARE(sequenceSpy.count(), 3);
0232     QCOMPARE(resultSpy.count(), 1);
0233     QCOMPARE(recorder.currentKeySequence(), QKeySequence(Qt::Key_Insert, Qt::Key_Insert));
0234 }
0235 
0236 #include "moc_kkeysequencerecordertest.cpp"