mirror of
https://github.com/lihop/godot-xterm.git
synced 2024-11-13 22:10:25 +01:00
chore(test): update tests
Adds additional tests for the interface. Creates a new base test class GodotXtermTest that adds some additional assert methods. Tests inheriting from this should override the got_described_class() method. Add instance of the described class named 'subject' will be created and added to the scene tree before each test.
This commit is contained in:
parent
cb86cc95d7
commit
1a5f0f96da
5 changed files with 387 additions and 125 deletions
91
test/godot_xterm_test.gd
Normal file
91
test/godot_xterm_test.gd
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
# SPDX-FileCopyrightText: 2024 Leroy Hopson <godot-xterm@leroy.nix.nz>
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
class_name GodotXtermTest
|
||||||
|
extends GutTest
|
||||||
|
## Base class for tests in the GodotXterm project.
|
||||||
|
##
|
||||||
|
## Contains some helpful methods that extend upon Gut's built-in assertions.
|
||||||
|
|
||||||
|
var subject: Object
|
||||||
|
var described_class_name: String:
|
||||||
|
get:
|
||||||
|
return subject.get_class()
|
||||||
|
var described_class:
|
||||||
|
get:
|
||||||
|
return get_described_class()
|
||||||
|
|
||||||
|
|
||||||
|
func before_each():
|
||||||
|
subject = described_class.new()
|
||||||
|
watch_signals(subject)
|
||||||
|
add_child_autofree(subject)
|
||||||
|
|
||||||
|
|
||||||
|
# Override this in your tests to set the class you want to test.
|
||||||
|
func get_described_class() -> Object:
|
||||||
|
assert(false, "You need to override get_described_class() in your test.")
|
||||||
|
return null
|
||||||
|
|
||||||
|
|
||||||
|
func assert_has_property(property_name: String, type: Variant.Type = -1) -> bool:
|
||||||
|
var has_property = property_name in subject
|
||||||
|
assert_true(
|
||||||
|
has_property, "Expected %s to have property '%s'." % [described_class_name, property_name]
|
||||||
|
)
|
||||||
|
if has_property and type > -1:
|
||||||
|
var expected_type = type_string(type)
|
||||||
|
var actual_type = type_string(typeof(subject.get(property_name)))
|
||||||
|
assert_eq(
|
||||||
|
actual_type,
|
||||||
|
expected_type,
|
||||||
|
(
|
||||||
|
"Expected '%s' property of %s to be type '%s', but it was type '%s'."
|
||||||
|
% [name, described_class_name, expected_type, actual_type]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return expected_type == actual_type
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
func assert_has_property_with_default_value(property_name: String, expected_default_value) -> void:
|
||||||
|
if assert_has_property(property_name, typeof(expected_default_value)):
|
||||||
|
var actual_default_value = subject.get(property_name)
|
||||||
|
assert_eq(
|
||||||
|
actual_default_value,
|
||||||
|
expected_default_value,
|
||||||
|
(
|
||||||
|
"Expected '%s' property of %s to have default value '%s', but it was '%s'."
|
||||||
|
% [
|
||||||
|
property_name,
|
||||||
|
described_class_name,
|
||||||
|
expected_default_value,
|
||||||
|
actual_default_value
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func assert_has_method_with_return_type(method_name: String, expected_return_type: Variant.Type):
|
||||||
|
var has_method = subject.has_method(method_name)
|
||||||
|
if has_method:
|
||||||
|
var expected_type = type_string(expected_return_type)
|
||||||
|
var method_list = subject.get_method_list()
|
||||||
|
for method in method_list:
|
||||||
|
if method.name == method_name:
|
||||||
|
var actual_type = type_string(method["return"]["type"])
|
||||||
|
assert_eq(
|
||||||
|
actual_type,
|
||||||
|
expected_type,
|
||||||
|
(
|
||||||
|
"Expected method '%s' of %s to return type '%s', but it returns type '%s'."
|
||||||
|
% [method_name, described_class_name, expected_type, actual_type]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
assert_has_method(
|
||||||
|
subject,
|
||||||
|
method_name,
|
||||||
|
"Expected %s to have method '%s'." % [described_class_name, method_name]
|
||||||
|
)
|
|
@ -1,9 +1,12 @@
|
||||||
class_name NixTest extends GutTest
|
class_name NixTest extends GodotXtermTest
|
||||||
|
|
||||||
var pty: PTY
|
|
||||||
var helper: Helper
|
var helper: Helper
|
||||||
|
|
||||||
|
|
||||||
|
func get_described_class():
|
||||||
|
return PTY
|
||||||
|
|
||||||
|
|
||||||
func before_all():
|
func before_all():
|
||||||
if OS.get_name() == "macOS":
|
if OS.get_name() == "macOS":
|
||||||
helper = MacOSHelper.new()
|
helper = MacOSHelper.new()
|
||||||
|
@ -11,48 +14,42 @@ func before_all():
|
||||||
helper = LinuxHelper.new()
|
helper = LinuxHelper.new()
|
||||||
|
|
||||||
|
|
||||||
func before_each():
|
|
||||||
pty = PTY.new()
|
|
||||||
watch_signals(pty)
|
|
||||||
add_child_autofree(pty)
|
|
||||||
|
|
||||||
|
|
||||||
func test_fork_succeeds():
|
func test_fork_succeeds():
|
||||||
var err = pty.fork("sh")
|
var err = subject.fork("sh")
|
||||||
assert_eq(err, OK)
|
assert_eq(err, OK)
|
||||||
|
|
||||||
|
|
||||||
func test_fork_emits_data_received():
|
func test_fork_emits_data_received():
|
||||||
pty.call_deferred("fork", "sh", ["-c", "echo'"])
|
subject.call_deferred("fork", "sh", ["-c", "echo'"])
|
||||||
await wait_for_signal(pty.data_received, 1)
|
await wait_for_signal(subject.data_received, 1)
|
||||||
assert_signal_emitted(pty, "data_received")
|
assert_signal_emitted(subject, "data_received")
|
||||||
|
|
||||||
|
|
||||||
func test_open_succeeds():
|
func test_open_succeeds():
|
||||||
var err = pty.open()
|
var err = subject.open()
|
||||||
assert_eq(err, OK)
|
assert_eq(err, OK)
|
||||||
|
|
||||||
|
|
||||||
func test_open_creates_a_new_pty():
|
func test_open_creates_a_new_pty():
|
||||||
var num_pts = helper.get_pts().size()
|
var num_pts = helper.get_pts().size()
|
||||||
pty.open()
|
subject.open()
|
||||||
var new_num_pts = helper.get_pts().size()
|
var new_num_pts = helper.get_pts().size()
|
||||||
assert_eq(new_num_pts, num_pts + 1)
|
assert_eq(new_num_pts, num_pts + 1)
|
||||||
|
|
||||||
|
|
||||||
func test_open_pty_has_correct_name():
|
func test_open_pty_has_correct_name():
|
||||||
var original_pts = helper.get_pts()
|
var original_pts = helper.get_pts()
|
||||||
pty.open()
|
subject.open()
|
||||||
var new_pts = helper.get_pts()
|
var new_pts = helper.get_pts()
|
||||||
for pt in original_pts:
|
for pt in original_pts:
|
||||||
new_pts.erase(pt)
|
new_pts.erase(pt)
|
||||||
assert_eq(pty.get_pts(), new_pts[0])
|
assert_eq(subject.get_pts(), new_pts[0])
|
||||||
|
|
||||||
|
|
||||||
func xtest_open_pty_has_correct_win_size():
|
func xtest_open_pty_has_correct_win_size():
|
||||||
var cols = 7684
|
var cols = 7684
|
||||||
var rows = 9314
|
var rows = 9314
|
||||||
#var result = pty.open(cols, rows)
|
#var result = subject.open(cols, rows)
|
||||||
#var winsize = helper._get_winsize(result[1].master)
|
#var winsize = helper._get_winsize(result[1].master)
|
||||||
#assert_eq(winsize.cols, cols)
|
#assert_eq(winsize.cols, cols)
|
||||||
#assert_eq(winsize.rows, rows)
|
#assert_eq(winsize.rows, rows)
|
||||||
|
@ -61,7 +58,7 @@ func xtest_open_pty_has_correct_win_size():
|
||||||
func xtest_win_size_supports_max_unsigned_short_value():
|
func xtest_win_size_supports_max_unsigned_short_value():
|
||||||
var cols = 65535
|
var cols = 65535
|
||||||
var rows = 65535
|
var rows = 65535
|
||||||
#var result = pty.open(cols, rows)
|
#var result = subject.open(cols, rows)
|
||||||
#var winsize = helper._get_winsize(result[1].master)
|
#var winsize = helper._get_winsize(result[1].master)
|
||||||
#assert_eq(winsize.cols, cols)
|
#assert_eq(winsize.cols, cols)
|
||||||
#assert_eq(winsize.cols, rows)
|
#assert_eq(winsize.cols, rows)
|
||||||
|
@ -71,45 +68,45 @@ func test_closes_pty_on_free():
|
||||||
if OS.get_name() == "macOS":
|
if OS.get_name() == "macOS":
|
||||||
return
|
return
|
||||||
var num_pts = helper.get_pts().size()
|
var num_pts = helper.get_pts().size()
|
||||||
pty.fork("sleep", ["1000"])
|
subject.fork("sleep", ["1000"])
|
||||||
pty.free()
|
subject.free()
|
||||||
await wait_frames(1)
|
await wait_frames(1)
|
||||||
var new_num_pts = helper.get_pts().size()
|
var new_num_pts = helper.get_pts().size()
|
||||||
assert_eq(new_num_pts, num_pts)
|
assert_eq(new_num_pts, num_pts)
|
||||||
|
|
||||||
|
|
||||||
func test_emits_exited_signal_when_child_process_exits():
|
func test_emits_exited_signal_when_child_process_exits():
|
||||||
pty.call_deferred("fork", "exit")
|
subject.call_deferred("fork", "exit")
|
||||||
await wait_for_signal(pty.exited, 1)
|
await wait_for_signal(subject.exited, 1)
|
||||||
assert_signal_emitted(pty, "exited")
|
assert_signal_emitted(subject, "exited")
|
||||||
|
|
||||||
|
|
||||||
func test_emits_exit_code_on_success():
|
func test_emits_exit_code_on_success():
|
||||||
pty.call_deferred("fork", "true")
|
subject.call_deferred("fork", "true")
|
||||||
await wait_for_signal(pty.exited, 1)
|
await wait_for_signal(subject.exited, 1)
|
||||||
assert_signal_emitted_with_parameters(pty, "exited", [0, 0])
|
assert_signal_emitted_with_parameters(subject, "exited", [0, 0])
|
||||||
|
|
||||||
|
|
||||||
func test_emits_exit_code_on_failure():
|
func test_emits_exit_code_on_failure():
|
||||||
pty.call_deferred("fork", "false")
|
subject.call_deferred("fork", "false")
|
||||||
await wait_for_signal(pty.exited, 1)
|
await wait_for_signal(subject.exited, 1)
|
||||||
assert_signal_emitted_with_parameters(pty, "exited", [1, 0])
|
assert_signal_emitted_with_parameters(subject, "exited", [1, 0])
|
||||||
|
|
||||||
|
|
||||||
func test_emits_exited_on_kill():
|
func test_emits_exited_on_kill():
|
||||||
pty.call("fork", "yes")
|
subject.call("fork", "yes")
|
||||||
await wait_frames(1)
|
await wait_frames(1)
|
||||||
pty.call_deferred("kill", PTY.SIGNAL_SIGKILL)
|
subject.call_deferred("kill", PTY.SIGNAL_SIGKILL)
|
||||||
await wait_for_signal(pty.exited, 1)
|
await wait_for_signal(subject.exited, 1)
|
||||||
assert_signal_emitted(pty, "exited")
|
assert_signal_emitted(subject, "exited")
|
||||||
|
|
||||||
|
|
||||||
func test_emits_exited_with_signal():
|
func test_emits_exited_with_signal():
|
||||||
pty.call("fork", "yes")
|
subject.call("fork", "yes")
|
||||||
await wait_frames(1)
|
await wait_frames(1)
|
||||||
pty.call_deferred("kill", PTY.SIGNAL_SIGSEGV)
|
subject.call_deferred("kill", PTY.SIGNAL_SIGSEGV)
|
||||||
await wait_for_signal(pty.exited, 1)
|
await wait_for_signal(subject.exited, 1)
|
||||||
assert_signal_emitted_with_parameters(pty, "exited", [0, PTY.SIGNAL_SIGSEGV])
|
assert_signal_emitted_with_parameters(subject, "exited", [0, PTY.SIGNAL_SIGSEGV])
|
||||||
|
|
||||||
|
|
||||||
# Run the same tests, but with use_threads = false.
|
# Run the same tests, but with use_threads = false.
|
||||||
|
@ -118,7 +115,7 @@ class TestNoThreads:
|
||||||
|
|
||||||
func before_each():
|
func before_each():
|
||||||
super.before_each()
|
super.before_each()
|
||||||
pty.use_threads = false
|
subject.use_threads = false
|
||||||
|
|
||||||
|
|
||||||
class Helper:
|
class Helper:
|
||||||
|
@ -156,13 +153,12 @@ class Helper:
|
||||||
|
|
||||||
|
|
||||||
class XTestPTYSize:
|
class XTestPTYSize:
|
||||||
extends "res://addons/gut/test.gd"
|
extends NixTest
|
||||||
# Tests to check that psuedoterminal size (as reported by the stty command)
|
# Tests to check that psuedoterminal size (as reported by the stty command)
|
||||||
# matches the size of the Terminal node. Uses various scene tree layouts with
|
# matches the size of the Terminal node. Uses various scene tree layouts with
|
||||||
# Terminal and PTY nodes in different places.
|
# Terminal and PTY nodes in different places.
|
||||||
# See: https://github.com/lihop/godot-xterm/issues/56
|
# See: https://github.com/lihop/godot-xterm/issues/56
|
||||||
|
|
||||||
var pty: PTY
|
|
||||||
var terminal: Terminal
|
var terminal: Terminal
|
||||||
var scene: Node
|
var scene: Node
|
||||||
var regex := RegEx.new()
|
var regex := RegEx.new()
|
||||||
|
@ -183,14 +179,14 @@ class XTestPTYSize:
|
||||||
"PTYCousinAbove2",
|
"PTYCousinAbove2",
|
||||||
"PTYCousinBelow2"
|
"PTYCousinBelow2"
|
||||||
]:
|
]:
|
||||||
pty = scene.get_node(s).find_child("PTY")
|
subject = scene.get_node(s).find_child("PTY")
|
||||||
terminal = scene.get_node(s).find_child("Terminal")
|
terminal = scene.get_node(s).find_child("Terminal")
|
||||||
|
|
||||||
pty.call_deferred("fork", OS.get_environment("SHELL"))
|
subject.call_deferred("fork", OS.get_environment("SHELL"))
|
||||||
pty.call_deferred("write", "stty -a | head -n1\n")
|
subject.call_deferred("write", "stty -a | head -n1\n")
|
||||||
var output := ""
|
var output := ""
|
||||||
while not "rows" in output and not "columns" in output:
|
while not "rows" in output and not "columns" in output:
|
||||||
output = (await pty.data_received).get_string_from_utf8()
|
output = (await subject.data_received).get_string_from_utf8()
|
||||||
var regex_match = regex.search(output)
|
var regex_match = regex.search(output)
|
||||||
var stty_rows = int(regex_match.get_string("rows"))
|
var stty_rows = int(regex_match.get_string("rows"))
|
||||||
var stty_cols = int(regex_match.get_string("columns"))
|
var stty_cols = int(regex_match.get_string("columns"))
|
||||||
|
|
|
@ -1,21 +1,86 @@
|
||||||
# SPDX-FileCopyrightText: 2024 Leroy Hopson <godot-xterm@leroy.nix.nz>
|
# SPDX-FileCopyrightText: 2024 Leroy Hopson <godot-xterm@leroy.nix.nz>
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
class_name PTYTest extends "res://addons/gut/test.gd"
|
class_name PTYTest extends GodotXtermTest
|
||||||
|
|
||||||
var pty: PTY
|
|
||||||
|
|
||||||
|
|
||||||
func before_each():
|
func get_described_class():
|
||||||
pty = PTY.new()
|
return PTY
|
||||||
add_child_autofree(pty)
|
|
||||||
|
|
||||||
|
|
||||||
class TestDefaults:
|
class TestInterface:
|
||||||
extends PTYTest
|
extends PTYTest
|
||||||
|
|
||||||
func test_default_env() -> void:
|
## API V2.
|
||||||
assert_eq(pty.env, {"TERM": "xterm-256color", "COLORTERM": "truecolor"})
|
|
||||||
|
|
||||||
func test_default_use_os_env() -> void:
|
# Properties.
|
||||||
assert_eq(pty.use_os_env, true)
|
|
||||||
|
# TODO: Implement cols property.
|
||||||
|
func xtest_has_property_cols() -> void:
|
||||||
|
assert_has_property_with_default_value("cols", 80)
|
||||||
|
|
||||||
|
func test_has_property_env() -> void:
|
||||||
|
assert_has_property_with_default_value(
|
||||||
|
"env", {"TERM": "xterm-256color", "COLORTERM": "truecolor"}
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO: Implement rows property.
|
||||||
|
func xtest_has_property_rows() -> void:
|
||||||
|
assert_has_property_with_default_value("rows", 24)
|
||||||
|
|
||||||
|
# TODO: Implement terminal_path property.
|
||||||
|
func xtest_has_property_terminal_path() -> void:
|
||||||
|
assert_has_property("terminal_path")
|
||||||
|
|
||||||
|
func test_has_proprty_use_os_env() -> void:
|
||||||
|
assert_has_property_with_default_value("use_os_env", true)
|
||||||
|
|
||||||
|
# Methods.
|
||||||
|
|
||||||
|
func test_has_method_fork():
|
||||||
|
assert_has_method_with_return_type("fork", TYPE_INT)
|
||||||
|
|
||||||
|
func test_has_method_kill():
|
||||||
|
assert_has_method_with_return_type("kill", TYPE_NIL)
|
||||||
|
|
||||||
|
func test_has_method_open():
|
||||||
|
assert_has_method_with_return_type("open", TYPE_INT)
|
||||||
|
|
||||||
|
func test_has_method_resize():
|
||||||
|
assert_has_method_with_return_type("resize", TYPE_NIL)
|
||||||
|
|
||||||
|
func test_has_method_resizev():
|
||||||
|
assert_has_method_with_return_type("resizev", TYPE_NIL)
|
||||||
|
|
||||||
|
func test_has_method_write():
|
||||||
|
assert_has_method_with_return_type("write", TYPE_NIL)
|
||||||
|
|
||||||
|
# Signals.
|
||||||
|
|
||||||
|
func test_has_signal_data_received() -> void:
|
||||||
|
assert_has_signal(subject, "data_received")
|
||||||
|
|
||||||
|
func test_has_signal_exited() -> void:
|
||||||
|
assert_has_signal(subject, "exited")
|
||||||
|
|
||||||
|
# Enums.
|
||||||
|
|
||||||
|
# Added SIGNAL_ prefix to name.
|
||||||
|
func test_has_enum_signal():
|
||||||
|
assert_eq(described_class.SIGNAL_SIGHUP, 1)
|
||||||
|
assert_eq(described_class.SIGNAL_SIGINT, 2)
|
||||||
|
assert_eq(described_class.SIGNAL_SIGQUIT, 3)
|
||||||
|
assert_eq(described_class.SIGNAL_SIGILL, 4)
|
||||||
|
assert_eq(described_class.SIGNAL_SIGTRAP, 5)
|
||||||
|
assert_eq(described_class.SIGNAL_SIGABRT, 6)
|
||||||
|
assert_eq(described_class.SIGNAL_SIGFPE, 8)
|
||||||
|
assert_eq(described_class.SIGNAL_SIGKILL, 9)
|
||||||
|
assert_eq(described_class.SIGNAL_SIGSEGV, 11)
|
||||||
|
assert_eq(described_class.SIGNAL_SIGPIPE, 13)
|
||||||
|
assert_eq(described_class.SIGNAL_SIGALRM, 14)
|
||||||
|
assert_eq(described_class.SIGNAL_SIGTERM, 15)
|
||||||
|
|
||||||
|
## Other tests.
|
||||||
|
|
||||||
|
func test_has_no_visible_children():
|
||||||
|
assert_eq(subject.get_child_count(), 0)
|
||||||
|
|
|
@ -1,36 +1,38 @@
|
||||||
# SPDX-FileCopyrightText: 2024 Leroy Hopson <godot-xterm@leroy.nix.nz>
|
# SPDX-FileCopyrightText: 2024 Leroy Hopson <godot-xterm@leroy.nix.nz>
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
class_name RenderingTest extends GutTest
|
class_name RenderingTest extends GodotXtermTest
|
||||||
|
|
||||||
var terminal: Terminal
|
|
||||||
|
func get_described_class():
|
||||||
|
return Terminal
|
||||||
|
|
||||||
|
|
||||||
# Return the color in the center of the given cell.
|
# Return the color in the center of the given cell.
|
||||||
func pick_cell_color(cell := Vector2i(0, 0)) -> Color:
|
func pick_cell_color(cell := Vector2i(0, 0)) -> Color:
|
||||||
var cell_size = terminal.get_cell_size()
|
var cell_size = subject.get_cell_size()
|
||||||
var pixelv = Vector2(cell) * cell_size + (cell_size / 2)
|
var pixelv = Vector2(cell) * cell_size + (cell_size / 2)
|
||||||
return get_viewport().get_texture().get_image().get_pixelv(cell_size / 2)
|
return get_viewport().get_texture().get_image().get_pixelv(cell_size / 2)
|
||||||
|
|
||||||
|
|
||||||
func before_each():
|
func before_each():
|
||||||
terminal = Terminal.new()
|
subject = described_class.new()
|
||||||
terminal.add_theme_font_override("normal_font", preload("res://themes/fonts/regular.tres"))
|
subject.add_theme_font_override("normal_font", preload("res://themes/fonts/regular.tres"))
|
||||||
terminal.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
subject.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||||
watch_signals(terminal)
|
watch_signals(subject)
|
||||||
call_deferred("add_child_autofree", terminal)
|
call_deferred("add_child_autofree", subject)
|
||||||
await wait_for_signal(terminal.ready, 5)
|
await wait_for_signal(subject.ready, 5)
|
||||||
|
|
||||||
|
|
||||||
class TestRendering:
|
class TestRendering:
|
||||||
extends RenderingTest
|
extends RenderingTest
|
||||||
|
|
||||||
func test_update():
|
func test_update():
|
||||||
terminal.write("\u001b[38;2;255;0;0m")
|
subject.write("\u001b[38;2;255;0;0m")
|
||||||
terminal.write("█".repeat(terminal.get_cols() * terminal.get_rows()))
|
subject.write("█".repeat(subject.get_cols() * subject.get_rows()))
|
||||||
await get_tree().physics_frame
|
await get_tree().physics_frame
|
||||||
terminal.queue_redraw()
|
subject.queue_redraw()
|
||||||
await wait_for_signal(terminal.draw, 3)
|
await wait_for_signal(subject.draw, 3)
|
||||||
await wait_frames(15)
|
await wait_frames(15)
|
||||||
var cell_color = pick_cell_color(Vector2i(0, 0))
|
var cell_color = pick_cell_color(Vector2i(0, 0))
|
||||||
assert_eq(cell_color, Color.RED)
|
assert_eq(cell_color, Color.RED)
|
||||||
|
@ -44,7 +46,7 @@ class TestKeyPressed:
|
||||||
func before_each():
|
func before_each():
|
||||||
await super.before_each()
|
await super.before_each()
|
||||||
|
|
||||||
terminal.grab_focus()
|
subject.grab_focus()
|
||||||
|
|
||||||
input_event = InputEventKey.new()
|
input_event = InputEventKey.new()
|
||||||
input_event.pressed = true
|
input_event.pressed = true
|
||||||
|
@ -54,38 +56,38 @@ class TestKeyPressed:
|
||||||
input_event.keycode = KEY_A
|
input_event.keycode = KEY_A
|
||||||
input_event.unicode = "a".unicode_at(0)
|
input_event.unicode = "a".unicode_at(0)
|
||||||
|
|
||||||
await wait_for_signal(terminal.key_pressed, 1)
|
await wait_for_signal(subject.key_pressed, 1)
|
||||||
assert_signal_emitted(terminal, "key_pressed")
|
assert_signal_emitted(subject, "key_pressed")
|
||||||
|
|
||||||
func test_key_pressed_emitted_only_once_per_key_input():
|
func test_key_pressed_emitted_only_once_per_key_input():
|
||||||
input_event.keycode = KEY_B
|
input_event.keycode = KEY_B
|
||||||
input_event.unicode = "b".unicode_at(0)
|
input_event.unicode = "b".unicode_at(0)
|
||||||
|
|
||||||
await wait_for_signal(terminal.key_pressed, 1)
|
await wait_for_signal(subject.key_pressed, 1)
|
||||||
assert_signal_emit_count(terminal, "key_pressed", 1)
|
assert_signal_emit_count(subject, "key_pressed", 1)
|
||||||
|
|
||||||
func test_key_pressed_emits_interpreted_key_input_as_first_param():
|
func test_key_pressed_emits_interpreted_key_input_as_first_param():
|
||||||
input_event.keycode = KEY_UP
|
input_event.keycode = KEY_UP
|
||||||
input_event.unicode = 0
|
input_event.unicode = 0
|
||||||
|
|
||||||
await wait_for_signal(terminal.key_pressed, 1)
|
await wait_for_signal(subject.key_pressed, 1)
|
||||||
|
|
||||||
var signal_parameters = get_signal_parameters(terminal, "key_pressed", 0)
|
var signal_parameters = get_signal_parameters(subject, "key_pressed", 0)
|
||||||
assert_eq(signal_parameters[0], "\u001b[A")
|
assert_eq(signal_parameters[0], "\u001b[A")
|
||||||
|
|
||||||
func test_key_pressed_emits_original_input_event_as_second_param():
|
func test_key_pressed_emits_original_input_event_as_second_param():
|
||||||
input_event.keycode = KEY_L
|
input_event.keycode = KEY_L
|
||||||
input_event.unicode = "l".unicode_at(0)
|
input_event.unicode = "l".unicode_at(0)
|
||||||
|
|
||||||
await wait_for_signal(terminal.key_pressed, 1)
|
await wait_for_signal(subject.key_pressed, 1)
|
||||||
|
|
||||||
var signal_parameters = get_signal_parameters(terminal, "key_pressed", 0)
|
var signal_parameters = get_signal_parameters(subject, "key_pressed", 0)
|
||||||
assert_eq(signal_parameters[1], input_event)
|
assert_eq(signal_parameters[1], input_event)
|
||||||
|
|
||||||
func test_key_pressed_not_emitted_when_writing_to_terminal():
|
func test_key_pressed_not_emitted_when_writing_to_subject():
|
||||||
terminal.write("a")
|
subject.write("a")
|
||||||
await wait_frames(1)
|
await wait_frames(1)
|
||||||
assert_signal_emit_count(terminal, "key_pressed", 0)
|
assert_signal_emit_count(subject, "key_pressed", 0)
|
||||||
|
|
||||||
func test_key_pressed_not_emitted_by_other_input_type():
|
func test_key_pressed_not_emitted_by_other_input_type():
|
||||||
var mouse_input = InputEventMouseButton.new()
|
var mouse_input = InputEventMouseButton.new()
|
||||||
|
@ -93,5 +95,5 @@ class TestKeyPressed:
|
||||||
mouse_input.pressed = true
|
mouse_input.pressed = true
|
||||||
Input.call_deferred("parse_input_event", mouse_input)
|
Input.call_deferred("parse_input_event", mouse_input)
|
||||||
|
|
||||||
await wait_for_signal(terminal.gui_input, 1)
|
await wait_for_signal(subject.gui_input, 1)
|
||||||
assert_signal_emit_count(terminal, "key_pressed", 0)
|
assert_signal_emit_count(subject, "key_pressed", 0)
|
||||||
|
|
|
@ -1,93 +1,201 @@
|
||||||
# SPDX-FileCopyrightText: 2021-2024 Leroy Hopson <godot-xterm@leroy.nix.nz>
|
# SPDX-FileCopyrightText: 2021-2024 Leroy Hopson <godot-xterm@leroy.nix.nz>
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
class_name TerminalTest extends "res://addons/gut/test.gd"
|
class_name TerminalTest extends GodotXtermTest
|
||||||
|
|
||||||
var terminal: Terminal
|
|
||||||
|
func get_described_class():
|
||||||
|
return Terminal
|
||||||
|
|
||||||
|
|
||||||
func before_each():
|
func before_each():
|
||||||
terminal = Terminal.new()
|
super.before_each()
|
||||||
terminal.size = Vector2(400, 200)
|
subject.size = Vector2(400, 200)
|
||||||
watch_signals(terminal)
|
|
||||||
add_child_autofree(terminal)
|
|
||||||
|
class TestInterface:
|
||||||
|
extends TerminalTest
|
||||||
|
|
||||||
|
## API V2.
|
||||||
|
|
||||||
|
# Properties.
|
||||||
|
|
||||||
|
func test_has_property_bell_muted():
|
||||||
|
assert_has_property_with_default_value("bell_muted", false)
|
||||||
|
|
||||||
|
func test_has_property_bell_cooldown():
|
||||||
|
assert_has_property_with_default_value("bell_cooldown", 0.1)
|
||||||
|
|
||||||
|
func test_has_property_blink_on_time():
|
||||||
|
assert_has_property_with_default_value("blink_on_time", 0.6)
|
||||||
|
|
||||||
|
func test_has_property_blink_off_time():
|
||||||
|
assert_has_property_with_default_value("blink_off_time", 0.3)
|
||||||
|
|
||||||
|
# TODO: Implement copy_on_selection property.
|
||||||
|
func xtest_has_property_copy_on_selection():
|
||||||
|
assert_has_property_with_default_value("copy_on_selection", false)
|
||||||
|
|
||||||
|
# TODO: Implement update_mode property.
|
||||||
|
func xtest_has_property_update_mode():
|
||||||
|
#assert_has_property_with_default_value("update_mode", UPDATE_MODE_AUTO)
|
||||||
|
pass
|
||||||
|
|
||||||
|
# cols and rows removed.
|
||||||
|
|
||||||
|
# Methods.
|
||||||
|
|
||||||
|
# TODO: Implement clear() method.
|
||||||
|
func xtest_has_method_clear():
|
||||||
|
assert_has_method_with_return_type("clear", TYPE_NIL)
|
||||||
|
|
||||||
|
# TODO: Implement copy_all() method.
|
||||||
|
func xtest_has_method_copy_all():
|
||||||
|
assert_has_method_with_return_type("copy_all", TYPE_STRING)
|
||||||
|
|
||||||
|
# TODO: Implement copy_selection() method.
|
||||||
|
func xtest_has_method_copy_selection():
|
||||||
|
assert_has_method_with_return_type("copy_selection", TYPE_STRING)
|
||||||
|
|
||||||
|
func test_has_method_get_cols():
|
||||||
|
assert_has_method_with_return_type("get_cols", TYPE_INT)
|
||||||
|
|
||||||
|
func test_has_method_get_rows():
|
||||||
|
assert_has_method_with_return_type("get_rows", TYPE_INT)
|
||||||
|
|
||||||
|
func test_has_method_write():
|
||||||
|
assert_has_method(subject, "write")
|
||||||
|
|
||||||
|
# Signals.
|
||||||
|
|
||||||
|
func test_has_signal_data_sent():
|
||||||
|
assert_has_signal(subject, "data_sent")
|
||||||
|
|
||||||
|
func test_has_signal_key_pressed():
|
||||||
|
assert_has_signal(subject, "key_pressed")
|
||||||
|
|
||||||
|
func test_has_signal_size_changed():
|
||||||
|
assert_has_signal(subject, "size_changed")
|
||||||
|
|
||||||
|
func test_has_signal_bell():
|
||||||
|
assert_has_signal(subject, "bell")
|
||||||
|
|
||||||
|
# Enums.
|
||||||
|
|
||||||
|
# TODO: Implement SelectionMode enum.
|
||||||
|
func xtest_has_enum_selection_mode():
|
||||||
|
assert_eq(described_class.SELECTION_MODE_NONE, 0)
|
||||||
|
assert_eq(described_class.SELECTION_MODE_POINTER, 1)
|
||||||
|
|
||||||
|
# TODO: Implement UpdateMode enum.
|
||||||
|
func xtest_has_enum_update_mode():
|
||||||
|
assert_eq(described_class.UPDATE_MODE_DISABLED, 0)
|
||||||
|
assert_eq(described_class.AUTO, 1)
|
||||||
|
assert_eq(described_class.ALL, 2)
|
||||||
|
assert_eq(described_class.ALL_NEXT_FRAME, 3)
|
||||||
|
|
||||||
|
## API Next.
|
||||||
|
|
||||||
|
# Methods.
|
||||||
|
|
||||||
|
func test_has_method_get_cursor_pos():
|
||||||
|
assert_has_method_with_return_type("get_cursor_pos", TYPE_VECTOR2I)
|
||||||
|
|
||||||
|
func test_has_method_get_cell_size():
|
||||||
|
assert_has_method_with_return_type("get_cell_size", TYPE_VECTOR2)
|
||||||
|
|
||||||
|
func test_has_method_write_with_response():
|
||||||
|
assert_has_method_with_return_type("write", TYPE_STRING)
|
||||||
|
|
||||||
|
# Enums.
|
||||||
|
|
||||||
|
func test_has_enum_inverse_mode():
|
||||||
|
assert_eq(described_class.INVERSE_MODE_INVERT, 0)
|
||||||
|
assert_eq(described_class.INVERSE_MODE_SWAP, 1)
|
||||||
|
|
||||||
|
## Other tests.
|
||||||
|
|
||||||
|
func test_has_no_visible_children():
|
||||||
|
# We add children like the bell timer for private use that should not
|
||||||
|
# be visible outside of the node itself.
|
||||||
|
assert_eq(subject.get_child_count(), 0)
|
||||||
|
|
||||||
|
|
||||||
class TestBell:
|
class TestBell:
|
||||||
extends TerminalTest
|
extends TerminalTest
|
||||||
|
|
||||||
func test_bell() -> void:
|
func test_bell() -> void:
|
||||||
watch_signals(terminal)
|
watch_signals(subject)
|
||||||
terminal.bell_cooldown = 0
|
subject.bell_cooldown = 0
|
||||||
terminal.write(char(7))
|
subject.write(char(7))
|
||||||
terminal.write(char(0x07))
|
subject.write(char(0x07))
|
||||||
terminal.write("\a")
|
subject.write("\a")
|
||||||
terminal.write("\u0007")
|
subject.write("\u0007")
|
||||||
terminal.write("'Ask not for whom the \a tolls; it tolls for thee' - John Donne")
|
subject.write("'Ask not for whom the \a tolls; it tolls for thee' - John Donne")
|
||||||
assert_signal_emit_count(terminal, "bell", 5)
|
assert_signal_emit_count(subject, "bell", 5)
|
||||||
|
|
||||||
func test_bell_mute() -> void:
|
func test_bell_mute() -> void:
|
||||||
watch_signals(terminal)
|
watch_signals(subject)
|
||||||
terminal.bell_muted = true
|
subject.bell_muted = true
|
||||||
terminal.write("\a")
|
subject.write("\a")
|
||||||
assert_signal_emit_count(terminal, "bell", 0)
|
assert_signal_emit_count(subject, "bell", 0)
|
||||||
|
|
||||||
func test_bell_cooldown() -> void:
|
func test_bell_cooldown() -> void:
|
||||||
watch_signals(terminal)
|
watch_signals(subject)
|
||||||
terminal.bell_cooldown = 10000
|
subject.bell_cooldown = 10000
|
||||||
terminal.write("\a")
|
subject.write("\a")
|
||||||
terminal.write("\a")
|
subject.write("\a")
|
||||||
assert_signal_emit_count(terminal, "bell", 1)
|
assert_signal_emit_count(subject, "bell", 1)
|
||||||
|
|
||||||
func test_change_cooldown_while_active() -> void:
|
func test_change_cooldown_while_active() -> void:
|
||||||
watch_signals(terminal)
|
watch_signals(subject)
|
||||||
terminal.bell_cooldown = 10000
|
subject.bell_cooldown = 10000
|
||||||
terminal.write("\a")
|
subject.write("\a")
|
||||||
terminal.bell_cooldown = 0
|
subject.bell_cooldown = 0
|
||||||
terminal.write("\a")
|
subject.write("\a")
|
||||||
assert_signal_emit_count(terminal, "bell", 2)
|
assert_signal_emit_count(subject, "bell", 2)
|
||||||
|
|
||||||
|
|
||||||
class TestCursorPos:
|
class TestCursorPos:
|
||||||
extends TerminalTest
|
extends TerminalTest
|
||||||
|
|
||||||
func test_get_cursor_pos_initial():
|
func test_get_cursor_pos_initial():
|
||||||
assert_eq(terminal.get_cursor_pos(), Vector2i.ZERO)
|
assert_eq(subject.get_cursor_pos(), Vector2i.ZERO)
|
||||||
|
|
||||||
func test_get_cursor_pos_x():
|
func test_get_cursor_pos_x():
|
||||||
terminal.write("_")
|
subject.write("_")
|
||||||
assert_eq(terminal.get_cursor_pos().x, 1)
|
assert_eq(subject.get_cursor_pos().x, 1)
|
||||||
|
|
||||||
func test_get_cursor_pos_y():
|
func test_get_cursor_pos_y():
|
||||||
terminal.write("_".repeat(terminal.cols + 1))
|
subject.write("_".repeat(subject.cols + 1))
|
||||||
assert_eq(terminal.get_cursor_pos().y, 1)
|
assert_eq(subject.get_cursor_pos().y, 1)
|
||||||
|
|
||||||
|
|
||||||
class TestWrite:
|
class TestWrite:
|
||||||
extends TerminalTest
|
extends TerminalTest
|
||||||
|
|
||||||
func test_returns_response_when_input_contains_query():
|
func test_returns_response_when_input_contains_query():
|
||||||
var response = terminal.write("\u001b[6n") # Query cursor position.
|
var response = subject.write("\u001b[6n") # Query cursor position.
|
||||||
assert_eq(response, "\u001b[1;1R")
|
assert_eq(response, "\u001b[1;1R")
|
||||||
|
|
||||||
func test_returns_response_to_multiple_queries():
|
func test_returns_response_to_multiple_queries():
|
||||||
var response = terminal.write("\u001b[6n\u001b[5n") # Query cursor position and status.
|
var response = subject.write("\u001b[6n\u001b[5n") # Query cursor position and status.
|
||||||
assert_eq(response, "\u001b[1;1R\u001b[0n")
|
assert_eq(response, "\u001b[1;1R\u001b[0n")
|
||||||
|
|
||||||
func test_returns_response_to_multiple_queries_among_other_data():
|
func test_returns_response_to_multiple_queries_among_other_data():
|
||||||
var response = terminal.write("hello\r\nworld\u001b[6nother\r\ndata\u001b[5ntest")
|
var response = subject.write("hello\r\nworld\u001b[6nother\r\ndata\u001b[5ntest")
|
||||||
assert_eq(response, "\u001b[2;6R\u001b[0n")
|
assert_eq(response, "\u001b[2;6R\u001b[0n")
|
||||||
|
|
||||||
func test_data_sent_emitted_on_query():
|
func test_data_sent_emitted_on_query():
|
||||||
terminal.write("\u001b[6n")
|
subject.write("\u001b[6n")
|
||||||
assert_signal_emitted(terminal, "data_sent")
|
assert_signal_emitted(subject, "data_sent")
|
||||||
|
|
||||||
func test_data_sent_emitted_with_response():
|
func test_data_sent_emitted_with_response():
|
||||||
terminal.write("\u001b[6n")
|
subject.write("\u001b[6n")
|
||||||
assert_signal_emitted_with_parameters(
|
assert_signal_emitted_with_parameters(
|
||||||
terminal, "data_sent", ["\u001b[1;1R".to_utf8_buffer()]
|
subject, "data_sent", ["\u001b[1;1R".to_utf8_buffer()]
|
||||||
)
|
)
|
||||||
|
|
||||||
func test_data_sent_not_emitted_when_empty_string_written():
|
func test_data_sent_not_emitted_when_empty_string_written():
|
||||||
terminal.write("")
|
subject.write("")
|
||||||
assert_signal_emit_count(terminal, "data_sent", 0)
|
assert_signal_emit_count(subject, "data_sent", 0)
|
||||||
|
|
Loading…
Reference in a new issue