From 05d29ccce1898ed89c0b650c77242c2fa2805128 Mon Sep 17 00:00:00 2001 From: Sophia Pearson Date: Fri, 20 May 2022 00:45:25 +0200 Subject: texty: initial commit --- addons/gut/gui/BottomPanelShortcuts.gd | 82 ++++++ addons/gut/gui/BottomPanelShortcuts.tscn | 232 +++++++++++++++ addons/gut/gui/GutBottomPanel.gd | 326 ++++++++++++++++++++ addons/gut/gui/GutBottomPanel.tscn | 386 ++++++++++++++++++++++++ addons/gut/gui/GutRunner.gd | 98 +++++++ addons/gut/gui/GutRunner.tscn | 9 + addons/gut/gui/GutSceneTheme.tres | 11 + addons/gut/gui/RunAtCursor.gd | 130 ++++++++ addons/gut/gui/RunAtCursor.tscn | 80 +++++ addons/gut/gui/Settings.tscn | 7 + addons/gut/gui/ShortcutButton.gd | 164 +++++++++++ addons/gut/gui/ShortcutButton.tscn | 80 +++++ addons/gut/gui/arrow.png | 3 + addons/gut/gui/arrow.png.import | 35 +++ addons/gut/gui/gut_config_gui.gd | 408 ++++++++++++++++++++++++++ addons/gut/gui/play.png | 3 + addons/gut/gui/play.png.import | 35 +++ addons/gut/gui/script_text_editor_controls.gd | 230 +++++++++++++++ 18 files changed, 2319 insertions(+) create mode 100644 addons/gut/gui/BottomPanelShortcuts.gd create mode 100644 addons/gut/gui/BottomPanelShortcuts.tscn create mode 100644 addons/gut/gui/GutBottomPanel.gd create mode 100644 addons/gut/gui/GutBottomPanel.tscn create mode 100644 addons/gut/gui/GutRunner.gd create mode 100644 addons/gut/gui/GutRunner.tscn create mode 100644 addons/gut/gui/GutSceneTheme.tres create mode 100644 addons/gut/gui/RunAtCursor.gd create mode 100644 addons/gut/gui/RunAtCursor.tscn create mode 100644 addons/gut/gui/Settings.tscn create mode 100644 addons/gut/gui/ShortcutButton.gd create mode 100644 addons/gut/gui/ShortcutButton.tscn create mode 100644 addons/gut/gui/arrow.png create mode 100644 addons/gut/gui/arrow.png.import create mode 100644 addons/gut/gui/gut_config_gui.gd create mode 100644 addons/gut/gui/play.png create mode 100644 addons/gut/gui/play.png.import create mode 100644 addons/gut/gui/script_text_editor_controls.gd (limited to 'addons/gut/gui') diff --git a/addons/gut/gui/BottomPanelShortcuts.gd b/addons/gut/gui/BottomPanelShortcuts.gd new file mode 100644 index 0000000..86fbf8d --- /dev/null +++ b/addons/gut/gui/BottomPanelShortcuts.gd @@ -0,0 +1,82 @@ +tool +extends WindowDialog + +onready var _ctrls = { + run_all = $Layout/CRunAll/ShortcutButton, + run_current_script = $Layout/CRunCurrentScript/ShortcutButton, + run_current_inner = $Layout/CRunCurrentInner/ShortcutButton, + run_current_test = $Layout/CRunCurrentTest/ShortcutButton, + panel_button = $Layout/CPanelButton/ShortcutButton, +} + +func _ready(): + for key in _ctrls: + var sc_button = _ctrls[key] + sc_button.connect('start_edit', self, '_on_edit_start', [sc_button]) + sc_button.connect('end_edit', self, '_on_edit_end') + + + # show dialog when running scene from editor. + if(get_parent() == get_tree().root): + popup_centered() + +# ------------ +# Events +# ------------ +func _on_Hide_pressed(): + hide() + +func _on_edit_start(which): + for key in _ctrls: + var sc_button = _ctrls[key] + if(sc_button != which): + sc_button.disable_set(true) + sc_button.disable_clear(true) + +func _on_edit_end(): + for key in _ctrls: + var sc_button = _ctrls[key] + sc_button.disable_set(false) + sc_button.disable_clear(false) + +# ------------ +# Public +# ------------ +func get_run_all(): + return _ctrls.run_all.get_shortcut() + +func get_run_current_script(): + return _ctrls.run_current_script.get_shortcut() + +func get_run_current_inner(): + return _ctrls.run_current_inner.get_shortcut() + +func get_run_current_test(): + return _ctrls.run_current_test.get_shortcut() + +func get_panel_button(): + return _ctrls.panel_button.get_shortcut() + + +func save_shortcuts(path): + var f = ConfigFile.new() + + f.set_value('main', 'run_all', _ctrls.run_all.get_shortcut()) + f.set_value('main', 'run_current_script', _ctrls.run_current_script.get_shortcut()) + f.set_value('main', 'run_current_inner', _ctrls.run_current_inner.get_shortcut()) + f.set_value('main', 'run_current_test', _ctrls.run_current_test.get_shortcut()) + f.set_value('main', 'panel_button', _ctrls.panel_button.get_shortcut()) + + f.save(path) + + +func load_shortcuts(path): + var emptyShortcut = ShortCut.new() + var f = ConfigFile.new() + f.load(path) + + _ctrls.run_all.set_shortcut(f.get_value('main', 'run_all', emptyShortcut)) + _ctrls.run_current_script.set_shortcut(f.get_value('main', 'run_current_script', emptyShortcut)) + _ctrls.run_current_inner.set_shortcut(f.get_value('main', 'run_current_inner', emptyShortcut)) + _ctrls.run_current_test.set_shortcut(f.get_value('main', 'run_current_test', emptyShortcut)) + _ctrls.panel_button.set_shortcut(f.get_value('main', 'panel_button', emptyShortcut)) diff --git a/addons/gut/gui/BottomPanelShortcuts.tscn b/addons/gut/gui/BottomPanelShortcuts.tscn new file mode 100644 index 0000000..5e2e5d9 --- /dev/null +++ b/addons/gut/gui/BottomPanelShortcuts.tscn @@ -0,0 +1,232 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://addons/gut/gui/ShortcutButton.tscn" type="PackedScene" id=1] +[ext_resource path="res://addons/gut/gui/BottomPanelShortcuts.gd" type="Script" id=2] + +[node name="BottomPanelShortcuts" type="WindowDialog"] +visible = true +anchor_right = 0.234 +anchor_bottom = 0.328 +margin_right = 195.384 +margin_bottom = 62.2 +rect_min_size = Vector2( 435, 305 ) +popup_exclusive = true +window_title = "GUT Shortcuts" +resizable = true +script = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Layout" type="VBoxContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 5.0 +margin_right = -5.0 +margin_bottom = 2.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="TopPad" type="CenterContainer" parent="Layout"] +margin_right = 425.0 +margin_bottom = 5.0 +rect_min_size = Vector2( 0, 5 ) + +[node name="Label2" type="Label" parent="Layout"] +margin_top = 9.0 +margin_right = 425.0 +margin_bottom = 29.0 +rect_min_size = Vector2( 0, 20 ) +text = "Always Active" +align = 1 +valign = 1 +autowrap = true + +[node name="ColorRect" type="ColorRect" parent="Layout/Label2"] +show_behind_parent = true +anchor_right = 1.0 +anchor_bottom = 1.0 +color = Color( 0, 0, 0, 0.196078 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="CPanelButton" type="HBoxContainer" parent="Layout"] +margin_top = 33.0 +margin_right = 425.0 +margin_bottom = 58.0 + +[node name="Label" type="Label" parent="Layout/CPanelButton"] +margin_right = 138.0 +margin_bottom = 25.0 +rect_min_size = Vector2( 50, 0 ) +size_flags_vertical = 7 +text = "Show/Hide GUT Panel" +valign = 1 + +[node name="ShortcutButton" parent="Layout/CPanelButton" instance=ExtResource( 1 )] +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 142.0 +margin_right = 425.0 +margin_bottom = 25.0 +size_flags_horizontal = 3 + +[node name="GutPanelPad" type="CenterContainer" parent="Layout"] +margin_top = 62.0 +margin_right = 425.0 +margin_bottom = 67.0 +rect_min_size = Vector2( 0, 5 ) + +[node name="Label" type="Label" parent="Layout"] +margin_top = 71.0 +margin_right = 425.0 +margin_bottom = 91.0 +rect_min_size = Vector2( 0, 20 ) +text = "Only Active When GUT Panel Shown" +align = 1 +valign = 1 +autowrap = true + +[node name="ColorRect2" type="ColorRect" parent="Layout/Label"] +show_behind_parent = true +anchor_right = 1.0 +anchor_bottom = 1.0 +color = Color( 0, 0, 0, 0.196078 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="TopPad2" type="CenterContainer" parent="Layout"] +margin_top = 95.0 +margin_right = 425.0 +margin_bottom = 100.0 +rect_min_size = Vector2( 0, 5 ) + +[node name="CRunAll" type="HBoxContainer" parent="Layout"] +margin_top = 104.0 +margin_right = 425.0 +margin_bottom = 129.0 + +[node name="Label" type="Label" parent="Layout/CRunAll"] +margin_right = 50.0 +margin_bottom = 25.0 +rect_min_size = Vector2( 50, 0 ) +size_flags_vertical = 7 +text = "Run All" +valign = 1 + +[node name="ShortcutButton" parent="Layout/CRunAll" instance=ExtResource( 1 )] +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 54.0 +margin_right = 425.0 +margin_bottom = 25.0 +size_flags_horizontal = 3 + +[node name="CRunCurrentScript" type="HBoxContainer" parent="Layout"] +margin_top = 133.0 +margin_right = 425.0 +margin_bottom = 158.0 + +[node name="Label" type="Label" parent="Layout/CRunCurrentScript"] +margin_right = 115.0 +margin_bottom = 25.0 +rect_min_size = Vector2( 50, 0 ) +size_flags_vertical = 7 +text = "Run Current Script" +valign = 1 + +[node name="ShortcutButton" parent="Layout/CRunCurrentScript" instance=ExtResource( 1 )] +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 119.0 +margin_right = 425.0 +margin_bottom = 25.0 +size_flags_horizontal = 3 + +[node name="CRunCurrentInner" type="HBoxContainer" parent="Layout"] +margin_top = 162.0 +margin_right = 425.0 +margin_bottom = 187.0 + +[node name="Label" type="Label" parent="Layout/CRunCurrentInner"] +margin_right = 150.0 +margin_bottom = 25.0 +rect_min_size = Vector2( 50, 0 ) +size_flags_vertical = 7 +text = "Run Current Inner Class" +valign = 1 + +[node name="ShortcutButton" parent="Layout/CRunCurrentInner" instance=ExtResource( 1 )] +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 154.0 +margin_right = 425.0 +margin_bottom = 25.0 +size_flags_horizontal = 3 + +[node name="CRunCurrentTest" type="HBoxContainer" parent="Layout"] +margin_top = 191.0 +margin_right = 425.0 +margin_bottom = 216.0 + +[node name="Label" type="Label" parent="Layout/CRunCurrentTest"] +margin_right = 106.0 +margin_bottom = 25.0 +rect_min_size = Vector2( 50, 0 ) +size_flags_vertical = 7 +text = "Run Current Test" +valign = 1 + +[node name="ShortcutButton" parent="Layout/CRunCurrentTest" instance=ExtResource( 1 )] +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 110.0 +margin_right = 425.0 +margin_bottom = 25.0 +size_flags_horizontal = 3 + +[node name="CenterContainer2" type="CenterContainer" parent="Layout"] +margin_top = 220.0 +margin_right = 425.0 +margin_bottom = 241.0 +rect_min_size = Vector2( 0, 5 ) +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="ShiftDisclaimer" type="Label" parent="Layout"] +margin_top = 245.0 +margin_right = 425.0 +margin_bottom = 259.0 +text = "\"Shift\" cannot be the only modifier for a shortcut." +align = 2 +autowrap = true + +[node name="HBoxContainer" type="HBoxContainer" parent="Layout"] +margin_top = 263.0 +margin_right = 425.0 +margin_bottom = 293.0 + +[node name="CenterContainer" type="CenterContainer" parent="Layout/HBoxContainer"] +margin_right = 361.0 +margin_bottom = 30.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Hide" type="Button" parent="Layout/HBoxContainer"] +margin_left = 365.0 +margin_right = 425.0 +margin_bottom = 30.0 +rect_min_size = Vector2( 60, 30 ) +text = "Close" + +[node name="BottomPad" type="CenterContainer" parent="Layout"] +margin_top = 297.0 +margin_right = 425.0 +margin_bottom = 307.0 +rect_min_size = Vector2( 0, 10 ) +size_flags_horizontal = 3 + +[connection signal="pressed" from="Layout/HBoxContainer/Hide" to="." method="_on_Hide_pressed"] diff --git a/addons/gut/gui/GutBottomPanel.gd b/addons/gut/gui/GutBottomPanel.gd new file mode 100644 index 0000000..50a32d8 --- /dev/null +++ b/addons/gut/gui/GutBottomPanel.gd @@ -0,0 +1,326 @@ +tool +extends Control + +const RUNNER_JSON_PATH = 'res://.gut_editor_config.json' +const RESULT_FILE = 'user://.gut_editor.bbcode' +const RESULT_JSON = 'user://.gut_editor.json' +const SHORTCUTS_PATH = 'res://.gut_editor_shortcuts.cfg' + +var TestScript = load('res://addons/gut/test.gd') +var GutConfigGui = load('res://addons/gut/gui/gut_config_gui.gd') + +var _interface = null; +var _is_running = false; +var _gut_config = load('res://addons/gut/gut_config.gd').new() +var _gut_config_gui = null +var _gut_plugin = null +var _light_color = Color(0, 0, 0, .5) +var _panel_button = null +var _last_selected_path = null + + +onready var _ctrls = { + output = $layout/RSplit/CResults/Output, + run_button = $layout/ControlBar/RunAll, + settings = $layout/RSplit/sc/Settings, + shortcut_dialog = $BottomPanelShortcuts, + light = $layout/RSplit/CResults/ControlBar/Light, + results = { + passing = $layout/RSplit/CResults/ControlBar/Passing/value, + failing = $layout/RSplit/CResults/ControlBar/Failing/value, + pending = $layout/RSplit/CResults/ControlBar/Pending/value, + errors = $layout/RSplit/CResults/ControlBar/Errors/value, + warnings = $layout/RSplit/CResults/ControlBar/Warnings/value, + orphans = $layout/RSplit/CResults/ControlBar/Orphans/value + }, + run_at_cursor = $layout/ControlBar/RunAtCursor +} + + +func _init(): + _gut_config.load_panel_options(RUNNER_JSON_PATH) + + +func _ready(): + _gut_config_gui = GutConfigGui.new(_ctrls.settings) + _gut_config_gui.set_options(_gut_config.options) + _set_all_fonts_in_ftl(_ctrls.output, _gut_config.options.panel_options.font_name) + _set_font_size_for_rtl(_ctrls.output, _gut_config.options.panel_options.font_size) + + +func _process(delta): + if(_is_running): + if(!_interface.is_playing_scene()): + _is_running = false + _ctrls.output.add_text("\ndone") + load_result_output() + _gut_plugin.make_bottom_panel_item_visible(self) + +# --------------- +# Private +# --------------- + +func load_shortcuts(): + _ctrls.shortcut_dialog.load_shortcuts(SHORTCUTS_PATH) + _apply_shortcuts() + + +# ----------------------------------- +func _set_font(rtl, font_name, custom_name): + if(font_name == null): + rtl.set('custom_fonts/' + custom_name, null) + else: + var dyn_font = DynamicFont.new() + var font_data = DynamicFontData.new() + font_data.font_path = 'res://addons/gut/fonts/' + font_name + '.ttf' + font_data.antialiased = true + dyn_font.font_data = font_data + rtl.set('custom_fonts/' + custom_name, dyn_font) + + +func _set_all_fonts_in_ftl(ftl, base_name): + if(base_name == 'Default'): + _set_font(ftl, null, 'normal_font') + _set_font(ftl, null, 'bold_font') + _set_font(ftl, null, 'italics_font') + _set_font(ftl, null, 'bold_italics_font') + else: + _set_font(ftl, base_name + '-Regular', 'normal_font') + _set_font(ftl, base_name + '-Bold', 'bold_font') + _set_font(ftl, base_name + '-Italic', 'italics_font') + _set_font(ftl, base_name + '-BoldItalic', 'bold_italics_font') + + +func _set_font_size_for_rtl(rtl, new_size): + if(rtl.get('custom_fonts/normal_font') != null): + rtl.get('custom_fonts/bold_italics_font').size = new_size + rtl.get('custom_fonts/bold_font').size = new_size + rtl.get('custom_fonts/italics_font').size = new_size + rtl.get('custom_fonts/normal_font').size = new_size +# ----------------------------------- + + +func _is_test_script(script): + var from = script.get_base_script() + while(from and from.resource_path != 'res://addons/gut/test.gd'): + from = from.get_base_script() + + return from != null + + +func _update_last_run_label(): + var text = '' + + if( _gut_config.options.selected == null and + _gut_config.options.inner_class == null and + _gut_config.options.unit_test_name == null): + text = 'All' + else: + text = nvl(_gut_config.options.selected, '') + ' ' + text += nvl(_gut_config.options.inner_class, '') + ' ' + text += nvl(_gut_config.options.unit_test_name, '') + + + +func _show_errors(errs): + _ctrls.output.clear() + var text = "Cannot run tests, you have a conrfiguration error:\n" + for e in errs: + text += str('* ', e, "\n") + text += "[right]Check your settings here ----->[/right]" + _ctrls.output.bbcode_text = text + + +func _run_tests(): + var issues = _gut_config_gui.get_config_issues() + if(issues.size() > 0): + _show_errors(issues) + return + + write_file(RESULT_FILE, 'Run in progress') + _gut_config.options = _gut_config_gui.get_options(_gut_config.options) + _set_all_fonts_in_ftl(_ctrls.output, _gut_config.options.panel_options.font_name) + _set_font_size_for_rtl(_ctrls.output, _gut_config.options.panel_options.font_size) + + var w_result = _gut_config.write_options(RUNNER_JSON_PATH) + if(w_result != OK): + push_error(str('Could not write options to ', RUNNER_JSON_PATH, ': ', w_result)) + return; + + _ctrls.output.clear() + + _update_last_run_label() + _interface.play_custom_scene('res://addons/gut/gui/GutRunner.tscn') + + _is_running = true + _ctrls.output.add_text('running...') + + +func _apply_shortcuts(): + _ctrls.run_button.shortcut = _ctrls.shortcut_dialog.get_run_all() + + _ctrls.run_at_cursor.get_script_button().shortcut = \ + _ctrls.shortcut_dialog.get_run_current_script() + _ctrls.run_at_cursor.get_inner_button().shortcut = \ + _ctrls.shortcut_dialog.get_run_current_inner() + _ctrls.run_at_cursor.get_test_button().shortcut = \ + _ctrls.shortcut_dialog.get_run_current_test() + + _panel_button.shortcut = _ctrls.shortcut_dialog.get_panel_button() + + +func _run_all(): + _gut_config.options.selected = null + _gut_config.options.inner_class = null + _gut_config.options.unit_test_name = null + + _run_tests() + + +# --------------- +# Events +# --------------- +func _on_editor_script_changed(script): + if(script): + set_current_script(script) + + +func _on_RunAll_pressed(): + _on_RunTests_pressed() + + +func _on_RunTests_pressed(): + _run_all() + + +func _on_CopyButton_pressed(): + OS.clipboard = _ctrls.output.text + + +func _on_ClearButton_pressed(): + _ctrls.output.clear() + + +func _on_Shortcuts_pressed(): + _ctrls.shortcut_dialog.popup_centered() + + +func _on_BottomPanelShortcuts_popup_hide(): + _apply_shortcuts() + _ctrls.shortcut_dialog.save_shortcuts(SHORTCUTS_PATH) + + +func _on_Light_draw(): + var l = _ctrls.light + l.draw_circle(Vector2(l.rect_size.x / 2, l.rect_size.y / 2), l.rect_size.x / 2, _light_color) + + +func _on_RunAtCursor_run_tests(what): + _gut_config.options.selected = what.script + _gut_config.options.inner_class = what.inner_class + _gut_config.options.unit_test_name = what.test_method + + _run_tests() + + +# --------------- +# Public +# --------------- + +func load_result_output(): + _ctrls.output.bbcode_text = get_file_as_text(RESULT_FILE) + _ctrls.output.grab_focus() + _ctrls.output.scroll_to_line(_ctrls.output.get_line_count() -1) + + var summary = get_file_as_text(RESULT_JSON) + var results = JSON.parse(summary) + if(results.error != OK): + return + var summary_json = results.result['test_scripts']['props'] + _ctrls.results.passing.text = str(summary_json.passing) + _ctrls.results.passing.get_parent().visible = true + + _ctrls.results.failing.text = str(summary_json.failures) + _ctrls.results.failing.get_parent().visible = true + + _ctrls.results.pending.text = str(summary_json.pending) + _ctrls.results.pending.get_parent().visible = _ctrls.results.pending.text != '0' + + _ctrls.results.errors.text = str(summary_json.errors) + _ctrls.results.errors.get_parent().visible = _ctrls.results.errors.text != '0' + + _ctrls.results.warnings.text = str(summary_json.warnings) + _ctrls.results.warnings.get_parent().visible = _ctrls.results.warnings.text != '0' + + _ctrls.results.orphans.text = str(summary_json.orphans) + _ctrls.results.orphans.get_parent().visible = _ctrls.results.orphans.text != '0' and !_gut_config.options.hide_orphans + + if(summary_json.tests == 0): + _light_color = Color(1, 0, 0, .75) + elif(summary_json.failures != 0): + _light_color = Color(1, 0, 0, .75) + elif(summary_json.pending != 0): + _light_color = Color(1, 1, 0, .75) + else: + _light_color = Color(0, 1, 0, .75) + _ctrls.light.update() + + + +func set_current_script(script): + if(script): + if(_is_test_script(script)): + var file = script.resource_path.get_file() + _last_selected_path = script.resource_path.get_file() + _ctrls.run_at_cursor.activate_for_script(script.resource_path) + + +func set_interface(value): + _interface = value + _interface.get_script_editor().connect("editor_script_changed", self, '_on_editor_script_changed') + _ctrls.run_at_cursor.set_script_editor(_interface.get_script_editor()) + set_current_script(_interface.get_script_editor().get_current_script()) + + +func set_plugin(value): + _gut_plugin = value + + +func set_panel_button(value): + _panel_button = value + +# ------------------------------------------------------------------------------ +# Write a file. +# ------------------------------------------------------------------------------ +func write_file(path, content): + var f = File.new() + var result = f.open(path, f.WRITE) + if(result == OK): + f.store_string(content) + f.close() + return result + + +# ------------------------------------------------------------------------------ +# Returns the text of a file or an empty string if the file could not be opened. +# ------------------------------------------------------------------------------ +func get_file_as_text(path): + var to_return = '' + var f = File.new() + var result = f.open(path, f.READ) + if(result == OK): + to_return = f.get_as_text() + f.close() + return to_return + + +# ------------------------------------------------------------------------------ +# return if_null if value is null otherwise return value +# ------------------------------------------------------------------------------ +func nvl(value, if_null): + if(value == null): + return if_null + else: + return value + + diff --git a/addons/gut/gui/GutBottomPanel.tscn b/addons/gut/gui/GutBottomPanel.tscn new file mode 100644 index 0000000..0bb7fc3 --- /dev/null +++ b/addons/gut/gui/GutBottomPanel.tscn @@ -0,0 +1,386 @@ +[gd_scene load_steps=16 format=2] + +[ext_resource path="res://addons/gut/gui/GutBottomPanel.gd" type="Script" id=1] +[ext_resource path="res://addons/gut/gui/BottomPanelShortcuts.tscn" type="PackedScene" id=2] +[ext_resource path="res://addons/gut/gui/RunAtCursor.tscn" type="PackedScene" id=3] +[ext_resource path="res://addons/gut/gui/play.png" type="Texture" id=4] + +[sub_resource type="InputEventKey" id=8] +control = true +scancode = 49 + +[sub_resource type="ShortCut" id=9] +shortcut = SubResource( 8 ) + +[sub_resource type="StyleBoxEmpty" id=5] + +[sub_resource type="DynamicFontData" id=10] +font_path = "res://addons/gut/fonts/CourierPrime-BoldItalic.ttf" + +[sub_resource type="DynamicFont" id=11] +size = 30 +font_data = SubResource( 10 ) + +[sub_resource type="DynamicFontData" id=12] +font_path = "res://addons/gut/fonts/CourierPrime-Italic.ttf" + +[sub_resource type="DynamicFont" id=13] +size = 30 +font_data = SubResource( 12 ) + +[sub_resource type="DynamicFontData" id=14] +font_path = "res://addons/gut/fonts/CourierPrime-Bold.ttf" + +[sub_resource type="DynamicFont" id=15] +size = 30 +font_data = SubResource( 14 ) + +[sub_resource type="DynamicFontData" id=16] +font_path = "res://addons/gut/fonts/CourierPrime-Regular.ttf" + +[sub_resource type="DynamicFont" id=17] +size = 30 +font_data = SubResource( 16 ) + +[node name="GutBottomPanel" type="Control"] +anchor_left = -0.0025866 +anchor_top = -0.00176575 +anchor_right = 0.997413 +anchor_bottom = 0.998234 +margin_left = 2.64868 +margin_top = 1.05945 +margin_right = 2.64862 +margin_bottom = 1.05945 +rect_min_size = Vector2( 0, 300 ) +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="layout" type="VBoxContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ControlBar" type="HBoxContainer" parent="layout"] +margin_right = 1023.0 +margin_bottom = 40.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="RunAll" type="Button" parent="layout/ControlBar"] +margin_right = 150.0 +margin_bottom = 40.0 +rect_min_size = Vector2( 150, 0 ) +hint_tooltip = "Run all test scripts in the suite." +size_flags_vertical = 11 +shortcut = SubResource( 9 ) +text = "Run All" +icon = ExtResource( 4 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Label" type="Label" parent="layout/ControlBar"] +margin_left = 154.0 +margin_top = 13.0 +margin_right = 213.0 +margin_bottom = 27.0 +hint_tooltip = "When a test script is edited, buttons are displayed to +run the opened script or an Inner-Test-Class or a +single test. The buttons change based on the location +of the cursor in the file. + +These buttons will remain active when editing other +items so that you can run tests without having to switch +back to the test script. + +You can assign keyboard shortcuts for these buttons +using the \"shortcuts\" button in the GUT panel." +mouse_filter = 1 +text = "Current: " + +[node name="RunAtCursor" parent="layout/ControlBar" instance=ExtResource( 3 )] +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 217.0 +margin_right = 456.0 +margin_bottom = 40.0 +rect_min_size = Vector2( 0, 40 ) + +[node name="CenterContainer2" type="CenterContainer" parent="layout/ControlBar"] +margin_left = 460.0 +margin_right = 699.0 +margin_bottom = 40.0 +size_flags_horizontal = 3 + +[node name="FocusButton" type="Button" parent="layout/ControlBar"] +show_behind_parent = true +margin_left = 703.0 +margin_right = 703.0 +margin_bottom = 40.0 +custom_styles/normal = SubResource( 5 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="CenterContainer" type="CenterContainer" parent="layout/ControlBar"] +margin_left = 707.0 +margin_right = 946.0 +margin_bottom = 40.0 +size_flags_horizontal = 3 + +[node name="Shortcuts" type="Button" parent="layout/ControlBar"] +margin_left = 950.0 +margin_right = 1022.0 +margin_bottom = 40.0 +hint_tooltip = "Set shortcuts for GUT buttons. Shortcuts do not work when the GUT panel is not visible." +size_flags_vertical = 11 +text = "Shortcuts" + +[node name="RSplit" type="HSplitContainer" parent="layout"] +margin_top = 44.0 +margin_right = 1023.0 +margin_bottom = 599.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="CResults" type="VBoxContainer" parent="layout/RSplit"] +margin_right = 611.0 +margin_bottom = 555.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="ControlBar" type="HBoxContainer" parent="layout/RSplit/CResults"] +margin_right = 611.0 +margin_bottom = 35.0 +rect_min_size = Vector2( 0, 35 ) + +[node name="Light" type="Control" parent="layout/RSplit/CResults/ControlBar"] +margin_right = 30.0 +margin_bottom = 35.0 +rect_min_size = Vector2( 30, 30 ) + +[node name="Passing" type="HBoxContainer" parent="layout/RSplit/CResults/ControlBar"] +visible = false +margin_left = 34.0 +margin_right = 107.0 +margin_bottom = 35.0 + +[node name="Sep" type="ColorRect" parent="layout/RSplit/CResults/ControlBar/Passing"] +margin_right = 2.0 +margin_bottom = 35.0 +rect_min_size = Vector2( 2, 0 ) + +[node name="label" type="Label" parent="layout/RSplit/CResults/ControlBar/Passing"] +margin_left = 6.0 +margin_top = 10.0 +margin_right = 54.0 +margin_bottom = 24.0 +text = "Passing" + +[node name="value" type="Label" parent="layout/RSplit/CResults/ControlBar/Passing"] +margin_left = 58.0 +margin_top = 10.0 +margin_right = 73.0 +margin_bottom = 24.0 +text = "---" + +[node name="Failing" type="HBoxContainer" parent="layout/RSplit/CResults/ControlBar"] +visible = false +margin_left = 34.0 +margin_right = 100.0 +margin_bottom = 35.0 + +[node name="Sep" type="ColorRect" parent="layout/RSplit/CResults/ControlBar/Failing"] +margin_right = 2.0 +margin_bottom = 35.0 +rect_min_size = Vector2( 2, 0 ) + +[node name="label" type="Label" parent="layout/RSplit/CResults/ControlBar/Failing"] +margin_left = 6.0 +margin_top = 10.0 +margin_right = 47.0 +margin_bottom = 24.0 +text = "Failing" + +[node name="value" type="Label" parent="layout/RSplit/CResults/ControlBar/Failing"] +margin_left = 51.0 +margin_top = 10.0 +margin_right = 66.0 +margin_bottom = 24.0 +text = "---" + +[node name="Pending" type="HBoxContainer" parent="layout/RSplit/CResults/ControlBar"] +visible = false +margin_left = 34.0 +margin_right = 110.0 +margin_bottom = 35.0 + +[node name="Sep" type="ColorRect" parent="layout/RSplit/CResults/ControlBar/Pending"] +margin_right = 2.0 +margin_bottom = 35.0 +rect_min_size = Vector2( 2, 0 ) + +[node name="label" type="Label" parent="layout/RSplit/CResults/ControlBar/Pending"] +margin_left = 6.0 +margin_top = 10.0 +margin_right = 57.0 +margin_bottom = 24.0 +text = "Pending" + +[node name="value" type="Label" parent="layout/RSplit/CResults/ControlBar/Pending"] +margin_left = 61.0 +margin_top = 10.0 +margin_right = 76.0 +margin_bottom = 24.0 +text = "---" + +[node name="Orphans" type="HBoxContainer" parent="layout/RSplit/CResults/ControlBar"] +visible = false +margin_left = 34.0 +margin_right = 110.0 +margin_bottom = 35.0 + +[node name="Sep" type="ColorRect" parent="layout/RSplit/CResults/ControlBar/Orphans"] +margin_right = 2.0 +margin_bottom = 35.0 +rect_min_size = Vector2( 2, 0 ) + +[node name="label" type="Label" parent="layout/RSplit/CResults/ControlBar/Orphans"] +margin_left = 6.0 +margin_top = 10.0 +margin_right = 57.0 +margin_bottom = 24.0 +text = "Orphans" + +[node name="value" type="Label" parent="layout/RSplit/CResults/ControlBar/Orphans"] +margin_left = 61.0 +margin_top = 10.0 +margin_right = 76.0 +margin_bottom = 24.0 +text = "---" + +[node name="Errors" type="HBoxContainer" parent="layout/RSplit/CResults/ControlBar"] +visible = false +margin_left = 34.0 +margin_right = 96.0 +margin_bottom = 35.0 + +[node name="Sep" type="ColorRect" parent="layout/RSplit/CResults/ControlBar/Errors"] +margin_right = 2.0 +margin_bottom = 35.0 +rect_min_size = Vector2( 2, 0 ) + +[node name="label" type="Label" parent="layout/RSplit/CResults/ControlBar/Errors"] +margin_left = 6.0 +margin_top = 10.0 +margin_right = 43.0 +margin_bottom = 24.0 +hint_tooltip = "The number of GUT errors generated. This does not include engine errors." +text = "Errors" + +[node name="value" type="Label" parent="layout/RSplit/CResults/ControlBar/Errors"] +margin_left = 47.0 +margin_top = 10.0 +margin_right = 62.0 +margin_bottom = 24.0 +text = "---" + +[node name="Warnings" type="HBoxContainer" parent="layout/RSplit/CResults/ControlBar"] +visible = false +margin_left = 34.0 +margin_right = 118.0 +margin_bottom = 35.0 + +[node name="Sep" type="ColorRect" parent="layout/RSplit/CResults/ControlBar/Warnings"] +margin_right = 2.0 +margin_bottom = 35.0 +rect_min_size = Vector2( 2, 0 ) + +[node name="label" type="Label" parent="layout/RSplit/CResults/ControlBar/Warnings"] +margin_left = 6.0 +margin_top = 10.0 +margin_right = 65.0 +margin_bottom = 24.0 +text = "Warnings" +__meta__ = { +"_editor_description_": "The number of GUT Warnings generated. This does not include engine warnings." +} + +[node name="value" type="Label" parent="layout/RSplit/CResults/ControlBar/Warnings"] +margin_left = 69.0 +margin_top = 10.0 +margin_right = 84.0 +margin_bottom = 24.0 +text = "---" + +[node name="CenterContainer" type="CenterContainer" parent="layout/RSplit/CResults/ControlBar"] +margin_left = 34.0 +margin_right = 488.0 +margin_bottom = 35.0 +size_flags_horizontal = 3 + +[node name="CopyButton" type="Button" parent="layout/RSplit/CResults/ControlBar"] +margin_left = 492.0 +margin_right = 547.0 +margin_bottom = 35.0 +text = " Copy " + +[node name="ClearButton" type="Button" parent="layout/RSplit/CResults/ControlBar"] +margin_left = 551.0 +margin_right = 611.0 +margin_bottom = 35.0 +text = " Clear " + +[node name="Output" type="RichTextLabel" parent="layout/RSplit/CResults"] +margin_top = 39.0 +margin_right = 611.0 +margin_bottom = 555.0 +focus_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +custom_fonts/bold_italics_font = SubResource( 11 ) +custom_fonts/italics_font = SubResource( 13 ) +custom_fonts/bold_font = SubResource( 15 ) +custom_fonts/normal_font = SubResource( 17 ) +bbcode_enabled = true +scroll_following = true +selection_enabled = true + +[node name="sc" type="ScrollContainer" parent="layout/RSplit"] +margin_left = 623.0 +margin_right = 1023.0 +margin_bottom = 555.0 +rect_min_size = Vector2( 400, 0 ) +mouse_filter = 1 +size_flags_vertical = 3 + +[node name="Settings" type="VBoxContainer" parent="layout/RSplit/sc"] +margin_right = 388.0 +margin_bottom = 862.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="BottomPanelShortcuts" parent="." instance=ExtResource( 2 )] +visible = false +anchor_left = -0.000517324 +anchor_top = 0.000882874 +anchor_right = 0.233483 +anchor_bottom = 0.328883 +margin_left = 10.0649 +margin_top = -173.752 +margin_right = 31.6969 +margin_bottom = -125.552 + +[connection signal="pressed" from="layout/ControlBar/RunAll" to="." method="_on_RunAll_pressed"] +[connection signal="run_tests" from="layout/ControlBar/RunAtCursor" to="." method="_on_RunAtCursor_run_tests"] +[connection signal="pressed" from="layout/ControlBar/FocusButton" to="." method="_on_FocusButton_pressed"] +[connection signal="pressed" from="layout/ControlBar/Shortcuts" to="." method="_on_Shortcuts_pressed"] +[connection signal="draw" from="layout/RSplit/CResults/ControlBar/Light" to="." method="_on_Light_draw"] +[connection signal="pressed" from="layout/RSplit/CResults/ControlBar/CopyButton" to="." method="_on_CopyButton_pressed"] +[connection signal="pressed" from="layout/RSplit/CResults/ControlBar/ClearButton" to="." method="_on_ClearButton_pressed"] +[connection signal="popup_hide" from="BottomPanelShortcuts" to="." method="_on_BottomPanelShortcuts_popup_hide"] diff --git a/addons/gut/gui/GutRunner.gd b/addons/gut/gui/GutRunner.gd new file mode 100644 index 0000000..b2b16f2 --- /dev/null +++ b/addons/gut/gui/GutRunner.gd @@ -0,0 +1,98 @@ +extends Node2D + +var Gut = load('res://addons/gut/gut.gd') +var ResultExporter = load('res://addons/gut/result_exporter.gd') +var GutConfig = load('res://addons/gut/gut_config.gd') + +const RUNNER_JSON_PATH = 'res://.gut_editor_config.json' +const RESULT_FILE = 'user://.gut_editor.bbcode' +const RESULT_JSON = 'user://.gut_editor.json' + +var _gut_config = null +var _gut = null; +var _wrote_results = false +# Flag for when this is being used at the command line. Otherwise it is +# assumed this is being used by the panel and being launched with +# play_custom_scene +var _cmdln_mode = false + +onready var _gut_layer = $GutLayer + + +func _ready(): + if(_gut_config == null): + _gut_config = GutConfig.new() + _gut_config.load_options(RUNNER_JSON_PATH) + + + # The command line will call run_tests on its own. When used from the panel + # we have to kick off the tests ourselves b/c there's no way I know of to + # interact with the scene that was run via play_custom_scene. + if(!_cmdln_mode): + call_deferred('run_tests') + + +func run_tests(): + if(_gut == null): + _gut = Gut.new() + + _gut.set_add_children_to(self) + if(_gut_config.options.gut_on_top): + _gut_layer.add_child(_gut) + else: + add_child(_gut) + + if(!_cmdln_mode): + _gut.connect('tests_finished', self, '_on_tests_finished', + [_gut_config.options.should_exit, _gut_config.options.should_exit_on_success]) + + _gut_config.config_gut(_gut) + if(_gut_config.options.gut_on_top): + _gut.get_gui().goto_bottom_right_corner() + + var run_rest_of_scripts = _gut_config.options.unit_test_name == '' + _gut.test_scripts(run_rest_of_scripts) + + +func _write_results(): + # bbcode_text appears to be empty. I'm not 100% sure why. Until that is + # figured out we have to just get the text which stinks. + var content = _gut.get_gui().get_text_box().text + + var f = File.new() + var result = f.open(RESULT_FILE, f.WRITE) + if(result == OK): + f.store_string(content) + f.close() + else: + print('ERROR Could not save bbcode, result = ', result) + + var exporter = ResultExporter.new() + var f_result = exporter.write_summary_file(_gut, RESULT_JSON) + _wrote_results = true + + +func _exit_tree(): + if(!_wrote_results and !_cmdln_mode): + _write_results() + + +func _on_tests_finished(should_exit, should_exit_on_success): + _write_results() + + if(should_exit): + get_tree().quit() + elif(should_exit_on_success and _gut.get_fail_count() == 0): + get_tree().quit() + + +func get_gut(): + if(_gut == null): + _gut = Gut.new() + return _gut + +func set_gut_config(which): + _gut_config = which + +func set_cmdln_mode(is_it): + _cmdln_mode = is_it diff --git a/addons/gut/gui/GutRunner.tscn b/addons/gut/gui/GutRunner.tscn new file mode 100644 index 0000000..077e411 --- /dev/null +++ b/addons/gut/gui/GutRunner.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://addons/gut/gui/GutRunner.gd" type="Script" id=1] + +[node name="GutRunner" type="Node2D"] +script = ExtResource( 1 ) + +[node name="GutLayer" type="CanvasLayer" parent="."] +layer = 128 diff --git a/addons/gut/gui/GutSceneTheme.tres b/addons/gut/gui/GutSceneTheme.tres new file mode 100644 index 0000000..565a6af --- /dev/null +++ b/addons/gut/gui/GutSceneTheme.tres @@ -0,0 +1,11 @@ +[gd_resource type="Theme" load_steps=3 format=2] + +[sub_resource type="DynamicFontData" id=9] +font_path = "res://addons/gut/fonts/AnonymousPro-Regular.ttf" + +[sub_resource type="DynamicFont" id=10] +size = 14 +font_data = SubResource( 9 ) + +[resource] +default_font = SubResource( 10 ) diff --git a/addons/gut/gui/RunAtCursor.gd b/addons/gut/gui/RunAtCursor.gd new file mode 100644 index 0000000..960414e --- /dev/null +++ b/addons/gut/gui/RunAtCursor.gd @@ -0,0 +1,130 @@ +tool +extends Control + + +var ScriptTextEditors = load('res://addons/gut/gui/script_text_editor_controls.gd') + +onready var _ctrls = { + btn_script = $HBox/BtnRunScript, + btn_inner = $HBox/BtnRunInnerClass, + btn_method = $HBox/BtnRunMethod, + lbl_none = $HBox/LblNoneSelected, + arrow_1 = $HBox/Arrow1, + arrow_2 = $HBox/Arrow2 +} + +var _editors = null +var _script_editor = null +var _cur_editor = null +var _last_line = -1 +var _cur_script_path = null +var _last_info = null + +signal run_tests(what) + + +func _ready(): + _ctrls.lbl_none.visible = true + _ctrls.btn_script.visible = false + _ctrls.btn_inner.visible = false + _ctrls.btn_method.visible = false + + +func _set_editor(which): + _last_line = -1 + if(_cur_editor != null and _cur_editor.get_ref()): + _cur_editor.get_ref().disconnect('cursor_changed', self, '_on_cursor_changed') + + if(which != null): + _cur_editor = weakref(which) + which.connect('cursor_changed', self, '_on_cursor_changed', [which]) + + _last_line = which.cursor_get_line() + _last_info = _editors.get_line_info() + _update_buttons(_last_info) + + + +func _update_buttons(info): + _ctrls.lbl_none.visible = _cur_script_path == null + _ctrls.btn_script.visible = _cur_script_path != null + + _ctrls.btn_inner.visible = info.inner_class != null + _ctrls.arrow_1.visible = info.inner_class != null + _ctrls.btn_inner.text = str(info.inner_class) + _ctrls.btn_inner.hint_tooltip = str("Run all tests in Inner-Test-Class ", info.inner_class) + + _ctrls.btn_method.visible = info.test_method != null + _ctrls.arrow_2.visible = info.test_method != null + _ctrls.btn_method.text = str(info.test_method) + _ctrls.btn_method.hint_tooltip = str("Run test ", info.test_method) + + # The button's new size won't take effect until the next frame. + # This appears to be what was causing the button to not be clickable the + # first time. + call_deferred("_update_rect_size") + + +func _update_rect_size(): + rect_min_size.x = _ctrls.btn_method.rect_size.x + _ctrls.btn_method.rect_position.x + +func _on_cursor_changed(which): + if(which.cursor_get_line() != _last_line): + _last_line = which.cursor_get_line() + _last_info = _editors.get_line_info() + _update_buttons(_last_info) + + +func set_script_editor(value): + _script_editor = value + _editors = ScriptTextEditors.new(value) + + +func activate_for_script(path): + _ctrls.btn_script.visible = true + _ctrls.btn_script.text = path.get_file() + _ctrls.btn_script.hint_tooltip = str("Run all tests in script ", path) + _cur_script_path = path + _editors.refresh() + _set_editor(_editors.get_current_text_edit()) + + +func _on_BtnRunScript_pressed(): + var info = _last_info.duplicate() + info.script = _cur_script_path.get_file() + info.inner_class = null + info.test_method = null + emit_signal("run_tests", info) + + +func _on_BtnRunInnerClass_pressed(): + var info = _last_info.duplicate() + info.script = _cur_script_path.get_file() + info.test_method = null + emit_signal("run_tests", info) + + +func _on_BtnRunMethod_pressed(): + var info = _last_info.duplicate() + info.script = _cur_script_path.get_file() + emit_signal("run_tests", info) + + +func get_script_button(): + return _ctrls.btn_script + + +func get_inner_button(): + return _ctrls.btn_inner + + +func get_test_button(): + return _ctrls.btn_method + +# not used, thought was configurable but it's just the script prefix +func set_method_prefix(value): + _editors.set_method_prefix(value) + +# not used, thought was configurable but it's just the script prefix +func set_inner_class_prefix(value): + _editors.set_inner_class_prefix(value) diff --git a/addons/gut/gui/RunAtCursor.tscn b/addons/gut/gui/RunAtCursor.tscn new file mode 100644 index 0000000..b4662df --- /dev/null +++ b/addons/gut/gui/RunAtCursor.tscn @@ -0,0 +1,80 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://addons/gut/gui/RunAtCursor.gd" type="Script" id=1] +[ext_resource path="res://addons/gut/gui/play.png" type="Texture" id=2] +[ext_resource path="res://addons/gut/gui/arrow.png" type="Texture" id=3] + +[node name="RunAtCursor" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_right = 1.0 +margin_bottom = -527.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="HBox" type="HBoxContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="LblNoneSelected" type="Label" parent="HBox"] +margin_top = 29.0 +margin_right = 50.0 +margin_bottom = 43.0 +text = "" + +[node name="BtnRunScript" type="Button" parent="HBox"] +visible = false +margin_left = 54.0 +margin_right = 140.0 +margin_bottom = 73.0 +text = "