Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve settings UI #534

Merged
merged 4 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 43 additions & 32 deletions addons/gdUnit4/src/core/GdUnitSettings.gd
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const SERVER_TIMEOUT = GROUP_COMMON + "/server_connection_timeout_minutes"
const GROUP_TEST = COMMON_SETTINGS + "/test"
const TEST_TIMEOUT = GROUP_TEST + "/test_timeout_seconds"
const TEST_LOOKUP_FOLDER = GROUP_TEST + "/test_lookup_folder"
const TEST_SITE_NAMING_CONVENTION = GROUP_TEST + "/test_suite_naming_convention"
const TEST_SUITE_NAMING_CONVENTION = GROUP_TEST + "/test_suite_naming_convention"
const TEST_DISCOVER_ENABLED = GROUP_TEST + "/test_discovery"


Expand Down Expand Up @@ -81,7 +81,7 @@ const DEFAULT_TEST_TIMEOUT :int = 60*5
const DEFAULT_TEST_LOOKUP_FOLDER := "test"

# help texts
const HELP_TEST_LOOKUP_FOLDER := "Sets the subfolder for the search/creation of test suites. (leave empty to use source folder)"
const HELP_TEST_LOOKUP_FOLDER := "Subfolder where test suites are located (or empty to use source folder directly)"

enum NAMING_CONVENTIONS {
AUTO_DETECT,
Expand All @@ -90,29 +90,32 @@ enum NAMING_CONVENTIONS {
}


const _VALUE_SET_SEPARATOR = "\f" # ASCII Form-feed character (AKA page break)


static func setup() -> void:
create_property_if_need(UPDATE_NOTIFICATION_ENABLED, true, "Enables/Disables the update notification checked startup.")
create_property_if_need(SERVER_TIMEOUT, DEFAULT_SERVER_TIMEOUT, "Sets the server connection timeout in minutes.")
create_property_if_need(TEST_TIMEOUT, DEFAULT_TEST_TIMEOUT, "Sets the test case runtime timeout in seconds.")
create_property_if_need(UPDATE_NOTIFICATION_ENABLED, true, "Show notification if new gdUnit4 version is found")
create_property_if_need(SERVER_TIMEOUT, DEFAULT_SERVER_TIMEOUT, "Server connection timeout in minutes")
create_property_if_need(TEST_TIMEOUT, DEFAULT_TEST_TIMEOUT, "Test case runtime timeout in seconds")
create_property_if_need(TEST_LOOKUP_FOLDER, DEFAULT_TEST_LOOKUP_FOLDER, HELP_TEST_LOOKUP_FOLDER)
create_property_if_need(TEST_SITE_NAMING_CONVENTION, NAMING_CONVENTIONS.AUTO_DETECT, "Sets test-suite genrate script name convention.", NAMING_CONVENTIONS.keys())
create_property_if_need(TEST_DISCOVER_ENABLED, false, "Enables/Disables the automatic detection of tests by finding tests in test lookup folders at runtime.")
create_property_if_need(REPORT_PUSH_ERRORS, false, "Enables/Disables report of push_error() as failure!")
create_property_if_need(REPORT_SCRIPT_ERRORS, true, "Enables/Disables report of script errors as failure!")
create_property_if_need(REPORT_ORPHANS, true, "Enables/Disables orphan reporting.")
create_property_if_need(REPORT_ASSERT_ERRORS, true, "Enables/Disables error reporting checked asserts.")
create_property_if_need(REPORT_ASSERT_WARNINGS, true, "Enables/Disables warning reporting checked asserts")
create_property_if_need(REPORT_ASSERT_STRICT_NUMBER_TYPE_COMPARE, true, "Enabled/disabled number values will be compared strictly by type. (real vs int)")
create_property_if_need(TEST_SUITE_NAMING_CONVENTION, NAMING_CONVENTIONS.AUTO_DETECT, "Naming convention to use when generating testsuites", NAMING_CONVENTIONS.keys())
create_property_if_need(TEST_DISCOVER_ENABLED, false, "Automatically detect new tests in test lookup folders at runtime")
create_property_if_need(REPORT_PUSH_ERRORS, false, "Report push_error() as failure")
create_property_if_need(REPORT_SCRIPT_ERRORS, true, "Report script errors as failure")
create_property_if_need(REPORT_ORPHANS, true, "Report orphaned nodes after tests finish")
create_property_if_need(REPORT_ASSERT_ERRORS, true, "Report assertion failures as errors")
create_property_if_need(REPORT_ASSERT_WARNINGS, true, "Report assertion failures as warnings")
create_property_if_need(REPORT_ASSERT_STRICT_NUMBER_TYPE_COMPARE, true, "Compare number values strictly by type (real vs int)")
# inspector
create_property_if_need(INSPECTOR_NODE_COLLAPSE, true,
"Enables/Disables that the testsuite node is closed after a successful test run.")
"Close testsuite node after a successful test run.")
create_property_if_need(INSPECTOR_TREE_VIEW_MODE, GdUnitInspectorTreeConstants.TREE_VIEW_MODE.TREE,
"Sets the inspector panel presentation.", GdUnitInspectorTreeConstants.TREE_VIEW_MODE.keys())
"Inspector panel presentation mode", GdUnitInspectorTreeConstants.TREE_VIEW_MODE.keys())
create_property_if_need(INSPECTOR_TREE_SORT_MODE, GdUnitInspectorTreeConstants.SORT_MODE.UNSORTED,
"Sets the inspector panel presentation.", GdUnitInspectorTreeConstants.SORT_MODE.keys())
"Inspector panel sorting mode", GdUnitInspectorTreeConstants.SORT_MODE.keys())
create_property_if_need(INSPECTOR_TOOLBAR_BUTTON_RUN_OVERALL, false,
"Shows/Hides the 'Run overall Tests' button in the inspector toolbar.")
create_property_if_need(TEMPLATE_TS_GD, GdUnitTestSuiteTemplate.default_GD_template(), "Defines the test suite template")
"Show 'Run overall Tests' button in the inspector toolbar")
create_property_if_need(TEMPLATE_TS_GD, GdUnitTestSuiteTemplate.default_GD_template(), "Test suite template to use")
create_shortcut_properties_if_need()
migrate_properties()

