main/ holds the main window and top bar, quiz/ the quiz and its parts, player/ the music player, popups/ every popup and what they share, data/ the songs, players, playlist and settings, server/ the MusicServer client, common/ the list row and GameLog, and themes/ the themes and style boxes.
135 lines
4.6 KiB
GDScript
135 lines
4.6 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
|
|
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
|
|
|
|
_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://main/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
|
|
|
|
|
|
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)
|
|
|
|
|
|
## Presses a button in the quiz.
|
|
func _press(button_path: String) -> void:
|
|
(_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("SongControls/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
|
|
|
|
|
|
## Returns the row in the player list that shows [param player_object].
|
|
func _player_row(player_object: PlayerObject) -> PlayerRow:
|
|
var rows: Node = _quiz.get_node(
|
|
"PlayersPanel/VBoxContainer/ScrollContainer/PlayersListVBoxContainer")
|
|
for row: PlayerRow 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)
|
|
|
|
|
|
## 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()
|
|
|
|
|
|
## 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)
|