diff --git a/ui/StatusQ/.gitignore b/ui/StatusQ/.gitignore index a7255d0a4b..5bb63e00cc 100644 --- a/ui/StatusQ/.gitignore +++ b/ui/StatusQ/.gitignore @@ -13,4 +13,5 @@ Makefile *_qml.cpp *_qmlcache.qrc sandbox/qmlcache_loader.cpp -doc/html \ No newline at end of file +doc/html +CMakeLists.txt.user diff --git a/ui/StatusQ/tests/TestControls/CMakeLists.txt b/ui/StatusQ/tests/TestControls/CMakeLists.txt new file mode 100644 index 0000000000..dea62f28b1 --- /dev/null +++ b/ui/StatusQ/tests/TestControls/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.5) + +project(TestStatusInputWithRegex LANGUAGES CXX) + +enable_testing() + +# TODO: Workaround until we make StatusQ a CMake library +list(APPEND QML_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/../../src/") +set(QML_IMPORT_PATH "${QML_DIRS}" CACHE STRING "Qt Creator extra qml import paths") +set(QML2_IMPORT_PATH "${QML_DIRS}" CACHE STRING "Qt Creator extra qml import paths") + +find_package(QT NAMES Qt6 Qt5 COMPONENTS QuickTest Qml REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS QuickTest Qml REQUIRED) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# no need to copy around qml test files for shadow builds - just set the respective define +add_definitions(-DQUICK_TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}") + +add_executable(TestStatusInputWithRegex main.cpp) +add_test(NAME TestStatusInputWithRegex COMMAND TestStatusInputWithRegex) + +target_link_libraries(TestStatusInputWithRegex PRIVATE + Qt${QT_VERSION_MAJOR}::QuickTest + Qt${QT_VERSION_MAJOR}::Qml) + diff --git a/ui/StatusQ/tests/TestControls/main.cpp b/ui/StatusQ/tests/TestControls/main.cpp new file mode 100644 index 0000000000..8f83f0da52 --- /dev/null +++ b/ui/StatusQ/tests/TestControls/main.cpp @@ -0,0 +1,21 @@ +#include +#include + +class TestSetup : public QObject +{ + Q_OBJECT + +public: + TestSetup() {} + +public slots: + void qmlEngineAvailable(QQmlEngine *engine) + { + // TODO: Workaround until we make StatusQ a CMake library + engine->addImportPath("../../src/"); + } +}; + +QUICK_TEST_MAIN_WITH_SETUP(TestControls, TestSetup) + +#include "main.moc" diff --git a/ui/StatusQ/tests/TestControls/tst_test-statusinput.qml b/ui/StatusQ/tests/TestControls/tst_test-statusinput.qml new file mode 100644 index 0000000000..f8c7a22bb8 --- /dev/null +++ b/ui/StatusQ/tests/TestControls/tst_test-statusinput.qml @@ -0,0 +1,85 @@ +import QtQuick 2.0 +import QtTest 1.0 + +import StatusQ.Controls 0.1 +import StatusQ.Controls.Validators 0.1 + +Item { + width: 300 + height: 100 + + property int _defaultValidationMode + + Component.onCompleted: { + _defaultValidationMode = statusInput.validationMode + } + StatusInput { + id: statusInput + label: "Control under test" + charLimit: 30 + input.placeholderText: `Must match regex(${validators[0].regularExpression.toString()}) and <= 30 chars` + focus: true + + validators: [ + StatusRegularExpressionValidator { + regularExpression: /^[0-9A-Za-z_\$-\s]*$/ + } + ] + } + + TestCase { + name: "RegexValidationTest" + + when: windowShown + + // + // Test guards + function initTestCase() { + mouseClick(statusInput) + } + + function cleanup() { + statusInput.text = "" + statusInput.validationMode = _defaultValidationMode + } + + // + // Tests + function test_initial_empty_is_valid() { + verify(statusInput.valid, "Expected valid input") + } + + function test_regex_validation() { + keyClick(Qt.Key_1) + verify(statusInput.valid, "Expected valid input") + keyClick(Qt.Key_Ampersand) + verify(!statusInput.valid, "Expected invalid input") + } + + function test_no_invalid_input() { + statusInput.validationMode = StatusInput.ValidationMode.IgnoreInvalidInput + + verify(statusInput.valid, "Expected valid input") + verify(statusInput.text.length === 0, "Expected no input") + keyClick(Qt.Key_2) + verify(statusInput.valid, "Expected valid input") + verify(statusInput.text === "2", "Expect one character") + keyClick(Qt.Key_Ampersand) + verify(statusInput.valid, "Expected invalid input") + verify(statusInput.text === "2", "Expect the same input") + } + + // Use case expected in case new validation changes are enabled with old unvalid data + function test_user_can_delete_initial_invalid_input() { + const appendInvalidChars = "#@!*" + + statusInput.text = "invalid $" + appendInvalidChars + keyClick(Qt.Key_End) + verify(!statusInput.valid, "Expected invalid input due to characters not matching") + // Delete invalid characters to get a valid text + for(let i = 0; i < appendInvalidChars.length; ++i) + keyClick(Qt.Key_Backspace) + verify(statusInput.valid, "Expected valid input") + } + } +}