Expand All @@ -129,17 +132,17 @@ static func migrate_properties() -> void:

static func create_shortcut_properties_if_need() -> void:
# inspector
create_property_if_need(SHORTCUT_INSPECTOR_RERUN_TEST, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.RERUN_TESTS), "Rerun of the last tests performed.")
create_property_if_need(SHORTCUT_INSPECTOR_RERUN_TEST_DEBUG, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.RERUN_TESTS_DEBUG), "Rerun of the last tests performed (Debug).")
create_property_if_need(SHORTCUT_INSPECTOR_RUN_TEST_OVERALL, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.RUN_TESTS_OVERALL), "Runs all tests (Debug).")
create_property_if_need(SHORTCUT_INSPECTOR_RUN_TEST_STOP, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.STOP_TEST_RUN), "Stops the current test execution.")
create_property_if_need(SHORTCUT_INSPECTOR_RERUN_TEST, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.RERUN_TESTS), "Rerun the most recently executed tests")
create_property_if_need(SHORTCUT_INSPECTOR_RERUN_TEST_DEBUG, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.RERUN_TESTS_DEBUG), "Rerun the most recently executed tests (Debug mode)")
create_property_if_need(SHORTCUT_INSPECTOR_RUN_TEST_OVERALL, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.RUN_TESTS_OVERALL), "Runs all tests (Debug mode)")
create_property_if_need(SHORTCUT_INSPECTOR_RUN_TEST_STOP, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.STOP_TEST_RUN), "Stop the current test execution")
# script editor
create_property_if_need(SHORTCUT_EDITOR_RUN_TEST, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.RUN_TESTCASE), "Runs the currently selected test.")
create_property_if_need(SHORTCUT_EDITOR_RUN_TEST_DEBUG, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.RUN_TESTCASE_DEBUG), "Runs the currently selected test (Debug).")
create_property_if_need(SHORTCUT_EDITOR_CREATE_TEST, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.CREATE_TEST), "Creates a new test case for the currently selected function.")
create_property_if_need(SHORTCUT_EDITOR_RUN_TEST, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.RUN_TESTCASE), "Run the currently selected test")
create_property_if_need(SHORTCUT_EDITOR_RUN_TEST_DEBUG, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.RUN_TESTCASE_DEBUG), "Run the currently selected test (Debug mode).")
create_property_if_need(SHORTCUT_EDITOR_CREATE_TEST, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.CREATE_TEST), "Create a new test case for the currently selected function")
# filesystem
create_property_if_need(SHORTCUT_FILESYSTEM_RUN_TEST, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.NONE), "Runs all test suites on the selected folder or file.")
create_property_if_need(SHORTCUT_FILESYSTEM_RUN_TEST_DEBUG, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.NONE), "Runs all test suites on the selected folder or file (Debug).")
create_property_if_need(SHORTCUT_FILESYSTEM_RUN_TEST, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.NONE), "Run all test suites in the selected folder or file")
create_property_if_need(SHORTCUT_FILESYSTEM_RUN_TEST_DEBUG, GdUnitShortcut.default_keys(GdUnitShortcut.ShortCut.NONE), "Run all test suites in the selected folder or file (Debug)")


