mirror of
https://github.com/lihop/godot-xterm.git
synced 2024-11-10 04:40:25 +01:00
d00a31fb45
Clears all but the bottommost row of the terminal (including scrollback buffer) and moves the bottommost row to the top.
242 lines
6.6 KiB
GDScript
242 lines
6.6 KiB
GDScript
# SPDX-FileCopyrightText: 2021-2024 Leroy Hopson <godot-xterm@leroy.nix.nz>
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
class_name TerminalTest extends GodotXtermTest
|
|
|
|
|
|
func get_described_class():
|
|
return Terminal
|
|
|
|
|
|
func before_each():
|
|
super.before_each()
|
|
subject.size = Vector2(400, 200)
|
|
|
|
|
|
# Helper function to fill the screen with the given character.
|
|
func fill_screen(char: String = "A") -> String:
|
|
var result = char.repeat(subject.get_cols() * subject.get_rows())
|
|
subject.write(result)
|
|
return result
|
|
|
|
|
|
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)
|
|
|
|
func test_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.
|
|
|
|
func test_has_method_clear():
|
|
assert_has_method_with_return_type("clear", TYPE_NIL)
|
|
|
|
func test_has_method_copy_all():
|
|
assert_has_method_with_return_type("copy_all", TYPE_STRING)
|
|
|
|
func test_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 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:
|
|
extends TerminalTest
|
|
|
|
func test_bell() -> void:
|
|
watch_signals(subject)
|
|
subject.bell_cooldown = 0
|
|
subject.write(char(7))
|
|
subject.write(char(0x07))
|
|
subject.write("\a")
|
|
subject.write("\u0007")
|
|
subject.write("'Ask not for whom the \a tolls; it tolls for thee' - John Donne")
|
|
assert_signal_emit_count(subject, "bell", 5)
|
|
|
|
func test_bell_mute() -> void:
|
|
watch_signals(subject)
|
|
subject.bell_muted = true
|
|
subject.write("\a")
|
|
assert_signal_emit_count(subject, "bell", 0)
|
|
|
|
func test_bell_cooldown() -> void:
|
|
watch_signals(subject)
|
|
subject.bell_cooldown = 10000
|
|
subject.write("\a")
|
|
subject.write("\a")
|
|
assert_signal_emit_count(subject, "bell", 1)
|
|
|
|
func test_change_cooldown_while_active() -> void:
|
|
watch_signals(subject)
|
|
subject.bell_cooldown = 10000
|
|
subject.write("\a")
|
|
subject.bell_cooldown = 0
|
|
subject.write("\a")
|
|
assert_signal_emit_count(subject, "bell", 2)
|
|
|
|
|
|
class TestCursorPos:
|
|
extends TerminalTest
|
|
|
|
func test_get_cursor_pos_initial():
|
|
assert_eq(subject.get_cursor_pos(), Vector2i.ZERO)
|
|
|
|
func test_get_cursor_pos_x():
|
|
subject.write("_")
|
|
assert_eq(subject.get_cursor_pos().x, 1)
|
|
|
|
func test_get_cursor_pos_y():
|
|
subject.write("_".repeat(subject.cols + 1))
|
|
assert_eq(subject.get_cursor_pos().y, 1)
|
|
|
|
|
|
class TestWrite:
|
|
extends TerminalTest
|
|
|
|
func test_returns_response_when_input_contains_query():
|
|
var response = subject.write("\u001b[6n") # Query cursor position.
|
|
assert_eq(response, "\u001b[1;1R")
|
|
|
|
func test_returns_response_to_multiple_queries():
|
|
var response = subject.write("\u001b[6n\u001b[5n") # Query cursor position and status.
|
|
assert_eq(response, "\u001b[1;1R\u001b[0n")
|
|
|
|
func test_returns_response_to_multiple_queries_among_other_data():
|
|
var response = subject.write("hello\r\nworld\u001b[6nother\r\ndata\u001b[5ntest")
|
|
assert_eq(response, "\u001b[2;6R\u001b[0n")
|
|
|
|
func test_data_sent_emitted_on_query():
|
|
subject.write("\u001b[6n")
|
|
assert_signal_emitted(subject, "data_sent")
|
|
|
|
func test_data_sent_emitted_with_response():
|
|
subject.write("\u001b[6n")
|
|
assert_signal_emitted_with_parameters(
|
|
subject, "data_sent", ["\u001b[1;1R".to_utf8_buffer()]
|
|
)
|
|
|
|
func test_data_sent_not_emitted_when_empty_string_written():
|
|
subject.write("")
|
|
assert_signal_emit_count(subject, "data_sent", 0)
|
|
|
|
|
|
class TestCopy:
|
|
extends TerminalTest
|
|
|
|
func test_copy_all_copies_the_entire_screen():
|
|
var text = fill_screen()
|
|
# The text will be wrapped over multiple lines and copy_all() preserves
|
|
# these line wraps, therefore we need to strip them.
|
|
assert_eq(subject.copy_all().replace("\n", ""), text)
|
|
|
|
func test_copy_all_empty_screen():
|
|
assert_eq(subject.copy_all(), "\n".repeat(subject.get_rows()))
|
|
|
|
func test_copy_all_copies_the_scrollback_buffer():
|
|
var text = fill_screen()
|
|
text += fill_screen("B")
|
|
text += fill_screen("C")
|
|
assert_eq(subject.copy_all().replace("\n", ""), text)
|
|
|
|
func test_copy_all_copies_unicode_text():
|
|
var text = "アイウエオカキクケコサシスセソ"
|
|
subject.write(text)
|
|
assert_string_contains(subject.copy_all(), text)
|
|
|
|
|
|
class TestClear:
|
|
extends TerminalTest
|
|
|
|
func test_clear_an_empty_screen_changes_nothing():
|
|
var empty_screen = subject.copy_all()
|
|
subject.clear()
|
|
var screen_after = subject.copy_all()
|
|
assert_eq(screen_after, empty_screen)
|
|
|
|
func test_clear_when_screen_is_full_clears_all_but_the_bottommost_row():
|
|
fill_screen()
|
|
var final_line = "THIS SHOULDN'T BE CLEARED"
|
|
subject.write(final_line)
|
|
subject.clear()
|
|
var screen_after = subject.copy_all()
|
|
var expected = final_line + "\n".repeat(subject.get_rows())
|
|
assert_eq(screen_after, expected)
|