diff --git a/http_transport.gd b/http_transport.gd index 32589a0..d497b10 100644 --- a/http_transport.gd +++ b/http_transport.gd @@ -12,31 +12,31 @@ var _owner: Node func _init(owner: Node) -> void: - _owner = owner + _owner = owner ## Requests [param url] and calls [param on_complete] with ## [code](response_code: int, body: PackedByteArray)[/code]. Connection errors and ## timeouts are reported with response code 0. func request(url: String, method: int, on_complete: Callable) -> void: - var http_request: HTTPRequest = HTTPRequest.new() - http_request.timeout = timeout_seconds - _owner.add_child(http_request) - http_request.request_completed.connect( - func( - result: int, - response_code: int, - _headers: PackedStringArray, - body: PackedByteArray, - ) -> void: - http_request.queue_free() - on_complete.call(response_code if result == HTTPRequest.RESULT_SUCCESS else 0, body) - ) - var headers: PackedStringArray = [] - if method == HTTPClient.METHOD_PUT: - headers.append("Content-Type: application/json") - var error: int = http_request.request(url, headers, method) - if error != OK: - http_request.queue_free() - push_error("Could not send request to %s (error %d)" % [url, error]) - on_complete.call(0, PackedByteArray()) + var http_request: HTTPRequest = HTTPRequest.new() + http_request.timeout = timeout_seconds + _owner.add_child(http_request) + http_request.request_completed.connect( + func( + result: int, + response_code: int, + _headers: PackedStringArray, + body: PackedByteArray, + ) -> void: + http_request.queue_free() + on_complete.call(response_code if result == HTTPRequest.RESULT_SUCCESS else 0, body) + ) + var headers: PackedStringArray = [] + if method == HTTPClient.METHOD_PUT: + headers.append("Content-Type: application/json") + var error: int = http_request.request(url, headers, method) + if error != OK: + http_request.queue_free() + push_error("Could not send request to %s (error %d)" % [url, error]) + on_complete.call(0, PackedByteArray()) diff --git a/inspiration_list.gd b/inspiration_list.gd index 3ad9a4a..5de3937 100644 --- a/inspiration_list.gd +++ b/inspiration_list.gd @@ -14,54 +14,54 @@ var _rows: VBoxContainer = $VBoxContainer # Called when the node enters the scene tree for the first time. func _ready() -> void: - scroll_direction = 1 + scroll_direction = 1 # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: - var speed_pixels_per_second: float = float(Settings.inspiration_list_speed) * 60.0 - var scroll_amount: float = speed_pixels_per_second * delta * float(scroll_direction) + var speed_pixels_per_second: float = float(Settings.inspiration_list_speed) * 60.0 + var scroll_amount: float = speed_pixels_per_second * delta * float(scroll_direction) - var scroll_bar = get_v_scroll_bar() + var scroll_bar = get_v_scroll_bar() - # Don't scroll if list is empty or too short - if scroll_bar.max_value <= 0: - return + # Don't scroll if list is empty or too short + if scroll_bar.max_value <= 0: + return - var current_pos = scroll_bar.value + var current_pos = scroll_bar.value - if scroll_direction == 1: - # Scrolling down - if current_pos + scroll_bar.page < scroll_bar.max_value: - scroll_bar.value = min(current_pos + scroll_amount, scroll_bar.max_value - scroll_bar.page) - else: - # Reached bottom, reverse direction - scroll_direction = -1 - scroll_bar.value = scroll_bar.max_value - scroll_bar.page - else: - # Scrolling up - if current_pos > 0: - scroll_bar.value = max(current_pos + scroll_amount, 0) - else: - # Reached top, reverse direction - scroll_direction = 1 - scroll_bar.value = 0 + if scroll_direction == 1: + # Scrolling down + if current_pos + scroll_bar.page < scroll_bar.max_value: + scroll_bar.value = min(current_pos + scroll_amount, scroll_bar.max_value - scroll_bar.page) + else: + # Reached bottom, reverse direction + scroll_direction = -1 + scroll_bar.value = scroll_bar.max_value - scroll_bar.page + else: + # Scrolling up + if current_pos > 0: + scroll_bar.value = max(current_pos + scroll_amount, 0) + else: + # Reached top, reverse direction + scroll_direction = 1 + scroll_bar.value = 0 ## Fetches every soundtrack from the server and shows them. func load_from_server() -> void: - print("load_from_server") - var populate_list: Callable = func populate_list(array) -> void: - if typeof(array) == TYPE_ARRAY: - show_soundtracks(array) - else: - print("Unexpected data") - MusicServerClient.fetch_all_soundtracks(populate_list) + print("load_from_server") + var populate_list: Callable = func populate_list(array) -> void: + if typeof(array) == TYPE_ARRAY: + show_soundtracks(array) + else: + print("Unexpected data") + MusicServerClient.fetch_all_soundtracks(populate_list) ## Shows [param list] instead of the soundtracks shown now. func show_soundtracks(list: Array) -> void: - soundtracks = [] - soundtracks.append_array(list) - Settings.delete_children(_rows) - for i: int in soundtracks.size(): - _rows.add_child(ListRow.create(soundtracks[i], i, 20)) + soundtracks = [] + soundtracks.append_array(list) + Settings.delete_children(_rows) + for i: int in soundtracks.size(): + _rows.add_child(ListRow.create(soundtracks[i], i, 20)) diff --git a/linux/render_icon.gd b/linux/render_icon.gd index ceab257..de961c7 100644 --- a/linux/render_icon.gd +++ b/linux/render_icon.gd @@ -5,20 +5,20 @@ extends SceneTree func _initialize() -> void: - var args: PackedStringArray = OS.get_cmdline_user_args() - if args.size() != 3: - printerr("Usage: godot --headless -s render_icon.gd -- ") - quit(1) - return - var svg: String = FileAccess.get_file_as_string(args[0]) - var source: Image = Image.new() - # Load at 1x to read the SVG's own size, then scale so the result is pixels - var error: int = source.load_svg_from_string(svg) - if error == OK: - var image: Image = Image.new() - error = image.load_svg_from_string(svg, float(args[2]) / source.get_width()) - if error == OK: - error = image.save_png(args[1]) - if error != OK: - printerr("Could not render %s to %s (error %d)" % [args[0], args[1], error]) - quit(error) + var args: PackedStringArray = OS.get_cmdline_user_args() + if args.size() != 3: + printerr("Usage: godot --headless -s render_icon.gd -- ") + quit(1) + return + var svg: String = FileAccess.get_file_as_string(args[0]) + var source: Image = Image.new() + # Load at 1x to read the SVG's own size, then scale so the result is pixels + var error: int = source.load_svg_from_string(svg) + if error == OK: + var image: Image = Image.new() + error = image.load_svg_from_string(svg, float(args[2]) / source.get_width()) + if error == OK: + error = image.save_png(args[1]) + if error != OK: + printerr("Could not render %s to %s (error %d)" % [args[0], args[1], error]) + quit(error) diff --git a/list_row.gd b/list_row.gd index c9fd8eb..a201fdd 100644 --- a/list_row.gd +++ b/list_row.gd @@ -16,42 +16,42 @@ var label: Label ## The item's text. var text: String: - get: - return label.text + get: + return label.text ## Creates the row for item number [param row] (counting from 0) in a list. static func create( - item_text: String, - row: int, - font_size: int, - alignment: HorizontalAlignment = HORIZONTAL_ALIGNMENT_LEFT, + item_text: String, + row: int, + font_size: int, + alignment: HorizontalAlignment = HORIZONTAL_ALIGNMENT_LEFT, ) -> ListRow: - var list_row: ListRow = ListRow.new() - list_row.add_theme_stylebox_override("panel", _style(row % 2 != 0)) - list_row.label = Label.new() - list_row.label.add_theme_font_size_override("font_size", font_size) - list_row.label.text = item_text - list_row.label.horizontal_alignment = alignment - list_row.label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART - list_row.add_child(list_row.label) - return list_row + var list_row: ListRow = ListRow.new() + list_row.add_theme_stylebox_override("panel", _style(row % 2 != 0)) + list_row.label = Label.new() + list_row.label.add_theme_font_size_override("font_size", font_size) + list_row.label.text = item_text + list_row.label.horizontal_alignment = alignment + list_row.label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + list_row.add_child(list_row.label) + return list_row # Rows share two styles instead of each creating its own static func _style(odd: bool) -> StyleBoxFlat: - if _even_style == null: - _even_style = _make_style(EVEN_BACKGROUND) - _odd_style = _make_style(ODD_BACKGROUND) - return _odd_style if odd else _even_style + if _even_style == null: + _even_style = _make_style(EVEN_BACKGROUND) + _odd_style = _make_style(ODD_BACKGROUND) + return _odd_style if odd else _even_style static func _make_style(background: Color) -> StyleBoxFlat: - var style: StyleBoxFlat = StyleBoxFlat.new() - style.bg_color = background - style.set_corner_radius_all(4) - style.content_margin_left = 8 - style.content_margin_right = 8 - style.content_margin_top = 2 - style.content_margin_bottom = 2 - return style + var style: StyleBoxFlat = StyleBoxFlat.new() + style.bg_color = background + style.set_corner_radius_all(4) + style.content_margin_left = 8 + style.content_margin_right = 8 + style.content_margin_top = 2 + style.content_margin_bottom = 2 + return style diff --git a/music_list_panel.gd b/music_list_panel.gd index fdb0687..22112e6 100644 --- a/music_list_panel.gd +++ b/music_list_panel.gd @@ -13,14 +13,14 @@ var _rows: VBoxContainer = $ScrollContainer/MusicList ## Shows the songs in the playlist again, so it shows their latest state. func refresh() -> void: - Settings.delete_children(_rows) - for s: SongObject in Playlist.get_playlist(): - var new_song_list_object: SongListObject = _song_list_object.instantiate() - new_song_list_object.song_object = s - new_song_list_object.gui_input.connect(_on_row_input.bind(s.song_number)) - _rows.add_child(new_song_list_object) + Settings.delete_children(_rows) + for s: SongObject in Playlist.get_playlist(): + var new_song_list_object: SongListObject = _song_list_object.instantiate() + new_song_list_object.song_object = s + new_song_list_object.gui_input.connect(_on_row_input.bind(s.song_number)) + _rows.add_child(new_song_list_object) func _on_row_input(event: InputEvent, song_no: int) -> void: - if event is InputEventMouseButton && event.pressed && event.button_index == MOUSE_BUTTON_LEFT: - song_clicked.emit(song_no) + if event is InputEventMouseButton && event.pressed && event.button_index == MOUSE_BUTTON_LEFT: + song_clicked.emit(song_no) diff --git a/music_server_client.gd b/music_server_client.gd index b3285b4..73fdc51 100644 --- a/music_server_client.gd +++ b/music_server_client.gd @@ -11,129 +11,129 @@ var transport: HttpTransport func _ready() -> void: - if transport == null: - transport = HttpTransport.new(self) + if transport == null: + transport = HttpTransport.new(self) ## Fetches the songs already in the server playlist, as an Array of ## [code]{SongNo, Soundtrack, Song}[/code] dictionaries. func fetch_song_list(on_done: Callable, on_failed: Callable = Callable()) -> void: - get_json("/music/list", on_done, on_failed) + get_json("/music/list", on_done, on_failed) ## Downloads a random song as MP3 bytes. With [param low_played] the server prefers ## soundtracks that have been played the least. func fetch_random_song( - low_played: bool, on_done: Callable, on_failed: Callable = Callable()) -> void: - get_bytes("/music/rand/low" if low_played else "/music/rand", on_done, on_failed) + low_played: bool, on_done: Callable, on_failed: Callable = Callable()) -> void: + get_bytes("/music/rand/low" if low_played else "/music/rand", on_done, on_failed) ## Adds the most recently fetched random song to the server playlist. func add_to_queue(on_done: Callable, on_failed: Callable = Callable()) -> void: - send("/music/addQue", on_done, on_failed) + send("/music/addQue", on_done, on_failed) ## Fetches [code]{SongNo, Soundtrack, Song}[/code] for the most recently queued song. func fetch_song_info(on_done: Callable, on_failed: Callable = Callable()) -> void: - get_json("/music/info", on_done, on_failed) + get_json("/music/info", on_done, on_failed) ## Downloads a song from the server playlist as MP3 bytes. func fetch_song(song_no: int, on_done: Callable, on_failed: Callable = Callable()) -> void: - get_bytes("/music?song=" + str(song_no), on_done, on_failed) + get_bytes("/music?song=" + str(song_no), on_done, on_failed) ## Downloads the sound test song as MP3 bytes. func fetch_sound_test_song(on_done: Callable, on_failed: Callable = Callable()) -> void: - get_bytes("/music/soundTest", on_done, on_failed) + get_bytes("/music/soundTest", on_done, on_failed) ## Clears the server playlist. func reset_playlist(on_done: Callable, on_failed: Callable = Callable()) -> void: - send("/music/reset", on_done, on_failed) + send("/music/reset", on_done, on_failed) ## Fetches every soundtrack name as an Array of Strings. func fetch_all_soundtracks(on_done: Callable, on_failed: Callable = Callable()) -> void: - get_json("/music/all", on_done, on_failed) + get_json("/music/all", on_done, on_failed) ## Fetches every soundtrack name, sorted, as an Array of Strings. func fetch_all_soundtracks_ordered(on_done: Callable, on_failed: Callable = Callable()) -> void: - get_json("/music/all/order", on_done, on_failed) + get_json("/music/all/order", on_done, on_failed) ## Records in the server statistics that a song has been played. func mark_song_played(song_no: int) -> void: - send("/music/played?song=" + str(song_no), Callable(), Callable(), HTTPClient.METHOD_PUT) + send("/music/played?song=" + str(song_no), Callable(), Callable(), HTTPClient.METHOD_PUT) ## Fetches the names of all character images. func fetch_character_list(on_done: Callable, on_failed: Callable = Callable()) -> void: - get_json("/characters", on_done, on_failed) + get_json("/characters", on_done, on_failed) ## Downloads a character image as PNG bytes. func fetch_character_image( - character_name: String, on_done: Callable, on_failed: Callable = Callable()) -> void: - get_bytes("/character?name=" + character_name.uri_encode(), on_done, on_failed) + character_name: String, on_done: Callable, on_failed: Callable = Callable()) -> void: + get_bytes("/character?name=" + character_name.uri_encode(), on_done, on_failed) ## Starts syncing the server's soundtrack library with its music folder. func start_sync(on_done: Callable, on_failed: Callable = Callable()) -> void: - send("/sync", on_done, on_failed) + send("/sync", on_done, on_failed) ## Fetches the sync state: [code]{progress, time_spent}[/code] while running, or the ## sync result once finished. func fetch_sync_progress(on_done: Callable, on_failed: Callable = Callable()) -> void: - get_json("/sync/progress", on_done, on_failed) + get_json("/sync/progress", on_done, on_failed) ## Requests [param path] and calls [param on_done] with the parsed JSON. ## [param on_failed] is called with no arguments if the request fails or the body is ## not valid JSON. func get_json(path: String, on_done: Callable, on_failed: Callable = Callable()) -> void: - _request(path, HTTPClient.METHOD_GET, func(body: PackedByteArray) -> void: - var json: JSON = JSON.new() - if json.parse(body.get_string_from_utf8()) != OK: - push_warning("Invalid JSON from %s: %s" % [path, json.get_error_message()]) - _call_if_valid(on_failed) - return - on_done.call(json.data) - , on_failed) + _request(path, HTTPClient.METHOD_GET, func(body: PackedByteArray) -> void: + var json: JSON = JSON.new() + if json.parse(body.get_string_from_utf8()) != OK: + push_warning("Invalid JSON from %s: %s" % [path, json.get_error_message()]) + _call_if_valid(on_failed) + return + on_done.call(json.data) + , on_failed) ## Requests [param path] and calls [param on_done] with the raw response body, or ## [param on_failed] with no arguments if the request fails. func get_bytes(path: String, on_done: Callable, on_failed: Callable = Callable()) -> void: - _request(path, HTTPClient.METHOD_GET, on_done, on_failed) + _request(path, HTTPClient.METHOD_GET, on_done, on_failed) ## Requests [param path] and calls [param on_done] with no arguments when it succeeds, ## or [param on_failed] when it fails. Either may be an empty Callable. func send( - path: String, - on_done: Callable, - on_failed: Callable = Callable(), - method: int = HTTPClient.METHOD_GET, + path: String, + on_done: Callable, + on_failed: Callable = Callable(), + method: int = HTTPClient.METHOD_GET, ) -> void: - _request(path, method, func(_body: PackedByteArray) -> void: - _call_if_valid(on_done) - , on_failed) + _request(path, method, func(_body: PackedByteArray) -> void: + _call_if_valid(on_done) + , on_failed) func _request(path: String, method: int, on_success: Callable, on_failed: Callable) -> void: - var url: String = Settings.default_path + path - transport.request(url, method, func(response_code: int, body: PackedByteArray) -> void: - if response_code != 200: - push_warning("Request to %s failed with response code %d" % [url, response_code]) - _call_if_valid(on_failed) - return - on_success.call(body) - ) + var url: String = Settings.default_path + path + transport.request(url, method, func(response_code: int, body: PackedByteArray) -> void: + if response_code != 200: + push_warning("Request to %s failed with response code %d" % [url, response_code]) + _call_if_valid(on_failed) + return + on_success.call(body) + ) static func _call_if_valid(callback: Callable) -> void: - if callback.is_valid(): - callback.call() + if callback.is_valid(): + callback.call() diff --git a/players_panel.gd b/players_panel.gd index 96a51e1..363b50a 100644 --- a/players_panel.gd +++ b/players_panel.gd @@ -34,57 +34,57 @@ var players_list_container: VBoxContainer = $VBoxContainer/ScrollContainer/Playe func _ready() -> void: - add_players_button.pressed.connect(add_players) - add_player_button.pressed.connect(add_player) - new_player_name_field.connect("enter_key_pressed", add_player) + add_players_button.pressed.connect(add_players) + add_player_button.pressed.connect(add_player) + new_player_name_field.connect("enter_key_pressed", add_player) ## Shows or hides the row for adding players, and the buttons for removing them. func add_players() -> void: - print("add_players") - Settings.edit_players = !Settings.edit_players - add_player_container.visible = !add_player_container.visible - new_player_name_field.grab_focus() + print("add_players") + Settings.edit_players = !Settings.edit_players + add_player_container.visible = !add_player_container.visible + new_player_name_field.grab_focus() ## Adds a player with the name in the name field, unless it is empty or there are ## already as many players as there can be. func add_player() -> void: - print("add_player") - if new_player_name_field.text != "" && Settings.player_array.size() < Settings.MAX_NUMBER_OF_PLAYERS: - var new_player_object: PlayerObject = PlayerObject.new(new_player_name_field.text) - new_player_name_field.text = "" - Settings.player_array.append(new_player_object) - player_added.emit(new_player_object) - reload() + print("add_player") + if new_player_name_field.text != "" && Settings.player_array.size() < Settings.MAX_NUMBER_OF_PLAYERS: + var new_player_object: PlayerObject = PlayerObject.new(new_player_name_field.text) + new_player_name_field.text = "" + Settings.player_array.append(new_player_object) + player_added.emit(new_player_object) + reload() ## Shows the players in [code]Settings.player_array[/code] again, e.g. after their ## points were reset. func reload() -> void: - print("load_players") - Settings.delete_children(players_list_container) - var counter: int = 0 - for player_object: PlayerObject in Settings.player_array: - print(player_object.player_name) + print("load_players") + Settings.delete_children(players_list_container) + var counter: int = 0 + for player_object: PlayerObject in Settings.player_array: + print(player_object.player_name) - var new_player: Player = _player_row.instantiate() - new_player.player_object = player_object - new_player.list_index = counter + var new_player: Player = _player_row.instantiate() + new_player.player_object = player_object + new_player.list_index = counter - new_player.connect("change_character_clicked", _on_change_character_clicked.bind(new_player, player_object.player_name)) - new_player.connect("player_removed", _on_player_removed.bind(player_object)) + new_player.connect("change_character_clicked", _on_change_character_clicked.bind(new_player, player_object.player_name)) + new_player.connect("player_removed", _on_player_removed.bind(player_object)) - players_list_container.add_child(new_player) - counter += 1 + players_list_container.add_child(new_player) + counter += 1 func _on_change_character_clicked(row: Player, player_name: String) -> void: - change_character_requested.emit(row, player_name) + change_character_requested.emit(row, player_name) func _on_player_removed(player_object: PlayerObject) -> void: - print("_on_player_removed ", player_object.player_name) - Settings.player_array.erase(player_object) - reload() - player_removed.emit(player_object) + print("_on_player_removed ", player_object.player_name) + Settings.player_array.erase(player_object) + reload() + player_removed.emit(player_object) diff --git a/popup_backdrop.gd b/popup_backdrop.gd index 54f9a5d..4b1d444 100644 --- a/popup_backdrop.gd +++ b/popup_backdrop.gd @@ -13,19 +13,19 @@ var _popups: Array[PopupWindow] = [] ## Adds a backdrop to [param parent] and moves [param popups] above it. The backdrop ## shows while any of them is open. static func add_to(parent: Control, popups: Array[PopupWindow]) -> PopupBackdrop: - var backdrop: PopupBackdrop = PopupBackdrop.new() - backdrop.name = "PopupBackdrop" - backdrop.color = Color(0, 0, 0, 0.55) - backdrop.mouse_filter = Control.MOUSE_FILTER_STOP - backdrop._popups = popups - parent.add_child(backdrop) - backdrop.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) - for popup: PopupWindow in popups: - parent.move_child(popup, -1) - popup.visibility_changed.connect(backdrop._update) - backdrop._update() - return backdrop + var backdrop: PopupBackdrop = PopupBackdrop.new() + backdrop.name = "PopupBackdrop" + backdrop.color = Color(0, 0, 0, 0.55) + backdrop.mouse_filter = Control.MOUSE_FILTER_STOP + backdrop._popups = popups + parent.add_child(backdrop) + backdrop.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + for popup: PopupWindow in popups: + parent.move_child(popup, -1) + popup.visibility_changed.connect(backdrop._update) + backdrop._update() + return backdrop func _update() -> void: - visible = _popups.any(func(popup: PopupWindow) -> bool: return popup.visible) + visible = _popups.any(func(popup: PopupWindow) -> bool: return popup.visible) diff --git a/popup_window.gd b/popup_window.gd index 46698e3..fc85af6 100644 --- a/popup_window.gd +++ b/popup_window.gd @@ -11,27 +11,27 @@ extends Control ## Shows the popup. func open() -> void: - visible = true + visible = true ## Hides the popup. func close() -> void: - visible = false + visible = false ## Opens the popup if it is closed and closes it if it is open. func toggle() -> void: - if visible: - close() - else: - open() + if visible: + close() + else: + open() func _input(event: InputEvent) -> void: - if !visible || !(event is InputEventMouseButton) || !event.pressed: - return - var click: InputEventMouseButton = panel.make_input_local(event) - if !Rect2(Vector2.ZERO, panel.size).has_point(click.position): - close() - # The click only closes the popup; it must not also press what is behind it - get_viewport().set_input_as_handled() + if !visible || !(event is InputEventMouseButton) || !event.pressed: + return + var click: InputEventMouseButton = panel.make_input_local(event) + if !Rect2(Vector2.ZERO, panel.size).has_point(click.position): + close() + # The click only closes the popup; it must not also press what is behind it + get_viewport().set_input_as_handled() diff --git a/tests/fakes/autoload_snapshot.gd b/tests/fakes/autoload_snapshot.gd index 161f59d..341992c 100644 --- a/tests/fakes/autoload_snapshot.gd +++ b/tests/fakes/autoload_snapshot.gd @@ -8,20 +8,20 @@ var _values: Dictionary = {} ## Records the current values of every script variable on [param autoloads]. static func take(autoloads: Array[Node]) -> AutoloadSnapshot: - var snapshot: AutoloadSnapshot = AutoloadSnapshot.new() - for autoload: Node in autoloads: - var values: Dictionary = {} - for property: Dictionary in autoload.get_property_list(): - if property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE: - var value: Variant = autoload.get(property.name) - values[property.name] = value.duplicate() if value is Array else value - snapshot._values[autoload] = values - return snapshot + var snapshot: AutoloadSnapshot = AutoloadSnapshot.new() + for autoload: Node in autoloads: + var values: Dictionary = {} + for property: Dictionary in autoload.get_property_list(): + if property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE: + var value: Variant = autoload.get(property.name) + values[property.name] = value.duplicate() if value is Array else value + snapshot._values[autoload] = values + return snapshot ## Puts back the values recorded by [method take]. func restore() -> void: - for autoload: Node in _values: - var values: Dictionary = _values[autoload] - for property_name: String in values: - autoload.set(property_name, values[property_name]) + for autoload: Node in _values: + var values: Dictionary = _values[autoload] + for property_name: String in values: + autoload.set(property_name, values[property_name]) diff --git a/tests/fakes/fake_http_transport.gd b/tests/fakes/fake_http_transport.gd index 3cbf698..0686c43 100644 --- a/tests/fakes/fake_http_transport.gd +++ b/tests/fakes/fake_http_transport.gd @@ -18,74 +18,74 @@ var _previous_transport: HttpTransport func _init() -> void: - super(null) + super(null) ## Replaces the MusicServerClient transport with this fake. func install() -> FakeHttpTransport: - _previous_transport = MusicServerClient.transport - MusicServerClient.transport = self - return self + _previous_transport = MusicServerClient.transport + MusicServerClient.transport = self + return self ## Restores the transport that was active before [method install]. func uninstall() -> void: - MusicServerClient.transport = _previous_transport + MusicServerClient.transport = _previous_transport ## Answers requests to [param path] with [param data] encoded as JSON. func respond_json(path: String, data: Variant, response_code: int = 200) -> void: - respond_bytes(path, JSON.stringify(data).to_utf8_buffer(), response_code) + respond_bytes(path, JSON.stringify(data).to_utf8_buffer(), response_code) ## Answers requests to [param path] with [param body] as-is. func respond_bytes(path: String, body: PackedByteArray, response_code: int = 200) -> void: - _responses[path] = {"code": response_code, "body": body} - _successes_left.erase(path) + _responses[path] = {"code": response_code, "body": body} + _successes_left.erase(path) ## Lets [param successes] more requests to [param path] succeed, then answers 503 until ## a new response is registered for the path. func fail_after(path: String, successes: int) -> void: - _successes_left[path] = successes + _successes_left[path] = successes ## Holds back responses to [param path] until [method release] is called, like a slow ## server. func hold(path: String) -> void: - _held_paths[path] = [] + _held_paths[path] = [] ## Delivers the responses held back for [param path] and stops holding it. func release(path: String) -> void: - var waiting: Array = _held_paths.get(path, []) - _held_paths.erase(path) - for pending: Callable in waiting: - pending.call() + var waiting: Array = _held_paths.get(path, []) + _held_paths.erase(path) + for pending: Callable in waiting: + pending.call() ## Returns how many times [param path] has been requested. func count(path: String) -> int: - return requested_paths.count(path) + return requested_paths.count(path) func request(url: String, method: int, on_complete: Callable) -> void: - var path: String = url.trim_prefix(Settings.default_path) - requested_paths.append(path) - requested_methods.append(method) - if _held_paths.has(path): - _held_paths[path].append(_answer.bind(path, on_complete)) - return - _answer(path, on_complete) + var path: String = url.trim_prefix(Settings.default_path) + requested_paths.append(path) + requested_methods.append(method) + if _held_paths.has(path): + _held_paths[path].append(_answer.bind(path, on_complete)) + return + _answer(path, on_complete) func _answer(path: String, on_complete: Callable) -> void: - if _successes_left.has(path): - if _successes_left[path] == 0: - on_complete.call(503, PackedByteArray()) - return - _successes_left[path] -= 1 - if _responses.has(path): - on_complete.call(_responses[path].code, _responses[path].body) - else: - on_complete.call(404, PackedByteArray()) + if _successes_left.has(path): + if _successes_left[path] == 0: + on_complete.call(503, PackedByteArray()) + return + _successes_left[path] -= 1 + if _responses.has(path): + on_complete.call(_responses[path].code, _responses[path].body) + else: + on_complete.call(404, PackedByteArray()) diff --git a/tests/fakes/main_window_test_suite.gd b/tests/fakes/main_window_test_suite.gd index 2c4b792..f3c85c6 100644 --- a/tests/fakes/main_window_test_suite.gd +++ b/tests/fakes/main_window_test_suite.gd @@ -3,8 +3,8 @@ extends GdUnitTestSuite ## Base for tests that run the real main window against a fake MusicServer. const SONG_INFO: Array[Dictionary] = [ - {"SongNo": 0, "Soundtrack": "Chrono Trigger", "Song": "Corridors of Time"}, - {"SongNo": 1, "Soundtrack": "Final Fantasy VI", "Song": "Dancing Mad"}, + {"SongNo": 0, "Soundtrack": "Chrono Trigger", "Song": "Corridors of Time"}, + {"SongNo": 1, "Soundtrack": "Final Fantasy VI", "Song": "Dancing Mad"}, ] var _server: FakeHttpTransport @@ -15,120 +15,120 @@ var _quiz: Quiz func before_test() -> void: - _snapshot = AutoloadSnapshot.take([Settings, Playlist]) - Playlist.reset_playlist() - Playlist.first_song_played = false - Playlist.is_song_downloading = false - Settings.player_array.clear() - Settings.add_to_stats = true - Settings.hide_next_track = true - Settings.use_low_played_mode = false - Settings.winning_score = 20 + _snapshot = AutoloadSnapshot.take([Settings, Playlist]) + Playlist.reset_playlist() + Playlist.first_song_played = false + Playlist.is_song_downloading = false + Settings.player_array.clear() + Settings.add_to_stats = true + Settings.hide_next_track = true + Settings.use_low_played_mode = false + Settings.winning_score = 20 - _server = FakeHttpTransport.new().install() - var mp3: PackedByteArray = FileAccess.get_file_as_bytes("res://tests/data/short.mp3") - _server.respond_json("/music/all", ["Chrono Trigger", "Final Fantasy VI"]) - _server.respond_json("/music/all/order", ["Chrono Trigger", "Final Fantasy VI"]) - _server.respond_json("/music/list", []) - _server.respond_json("/characters", []) - _server.respond_bytes("/music/rand", mp3) - _server.respond_bytes("/music/addQue", PackedByteArray()) - _server.respond_json("/music/info", SONG_INFO[0]) - _server.respond_bytes("/music/reset", PackedByteArray()) - _server.respond_bytes("/music/played?song=0", PackedByteArray()) + _server = FakeHttpTransport.new().install() + var mp3: PackedByteArray = FileAccess.get_file_as_bytes("res://tests/data/short.mp3") + _server.respond_json("/music/all", ["Chrono Trigger", "Final Fantasy VI"]) + _server.respond_json("/music/all/order", ["Chrono Trigger", "Final Fantasy VI"]) + _server.respond_json("/music/list", []) + _server.respond_json("/characters", []) + _server.respond_bytes("/music/rand", mp3) + _server.respond_bytes("/music/addQue", PackedByteArray()) + _server.respond_json("/music/info", SONG_INFO[0]) + _server.respond_bytes("/music/reset", PackedByteArray()) + _server.respond_bytes("/music/played?song=0", PackedByteArray()) - _before_window_starts() - _runner = scene_runner("res://MainWindow.tscn") - _window = _runner.scene() - _quiz = _window.get_node("Quiz") - # The debug build lowers the winning score on startup; keep it out of reach - Settings.winning_score = 20 + _before_window_starts() + _runner = scene_runner("res://MainWindow.tscn") + _window = _runner.scene() + _quiz = _window.get_node("Quiz") + # The debug build lowers the winning score on startup; keep it out of reach + Settings.winning_score = 20 ## Override to change the fake server before the window starts and sends its first ## requests. func _before_window_starts() -> void: - pass + pass func after_test() -> void: - # Let nodes queued for deletion by the window be freed before orphans are counted - await await_idle_frame() - _server.uninstall() - _snapshot.restore() + # Let nodes queued for deletion by the window be freed before orphans are counted + await await_idle_frame() + _server.uninstall() + _snapshot.restore() ## Makes the next song the server hands out the one described by [param info]. func _next_song_is(info: Dictionary) -> void: - _server.respond_json("/music/info", info) + _server.respond_json("/music/info", info) ## Presses a button in the quiz. func _press(button_path: String) -> void: - (_quiz.get_node(button_path) as Button).pressed.emit() + (_quiz.get_node(button_path) as Button).pressed.emit() ## Presses Next and waits until the first song is playing. func _play_first_song() -> void: - _press("NextButton") - await _runner.simulate_frames(2) + _press("NextButton") + await _runner.simulate_frames(2) ## Adds a player through the name field, the same way the user does. func _add_player(player_name: String) -> PlayerObject: - var name_field: TextEdit = _quiz.get_node( - "PlayersPanel/VBoxContainer/AddPlayerContainer/PlayerNameField") - name_field.text = player_name - _quiz.players_panel.add_player() - return Settings.player_array.back() if !Settings.player_array.is_empty() else null + var name_field: TextEdit = _quiz.get_node( + "PlayersPanel/VBoxContainer/AddPlayerContainer/PlayerNameField") + name_field.text = player_name + _quiz.players_panel.add_player() + return Settings.player_array.back() if !Settings.player_array.is_empty() else null ## Returns the row in the player list that shows [param player_object]. func _player_row(player_object: PlayerObject) -> Player: - var rows: Node = _quiz.get_node( - "PlayersPanel/VBoxContainer/ScrollContainer/PlayersListVBoxContainer") - for row: Player in rows.get_children(): - if row.player_object == player_object: - return row - return null + var rows: Node = _quiz.get_node( + "PlayersPanel/VBoxContainer/ScrollContainer/PlayersListVBoxContainer") + for row: Player in rows.get_children(): + if row.player_object == player_object: + return row + return null ## Removes a player with the remove button in its row. func _remove_player(player_object: PlayerObject) -> void: - (_player_row(player_object).get_node("HBoxContainer/RemovePlayer") as BaseButton) \ - .pressed.emit() - await _runner.simulate_frames(1) + (_player_row(player_object).get_node("HBoxContainer/RemovePlayer") as BaseButton) \ + .pressed.emit() + await _runner.simulate_frames(1) ## Clicks at [param position], given in the window's 1920x1080 layout coordinates. func _click_at(position: Vector2) -> void: - # The runner takes window pixels; the headless test window is much smaller than the - # layout, so convert like a real mouse position would be - _runner.set_mouse_position(_window.get_viewport().get_final_transform() * position) - await _runner.simulate_mouse_button_pressed(MOUSE_BUTTON_LEFT) - await _runner.await_input_processed() + # The runner takes window pixels; the headless test window is much smaller than the + # layout, so convert like a real mouse position would be + _runner.set_mouse_position(_window.get_viewport().get_final_transform() * position) + await _runner.simulate_mouse_button_pressed(MOUSE_BUTTON_LEFT) + await _runner.await_input_processed() ## Presses [param keys] together, e.g. [code][KEY_ALT, KEY_1][/code], then releases them. func _press_keys(keys: Array[Key]) -> void: - for key: Key in keys: - _runner.simulate_key_press(key) - await _runner.await_input_processed() - keys.reverse() - for key: Key in keys: - _runner.simulate_key_release(key) - await _runner.await_input_processed() + for key: Key in keys: + _runner.simulate_key_press(key) + await _runner.await_input_processed() + keys.reverse() + for key: Key in keys: + _runner.simulate_key_release(key) + await _runner.await_input_processed() ## Gives a point with Alt+. func _give_point_with_keybind(number: int) -> void: - await _press_keys([KEY_ALT, (KEY_0 + number) as Key]) + await _press_keys([KEY_ALT, (KEY_0 + number) as Key]) ## Takes a point with Ctrl+Alt+. func _take_point_with_keybind(number: int) -> void: - await _press_keys([KEY_CTRL, KEY_ALT, (KEY_0 + number) as Key]) + await _press_keys([KEY_CTRL, KEY_ALT, (KEY_0 + number) as Key]) func _scores() -> Array: - return Settings.player_array.map(func(p: PlayerObject) -> int: return p.player_score) + return Settings.player_array.map(func(p: PlayerObject) -> int: return p.player_score) diff --git a/tests/fakes/ui_tour.gd b/tests/fakes/ui_tour.gd index 71e4b39..3176bec 100644 --- a/tests/fakes/ui_tour.gd +++ b/tests/fakes/ui_tour.gd @@ -9,131 +9,131 @@ extends RefCounted ## them a node lives in. const SOUNDTRACKS: Array[String] = [ - "Chrono Trigger", "Final Fantasy VI", "Secret of Mana", "Terranigma", - "Earthbound", "Super Metroid", "The Legend of Zelda: A Link to the Past", - "Donkey Kong Country 2", "Lufia II", "Illusion of Gaia", + "Chrono Trigger", "Final Fantasy VI", "Secret of Mana", "Terranigma", + "Earthbound", "Super Metroid", "The Legend of Zelda: A Link to the Past", + "Donkey Kong Country 2", "Lufia II", "Illusion of Gaia", ] const SONG_INFO: Dictionary = { - "SongNo": 0, "Soundtrack": "Chrono Trigger", "Song": "Corridors of Time", + "SongNo": 0, "Soundtrack": "Chrono Trigger", "Song": "Corridors of Time", } const SYNC_PROGRESS: Dictionary = {"progress": 40, "time_spent": "00:00:02"} const SYNC_RESULT: Dictionary = { - "soundtracks_added": ["Terranigma", "Lufia II"], - "soundtracks_re_added": [], - "soundtracks_changed_title": {"FF6": "Final Fantasy VI"}, - "soundtracks_changed_content": ["Chrono Trigger"], - "soundtracks_removed": ["Old Soundtrack"], - "catched_errors": [], - "total_time": "00:00:03", + "soundtracks_added": ["Terranigma", "Lufia II"], + "soundtracks_re_added": [], + "soundtracks_changed_title": {"FF6": "Final Fantasy VI"}, + "soundtracks_changed_content": ["Chrono Trigger"], + "soundtracks_removed": ["Old Soundtrack"], + "catched_errors": [], + "total_time": "00:00:03", } ## Popups in the order the tour opens them. const POPUPS: Array[String] = [ - "Search", "SyncWindow", "SettingsWindow", "QRWindow", "NewCharacterSelect", - "ShortcutsWindow", "AboutWindow", "WinnerWindow", "Log", "StatisticsPopupPanel", + "Search", "SyncWindow", "SettingsWindow", "QRWindow", "NewCharacterSelect", + "ShortcutsWindow", "AboutWindow", "WinnerWindow", "Log", "StatisticsPopupPanel", ] var _main: Control func _init(main: Control) -> void: - _main = main + _main = main ## Returns a fake server that answers every request the main window makes on the tour. ## Call [method FakeHttpTransport.install] before the main window is created. static func make_server() -> FakeHttpTransport: - var server: FakeHttpTransport = FakeHttpTransport.new() - var mp3: PackedByteArray = FileAccess.get_file_as_bytes("res://tests/data/short.mp3") - server.respond_json("/music/all", SOUNDTRACKS) - server.respond_json("/music/all/order", SOUNDTRACKS) - server.respond_json("/music/list", []) - server.respond_json("/characters", []) - server.respond_bytes("/music/rand", mp3) - server.respond_bytes("/music/addQue", PackedByteArray()) - server.respond_json("/music/info", SONG_INFO) - server.respond_bytes("/music/reset", PackedByteArray()) - server.respond_bytes("/music/played?song=0", PackedByteArray()) - server.respond_bytes("/sync", PackedByteArray()) - server.respond_json("/sync/progress", SYNC_PROGRESS) - return server + var server: FakeHttpTransport = FakeHttpTransport.new() + var mp3: PackedByteArray = FileAccess.get_file_as_bytes("res://tests/data/short.mp3") + server.respond_json("/music/all", SOUNDTRACKS) + server.respond_json("/music/all/order", SOUNDTRACKS) + server.respond_json("/music/list", []) + server.respond_json("/characters", []) + server.respond_bytes("/music/rand", mp3) + server.respond_bytes("/music/addQue", PackedByteArray()) + server.respond_json("/music/info", SONG_INFO) + server.respond_bytes("/music/reset", PackedByteArray()) + server.respond_bytes("/music/played?song=0", PackedByteArray()) + server.respond_bytes("/sync", PackedByteArray()) + server.respond_json("/sync/progress", SYNC_PROGRESS) + return server ## Puts Settings and Playlist in the state the tour expects. Call it before the main ## window is created. static func prepare_autoloads() -> void: - Playlist.reset_playlist() - Playlist.first_song_played = false - Playlist.is_song_downloading = false - Settings.player_array.clear() - Settings.edit_players = false - Settings.currently_syncing = false - Settings.character_select_open = false - Settings.add_to_stats = true - Settings.hide_next_track = true - Settings.use_low_played_mode = false - Settings.winning_score = 20 - # The inspiration list scrolls by itself, which would make every picture different - Settings.inspiration_list_speed = 0 + Playlist.reset_playlist() + Playlist.first_song_played = false + Playlist.is_song_downloading = false + Settings.player_array.clear() + Settings.edit_players = false + Settings.currently_syncing = false + Settings.character_select_open = false + Settings.add_to_stats = true + Settings.hide_next_track = true + Settings.use_low_played_mode = false + Settings.winning_score = 20 + # The inspiration list scrolls by itself, which would make every picture different + Settings.inspiration_list_speed = 0 ## Runs the tour. [param on_state] is called (and awaited) with the name of each state ## and the popup that is open in it, or [code]null[/code] when no popup is open. func run(on_state: Callable) -> void: - # The debug build lowers the winning score on startup; keep it out of reach - Settings.winning_score = 20 - await _settle() - await on_state.call("startup", null) + # The debug build lowers the winning score on startup; keep it out of reach + Settings.winning_score = 20 + await _settle() + await on_state.call("startup", null) - _call("add_players") - await _settle() - await on_state.call("add_player_row", null) + _call("add_players") + await _settle() + await on_state.call("add_player_row", null) - _add_player("Crono") - _add_player("Marle") - _call("add_players") - await _settle() - await on_state.call("players_added", null) + _add_player("Crono") + _add_player("Marle") + _call("add_players") + await _settle() + await on_state.call("players_added", null) - _call("play_next_song") - await _settle() - _freeze_music_player() - _player_row(0).add_point() - _player_row(0).add_point() - _player_row(1).add_point() - _call("show_answer_pressed") - await _settle() - _freeze_music_player() - _fix_log_times() - await _settle() - await on_state.call("playing", null) + _call("play_next_song") + await _settle() + _freeze_music_player() + _player_row(0).add_point() + _player_row(0).add_point() + _player_row(1).add_point() + _call("show_answer_pressed") + await _settle() + _freeze_music_player() + _fix_log_times() + await _settle() + await on_state.call("playing", null) - for popup_name: String in POPUPS: - var popup: Node = await _open_popup(popup_name) - await _settle() - await on_state.call("popup_" + popup_name, popup) - _close_popup(popup) - await _settle() + for popup_name: String in POPUPS: + var popup: Node = await _open_popup(popup_name) + await _settle() + await on_state.call("popup_" + popup_name, popup) + _close_popup(popup) + await _settle() - var sync_window: PopupWindow = _node("SyncWindow") - Settings.currently_syncing = false - sync_window.has_synced = false - sync_window.start_sync() - sync_window.sync_timer.stop() - sync_window._on_sync_timeout() - await _settle() - await on_state.call("sync_in_progress", sync_window) - sync_window.close() - await _settle() - await on_state.call("sync_buttons_locked", null) + var sync_window: PopupWindow = _node("SyncWindow") + Settings.currently_syncing = false + sync_window.has_synced = false + sync_window.start_sync() + sync_window.sync_timer.stop() + sync_window._on_sync_timeout() + await _settle() + await on_state.call("sync_in_progress", sync_window) + sync_window.close() + await _settle() + await on_state.call("sync_buttons_locked", null) - _server().respond_json("/sync/progress", SYNC_RESULT) - sync_window._on_sync_timeout() - sync_window.open() - await _settle() - await on_state.call("sync_result", sync_window) - sync_window.close() - await _settle() + _server().respond_json("/sync/progress", SYNC_RESULT) + sync_window._on_sync_timeout() + sync_window.open() + await _settle() + await on_state.call("sync_result", sync_window) + sync_window.close() + await _settle() ## Returns where every Control and Window in [param subtree] is on screen, keyed by its @@ -141,109 +141,109 @@ func run(on_state: Callable) -> void: ## Nodes added at runtime without a name are keyed by their index, e.g. [code]#2[/code], ## so the keys are the same on every run. static func dump_layout(main: Node, subtree: Node) -> Dictionary: - var layout: Dictionary = {} - var path: String = String(main.get_path_to(subtree)) - _dump_node(subtree, path, layout) - return layout + var layout: Dictionary = {} + var path: String = String(main.get_path_to(subtree)) + _dump_node(subtree, path, layout) + return layout static func _dump_node(node: Node, path: String, layout: Dictionary) -> void: - if node is Control: - var rect: Rect2 = (node as Control).get_global_rect() - layout[path] = {"rect": _round_rect(rect), "visible": node.is_visible_in_tree()} - elif node is Window: - var window: Window = node - layout[path] = { - "rect": _round_rect(Rect2(window.position, window.size)), - "visible": window.visible, - } - for child: Node in node.get_children(): - var key: String = "#%d" % child.get_index() if "@" in child.name \ - else String(child.name) - _dump_node(child, key if path == "." else path + "/" + key, layout) + if node is Control: + var rect: Rect2 = (node as Control).get_global_rect() + layout[path] = {"rect": _round_rect(rect), "visible": node.is_visible_in_tree()} + elif node is Window: + var window: Window = node + layout[path] = { + "rect": _round_rect(Rect2(window.position, window.size)), + "visible": window.visible, + } + for child: Node in node.get_children(): + var key: String = "#%d" % child.get_index() if "@" in child.name \ + else String(child.name) + _dump_node(child, key if path == "." else path + "/" + key, layout) static func _round_rect(rect: Rect2) -> Array[float]: - return [snappedf(rect.position.x, 0.01), snappedf(rect.position.y, 0.01), - snappedf(rect.size.x, 0.01), snappedf(rect.size.y, 0.01)] + return [snappedf(rect.position.x, 0.01), snappedf(rect.position.y, 0.01), + snappedf(rect.size.x, 0.01), snappedf(rect.size.y, 0.01)] ## Finds a node of the main window by [param node_name], whether it is a direct child ## of the main window or of its Quiz or TopBar scene. func _node(node_name: String) -> Node: - for parent: Node in [_main, _main.get_node_or_null("Quiz"), - _main.get_node_or_null("TopBar")]: - if parent != null && parent.has_node(node_name): - return parent.get_node(node_name) - push_error("UiTour: no node named " + node_name) - return null + for parent: Node in [_main, _main.get_node_or_null("Quiz"), + _main.get_node_or_null("TopBar")]: + if parent != null && parent.has_node(node_name): + return parent.get_node(node_name) + push_error("UiTour: no node named " + node_name) + return null ## Calls [param method] on the players panel, the quiz or the main window, whichever ## has it first. func _call(method: String, args: Array = []) -> Variant: - for path: String in ["Quiz/PlayersPanel", "Quiz"]: - var target: Node = _main.get_node_or_null(path) - if target != null && target.has_method(method): - return target.callv(method, args) - return _main.callv(method, args) + for path: String in ["Quiz/PlayersPanel", "Quiz"]: + var target: Node = _main.get_node_or_null(path) + if target != null && target.has_method(method): + return target.callv(method, args) + return _main.callv(method, args) func _server() -> FakeHttpTransport: - return MusicServerClient.transport + return MusicServerClient.transport func _settle() -> void: - for i: int in 4: - await _main.get_tree().process_frame + for i: int in 4: + await _main.get_tree().process_frame func _add_player(player_name: String) -> void: - (_node("PlayersPanel").get_node("VBoxContainer/AddPlayerContainer/PlayerNameField") \ - as TextEdit).text = player_name - _call("add_player") + (_node("PlayersPanel").get_node("VBoxContainer/AddPlayerContainer/PlayerNameField") \ + as TextEdit).text = player_name + _call("add_player") func _player_row(index: int) -> Player: - return _node("PlayersPanel").get_node( - "VBoxContainer/ScrollContainer/PlayersListVBoxContainer").get_child(index) + return _node("PlayersPanel").get_node( + "VBoxContainer/ScrollContainer/PlayersListVBoxContainer").get_child(index) ## Stops the song so the time and progress bar look the same on every run. func _freeze_music_player() -> void: - var music_player: MusicPlayer = _node("MusicPlayer") - music_player.audio_player.stop() - music_player.sound_player.stop() - music_player.progress_slider.value = 0 - music_player.music_time_label.text = "00:00 / 00:01" + var music_player: MusicPlayer = _node("MusicPlayer") + music_player.audio_player.stop() + music_player.sound_player.stop() + music_player.progress_slider.value = 0 + music_player.music_time_label.text = "00:00 / 00:01" ## The log starts each row with the time of day; use a fixed time instead. func _fix_log_times() -> void: - var log_window: PopupWindow = _node("Log") - for row: Label in log_window.log_box.get_children(): - row.text = "12:00:00 " + row.text.substr(9) + var log_window: PopupWindow = _node("Log") + for row: Label in log_window.log_box.get_children(): + row.text = "12:00:00 " + row.text.substr(9) func _open_popup(popup_name: String) -> Node: - var popup: Node = _node(popup_name) - match popup_name: - "SyncWindow": - # Opening the window starts a sync; show the empty window instead - popup.open() - "NewCharacterSelect": - popup.show_grid("Crono") - "WinnerWindow": - popup.show_winner(Settings.player_array[0]) - "StatisticsPopupPanel": - _call("get_statistics") - _: - popup.open() - return popup + var popup: Node = _node(popup_name) + match popup_name: + "SyncWindow": + # Opening the window starts a sync; show the empty window instead + popup.open() + "NewCharacterSelect": + popup.show_grid("Crono") + "WinnerWindow": + popup.show_winner(Settings.player_array[0]) + "StatisticsPopupPanel": + _call("get_statistics") + _: + popup.open() + return popup func _close_popup(popup: Node) -> void: - if popup is PopupWindow: - popup.close() - else: - popup.visible = false + if popup is PopupWindow: + popup.close() + else: + popup.visible = false diff --git a/tests/integration/test_inspiration_list.gd b/tests/integration/test_inspiration_list.gd index 89f085d..b0a5d77 100644 --- a/tests/integration/test_inspiration_list.gd +++ b/tests/integration/test_inspiration_list.gd @@ -11,82 +11,82 @@ var _list: InspirationList func before_test() -> void: - _snapshot = AutoloadSnapshot.take([Settings]) - Settings.inspiration_list_speed = 0 - _server = FakeHttpTransport.new().install() - _server.respond_json("/music/all", SOUNDTRACKS) - _runner = scene_runner("res://InspirationList.tscn") - _list = _runner.scene() + _snapshot = AutoloadSnapshot.take([Settings]) + Settings.inspiration_list_speed = 0 + _server = FakeHttpTransport.new().install() + _server.respond_json("/music/all", SOUNDTRACKS) + _runner = scene_runner("res://InspirationList.tscn") + _list = _runner.scene() func after_test() -> void: - await await_idle_frame() - _server.uninstall() - _snapshot.restore() + await await_idle_frame() + _server.uninstall() + _snapshot.restore() func _rows() -> Array[Node]: - return _list.get_node("VBoxContainer").get_children() + return _list.get_node("VBoxContainer").get_children() func _texts() -> Array: - return _rows().map(func(row: ListRow) -> String: return row.text) + return _rows().map(func(row: ListRow) -> String: return row.text) func test_load_from_server_shows_every_soundtrack_in_order() -> void: - _list.load_from_server() + _list.load_from_server() - assert_array(_texts()).contains_exactly(SOUNDTRACKS) - assert_array(_list.soundtracks).contains_exactly(SOUNDTRACKS) + assert_array(_texts()).contains_exactly(SOUNDTRACKS) + assert_array(_list.soundtracks).contains_exactly(SOUNDTRACKS) func test_rows_alternate_backgrounds() -> void: - _list.load_from_server() + _list.load_from_server() - var rows: Array[Node] = _rows() - assert_that((rows[0] as ListRow).get_theme_stylebox("panel")) \ - .is_not_equal((rows[1] as ListRow).get_theme_stylebox("panel")) - assert_that((rows[0] as ListRow).get_theme_stylebox("panel")) \ - .is_equal((rows[2] as ListRow).get_theme_stylebox("panel")) + var rows: Array[Node] = _rows() + assert_that((rows[0] as ListRow).get_theme_stylebox("panel")) \ + .is_not_equal((rows[1] as ListRow).get_theme_stylebox("panel")) + assert_that((rows[0] as ListRow).get_theme_stylebox("panel")) \ + .is_equal((rows[2] as ListRow).get_theme_stylebox("panel")) func test_loading_again_replaces_the_rows() -> void: - _list.load_from_server() - _server.respond_json("/music/all", ["Terranigma"]) + _list.load_from_server() + _server.respond_json("/music/all", ["Terranigma"]) - _list.load_from_server() + _list.load_from_server() - assert_array(_texts()).contains_exactly(["Terranigma"]) + assert_array(_texts()).contains_exactly(["Terranigma"]) func test_failed_load_keeps_the_rows() -> void: - _list.load_from_server() - _server.respond_bytes("/music/all", PackedByteArray(), 500) + _list.load_from_server() + _server.respond_bytes("/music/all", PackedByteArray(), 500) - _list.load_from_server() + _list.load_from_server() - assert_array(_texts()).contains_exactly(SOUNDTRACKS) + assert_array(_texts()).contains_exactly(SOUNDTRACKS) func _long_list() -> Array[String]: - var names: Array[String] = [] - for i: int in 40: - names.append("Soundtrack %d" % i) - return names + var names: Array[String] = [] + for i: int in 40: + names.append("Soundtrack %d" % i) + return names func test_scrolls_down_by_itself() -> void: - _list.show_soundtracks(_long_list()) - Settings.inspiration_list_speed = 5 + _list.show_soundtracks(_long_list()) + Settings.inspiration_list_speed = 5 - await _runner.simulate_frames(30, 16) + await _runner.simulate_frames(30, 16) - assert_int(_list.scroll_vertical).is_greater(0) + assert_int(_list.scroll_vertical).is_greater(0) func test_does_not_scroll_at_speed_zero() -> void: - _list.show_soundtracks(_long_list()) + _list.show_soundtracks(_long_list()) - await _runner.simulate_frames(30, 16) + await _runner.simulate_frames(30, 16) - assert_int(_list.scroll_vertical).is_equal(0) + assert_int(_list.scroll_vertical).is_equal(0) diff --git a/tests/integration/test_layout_unchanged.gd b/tests/integration/test_layout_unchanged.gd index 10aede3..fbfc6e2 100644 --- a/tests/integration/test_layout_unchanged.gd +++ b/tests/integration/test_layout_unchanged.gd @@ -12,22 +12,22 @@ const BASELINE_PATH: String = "res://tests/data/layout_baseline.json" ## Nodes that moved from the main window into the Quiz scene, by their old name. const QUIZ_NODES: Array[String] = [ - "Open", "FileDialog", "MusicListPanel", "VBoxContainer", - "MusicPlayer", "ResetPlaylistButton", "ResetPointsButton", "SettingsButton", - "SoundTestButton", "ShowAnswerButton", "NextButton", "RepeatSongCheckButton", - "DebugLabel", "SettingsWindow", "NewCharacterSelect", "WinnerWindow", "Log", + "Open", "FileDialog", "MusicListPanel", "VBoxContainer", + "MusicPlayer", "ResetPlaylistButton", "ResetPointsButton", "SettingsButton", + "SoundTestButton", "ShowAnswerButton", "NextButton", "RepeatSongCheckButton", + "DebugLabel", "SettingsWindow", "NewCharacterSelect", "WinnerWindow", "Log", ] ## Nodes that moved into the Quiz scene and were renamed there: old name to new name. const RENAMED_QUIZ_NODES: Dictionary = { - "Players": "PlayersPanel", - "ScrollContainer": "InspirationList", + "Players": "PlayersPanel", + "ScrollContainer": "InspirationList", } ## Nodes that moved from the main window into the TopBar scene, by their old name. const TOP_BAR_NODES: Array[String] = [ - "TopPanelContainer", "Title", "SearchButton", "SyncButton", "StatisticsButton", - "ShortcutsButton", "AboutButton", "QRButton", + "TopPanelContainer", "Title", "SearchButton", "SyncButton", "StatisticsButton", + "ShortcutsButton", "AboutButton", "QRButton", ] ## How far a node may be from its old place, in pixels. @@ -40,67 +40,67 @@ var _layout: Dictionary = {} func before() -> void: - _snapshot = AutoloadSnapshot.take([Settings, Playlist]) - UiTour.prepare_autoloads() - _server = UiTour.make_server().install() - # Laid out at the size the baseline was taken at, like the screenshots - var viewport: SubViewport = auto_free(SubViewport.new()) - viewport.size = Vector2i(1920, 1080) - viewport.gui_embed_subwindows = true - Engine.get_main_loop().root.add_child(viewport) - _main = load("res://MainWindow.tscn").instantiate() - viewport.add_child(_main) - await UiTour.new(_main).run(func(state: String, popup: Node) -> void: - _layout[state] = UiTour.dump_layout(_main, _main if popup == null else popup)) + _snapshot = AutoloadSnapshot.take([Settings, Playlist]) + UiTour.prepare_autoloads() + _server = UiTour.make_server().install() + # Laid out at the size the baseline was taken at, like the screenshots + var viewport: SubViewport = auto_free(SubViewport.new()) + viewport.size = Vector2i(1920, 1080) + viewport.gui_embed_subwindows = true + Engine.get_main_loop().root.add_child(viewport) + _main = load("res://MainWindow.tscn").instantiate() + viewport.add_child(_main) + await UiTour.new(_main).run(func(state: String, popup: Node) -> void: + _layout[state] = UiTour.dump_layout(_main, _main if popup == null else popup)) func after() -> void: - _main.free() - await Engine.get_main_loop().process_frame - _server.uninstall() - _snapshot.restore() + _main.free() + await Engine.get_main_loop().process_frame + _server.uninstall() + _snapshot.restore() ## Where the node that used to be at [param old_path] in the main window is now. static func new_path(old_path: String) -> String: - var first: String = old_path.get_slice("/", 0) - if first in QUIZ_NODES: - return "Quiz/" + old_path - if first in RENAMED_QUIZ_NODES: - return "Quiz/" + RENAMED_QUIZ_NODES[first] + old_path.trim_prefix(first) - if first in TOP_BAR_NODES: - return "TopBar/" + old_path - return old_path + var first: String = old_path.get_slice("/", 0) + if first in QUIZ_NODES: + return "Quiz/" + old_path + if first in RENAMED_QUIZ_NODES: + return "Quiz/" + RENAMED_QUIZ_NODES[first] + old_path.trim_prefix(first) + if first in TOP_BAR_NODES: + return "TopBar/" + old_path + return old_path func _baseline() -> Dictionary: - return JSON.parse_string(FileAccess.get_file_as_string(BASELINE_PATH)) + return JSON.parse_string(FileAccess.get_file_as_string(BASELINE_PATH)) func test_tour_has_the_same_states_as_the_baseline() -> void: - assert_array(_layout.keys()).contains_exactly_in_any_order(_baseline().keys()) + assert_array(_layout.keys()).contains_exactly_in_any_order(_baseline().keys()) func test_every_node_is_where_it_was() -> void: - var problems: Array[String] = [] - var baseline: Dictionary = _baseline() - for state: String in baseline: - var actual: Dictionary = _layout.get(state, {}) - for old_path: String in baseline[state]: - var path: String = new_path(old_path) - var expected: Dictionary = baseline[state][old_path] - if !actual.has(path): - problems.append("%s: %s is missing (was %s)" % [state, path, old_path]) - continue - var rect: Array = actual[path].rect - for i: int in 4: - if absf(rect[i] - expected.rect[i]) > TOLERANCE: - problems.append("%s: %s is at %s, was %s" - % [state, path, rect, expected.rect]) - break - if actual[path].visible != expected.visible: - problems.append("%s: %s visible is %s, was %s" - % [state, path, actual[path].visible, expected.visible]) - assert_array(problems).override_failure_message( - "%d nodes moved:\n%s" % [problems.size(), "\n".join(problems.slice(0, 30))]) \ - .is_empty() + var problems: Array[String] = [] + var baseline: Dictionary = _baseline() + for state: String in baseline: + var actual: Dictionary = _layout.get(state, {}) + for old_path: String in baseline[state]: + var path: String = new_path(old_path) + var expected: Dictionary = baseline[state][old_path] + if !actual.has(path): + problems.append("%s: %s is missing (was %s)" % [state, path, old_path]) + continue + var rect: Array = actual[path].rect + for i: int in 4: + if absf(rect[i] - expected.rect[i]) > TOLERANCE: + problems.append("%s: %s is at %s, was %s" + % [state, path, rect, expected.rect]) + break + if actual[path].visible != expected.visible: + problems.append("%s: %s visible is %s, was %s" + % [state, path, actual[path].visible, expected.visible]) + assert_array(problems).override_failure_message( + "%d nodes moved:\n%s" % [problems.size(), "\n".join(problems.slice(0, 30))]) \ + .is_empty() diff --git a/tests/integration/test_main_window.gd b/tests/integration/test_main_window.gd index 5f9dc11..66fc24b 100644 --- a/tests/integration/test_main_window.gd +++ b/tests/integration/test_main_window.gd @@ -3,240 +3,240 @@ extends MainWindowTestSuite func test_startup_loads_soundtracks_and_preloads_a_song() -> void: - assert_int(_server.count("/music/list")).is_equal(1) - assert_int(_server.count("/music/all")).is_equal(1) - assert_array(_server.requested_paths).contains(["/music/rand", "/music/addQue", "/music/info"]) - assert_int(Playlist.song_object_array.size()).is_equal(1) - assert_bool((_quiz.get_node("NextButton") as Button).disabled).is_false() + assert_int(_server.count("/music/list")).is_equal(1) + assert_int(_server.count("/music/all")).is_equal(1) + assert_array(_server.requested_paths).contains(["/music/rand", "/music/addQue", "/music/info"]) + assert_int(Playlist.song_object_array.size()).is_equal(1) + assert_bool((_quiz.get_node("NextButton") as Button).disabled).is_false() func test_low_played_mode_fetches_from_low_played_endpoint() -> void: - Settings.use_low_played_mode = true - _server.respond_bytes( - "/music/rand/low", FileAccess.get_file_as_bytes("res://tests/data/short.mp3")) + Settings.use_low_played_mode = true + _server.respond_bytes( + "/music/rand/low", FileAccess.get_file_as_bytes("res://tests/data/short.mp3")) - _quiz.fetch_song() + _quiz.fetch_song() - assert_int(_server.count("/music/rand/low")).is_equal(1) + assert_int(_server.count("/music/rand/low")).is_equal(1) func test_next_plays_preloaded_song_and_fetches_another() -> void: - _next_song_is(SONG_INFO[1]) + _next_song_is(SONG_INFO[1]) - _press("NextButton") - await _runner.simulate_frames(2) + _press("NextButton") + await _runner.simulate_frames(2) - assert_int(Playlist.currently_playing_song).is_equal(0) - assert_bool(Playlist.song_object_array[0].has_played).is_true() - assert_int(Playlist.song_object_array.size()).is_equal(2) - assert_int(_server.count("/music/rand")).is_equal(2) + assert_int(Playlist.currently_playing_song).is_equal(0) + assert_bool(Playlist.song_object_array[0].has_played).is_true() + assert_int(Playlist.song_object_array.size()).is_equal(2) + assert_int(_server.count("/music/rand")).is_equal(2) func test_title_is_hidden_until_answer_is_shown() -> void: - var soundtrack_label: Label = _quiz.get_node("VBoxContainer/SoundtrackLabel") - _press("NextButton") - await _runner.simulate_frames(2) + var soundtrack_label: Label = _quiz.get_node("VBoxContainer/SoundtrackLabel") + _press("NextButton") + await _runner.simulate_frames(2) - assert_str(soundtrack_label.text).is_equal("????????") + assert_str(soundtrack_label.text).is_equal("????????") - _press("ShowAnswerButton") + _press("ShowAnswerButton") - assert_str(soundtrack_label.text).is_equal("Chrono Trigger") - assert_int(_server.count("/music/played?song=0")).is_equal(1) + assert_str(soundtrack_label.text).is_equal("Chrono Trigger") + assert_int(_server.count("/music/played?song=0")).is_equal(1) func test_reset_playlist_clears_server_and_preloads_again() -> void: - _press("NextButton") - await _runner.simulate_frames(2) + _press("NextButton") + await _runner.simulate_frames(2) - _press("ResetPlaylistButton") + _press("ResetPlaylistButton") - assert_int(_server.count("/music/reset")).is_equal(1) - assert_int(Playlist.currently_playing_song).is_equal(-1) - assert_int(Playlist.song_object_array.size()).is_equal(1) - assert_bool(Playlist.song_object_array[0].has_played).is_false() + assert_int(_server.count("/music/reset")).is_equal(1) + assert_int(Playlist.currently_playing_song).is_equal(-1) + assert_int(Playlist.song_object_array.size()).is_equal(1) + assert_bool(Playlist.song_object_array[0].has_played).is_false() func test_reset_points_sets_all_scores_to_zero() -> void: - _add_player("Crono").add_point() - _add_player("Marle").add_point() + _add_player("Crono").add_point() + _add_player("Marle").add_point() - _press("ResetPointsButton") + _press("ResetPointsButton") - assert_int(Settings.player_array[0].player_score).is_equal(0) - assert_int(Settings.player_array[1].player_score).is_equal(0) + assert_int(Settings.player_array[0].player_score).is_equal(0) + assert_int(Settings.player_array[1].player_score).is_equal(0) func test_cannot_add_more_than_max_players() -> void: - for i: int in Settings.MAX_NUMBER_OF_PLAYERS + 1: - _add_player("Player %d" % i) + for i: int in Settings.MAX_NUMBER_OF_PLAYERS + 1: + _add_player("Player %d" % i) - assert_int(Settings.player_array.size()).is_equal(Settings.MAX_NUMBER_OF_PLAYERS) + assert_int(Settings.player_array.size()).is_equal(Settings.MAX_NUMBER_OF_PLAYERS) func test_cannot_add_player_without_name() -> void: - _add_player("") + _add_player("") - assert_array(Settings.player_array).is_empty() + assert_array(Settings.player_array).is_empty() func test_failed_song_download_is_retried_until_the_server_answers() -> void: - _quiz.song_fetch_retry_seconds = 0.05 - var songs_before: int = Playlist.song_object_array.size() - var mp3: PackedByteArray = FileAccess.get_file_as_bytes("res://tests/data/short.mp3") - _server.respond_bytes("/music/rand", PackedByteArray(), 503) - var rand_requests_before: int = _server.count("/music/rand") + _quiz.song_fetch_retry_seconds = 0.05 + var songs_before: int = Playlist.song_object_array.size() + var mp3: PackedByteArray = FileAccess.get_file_as_bytes("res://tests/data/short.mp3") + _server.respond_bytes("/music/rand", PackedByteArray(), 503) + var rand_requests_before: int = _server.count("/music/rand") - _quiz.fetch_song() - await await_millis(200) + _quiz.fetch_song() + await await_millis(200) - assert_int(_server.count("/music/rand") - rand_requests_before).is_greater(1) - assert_int(Playlist.song_object_array.size()).is_equal(songs_before) - assert_bool(Playlist.is_song_downloading).is_true() + assert_int(_server.count("/music/rand") - rand_requests_before).is_greater(1) + assert_int(Playlist.song_object_array.size()).is_equal(songs_before) + assert_bool(Playlist.is_song_downloading).is_true() - _server.respond_bytes("/music/rand", mp3) - await await_millis(200) + _server.respond_bytes("/music/rand", mp3) + await await_millis(200) - assert_int(Playlist.song_object_array.size()).is_equal(songs_before + 1) - assert_bool(Playlist.is_song_downloading).is_false() + assert_int(Playlist.song_object_array.size()).is_equal(songs_before + 1) + assert_bool(Playlist.is_song_downloading).is_false() func test_failed_song_info_retries_only_that_step() -> void: - _quiz.song_fetch_retry_seconds = 0.05 - var songs_before: int = Playlist.song_object_array.size() - _server.respond_bytes("/music/info", PackedByteArray(), 503) - var rand_before: int = _server.count("/music/rand") - var queue_before: int = _server.count("/music/addQue") + _quiz.song_fetch_retry_seconds = 0.05 + var songs_before: int = Playlist.song_object_array.size() + _server.respond_bytes("/music/info", PackedByteArray(), 503) + var rand_before: int = _server.count("/music/rand") + var queue_before: int = _server.count("/music/addQue") - _quiz.fetch_song() - await await_millis(200) - _next_song_is(SONG_INFO[1]) - await await_millis(200) + _quiz.fetch_song() + await await_millis(200) + _next_song_is(SONG_INFO[1]) + await await_millis(200) - # The song was downloaded and queued once; only the info request was repeated - assert_int(_server.count("/music/rand") - rand_before).is_equal(1) - assert_int(_server.count("/music/addQue") - queue_before).is_equal(1) - assert_int(Playlist.song_object_array.size()).is_equal(songs_before + 1) - assert_str(Playlist.song_object_array.back().song_title).is_equal("Dancing Mad") - assert_bool(Playlist.is_song_downloading).is_false() + # The song was downloaded and queued once; only the info request was repeated + assert_int(_server.count("/music/rand") - rand_before).is_equal(1) + assert_int(_server.count("/music/addQue") - queue_before).is_equal(1) + assert_int(Playlist.song_object_array.size()).is_equal(songs_before + 1) + assert_str(Playlist.song_object_array.back().song_title).is_equal("Dancing Mad") + assert_bool(Playlist.is_song_downloading).is_false() func test_preloads_as_many_songs_as_the_cache_setting() -> void: - Playlist.number_of_tracks_to_preload = 3 + Playlist.number_of_tracks_to_preload = 3 - _quiz.fetch_song() + _quiz.fetch_song() - assert_int(Playlist.get_preloaded_songs()).is_equal(3) - assert_bool(Playlist.is_song_downloading).is_false() + assert_int(Playlist.get_preloaded_songs()).is_equal(3) + assert_bool(Playlist.is_song_downloading).is_false() func test_playing_a_song_tops_the_cache_up_again() -> void: - Playlist.number_of_tracks_to_preload = 3 - _quiz.fetch_song() + Playlist.number_of_tracks_to_preload = 3 + _quiz.fetch_song() - await _play_first_song() + await _play_first_song() - assert_int(Playlist.get_preloaded_songs()).is_equal(3) - assert_int(Playlist.song_object_array.size()).is_equal(4) + assert_int(Playlist.get_preloaded_songs()).is_equal(3) + assert_int(Playlist.song_object_array.size()).is_equal(4) func test_cache_keeps_filling_after_a_failed_download() -> void: - _quiz.song_fetch_retry_seconds = 0.05 - Playlist.number_of_tracks_to_preload = 3 - var mp3: PackedByteArray = FileAccess.get_file_as_bytes("res://tests/data/short.mp3") - # One more download works, then the server stops answering - _server.fail_after("/music/rand", 1) + _quiz.song_fetch_retry_seconds = 0.05 + Playlist.number_of_tracks_to_preload = 3 + var mp3: PackedByteArray = FileAccess.get_file_as_bytes("res://tests/data/short.mp3") + # One more download works, then the server stops answering + _server.fail_after("/music/rand", 1) - _quiz.fetch_song() - await await_millis(150) + _quiz.fetch_song() + await await_millis(150) - assert_int(Playlist.get_preloaded_songs()).is_equal(2) - assert_bool(Playlist.is_song_downloading).is_true() + assert_int(Playlist.get_preloaded_songs()).is_equal(2) + assert_bool(Playlist.is_song_downloading).is_true() - _server.respond_bytes("/music/rand", mp3) - await await_millis(150) + _server.respond_bytes("/music/rand", mp3) + await await_millis(150) - assert_int(Playlist.get_preloaded_songs()).is_equal(3) - assert_bool(Playlist.is_song_downloading).is_false() + assert_int(Playlist.get_preloaded_songs()).is_equal(3) + assert_bool(Playlist.is_song_downloading).is_false() func _open_settings() -> void: - _press("SettingsButton") + _press("SettingsButton") func _close_settings() -> void: - (_quiz.get_node("SettingsWindow") as Control).visible = false + (_quiz.get_node("SettingsWindow") as Control).visible = false func _press_settings_button(unique_name: String) -> void: - (_quiz.get_node("SettingsWindow").get_node("%" + unique_name) as Button).pressed.emit() + (_quiz.get_node("SettingsWindow").get_node("%" + unique_name) as Button).pressed.emit() func test_raising_cache_size_does_not_download_while_settings_are_open() -> void: - var downloads_before: int = _server.count("/music/rand") - _open_settings() + var downloads_before: int = _server.count("/music/rand") + _open_settings() - _press_settings_button("IncreaseCacheButton") - _press_settings_button("IncreaseCacheButton") + _press_settings_button("IncreaseCacheButton") + _press_settings_button("IncreaseCacheButton") - assert_int(Playlist.number_of_tracks_to_preload).is_equal(3) - assert_int(_server.count("/music/rand")).is_equal(downloads_before) + assert_int(Playlist.number_of_tracks_to_preload).is_equal(3) + assert_int(_server.count("/music/rand")).is_equal(downloads_before) func test_closing_settings_fills_cache_to_new_size() -> void: - _open_settings() - _press_settings_button("IncreaseCacheButton") - _press_settings_button("IncreaseCacheButton") + _open_settings() + _press_settings_button("IncreaseCacheButton") + _press_settings_button("IncreaseCacheButton") - _close_settings() + _close_settings() - assert_int(Playlist.get_preloaded_songs()).is_equal(3) + assert_int(Playlist.get_preloaded_songs()).is_equal(3) func test_changing_cache_size_back_and_forth_downloads_only_what_is_needed() -> void: - var downloads_before: int = _server.count("/music/rand") - _open_settings() - for i: int in 5: - _press_settings_button("IncreaseCacheButton") - _press_settings_button("LowerCacheButton") - _press_settings_button("IncreaseCacheButton") + var downloads_before: int = _server.count("/music/rand") + _open_settings() + for i: int in 5: + _press_settings_button("IncreaseCacheButton") + _press_settings_button("LowerCacheButton") + _press_settings_button("IncreaseCacheButton") - _close_settings() + _close_settings() - assert_int(_server.count("/music/rand") - downloads_before).is_equal(1) - assert_int(Playlist.get_preloaded_songs()).is_equal(2) + assert_int(_server.count("/music/rand") - downloads_before).is_equal(1) + assert_int(Playlist.get_preloaded_songs()).is_equal(2) func test_closing_settings_with_full_cache_downloads_nothing() -> void: - var downloads_before: int = _server.count("/music/rand") - _open_settings() + var downloads_before: int = _server.count("/music/rand") + _open_settings() - _close_settings() + _close_settings() - assert_int(_server.count("/music/rand")).is_equal(downloads_before) + assert_int(_server.count("/music/rand")).is_equal(downloads_before) func test_show_answer_before_first_song_does_not_reveal_next_song() -> void: - _press("ShowAnswerButton") + _press("ShowAnswerButton") - assert_bool(Playlist.song_object_array[0].is_answered).is_false() - assert_int(_server.count("/music/played?song=-1")).is_equal(0) + assert_bool(Playlist.song_object_array[0].is_answered).is_false() + assert_int(_server.count("/music/played?song=-1")).is_equal(0) - await _play_first_song() + await _play_first_song() - assert_str((_quiz.get_node("VBoxContainer/SoundtrackLabel") as Label).text) \ - .is_equal("????????") + assert_str((_quiz.get_node("VBoxContainer/SoundtrackLabel") as Label).text) \ + .is_equal("????????") func test_log_adds_one_row_per_point_with_padded_time() -> void: - var log_box: VBoxContainer = _quiz.get_node("%Log").get_node("%LogVBoxContainer") - var crono: PlayerObject = _add_player("Crono") - await _play_first_song() + var log_box: VBoxContainer = _quiz.get_node("%Log").get_node("%LogVBoxContainer") + var crono: PlayerObject = _add_player("Crono") + await _play_first_song() - crono.add_point() - crono.minus_point() + crono.add_point() + crono.minus_point() - assert_int(log_box.get_child_count()).is_equal(2) - var time_pattern: RegEx = RegEx.create_from_string("^\\d\\d:\\d\\d:\\d\\d Crono got a point$") - assert_object(time_pattern.search((log_box.get_child(0) as Label).text)).is_not_null() - assert_str((log_box.get_child(1) as Label).text).ends_with("Crono lost a point") + assert_int(log_box.get_child_count()).is_equal(2) + var time_pattern: RegEx = RegEx.create_from_string("^\\d\\d:\\d\\d:\\d\\d Crono got a point$") + assert_object(time_pattern.search((log_box.get_child(0) as Label).text)).is_not_null() + assert_str((log_box.get_child(1) as Label).text).ends_with("Crono lost a point") diff --git a/tests/integration/test_main_window_startup.gd b/tests/integration/test_main_window_startup.gd index 4d882c5..27e9fb4 100644 --- a/tests/integration/test_main_window_startup.gd +++ b/tests/integration/test_main_window_startup.gd @@ -3,39 +3,39 @@ extends MainWindowTestSuite func _before_window_starts() -> void: - _server.respond_json("/music/list", [ - {"SongNo": 0, "Soundtrack": "Chrono Trigger", "Song": "Corridors of Time"}, - ]) - _next_song_is({"SongNo": 1, "Soundtrack": "Final Fantasy VI", "Song": "Dancing Mad"}) - _server.hold("/music/list") + _server.respond_json("/music/list", [ + {"SongNo": 0, "Soundtrack": "Chrono Trigger", "Song": "Corridors of Time"}, + ]) + _next_song_is({"SongNo": 1, "Soundtrack": "Final Fantasy VI", "Song": "Dancing Mad"}) + _server.hold("/music/list") func test_preloaded_song_survives_a_slow_song_list() -> void: - _server.release("/music/list") + _server.release("/music/list") - # The song already on the server, then the preloaded one - assert_int(Playlist.song_object_array.size()).is_equal(2) - assert_str(Playlist.song_object_array[1].song_title).is_equal("Dancing Mad") - assert_int(Playlist.get_preloaded_songs()).is_equal(1) + # The song already on the server, then the preloaded one + assert_int(Playlist.song_object_array.size()).is_equal(2) + assert_str(Playlist.song_object_array[1].song_title).is_equal("Dancing Mad") + assert_int(Playlist.get_preloaded_songs()).is_equal(1) func test_next_plays_the_preloaded_song_after_a_slow_song_list() -> void: - _server.release("/music/list") + _server.release("/music/list") - await _play_first_song() + await _play_first_song() - assert_int(Playlist.currently_playing_song).is_equal(1) + assert_int(Playlist.currently_playing_song).is_equal(1) func test_failed_song_list_is_retried_before_preloading() -> void: - _quiz.song_fetch_retry_seconds = 0.05 - _server.respond_json("/music/list", [], 503) - _server.release("/music/list") + _quiz.song_fetch_retry_seconds = 0.05 + _server.respond_json("/music/list", [], 503) + _server.release("/music/list") - assert_int(_server.count("/music/rand")).is_equal(0) + assert_int(_server.count("/music/rand")).is_equal(0) - _server.respond_json("/music/list", []) - await await_millis(200) + _server.respond_json("/music/list", []) + await await_millis(200) - assert_int(_server.count("/music/rand")).is_equal(1) - assert_int(Playlist.get_preloaded_songs()).is_equal(1) + assert_int(_server.count("/music/rand")).is_equal(1) + assert_int(Playlist.get_preloaded_songs()).is_equal(1) diff --git a/tests/integration/test_music_list_panel.gd b/tests/integration/test_music_list_panel.gd index f6fa444..a056e12 100644 --- a/tests/integration/test_music_list_panel.gd +++ b/tests/integration/test_music_list_panel.gd @@ -8,72 +8,72 @@ var _panel: MusicListPanel func before_test() -> void: - _snapshot = AutoloadSnapshot.take([Settings, Playlist]) - Playlist.reset_playlist() - for i: int in 3: - var song: SongObject = SongObject.new() - song.song_number = i - song.soundtrack_title = "Soundtrack %d" % i - song.song_title = "Song %d" % i - song.has_played = true - Playlist.add_to_playlist(song) - _runner = scene_runner("res://MusicListPanel.tscn") - _panel = _runner.scene() + _snapshot = AutoloadSnapshot.take([Settings, Playlist]) + Playlist.reset_playlist() + for i: int in 3: + var song: SongObject = SongObject.new() + song.song_number = i + song.soundtrack_title = "Soundtrack %d" % i + song.song_title = "Song %d" % i + song.has_played = true + Playlist.add_to_playlist(song) + _runner = scene_runner("res://MusicListPanel.tscn") + _panel = _runner.scene() func after_test() -> void: - await await_idle_frame() - _snapshot.restore() + await await_idle_frame() + _snapshot.restore() func _rows() -> Array[Node]: - return _panel.get_node("ScrollContainer/MusicList").get_children() + return _panel.get_node("ScrollContainer/MusicList").get_children() func test_starts_empty() -> void: - assert_array(_rows()).is_empty() + assert_array(_rows()).is_empty() func test_refresh_shows_one_row_per_song_in_order() -> void: - _panel.refresh() + _panel.refresh() - assert_array(_rows().map(func(row: SongListObject) -> int: return row.song_object.song_number)) \ - .contains_exactly([0, 1, 2]) + assert_array(_rows().map(func(row: SongListObject) -> int: return row.song_object.song_number)) \ + .contains_exactly([0, 1, 2]) func test_refresh_again_replaces_the_rows() -> void: - _panel.refresh() - Playlist.song_object_array.pop_back() + _panel.refresh() + Playlist.song_object_array.pop_back() - _panel.refresh() + _panel.refresh() - assert_int(_rows().size()).is_equal(2) + assert_int(_rows().size()).is_equal(2) func test_clicking_a_row_tells_which_song() -> void: - _panel.refresh() - await _runner.simulate_frames(2) - var signals: GdUnitSignalAssert = assert_signal(monitor_signals(_panel)) - var row: Control = _rows()[1] - # The left end of the row is the song text, not one of the player icons - var target: Vector2 = row.get_global_rect().position + Vector2(20, row.size.y / 2) + _panel.refresh() + await _runner.simulate_frames(2) + var signals: GdUnitSignalAssert = assert_signal(monitor_signals(_panel)) + var row: Control = _rows()[1] + # The left end of the row is the song text, not one of the player icons + var target: Vector2 = row.get_global_rect().position + Vector2(20, row.size.y / 2) - _runner.set_mouse_position(_panel.get_viewport().get_final_transform() * target) - await _runner.simulate_mouse_button_pressed(MOUSE_BUTTON_LEFT) - await _runner.await_input_processed() + _runner.set_mouse_position(_panel.get_viewport().get_final_transform() * target) + await _runner.simulate_mouse_button_pressed(MOUSE_BUTTON_LEFT) + await _runner.await_input_processed() - await signals.is_emitted("song_clicked", [1]) + await signals.is_emitted("song_clicked", [1]) func test_right_click_does_nothing() -> void: - _panel.refresh() - await _runner.simulate_frames(2) - var signals: GdUnitSignalAssert = assert_signal(monitor_signals(_panel)) - var row: Control = _rows()[0] + _panel.refresh() + await _runner.simulate_frames(2) + var signals: GdUnitSignalAssert = assert_signal(monitor_signals(_panel)) + var row: Control = _rows()[0] - _runner.set_mouse_position(_panel.get_viewport().get_final_transform() - * (row.get_global_rect().position + Vector2(20, row.size.y / 2))) - await _runner.simulate_mouse_button_pressed(MOUSE_BUTTON_RIGHT) - await _runner.await_input_processed() + _runner.set_mouse_position(_panel.get_viewport().get_final_transform() + * (row.get_global_rect().position + Vector2(20, row.size.y / 2))) + await _runner.simulate_mouse_button_pressed(MOUSE_BUTTON_RIGHT) + await _runner.await_input_processed() - await signals.wait_until(200).is_not_emitted("song_clicked") + await signals.wait_until(200).is_not_emitted("song_clicked") diff --git a/tests/integration/test_player_keybinds.gd b/tests/integration/test_player_keybinds.gd index 8dd3778..2d91ce3 100644 --- a/tests/integration/test_player_keybinds.gd +++ b/tests/integration/test_player_keybinds.gd @@ -10,143 +10,143 @@ var _lucca: PlayerObject func before_test() -> void: - super() - _crono = _add_player("Crono") - _marle = _add_player("Marle") - _lucca = _add_player("Lucca") - await _play_first_song() + super() + _crono = _add_player("Crono") + _marle = _add_player("Marle") + _lucca = _add_player("Lucca") + await _play_first_song() func _song_points() -> Array[String]: - return Playlist.song_object_array[Playlist.currently_playing_song].players_given_point + return Playlist.song_object_array[Playlist.currently_playing_song].players_given_point func test_alt_number_gives_point_to_player_in_that_row() -> void: - await _give_point_with_keybind(2) + await _give_point_with_keybind(2) - assert_array(_scores()).contains_exactly([0, 1, 0]) - assert_array(_song_points()).contains_exactly([_marle.id]) + assert_array(_scores()).contains_exactly([0, 1, 0]) + assert_array(_song_points()).contains_exactly([_marle.id]) func test_ctrl_alt_number_takes_point_from_player_in_that_row() -> void: - await _give_point_with_keybind(3) - await _give_point_with_keybind(3) + await _give_point_with_keybind(3) + await _give_point_with_keybind(3) - await _take_point_with_keybind(3) + await _take_point_with_keybind(3) - assert_array(_scores()).contains_exactly([0, 0, 1]) + assert_array(_scores()).contains_exactly([0, 0, 1]) func test_taking_last_point_removes_player_from_song() -> void: - await _give_point_with_keybind(1) + await _give_point_with_keybind(1) - await _take_point_with_keybind(1) + await _take_point_with_keybind(1) - assert_int(_crono.player_score).is_equal(0) - assert_array(_song_points()).is_empty() + assert_int(_crono.player_score).is_equal(0) + assert_array(_song_points()).is_empty() func test_each_keybind_only_affects_its_own_player() -> void: - await _give_point_with_keybind(1) - await _give_point_with_keybind(3) - await _give_point_with_keybind(3) + await _give_point_with_keybind(1) + await _give_point_with_keybind(3) + await _give_point_with_keybind(3) - assert_int(_crono.player_score).is_equal(1) - assert_int(_marle.player_score).is_equal(0) - assert_int(_lucca.player_score).is_equal(2) - assert_array(_song_points()).contains_exactly([_crono.id, _lucca.id]) + assert_int(_crono.player_score).is_equal(1) + assert_int(_marle.player_score).is_equal(0) + assert_int(_lucca.player_score).is_equal(2) + assert_array(_song_points()).contains_exactly([_crono.id, _lucca.id]) func test_number_without_player_does_nothing() -> void: - await _give_point_with_keybind(4) + await _give_point_with_keybind(4) - assert_array(_scores()).contains_exactly([0, 0, 0]) - assert_array(_song_points()).is_empty() + assert_array(_scores()).contains_exactly([0, 0, 0]) + assert_array(_song_points()).is_empty() func test_keybinds_move_up_when_first_player_is_removed() -> void: - await _remove_player(_crono) + await _remove_player(_crono) - await _give_point_with_keybind(1) - await _give_point_with_keybind(2) - await _give_point_with_keybind(2) + await _give_point_with_keybind(1) + await _give_point_with_keybind(2) + await _give_point_with_keybind(2) - assert_int(_marle.player_score).is_equal(1) - assert_int(_lucca.player_score).is_equal(2) - assert_array(_song_points()).contains_exactly([_marle.id, _lucca.id]) + assert_int(_marle.player_score).is_equal(1) + assert_int(_lucca.player_score).is_equal(2) + assert_array(_song_points()).contains_exactly([_marle.id, _lucca.id]) func test_keybind_after_last_row_does_nothing_after_removal() -> void: - await _remove_player(_marle) + await _remove_player(_marle) - await _give_point_with_keybind(3) + await _give_point_with_keybind(3) - assert_int(_crono.player_score).is_equal(0) - assert_int(_lucca.player_score).is_equal(0) + assert_int(_crono.player_score).is_equal(0) + assert_int(_lucca.player_score).is_equal(0) func test_removing_player_removes_only_their_points() -> void: - await _give_point_with_keybind(1) - await _give_point_with_keybind(2) - await _give_point_with_keybind(3) + await _give_point_with_keybind(1) + await _give_point_with_keybind(2) + await _give_point_with_keybind(3) - await _remove_player(_marle) + await _remove_player(_marle) - assert_array(_song_points()).contains_exactly([_crono.id, _lucca.id]) - assert_int(_crono.player_score).is_equal(1) - assert_int(_lucca.player_score).is_equal(1) + assert_array(_song_points()).contains_exactly([_crono.id, _lucca.id]) + assert_int(_crono.player_score).is_equal(1) + assert_int(_lucca.player_score).is_equal(1) func test_new_player_gets_next_free_keybind_after_removal() -> void: - await _remove_player(_marle) - var robo: PlayerObject = _add_player("Robo") + await _remove_player(_marle) + var robo: PlayerObject = _add_player("Robo") - await _give_point_with_keybind(2) - await _give_point_with_keybind(3) + await _give_point_with_keybind(2) + await _give_point_with_keybind(3) - assert_int(_lucca.player_score).is_equal(1) - assert_int(robo.player_score).is_equal(1) - assert_int(_crono.player_score).is_equal(0) - assert_array(_song_points()).contains_exactly([_lucca.id, robo.id]) + assert_int(_lucca.player_score).is_equal(1) + assert_int(robo.player_score).is_equal(1) + assert_int(_crono.player_score).is_equal(0) + assert_array(_song_points()).contains_exactly([_lucca.id, robo.id]) func test_new_player_does_not_inherit_removed_players_points() -> void: - await _give_point_with_keybind(3) - await _remove_player(_lucca) + await _give_point_with_keybind(3) + await _remove_player(_lucca) - var robo: PlayerObject = _add_player("Robo") + var robo: PlayerObject = _add_player("Robo") - assert_int(robo.player_score).is_equal(0) - assert_array(_song_points()).is_empty() + assert_int(robo.player_score).is_equal(0) + assert_array(_song_points()).is_empty() func test_points_follow_players_through_several_changes() -> void: - await _give_point_with_keybind(1) - await _remove_player(_crono) - var robo: PlayerObject = _add_player("Robo") - await _give_point_with_keybind(1) - await _remove_player(_marle) - var ayla: PlayerObject = _add_player("Ayla") - await _give_point_with_keybind(3) - await _give_point_with_keybind(2) - await _take_point_with_keybind(2) + await _give_point_with_keybind(1) + await _remove_player(_crono) + var robo: PlayerObject = _add_player("Robo") + await _give_point_with_keybind(1) + await _remove_player(_marle) + var ayla: PlayerObject = _add_player("Ayla") + await _give_point_with_keybind(3) + await _give_point_with_keybind(2) + await _take_point_with_keybind(2) - # Rows are now: Lucca, Robo, Ayla - assert_array(Settings.player_array).contains_exactly([_lucca, robo, ayla]) - assert_int(_lucca.player_score).is_equal(0) - assert_int(robo.player_score).is_equal(0) - assert_int(ayla.player_score).is_equal(1) - assert_array(_song_points()).contains_exactly([ayla.id]) + # Rows are now: Lucca, Robo, Ayla + assert_array(Settings.player_array).contains_exactly([_lucca, robo, ayla]) + assert_int(_lucca.player_score).is_equal(0) + assert_int(robo.player_score).is_equal(0) + assert_int(ayla.player_score).is_equal(1) + assert_array(_song_points()).contains_exactly([ayla.id]) func test_player_list_shows_rows_in_player_order() -> void: - await _remove_player(_crono) - var robo: PlayerObject = _add_player("Robo") + await _remove_player(_crono) + var robo: PlayerObject = _add_player("Robo") - var rows: Array[Node] = _quiz.get_node( - "PlayersPanel/VBoxContainer/ScrollContainer/PlayersListVBoxContainer").get_children() + var rows: Array[Node] = _quiz.get_node( + "PlayersPanel/VBoxContainer/ScrollContainer/PlayersListVBoxContainer").get_children() - assert_array(rows.map(func(row: Player) -> PlayerObject: return row.player_object)) \ - .contains_exactly([_marle, _lucca, robo]) - assert_array(rows.map(func(row: Player) -> int: return row.list_index)) \ - .contains_exactly([0, 1, 2]) + assert_array(rows.map(func(row: Player) -> PlayerObject: return row.player_object)) \ + .contains_exactly([_marle, _lucca, robo]) + assert_array(rows.map(func(row: Player) -> int: return row.list_index)) \ + .contains_exactly([0, 1, 2]) diff --git a/tests/integration/test_players_panel.gd b/tests/integration/test_players_panel.gd index 07642a8..8aaa37d 100644 --- a/tests/integration/test_players_panel.gd +++ b/tests/integration/test_players_panel.gd @@ -8,139 +8,139 @@ var _panel: PlayersPanel func before_test() -> void: - _snapshot = AutoloadSnapshot.take([Settings]) - Settings.player_array.clear() - Settings.edit_players = false - _runner = scene_runner("res://PlayersPanel.tscn") - _panel = _runner.scene() + _snapshot = AutoloadSnapshot.take([Settings]) + Settings.player_array.clear() + Settings.edit_players = false + _runner = scene_runner("res://PlayersPanel.tscn") + _panel = _runner.scene() func after_test() -> void: - await await_idle_frame() - _snapshot.restore() + await await_idle_frame() + _snapshot.restore() func _rows() -> Array[Node]: - return _panel.players_list_container.get_children() + return _panel.players_list_container.get_children() func _add(player_name: String) -> void: - _panel.new_player_name_field.text = player_name - _panel.add_player() + _panel.new_player_name_field.text = player_name + _panel.add_player() func _click(control: Control) -> void: - _runner.set_mouse_position(_panel.get_viewport().get_final_transform() - * control.get_global_rect().get_center()) - await _runner.simulate_mouse_button_pressed(MOUSE_BUTTON_LEFT) - await _runner.await_input_processed() + _runner.set_mouse_position(_panel.get_viewport().get_final_transform() + * control.get_global_rect().get_center()) + await _runner.simulate_mouse_button_pressed(MOUSE_BUTTON_LEFT) + await _runner.await_input_processed() func test_add_button_shows_and_hides_the_add_row() -> void: - assert_bool(_panel.add_player_container.visible).is_false() + assert_bool(_panel.add_player_container.visible).is_false() - await _click(_panel.add_players_button) - assert_bool(_panel.add_player_container.visible).is_true() - assert_bool(Settings.edit_players).is_true() + await _click(_panel.add_players_button) + assert_bool(_panel.add_player_container.visible).is_true() + assert_bool(Settings.edit_players).is_true() - await _click(_panel.add_players_button) - assert_bool(_panel.add_player_container.visible).is_false() - assert_bool(Settings.edit_players).is_false() + await _click(_panel.add_players_button) + assert_bool(_panel.add_player_container.visible).is_false() + assert_bool(Settings.edit_players).is_false() func test_adding_a_name_adds_a_player_and_a_row() -> void: - var signals: GdUnitSignalAssert = assert_signal(monitor_signals(_panel)) + var signals: GdUnitSignalAssert = assert_signal(monitor_signals(_panel)) - _add("Crono") + _add("Crono") - assert_int(Settings.player_array.size()).is_equal(1) - var crono: PlayerObject = Settings.player_array[0] - assert_str(crono.player_name).is_equal("Crono") - await signals.is_emitted("player_added", [crono]) - assert_str(_panel.new_player_name_field.text).is_empty() - assert_object((_rows()[0] as Player).player_object).is_same(crono) + assert_int(Settings.player_array.size()).is_equal(1) + var crono: PlayerObject = Settings.player_array[0] + assert_str(crono.player_name).is_equal("Crono") + await signals.is_emitted("player_added", [crono]) + assert_str(_panel.new_player_name_field.text).is_empty() + assert_object((_rows()[0] as Player).player_object).is_same(crono) func test_add_button_in_the_row_adds_the_player() -> void: - await _click(_panel.add_players_button) - _panel.new_player_name_field.text = "Marle" + await _click(_panel.add_players_button) + _panel.new_player_name_field.text = "Marle" - await _click(_panel.add_player_button) + await _click(_panel.add_player_button) - assert_int(Settings.player_array.size()).is_equal(1) + assert_int(Settings.player_array.size()).is_equal(1) func test_enter_in_the_name_field_adds_the_player() -> void: - await _click(_panel.add_players_button) - _panel.new_player_name_field.text = "Lucca" - _panel.new_player_name_field.grab_focus() + await _click(_panel.add_players_button) + _panel.new_player_name_field.text = "Lucca" + _panel.new_player_name_field.grab_focus() - _runner.simulate_key_pressed(KEY_ENTER) - await _runner.await_input_processed() + _runner.simulate_key_pressed(KEY_ENTER) + await _runner.await_input_processed() - assert_array(Settings.player_array.map( - func(p: PlayerObject) -> String: return p.player_name)).contains_exactly(["Lucca"]) + assert_array(Settings.player_array.map( + func(p: PlayerObject) -> String: return p.player_name)).contains_exactly(["Lucca"]) func test_empty_name_adds_nobody() -> void: - var signals: GdUnitSignalAssert = assert_signal(monitor_signals(_panel)) + var signals: GdUnitSignalAssert = assert_signal(monitor_signals(_panel)) - _add("") + _add("") - assert_array(Settings.player_array).is_empty() - assert_array(_rows()).is_empty() - await signals.wait_until(200).is_not_emitted("player_added") + assert_array(Settings.player_array).is_empty() + assert_array(_rows()).is_empty() + await signals.wait_until(200).is_not_emitted("player_added") func test_cannot_add_more_than_max_players() -> void: - for i: int in Settings.MAX_NUMBER_OF_PLAYERS + 1: - _add("Player %d" % i) + for i: int in Settings.MAX_NUMBER_OF_PLAYERS + 1: + _add("Player %d" % i) - assert_int(Settings.player_array.size()).is_equal(Settings.MAX_NUMBER_OF_PLAYERS) - assert_int(_rows().size()).is_equal(Settings.MAX_NUMBER_OF_PLAYERS) + assert_int(Settings.player_array.size()).is_equal(Settings.MAX_NUMBER_OF_PLAYERS) + assert_int(_rows().size()).is_equal(Settings.MAX_NUMBER_OF_PLAYERS) func test_rows_follow_player_order_and_numbering() -> void: - _add("Crono") - _add("Marle") - _add("Lucca") + _add("Crono") + _add("Marle") + _add("Lucca") - assert_array(_rows().map(func(row: Player) -> String: return row.player_object.player_name)) \ - .contains_exactly(["Crono", "Marle", "Lucca"]) - assert_array(_rows().map(func(row: Player) -> int: return row.list_index)) \ - .contains_exactly([0, 1, 2]) + assert_array(_rows().map(func(row: Player) -> String: return row.player_object.player_name)) \ + .contains_exactly(["Crono", "Marle", "Lucca"]) + assert_array(_rows().map(func(row: Player) -> int: return row.list_index)) \ + .contains_exactly([0, 1, 2]) func test_remove_button_removes_the_player_and_row() -> void: - _add("Crono") - _add("Marle") - var crono: PlayerObject = Settings.player_array[0] - var signals: GdUnitSignalAssert = assert_signal(monitor_signals(_panel)) + _add("Crono") + _add("Marle") + var crono: PlayerObject = Settings.player_array[0] + var signals: GdUnitSignalAssert = assert_signal(monitor_signals(_panel)) - (_rows()[0].get_node("HBoxContainer/RemovePlayer") as BaseButton).pressed.emit() + (_rows()[0].get_node("HBoxContainer/RemovePlayer") as BaseButton).pressed.emit() - await signals.is_emitted("player_removed", [crono]) - assert_array(Settings.player_array.map( - func(p: PlayerObject) -> String: return p.player_name)).contains_exactly(["Marle"]) - assert_int(_rows().size()).is_equal(1) - assert_int((_rows()[0] as Player).list_index).is_equal(0) + await signals.is_emitted("player_removed", [crono]) + assert_array(Settings.player_array.map( + func(p: PlayerObject) -> String: return p.player_name)).contains_exactly(["Marle"]) + assert_int(_rows().size()).is_equal(1) + assert_int((_rows()[0] as Player).list_index).is_equal(0) func test_character_button_asks_for_a_new_character() -> void: - _add("Crono") - var row: Player = _rows()[0] - var signals: GdUnitSignalAssert = assert_signal(monitor_signals(_panel)) + _add("Crono") + var row: Player = _rows()[0] + var signals: GdUnitSignalAssert = assert_signal(monitor_signals(_panel)) - (row.get_node("HBoxContainer/Character") as BaseButton).pressed.emit() + (row.get_node("HBoxContainer/Character") as BaseButton).pressed.emit() - await signals.is_emitted("change_character_requested", [row, "Crono"]) + await signals.is_emitted("change_character_requested", [row, "Crono"]) func test_reload_shows_new_scores() -> void: - _add("Crono") - Settings.player_array[0].player_score = 3 + _add("Crono") + Settings.player_array[0].player_score = 3 - _panel.reload() + _panel.reload() - assert_str(((_rows()[0] as Player).get_node("HBoxContainer/Name") as Label).text) \ - .ends_with("Crono: 3") + assert_str(((_rows()[0] as Player).get_node("HBoxContainer/Name") as Label).text) \ + .ends_with("Crono: 3") diff --git a/tests/integration/test_popups.gd b/tests/integration/test_popups.gd index 0eb2c3b..cd45caa 100644 --- a/tests/integration/test_popups.gd +++ b/tests/integration/test_popups.gd @@ -5,127 +5,127 @@ extends MainWindowTestSuite ## Popups opened from the top bar, in the main window. const MAIN_POPUPS: Array[String] = [ - "Search", "SyncWindow", "QRWindow", "ShortcutsWindow", "AboutWindow", + "Search", "SyncWindow", "QRWindow", "ShortcutsWindow", "AboutWindow", ] ## Popups opened from the quiz, in the Quiz scene. const QUIZ_POPUPS: Array[String] = [ - "SettingsWindow", "NewCharacterSelect", "WinnerWindow", "Log", + "SettingsWindow", "NewCharacterSelect", "WinnerWindow", "Log", ] func _popup(node_name: String) -> PopupWindow: - return _quiz.get_node(node_name) if node_name in QUIZ_POPUPS \ - else _window.get_node(node_name) + return _quiz.get_node(node_name) if node_name in QUIZ_POPUPS \ + else _window.get_node(node_name) ## The backdrop that shows behind [param popup]. func _backdrop(popup: PopupWindow = _popup("SettingsWindow")) -> ColorRect: - return popup.get_parent().get_node("PopupBackdrop") + return popup.get_parent().get_node("PopupBackdrop") ## A point on screen outside the popup's panel. func _outside(popup: PopupWindow) -> Vector2: - var rect: Rect2 = popup.panel.get_global_rect() - return Vector2(rect.end.x + 5, rect.end.y + 5) if rect.end.x < 1900 \ - else Vector2(rect.position.x - 5, rect.position.y - 5) + var rect: Rect2 = popup.panel.get_global_rect() + return Vector2(rect.end.x + 5, rect.end.y + 5) if rect.end.x < 1900 \ + else Vector2(rect.position.x - 5, rect.position.y - 5) func test_backdrops_are_hidden_without_popups() -> void: - assert_bool(_backdrop(_popup("SettingsWindow")).visible).is_false() - assert_bool(_backdrop(_popup("AboutWindow")).visible).is_false() + assert_bool(_backdrop(_popup("SettingsWindow")).visible).is_false() + assert_bool(_backdrop(_popup("AboutWindow")).visible).is_false() func test_backdrops_cover_the_whole_window() -> void: - for node_name: String in ["SettingsWindow", "AboutWindow"]: - var popup: PopupWindow = _popup(node_name) - popup.open() + for node_name: String in ["SettingsWindow", "AboutWindow"]: + var popup: PopupWindow = _popup(node_name) + popup.open() - assert_object(_backdrop(popup).get_global_rect()).override_failure_message( - "%s: backdrop does not cover the window" % node_name) \ - .is_equal(_window.get_viewport_rect()) - popup.close() + assert_object(_backdrop(popup).get_global_rect()).override_failure_message( + "%s: backdrop does not cover the window" % node_name) \ + .is_equal(_window.get_viewport_rect()) + popup.close() func test_every_popup_is_a_popup_window() -> void: - for node_name: String in MAIN_POPUPS + QUIZ_POPUPS: - assert_object(_popup(node_name)).is_instanceof(PopupWindow) + for node_name: String in MAIN_POPUPS + QUIZ_POPUPS: + assert_object(_popup(node_name)).is_instanceof(PopupWindow) func test_every_popup_shows_backdrop_and_closes_on_outside_click() -> void: - for node_name: String in MAIN_POPUPS + QUIZ_POPUPS: - var popup: PopupWindow = _popup(node_name) - popup.open() - await _runner.simulate_frames(1) - assert_bool(_backdrop(popup).visible).override_failure_message( - "%s: backdrop not shown" % node_name).is_true() + for node_name: String in MAIN_POPUPS + QUIZ_POPUPS: + var popup: PopupWindow = _popup(node_name) + popup.open() + await _runner.simulate_frames(1) + assert_bool(_backdrop(popup).visible).override_failure_message( + "%s: backdrop not shown" % node_name).is_true() - await _click_at(_outside(popup)) + await _click_at(_outside(popup)) - assert_bool(popup.visible).override_failure_message( - "%s: not closed by outside click" % node_name).is_false() - assert_bool(_backdrop(popup).visible).override_failure_message( - "%s: backdrop still shown" % node_name).is_false() + assert_bool(popup.visible).override_failure_message( + "%s: not closed by outside click" % node_name).is_false() + assert_bool(_backdrop(popup).visible).override_failure_message( + "%s: backdrop still shown" % node_name).is_false() func test_click_inside_popup_keeps_it_open() -> void: - var settings: PopupWindow = _popup("SettingsWindow") - settings.open() - await _runner.simulate_frames(1) + var settings: PopupWindow = _popup("SettingsWindow") + settings.open() + await _runner.simulate_frames(1) - await _click_at(settings.panel.get_global_rect().get_center()) + await _click_at(settings.panel.get_global_rect().get_center()) - assert_bool(settings.visible).is_true() + assert_bool(settings.visible).is_true() func test_closing_click_does_not_press_button_behind_popup() -> void: - var settings: PopupWindow = _popup("SettingsWindow") - var reset_button: Button = _quiz.get_node("ResetPlaylistButton") - settings.open() - await _runner.simulate_frames(1) - assert_bool(settings.panel.get_global_rect().intersects(reset_button.get_global_rect())) \ - .is_false() + var settings: PopupWindow = _popup("SettingsWindow") + var reset_button: Button = _quiz.get_node("ResetPlaylistButton") + settings.open() + await _runner.simulate_frames(1) + assert_bool(settings.panel.get_global_rect().intersects(reset_button.get_global_rect())) \ + .is_false() - await _click_at(reset_button.get_global_rect().get_center()) + await _click_at(reset_button.get_global_rect().get_center()) - assert_bool(settings.visible).is_false() - assert_int(_server.count("/music/reset")).is_equal(0) + assert_bool(settings.visible).is_false() + assert_int(_server.count("/music/reset")).is_equal(0) func test_button_works_again_after_popup_closed() -> void: - var reset_button: Button = _quiz.get_node("ResetPlaylistButton") + var reset_button: Button = _quiz.get_node("ResetPlaylistButton") - await _click_at(reset_button.get_global_rect().get_center()) + await _click_at(reset_button.get_global_rect().get_center()) - assert_int(_server.count("/music/reset")).is_equal(1) + assert_int(_server.count("/music/reset")).is_equal(1) func test_closing_search_clears_the_search() -> void: - var search: PopupWindow = _popup("Search") - search.open() - var search_bar: TextEdit = search.get_node("Searchbar") - search_bar.text = "mario" + var search: PopupWindow = _popup("Search") + search.open() + var search_bar: TextEdit = search.get_node("Searchbar") + search_bar.text = "mario" - search.close() + search.close() - assert_str(search_bar.text).is_empty() + assert_str(search_bar.text).is_empty() func test_closing_character_select_allows_song_clicks_again() -> void: - var character_select: PopupWindow = _popup("NewCharacterSelect") - character_select.show_grid("Crono") - assert_bool(Settings.character_select_open).is_true() + var character_select: PopupWindow = _popup("NewCharacterSelect") + character_select.show_grid("Crono") + assert_bool(Settings.character_select_open).is_true() - character_select.close() + character_select.close() - assert_bool(Settings.character_select_open).is_false() + assert_bool(Settings.character_select_open).is_false() func test_toggle_opens_and_closes() -> void: - var shortcuts: PopupWindow = _popup("ShortcutsWindow") + var shortcuts: PopupWindow = _popup("ShortcutsWindow") - shortcuts.toggle() - assert_bool(shortcuts.visible).is_true() + shortcuts.toggle() + assert_bool(shortcuts.visible).is_true() - shortcuts.toggle() - assert_bool(shortcuts.visible).is_false() + shortcuts.toggle() + assert_bool(shortcuts.visible).is_false() diff --git a/tests/integration/test_scene_split.gd b/tests/integration/test_scene_split.gd index 4291818..b1455fc 100644 --- a/tests/integration/test_scene_split.gd +++ b/tests/integration/test_scene_split.gd @@ -5,239 +5,239 @@ extends MainWindowTestSuite ## server and the keyboard shortcuts reach both the main window and the quiz. const MAIN_WINDOW_CHILDREN: Array[String] = [ - "TopBar", "Quiz", "PopupBackdrop", "Search", "SyncWindow", "QRWindow", - "ShortcutsWindow", "StatisticsPopupPanel", "AboutWindow", + "TopBar", "Quiz", "PopupBackdrop", "Search", "SyncWindow", "QRWindow", + "ShortcutsWindow", "StatisticsPopupPanel", "AboutWindow", ] const TOP_BAR_CHILDREN: Array[String] = [ - "TopPanelContainer", "Title", "SyncButton", "SearchButton", "StatisticsButton", - "ShortcutsButton", "AboutButton", "QRButton", + "TopPanelContainer", "Title", "SyncButton", "SearchButton", "StatisticsButton", + "ShortcutsButton", "AboutButton", "QRButton", ] ## Each top bar button and the popup it opens in the main window. const TOP_BAR_POPUPS: Dictionary = { - "SearchButton": "Search", - "SyncButton": "SyncWindow", - "StatisticsButton": "StatisticsPopupPanel", - "ShortcutsButton": "ShortcutsWindow", - "AboutButton": "AboutWindow", - "QRButton": "QRWindow", + "SearchButton": "Search", + "SyncButton": "SyncWindow", + "StatisticsButton": "StatisticsPopupPanel", + "ShortcutsButton": "ShortcutsWindow", + "AboutButton": "AboutWindow", + "QRButton": "QRWindow", } func _top_bar_button(button_name: String) -> Button: - return _window.get_node("TopBar/" + button_name) + return _window.get_node("TopBar/" + button_name) func _children(node: Node) -> Array[String]: - var names: Array[String] = [] - for child: Node in node.get_children(): - names.append(String(child.name)) - return names + var names: Array[String] = [] + for child: Node in node.get_children(): + names.append(String(child.name)) + return names func _center(control: Control) -> Vector2: - return control.get_global_rect().get_center() + return control.get_global_rect().get_center() func test_main_window_holds_only_top_bar_quiz_and_its_popups() -> void: - assert_array(_children(_window)).contains_exactly_in_any_order(MAIN_WINDOW_CHILDREN) + assert_array(_children(_window)).contains_exactly_in_any_order(MAIN_WINDOW_CHILDREN) func test_top_bar_is_drawn_below_the_quiz() -> void: - # The quiz popups' backdrop has to cover the top bar too - assert_int(_window.get_node("TopBar").get_index()) \ - .is_less(_window.get_node("Quiz").get_index()) + # The quiz popups' backdrop has to cover the top bar too + assert_int(_window.get_node("TopBar").get_index()) \ + .is_less(_window.get_node("Quiz").get_index()) func test_quiz_parts_are_their_own_scenes() -> void: - for node_name: String in ["MusicListPanel", "PlayersPanel", "InspirationList"]: - assert_str(_quiz.get_node(node_name).scene_file_path) \ - .is_equal("res://%s.tscn" % node_name) + for node_name: String in ["MusicListPanel", "PlayersPanel", "InspirationList"]: + assert_str(_quiz.get_node(node_name).scene_file_path) \ + .is_equal("res://%s.tscn" % node_name) func test_top_bar_holds_only_title_and_buttons() -> void: - assert_array(_children(_window.get_node("TopBar"))) \ - .contains_exactly_in_any_order(TOP_BAR_CHILDREN) + assert_array(_children(_window.get_node("TopBar"))) \ + .contains_exactly_in_any_order(TOP_BAR_CHILDREN) func test_quiz_and_top_bar_let_clicks_through_where_they_are_empty() -> void: - assert_int(_quiz.mouse_filter).is_equal(Control.MOUSE_FILTER_IGNORE) - assert_int((_window.get_node("TopBar") as Control).mouse_filter) \ - .is_equal(Control.MOUSE_FILTER_IGNORE) + assert_int(_quiz.mouse_filter).is_equal(Control.MOUSE_FILTER_IGNORE) + assert_int((_window.get_node("TopBar") as Control).mouse_filter) \ + .is_equal(Control.MOUSE_FILTER_IGNORE) func test_clicking_each_top_bar_button_opens_its_popup() -> void: - for button_name: String in TOP_BAR_POPUPS: - var popup: Node = _window.get_node(TOP_BAR_POPUPS[button_name]) + for button_name: String in TOP_BAR_POPUPS: + var popup: Node = _window.get_node(TOP_BAR_POPUPS[button_name]) - await _click_at(_center(_top_bar_button(button_name))) + await _click_at(_center(_top_bar_button(button_name))) - assert_bool(popup.visible).override_failure_message( - "%s did not open %s" % [button_name, popup.name]).is_true() - if popup is PopupWindow: - popup.close() - else: - popup.visible = false - await _runner.simulate_frames(1) + assert_bool(popup.visible).override_failure_message( + "%s did not open %s" % [button_name, popup.name]).is_true() + if popup is PopupWindow: + popup.close() + else: + popup.visible = false + await _runner.simulate_frames(1) func test_clicking_quiz_buttons_plays_and_shows_answer() -> void: - await _click_at(_center(_quiz.get_node("NextButton"))) - await _runner.simulate_frames(2) - assert_int(Playlist.currently_playing_song).is_equal(0) - assert_str((_quiz.get_node("VBoxContainer/SoundtrackLabel") as Label).text) \ - .is_not_equal("Chrono Trigger") + await _click_at(_center(_quiz.get_node("NextButton"))) + await _runner.simulate_frames(2) + assert_int(Playlist.currently_playing_song).is_equal(0) + assert_str((_quiz.get_node("VBoxContainer/SoundtrackLabel") as Label).text) \ + .is_not_equal("Chrono Trigger") - await _click_at(_center(_quiz.get_node("ShowAnswerButton"))) + await _click_at(_center(_quiz.get_node("ShowAnswerButton"))) - assert_str((_quiz.get_node("VBoxContainer/SoundtrackLabel") as Label).text) \ - .is_equal("Chrono Trigger") + assert_str((_quiz.get_node("VBoxContainer/SoundtrackLabel") as Label).text) \ + .is_equal("Chrono Trigger") func test_clicking_a_song_in_the_music_list_plays_it() -> void: - _next_song_is(SONG_INFO[1]) - await _play_first_song() - _press("NextButton") - # Changing song waits a moment for the old one to stop - await get_tree().create_timer(0.7).timeout - assert_int(Playlist.currently_playing_song).is_equal(1) - var rows: Array[Node] = _quiz.get_node("MusicListPanel/ScrollContainer/MusicList") \ - .get_children() - var first_row: Control = rows.filter( - func(row: SongListObject) -> bool: return row.song_object.song_number == 0)[0] + _next_song_is(SONG_INFO[1]) + await _play_first_song() + _press("NextButton") + # Changing song waits a moment for the old one to stop + await get_tree().create_timer(0.7).timeout + assert_int(Playlist.currently_playing_song).is_equal(1) + var rows: Array[Node] = _quiz.get_node("MusicListPanel/ScrollContainer/MusicList") \ + .get_children() + var first_row: Control = rows.filter( + func(row: SongListObject) -> bool: return row.song_object.song_number == 0)[0] - await _click_at(first_row.get_global_rect().position + Vector2(20, first_row.size.y / 2)) - await get_tree().create_timer(0.7).timeout + await _click_at(first_row.get_global_rect().position + Vector2(20, first_row.size.y / 2)) + await get_tree().create_timer(0.7).timeout - assert_int(Playlist.currently_playing_song).is_equal(0) + assert_int(Playlist.currently_playing_song).is_equal(0) func test_points_from_the_player_list_reach_the_song_and_log() -> void: - await _play_first_song() - var crono: PlayerObject = _add_player("Crono") + await _play_first_song() + var crono: PlayerObject = _add_player("Crono") - (_player_row(crono).get_node("HBoxContainer/AddPoint") as BaseButton).pressed.emit() + (_player_row(crono).get_node("HBoxContainer/AddPoint") as BaseButton).pressed.emit() - assert_array(Playlist.song_object_array[0].players_given_point).contains_exactly([crono.id]) - assert_int((_quiz.get_node("%Log").get_node("%LogVBoxContainer") as Node).get_child_count()) \ - .is_equal(1) + assert_array(Playlist.song_object_array[0].players_given_point).contains_exactly([crono.id]) + assert_int((_quiz.get_node("%Log").get_node("%LogVBoxContainer") as Node).get_child_count()) \ + .is_equal(1) func test_character_button_in_the_player_list_picks_a_new_character() -> void: - var crono: PlayerObject = _add_player("Crono") - var character_select: PopupWindow = _quiz.get_node("NewCharacterSelect") + var crono: PlayerObject = _add_player("Crono") + var character_select: PopupWindow = _quiz.get_node("NewCharacterSelect") - (_player_row(crono).get_node("HBoxContainer/Character") as BaseButton).pressed.emit() + (_player_row(crono).get_node("HBoxContainer/Character") as BaseButton).pressed.emit() - assert_bool(character_select.visible).is_true() - var texture: ImageTexture = ImageTexture.create_from_image( - Image.create(4, 4, false, Image.FORMAT_RGBA8)) - character_select.new_new_character_selected.emit(texture) - assert_object(crono.character).is_same(texture) + assert_bool(character_select.visible).is_true() + var texture: ImageTexture = ImageTexture.create_from_image( + Image.create(4, 4, false, Image.FORMAT_RGBA8)) + character_select.new_new_character_selected.emit(texture) + assert_object(crono.character).is_same(texture) func test_quiz_popup_backdrop_covers_the_top_bar() -> void: - var settings: PopupWindow = _quiz.get_node("SettingsWindow") - settings.open() - await _runner.simulate_frames(1) + var settings: PopupWindow = _quiz.get_node("SettingsWindow") + settings.open() + await _runner.simulate_frames(1) - var backdrop: Control = _quiz.get_node("PopupBackdrop") - assert_bool(backdrop.visible).is_true() - assert_bool(backdrop.get_global_rect().encloses( - (_window.get_node("TopBar/TopPanelContainer") as Control).get_global_rect())) \ - .is_true() + var backdrop: Control = _quiz.get_node("PopupBackdrop") + assert_bool(backdrop.visible).is_true() + assert_bool(backdrop.get_global_rect().encloses( + (_window.get_node("TopBar/TopPanelContainer") as Control).get_global_rect())) \ + .is_true() func test_click_on_top_bar_while_quiz_popup_is_open_only_closes_it() -> void: - var settings: PopupWindow = _quiz.get_node("SettingsWindow") - var search: PopupWindow = _window.get_node("Search") - settings.open() - await _runner.simulate_frames(1) + var settings: PopupWindow = _quiz.get_node("SettingsWindow") + var search: PopupWindow = _window.get_node("Search") + settings.open() + await _runner.simulate_frames(1) - await _click_at(_center(_top_bar_button("SearchButton"))) + await _click_at(_center(_top_bar_button("SearchButton"))) - assert_bool(settings.visible).is_false() - assert_bool(search.visible).is_false() + assert_bool(settings.visible).is_false() + assert_bool(search.visible).is_false() func test_sync_disables_quiz_buttons_until_finished() -> void: - _server.respond_bytes("/sync", PackedByteArray()) - _server.respond_json("/sync/progress", {"progress": 10, "time_spent": "00:00:01"}) - var sync_window: PopupWindow = _window.get_node("SyncWindow") + _server.respond_bytes("/sync", PackedByteArray()) + _server.respond_json("/sync/progress", {"progress": 10, "time_spent": "00:00:01"}) + var sync_window: PopupWindow = _window.get_node("SyncWindow") - _top_bar_button("SyncButton").pressed.emit() - sync_window.sync_timer.stop() + _top_bar_button("SyncButton").pressed.emit() + sync_window.sync_timer.stop() - for button_name: String in ["SoundTestButton", "ResetPlaylistButton", "ShowAnswerButton", - "NextButton"]: - assert_bool((_quiz.get_node(button_name) as Button).disabled) \ - .override_failure_message(button_name + " not disabled").is_true() - assert_bool(_top_bar_button("SyncButton").disabled).is_false() + for button_name: String in ["SoundTestButton", "ResetPlaylistButton", "ShowAnswerButton", + "NextButton"]: + assert_bool((_quiz.get_node(button_name) as Button).disabled) \ + .override_failure_message(button_name + " not disabled").is_true() + assert_bool(_top_bar_button("SyncButton").disabled).is_false() - _server.respond_json("/sync/progress", UiTour.SYNC_RESULT) - var reloads_before: int = _server.count("/music/all/order") - sync_window._on_sync_timeout() - await _runner.simulate_frames(2) + _server.respond_json("/sync/progress", UiTour.SYNC_RESULT) + var reloads_before: int = _server.count("/music/all/order") + sync_window._on_sync_timeout() + await _runner.simulate_frames(2) - for button_name: String in ["SoundTestButton", "ResetPlaylistButton", "ShowAnswerButton", - "NextButton"]: - assert_bool((_quiz.get_node(button_name) as Button).disabled) \ - .override_failure_message(button_name + " still disabled").is_false() - # The search list in the main window and the quiz playlist are both reloaded - assert_int(_server.count("/music/all/order")).is_equal(reloads_before + 1) - assert_int(_server.count("/music/reset")).is_equal(1) + for button_name: String in ["SoundTestButton", "ResetPlaylistButton", "ShowAnswerButton", + "NextButton"]: + assert_bool((_quiz.get_node(button_name) as Button).disabled) \ + .override_failure_message(button_name + " still disabled").is_false() + # The search list in the main window and the quiz playlist are both reloaded + assert_int(_server.count("/music/all/order")).is_equal(reloads_before + 1) + assert_int(_server.count("/music/reset")).is_equal(1) func test_changing_server_reloads_search_and_quiz() -> void: - var search_loads: int = _server.count("/music/all/order") - var inspiration_loads: int = _server.count("/music/all") - var player: PlayerObject = _add_player("Crono") - player.add_point() + var search_loads: int = _server.count("/music/all/order") + var inspiration_loads: int = _server.count("/music/all") + var player: PlayerObject = _add_player("Crono") + player.add_point() - _quiz.get_node("SettingsWindow").server_changed.emit() + _quiz.get_node("SettingsWindow").server_changed.emit() - assert_int(_server.count("/music/all/order")).is_equal(search_loads + 1) - assert_int(_server.count("/music/all")).is_equal(inspiration_loads + 1) - assert_int(_server.count("/music/reset")).is_equal(1) - assert_int(player.player_score).is_equal(0) + assert_int(_server.count("/music/all/order")).is_equal(search_loads + 1) + assert_int(_server.count("/music/all")).is_equal(inspiration_loads + 1) + assert_int(_server.count("/music/reset")).is_equal(1) + assert_int(player.player_score).is_equal(0) func test_alt_k_opens_shortcuts_and_alt_l_opens_log() -> void: - await _press_keys([KEY_ALT, KEY_K]) - assert_bool((_window.get_node("ShortcutsWindow") as Control).visible).is_true() + await _press_keys([KEY_ALT, KEY_K]) + assert_bool((_window.get_node("ShortcutsWindow") as Control).visible).is_true() - await _press_keys([KEY_ALT, KEY_L]) - assert_bool((_quiz.get_node("Log") as Control).visible).is_true() + await _press_keys([KEY_ALT, KEY_L]) + assert_bool((_quiz.get_node("Log") as Control).visible).is_true() func test_alt_down_lowers_the_volume() -> void: - var bus: int = AudioServer.get_bus_index("Master") - var volume_db: float = AudioServer.get_bus_volume_db(bus) - var slider: HSlider = _quiz.get_node("MusicPlayer").volume_slider - var volume: float = slider.value + var bus: int = AudioServer.get_bus_index("Master") + var volume_db: float = AudioServer.get_bus_volume_db(bus) + var slider: HSlider = _quiz.get_node("MusicPlayer").volume_slider + var volume: float = slider.value - await _press_keys([KEY_ALT, KEY_DOWN]) + await _press_keys([KEY_ALT, KEY_DOWN]) - assert_float(slider.value).is_less(volume) - AudioServer.set_bus_volume_db(bus, volume_db) + assert_float(slider.value).is_less(volume) + AudioServer.set_bus_volume_db(bus, volume_db) func test_alt_enter_switches_fullscreen_and_settings_shows_it() -> void: - var settings: PopupWindow = _quiz.get_node("SettingsWindow") - var was_fullscreen: bool = Settings.fullscreen + var settings: PopupWindow = _quiz.get_node("SettingsWindow") + var was_fullscreen: bool = Settings.fullscreen - await _press_keys([KEY_ALT, KEY_ENTER]) - settings.open() + await _press_keys([KEY_ALT, KEY_ENTER]) + settings.open() - assert_bool(Settings.fullscreen).is_equal(!was_fullscreen) - assert_bool(settings.fullscreen_button.button_pressed).is_equal(!was_fullscreen) - await _press_keys([KEY_ALT, KEY_ENTER]) - assert_bool(Settings.fullscreen).is_equal(was_fullscreen) + assert_bool(Settings.fullscreen).is_equal(!was_fullscreen) + assert_bool(settings.fullscreen_button.button_pressed).is_equal(!was_fullscreen) + await _press_keys([KEY_ALT, KEY_ENTER]) + assert_bool(Settings.fullscreen).is_equal(was_fullscreen) func test_statistics_counts_the_soundtracks() -> void: - _top_bar_button("StatisticsButton").pressed.emit() + _top_bar_button("StatisticsButton").pressed.emit() - assert_str((_window.get_node("StatisticsPopupPanel/StatisticsLabel") as Label).text) \ - .is_equal("Total amount of soundtracks in the playlist: 2") + assert_str((_window.get_node("StatisticsPopupPanel/StatisticsLabel") as Label).text) \ + .is_equal("Total amount of soundtracks in the playlist: 2") diff --git a/tests/integration/test_stats_after_win.gd b/tests/integration/test_stats_after_win.gd index 3a743f2..0a5bc60 100644 --- a/tests/integration/test_stats_after_win.gd +++ b/tests/integration/test_stats_after_win.gd @@ -5,61 +5,61 @@ var _crono: PlayerObject func before_test() -> void: - super() - _crono = _add_player("Crono") - await _play_first_song() - Settings.winning_score = 1 + super() + _crono = _add_player("Crono") + await _play_first_song() + Settings.winning_score = 1 func _stats_checkbox() -> CheckButton: - return _quiz.get_node("SettingsWindow").get_node("%AddToDatabaseCheckButton") + return _quiz.get_node("SettingsWindow").get_node("%AddToDatabaseCheckButton") func test_winning_turns_statistics_off() -> void: - await _give_point_with_keybind(1) + await _give_point_with_keybind(1) - assert_bool(Settings.add_to_stats).is_false() + assert_bool(Settings.add_to_stats).is_false() func test_resetting_points_turns_statistics_back_on() -> void: - await _give_point_with_keybind(1) + await _give_point_with_keybind(1) - _press("ResetPointsButton") + _press("ResetPointsButton") - assert_bool(Settings.add_to_stats).is_true() + assert_bool(Settings.add_to_stats).is_true() func test_statistics_turned_off_by_hand_stay_off_after_reset() -> void: - Settings.add_to_stats = false - await _give_point_with_keybind(1) + Settings.add_to_stats = false + await _give_point_with_keybind(1) - _press("ResetPointsButton") + _press("ResetPointsButton") - assert_bool(Settings.add_to_stats).is_false() + assert_bool(Settings.add_to_stats).is_false() func test_settings_checkbox_shows_statistics_off_after_win() -> void: - await _give_point_with_keybind(1) + await _give_point_with_keybind(1) - _press("SettingsButton") + _press("SettingsButton") - assert_bool(_stats_checkbox().button_pressed).is_false() + assert_bool(_stats_checkbox().button_pressed).is_false() func test_songs_after_a_win_are_not_counted() -> void: - await _give_point_with_keybind(1) - var played_before: int = _server.count("/music/played?song=0") + await _give_point_with_keybind(1) + var played_before: int = _server.count("/music/played?song=0") - _press("ShowAnswerButton") + _press("ShowAnswerButton") - assert_int(_server.count("/music/played?song=0")).is_equal(played_before) + assert_int(_server.count("/music/played?song=0")).is_equal(played_before) func test_winning_score_cannot_go_below_one() -> void: - _press("SettingsButton") - var lower_button: Button = _quiz.get_node("SettingsWindow").get_node("%LowerButton") + _press("SettingsButton") + var lower_button: Button = _quiz.get_node("SettingsWindow").get_node("%LowerButton") - for i: int in 3: - lower_button.pressed.emit() + for i: int in 3: + lower_button.pressed.emit() - assert_int(Settings.winning_score).is_equal(1) + assert_int(Settings.winning_score).is_equal(1) diff --git a/tests/integration/test_sync_window.gd b/tests/integration/test_sync_window.gd index 60e3dfa..210ef0a 100644 --- a/tests/integration/test_sync_window.gd +++ b/tests/integration/test_sync_window.gd @@ -7,194 +7,194 @@ var _window: Control func before_test() -> void: - _snapshot = AutoloadSnapshot.take([Settings]) - Settings.currently_syncing = false - _server = FakeHttpTransport.new().install() - _server.respond_bytes("/sync", PackedByteArray()) - _runner = scene_runner("res://SyncWindow.tscn") - _window = _runner.scene() + _snapshot = AutoloadSnapshot.take([Settings]) + Settings.currently_syncing = false + _server = FakeHttpTransport.new().install() + _server.respond_bytes("/sync", PackedByteArray()) + _runner = scene_runner("res://SyncWindow.tscn") + _window = _runner.scene() func after_test() -> void: - _server.uninstall() - _snapshot.restore() + _server.uninstall() + _snapshot.restore() func _node(unique_name: String) -> Control: - return _window.get_node("%" + unique_name) + return _window.get_node("%" + unique_name) func _finish_sync(result: Dictionary) -> void: - _server.respond_json("/sync/progress", result) - _runner.invoke("_on_sync_timeout") + _server.respond_json("/sync/progress", result) + _runner.invoke("_on_sync_timeout") func _empty_result() -> Dictionary: - return { - "soundtracks_added": [], - "soundtracks_re_added": [], - "soundtracks_changed_title": {}, - "soundtracks_changed_content": [], - "soundtracks_removed": [], - "catched_errors": [], - "total_time": "00:00:03", - } + return { + "soundtracks_added": [], + "soundtracks_re_added": [], + "soundtracks_changed_title": {}, + "soundtracks_changed_content": [], + "soundtracks_removed": [], + "catched_errors": [], + "total_time": "00:00:03", + } func test_start_sync_asks_server_and_shows_progress() -> void: - monitor_signals(_window, false) + monitor_signals(_window, false) - _runner.invoke("start_sync") + _runner.invoke("start_sync") - assert_array(_server.requested_paths).contains_exactly(["/sync"]) - assert_bool(Settings.currently_syncing).is_true() - assert_bool(_node("ProgressHBoxContainer").visible).is_true() - assert_str(_node("SyncTitleLabel").text).is_equal("Sync in Progress") - await assert_signal(_window).is_emitted("sync_started") + assert_array(_server.requested_paths).contains_exactly(["/sync"]) + assert_bool(Settings.currently_syncing).is_true() + assert_bool(_node("ProgressHBoxContainer").visible).is_true() + assert_str(_node("SyncTitleLabel").text).is_equal("Sync in Progress") + await assert_signal(_window).is_emitted("sync_started") func test_start_sync_does_nothing_while_already_syncing() -> void: - Settings.currently_syncing = true + Settings.currently_syncing = true - _runner.invoke("start_sync") + _runner.invoke("start_sync") - assert_array(_server.requested_paths).is_empty() + assert_array(_server.requested_paths).is_empty() func test_progress_updates_progress_bar() -> void: - _runner.invoke("start_sync") - _server.respond_json("/sync/progress", {"progress": "42", "time_spent": "00:00:12"}) + _runner.invoke("start_sync") + _server.respond_json("/sync/progress", {"progress": "42", "time_spent": "00:00:12"}) - _runner.invoke("_on_sync_timeout") + _runner.invoke("_on_sync_timeout") - assert_float(_node("SyncProgressBar").value).is_equal(42.0) - assert_str(_node("SyncTime").text).is_equal("00:00:12") + assert_float(_node("SyncProgressBar").value).is_equal(42.0) + assert_str(_node("SyncTime").text).is_equal("00:00:12") func test_finished_sync_shows_only_sections_with_changes() -> void: - _runner.invoke("start_sync") - monitor_signals(_window, false) - var result: Dictionary = _empty_result() - result.soundtracks_added = ["Chrono Cross", "Xenogears"] - result.soundtracks_removed = ["Bad Rip"] + _runner.invoke("start_sync") + monitor_signals(_window, false) + var result: Dictionary = _empty_result() + result.soundtracks_added = ["Chrono Cross", "Xenogears"] + result.soundtracks_removed = ["Bad Rip"] - _finish_sync(result) + _finish_sync(result) - assert_bool(_node("SoundtracksAddedVBox").visible).is_true() - assert_bool(_node("SoundtracksRemovedVBox").visible).is_true() - assert_bool(_node("SoundtracksReAddedVBox").visible).is_false() - assert_bool(_node("SoundtracksChangedTitleVBox").visible).is_false() - assert_bool(_node("NoChangesLabel").visible).is_false() - # Header plus one label per soundtrack - assert_int(_node("SoundtracksAddedVBox").get_child_count()).is_equal(3) - assert_str(_node("SyncTime").text).is_equal("Total time: 00:00:03") - assert_bool(Settings.currently_syncing).is_false() - await assert_signal(_window).is_emitted("sync_finished") + assert_bool(_node("SoundtracksAddedVBox").visible).is_true() + assert_bool(_node("SoundtracksRemovedVBox").visible).is_true() + assert_bool(_node("SoundtracksReAddedVBox").visible).is_false() + assert_bool(_node("SoundtracksChangedTitleVBox").visible).is_false() + assert_bool(_node("NoChangesLabel").visible).is_false() + # Header plus one label per soundtrack + assert_int(_node("SoundtracksAddedVBox").get_child_count()).is_equal(3) + assert_str(_node("SyncTime").text).is_equal("Total time: 00:00:03") + assert_bool(Settings.currently_syncing).is_false() + await assert_signal(_window).is_emitted("sync_finished") func test_separator_shown_only_between_visible_sections() -> void: - _runner.invoke("start_sync") - var result: Dictionary = _empty_result() - result.soundtracks_added = ["Chrono Cross"] - result.soundtracks_removed = ["Bad Rip"] + _runner.invoke("start_sync") + var result: Dictionary = _empty_result() + result.soundtracks_added = ["Chrono Cross"] + result.soundtracks_removed = ["Bad Rip"] - _finish_sync(result) + _finish_sync(result) - assert_bool(_node("SoundtracksAddedSeparator").visible).is_true() - assert_bool(_node("SoundtracksRemovedSeparator").visible).is_false() + assert_bool(_node("SoundtracksAddedSeparator").visible).is_true() + assert_bool(_node("SoundtracksRemovedSeparator").visible).is_false() func test_changed_titles_list_old_and_new_title() -> void: - _runner.invoke("start_sync") - var result: Dictionary = _empty_result() - result.soundtracks_changed_title = {"FF7": "Final Fantasy VII"} + _runner.invoke("start_sync") + var result: Dictionary = _empty_result() + result.soundtracks_changed_title = {"FF7": "Final Fantasy VII"} - _finish_sync(result) + _finish_sync(result) - var vbox: Control = _node("SoundtracksChangedTitleVBox") - assert_bool(vbox.visible).is_true() - assert_str((vbox.get_child(1) as ListRow).text).is_equal( - "FF7\nchanged title to\nFinal Fantasy VII") + var vbox: Control = _node("SoundtracksChangedTitleVBox") + assert_bool(vbox.visible).is_true() + assert_str((vbox.get_child(1) as ListRow).text).is_equal( + "FF7\nchanged title to\nFinal Fantasy VII") func test_no_changes_shows_no_changes_label() -> void: - _runner.invoke("start_sync") + _runner.invoke("start_sync") - _finish_sync(_empty_result()) + _finish_sync(_empty_result()) - assert_bool(_node("NoChangesLabel").visible).is_true() + assert_bool(_node("NoChangesLabel").visible).is_true() func test_errors_are_listed() -> void: - _runner.invoke("start_sync") - var result: Dictionary = _empty_result() - result.catched_errors = ["Could not read tags in broken.mp3"] + _runner.invoke("start_sync") + var result: Dictionary = _empty_result() + result.catched_errors = ["Could not read tags in broken.mp3"] - _finish_sync(result) + _finish_sync(result) - assert_bool(_node("CatchedErrorsVBox").visible).is_true() + assert_bool(_node("CatchedErrorsVBox").visible).is_true() func test_reopening_after_sync_shows_result_without_syncing_again() -> void: - _runner.invoke("start_sync") - _finish_sync(_empty_result()) + _runner.invoke("start_sync") + _finish_sync(_empty_result()) - _runner.invoke("start_sync") + _runner.invoke("start_sync") - assert_int(_server.count("/sync")).is_equal(1) - assert_str(_node("SyncTitleLabel").text).is_equal("Sync Result") + assert_int(_server.count("/sync")).is_equal(1) + assert_str(_node("SyncTitleLabel").text).is_equal("Sync Result") func test_errors_section_has_errors_header() -> void: - _runner.invoke("start_sync") - var result: Dictionary = _empty_result() - result.catched_errors = ["Could not read tags in broken.mp3"] + _runner.invoke("start_sync") + var result: Dictionary = _empty_result() + result.catched_errors = ["Could not read tags in broken.mp3"] - _finish_sync(result) + _finish_sync(result) - assert_str((_node("CatchedErrorsVBox").get_child(0) as Label).text).is_equal("Errors") + assert_str((_node("CatchedErrorsVBox").get_child(0) as Label).text).is_equal("Errors") func test_long_names_wrap_instead_of_widening_the_window() -> void: - _runner.invoke("start_sync") - var long_name: String = "The Legend of Zelda: Breath of the Wild Original Soundtrack" - var result: Dictionary = _empty_result() - result.soundtracks_added = [long_name] - result.soundtracks_re_added = [long_name] - result.soundtracks_changed_content = [long_name] - result.soundtracks_removed = [long_name] - result.soundtracks_changed_title = {long_name: long_name} - result.catched_errors = [long_name + " could not be read"] + _runner.invoke("start_sync") + var long_name: String = "The Legend of Zelda: Breath of the Wild Original Soundtrack" + var result: Dictionary = _empty_result() + result.soundtracks_added = [long_name] + result.soundtracks_re_added = [long_name] + result.soundtracks_changed_content = [long_name] + result.soundtracks_removed = [long_name] + result.soundtracks_changed_title = {long_name: long_name} + result.catched_errors = [long_name + " could not be read"] - _finish_sync(result) - await _runner.simulate_frames(2) + _finish_sync(result) + await _runner.simulate_frames(2) - # The minimum width is what the content needs; wider than the panel it would stick out - var panel_width: float = (_window.get_node("SyncPanel") as Control).size.x - assert_float(_node("SyncHBoxContainer").get_combined_minimum_size().x) \ - .is_less(panel_width) - assert_float(_node("CatchedErrorsVBox").get_combined_minimum_size().x) \ - .is_less(panel_width) + # The minimum width is what the content needs; wider than the panel it would stick out + var panel_width: float = (_window.get_node("SyncPanel") as Control).size.x + assert_float(_node("SyncHBoxContainer").get_combined_minimum_size().x) \ + .is_less(panel_width) + assert_float(_node("CatchedErrorsVBox").get_combined_minimum_size().x) \ + .is_less(panel_width) func test_visible_columns_share_the_width_equally() -> void: - _runner.invoke("start_sync") - var result: Dictionary = _empty_result() - result.soundtracks_added = ["Chrono Cross", "Xenoblade Chronicles X Original Soundtrack"] - result.soundtracks_removed = ["Bad Rip"] + _runner.invoke("start_sync") + var result: Dictionary = _empty_result() + result.soundtracks_added = ["Chrono Cross", "Xenoblade Chronicles X Original Soundtrack"] + result.soundtracks_removed = ["Bad Rip"] - _finish_sync(result) - await _runner.simulate_frames(2) + _finish_sync(result) + await _runner.simulate_frames(2) - assert_float(_node("SoundtracksAddedVBox").size.x).is_equal_approx( - _node("SoundtracksRemovedVBox").size.x, 1.0) + assert_float(_node("SoundtracksAddedVBox").size.x).is_equal_approx( + _node("SoundtracksRemovedVBox").size.x, 1.0) func test_column_headers() -> void: - _runner.invoke("start_sync") - var result: Dictionary = _empty_result() - result.soundtracks_re_added = ["Super Metroid"] + _runner.invoke("start_sync") + var result: Dictionary = _empty_result() + result.soundtracks_re_added = ["Super Metroid"] - _finish_sync(result) + _finish_sync(result) - assert_str((_node("SoundtracksReAddedVBox").get_child(0) as Label).text).is_equal("Re-added") + assert_str((_node("SoundtracksReAddedVBox").get_child(0) as Label).text).is_equal("Re-added") diff --git a/tests/unit/test_http_transport.gd b/tests/unit/test_http_transport.gd index f3e5f25..0a31f82 100644 --- a/tests/unit/test_http_transport.gd +++ b/tests/unit/test_http_transport.gd @@ -8,41 +8,41 @@ var _owner: Node func before_test() -> void: - _server = TCPServer.new() - assert_int(_server.listen(0, "127.0.0.1")).is_equal(OK) - _owner = auto_free(Node.new()) - add_child(_owner) + _server = TCPServer.new() + assert_int(_server.listen(0, "127.0.0.1")).is_equal(OK) + _owner = auto_free(Node.new()) + add_child(_owner) func after_test() -> void: - for connection: StreamPeerTCP in _connections: - connection.disconnect_from_host() - _server.stop() + for connection: StreamPeerTCP in _connections: + connection.disconnect_from_host() + _server.stop() func _accept_connections() -> void: - while _server.is_connection_available(): - _connections.append(_server.take_connection()) + while _server.is_connection_available(): + _connections.append(_server.take_connection()) func test_request_to_silent_server_times_out_as_failed() -> void: - var transport: HttpTransport = HttpTransport.new(_owner) - transport.timeout_seconds = 0.5 - var response_codes: Array[int] = [] + var transport: HttpTransport = HttpTransport.new(_owner) + transport.timeout_seconds = 0.5 + var response_codes: Array[int] = [] - transport.request("http://127.0.0.1:%d/music/rand" % _server.get_local_port(), - HTTPClient.METHOD_GET, - func(response_code: int, _body: PackedByteArray) -> void: - response_codes.append(response_code)) - for i: int in 40: - _accept_connections() - await await_millis(50) - if !response_codes.is_empty(): - break + transport.request("http://127.0.0.1:%d/music/rand" % _server.get_local_port(), + HTTPClient.METHOD_GET, + func(response_code: int, _body: PackedByteArray) -> void: + response_codes.append(response_code)) + for i: int in 40: + _accept_connections() + await await_millis(50) + if !response_codes.is_empty(): + break - assert_bool(_connections.is_empty()).is_false() - assert_array(response_codes).contains_exactly([0]) + assert_bool(_connections.is_empty()).is_false() + assert_array(response_codes).contains_exactly([0]) func test_default_timeout_is_set() -> void: - assert_float(HttpTransport.new(_owner).timeout_seconds).is_greater(0.0) + assert_float(HttpTransport.new(_owner).timeout_seconds).is_greater(0.0) diff --git a/tests/unit/test_list_row.gd b/tests/unit/test_list_row.gd index d25bb06..ce5b428 100644 --- a/tests/unit/test_list_row.gd +++ b/tests/unit/test_list_row.gd @@ -2,25 +2,25 @@ extends GdUnitTestSuite func _background(list_row: ListRow) -> Color: - return (list_row.get_theme_stylebox("panel") as StyleBoxFlat).bg_color + return (list_row.get_theme_stylebox("panel") as StyleBoxFlat).bg_color func test_row_shows_text() -> void: - var list_row: ListRow = auto_free(ListRow.create("Chrono Trigger", 0, 20)) + var list_row: ListRow = auto_free(ListRow.create("Chrono Trigger", 0, 20)) - assert_str(list_row.text).is_equal("Chrono Trigger") + assert_str(list_row.text).is_equal("Chrono Trigger") func test_neighbouring_rows_have_different_backgrounds() -> void: - var first: ListRow = auto_free(ListRow.create("Chrono Trigger", 0, 20)) - var second: ListRow = auto_free(ListRow.create("Chrono Cross", 1, 20)) - var third: ListRow = auto_free(ListRow.create("Xenogears", 2, 20)) + var first: ListRow = auto_free(ListRow.create("Chrono Trigger", 0, 20)) + var second: ListRow = auto_free(ListRow.create("Chrono Cross", 1, 20)) + var third: ListRow = auto_free(ListRow.create("Xenogears", 2, 20)) - assert_that(_background(first)).is_not_equal(_background(second)) - assert_that(_background(first)).is_equal(_background(third)) + assert_that(_background(first)).is_not_equal(_background(second)) + assert_that(_background(first)).is_equal(_background(third)) func test_long_text_wraps() -> void: - var list_row: ListRow = auto_free(ListRow.create("Castlevania: Symphony of the Night", 0, 20)) + var list_row: ListRow = auto_free(ListRow.create("Castlevania: Symphony of the Night", 0, 20)) - assert_int(list_row.label.autowrap_mode).is_equal(TextServer.AUTOWRAP_WORD_SMART) + assert_int(list_row.label.autowrap_mode).is_equal(TextServer.AUTOWRAP_WORD_SMART) diff --git a/tests/unit/test_music_player_time.gd b/tests/unit/test_music_player_time.gd index 6c61f65..a048882 100644 --- a/tests/unit/test_music_player_time.gd +++ b/tests/unit/test_music_player_time.gd @@ -7,62 +7,62 @@ var _hide_for_seconds: float func before_test() -> void: - _music_player = auto_free(MusicPlayer.new()) - _hide_beginning = Settings.hide_beginning - _hide_length = Settings.hide_length - _hide_for_seconds = Settings.hide_for_seconds - Settings.hide_beginning = false - Settings.hide_length = false - Settings.hide_for_seconds = 5.0 + _music_player = auto_free(MusicPlayer.new()) + _hide_beginning = Settings.hide_beginning + _hide_length = Settings.hide_length + _hide_for_seconds = Settings.hide_for_seconds + Settings.hide_beginning = false + Settings.hide_length = false + Settings.hide_for_seconds = 5.0 func after_test() -> void: - Settings.hide_beginning = _hide_beginning - Settings.hide_length = _hide_length - Settings.hide_for_seconds = _hide_for_seconds + Settings.hide_beginning = _hide_beginning + Settings.hide_length = _hide_length + Settings.hide_for_seconds = _hide_for_seconds func test_format_time() -> void: - assert_str(_music_player.format_time(0.0)).is_equal("00:00") - assert_str(_music_player.format_time(65.0)).is_equal("01:05") - assert_str(_music_player.format_time(3661.0)).is_equal("61:01") + assert_str(_music_player.format_time(0.0)).is_equal("00:00") + assert_str(_music_player.format_time(65.0)).is_equal("01:05") + assert_str(_music_player.format_time(3661.0)).is_equal("61:01") func test_format_time_rounds_up_into_next_minute() -> void: - assert_str(_music_player.format_time(59.6)).is_equal("01:00") + assert_str(_music_player.format_time(59.6)).is_equal("01:00") func test_format_text_shows_position_and_length() -> void: - assert_str(_music_player.format_text(10.0, 100.0)).is_equal("00:10 / 01:40") + assert_str(_music_player.format_text(10.0, 100.0)).is_equal("00:10 / 01:40") func test_format_text_hides_length() -> void: - Settings.hide_length = true + Settings.hide_length = true - assert_str(_music_player.format_text(10.0, 100.0)).is_equal("00:10 / ??:??") + assert_str(_music_player.format_text(10.0, 100.0)).is_equal("00:10 / ??:??") func test_format_text_hides_position_at_start() -> void: - Settings.hide_beginning = true + Settings.hide_beginning = true - assert_str(_music_player.format_text(3.0, 100.0)).is_equal("??:?? / 01:40") + assert_str(_music_player.format_text(3.0, 100.0)).is_equal("??:?? / 01:40") func test_format_text_shows_position_after_hidden_start() -> void: - Settings.hide_beginning = true + Settings.hide_beginning = true - assert_str(_music_player.format_text(5.0, 100.0)).is_equal("00:05 / 01:40") + assert_str(_music_player.format_text(5.0, 100.0)).is_equal("00:05 / 01:40") func test_format_text_hides_everything_at_start() -> void: - Settings.hide_beginning = true - Settings.hide_length = true + Settings.hide_beginning = true + Settings.hide_length = true - assert_str(_music_player.format_text(3.0, 100.0)).is_equal("??:?? / ??:??") + assert_str(_music_player.format_text(3.0, 100.0)).is_equal("??:?? / ??:??") func test_format_text_keeps_length_hidden_after_hidden_start() -> void: - Settings.hide_beginning = true - Settings.hide_length = true + Settings.hide_beginning = true + Settings.hide_length = true - assert_str(_music_player.format_text(5.0, 100.0)).is_equal("00:05 / ??:??") + assert_str(_music_player.format_text(5.0, 100.0)).is_equal("00:05 / ??:??") diff --git a/tests/unit/test_music_server_client.gd b/tests/unit/test_music_server_client.gd index 9391d45..3fb5e7c 100644 --- a/tests/unit/test_music_server_client.gd +++ b/tests/unit/test_music_server_client.gd @@ -4,143 +4,143 @@ var _server: FakeHttpTransport func before_test() -> void: - _server = FakeHttpTransport.new().install() + _server = FakeHttpTransport.new().install() func after_test() -> void: - _server.uninstall() + _server.uninstall() func test_fetch_song_list_passes_parsed_json() -> void: - var songs: Array = [{"SongNo": 0, "Soundtrack": "Chrono Trigger", "Song": "Corridors of Time"}] - _server.respond_json("/music/list", songs) - var received: Array = [] + var songs: Array = [{"SongNo": 0, "Soundtrack": "Chrono Trigger", "Song": "Corridors of Time"}] + _server.respond_json("/music/list", songs) + var received: Array = [] - MusicServerClient.fetch_song_list(func(data: Array) -> void: received.append_array(data)) + MusicServerClient.fetch_song_list(func(data: Array) -> void: received.append_array(data)) - assert_int(received.size()).is_equal(1) - assert_int(int(received[0].SongNo)).is_equal(0) - assert_str(received[0].Soundtrack).is_equal("Chrono Trigger") + assert_int(received.size()).is_equal(1) + assert_int(int(received[0].SongNo)).is_equal(0) + assert_str(received[0].Soundtrack).is_equal("Chrono Trigger") func test_fetch_random_song_uses_normal_endpoint() -> void: - MusicServerClient.fetch_random_song(false, func(_body: PackedByteArray) -> void: pass) + MusicServerClient.fetch_random_song(false, func(_body: PackedByteArray) -> void: pass) - assert_array(_server.requested_paths).contains_exactly(["/music/rand"]) + assert_array(_server.requested_paths).contains_exactly(["/music/rand"]) func test_fetch_random_song_uses_low_played_endpoint() -> void: - MusicServerClient.fetch_random_song(true, func(_body: PackedByteArray) -> void: pass) + MusicServerClient.fetch_random_song(true, func(_body: PackedByteArray) -> void: pass) - assert_array(_server.requested_paths).contains_exactly(["/music/rand/low"]) + assert_array(_server.requested_paths).contains_exactly(["/music/rand/low"]) func test_fetch_song_passes_raw_bytes() -> void: - var mp3: PackedByteArray = PackedByteArray([0x49, 0x44, 0x33]) - _server.respond_bytes("/music?song=4", mp3) - var received: Array[PackedByteArray] = [] + var mp3: PackedByteArray = PackedByteArray([0x49, 0x44, 0x33]) + _server.respond_bytes("/music?song=4", mp3) + var received: Array[PackedByteArray] = [] - MusicServerClient.fetch_song(4, func(body: PackedByteArray) -> void: received.append(body)) + MusicServerClient.fetch_song(4, func(body: PackedByteArray) -> void: received.append(body)) - assert_array(received).contains_exactly([mp3]) + assert_array(received).contains_exactly([mp3]) func test_failed_request_does_not_call_back() -> void: - _server.respond_json("/music/list", [], 500) - var called: Array[bool] = [false] + _server.respond_json("/music/list", [], 500) + var called: Array[bool] = [false] - MusicServerClient.fetch_song_list(func(_data: Variant) -> void: called[0] = true) + MusicServerClient.fetch_song_list(func(_data: Variant) -> void: called[0] = true) - assert_bool(called[0]).is_false() + assert_bool(called[0]).is_false() func test_invalid_json_does_not_call_back() -> void: - _server.respond_bytes("/music/info", "not json".to_utf8_buffer()) - var called: Array[bool] = [false] + _server.respond_bytes("/music/info", "not json".to_utf8_buffer()) + var called: Array[bool] = [false] - MusicServerClient.fetch_song_info(func(_data: Variant) -> void: called[0] = true) + MusicServerClient.fetch_song_info(func(_data: Variant) -> void: called[0] = true) - assert_bool(called[0]).is_false() + assert_bool(called[0]).is_false() func test_failed_request_calls_on_failed() -> void: - _server.respond_bytes("/music/rand", PackedByteArray(), 503) - var outcome: Array[String] = [] + _server.respond_bytes("/music/rand", PackedByteArray(), 503) + var outcome: Array[String] = [] - MusicServerClient.fetch_random_song(false, - func(_body: PackedByteArray) -> void: outcome.append("done"), - func() -> void: outcome.append("failed")) + MusicServerClient.fetch_random_song(false, + func(_body: PackedByteArray) -> void: outcome.append("done"), + func() -> void: outcome.append("failed")) - assert_array(outcome).contains_exactly(["failed"]) + assert_array(outcome).contains_exactly(["failed"]) func test_invalid_json_calls_on_failed() -> void: - _server.respond_bytes("/music/info", "not json".to_utf8_buffer()) - var outcome: Array[String] = [] + _server.respond_bytes("/music/info", "not json".to_utf8_buffer()) + var outcome: Array[String] = [] - MusicServerClient.fetch_song_info( - func(_data: Variant) -> void: outcome.append("done"), - func() -> void: outcome.append("failed")) + MusicServerClient.fetch_song_info( + func(_data: Variant) -> void: outcome.append("done"), + func() -> void: outcome.append("failed")) - assert_array(outcome).contains_exactly(["failed"]) + assert_array(outcome).contains_exactly(["failed"]) func test_successful_request_does_not_call_on_failed() -> void: - _server.respond_bytes("/music/addQue", PackedByteArray()) - var outcome: Array[String] = [] + _server.respond_bytes("/music/addQue", PackedByteArray()) + var outcome: Array[String] = [] - MusicServerClient.add_to_queue( - func() -> void: outcome.append("done"), - func() -> void: outcome.append("failed")) + MusicServerClient.add_to_queue( + func() -> void: outcome.append("done"), + func() -> void: outcome.append("failed")) - assert_array(outcome).contains_exactly(["done"]) + assert_array(outcome).contains_exactly(["done"]) func test_send_calls_back_without_arguments() -> void: - _server.respond_bytes("/music/reset", PackedByteArray()) - var called: Array[bool] = [false] + _server.respond_bytes("/music/reset", PackedByteArray()) + var called: Array[bool] = [false] - MusicServerClient.reset_playlist(func() -> void: called[0] = true) + MusicServerClient.reset_playlist(func() -> void: called[0] = true) - assert_bool(called[0]).is_true() + assert_bool(called[0]).is_true() func test_mark_song_played_sends_put() -> void: - _server.respond_bytes("/music/played?song=3", PackedByteArray()) + _server.respond_bytes("/music/played?song=3", PackedByteArray()) - MusicServerClient.mark_song_played(3) + MusicServerClient.mark_song_played(3) - assert_array(_server.requested_paths).contains_exactly(["/music/played?song=3"]) - assert_array(_server.requested_methods).contains_exactly([HTTPClient.METHOD_PUT]) + assert_array(_server.requested_paths).contains_exactly(["/music/played?song=3"]) + assert_array(_server.requested_methods).contains_exactly([HTTPClient.METHOD_PUT]) func test_character_name_is_url_encoded() -> void: - MusicServerClient.fetch_character_image("Paper Mario.png", func(_body: PackedByteArray) -> void: pass) + MusicServerClient.fetch_character_image("Paper Mario.png", func(_body: PackedByteArray) -> void: pass) - assert_array(_server.requested_paths).contains_exactly(["/character?name=Paper%20Mario.png"]) + assert_array(_server.requested_paths).contains_exactly(["/character?name=Paper%20Mario.png"]) func test_requests_go_to_selected_server() -> void: - var previous_path: String = Settings.default_path - Settings.default_path = "http://localhost:8080" - var requested_urls: Array[String] = [] - var recording_transport: HttpTransport = _RecordingTransport.new(requested_urls) - MusicServerClient.transport = recording_transport + var previous_path: String = Settings.default_path + Settings.default_path = "http://localhost:8080" + var requested_urls: Array[String] = [] + var recording_transport: HttpTransport = _RecordingTransport.new(requested_urls) + MusicServerClient.transport = recording_transport - MusicServerClient.fetch_song_info(func(_data: Variant) -> void: pass) + MusicServerClient.fetch_song_info(func(_data: Variant) -> void: pass) - Settings.default_path = previous_path - assert_array(requested_urls).contains_exactly(["http://localhost:8080/music/info"]) + Settings.default_path = previous_path + assert_array(requested_urls).contains_exactly(["http://localhost:8080/music/info"]) class _RecordingTransport: - extends HttpTransport + extends HttpTransport - var _urls: Array[String] + var _urls: Array[String] - func _init(urls: Array[String]) -> void: - super(null) - _urls = urls + func _init(urls: Array[String]) -> void: + super(null) + _urls = urls - func request(url: String, _method: int, _on_complete: Callable) -> void: - _urls.append(url) + func request(url: String, _method: int, _on_complete: Callable) -> void: + _urls.append(url) diff --git a/tests/unit/test_player_object.gd b/tests/unit/test_player_object.gd index ec3834f..e9753aa 100644 --- a/tests/unit/test_player_object.gd +++ b/tests/unit/test_player_object.gd @@ -5,134 +5,134 @@ var _player: PlayerObject func before_test() -> void: - _winning_score = Settings.winning_score - Settings.winning_score = 3 - _player = PlayerObject.new("Crono") + _winning_score = Settings.winning_score + Settings.winning_score = 3 + _player = PlayerObject.new("Crono") func after_test() -> void: - Settings.winning_score = _winning_score + Settings.winning_score = _winning_score func test_first_point_triggers_first_point_signal() -> void: - monitor_signals(_player, false) + monitor_signals(_player, false) - _player.add_point() + _player.add_point() - assert_int(_player.player_score).is_equal(1) - await assert_signal(_player).is_emitted("first_point_triggerd") - await assert_signal(_player).is_emitted("player_point_given") + assert_int(_player.player_score).is_equal(1) + await assert_signal(_player).is_emitted("first_point_triggerd") + await assert_signal(_player).is_emitted("player_point_given") func test_one_point_from_winning_triggers_match_point() -> void: - _player.add_point() - monitor_signals(_player, false) + _player.add_point() + monitor_signals(_player, false) - _player.add_point() + _player.add_point() - await assert_signal(_player).is_emitted("match_point_triggerd") + await assert_signal(_player).is_emitted("match_point_triggerd") func test_reaching_winning_score_triggers_winner() -> void: - _player.add_point() - _player.add_point() - monitor_signals(_player, false) + _player.add_point() + _player.add_point() + monitor_signals(_player, false) - _player.add_point() + _player.add_point() - assert_int(_player.player_score).is_equal(3) - await assert_signal(_player).is_emitted("winner_triggerd") + assert_int(_player.player_score).is_equal(3) + await assert_signal(_player).is_emitted("winner_triggerd") func test_score_does_not_go_past_winning_score() -> void: - for i: int in 3: - _player.add_point() - monitor_signals(_player, false) + for i: int in 3: + _player.add_point() + monitor_signals(_player, false) - _player.add_point() + _player.add_point() - assert_int(_player.player_score).is_equal(3) - await assert_signal(_player).wait_until(50).is_not_emitted("player_point_given") + assert_int(_player.player_score).is_equal(3) + await assert_signal(_player).wait_until(50).is_not_emitted("player_point_given") func test_ordinary_point_plays_point_sound() -> void: - Settings.winning_score = 10 - _player.add_point() - monitor_signals(_player, false) + Settings.winning_score = 10 + _player.add_point() + monitor_signals(_player, false) - _player.add_point() + _player.add_point() - await assert_signal(_player).is_emitted("point_given_sound") + await assert_signal(_player).is_emitted("point_given_sound") func test_minus_point_lowers_score() -> void: - _player.add_point() - monitor_signals(_player, false) + _player.add_point() + monitor_signals(_player, false) - _player.minus_point() + _player.minus_point() - assert_int(_player.player_score).is_equal(0) - await assert_signal(_player).is_emitted("player_point_taken") + assert_int(_player.player_score).is_equal(0) + await assert_signal(_player).is_emitted("player_point_taken") func test_score_does_not_go_below_zero() -> void: - monitor_signals(_player, false) + monitor_signals(_player, false) - _player.minus_point() + _player.minus_point() - assert_int(_player.player_score).is_equal(0) - await assert_signal(_player).wait_until(50).is_not_emitted("player_point_taken") + assert_int(_player.player_score).is_equal(0) + await assert_signal(_player).wait_until(50).is_not_emitted("player_point_taken") func test_dropping_back_to_zero_allows_first_point_again() -> void: - _player.add_point() - _player.minus_point() - monitor_signals(_player, false) + _player.add_point() + _player.minus_point() + monitor_signals(_player, false) - _player.add_point() + _player.add_point() - await assert_signal(_player).is_emitted("first_point_triggerd") + await assert_signal(_player).is_emitted("first_point_triggerd") func test_reset_points() -> void: - _player.add_point() - _player.add_point() + _player.add_point() + _player.add_point() - _player.reset_points() + _player.reset_points() - assert_int(_player.player_score).is_equal(0) - assert_bool(_player.is_first_point).is_true() + assert_int(_player.player_score).is_equal(0) + assert_bool(_player.is_first_point).is_true() func test_id_is_a_uuid() -> void: - var uuid_pattern: RegEx = RegEx.create_from_string( - "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$") + var uuid_pattern: RegEx = RegEx.create_from_string( + "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$") - assert_object(uuid_pattern.search(_player.id)).is_not_null() + assert_object(uuid_pattern.search(_player.id)).is_not_null() func test_every_player_gets_a_different_id() -> void: - var ids: Dictionary = {} - for i: int in 100: - ids[PlayerObject.new("Player %d" % i).id] = true + var ids: Dictionary = {} + for i: int in 100: + ids[PlayerObject.new("Player %d" % i).id] = true - assert_int(ids.size()).is_equal(100) + assert_int(ids.size()).is_equal(100) func test_winning_score_of_one_is_won_with_first_point() -> void: - Settings.winning_score = 1 - monitor_signals(_player, false) + Settings.winning_score = 1 + monitor_signals(_player, false) - _player.add_point() + _player.add_point() - await assert_signal(_player).is_emitted("winner_triggerd") + await assert_signal(_player).is_emitted("winner_triggerd") func test_first_point_is_match_point_when_winning_score_is_two() -> void: - Settings.winning_score = 2 - monitor_signals(_player, false) + Settings.winning_score = 2 + monitor_signals(_player, false) - _player.add_point() + _player.add_point() - await assert_signal(_player).is_emitted("match_point_triggerd") - assert_bool(_player.is_first_point).is_false() + await assert_signal(_player).is_emitted("match_point_triggerd") + assert_bool(_player.is_first_point).is_false() diff --git a/tests/unit/test_playlist.gd b/tests/unit/test_playlist.gd index cb63409..01e7225 100644 --- a/tests/unit/test_playlist.gd +++ b/tests/unit/test_playlist.gd @@ -6,196 +6,196 @@ var _is_debug: bool func before_test() -> void: - _server = FakeHttpTransport.new().install() - _add_to_stats = Settings.add_to_stats - _is_debug = Settings.is_debug - Settings.add_to_stats = false - Settings.is_debug = false - Playlist.reset_playlist() - Playlist.number_of_tracks_to_preload = 1 + _server = FakeHttpTransport.new().install() + _add_to_stats = Settings.add_to_stats + _is_debug = Settings.is_debug + Settings.add_to_stats = false + Settings.is_debug = false + Playlist.reset_playlist() + Playlist.number_of_tracks_to_preload = 1 func after_test() -> void: - Playlist.reset_playlist() - Settings.add_to_stats = _add_to_stats - Settings.is_debug = _is_debug - _server.uninstall() + Playlist.reset_playlist() + Settings.add_to_stats = _add_to_stats + Settings.is_debug = _is_debug + _server.uninstall() func _add_songs(count: int) -> Array[SongObject]: - var songs: Array[SongObject] = [] - for i: int in count: - var song: SongObject = SongObject.new() - song.song_number = i - song.soundtrack_title = "Soundtrack %d" % i - song.song_title = "Song %d" % i - Playlist.add_to_playlist(song) - songs.append(song) - return songs + var songs: Array[SongObject] = [] + for i: int in count: + var song: SongObject = SongObject.new() + song.song_number = i + song.soundtrack_title = "Soundtrack %d" % i + song.song_title = "Song %d" % i + Playlist.add_to_playlist(song) + songs.append(song) + return songs func test_set_latest_played_song_advances() -> void: - _add_songs(3) + _add_songs(3) - Playlist.set_latest_played_song() + Playlist.set_latest_played_song() - assert_int(Playlist.latest_played_song).is_equal(1) + assert_int(Playlist.latest_played_song).is_equal(1) func test_set_latest_played_song_stops_at_last_song() -> void: - _add_songs(2) + _add_songs(2) - Playlist.set_latest_played_song() - Playlist.set_latest_played_song() - Playlist.set_latest_played_song() + Playlist.set_latest_played_song() + Playlist.set_latest_played_song() + Playlist.set_latest_played_song() - assert_int(Playlist.latest_played_song).is_equal(1) + assert_int(Playlist.latest_played_song).is_equal(1) func test_get_next_song_returns_latest_played() -> void: - var songs: Array[SongObject] = _add_songs(3) - Playlist.latest_played_song = 2 + var songs: Array[SongObject] = _add_songs(3) + Playlist.latest_played_song = 2 - assert_object(Playlist.get_next_song()).is_same(songs[2]) + assert_object(Playlist.get_next_song()).is_same(songs[2]) func test_update_last_played_song_points_past_existing_songs() -> void: - _add_songs(4) + _add_songs(4) - Playlist.update_last_played_song() + Playlist.update_last_played_song() - assert_int(Playlist.latest_played_song).is_equal(4) + assert_int(Playlist.latest_played_song).is_equal(4) func test_preloaded_songs_counts_unplayed_songs() -> void: - var songs: Array[SongObject] = _add_songs(3) - songs[0].has_played = true + var songs: Array[SongObject] = _add_songs(3) + songs[0].has_played = true - assert_int(Playlist.get_preloaded_songs()).is_equal(2) + assert_int(Playlist.get_preloaded_songs()).is_equal(2) func test_should_preload_more_songs_when_below_target() -> void: - var songs: Array[SongObject] = _add_songs(1) - songs[0].has_played = true + var songs: Array[SongObject] = _add_songs(1) + songs[0].has_played = true - assert_bool(Playlist.should_preload_more_songs()).is_true() + assert_bool(Playlist.should_preload_more_songs()).is_true() func test_should_not_preload_more_songs_when_target_reached() -> void: - _add_songs(1) + _add_songs(1) - assert_bool(Playlist.should_preload_more_songs()).is_false() + assert_bool(Playlist.should_preload_more_songs()).is_false() func test_get_playlist_hides_unplayed_songs() -> void: - var songs: Array[SongObject] = _add_songs(3) - songs[0].has_played = true + var songs: Array[SongObject] = _add_songs(3) + songs[0].has_played = true - assert_array(Playlist.get_playlist()).contains_exactly([songs[0]]) + assert_array(Playlist.get_playlist()).contains_exactly([songs[0]]) func test_get_playlist_shows_everything_in_debug() -> void: - Settings.is_debug = true - var songs: Array[SongObject] = _add_songs(2) + Settings.is_debug = true + var songs: Array[SongObject] = _add_songs(2) - assert_array(Playlist.get_playlist()).contains_exactly(songs) + assert_array(Playlist.get_playlist()).contains_exactly(songs) func test_song_is_answered_marks_song() -> void: - var songs: Array[SongObject] = _add_songs(2) + var songs: Array[SongObject] = _add_songs(2) - Playlist.song_is_answered(1) + Playlist.song_is_answered(1) - assert_bool(songs[1].is_answered).is_true() - assert_bool(songs[0].is_answered).is_false() + assert_bool(songs[1].is_answered).is_true() + assert_bool(songs[0].is_answered).is_false() func test_song_is_answered_reports_to_stats_when_enabled() -> void: - Settings.add_to_stats = true - _add_songs(2) + Settings.add_to_stats = true + _add_songs(2) - Playlist.song_is_answered(1) + Playlist.song_is_answered(1) - assert_array(_server.requested_paths).contains_exactly(["/music/played?song=1"]) + assert_array(_server.requested_paths).contains_exactly(["/music/played?song=1"]) func test_song_is_answered_does_not_report_when_stats_disabled() -> void: - _add_songs(2) + _add_songs(2) - Playlist.song_is_answered(1) + Playlist.song_is_answered(1) - assert_array(_server.requested_paths).is_empty() + assert_array(_server.requested_paths).is_empty() func test_points_are_recorded_on_current_song() -> void: - var songs: Array[SongObject] = _add_songs(2) - Playlist.set_currently_playing_song(1) + var songs: Array[SongObject] = _add_songs(2) + Playlist.set_currently_playing_song(1) - Playlist.add_point("lucca-id") - Playlist.add_point("crono-id") + Playlist.add_point("lucca-id") + Playlist.add_point("crono-id") - assert_array(songs[1].players_given_point).contains_exactly(["lucca-id", "crono-id"]) - assert_array(songs[0].players_given_point).is_empty() + assert_array(songs[1].players_given_point).contains_exactly(["lucca-id", "crono-id"]) + assert_array(songs[0].players_given_point).is_empty() func test_remove_point_from_current_song() -> void: - var songs: Array[SongObject] = _add_songs(1) - Playlist.set_currently_playing_song(0) - Playlist.add_point("crono-id") - Playlist.add_point("marle-id") + var songs: Array[SongObject] = _add_songs(1) + Playlist.set_currently_playing_song(0) + Playlist.add_point("crono-id") + Playlist.add_point("marle-id") - Playlist.remove_point("crono-id") + Playlist.remove_point("crono-id") - assert_array(songs[0].players_given_point).contains_exactly(["marle-id"]) + assert_array(songs[0].players_given_point).contains_exactly(["marle-id"]) func test_remove_player_removes_only_that_players_points() -> void: - var songs: Array[SongObject] = _add_songs(2) - songs[0].players_given_point.assign(["crono-id", "marle-id"]) - songs[1].players_given_point.assign(["crono-id"]) + var songs: Array[SongObject] = _add_songs(2) + songs[0].players_given_point.assign(["crono-id", "marle-id"]) + songs[1].players_given_point.assign(["crono-id"]) - Playlist.remove_player_from_list("marle-id") + Playlist.remove_player_from_list("marle-id") - assert_array(songs[0].players_given_point).contains_exactly(["crono-id"]) - assert_array(songs[1].players_given_point).contains_exactly(["crono-id"]) + assert_array(songs[0].players_given_point).contains_exactly(["crono-id"]) + assert_array(songs[1].players_given_point).contains_exactly(["crono-id"]) func test_reset_playlist_clears_songs_and_position() -> void: - _add_songs(3) - Playlist.latest_played_song = 2 - Playlist.set_currently_playing_song(1) + _add_songs(3) + Playlist.latest_played_song = 2 + Playlist.set_currently_playing_song(1) - Playlist.reset_playlist() + Playlist.reset_playlist() - assert_array(Playlist.song_object_array).is_empty() - assert_int(Playlist.latest_played_song).is_equal(0) - assert_int(Playlist.currently_playing_song).is_equal(-1) + assert_array(Playlist.song_object_array).is_empty() + assert_int(Playlist.latest_played_song).is_equal(0) + assert_int(Playlist.currently_playing_song).is_equal(-1) func test_current_titles_are_hidden_until_answered() -> void: - var songs: Array[SongObject] = _add_songs(1) - Playlist.set_currently_playing_song(0) + var songs: Array[SongObject] = _add_songs(1) + Playlist.set_currently_playing_song(0) - assert_str(Playlist.get_current_soundtrack_title()).is_equal("????????") + assert_str(Playlist.get_current_soundtrack_title()).is_equal("????????") - songs[0].is_answered = true + songs[0].is_answered = true - assert_str(Playlist.get_current_soundtrack_title()).is_equal("Soundtrack 0") - assert_str(Playlist.get_current_song_title()).is_equal("Song 0") + assert_str(Playlist.get_current_soundtrack_title()).is_equal("Soundtrack 0") + assert_str(Playlist.get_current_song_title()).is_equal("Song 0") func test_answering_when_nothing_is_playing_does_nothing() -> void: - Settings.add_to_stats = true - var songs: Array[SongObject] = _add_songs(2) + Settings.add_to_stats = true + var songs: Array[SongObject] = _add_songs(2) - Playlist.song_is_answered() + Playlist.song_is_answered() - assert_bool(songs[0].is_answered).is_false() - assert_bool(songs[1].is_answered).is_false() - assert_array(_server.requested_paths).is_empty() + assert_bool(songs[0].is_answered).is_false() + assert_bool(songs[1].is_answered).is_false() + assert_array(_server.requested_paths).is_empty() func test_answering_with_empty_playlist_does_nothing() -> void: - Playlist.song_is_answered() + Playlist.song_is_answered() - assert_array(_server.requested_paths).is_empty() + assert_array(_server.requested_paths).is_empty() diff --git a/tests/unit/test_search.gd b/tests/unit/test_search.gd index ee532de..fb27d3a 100644 --- a/tests/unit/test_search.gd +++ b/tests/unit/test_search.gd @@ -6,57 +6,57 @@ var _search: Control func before_test() -> void: - _search = auto_free(SearchWindowScript.new()) - _search.set_soundtracks([ - "Chrono Trigger", - "Final Fantasy VI", - "Mario & Luigi: Superstar Saga", - "Pokémon Red", - "Q*bert", - "Super Mario 64", - "The Legend of Zelda: A Link to the Past", - ]) + _search = auto_free(SearchWindowScript.new()) + _search.set_soundtracks([ + "Chrono Trigger", + "Final Fantasy VI", + "Mario & Luigi: Superstar Saga", + "Pokémon Red", + "Q*bert", + "Super Mario 64", + "The Legend of Zelda: A Link to the Past", + ]) func test_plain_text_matches_case_insensitively() -> void: - assert_array(_search.find_matches("chrono")).contains_exactly(["Chrono Trigger"]) + assert_array(_search.find_matches("chrono")).contains_exactly(["Chrono Trigger"]) func test_contains_matches_come_before_letter_order_matches() -> void: - var matches: Array[String] = _search.find_matches("mario") + var matches: Array[String] = _search.find_matches("mario") - assert_array(matches).contains_exactly([ - "Mario & Luigi: Superstar Saga", - "Super Mario 64", - ]) + assert_array(matches).contains_exactly([ + "Mario & Luigi: Superstar Saga", + "Super Mario 64", + ]) func test_ignores_spaces() -> void: - assert_array(_search.find_matches("finalfantasy")).contains_exactly(["Final Fantasy VI"]) + assert_array(_search.find_matches("finalfantasy")).contains_exactly(["Final Fantasy VI"]) func test_and_matches_ampersand() -> void: - assert_array(_search.find_matches("mario and luigi")).contains(["Mario & Luigi: Superstar Saga"]) + assert_array(_search.find_matches("mario and luigi")).contains(["Mario & Luigi: Superstar Saga"]) func test_accented_letters_match_plain_letters() -> void: - assert_array(_search.find_matches("pokemon")).contains_exactly(["Pokémon Red"]) + assert_array(_search.find_matches("pokemon")).contains_exactly(["Pokémon Red"]) func test_letters_in_order_match_abbreviations() -> void: - assert_array(_search.find_matches("lozlttp")).contains_exactly([ - "The Legend of Zelda: A Link to the Past", - ]) + assert_array(_search.find_matches("lozlttp")).contains_exactly([ + "The Legend of Zelda: A Link to the Past", + ]) func test_regex_characters_are_matched_literally() -> void: - assert_array(_search.find_matches("q*b")).contains_exactly(["Q*bert"]) + assert_array(_search.find_matches("q*b")).contains_exactly(["Q*bert"]) func test_no_matches() -> void: - assert_array(_search.find_matches("metroid")).is_empty() + assert_array(_search.find_matches("metroid")).is_empty() func test_clean_term() -> void: - assert_str(_search.clean_term("Rock 'n Roll Racing")).is_equal("rockandrollracing") - assert_str(_search.clean_term("Ys I & II")).is_equal("ysiandii") + assert_str(_search.clean_term("Rock 'n Roll Racing")).is_equal("rockandrollracing") + assert_str(_search.clean_term("Ys I & II")).is_equal("ysiandii") diff --git a/tests/unit/test_settings.gd b/tests/unit/test_settings.gd index 4e94c2c..3753150 100644 --- a/tests/unit/test_settings.gd +++ b/tests/unit/test_settings.gd @@ -2,12 +2,12 @@ extends GdUnitTestSuite func test_version_comes_from_project_settings() -> void: - assert_str(Settings.version).is_equal( - ProjectSettings.get_setting("application/config/version")) + assert_str(Settings.version).is_equal( + ProjectSettings.get_setting("application/config/version")) func test_version_is_major_minor_patch() -> void: - # The release job tags and names builds with this version - var pattern: RegEx = RegEx.create_from_string("^\\d+\\.\\d+\\.\\d+$") + # The release job tags and names builds with this version + var pattern: RegEx = RegEx.create_from_string("^\\d+\\.\\d+\\.\\d+$") - assert_object(pattern.search(Settings.version)).is_not_null() + assert_object(pattern.search(Settings.version)).is_not_null() diff --git a/tests/unit/test_song_object.gd b/tests/unit/test_song_object.gd index d607c47..73f8fdd 100644 --- a/tests/unit/test_song_object.gd +++ b/tests/unit/test_song_object.gd @@ -5,56 +5,56 @@ var _song: SongObject func before_test() -> void: - _is_debug = Settings.is_debug - Settings.is_debug = false - _song = SongObject.new() - _song.song_number = 4 - _song.soundtrack_title = "Final Fantasy VI" - _song.song_title = "Dancing Mad" + _is_debug = Settings.is_debug + Settings.is_debug = false + _song = SongObject.new() + _song.song_number = 4 + _song.soundtrack_title = "Final Fantasy VI" + _song.song_title = "Dancing Mad" func after_test() -> void: - Settings.is_debug = _is_debug + Settings.is_debug = _is_debug func test_titles_are_hidden_until_answered() -> void: - assert_str(_song.get_soundtrack_title()).is_equal("????????") - assert_str(_song.get_song_title()).is_equal("??????") - assert_str(_song.get_song_info()).is_equal("??? - ???") + assert_str(_song.get_soundtrack_title()).is_equal("????????") + assert_str(_song.get_song_title()).is_equal("??????") + assert_str(_song.get_song_info()).is_equal("??? - ???") func test_titles_are_shown_once_answered() -> void: - _song.is_answered = true + _song.is_answered = true - assert_str(_song.get_soundtrack_title()).is_equal("Final Fantasy VI") - assert_str(_song.get_song_title()).is_equal("Dancing Mad") - assert_str(_song.get_song_info()).is_equal("5. Final Fantasy VI - Dancing Mad") + assert_str(_song.get_soundtrack_title()).is_equal("Final Fantasy VI") + assert_str(_song.get_song_title()).is_equal("Dancing Mad") + assert_str(_song.get_song_info()).is_equal("5. Final Fantasy VI - Dancing Mad") func test_debug_info_shows_unanswered_songs() -> void: - Settings.is_debug = true + Settings.is_debug = true - assert_str(_song.get_song_info()).is_equal( - "5. Final Fantasy VI - Dancing Mad | played: false | answered: false") + assert_str(_song.get_song_info()).is_equal( + "5. Final Fantasy VI - Dancing Mad | played: false | answered: false") func test_points_are_kept_in_the_order_given() -> void: - _song.add_point("marle-id") - _song.add_point("crono-id") + _song.add_point("marle-id") + _song.add_point("crono-id") - assert_array(_song.players_given_point).contains_exactly(["marle-id", "crono-id"]) + assert_array(_song.players_given_point).contains_exactly(["marle-id", "crono-id"]) func test_player_gets_at_most_one_point_per_song() -> void: - _song.add_point("crono-id") - _song.add_point("crono-id") + _song.add_point("crono-id") + _song.add_point("crono-id") - assert_array(_song.players_given_point).contains_exactly(["crono-id"]) + assert_array(_song.players_given_point).contains_exactly(["crono-id"]) func test_removing_point_of_player_without_point_changes_nothing() -> void: - _song.add_point("crono-id") + _song.add_point("crono-id") - _song.remove_point("marle-id") + _song.remove_point("marle-id") - assert_array(_song.players_given_point).contains_exactly(["crono-id"]) + assert_array(_song.players_given_point).contains_exactly(["crono-id"]) diff --git a/tools/take_screenshots.gd b/tools/take_screenshots.gd index eb129f9..1459e3b 100644 --- a/tools/take_screenshots.gd +++ b/tools/take_screenshots.gd @@ -12,42 +12,42 @@ const SIZE: Vector2i = Vector2i(1920, 1080) func _initialize() -> void: - _take.call_deferred() + _take.call_deferred() func _take() -> void: - var args: PackedStringArray = OS.get_cmdline_user_args() - var out_dir: String = args[0] if !args.is_empty() else "user://screenshots" - DirAccess.make_dir_recursive_absolute(out_dir) - var draws: bool = DisplayServer.get_name() != "headless" + var args: PackedStringArray = OS.get_cmdline_user_args() + var out_dir: String = args[0] if !args.is_empty() else "user://screenshots" + DirAccess.make_dir_recursive_absolute(out_dir) + var draws: bool = DisplayServer.get_name() != "headless" - # Loaded here, not named as a class: autoloads such as Playlist do not exist yet - # when this script is compiled - var ui_tour: GDScript = load("res://tests/fakes/ui_tour.gd") - ui_tour.prepare_autoloads() - var server: RefCounted = ui_tour.make_server().install() + # Loaded here, not named as a class: autoloads such as Playlist do not exist yet + # when this script is compiled + var ui_tour: GDScript = load("res://tests/fakes/ui_tour.gd") + ui_tour.prepare_autoloads() + var server: RefCounted = ui_tour.make_server().install() - # Drawn at the layout size, so the pictures do not depend on the screen size - var viewport: SubViewport = SubViewport.new() - viewport.size = SIZE - viewport.gui_embed_subwindows = true - viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS - root.add_child(viewport) - var main: Control = load("res://MainWindow.tscn").instantiate() - viewport.add_child(main) + # Drawn at the layout size, so the pictures do not depend on the screen size + var viewport: SubViewport = SubViewport.new() + viewport.size = SIZE + viewport.gui_embed_subwindows = true + viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS + root.add_child(viewport) + var main: Control = load("res://MainWindow.tscn").instantiate() + viewport.add_child(main) - var layout: Dictionary = {} - var save_state: Callable = func(state: String, popup: Node) -> void: - layout[state] = ui_tour.dump_layout(main, main if popup == null else popup) - if draws: - await RenderingServer.frame_post_draw - viewport.get_texture().get_image().save_png(out_dir.path_join(state + ".png")) - print("Saved state ", state) - await ui_tour.new(main).run(save_state) + var layout: Dictionary = {} + var save_state: Callable = func(state: String, popup: Node) -> void: + layout[state] = ui_tour.dump_layout(main, main if popup == null else popup) + if draws: + await RenderingServer.frame_post_draw + viewport.get_texture().get_image().save_png(out_dir.path_join(state + ".png")) + print("Saved state ", state) + await ui_tour.new(main).run(save_state) - var file: FileAccess = FileAccess.open(out_dir.path_join("layout.json"), FileAccess.WRITE) - file.store_string(JSON.stringify(layout, " ", true)) - file.close() - server.uninstall() - main.queue_free() - quit() + var file: FileAccess = FileAccess.open(out_dir.path_join("layout.json"), FileAccess.WRITE) + file.store_string(JSON.stringify(layout, " ", true)) + file.close() + server.uninstall() + main.queue_free() + quit() diff --git a/top_bar.gd b/top_bar.gd index 6d9dd22..81b79b0 100644 --- a/top_bar.gd +++ b/top_bar.gd @@ -14,9 +14,9 @@ signal qr_pressed func _ready() -> void: - $SearchButton.pressed.connect(search_pressed.emit) - sync_button.pressed.connect(sync_pressed.emit) - $StatisticsButton.pressed.connect(statistics_pressed.emit) - $ShortcutsButton.pressed.connect(shortcuts_pressed.emit) - $AboutButton.pressed.connect(about_pressed.emit) - $QRButton.pressed.connect(qr_pressed.emit) + $SearchButton.pressed.connect(search_pressed.emit) + sync_button.pressed.connect(sync_pressed.emit) + $StatisticsButton.pressed.connect(statistics_pressed.emit) + $ShortcutsButton.pressed.connect(shortcuts_pressed.emit) + $AboutButton.pressed.connect(about_pressed.emit) + $QRButton.pressed.connect(qr_pressed.emit)