Files
MusicPlayer/tests/integration/test_offline_mode.gd
T
Sansan 06f457b027 Add a button in Settings that opens the config folder
Shows the folder with config.ini, the saved settings and the cached
characters and songs in the system's file manager.

Closes #45
2026-10-09 16:54:45 +02:00

342 lines
11 KiB
GDScript

extends MainWindowTestSuite
## Playing from a music folder instead of the server: soundtrack folders and prepared
## quizzes, with nothing but the characters asked from the server.
var _root: String
var _settings: SettingsPopup
var _top_bar: TopBar
func before_test() -> void:
_root = create_temp_dir("offline_%d" % randi())
super()
_settings = _window.get_node("SettingsPopup")
_top_bar = _window.get_node("TopBar")
func _song(relative_path: String) -> void:
var path: String = _root.path_join(relative_path)
DirAccess.make_dir_recursive_absolute(path.get_base_dir())
FileAccess.open(path, FileAccess.WRITE).store_buffer(
FileAccess.get_file_as_bytes("res://tests/data/short.mp3"))
func _soundtrack_folder() -> String:
_song("Music/Chrono Trigger/Corridors of Time.mp3")
_song("Music/Final Fantasy VI/Dancing Mad.mp3")
return _root.path_join("Music")
func _prepared_quiz() -> String:
for file_name: String in ["02. Ace Combat 7 - Daredevil.mp3", "01. Opening.mp3",
"10. Banjo Tooie - Cloud Race.mp3"]:
_song("Quiz/" + file_name)
return _root.path_join("Quiz")
# Requests to the server other than for characters
func _server_requests() -> Array[String]:
return _server.requested_paths.filter(
func(path: String) -> bool: return !path.begins_with("/character"))
func _use_folder(path: String) -> void:
_settings.use_music_folder(path)
await _runner.simulate_frames(2)
# Presses Next and waits until the song plays. Another playing song is stopped first,
# which takes half a second.
func _next() -> void:
_press("SongControls/NextButton")
await await_millis(700)
func _now_playing() -> Array[String]:
var now_playing: Node = _quiz.get_node("NowPlaying")
return [(now_playing.get_node("SoundtrackLabel") as Label).text,
(now_playing.get_node("SongLabel") as Label).text]
func test_picking_a_folder_makes_no_server_requests() -> void:
var before: int = _server_requests().size()
await _use_folder(_soundtrack_folder())
await _play_first_song()
_press("SongControls/ShowAnswerButton")
_press("QuizToolbar/SoundTestButton")
_press("QuizToolbar/ResetPlaylistButton")
await _runner.simulate_frames(2)
(_window.get_node("%AboutPopup") as AboutPopup).open()
assert_array(_server_requests().slice(before)).is_empty()
func test_next_plays_a_song_from_the_folder() -> void:
await _use_folder(_soundtrack_folder())
await _play_first_song()
var playing: SongObject = Playlist.song_object_array[Playlist.currently_playing_song]
assert_str(playing.song_path).starts_with(_root)
assert_bool((_quiz.get_node("MusicPlayer") as MusicPlayer).audio_player.playing).is_true()
func test_show_answer_shows_the_subfolder_and_the_song() -> void:
await _use_folder(_soundtrack_folder())
await _play_first_song()
_press("SongControls/ShowAnswerButton")
var song: SongObject = Playlist.song_object_array[Playlist.currently_playing_song]
assert_array(_now_playing()).contains_exactly([song.soundtrack_title, song.song_title])
assert_array(["Chrono Trigger", "Final Fantasy VI"]).contains([song.soundtrack_title])
assert_bool(song.song_title.ends_with(".mp3")).is_false()
func test_points_are_given_as_usual() -> void:
await _use_folder(_soundtrack_folder())
_add_player("Crono")
await _play_first_song()
await _give_point_with_keybind(1)
assert_array(_scores()).contains_exactly([1])
assert_array(Playlist.song_object_array[0].players_given_point).has_size(1)
func test_inspiration_list_and_search_show_the_subfolders() -> void:
await _use_folder(_soundtrack_folder())
assert_array(_quiz.inspiration_list.soundtracks) \
.contains_exactly(["Chrono Trigger", "Final Fantasy VI"])
assert_array((_window.get_node("SearchPopup") as SearchPopup).soundtracks) \
.contains_exactly(["Chrono Trigger", "Final Fantasy VI"])
func test_server_features_are_off_and_the_folder_is_shown() -> void:
await _use_folder(_soundtrack_folder())
assert_bool(_top_bar.sync_button.disabled).is_true()
assert_bool(_top_bar.qr_button.disabled).is_true()
assert_bool(_top_bar.statistics_tab.disabled).is_true()
assert_bool(_top_bar.offline_label.visible).is_true()
assert_str(_top_bar.offline_label.text).is_equal("Offline: Music")
assert_bool(_settings.select_server_button.disabled).is_true()
assert_bool(_settings.add_to_database_button.disabled).is_true()
# The config folder holds the cached characters, which are still used offline
assert_bool(_settings.open_config_folder_button.disabled).is_false()
func test_picking_a_folder_on_the_statistics_tab_goes_to_the_quiz() -> void:
_window.show_tab(&"statistics")
await _use_folder(_soundtrack_folder())
assert_bool(_quiz.visible).is_true()
func test_reset_playlist_starts_an_empty_playlist() -> void:
await _use_folder(_soundtrack_folder())
await _play_first_song()
await _next()
_press("QuizToolbar/ResetPlaylistButton")
await _runner.simulate_frames(2)
assert_int(Playlist.currently_playing_song).is_equal(-1)
assert_bool(Playlist.song_object_array.all(
func(song: SongObject) -> bool: return !song.has_played)).is_true()
func test_prepared_quiz_plays_in_order_and_shows_only_the_title() -> void:
await _use_folder(_prepared_quiz())
assert_bool(_settings.play_order_row.visible).is_true()
await _play_first_song()
_press("SongControls/ShowAnswerButton")
assert_array(_now_playing()).contains_exactly(["", "01. Opening"])
var row: SongRow = _quiz.music_list_panel.get_node("%MusicList").get_child(0)
assert_str(row.song_list_label.text).starts_with("1. 01. Opening")
assert_array(_quiz.inspiration_list.soundtracks).is_empty()
func test_prepared_quiz_stops_after_the_last_song() -> void:
await _use_folder(_prepared_quiz())
var titles: Array[String] = []
for i: int in 3:
await _next()
titles.append(Playlist.song_object_array[Playlist.currently_playing_song].song_title)
assert_array(titles).contains_exactly(
["01. Opening", "02. Ace Combat 7 - Daredevil", "10. Banjo Tooie - Cloud Race"])
assert_int(Playlist.song_object_array.size()).is_equal(3)
assert_str((_quiz.get_node("SongControls/NextButton") as Button).text) \
.is_equal("Show winner")
func test_prepared_quiz_at_random_plays_every_song() -> void:
await _use_folder(_prepared_quiz())
_settings.play_order_button.select(MusicFolder.PlayOrder.RANDOM)
_settings.play_order_button.item_selected.emit(MusicFolder.PlayOrder.RANDOM)
await _runner.simulate_frames(2)
for i: int in 3:
await _next()
assert_int(Settings.music_folder.play_order).is_equal(MusicFolder.PlayOrder.RANDOM)
var titles: Array = Playlist.song_object_array.map(
func(song: SongObject) -> String: return song.song_title)
assert_array(titles).contains_exactly_in_any_order(
["01. Opening", "02. Ace Combat 7 - Daredevil", "10. Banjo Tooie - Cloud Race"])
func test_play_order_is_only_shown_for_a_prepared_quiz() -> void:
await _use_folder(_soundtrack_folder())
assert_bool(_settings.play_order_row.visible).is_false()
func test_use_server_goes_back_to_the_server() -> void:
await _use_folder(_soundtrack_folder())
var before: int = _server_requests().size()
_settings.use_server()
await _runner.simulate_frames(2)
assert_bool(Settings.is_offline()).is_false()
assert_int(_server_requests().size()).is_greater(before)
assert_bool(_top_bar.sync_button.disabled).is_false()
assert_bool(_top_bar.offline_label.visible).is_false()
assert_bool(_settings.use_server_button.visible).is_false()
func test_folder_without_songs_is_not_used() -> void:
DirAccess.make_dir_recursive_absolute(_root.path_join("Empty"))
await _use_folder(_root.path_join("Empty"))
assert_bool(Settings.is_offline()).is_false()
assert_bool(_settings.folder_error_label.visible).is_true()
assert_str(_settings.folder_error_label.text).is_equal("No songs found in Empty")
func test_settings_panel_fits_its_rows_and_stays_centred() -> void:
_settings.open()
await _use_folder(_prepared_quiz())
await _runner.simulate_frames(1)
var panel: Rect2 = _settings.settings_panel.get_global_rect()
assert_bool(panel.encloses(_settings.rows.get_global_rect())).is_true()
assert_float(_settings.rows.get_combined_minimum_size().y) \
.is_less_equal(_settings.rows.size.y)
assert_float(panel.get_center().y).is_equal_approx(540.0, 1.0)
func test_characters_still_come_from_the_server() -> void:
var before: int = _server.count("/character/details")
await _use_folder(_soundtrack_folder())
assert_int(_server.count("/character/details")).is_greater(before)
func _play_whole_quiz() -> void:
await _play_first_song()
for i: int in 2:
await _next()
func test_prepared_quiz_has_no_winning_score() -> void:
Settings.winning_score = 1
var crono: PlayerObject = _add_player("Crono")
await _use_folder(_prepared_quiz())
await _play_first_song()
await _give_point_with_keybind(1)
await _give_point_with_keybind(1)
assert_int(crono.player_score).is_equal(2)
assert_bool(_quiz.winner_popup.visible).is_false()
func test_next_shows_the_winner_after_the_last_song() -> void:
_add_player("Crono")
_add_player("Marle")
await _use_folder(_prepared_quiz())
await _play_first_song()
await _give_point_with_keybind(2)
await _play_whole_quiz_rest()
var next_button: Button = _quiz.get_node("SongControls/NextButton")
assert_str(next_button.text).is_equal("Show winner")
assert_bool(next_button.disabled).is_false()
next_button.pressed.emit()
assert_bool(_quiz.winner_popup.visible).is_true()
assert_str(_quiz.winner_popup.winner_label.text).is_equal("Marle won with 1 point!!")
func _play_whole_quiz_rest() -> void:
for i: int in 2:
await _next()
func test_tied_players_all_win() -> void:
_add_player("Crono")
_add_player("Marle")
_add_player("Lucca")
await _use_folder(_prepared_quiz())
await _play_first_song()
await _give_point_with_keybind(1)
await _give_point_with_keybind(3)
await _play_whole_quiz_rest()
_press("SongControls/NextButton")
assert_str(_quiz.winner_popup.winner_label.text).is_equal("Crono and Lucca won with 1 point!!")
var header: Node = _quiz.winner_popup.winner_picture.get_parent()
var pictures: Array = header.get_children().filter(
func(node: Node) -> bool: return node is TextureRect && node.visible)
assert_array(pictures).has_size(2)
var others: Array = _quiz.winner_popup.players_list.get_children().map(
func(label: Label) -> String: return label.text)
assert_array(others).contains_exactly(["3. Marle - 0 points"])
func test_new_game_turns_show_winner_back_into_next() -> void:
await _use_folder(_prepared_quiz())
await _play_whole_quiz()
_press("QuizToolbar/ResetPlaylistButton")
await _runner.simulate_frames(2)
var next_button: Button = _quiz.get_node("SongControls/NextButton")
assert_str(next_button.text).is_equal("Randomize new track")
await _play_first_song()
assert_str(Playlist.song_object_array[Playlist.currently_playing_song].song_title) \
.is_equal("01. Opening")
func test_songs_playing_on_by_themselves_stop_at_the_end() -> void:
await _use_folder(_prepared_quiz())
await _play_whole_quiz()
_quiz.play_next_song()
await _runner.simulate_frames(2)
assert_str(Playlist.song_object_array[Playlist.currently_playing_song].song_title) \
.is_equal("10. Banjo Tooie - Cloud Race")
assert_str((_quiz.get_node("SongControls/NextButton") as Button).text) \
.is_equal("Show winner")
func test_quiz_settings_hide_the_winning_score_for_a_prepared_quiz() -> void:
await _use_folder(_prepared_quiz())
_quiz.quiz_settings_card.open()
assert_bool(_quiz.quiz_settings_card.winning_score_row.visible).is_false()