Files
MusicPlayer/tests/fakes/main_window_test_suite.gd
T
Sansan 739d0f7af6 Preload songs only after the song list has loaded
At startup and after resetting the playlist, loading the song list and
preloading the first song started at the same time. When the list
answered last, it cleared the playlist and dropped the preloaded song.
Preloading now starts once the list has loaded, and loading the list is
retried if it fails.
2026-10-06 08:32:56 +02:00

123 lines
4.2 KiB
GDScript

class_name MainWindowTestSuite
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"},
]
var _server: FakeHttpTransport
var _snapshot: AutoloadSnapshot
var _runner: GdUnitSceneRunner
var _window: Control
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
_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()
# 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
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()
## 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)
func _press(button_path: String) -> void:
(_window.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)
## Adds a player through the name field, the same way the user does.
func _add_player(player_name: String) -> PlayerObject:
var name_field: TextEdit = _window.get_node(
"Players/VBoxContainer/AddPlayerContainer/PlayerNameField")
name_field.text = player_name
_runner.invoke("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 = _window.get_node(
"Players/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)
## 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()
## Gives a point with Alt+<number>.
func _give_point_with_keybind(number: int) -> void:
await _press_keys([KEY_ALT, (KEY_0 + number) as Key])
## Takes a point with Ctrl+Alt+<number>.
func _take_point_with_keybind(number: int) -> void:
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)