static func create_property_if_need(name :String, default :Variant, help :="", value_set := PackedStringArray()) -> void:
Expand All @@ -148,7 +151,7 @@ static func create_property_if_need(name :String, default :Variant, help :="", v
ProjectSettings.set_setting(name, default)

ProjectSettings.set_initial_value(name, default)
help += "" if value_set.is_empty() else " %s" % value_set
help = help if value_set.is_empty() else "%s%s%s" % [help, _VALUE_SET_SEPARATOR, value_set]
set_help(name, default, help)


Expand Down Expand Up @@ -280,20 +283,28 @@ static func list_settings(category :String) -> Array[GdUnitProperty]:
var default :Variant = ProjectSettings.property_get_revert(property_name)
var help :String = property["hint_string"]
var value_set := extract_value_set_from_help(help)
settings.append(GdUnitProperty.new(property_name, property["type"], value, default, help, value_set))
settings.append(GdUnitProperty.new(property_name, property["type"], value, default, extract_help_text(help), value_set))
return settings


static func extract_value_set_from_help(value :String) -> PackedStringArray:
var split_value := value.split(_VALUE_SET_SEPARATOR)
if not split_value.size() > 1:
return PackedStringArray()

var regex := RegEx.new()
regex.compile("\\[(.+)\\]")
var matches := regex.search_all(value)
var matches := regex.search_all(split_value[1])
if matches.is_empty():
return PackedStringArray()
var values :String = matches[0].get_string(1)
var values: String = matches[0].get_string(1)
return values.replacen(" ", "").replacen("\"", "").split(",", false)


static func extract_help_text(value :String) -> String:
return value.split(_VALUE_SET_SEPARATOR)[0]


static func update_property(property :GdUnitProperty) -> Variant:
var current_value :Variant = ProjectSettings.get_setting(property.name())
if current_value != property.value():
Expand Down Expand Up @@ -353,7 +364,7 @@ static func get_property(name :String) -> GdUnitProperty:
var default :Variant = ProjectSettings.property_get_revert(property_name)
var help :String = property["hint_string"]
var value_set := extract_value_set_from_help(help)
return GdUnitProperty.new(property_name, property["type"], value, default, help, value_set)
return GdUnitProperty.new(property_name, property["type"], value, default, extract_help_text(help), value_set)
return null


Expand Down
2 changes: 1 addition & 1 deletion addons/gdUnit4/src/core/GdUnitTestSuiteScanner.gd
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ func _validate_argument(fd :GdFunctionDescriptor, test_case :_TestCase) -> void:

# converts given file name by configured naming convention
static func _to_naming_convention(file_name :String) -> String:
var nc :int = GdUnitSettings.get_setting(GdUnitSettings.TEST_SITE_NAMING_CONVENTION, 0)
var nc :int = GdUnitSettings.get_setting(GdUnitSettings.TEST_SUITE_NAMING_CONVENTION, 0)
match nc:
GdUnitSettings.NAMING_CONVENTIONS.AUTO_DETECT:
if GdObjects.is_snake_case(file_name):
Expand Down
28 changes: 18 additions & 10 deletions addons/gdUnit4/src/ui/settings/GdUnitSettingsDialog.gd
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,30 @@ func setup_properties(properties_parent: Node, property_category: String) -> voi
theme_.set_constant("h_separation", "GridContainer", 12)
var last_category := "!"
var min_size_overall := 0.0
var labels := []
var inputs := []
var info_labels := []
var grid: GridContainer = null
for p in category_properties:
var min_size_ := 0.0
var grid := GridContainer.new()
grid.columns = 4
grid.theme = theme_
var property: GdUnitProperty = p
var current_category := property.category()
if current_category != last_category:
if not grid or current_category != last_category:
grid = GridContainer.new()
grid.columns = 4
grid.theme = theme_

var sub_category: Node = _properties_template.get_child(3).duplicate()
sub_category.get_child(0).text = current_category.capitalize()
sub_category.custom_minimum_size.y = _font_size + 16
properties_parent.add_child(sub_category)
properties_parent.add_child(grid)
last_category = current_category
# property name
var label: Label = _properties_template.get_child(0).duplicate()
label.text = _to_human_readable(property.name())
label.custom_minimum_size = Vector2(_font_size * 20, 0)
labels.append(label)
grid.add_child(label)
min_size_ += label.size.x

# property reset btn
var reset_btn: Button = _properties_template.get_child(1).duplicate()
Expand All @@ -83,18 +88,21 @@ func setup_properties(properties_parent: Node, property_category: String) -> voi

# property type specific input element
var input: Node = _create_input_element(property, reset_btn)
input.custom_minimum_size = Vector2(_font_size * 15, 0)
inputs.append(input)
grid.add_child(input)
min_size_ += input.size.x
reset_btn.pressed.connect(_on_btn_property_reset_pressed.bind(property, input, reset_btn))
# property help text
var info: Node = _properties_template.get_child(2).duplicate()
info.text = property.help()
info_labels.append(info)
grid.add_child(info)
min_size_ += info.text.length() * _font_size
if min_size_overall < min_size_:
min_size_overall = min_size_
properties_parent.add_child(grid)
for controls: Array in [labels, inputs, info_labels]:
var _size: float = controls.map(func(c: Control) -> float: return c.size.x).max()
min_size_overall += _size
for control: Control in controls:
control.custom_minimum_size.x = _size
properties_parent.custom_minimum_size.x = min_size_overall


Expand Down
7 changes: 1 addition & 6 deletions addons/gdUnit4/src/ui/settings/GdUnitSettingsDialog.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ shadow_offset = Vector2(10, 10)
[node name="Control" type="Window"]
disable_3d = true
gui_embed_subwindows = true
title = "GdUnitSettings"
title = "GdUnit4 Settings"
mathrick marked this conversation as resolved.
Show resolved Hide resolved
initial_position = 1
size = Vector2i(1006, 723)
visible = false
Expand Down Expand Up @@ -157,7 +157,6 @@ offset_right = 590.0
offset_bottom = 25.0
size_flags_horizontal = 3
text = "Enables/disables the update notification "
clip_text = true
max_lines_visible = 1

[node name="sub_category" type="Panel" parent="property_template"]
Expand Down Expand Up @@ -310,7 +309,6 @@ layout_mode = 2
[node name="common-content" type="VBoxContainer" parent="Panel/PanelContainer/v/MarginContainer/GridContainer/Properties/Common"]
unique_name_in_owner = true
clip_contents = true
custom_minimum_size = Vector2(1557, 0)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
Expand All @@ -322,7 +320,6 @@ layout_mode = 2
[node name="ui-content" type="VBoxContainer" parent="Panel/PanelContainer/v/MarginContainer/GridContainer/Properties/UI"]
unique_name_in_owner = true
clip_contents = true
custom_minimum_size = Vector2(1361, 0)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
Expand All @@ -334,7 +331,6 @@ layout_mode = 2
[node name="shortcut-content" type="VBoxContainer" parent="Panel/PanelContainer/v/MarginContainer/GridContainer/Properties/Shortcuts"]
unique_name_in_owner = true
clip_contents = true
custom_minimum_size = Vector2(983, 0)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
Expand All @@ -346,7 +342,6 @@ layout_mode = 2
[node name="report-content" type="VBoxContainer" parent="Panel/PanelContainer/v/MarginContainer/GridContainer/Properties/Report"]
unique_name_in_owner = true
clip_contents = true
custom_minimum_size = Vector2(1249, 0)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
Expand Down
2 changes: 1 addition & 1 deletion addons/gdUnit4/test/core/GdUnitSettingsTest.gd
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func test_enum_property() -> void:
assert_that(property.default()).is_equal(GdUnitSettings.NAMING_CONVENTIONS.AUTO_DETECT)
assert_that(property.value()).is_equal(GdUnitSettings.NAMING_CONVENTIONS.AUTO_DETECT)
assert_that(property.type()).is_equal(TYPE_INT)
assert_that(property.help()).is_equal('help ["AUTO_DETECT", "SNAKE_CASE", "PASCAL_CASE"]')
assert_that(property.help()).is_equal('help')
assert_that(property.value_set()).is_equal(value_set)


Expand Down
8 changes: 4 additions & 4 deletions addons/gdUnit4/test/core/GdUnitTestSuiteScannerTest.gd
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ extends GdUnitTestSuite
const __source = 'res://addons/gdUnit4/src/core/GdUnitTestSuiteScanner.gd'

func before_test() -> void:
ProjectSettings.set_setting(GdUnitSettings.TEST_SITE_NAMING_CONVENTION, GdUnitSettings.NAMING_CONVENTIONS.AUTO_DETECT)
ProjectSettings.set_setting(GdUnitSettings.TEST_SUITE_NAMING_CONVENTION, GdUnitSettings.NAMING_CONVENTIONS.AUTO_DETECT)
clean_temp_dir()


Expand Down Expand Up @@ -320,17 +320,17 @@ func test_get_test_case_line_number() -> void:


func test__to_naming_convention() -> void:
ProjectSettings.set_setting(GdUnitSettings.TEST_SITE_NAMING_CONVENTION, GdUnitSettings.NAMING_CONVENTIONS.AUTO_DETECT)
ProjectSettings.set_setting(GdUnitSettings.TEST_SUITE_NAMING_CONVENTION, GdUnitSettings.NAMING_CONVENTIONS.AUTO_DETECT)
assert_str(GdUnitTestSuiteScanner._to_naming_convention("MyClass")).is_equal("MyClassTest")
assert_str(GdUnitTestSuiteScanner._to_naming_convention("my_class")).is_equal("my_class_test")
assert_str(GdUnitTestSuiteScanner._to_naming_convention("myclass")).is_equal("myclass_test")

ProjectSettings.set_setting(GdUnitSettings.TEST_SITE_NAMING_CONVENTION, GdUnitSettings.NAMING_CONVENTIONS.SNAKE_CASE)
ProjectSettings.set_setting(GdUnitSettings.TEST_SUITE_NAMING_CONVENTION, GdUnitSettings.NAMING_CONVENTIONS.SNAKE_CASE)
assert_str(GdUnitTestSuiteScanner._to_naming_convention("MyClass")).is_equal("my_class_test")
assert_str(GdUnitTestSuiteScanner._to_naming_convention("my_class")).is_equal("my_class_test")
assert_str(GdUnitTestSuiteScanner._to_naming_convention("myclass")).is_equal("myclass_test")

ProjectSettings.set_setting(GdUnitSettings.TEST_SITE_NAMING_CONVENTION, GdUnitSettings.NAMING_CONVENTIONS.PASCAL_CASE)
ProjectSettings.set_setting(GdUnitSettings.TEST_SUITE_NAMING_CONVENTION, GdUnitSettings.NAMING_CONVENTIONS.PASCAL_CASE)
assert_str(GdUnitTestSuiteScanner._to_naming_convention("MyClass")).is_equal("MyClassTest")
assert_str(GdUnitTestSuiteScanner._to_naming_convention("my_class")).is_equal("MyClassTest")
assert_str(GdUnitTestSuiteScanner._to_naming_convention("myclass")).is_equal("MyclassTest")
Expand Down