diff --git a/addons/gdUnit4/plugin.cfg b/addons/gdUnit4/plugin.cfg index 1bfdd62..cf7c92f 100644 --- a/addons/gdUnit4/plugin.cfg +++ b/addons/gdUnit4/plugin.cfg @@ -3,5 +3,5 @@ name="gdUnit4" description="Unit Testing Framework for Godot Scripts" author="Mike Schulze" -version="4.3.2" +version="4.3.3" script="plugin.gd" diff --git a/addons/gdUnit4/plugin.gd b/addons/gdUnit4/plugin.gd index 1c52ecd..37a2a69 100644 --- a/addons/gdUnit4/plugin.gd +++ b/addons/gdUnit4/plugin.gd @@ -1,12 +1,11 @@ @tool extends EditorPlugin -const GdUnitTools := preload("res://addons/gdUnit4/src/core/GdUnitTools.gd") -const GdUnitTestDiscoverGuard := preload("res://addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverGuard.gd") +const GdUnitTools := preload ("res://addons/gdUnit4/src/core/GdUnitTools.gd") +const GdUnitTestDiscoverGuard := preload ("res://addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverGuard.gd") var _gd_inspector :Node -var _server_node :Node var _gd_console :Node var _guard: GdUnitTestDiscoverGuard @@ -25,11 +24,9 @@ func _enter_tree() -> void: # install the GdUnit Console _gd_console = load("res://addons/gdUnit4/src/ui/GdUnitConsole.tscn").instantiate() add_control_to_bottom_panel(_gd_console, "gdUnitConsole") - _server_node = load("res://addons/gdUnit4/src/network/GdUnitServer.tscn").instantiate() - Engine.get_main_loop().root.add_child.call_deferred(_server_node) prints("Loading GdUnit4 Plugin success") if GdUnitSettings.is_update_notification_enabled(): - var update_tool :Node = load("res://addons/gdUnit4/src/update/GdUnitUpdateNotify.tscn").instantiate() + var update_tool: Node = load("res://addons/gdUnit4/src/update/GdUnitUpdateNotify.tscn").instantiate() Engine.get_main_loop().root.add_child.call_deferred(update_tool) if GdUnit4CSharpApiLoader.is_mono_supported(): prints("GdUnit4Net version '%s' loaded." % GdUnit4CSharpApiLoader.version()) @@ -43,14 +40,11 @@ func _exit_tree() -> void: return if is_instance_valid(_gd_inspector): remove_control_from_docks(_gd_inspector) - GodotVersionFixures.free_fix(_gd_inspector) + _gd_inspector.free() if is_instance_valid(_gd_console): remove_control_from_bottom_panel(_gd_console) _gd_console.free() - if is_instance_valid(_server_node): - Engine.get_main_loop().root.remove_child.call_deferred(_server_node) - _server_node.queue_free() - GdUnitTools.dispose_all.call_deferred() + GdUnitTools.dispose_all(true) prints("Unload GdUnit4 Plugin success") @@ -60,6 +54,6 @@ func check_running_in_test_env() -> bool: return DisplayServer.get_name() == "headless" or args.has("--selftest") or args.has("--add") or args.has("-a") or args.has("--quit-after") or args.has("--import") -func _on_resource_saved(resource :Resource) -> void: +func _on_resource_saved(resource: Resource) -> void: if resource is Script: _guard.discover(resource) diff --git a/addons/gdUnit4/src/GdUnitArrayAssert.gd b/addons/gdUnit4/src/GdUnitArrayAssert.gd index 3fdaaca..cc2226d 100644 --- a/addons/gdUnit4/src/GdUnitArrayAssert.gd +++ b/addons/gdUnit4/src/GdUnitArrayAssert.gd @@ -158,3 +158,14 @@ func extractv( extractor8 :GdUnitValueExtractor = null, extractor9 :GdUnitValueExtractor = null) -> GdUnitArrayAssert: return self + + + +@warning_ignore("unused_parameter") +func override_failure_message(message :String) -> GdUnitArrayAssert: + return self + + +@warning_ignore("unused_parameter") +func append_failure_message(message :String) -> GdUnitArrayAssert: + return self diff --git a/addons/gdUnit4/src/GdUnitAssert.gd b/addons/gdUnit4/src/GdUnitAssert.gd index d2a5fd0..fe056d8 100644 --- a/addons/gdUnit4/src/GdUnitAssert.gd +++ b/addons/gdUnit4/src/GdUnitAssert.gd @@ -39,3 +39,11 @@ func test_fail(): @warning_ignore("untyped_declaration") func override_failure_message(message :String): return self + + +## Appends a custom message to the failure message. +## This can be used to add additional infromations to the generated failure message. +@warning_ignore("unused_parameter") +@warning_ignore("untyped_declaration") +func append_failure_message(message :String): + return self diff --git a/addons/gdUnit4/src/GdUnitFailureAssert.gd b/addons/gdUnit4/src/GdUnitFailureAssert.gd index 64ff965..1ee987f 100644 --- a/addons/gdUnit4/src/GdUnitFailureAssert.gd +++ b/addons/gdUnit4/src/GdUnitFailureAssert.gd @@ -29,3 +29,9 @@ func has_message(expected: String) -> GdUnitFailureAssert: @warning_ignore("unused_parameter") func starts_with_message(expected: String) -> GdUnitFailureAssert: return self + + +## Verifies that the failure message contains the expected message. +@warning_ignore("unused_parameter") +func contains_message(expected: String) -> GdUnitFailureAssert: + return self diff --git a/addons/gdUnit4/src/GdUnitTestSuite.gd b/addons/gdUnit4/src/GdUnitTestSuite.gd index 7d689f6..f23cbd7 100644 --- a/addons/gdUnit4/src/GdUnitTestSuite.gd +++ b/addons/gdUnit4/src/GdUnitTestSuite.gd @@ -10,7 +10,7 @@ ## [/codeblock] ## @tutorial: https://mikeschulze.github.io/gdUnit4/faq/test-suite/ -@icon("res://addons/gdUnit4/src/ui/assets/TestSuite.svg") +@icon("res://addons/gdUnit4/src/ui/settings/logo.png") class_name GdUnitTestSuite extends Node diff --git a/addons/gdUnit4/src/asserts/GdAssertMessages.gd b/addons/gdUnit4/src/asserts/GdAssertMessages.gd index 01402ff..315a0a5 100644 --- a/addons/gdUnit4/src/asserts/GdAssertMessages.gd +++ b/addons/gdUnit4/src/asserts/GdAssertMessages.gd @@ -613,3 +613,13 @@ static func format_invalid(value :String) -> String: static func humanized(value :String) -> String: return value.replace("_", " ") + + +static func build_failure_message(failure :String, additional_failure_message: String, custom_failure_message: String) -> String: + var message := failure if custom_failure_message.is_empty() else custom_failure_message + if additional_failure_message.is_empty(): + return message + return """ + %s + [color=LIME_GREEN][b]Additional info:[/b][/color] + %s""".dedent().trim_prefix("\n") % [message, additional_failure_message] diff --git a/addons/gdUnit4/src/asserts/GdUnitArrayAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitArrayAssertImpl.gd index 8b71105..c2c3cef 100644 --- a/addons/gdUnit4/src/asserts/GdUnitArrayAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitArrayAssertImpl.gd @@ -33,7 +33,7 @@ func report_error(error :String) -> GdUnitArrayAssert: func failure_message() -> String: - return _base._current_error_message + return _base.failure_message() func override_failure_message(message :String) -> GdUnitArrayAssert: @@ -41,6 +41,11 @@ func override_failure_message(message :String) -> GdUnitArrayAssert: return self +func append_failure_message(message :String) -> GdUnitArrayAssert: + _base.append_failure_message(message) + return self + + func _validate_value_type(value :Variant) -> bool: return value == null or GdArrayTools.is_array_type(value) diff --git a/addons/gdUnit4/src/asserts/GdUnitAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitAssertImpl.gd index 2755285..583461d 100644 --- a/addons/gdUnit4/src/asserts/GdUnitAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitAssertImpl.gd @@ -2,8 +2,9 @@ extends GdUnitAssert var _current :Variant -var _current_error_message :String = "" +var _current_failure_message :String = "" var _custom_failure_message :String = "" +var _additional_failure_message: String = "" func _init(current :Variant) -> void: @@ -13,8 +14,11 @@ func _init(current :Variant) -> void: GdAssertReports.reset_last_error_line_number() + + + func failure_message() -> String: - return _current_error_message + return _current_failure_message func current_value() -> Variant: @@ -26,11 +30,11 @@ func report_success() -> GdUnitAssert: return self -func report_error(error_message :String, failure_line_number: int = -1) -> GdUnitAssert: +func report_error(failure :String, failure_line_number: int = -1) -> GdUnitAssert: var line_number := failure_line_number if failure_line_number != -1 else GdUnitAssertions.get_line_number() GdAssertReports.set_last_error_line_number(line_number) - _current_error_message = error_message if _custom_failure_message.is_empty() else _custom_failure_message - GdAssertReports.report_error(_current_error_message, line_number) + _current_failure_message = GdAssertMessages.build_failure_message(failure, _additional_failure_message, _custom_failure_message) + GdAssertReports.report_error(_current_failure_message, line_number) Engine.set_meta("GD_TEST_FAILURE", true) return self @@ -44,6 +48,11 @@ func override_failure_message(message :String) -> GdUnitAssert: return self +func append_failure_message(message :String) -> GdUnitAssert: + _additional_failure_message = message + return self + + func is_equal(expected :Variant) -> GdUnitAssert: var current :Variant = current_value() if not GdObjects.equals(current, expected): diff --git a/addons/gdUnit4/src/asserts/GdUnitBoolAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitBoolAssertImpl.gd index d25c6eb..b781e28 100644 --- a/addons/gdUnit4/src/asserts/GdUnitBoolAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitBoolAssertImpl.gd @@ -34,7 +34,7 @@ func report_error(error :String) -> GdUnitBoolAssert: func failure_message() -> String: - return _base._current_error_message + return _base.failure_message() func override_failure_message(message :String) -> GdUnitBoolAssert: @@ -42,6 +42,11 @@ func override_failure_message(message :String) -> GdUnitBoolAssert: return self +func append_failure_message(message :String) -> GdUnitBoolAssert: + _base.append_failure_message(message) + return self + + # Verifies that the current value is null. func is_null() -> GdUnitBoolAssert: _base.is_null() diff --git a/addons/gdUnit4/src/asserts/GdUnitDictionaryAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitDictionaryAssertImpl.gd index 87f77d1..a4dae18 100644 --- a/addons/gdUnit4/src/asserts/GdUnitDictionaryAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitDictionaryAssertImpl.gd @@ -30,7 +30,7 @@ func report_error(error :String) -> GdUnitDictionaryAssert: func failure_message() -> String: - return _base._current_error_message + return _base.failure_message() func override_failure_message(message :String) -> GdUnitDictionaryAssert: @@ -38,6 +38,11 @@ func override_failure_message(message :String) -> GdUnitDictionaryAssert: return self +func append_failure_message(message :String) -> GdUnitDictionaryAssert: + _base.append_failure_message(message) + return self + + func current_value() -> Variant: return _base.current_value() diff --git a/addons/gdUnit4/src/asserts/GdUnitFailureAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitFailureAssertImpl.gd index 88a3062..b25a675 100644 --- a/addons/gdUnit4/src/asserts/GdUnitFailureAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitFailureAssertImpl.gd @@ -89,6 +89,16 @@ func has_message(expected :String) -> GdUnitFailureAssert: return self +func contains_message(expected :String) -> GdUnitFailureAssert: + var expected_error := GdUnitTools.normalize_text(expected) + var current_error := GdUnitTools.normalize_text(GdUnitTools.richtext_normalize(_failure_message)) + if not current_error.contains(expected_error): + var diffs := GdDiffTool.string_diff(current_error, expected_error) + var current := GdAssertMessages.colored_array_div(diffs[1]) + _report_error(GdAssertMessages.error_not_same_error(current, expected_error)) + return self + + func starts_with_message(expected :String) -> GdUnitFailureAssert: var expected_error := GdUnitTools.normalize_text(expected) var current_error := GdUnitTools.normalize_text(GdUnitTools.richtext_normalize(_failure_message)) diff --git a/addons/gdUnit4/src/asserts/GdUnitFileAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitFileAssertImpl.gd index f511879..63683fc 100644 --- a/addons/gdUnit4/src/asserts/GdUnitFileAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitFileAssertImpl.gd @@ -36,7 +36,7 @@ func report_error(error :String) -> GdUnitFileAssert: func failure_message() -> String: - return _base._current_error_message + return _base.failure_message() func override_failure_message(message :String) -> GdUnitFileAssert: @@ -44,6 +44,11 @@ func override_failure_message(message :String) -> GdUnitFileAssert: return self +func append_failure_message(message :String) -> GdUnitFileAssert: + _base.append_failure_message(message) + return self + + func is_equal(expected :Variant) -> GdUnitFileAssert: _base.is_equal(expected) return self diff --git a/addons/gdUnit4/src/asserts/GdUnitFloatAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitFloatAssertImpl.gd index 5920d9d..27463fd 100644 --- a/addons/gdUnit4/src/asserts/GdUnitFloatAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitFloatAssertImpl.gd @@ -34,7 +34,7 @@ func report_error(error :String) -> GdUnitFloatAssert: func failure_message() -> String: - return _base._current_error_message + return _base.failure_message() func override_failure_message(message :String) -> GdUnitFloatAssert: @@ -42,6 +42,11 @@ func override_failure_message(message :String) -> GdUnitFloatAssert: return self +func append_failure_message(message :String) -> GdUnitFloatAssert: + _base.append_failure_message(message) + return self + + func is_null() -> GdUnitFloatAssert: _base.is_null() return self diff --git a/addons/gdUnit4/src/asserts/GdUnitFuncAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitFuncAssertImpl.gd index ccd2a11..c3992c7 100644 --- a/addons/gdUnit4/src/asserts/GdUnitFuncAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitFuncAssertImpl.gd @@ -6,8 +6,9 @@ const DEFAULT_TIMEOUT := 2000 var _current_value_provider :ValueProvider -var _current_error_message :String = "" +var _current_failure_message :String = "" var _custom_failure_message :String = "" +var _additional_failure_message: String = "" var _line_number := -1 var _timeout := DEFAULT_TIMEOUT var _interrupted := false @@ -43,14 +44,14 @@ func report_success() -> GdUnitFuncAssert: return self -func report_error(error_message :String) -> GdUnitFuncAssert: - _current_error_message = error_message if _custom_failure_message == "" else _custom_failure_message - GdAssertReports.report_error(_current_error_message, _line_number) +func report_error(failure :String) -> GdUnitFuncAssert: + _current_failure_message = GdAssertMessages.build_failure_message(failure, _additional_failure_message, _custom_failure_message) + GdAssertReports.report_error(_current_failure_message, _line_number) return self func failure_message() -> String: - return _current_error_message + return _current_failure_message func send_report(report :GdUnitReport)-> void: @@ -62,6 +63,11 @@ func override_failure_message(message :String) -> GdUnitFuncAssert: return self +func append_failure_message(message :String) -> GdUnitFuncAssert: + _additional_failure_message = message + return self + + func wait_until(timeout := 2000) -> GdUnitFuncAssert: if timeout <= 0: push_warning("Invalid timeout param, alloed timeouts must be grater than 0. Use default timeout instead") diff --git a/addons/gdUnit4/src/asserts/GdUnitIntAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitIntAssertImpl.gd index 98fd445..bfcc031 100644 --- a/addons/gdUnit4/src/asserts/GdUnitIntAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitIntAssertImpl.gd @@ -34,7 +34,7 @@ func report_error(error :String) -> GdUnitIntAssert: func failure_message() -> String: - return _base._current_error_message + return _base.failure_message() func override_failure_message(message :String) -> GdUnitIntAssert: @@ -42,6 +42,11 @@ func override_failure_message(message :String) -> GdUnitIntAssert: return self +func append_failure_message(message :String) -> GdUnitIntAssert: + _base.append_failure_message(message) + return self + + func is_null() -> GdUnitIntAssert: _base.is_null() return self diff --git a/addons/gdUnit4/src/asserts/GdUnitObjectAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitObjectAssertImpl.gd index b4090af..4ea12d9 100644 --- a/addons/gdUnit4/src/asserts/GdUnitObjectAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitObjectAssertImpl.gd @@ -38,7 +38,7 @@ func report_error(error :String) -> GdUnitObjectAssert: func failure_message() -> String: - return _base._current_error_message + return _base.failure_message() func override_failure_message(message :String) -> GdUnitObjectAssert: @@ -46,6 +46,11 @@ func override_failure_message(message :String) -> GdUnitObjectAssert: return self +func append_failure_message(message :String) -> GdUnitObjectAssert: + _base.append_failure_message(message) + return self + + func is_equal(expected :Variant) -> GdUnitObjectAssert: _base.is_equal(expected) return self diff --git a/addons/gdUnit4/src/asserts/GdUnitResultAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitResultAssertImpl.gd index e246039..6e734e0 100644 --- a/addons/gdUnit4/src/asserts/GdUnitResultAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitResultAssertImpl.gd @@ -38,7 +38,7 @@ func report_error(error :String) -> GdUnitResultAssert: func failure_message() -> String: - return _base._current_error_message + return _base.failure_message() func override_failure_message(message :String) -> GdUnitResultAssert: @@ -46,6 +46,11 @@ func override_failure_message(message :String) -> GdUnitResultAssert: return self +func append_failure_message(message :String) -> GdUnitResultAssert: + _base.append_failure_message(message) + return self + + func is_null() -> GdUnitResultAssert: _base.is_null() return self diff --git a/addons/gdUnit4/src/asserts/GdUnitSignalAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitSignalAssertImpl.gd index 9c0ea62..0a1302d 100644 --- a/addons/gdUnit4/src/asserts/GdUnitSignalAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitSignalAssertImpl.gd @@ -4,8 +4,9 @@ const DEFAULT_TIMEOUT := 2000 var _signal_collector :GdUnitSignalCollector var _emitter :Object -var _current_error_message :String = "" +var _current_failure_message :String = "" var _custom_failure_message :String = "" +var _additional_failure_message: String = "" var _line_number := -1 var _timeout := DEFAULT_TIMEOUT var _interrupted := false @@ -31,14 +32,14 @@ func report_warning(message :String) -> GdUnitAssert: return self -func report_error(error_message :String) -> GdUnitAssert: - _current_error_message = error_message if _custom_failure_message == "" else _custom_failure_message - GdAssertReports.report_error(_current_error_message, _line_number) +func report_error(failure :String) -> GdUnitAssert: + _current_failure_message = GdAssertMessages.build_failure_message(failure, _additional_failure_message, _custom_failure_message) + GdAssertReports.report_error(_current_failure_message, _line_number) return self func failure_message() -> String: - return _current_error_message + return _current_failure_message func send_report(report :GdUnitReport)-> void: @@ -50,6 +51,11 @@ func override_failure_message(message :String) -> GdUnitSignalAssert: return self +func append_failure_message(message :String) -> GdUnitSignalAssert: + _additional_failure_message = message + return self + + func wait_until(timeout := 2000) -> GdUnitSignalAssert: if timeout <= 0: report_warning("Invalid timeout parameter, allowed timeouts must be greater than 0, use default timeout instead!") diff --git a/addons/gdUnit4/src/asserts/GdUnitStringAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitStringAssertImpl.gd index 6168aaa..cf2c44b 100644 --- a/addons/gdUnit4/src/asserts/GdUnitStringAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitStringAssertImpl.gd @@ -20,7 +20,7 @@ func _notification(event :int) -> void: func failure_message() -> String: - return _base._current_error_message + return _base.failure_message() func current_value() -> Variant: @@ -42,6 +42,11 @@ func override_failure_message(message :String) -> GdUnitStringAssert: return self +func append_failure_message(message :String) -> GdUnitStringAssert: + _base.append_failure_message(message) + return self + + func is_null() -> GdUnitStringAssert: _base.is_null() return self diff --git a/addons/gdUnit4/src/asserts/GdUnitVectorAssertImpl.gd b/addons/gdUnit4/src/asserts/GdUnitVectorAssertImpl.gd index 048cc3f..0b35ed7 100644 --- a/addons/gdUnit4/src/asserts/GdUnitVectorAssertImpl.gd +++ b/addons/gdUnit4/src/asserts/GdUnitVectorAssertImpl.gd @@ -58,7 +58,7 @@ func report_error(error :String) -> GdUnitVectorAssert: func failure_message() -> String: - return _base._current_error_message + return _base.failure_message() func override_failure_message(message :String) -> GdUnitVectorAssert: @@ -66,6 +66,11 @@ func override_failure_message(message :String) -> GdUnitVectorAssert: return self +func append_failure_message(message :String) -> GdUnitVectorAssert: + _base.append_failure_message(message) + return self + + func is_null() -> GdUnitVectorAssert: _base.is_null() return self diff --git a/addons/gdUnit4/src/core/GdFunctionDoubler.gd b/addons/gdUnit4/src/core/GdFunctionDoubler.gd index aafe866..ade8653 100644 --- a/addons/gdUnit4/src/core/GdFunctionDoubler.gd +++ b/addons/gdUnit4/src/core/GdFunctionDoubler.gd @@ -39,6 +39,8 @@ const DEFAULT_TYPED_RETURN_VALUES := { TYPE_PACKED_STRING_ARRAY: "PackedStringArray()", TYPE_PACKED_VECTOR2_ARRAY: "PackedVector2Array()", TYPE_PACKED_VECTOR3_ARRAY: "PackedVector3Array()", + # since Godot 4.3.beta1 TYPE_PACKED_VECTOR4_ARRAY = 38 + GdObjects.TYPE_PACKED_VECTOR4_ARRAY: "PackedVector4Array()", TYPE_PACKED_COLOR_ARRAY: "PackedColorArray()", GdObjects.TYPE_VARIANT: "null", GdObjects.TYPE_ENUM: "0" diff --git a/addons/gdUnit4/src/core/GdObjects.gd b/addons/gdUnit4/src/core/GdObjects.gd index eadb79b..5a2eb5c 100644 --- a/addons/gdUnit4/src/core/GdObjects.gd +++ b/addons/gdUnit4/src/core/GdObjects.gd @@ -4,6 +4,10 @@ extends Resource const GdUnitTools := preload("res://addons/gdUnit4/src/core/GdUnitTools.gd") + +# introduced with Godot 4.3.beta1 +const TYPE_PACKED_VECTOR4_ARRAY = 38 #TYPE_PACKED_VECTOR4_ARRAY + const TYPE_VOID = TYPE_MAX + 1000 const TYPE_VARARG = TYPE_MAX + 1001 const TYPE_VARIANT = TYPE_MAX + 1002 @@ -59,6 +63,7 @@ const TYPE_AS_STRING_MAPPINGS := { TYPE_PACKED_STRING_ARRAY: "PackedStringArray", TYPE_PACKED_VECTOR2_ARRAY: "PackedVector2Array", TYPE_PACKED_VECTOR3_ARRAY: "PackedVector3Array", + TYPE_PACKED_VECTOR4_ARRAY: "PackedVector4Array", TYPE_PACKED_COLOR_ARRAY: "PackedColorArray", TYPE_VOID: "void", TYPE_VARARG: "VarArg", @@ -359,7 +364,7 @@ static func is_type(value :Variant) -> bool: if is_engine_type(value): return true # is a custom class type - if value is GDScript and value.can_instantiate(): + if value is GDScript and (value as GDScript).can_instantiate(): return true return false @@ -434,7 +439,7 @@ static func is_singleton(value :Variant) -> bool: static func is_instance(value :Variant) -> bool: if not is_instance_valid(value) or is_native_class(value): return false - if is_script(value) and value.get_instance_base_type() == "": + if is_script(value) and (value as Script).get_instance_base_type() == "": return true if is_scene(value): return true @@ -532,7 +537,7 @@ static func extract_class_name(clazz :Variant) -> GdUnitResult: var script := clazz.script as GDScript if script != null: return extract_class_name(script) - return GdUnitResult.success(clazz.get_class()) + return GdUnitResult.success((clazz as Object).get_class()) # extract name form full qualified class path if clazz is String: diff --git a/addons/gdUnit4/src/core/GdUnitRunner.gd b/addons/gdUnit4/src/core/GdUnitRunner.gd index 1c12f3f..68aadee 100644 --- a/addons/gdUnit4/src/core/GdUnitRunner.gd +++ b/addons/gdUnit4/src/core/GdUnitRunner.gd @@ -1,8 +1,5 @@ extends Node -signal sync_rpc_id_result_received - - @onready var _client :GdUnitTcpClient = $GdUnitTcpClient @onready var _executor :GdUnitTestSuiteExecutor = GdUnitTestSuiteExecutor.new() diff --git a/addons/gdUnit4/src/core/GdUnitSignals.gd b/addons/gdUnit4/src/core/GdUnitSignals.gd index d65b42c..652b7af 100644 --- a/addons/gdUnit4/src/core/GdUnitSignals.gd +++ b/addons/gdUnit4/src/core/GdUnitSignals.gd @@ -1,17 +1,26 @@ class_name GdUnitSignals extends RefCounted +@warning_ignore("unused_signal") signal gdunit_client_connected(client_id :int) +@warning_ignore("unused_signal") signal gdunit_client_disconnected(client_id :int) +@warning_ignore("unused_signal") signal gdunit_client_terminated() +@warning_ignore("unused_signal") signal gdunit_event(event :GdUnitEvent) +@warning_ignore("unused_signal") signal gdunit_event_debug(event :GdUnitEvent) +@warning_ignore("unused_signal") signal gdunit_add_test_suite(test_suite :GdUnitTestSuiteDto) +@warning_ignore("unused_signal") signal gdunit_message(message :String) +@warning_ignore("unused_signal") signal gdunit_report(execution_context_id :int, report :GdUnitReport) +@warning_ignore("unused_signal") signal gdunit_set_test_failed(is_failed :bool) - +@warning_ignore("unused_signal") signal gdunit_settings_changed(property :GdUnitProperty) const META_KEY := "GdUnitSignals" diff --git a/addons/gdUnit4/src/core/GdUnitSingleton.gd b/addons/gdUnit4/src/core/GdUnitSingleton.gd index fc63b48..ed6103e 100644 --- a/addons/gdUnit4/src/core/GdUnitSingleton.gd +++ b/addons/gdUnit4/src/core/GdUnitSingleton.gd @@ -28,7 +28,7 @@ static func instance(name :String, clazz :Callable) -> Variant: return singleton -static func unregister(p_singleton :String) -> void: +static func unregister(p_singleton :String, use_call_deferred :bool = false) -> void: var singletons :PackedStringArray = Engine.get_meta(MEATA_KEY, PackedStringArray()) if singletons.has(p_singleton): GdUnitTools.prints_verbose("\n Unregister singleton '%s'" % p_singleton); @@ -36,18 +36,18 @@ static func unregister(p_singleton :String) -> void: singletons.remove_at(index) var instance_ :Object = Engine.get_meta(p_singleton) GdUnitTools.prints_verbose(" Free singleton instance '%s:%s'" % [p_singleton, instance_]) - GdUnitTools.free_instance(instance_) + GdUnitTools.free_instance(instance_, use_call_deferred) Engine.remove_meta(p_singleton) GdUnitTools.prints_verbose(" Successfully freed '%s'" % p_singleton) Engine.set_meta(MEATA_KEY, singletons) -static func dispose() -> void: +static func dispose(use_call_deferred :bool = false) -> void: # use a copy because unregister is modify the singletons array var singletons := PackedStringArray(Engine.get_meta(MEATA_KEY, PackedStringArray())) GdUnitTools.prints_verbose("----------------------------------------------------------------") GdUnitTools.prints_verbose("Cleanup singletons %s" % singletons) for singleton in singletons: - unregister(singleton) + unregister(singleton, use_call_deferred) Engine.remove_meta(MEATA_KEY) GdUnitTools.prints_verbose("----------------------------------------------------------------") diff --git a/addons/gdUnit4/src/core/GdUnitTools.gd b/addons/gdUnit4/src/core/GdUnitTools.gd index f6d9705..b378271 100644 --- a/addons/gdUnit4/src/core/GdUnitTools.gd +++ b/addons/gdUnit4/src/core/GdUnitTools.gd @@ -27,7 +27,7 @@ static func prints_verbose(message :String) -> void: prints(message) -static func free_instance(instance :Variant, is_stdout_verbose :=false) -> bool: +static func free_instance(instance :Variant, use_call_deferred :bool = false, is_stdout_verbose := false) -> bool: if instance is Array: for element :Variant in instance: free_instance(element) @@ -43,7 +43,7 @@ static func free_instance(instance :Variant, is_stdout_verbose :=false) -> bool: print_verbose("GdUnit4:gc():free instance ", instance) release_double(instance) if instance is RefCounted: - instance.notification(Object.NOTIFICATION_PREDELETE) + (instance as RefCounted).notification(Object.NOTIFICATION_PREDELETE) return true else: # is instance already freed? @@ -52,15 +52,26 @@ static func free_instance(instance :Variant, is_stdout_verbose :=false) -> bool: #release_connections(instance) if instance is Timer: instance.stop() - instance.call_deferred("free") - await Engine.get_main_loop().process_frame + if use_call_deferred: + instance.call_deferred("free") + else: + instance.free() + await Engine.get_main_loop().process_frame return true if instance is Node and instance.get_parent() != null: if is_stdout_verbose: print_verbose("GdUnit4:gc():remove node from parent ", instance.get_parent(), instance) - instance.get_parent().remove_child(instance) - instance.set_owner(null) - instance.free() + if use_call_deferred: + instance.get_parent().remove_child.call_deferred(instance) + #instance.call_deferred("set_owner", null) + else: + instance.get_parent().remove_child(instance) + if is_stdout_verbose: + print_verbose("GdUnit4:gc():freeing `free()` the instance ", instance) + if use_call_deferred: + instance.call_deferred("free") + else: + instance.free() return !is_instance_valid(instance) @@ -92,9 +103,9 @@ static func release_timers() -> void: # the finally cleaup unfreed resources and singletons -static func dispose_all() -> void: +static func dispose_all(use_call_deferred :bool = false) -> void: release_timers() - GdUnitSingleton.dispose() + GdUnitSingleton.dispose(use_call_deferred) GdUnitSignals.dispose() diff --git a/addons/gdUnit4/src/core/GodotVersionFixures.gd b/addons/gdUnit4/src/core/GodotVersionFixures.gd index febe73d..9d5b6bb 100644 --- a/addons/gdUnit4/src/core/GodotVersionFixures.gd +++ b/addons/gdUnit4/src/core/GodotVersionFixures.gd @@ -19,13 +19,3 @@ static func set_event_global_position(event: InputEventMouseMotion, global_posit event.global_position = event.position else: event.global_position = global_position - - -# we crash on macOS when using free() inside the plugin _exit_tree -static func free_fix(instance: Object) -> void: - var distribution_name := OS.get_distribution_name() - if distribution_name != "Windows": - prints("Using queue_free() hotfix on system:", distribution_name) - instance.queue_free() - else: - instance.free() diff --git a/addons/gdUnit4/src/core/LocalTime.gd b/addons/gdUnit4/src/core/LocalTime.gd index 68900b5..64b9ba0 100644 --- a/addons/gdUnit4/src/core/LocalTime.gd +++ b/addons/gdUnit4/src/core/LocalTime.gd @@ -3,6 +3,7 @@ class_name LocalTime extends Resource enum TimeUnit { + DEFAULT = 0, MILLIS = 1, SECOND = 2, MINUTE = 3, diff --git a/addons/gdUnit4/src/core/command/GdUnitCommandHandler.gd b/addons/gdUnit4/src/core/command/GdUnitCommandHandler.gd index b59bf6c..339fb8c 100644 --- a/addons/gdUnit4/src/core/command/GdUnitCommandHandler.gd +++ b/addons/gdUnit4/src/core/command/GdUnitCommandHandler.gd @@ -228,9 +228,10 @@ func cmd_stop(client_id :int) -> void: if _running_debug_mode: EditorInterface.stop_playing_scene() else: if _current_runner_process_id > 0: - var result := OS.kill(_current_runner_process_id) - if result != OK: - push_error("ERROR checked stopping GdUnit Test Runner. error code: %s" % result) + if OS.is_process_running(_current_runner_process_id): + var result := OS.kill(_current_runner_process_id) + if result != OK: + push_error("ERROR checked stopping GdUnit Test Runner. error code: %s" % result) _current_runner_process_id = -1 diff --git a/addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverer.gd b/addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverer.gd index 1e92a4d..7e8dc81 100644 --- a/addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverer.gd +++ b/addons/gdUnit4/src/core/discovery/GdUnitTestDiscoverer.gd @@ -7,19 +7,31 @@ static func run() -> void: GdUnitSignals.instance().gdunit_event.emit(GdUnitEventTestDiscoverStart.new()) await Engine.get_main_loop().create_timer(.5).timeout - var test_suite_directories :PackedStringArray = GdUnitCommandHandler.scan_test_directorys("res://" , GdUnitSettings.test_root_folder(), []) - var scanner := GdUnitTestSuiteScanner.new() - var _test_suites_to_process :Array[Node] = [] - for test_suite_dir in test_suite_directories: - _test_suites_to_process.append_array(scanner.scan(test_suite_dir)) + # We run the test discovery in an extra thread so that the main thread is not blocked + var t:= Thread.new() + t.start(func () -> void: + var test_suite_directories :PackedStringArray = GdUnitCommandHandler.scan_test_directorys("res://" , GdUnitSettings.test_root_folder(), []) + var scanner := GdUnitTestSuiteScanner.new() + var _test_suites_to_process :Array[Node] = [] - var test_case_count :int = _test_suites_to_process.reduce(func (accum :int, test_suite :Node) -> int: - return accum + test_suite.get_child_count(), 0) + for test_suite_dir in test_suite_directories: + _test_suites_to_process.append_array(scanner.scan(test_suite_dir)) - for test_suite in _test_suites_to_process: - var ts_dto := GdUnitTestSuiteDto.of(test_suite) - GdUnitSignals.instance().gdunit_add_test_suite.emit(ts_dto) + # Do sync the main thread before emit the discovered test suites to the inspector + await Engine.get_main_loop().process_frame + var test_case_count :int = 0 + for test_suite in _test_suites_to_process: + test_case_count += test_suite.get_child_count() + var ts_dto := GdUnitTestSuiteDto.of(test_suite) + GdUnitSignals.instance().gdunit_add_test_suite.emit(ts_dto) + test_suite.free() - prints("%d test suites discovered." % _test_suites_to_process.size()) - GdUnitSignals.instance().gdunit_event.emit(GdUnitEventTestDiscoverEnd.new(_test_suites_to_process.size(), test_case_count)) - await Engine.get_main_loop().process_frame + prints("%d test suites discovered." % _test_suites_to_process.size()) + GdUnitSignals.instance().gdunit_event.emit(GdUnitEventTestDiscoverEnd.new(_test_suites_to_process.size(), test_case_count)) + _test_suites_to_process.clear() + ) + # wait unblocked to the tread is finished + while t.is_alive(): + await Engine.get_main_loop().process_frame + # needs finally to wait for finish + await t.wait_to_finish() diff --git a/addons/gdUnit4/src/core/parse/GdDefaultValueDecoder.gd b/addons/gdUnit4/src/core/parse/GdDefaultValueDecoder.gd index b504530..b1cc38a 100644 --- a/addons/gdUnit4/src/core/parse/GdDefaultValueDecoder.gd +++ b/addons/gdUnit4/src/core/parse/GdDefaultValueDecoder.gd @@ -21,6 +21,7 @@ var _decoders := { TYPE_PACKED_COLOR_ARRAY: _on_type_Array.bind(TYPE_PACKED_COLOR_ARRAY), TYPE_PACKED_VECTOR2_ARRAY: _on_type_Array.bind(TYPE_PACKED_VECTOR2_ARRAY), TYPE_PACKED_VECTOR3_ARRAY: _on_type_Array.bind(TYPE_PACKED_VECTOR3_ARRAY), + GdObjects.TYPE_PACKED_VECTOR4_ARRAY: _on_type_Array.bind(GdObjects.TYPE_PACKED_VECTOR4_ARRAY), TYPE_DICTIONARY: _on_type_Dictionary, TYPE_RID: _on_type_RID, TYPE_NODE_PATH: _on_type_NodePath, @@ -63,7 +64,7 @@ func _on_type_StringName(value :StringName) -> String: return 'StringName("%s")' % value -func _on_type_Object(value :Object, type :int) -> String: +func _on_type_Object(value :Object, _type :int) -> String: return str(value) @@ -79,11 +80,11 @@ func _on_type_NodePath(path :NodePath) -> String: return 'NodePath("%s")' % path -func _on_type_Callable(cb :Callable) -> String: +func _on_type_Callable(_cb :Callable) -> String: return 'Callable()' -func _on_type_Signal(s :Signal) -> String: +func _on_type_Signal(_s :Signal) -> String: return 'Signal()' @@ -122,6 +123,14 @@ func _on_type_Array(value :Variant, type :int) -> String: return "PackedVector3Array()" return "PackedVector3Array([%s])" % ", ".join(vectors) + GdObjects.TYPE_PACKED_VECTOR4_ARRAY: + var vectors := PackedStringArray() + for vector:Variant in value as Array: + vectors.append(_on_type_Vector(vector, TYPE_VECTOR4)) + if vectors.is_empty(): + return "PackedVector4Array()" + return "PackedVector4Array([%s])" % ", ".join(vectors) + TYPE_PACKED_STRING_ARRAY: var values := PackedStringArray() for v in value as PackedStringArray: diff --git a/addons/gdUnit4/src/network/GdUnitServer.gd b/addons/gdUnit4/src/network/GdUnitServer.gd index 9e6cf6b..7b7be09 100644 --- a/addons/gdUnit4/src/network/GdUnitServer.gd +++ b/addons/gdUnit4/src/network/GdUnitServer.gd @@ -17,20 +17,20 @@ func _ready() -> void: GdUnitCommandHandler.instance().gdunit_runner_stop.connect(_on_gdunit_runner_stop) -func _on_client_connected(client_id :int) -> void: +func _on_client_connected(client_id: int) -> void: GdUnitSignals.instance().gdunit_client_connected.emit(client_id) -func _on_client_disconnected(client_id :int) -> void: +func _on_client_disconnected(client_id: int) -> void: GdUnitSignals.instance().gdunit_client_disconnected.emit(client_id) -func _on_gdunit_runner_stop(client_id :int) -> void: +func _on_gdunit_runner_stop(client_id: int) -> void: if _server: _server.disconnect_client(client_id) -func _receive_rpc_data(p_rpc :RPC) -> void: +func _receive_rpc_data(p_rpc: Variant) -> void: if p_rpc is RPCMessage: GdUnitSignals.instance().gdunit_message.emit(p_rpc.message()) return diff --git a/addons/gdUnit4/src/network/GdUnitServer.tscn b/addons/gdUnit4/src/network/GdUnitServer.tscn index 4c7645c..4dbe8c4 100644 --- a/addons/gdUnit4/src/network/GdUnitServer.tscn +++ b/addons/gdUnit4/src/network/GdUnitServer.tscn @@ -1,10 +1,10 @@ -[gd_scene load_steps=3 format=2] +[gd_scene load_steps=3 format=3 uid="uid://cn5mp3tmi2gb1"] -[ext_resource path="res://addons/gdUnit4/src/network/GdUnitServer.gd" type="Script" id=1] -[ext_resource path="res://addons/gdUnit4/src/network/GdUnitTcpServer.gd" type="Script" id=2] +[ext_resource type="Script" path="res://addons/gdUnit4/src/network/GdUnitServer.gd" id="1"] +[ext_resource type="Script" path="res://addons/gdUnit4/src/network/GdUnitTcpServer.gd" id="2"] [node name="Control" type="Node"] -script = ExtResource( 1 ) +script = ExtResource("1") [node name="TcpServer" type="Node" parent="."] -script = ExtResource( 2 ) +script = ExtResource("2") diff --git a/addons/gdUnit4/src/network/GdUnitTcpClient.gd b/addons/gdUnit4/src/network/GdUnitTcpClient.gd index 9239d9d..5cf8b05 100644 --- a/addons/gdUnit4/src/network/GdUnitTcpClient.gd +++ b/addons/gdUnit4/src/network/GdUnitTcpClient.gd @@ -119,8 +119,8 @@ func rpc_receive() -> RPC: return null -func console(message :String) -> void: - prints("TCP Client:", message) +func console(_message :String) -> void: + #prints("TCP Client:", _message) pass diff --git a/addons/gdUnit4/src/network/GdUnitTcpServer.gd b/addons/gdUnit4/src/network/GdUnitTcpServer.gd index 5ab3f83..e27fe18 100644 --- a/addons/gdUnit4/src/network/GdUnitTcpServer.gd +++ b/addons/gdUnit4/src/network/GdUnitTcpServer.gd @@ -30,10 +30,11 @@ class TcpConnection extends Node: func close() -> void: - rpc_send(RPCClientDisconnect.new().with_id(_id)) - server().client_disconnected.emit(_id) - _stream.disconnect_from_host() - _readBuffer = "" + if _stream != null: + _stream.disconnect_from_host() + _readBuffer = "" + _stream = null + queue_free() func id() -> int: @@ -44,12 +45,12 @@ class TcpConnection extends Node: return get_parent() - func rpc_send(p_rpc :RPC) -> void: + func rpc_send(p_rpc: RPC) -> void: _stream.put_var(p_rpc.serialize(), true) - func _process(_delta :float) -> void: - if _stream.get_status() != StreamPeerTCP.STATUS_CONNECTED: + func _process(_delta: float) -> void: + if _stream == null or _stream.get_status() != StreamPeerTCP.STATUS_CONNECTED: return receive_packages() @@ -71,7 +72,7 @@ class TcpConnection extends Node: server().rpc_data.emit(rpc_) - func _read_next_data_packages(data_package :PackedByteArray) -> PackedStringArray: + func _read_next_data_packages(data_package: PackedByteArray) -> PackedStringArray: _readBuffer += data_package.get_string_from_utf8() var json_array := _readBuffer.split(GdUnitServerConstants.JSON_RESPONSE_DELIMITER) # We need to check if the current data is terminated by the delemiter (data packets can be split unspecifically). @@ -100,7 +101,7 @@ func _ready() -> void: client_disconnected.connect(_on_client_disconnected) -func _notification(what :int) -> void: +func _notification(what: int) -> void: if what == NOTIFICATION_PREDELETE: stop() @@ -131,34 +132,32 @@ func stop() -> void: if connection is TcpConnection: connection.close() remove_child(connection) + _server = null -func disconnect_client(client_id :int) -> void: - for connection in get_children(): - if connection is TcpConnection and connection.id() == client_id: - connection.close() +func disconnect_client(client_id: int) -> void: + client_disconnected.emit(client_id) -func _process(_delta :float) -> void: - if not _server.is_listening(): +func _process(_delta: float) -> void: + if _server != null and not _server.is_listening(): return # check if connection is ready to be used if _server.is_connection_available(): add_child(TcpConnection.new(_server)) -func _on_client_connected(client_id :int) -> void: +func _on_client_connected(client_id: int) -> void: console("Client connected %d" % client_id) -func _on_client_disconnected(client_id :int) -> void: - console("Client disconnected %d" % client_id) +func _on_client_disconnected(client_id: int) -> void: for connection in get_children(): if connection is TcpConnection and connection.id() == client_id: + connection.close() remove_child(connection) - -func console(_message :String) -> void: +func console(_message: String) -> void: #print_debug("TCP Server:", _message) pass diff --git a/addons/gdUnit4/src/ui/GdUnitInspector.gd b/addons/gdUnit4/src/ui/GdUnitInspector.gd index daadc86..b82fb35 100644 --- a/addons/gdUnit4/src/ui/GdUnitInspector.gd +++ b/addons/gdUnit4/src/ui/GdUnitInspector.gd @@ -2,6 +2,8 @@ class_name GdUnitInspecor extends Panel +const ScriptEditorContextMenuHandler = preload("res://addons/gdUnit4/src/ui/menu/ScriptEditorContextMenuHandler.gd") +const EditorFileSystemContextMenuHandler = preload("res://addons/gdUnit4/src/ui/menu/EditorFileSystemContextMenuHandler.gd") var _command_handler := GdUnitCommandHandler.instance() @@ -20,12 +22,6 @@ func _ready() -> void: add_file_system_dock_context_menu() -func _notification(what: int) -> void: - if what == NOTIFICATION_PREDELETE: - ScriptEditorControls.unregister_context_menu() - EditorFileSystemControls.unregister_context_menu() - - func _process(_delta: float) -> void: _command_handler._do_process() @@ -52,13 +48,13 @@ func _getEditorThemes() -> void: func add_file_system_dock_context_menu() -> void: var is_test_suite := func is_visible(script: Script, is_ts: bool) -> bool: if script == null: - return true + return false return GdObjects.is_test_suite(script) == is_ts var menu :Array[GdUnitContextMenuItem] = [ GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.TEST_RUN, "Run Testsuites", "Play", is_test_suite.bind(true), _command_handler.command(GdUnitCommandHandler.CMD_RUN_TESTSUITE)), GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.TEST_DEBUG, "Debug Testsuites", "PlayStart", is_test_suite.bind(true), _command_handler.command(GdUnitCommandHandler.CMD_RUN_TESTSUITE_DEBUG)), ] - EditorFileSystemControls.register_context_menu(menu) + add_child(EditorFileSystemContextMenuHandler.new(menu)) func add_script_editor_context_menu() -> void: @@ -69,7 +65,7 @@ func add_script_editor_context_menu() -> void: GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.TEST_DEBUG, "Debug Tests", "PlayStart", is_test_suite.bind(true),_command_handler.command(GdUnitCommandHandler.CMD_RUN_TESTCASE_DEBUG)), GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.CREATE_TEST, "Create Test", "New", is_test_suite.bind(false), _command_handler.command(GdUnitCommandHandler.CMD_CREATE_TESTCASE)) ] - ScriptEditorControls.register_context_menu(menu) + add_child(ScriptEditorContextMenuHandler.new(menu)) func _on_MainPanel_run_testsuite(test_suite_paths: Array, debug: bool) -> void: diff --git a/addons/gdUnit4/src/ui/GdUnitInspector.tscn b/addons/gdUnit4/src/ui/GdUnitInspector.tscn index 88f51f6..0055b98 100644 --- a/addons/gdUnit4/src/ui/GdUnitInspector.tscn +++ b/addons/gdUnit4/src/ui/GdUnitInspector.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=7 format=3 uid="uid://mpo5o6d4uybu"] +[gd_scene load_steps=8 format=3 uid="uid://mpo5o6d4uybu"] [ext_resource type="PackedScene" uid="uid://dx7xy4dgi3wwb" path="res://addons/gdUnit4/src/ui/parts/InspectorToolBar.tscn" id="1"] [ext_resource type="PackedScene" uid="uid://dva3tonxsxrlk" path="res://addons/gdUnit4/src/ui/parts/InspectorProgressBar.tscn" id="2"] @@ -6,6 +6,7 @@ [ext_resource type="PackedScene" uid="uid://djp8ait0bxpsc" path="res://addons/gdUnit4/src/ui/parts/InspectorMonitor.tscn" id="4"] [ext_resource type="Script" path="res://addons/gdUnit4/src/ui/GdUnitInspector.gd" id="5"] [ext_resource type="PackedScene" uid="uid://bqfpidewtpeg0" path="res://addons/gdUnit4/src/ui/parts/InspectorTreePanel.tscn" id="7"] +[ext_resource type="PackedScene" path="res://addons/gdUnit4/src/network/GdUnitServer.tscn" id="7_721no"] [node name="GdUnit" type="Panel"] use_parent_material = true @@ -51,6 +52,8 @@ layout_mode = 2 [node name="Monitor" parent="VBoxContainer" instance=ExtResource("4")] layout_mode = 2 +[node name="event_server" parent="." instance=ExtResource("7_721no")] + [connection signal="failure_next" from="VBoxContainer/Header/StatusBar" to="VBoxContainer/MainPanel" method="select_next_failure"] [connection signal="failure_prevous" from="VBoxContainer/Header/StatusBar" to="VBoxContainer/MainPanel" method="select_previous_failure"] [connection signal="request_discover_tests" from="VBoxContainer/Header/StatusBar" to="." method="_on_status_bar_request_discover_tests"] diff --git a/addons/gdUnit4/src/ui/ScriptEditorControls.gd b/addons/gdUnit4/src/ui/ScriptEditorControls.gd index 0ddf068..54a6eab 100644 --- a/addons/gdUnit4/src/ui/ScriptEditorControls.gd +++ b/addons/gdUnit4/src/ui/ScriptEditorControls.gd @@ -86,19 +86,6 @@ static func edit_script(script_path: String, line_number:=-1) -> void: EditorInterface.edit_script(script, line_number) -# Register the given context menu to the current script editor -# Is called when the plugin is activated -# The active script is connected to the ScriptEditorContextMenuHandler -static func register_context_menu(menu: Array[GdUnitContextMenuItem]) -> void: - Engine.get_main_loop().root.call_deferred("add_child", ScriptEditorContextMenuHandler.new(menu)) - - -# Unregisteres all registerend context menus and gives the ScriptEditorContextMenuHandler> free -# Is called when the plugin is deactivated -static func unregister_context_menu() -> void: - ScriptEditorContextMenuHandler.dispose() - - static func _menu_popup() -> PopupMenu: return EditorInterface.get_script_editor().get_child(0).get_child(0).get_child(0).get_popup() diff --git a/addons/gdUnit4/src/ui/menu/EditorFileSystemContextMenuHandler.gd b/addons/gdUnit4/src/ui/menu/EditorFileSystemContextMenuHandler.gd index 4b2b297..1c3b30d 100644 --- a/addons/gdUnit4/src/ui/menu/EditorFileSystemContextMenuHandler.gd +++ b/addons/gdUnit4/src/ui/menu/EditorFileSystemContextMenuHandler.gd @@ -1,4 +1,4 @@ -class_name EditorFileSystemContextMenuHandler +@tool extends Control var _context_menus := Dictionary() @@ -8,25 +8,12 @@ func _init(context_menus: Array[GdUnitContextMenuItem]) -> void: set_name("EditorFileSystemContextMenuHandler") for menu in context_menus: _context_menus[menu.id] = menu - var popup := EditorFileSystemContextMenuHandler._menu_popup() - var file_tree := EditorFileSystemContextMenuHandler._file_tree() + var popup := _menu_popup() + var file_tree := _file_tree() popup.about_to_popup.connect(on_context_menu_show.bind(popup, file_tree)) popup.id_pressed.connect(on_context_menu_pressed.bind(file_tree)) -static func dispose() -> void: - if Engine.get_main_loop().root == null: - return - var handler: EditorFileSystemContextMenuHandler = Engine.get_main_loop().root.find_child("EditorFileSystemContextMenuHandler*", false, false) - if handler: - var popup := _menu_popup() - if popup.about_to_popup.is_connected(Callable(handler, "on_context_menu_show")): - popup.about_to_popup.disconnect(Callable(handler, "on_context_menu_show")) - if popup.id_pressed.is_connected(Callable(handler, "on_context_menu_pressed")): - popup.id_pressed.disconnect(Callable(handler, "on_context_menu_pressed")) - GodotVersionFixures.free_fix(handler) - - func on_context_menu_show(context_menu: PopupMenu, file_tree: Tree) -> void: context_menu.add_separator() var current_index := context_menu.get_item_count() @@ -55,6 +42,7 @@ func collect_testsuites(_menu_item: GdUnitContextMenuItem, file_tree: Tree) -> P var file_system := EditorInterface.get_resource_filesystem() var selected_item := file_tree.get_selected() var selected_test_suites := PackedStringArray() + while selected_item: var resource_path: String = selected_item.get_metadata(0) var file_type := file_system.get_file_type(resource_path) @@ -71,14 +59,9 @@ func collect_testsuites(_menu_item: GdUnitContextMenuItem, file_tree: Tree) -> P return selected_test_suites -# Returns the FileSystemDock instance -static func filesystem_dock() -> FileSystemDock: - return EditorInterface.get_file_system_dock() - - -static func _file_tree() -> Tree: - return GdObjects.find_nodes_by_class(filesystem_dock(), "Tree", true)[-1] +func _file_tree() -> Tree: + return GdObjects.find_nodes_by_class(EditorInterface.get_file_system_dock(), "Tree", true)[-1] -static func _menu_popup() -> PopupMenu: - return GdObjects.find_nodes_by_class(filesystem_dock(), "PopupMenu")[-1] +func _menu_popup() -> PopupMenu: + return GdObjects.find_nodes_by_class(EditorInterface.get_file_system_dock(), "PopupMenu")[-1] diff --git a/addons/gdUnit4/src/ui/menu/GdUnitContextMenuItem.gd b/addons/gdUnit4/src/ui/menu/GdUnitContextMenuItem.gd index a591c11..2f89c61 100644 --- a/addons/gdUnit4/src/ui/menu/GdUnitContextMenuItem.gd +++ b/addons/gdUnit4/src/ui/menu/GdUnitContextMenuItem.gd @@ -1,13 +1,14 @@ class_name GdUnitContextMenuItem enum MENU_ID { + UNDEFINED = 0, TEST_RUN = 1000, TEST_DEBUG = 1001, TEST_RERUN = 1002, CREATE_TEST = 1010, } -var id: MENU_ID: +var id: MENU_ID = MENU_ID.UNDEFINED: set(value): id = value get: diff --git a/addons/gdUnit4/src/ui/menu/ScriptEditorContextMenuHandler.gd b/addons/gdUnit4/src/ui/menu/ScriptEditorContextMenuHandler.gd index 0bad13e..7fec3bc 100644 --- a/addons/gdUnit4/src/ui/menu/ScriptEditorContextMenuHandler.gd +++ b/addons/gdUnit4/src/ui/menu/ScriptEditorContextMenuHandler.gd @@ -1,4 +1,4 @@ -class_name ScriptEditorContextMenuHandler +@tool extends Control var _context_menus := Dictionary() @@ -14,17 +14,6 @@ func _init(context_menus: Array[GdUnitContextMenuItem]) -> void: on_script_changed(active_script()) -static func dispose() -> void: - if Engine.get_main_loop().root == null: - return - var handler: ScriptEditorContextMenuHandler = Engine.get_main_loop().root.find_child("ScriptEditorContextMenuHandler*", false, false) - if handler: - var editor := EditorInterface.get_script_editor() - if editor.editor_script_changed.is_connected(handler.on_script_changed): - editor.editor_script_changed.disconnect(handler.on_script_changed) - GodotVersionFixures.free_fix(handler) - - func _input(event: InputEvent) -> void: if event is InputEventKey and event.is_pressed(): for action: GdUnitContextMenuItem in _context_menus.values(): diff --git a/addons/gdUnit4/src/ui/parts/InspectorTreeMainPanel.gd b/addons/gdUnit4/src/ui/parts/InspectorTreeMainPanel.gd index 3cc35cc..b3949d7 100644 --- a/addons/gdUnit4/src/ui/parts/InspectorTreeMainPanel.gd +++ b/addons/gdUnit4/src/ui/parts/InspectorTreeMainPanel.gd @@ -553,6 +553,9 @@ func update_test_case(event: GdUnitEvent) -> void: func create_tree_item(test_suite: GdUnitTestSuiteDto) -> TreeItem: var root_folder := GdUnitSettings.test_root_folder() + # we need at least the root path to split up the path into elements + if root_folder.is_empty(): + root_folder = "res://" var path_spliced := ProjectSettings.localize_path(test_suite.path()).split(root_folder) var resource_path := path_spliced[0] + "/" + root_folder var parent := _tree_root