From ca0a9686c7c6f6136f7fff1edcacc3aa21fc9b82 Mon Sep 17 00:00:00 2001 From: Mohsen Date: Thu, 20 Jun 2024 17:35:33 +0330 Subject: [PATCH 01/10] Fix indents in tst_editorwidgets and fix variable types. --- test/qml/tst_editorwidgets.qml | 69 +++++++++++++++++----------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/test/qml/tst_editorwidgets.qml b/test/qml/tst_editorwidgets.qml index 69e0ba3292..d01abff2bf 100644 --- a/test/qml/tst_editorwidgets.qml +++ b/test/qml/tst_editorwidgets.qml @@ -8,39 +8,38 @@ import Theme 1.0 import "../../src/qml/editorwidgets" as EditorWidgets TestCase { - name: "EditorWidgets" - - EditorWidgets.TextEdit { - id: textEdit - property var value: 'one' - property var config: undefined - property bool isEnabled: true - } - - EditorWidgets.Range { - id: range - property var value: 1 - property var config: undefined - property bool isEnabled: true - } - - EditorWidgets.DateTime { - id: dateTime - - property var value: '2022-01-01' - property var config: undefined - property bool isEnabled: true - } - - function test_textEdit() { - compare(textEdit.children[1].text, 'one') - textEdit.value = 'two' - compare(textEdit.children[1].text, 'two') - } - - function test_range() { - compare(range.children[0].children[0].text, '1') - range.value = 2 - compare(range.children[0].children[0].text, '2') - } + name: "EditorWidgets" + + EditorWidgets.TextEdit { + id: textEdit + property string value: 'one' + property var config: undefined + property bool isEnabled: true + } + + EditorWidgets.Range { + id: range + property real value: 1 + property var config: undefined + property bool isEnabled: true + } + + EditorWidgets.DateTime { + id: dateTime + property string value: '2022-01-01' + property var config: undefined + property bool isEnabled: true + } + + function test_textEdit() { + compare(textEdit.children[1].text, 'one') + textEdit.value = 'two' + compare(textEdit.children[1].text, 'two') + } + + function test_range() { + compare(range.children[0].children[0].text, '1') + range.value = 2 + compare(range.children[0].children[0].text, '2') + } } From 644ea587796d2b30f7099f212dfede640034551d Mon Sep 17 00:00:00 2001 From: Mohsen Date: Fri, 21 Jun 2024 17:24:20 +0330 Subject: [PATCH 02/10] Add some tests for EditorWidgets.TextEdit,DateTime,Range. --- src/qml/editorwidgets/Range.qml | 1 + test/qml/tst_editorwidgets.qml | 175 +++++++++++++++++++++++++++++--- 2 files changed, 164 insertions(+), 12 deletions(-) diff --git a/src/qml/editorwidgets/Range.qml b/src/qml/editorwidgets/Range.qml index cd7ce88547..51d2382848 100644 --- a/src/qml/editorwidgets/Range.qml +++ b/src/qml/editorwidgets/Range.qml @@ -214,6 +214,7 @@ EditorWidgetBase { from: !Number.isFinite(rangeItem.min) ? Number.MIN_VALUE : rangeItem.min to: !Number.isFinite(rangeItem.max) ? Number.MAX_VALUE : rangeItem.max stepSize: !Number.isFinite(rangeItem.step) ? 1 : rangeItem.step + // TODO: using `rangeItem.parent.value` makes item reuseability harder. value: rangeItem.parent.value !== undefined && rangeItem.parent.value !== '' ? Number(rangeItem.parent.value) : from diff --git a/test/qml/tst_editorwidgets.qml b/test/qml/tst_editorwidgets.qml index d01abff2bf..bee4fa1f77 100644 --- a/test/qml/tst_editorwidgets.qml +++ b/test/qml/tst_editorwidgets.qml @@ -2,7 +2,6 @@ import QtQuick 2.3 import QtTest 1.0 import org.qfield 1.0 - import Theme 1.0 import "../../src/qml/editorwidgets" as EditorWidgets @@ -12,34 +11,186 @@ TestCase { EditorWidgets.TextEdit { id: textEdit - property string value: 'one' + property string value: "DEFAULT_VALUE" property var config: undefined property bool isEnabled: true } EditorWidgets.Range { id: range - property real value: 1 + property real value: default_value property var config: undefined property bool isEnabled: true + + readonly property real default_value: 999 } EditorWidgets.DateTime { id: dateTime - property string value: '2022-01-01' + property string value: "2022-01-01" property var config: undefined + property var field: undefined property bool isEnabled: true } - function test_textEdit() { - compare(textEdit.children[1].text, 'one') - textEdit.value = 'two' - compare(textEdit.children[1].text, 'two') + + /** + * Test case for textEdit widget + * + * This function tests the textEdit widget's functionality by setting its config to allow multiline and use html, + * setting its value to "six", verifying that it contains "six", resetting its config to disable multiline and html, + * setting its value to "seven", and comparing its children's texts with "six" and "seven". + */ + function test_01_textEdit() { + // Label -> textReadonlyValue + compare(textEdit.children[0].text, "") // NOTE: If the config is undefined, the label will be an empty string. + + // TextField -> textField + compare(textEdit.children[1].text, "DEFAULT_VALUE") + + // TextArea -> textArea + compare(textEdit.children[2].text, "DEFAULT_VALUE") + + textEdit.config = { + "IsMultiline": true, + "UseHtml": true + } + textEdit.value = "SECOND_VALUE" + + // Label -> textReadonlyValue + verify(textEdit.children[0].text.search("SECOND_VALUE") !== -1) + + // TextField -> textField + compare(textEdit.children[1].text, "SECOND_VALUE") + + // TextArea -> textArea + verify(textEdit.children[2].text.search("SECOND_VALUE") !== -1) + + textEdit.config = { + "IsMultiline": false, + "UseHtml": false + } + textEdit.value = "THIRD_VALUE" + + // Label -> textReadonlyValue + compare(textEdit.children[0].text, "SECOND_VALUE") // NOTE: If the values in the config are set to `false`, the label text will not change. + + // TextField -> textField + compare(textEdit.children[1].text, "THIRD_VALUE") + + // TextArea -> textArea + compare(textEdit.children[2].text, "THIRD_VALUE") + } + + + /** + * Test case for range widget + * + * This function tests the range widget's functionality by: + * + * - Verifying that the initial value of the range is correct + * - Setting the config to undefined for all properties and verifying that the default values are used + * - Verifying that the widget style changes to "TextField" when no style is specified in the config + * - Verifying that the precision, min, max, step, and suffix values are set to default values when not specified in the config + * + * Then, setting the config with specific values and verifying that they are used: + * + * - Setting the widget style to "Slider" and verifying that it changes + * - Setting precision, min, max, step, and suffix values and verifying that they are used + * + * Finally, setting the value of the range and verifying that it is displayed correctly in both text and slider formats. + */ + function test_01_range() { + compare(range.children[0].children[0].text, range.default_value + "") + + range.config = { + "Style": undefined, + "Precision": undefined, + "Min": undefined, + "Max": undefined, + "Step": undefined, + "Suffix": undefined + } + range.value = 3 + compare(range.widgetStyle, "TextField") + compare(range.precision, 1) + compare(range.min, -Infinity) + compare(range.max, Infinity) + compare(range.step, 1) + compare(range.suffix, "") + + // Row + // compare(range.children[0].visible, true) // ERROR ? should work but not working! + + // TextField -> textField + compare(range.children[0].children[0].text, "3") + + range.config = { + "Style": "Slider", + "Precision": 2, + "Min": -10, + "Max": 10, + "Step": 10, + "Suffix": "DEFAULT_SUFFIX" + } + range.value = 4 + compare(range.widgetStyle, "Slider") + compare(range.precision, 2) + compare(range.min, -10) + compare(range.max, 10) + compare(range.step, 10) + compare(range.suffix, "DEFAULT_SUFFIX") + + // Row -> sliderRow + compare(range.children[0].visible, false) + + // Text -> valueLabel + compare(range.children[1].children[0].text, range.min + ".00DEFAULT_SUFFIX") // NOTE: using `range.min` because of `rangeItem.parent.value` + + // QfSlider -> slider + compare(range.children[1].children[1].value, range.min) // NOTE: using `range.min` because of `rangeItem.parent.value` } - function test_range() { - compare(range.children[0].children[0].text, '1') - range.value = 2 - compare(range.children[0].children[0].text, '2') + + /** + * Test case for datetime widget + * + * This function tests the datetime widget's functionality by: + * + * - Setting an initial value without setting `config` and `field` objects and verifying that value is empty + * + * Then, it sets various display formats and verifies that the date and time are displayed correctly in different formats: + * + * - For each of the test times, it iterates over the display formats and sets the config with the format, calendar popup enabled, unknown field format, and disallows null values + * - It sets the field to a date or time type + * - It sets the value of the datetime widget to the test time and verifies that the text label is displayed correctly according to the format + */ + function test_01_dateTime() { + compare(dateTime.children[1].children[0].text, "") // NOTE: setting value without setting `config` and `field` objects won't work + + const testTimes = ["2023-01-01", "2023-01-01 23:33:56"] + const displayFormats = ["yyyy-MM-dd", "yyyy-MM.dd", "yyyy-MM-dd HH:mm:ss", "HH:mm:ss", "HH:mm"] + const results = ["2023-01-01", "2023-01.01", "2023-01-01 00:00:00", "00:00:00", "00:00", + "2023-01-01", "2023-01.01", "2023-01-01 23:33:56", "23:33:56", "23:33"] + let resultIdx = 0 + + for (let time of testTimes) { + for (let format of displayFormats) { + dateTime.config = { + "display_format": format, + "calendar_popup": true, + "field_format": "UNKNOWN!", + "allow_null": false + } + dateTime.field = { + "isDateOrTime": true + } + + dateTime.value = time + + // TextField -> lable + compare(dateTime.children[1].children[0].text, results[resultIdx++]) + } + } } } From 6bc9e418012de80f7f109c95d3ad972c625440ef Mon Sep 17 00:00:00 2001 From: Mohsen Date: Fri, 21 Jun 2024 20:36:12 +0330 Subject: [PATCH 03/10] Add some tests for EditorWidgets.CheckBox. --- test/qml/tst_editorwidgets.qml | 107 +++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/test/qml/tst_editorwidgets.qml b/test/qml/tst_editorwidgets.qml index bee4fa1f77..422d6382b1 100644 --- a/test/qml/tst_editorwidgets.qml +++ b/test/qml/tst_editorwidgets.qml @@ -33,6 +33,13 @@ TestCase { property bool isEnabled: true } + EditorWidgets.CheckBox { + id: checkBox + property bool value: true + property var config: undefined + property var field: undefined + } + /** * Test case for textEdit widget @@ -193,4 +200,104 @@ TestCase { } } } + + + /** + * Test case for checkBox widget + * + * This function tests the checkBox widget's functionality by: + * + * - Verifying the initial state of the widget (value, isBool, and null) and its labels + * + * Then, it sets a configuration with a custom checked and unchecked state and verifies that the widget reflects these states correctly: + * + * - Verifies the value, isBool, and null properties of the widget + * - Verifies the text displayed in the label + * - Verifies the checked state of the QfSwitch widget + * + * It also tests two additional scenarios: + * + * - Sets `TextDisplayMethod` to 0 and verifies that the display is different + * - Sets `type` of the field to 0 and verifies that the display is different + */ + function test_01_checkBox() { + compare(checkBox.value, true) + compare(checkBox.isBool, false) + compare(checkBox.isNull, false) + compare(checkBox.checkedLabel, "") // NOTE: `checkedLabel` initialized with "" when config is undefined + compare(checkBox.uncheckedLabel, "") // NOTE: `uncheckedLabel` initialized with "" when config is undefined + + // Label -> checkValue + compare(checkBox.children[0].text, "") + + // QfSwitch -> checkBox + compare(checkBox.children[1].checked, false) // NOTE: even if `value` be true, without config `checked` will be false + + checkBox.config = { + "TextDisplayMethod": 1, + "CheckedState": "DEFAULT_CHECKED_STATE", + "UncheckedState": "DEFAULT_UNCHECKED_STATE" + } + checkBox.field = { + "type": 1 + } + checkBox.value = true + compare(checkBox.value, true) + compare(checkBox.isBool, true) + compare(checkBox.isNull, false) + compare(checkBox.checkedLabel, "DEFAULT_CHECKED_STATE") + compare(checkBox.uncheckedLabel, "DEFAULT_UNCHECKED_STATE") + + // Label -> checkValue + compare(checkBox.children[0].text, "DEFAULT_CHECKED_STATE") + + // QfSwitch -> checkBox + compare(checkBox.children[1].checked, true) + + checkBox.value = false + + // Label -> checkValue + compare(checkBox.children[0].text, "DEFAULT_UNCHECKED_STATE") + + // QfSwitch -> checkBox + compare(checkBox.children[1].checked, false) + + // test TextDisplayMethod = 0 + checkBox.config = { + "TextDisplayMethod": 0, + "CheckedState": "DEFAULT_CHECKED_STATE", + "UncheckedState": "DEFAULT_UNCHECKED_STATE" + } + checkBox.field = { + "type": 1 + } + checkBox.value = true + compare(checkBox.checkedLabel, "True") + compare(checkBox.uncheckedLabel, "False") + + // test field type = 0 + checkBox.config = { + "TextDisplayMethod": 1, + "CheckedState": "DEFAULT_CHECKED_STATE", + "UncheckedState": "DEFAULT_UNCHECKED_STATE" + } + checkBox.field = { + "type": 0 + } + checkBox.value = true + + // Label -> checkValue + compare(checkBox.children[0].text, "DEFAULT_UNCHECKED_STATE") // NOTE: value is true but it in unchecked state + + // QfSwitch -> checkBox + compare(checkBox.children[1].checked, false) // NOTE: value is true but its not checked + + checkBox.value = false + + // Label -> checkValue + compare(checkBox.children[0].text, "DEFAULT_UNCHECKED_STATE") + + // QfSwitch -> checkBox + compare(checkBox.children[1].checked, false) + } } From 1cfedb479b8cd23d3d9e059bc47c769dede30541 Mon Sep 17 00:00:00 2001 From: Mohsen Date: Sun, 23 Jun 2024 18:35:10 +0330 Subject: [PATCH 04/10] Test `ValueMap`: Add registrations to test_qml.cpp and add a test. Still need to enhance the coverage of this basic test. --- test/qml/tst_editorwidgets.qml | 65 ++++++++++++++++++++++++++++++++++ test/test_qml.cpp | 46 ++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/test/qml/tst_editorwidgets.qml b/test/qml/tst_editorwidgets.qml index 422d6382b1..868f1db36a 100644 --- a/test/qml/tst_editorwidgets.qml +++ b/test/qml/tst_editorwidgets.qml @@ -40,6 +40,29 @@ TestCase { property var field: undefined } + EditorWidgets.ValueMap { + id: valueMap + property var value: undefined + property var config: undefined + property var field: undefined + + property var currentLayer: undefined + + Item { + id: currentLayerTrue + function customProperty(value) { + return true + } + } + + Item { + id: currentLayerFalse + function customProperty(value) { + return false + } + } + } + /** * Test case for textEdit widget @@ -300,4 +323,46 @@ TestCase { // QfSwitch -> checkBox compare(checkBox.children[1].checked, false) } + + function test_01_valueMap() { + let toggleButtons = valueMap.children[0].children[0] + let comboBox = valueMap.children[0].children[1] + + compare(valueMap.toggleButtonsThreshold, 0) + compare(valueMap.state, "comboBoxItemView") + compare(valueMap.currentItemCount, 0) + compare(comboBox.model.length, undefined) + compare(comboBox.currentIndex, toggleButtons.selectedIndex) + + valueMap.currentLayer = currentLayerTrue + valueMap.config = { + "map": [{ + "Buckfast bee": "Apis Mellifera" + }, { + "Carniolan honey bee": "Apis Mellifera Carnica" + }, { + "European honey bee": "Apis Mellifera Mellifera" + }] + } + valueMap.value = "Apis Mellifera" + + compare(valueMap.state, "toggleButtonsView") + compare(comboBox.currentIndex, toggleButtons.selectedIndex) + compare(comboBox.currentIndex, toggleButtons.selectedIndex) + compare(valueMap.currentKeyValue, valueMap.value) + + valueMap.currentLayer = currentLayerFalse + valueMap.value = "Apis Mellifera Carnica" + compare(valueMap.state, "comboBoxItemView") + compare(comboBox.currentIndex, toggleButtons.selectedIndex) + compare(comboBox.currentIndex, toggleButtons.selectedIndex) + compare(valueMap.currentKeyValue, valueMap.value) + + console.log("->", valueMap.currentKeyValue) + console.log(comboBox.currentIndex, toggleButtons.selectedIndex) + console.log(comboBox.model) + console.log(toggleButtons.currentSelectedKey) + console.log(toggleButtons.currentSelectedValue) + console.log(comboBox) + } } diff --git a/test/test_qml.cpp b/test/test_qml.cpp index 9cdcae671d..b6cb77eba3 100644 --- a/test/test_qml.cpp +++ b/test/test_qml.cpp @@ -27,7 +27,29 @@ #include #include #include +#include +#include #include +#include +#include + +#include +// #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define REGISTER_SINGLETON( uri, _class, name ) qmlRegisterSingletonType<_class>( uri, 1, 0, name, []( QQmlEngine *engine, QJSEngine *scriptEngine ) -> QObject * { Q_UNUSED(engine); Q_UNUSED(scriptEngine); return new _class(); } ) @@ -157,11 +179,35 @@ class Setup : public QObject qmlInit( engine ); engine->rootContext()->setContextProperty( QStringLiteral( "dataDir" ), mDataDir ); + + qmlRegisterType( "org.qgis", 1, 0, "SnappingUtils" ); + qmlRegisterType( "org.qgis", 1, 0, "MapLayerModel" ); + qmlRegisterType( "org.qgis", 1, 0, "VectorLayer" ); + qmlRegisterType( "org.qgis", 1, 0, "MapThemeCollection" ); + // qmlRegisterType( "org.qgis", 1, 0, "QgsLocatorProxyModel" ); + qmlRegisterType( "org.qgis", 1, 0, "QgsVectorLayerEditBuffer" ); + qmlRegisterUncreatableType( "org.qgis", 1, 0, "Qgis", "" ); + qmlRegisterUncreatableType( "org.qgis", 1, 0, "Project", "" ); + qmlRegisterUncreatableType( "org.qgis", 1, 0, "ProjectDisplaySettings", "" ); + qmlRegisterUncreatableType( "org.qgis", 1, 0, "CoordinateReferenceSystem", "" ); + qmlRegisterUncreatableType( "org.qgis", 1, 0, "QgsUnitTypes", "" ); + qmlRegisterUncreatableType( "org.qgis", 1, 0, "RelationManager", "The relation manager is available from the QgsProject. Try `qgisProject.relationManager`" ); + qmlRegisterUncreatableType( "org.qgis", 1, 0, "QgsWkbTypes", "" ); + qmlRegisterUncreatableType( "org.qgis", 1, 0, "MapLayer", "" ); + qmlRegisterUncreatableType( "org.qgis", 1, 0, "VectorLayerStatic", "" ); + qmlRegisterType( "org.qgis", 1, 0, "MapCanvasMap" ); + qmlRegisterType( "org.qgis", 1, 0, "MapSettings" ); + qmlRegisterType( "org.qfield", 1, 0, "CoordinateTransformer" ); + qmlRegisterType( "org.qgis", 1, 0, "ElevationProfileCanvas" ); + qmlRegisterType( "org.qgis", 1, 0, "MapTransform" ); + + qRegisterMetaType( "QgsGeometry" ); qRegisterMetaType( "QgsFeature" ); qRegisterMetaType( "QgsPoint" ); qRegisterMetaType( "QgsPointXY" ); + qmlRegisterType( "org.qfield", 1, 0, "ValueMapModel" ); qmlRegisterType( "org.qfield", 1, 0, "CoordinateTransformer" ); qmlRegisterUncreatableType( "org.qfield", 1, 0, "QAbstractSocket", "" ); qmlRegisterUncreatableType( "org.qfield", 1, 0, "AbstractGnssReceiver", "" ); From 3108b545bf8c1d55ed3e996a10887f07e64fd01a Mon Sep 17 00:00:00 2001 From: Mohsen Date: Sun, 23 Jun 2024 21:09:37 +0330 Subject: [PATCH 05/10] Use variables instead of using children items. --- test/qml/tst_editorwidgets.qml | 128 ++++++++++++++------------------- 1 file changed, 53 insertions(+), 75 deletions(-) diff --git a/test/qml/tst_editorwidgets.qml b/test/qml/tst_editorwidgets.qml index 868f1db36a..71cc8a6edf 100644 --- a/test/qml/tst_editorwidgets.qml +++ b/test/qml/tst_editorwidgets.qml @@ -72,14 +72,13 @@ TestCase { * setting its value to "seven", and comparing its children's texts with "six" and "seven". */ function test_01_textEdit() { - // Label -> textReadonlyValue - compare(textEdit.children[0].text, "") // NOTE: If the config is undefined, the label will be an empty string. + let textReadonlyValue = textEdit.children[0] + let textField = textEdit.children[1] + let textArea = textEdit.children[2] - // TextField -> textField - compare(textEdit.children[1].text, "DEFAULT_VALUE") - - // TextArea -> textArea - compare(textEdit.children[2].text, "DEFAULT_VALUE") + compare(textReadonlyValue.text, "") // NOTE: If the config is undefined, the label will be an empty string. + compare(textField.text, "DEFAULT_VALUE") + compare(textArea.text, "DEFAULT_VALUE") textEdit.config = { "IsMultiline": true, @@ -87,14 +86,9 @@ TestCase { } textEdit.value = "SECOND_VALUE" - // Label -> textReadonlyValue - verify(textEdit.children[0].text.search("SECOND_VALUE") !== -1) - - // TextField -> textField - compare(textEdit.children[1].text, "SECOND_VALUE") - - // TextArea -> textArea - verify(textEdit.children[2].text.search("SECOND_VALUE") !== -1) + verify(textReadonlyValue.text.search("SECOND_VALUE") !== -1) + compare(textField.text, "SECOND_VALUE") + verify(textArea.text.search("SECOND_VALUE") !== -1) textEdit.config = { "IsMultiline": false, @@ -102,14 +96,9 @@ TestCase { } textEdit.value = "THIRD_VALUE" - // Label -> textReadonlyValue - compare(textEdit.children[0].text, "SECOND_VALUE") // NOTE: If the values in the config are set to `false`, the label text will not change. - - // TextField -> textField - compare(textEdit.children[1].text, "THIRD_VALUE") - - // TextArea -> textArea - compare(textEdit.children[2].text, "THIRD_VALUE") + compare(textReadonlyValue.text, "SECOND_VALUE") // NOTE: If the values in the config are set to `false`, the label text will not change. + compare(textField.text, "THIRD_VALUE") + compare(textArea.text, "THIRD_VALUE") } @@ -131,7 +120,12 @@ TestCase { * Finally, setting the value of the range and verifying that it is displayed correctly in both text and slider formats. */ function test_01_range() { - compare(range.children[0].children[0].text, range.default_value + "") + let sliderRow = range.children[0] + let textField = sliderRow.children[0] + let valueLabel = range.children[1].children[0] + let slider = range.children[1].children[1] + + compare(textField.text, range.default_value + "") range.config = { "Style": undefined, @@ -150,10 +144,10 @@ TestCase { compare(range.suffix, "") // Row - // compare(range.children[0].visible, true) // ERROR ? should work but not working! + // compare(sliderRow.visible, true) // ERROR ? should work but not working! // TextField -> textField - compare(range.children[0].children[0].text, "3") + compare(textField.text, "3") range.config = { "Style": "Slider", @@ -171,14 +165,9 @@ TestCase { compare(range.step, 10) compare(range.suffix, "DEFAULT_SUFFIX") - // Row -> sliderRow - compare(range.children[0].visible, false) - - // Text -> valueLabel - compare(range.children[1].children[0].text, range.min + ".00DEFAULT_SUFFIX") // NOTE: using `range.min` because of `rangeItem.parent.value` - - // QfSlider -> slider - compare(range.children[1].children[1].value, range.min) // NOTE: using `range.min` because of `rangeItem.parent.value` + compare(sliderRow.visible, false) + compare(valueLabel.text, range.min + ".00DEFAULT_SUFFIX") // NOTE: using `range.min` because of `rangeItem.parent.value` + compare(slider.value, range.min) // NOTE: using `range.min` because of `rangeItem.parent.value` } @@ -196,7 +185,9 @@ TestCase { * - It sets the value of the datetime widget to the test time and verifies that the text label is displayed correctly according to the format */ function test_01_dateTime() { - compare(dateTime.children[1].children[0].text, "") // NOTE: setting value without setting `config` and `field` objects won't work + let label = dateTime.children[1].children[0] + + compare(label.text, "") // NOTE: setting value without setting `config` and `field` objects won't work const testTimes = ["2023-01-01", "2023-01-01 23:33:56"] const displayFormats = ["yyyy-MM-dd", "yyyy-MM.dd", "yyyy-MM-dd HH:mm:ss", "HH:mm:ss", "HH:mm"] @@ -218,8 +209,7 @@ TestCase { dateTime.value = time - // TextField -> lable - compare(dateTime.children[1].children[0].text, results[resultIdx++]) + compare(label.text, results[resultIdx++]) } } } @@ -244,17 +234,17 @@ TestCase { * - Sets `type` of the field to 0 and verifies that the display is different */ function test_01_checkBox() { + let labelItem = checkBox.children[0] + let checkBoxItem = checkBox.children[1] + compare(checkBox.value, true) compare(checkBox.isBool, false) compare(checkBox.isNull, false) compare(checkBox.checkedLabel, "") // NOTE: `checkedLabel` initialized with "" when config is undefined compare(checkBox.uncheckedLabel, "") // NOTE: `uncheckedLabel` initialized with "" when config is undefined - // Label -> checkValue - compare(checkBox.children[0].text, "") - - // QfSwitch -> checkBox - compare(checkBox.children[1].checked, false) // NOTE: even if `value` be true, without config `checked` will be false + compare(labelItem.text, "") + compare(checkBoxItem.checked, false) // NOTE: even if `value` be true, without config `checked` will be false checkBox.config = { "TextDisplayMethod": 1, @@ -271,19 +261,13 @@ TestCase { compare(checkBox.checkedLabel, "DEFAULT_CHECKED_STATE") compare(checkBox.uncheckedLabel, "DEFAULT_UNCHECKED_STATE") - // Label -> checkValue - compare(checkBox.children[0].text, "DEFAULT_CHECKED_STATE") - - // QfSwitch -> checkBox - compare(checkBox.children[1].checked, true) + compare(labelItem.text, "DEFAULT_CHECKED_STATE") + compare(checkBoxItem.checked, true) checkBox.value = false - // Label -> checkValue - compare(checkBox.children[0].text, "DEFAULT_UNCHECKED_STATE") - - // QfSwitch -> checkBox - compare(checkBox.children[1].checked, false) + compare(labelItem.text, "DEFAULT_UNCHECKED_STATE") + compare(checkBoxItem.checked, false) // test TextDisplayMethod = 0 checkBox.config = { @@ -309,30 +293,24 @@ TestCase { } checkBox.value = true - // Label -> checkValue - compare(checkBox.children[0].text, "DEFAULT_UNCHECKED_STATE") // NOTE: value is true but it in unchecked state - - // QfSwitch -> checkBox - compare(checkBox.children[1].checked, false) // NOTE: value is true but its not checked + compare(labelItem.text, "DEFAULT_UNCHECKED_STATE") // NOTE: value is true but it in unchecked state + compare(checkBoxItem.checked, false) // NOTE: value is true but its not checked checkBox.value = false - // Label -> checkValue - compare(checkBox.children[0].text, "DEFAULT_UNCHECKED_STATE") - - // QfSwitch -> checkBox - compare(checkBox.children[1].checked, false) + compare(labelItem.text, "DEFAULT_UNCHECKED_STATE") + compare(checkBoxItem.checked, false) } function test_01_valueMap() { - let toggleButtons = valueMap.children[0].children[0] - let comboBox = valueMap.children[0].children[1] + let toggleButtonsItem = valueMap.children[0].children[0] + let comboBoxItem = valueMap.children[0].children[1] compare(valueMap.toggleButtonsThreshold, 0) compare(valueMap.state, "comboBoxItemView") compare(valueMap.currentItemCount, 0) - compare(comboBox.model.length, undefined) - compare(comboBox.currentIndex, toggleButtons.selectedIndex) + compare(comboBoxItem.model.length, undefined) + compare(comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) valueMap.currentLayer = currentLayerTrue valueMap.config = { @@ -347,22 +325,22 @@ TestCase { valueMap.value = "Apis Mellifera" compare(valueMap.state, "toggleButtonsView") - compare(comboBox.currentIndex, toggleButtons.selectedIndex) - compare(comboBox.currentIndex, toggleButtons.selectedIndex) + compare(comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) + compare(comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) compare(valueMap.currentKeyValue, valueMap.value) valueMap.currentLayer = currentLayerFalse valueMap.value = "Apis Mellifera Carnica" compare(valueMap.state, "comboBoxItemView") - compare(comboBox.currentIndex, toggleButtons.selectedIndex) - compare(comboBox.currentIndex, toggleButtons.selectedIndex) + compare(comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) + compare(comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) compare(valueMap.currentKeyValue, valueMap.value) console.log("->", valueMap.currentKeyValue) - console.log(comboBox.currentIndex, toggleButtons.selectedIndex) - console.log(comboBox.model) - console.log(toggleButtons.currentSelectedKey) - console.log(toggleButtons.currentSelectedValue) - console.log(comboBox) + console.log(comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) + console.log(comboBoxItem.model) + console.log(toggleButtonsItem.currentSelectedKey) + console.log(toggleButtonsItem.currentSelectedValue) + console.log(comboBoxItem) } } From e59d399c67275c64264c1246ddd8e019528f1299 Mon Sep 17 00:00:00 2001 From: Mohsen Date: Sun, 23 Jun 2024 21:14:39 +0330 Subject: [PATCH 06/10] Use const instead of let. --- test/qml/tst_editorwidgets.qml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/qml/tst_editorwidgets.qml b/test/qml/tst_editorwidgets.qml index 71cc8a6edf..050bd92fd8 100644 --- a/test/qml/tst_editorwidgets.qml +++ b/test/qml/tst_editorwidgets.qml @@ -72,9 +72,9 @@ TestCase { * setting its value to "seven", and comparing its children's texts with "six" and "seven". */ function test_01_textEdit() { - let textReadonlyValue = textEdit.children[0] - let textField = textEdit.children[1] - let textArea = textEdit.children[2] + const textReadonlyValue = textEdit.children[0] + const textField = textEdit.children[1] + const textArea = textEdit.children[2] compare(textReadonlyValue.text, "") // NOTE: If the config is undefined, the label will be an empty string. compare(textField.text, "DEFAULT_VALUE") @@ -120,10 +120,10 @@ TestCase { * Finally, setting the value of the range and verifying that it is displayed correctly in both text and slider formats. */ function test_01_range() { - let sliderRow = range.children[0] - let textField = sliderRow.children[0] - let valueLabel = range.children[1].children[0] - let slider = range.children[1].children[1] + const sliderRow = range.children[0] + const textField = sliderRow.children[0] + const valueLabel = range.children[1].children[0] + const slider = range.children[1].children[1] compare(textField.text, range.default_value + "") @@ -185,7 +185,7 @@ TestCase { * - It sets the value of the datetime widget to the test time and verifies that the text label is displayed correctly according to the format */ function test_01_dateTime() { - let label = dateTime.children[1].children[0] + const label = dateTime.children[1].children[0] compare(label.text, "") // NOTE: setting value without setting `config` and `field` objects won't work @@ -234,8 +234,8 @@ TestCase { * - Sets `type` of the field to 0 and verifies that the display is different */ function test_01_checkBox() { - let labelItem = checkBox.children[0] - let checkBoxItem = checkBox.children[1] + const labelItem = checkBox.children[0] + const checkBoxItem = checkBox.children[1] compare(checkBox.value, true) compare(checkBox.isBool, false) @@ -303,8 +303,8 @@ TestCase { } function test_01_valueMap() { - let toggleButtonsItem = valueMap.children[0].children[0] - let comboBoxItem = valueMap.children[0].children[1] + const toggleButtonsItem = valueMap.children[0].children[0] + const comboBoxItem = valueMap.children[0].children[1] compare(valueMap.toggleButtonsThreshold, 0) compare(valueMap.state, "comboBoxItemView") From 6115f672cd3a5e2b00c3ff665b16c17cd1c6f88d Mon Sep 17 00:00:00 2001 From: Mohsen Date: Mon, 24 Jun 2024 21:27:22 +0330 Subject: [PATCH 07/10] Add small scenario for valueMap test . --- test/qml/tst_editorwidgets.qml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/test/qml/tst_editorwidgets.qml b/test/qml/tst_editorwidgets.qml index 050bd92fd8..2bd2e16c35 100644 --- a/test/qml/tst_editorwidgets.qml +++ b/test/qml/tst_editorwidgets.qml @@ -302,6 +302,16 @@ TestCase { compare(checkBoxItem.checked, false) } + /** + * Tests the valueMap object and its properties + * + * This function tests the valueMap object and its properties, including: + * - The initial state and current item count + * - The comboBoxItem model and current index + * - The toggleButtonsItem selected index + * - The current layer and config + * - The value and current key value + */ function test_01_valueMap() { const toggleButtonsItem = valueMap.children[0].children[0] const comboBoxItem = valueMap.children[0].children[1] @@ -336,11 +346,12 @@ TestCase { compare(comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) compare(valueMap.currentKeyValue, valueMap.value) - console.log("->", valueMap.currentKeyValue) - console.log(comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) - console.log(comboBoxItem.model) - console.log(toggleButtonsItem.currentSelectedKey) - console.log(toggleButtonsItem.currentSelectedValue) - console.log(comboBoxItem) + console.log("Check ->", valueMap.currentKeyValue) + console.log("Check ->", comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) + console.log("Check ->", comboBoxItem.model) + console.log("Check ->", comboBoxItem.model.rowCount()) + console.log("Check ->", toggleButtonsItem.currentSelectedKey) + console.log("Check ->", toggleButtonsItem.currentSelectedValue) + console.log("Check ->", comboBoxItem) } } From 7200a53867e5578f5a9f758dabc7202b20efeb4d Mon Sep 17 00:00:00 2001 From: Mohsen Date: Tue, 25 Jun 2024 14:02:39 +0330 Subject: [PATCH 08/10] Add some initial tests for UuidGenerator. --- test/qml/tst_editorwidgets.qml | 69 ++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/test/qml/tst_editorwidgets.qml b/test/qml/tst_editorwidgets.qml index 2bd2e16c35..ca1f08da1a 100644 --- a/test/qml/tst_editorwidgets.qml +++ b/test/qml/tst_editorwidgets.qml @@ -27,6 +27,7 @@ TestCase { EditorWidgets.DateTime { id: dateTime + fieldIsDate: false // to simulate LayerUtils.fieldType( field ) != 'QDate' property string value: "2022-01-01" property var config: undefined property var field: undefined @@ -45,24 +46,32 @@ TestCase { property var value: undefined property var config: undefined property var field: undefined - property var currentLayer: undefined + // to simulate customProperty('QFieldSync/value_map_button_interface_threshold') -> toggleButtons view Item { id: currentLayerTrue function customProperty(value) { - return true + return 100 } } + // to to simulate customProperty('QFieldSync/value_map_button_interface_threshold') -> comboBox veiw Item { id: currentLayerFalse function customProperty(value) { - return false + return 0 } } } + EditorWidgets.UuidGenerator{ + id: uuidGenerator + property var value: undefined + property var config: undefined + property bool isAdding: false + } + /** * Test case for textEdit widget @@ -101,7 +110,6 @@ TestCase { compare(textArea.text, "THIRD_VALUE") } - /** * Test case for range widget * @@ -146,7 +154,6 @@ TestCase { // Row // compare(sliderRow.visible, true) // ERROR ? should work but not working! - // TextField -> textField compare(textField.text, "3") range.config = { @@ -170,7 +177,6 @@ TestCase { compare(slider.value, range.min) // NOTE: using `range.min` because of `rangeItem.parent.value` } - /** * Test case for datetime widget * @@ -183,6 +189,8 @@ TestCase { * - For each of the test times, it iterates over the display formats and sets the config with the format, calendar popup enabled, unknown field format, and disallows null values * - It sets the field to a date or time type * - It sets the value of the datetime widget to the test time and verifies that the text label is displayed correctly according to the format + * + * TODO: Test `fieldIsDate = true` too, if the field is a date only -> revert the time zone offset. */ function test_01_dateTime() { const label = dateTime.children[1].children[0] @@ -197,6 +205,7 @@ TestCase { for (let time of testTimes) { for (let format of displayFormats) { + dateTime.fieldIsDate = false; dateTime.config = { "display_format": format, "calendar_popup": true, @@ -208,13 +217,11 @@ TestCase { } dateTime.value = time - compare(label.text, results[resultIdx++]) } } } - /** * Test case for checkBox widget * @@ -311,6 +318,8 @@ TestCase { * - The toggleButtonsItem selected index * - The current layer and config * - The value and current key value + * + * TODO: needs more checks on search and changing selected item in combobox or toggleButtons */ function test_01_valueMap() { const toggleButtonsItem = valueMap.children[0].children[0] @@ -322,7 +331,6 @@ TestCase { compare(comboBoxItem.model.length, undefined) compare(comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) - valueMap.currentLayer = currentLayerTrue valueMap.config = { "map": [{ "Buckfast bee": "Apis Mellifera" @@ -332,26 +340,47 @@ TestCase { "European honey bee": "Apis Mellifera Mellifera" }] } - valueMap.value = "Apis Mellifera" + valueMap.currentLayer = currentLayerTrue + valueMap.value = "Apis Mellifera" compare(valueMap.state, "toggleButtonsView") compare(comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) compare(comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) - compare(valueMap.currentKeyValue, valueMap.value) + compare(valueMap.currentKeyValue, "Apis Mellifera") valueMap.currentLayer = currentLayerFalse valueMap.value = "Apis Mellifera Carnica" compare(valueMap.state, "comboBoxItemView") compare(comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) compare(comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) - compare(valueMap.currentKeyValue, valueMap.value) - - console.log("Check ->", valueMap.currentKeyValue) - console.log("Check ->", comboBoxItem.currentIndex, toggleButtonsItem.selectedIndex) - console.log("Check ->", comboBoxItem.model) - console.log("Check ->", comboBoxItem.model.rowCount()) - console.log("Check ->", toggleButtonsItem.currentSelectedKey) - console.log("Check ->", toggleButtonsItem.currentSelectedValue) - console.log("Check ->", comboBoxItem) + compare(valueMap.currentKeyValue, "Apis Mellifera Carnica") + } + + /** + * Tests the UUIDGenerator object and its properties + * + * This function tests the UUIDGenerator object and its properties, including: + * - The initial state and value + * - The isLoaded and isAdding properties + * - The label text + * - The reset function + * + * TODO: + * - The generateUUID function + */ + function test_01_UuidGenerator() { + const label = uuidGenerator.children[0] + compare(label.text, ""); + compare(uuidGenerator.isLoaded, false); + + uuidGenerator.value = "ANY_VALUE" + compare(label.text, "ANY_VALUE"); + + uuidGenerator.isAdding = true + uuidGenerator.isLoaded = true + uuidGenerator.value = "" + // NOTE: with isAdding && isLoaded && empty value, label should be StringUtils.createUuid() + // but because `StringUtils` is not defined it should remain as its previous value + compare(label.text, "ANY_VALUE"); } } From 879ee3ecd7d60e9d0936b71e275dd87fe9ad9520 Mon Sep 17 00:00:00 2001 From: Mohsen Date: Thu, 27 Jun 2024 11:59:46 +0330 Subject: [PATCH 09/10] Fix QgsLocatorProxyModel register for qml_test. --- test/test_qml.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/test/test_qml.cpp b/test/test_qml.cpp index b6cb77eba3..7542200c31 100644 --- a/test/test_qml.cpp +++ b/test/test_qml.cpp @@ -25,19 +25,15 @@ #include #include #include +#include +#include #include #include +#include +#include #include #include #include -#include -#include - -#include -// #include -#include -#include #include #include #include @@ -46,11 +42,14 @@ #include #include #include +#include #include #include #include #include +#include + #define REGISTER_SINGLETON( uri, _class, name ) qmlRegisterSingletonType<_class>( uri, 1, 0, name, []( QQmlEngine *engine, QJSEngine *scriptEngine ) -> QObject * { Q_UNUSED(engine); Q_UNUSED(scriptEngine); return new _class(); } ) class NmeaServer : public QObject @@ -184,7 +183,7 @@ class Setup : public QObject qmlRegisterType( "org.qgis", 1, 0, "MapLayerModel" ); qmlRegisterType( "org.qgis", 1, 0, "VectorLayer" ); qmlRegisterType( "org.qgis", 1, 0, "MapThemeCollection" ); - // qmlRegisterType( "org.qgis", 1, 0, "QgsLocatorProxyModel" ); + qmlRegisterType( "org.qgis", 1, 0, "QgsLocatorProxyModel" ); qmlRegisterType( "org.qgis", 1, 0, "QgsVectorLayerEditBuffer" ); qmlRegisterUncreatableType( "org.qgis", 1, 0, "Qgis", "" ); qmlRegisterUncreatableType( "org.qgis", 1, 0, "Project", "" ); From 1f9226e1c1a288681258ca624a23bfccaec59569 Mon Sep 17 00:00:00 2001 From: Mohsen Date: Thu, 27 Jun 2024 13:06:44 +0330 Subject: [PATCH 10/10] Fix an include. --- test/test_qml.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/test_qml.cpp b/test/test_qml.cpp index 7542200c31..e73829d889 100644 --- a/test/test_qml.cpp +++ b/test/test_qml.cpp @@ -19,6 +19,7 @@ #include "positioning.h" #include "qfield_qml_init.h" #include "qgsquickcoordinatetransformer.h" +#include "valuemapmodel.h" #include #include @@ -48,8 +49,6 @@ #include #include -#include - #define REGISTER_SINGLETON( uri, _class, name ) qmlRegisterSingletonType<_class>( uri, 1, 0, name, []( QQmlEngine *engine, QJSEngine *scriptEngine ) -> QObject * { Q_UNUSED(engine); Q_UNUSED(scriptEngine); return new _class(); } ) class NmeaServer : public QObject