Files
MusicPlayer/tests/integration/test_character_folders.gd
T
Sansan e4352a9f34
Build / test (push) Successful in 1m25s
Build / build (push) Successful in 1m12s
Save the quiz and continue it after a restart; load characters from a folder
The quiz is saved to current_quiz.json in the config folder after every
change, and the game goes on where it was when it starts again: the
players with their points and characters, every song with who got a point
for it and whether it was played, answered or is playing, and the songs
downloaded ahead with their files. The song that was playing is ready to
play again. Songs whose files are gone are downloaded again.

On a server, the saved songs are checked against the server's playlist. If
it changed, e.g. after a sync, or another server is used, the quiz starts
over with the same players. A quiz from a music folder continues offline,
including how far a prepared quiz has come. A new game is saved like any
other change, and a file that can't be read starts a new quiz.

Characters can be read from a folder picked in Settings instead of the
server, for this session. A music folder with a characters folder brings
its own characters, e.g. for a themed quiz; that folder is not counted as
a soundtrack. When the characters come from somewhere else, players pick
their characters again.

Closes #11, closes #44
2026-10-09 18:08:50 +02:00

193 lines
7.0 KiB
GDScript

extends MainWindowTestSuite
## Characters from a folder on this computer: one picked in the settings, or the
## characters folder of the music folder played. Players pick again when the characters
## change.
var _settings: SettingsPopup
var _mp3: PackedByteArray = FileAccess.get_file_as_bytes("res://tests/data/short.mp3")
func _before_window_starts() -> void:
var png: PackedByteArray = Image.create(8, 4, false, Image.FORMAT_RGB8).save_png_to_buffer()
_server.respond_json("/character/list", ["Crono.png", "Frog.png"])
_server.respond_bytes("/character?name=Crono.png", png)
_server.respond_bytes("/character?name=Frog.png", png)
func before_test() -> void:
super()
_settings = _window.settings_popup
await _runner.simulate_frames(2)
func _folder(pictures: Array[String], songs: Array[String] = []) -> String:
var root: String = create_temp_dir("character_folders_%d" % randi())
for file_name: String in pictures:
var path: String = root.path_join(file_name)
DirAccess.make_dir_recursive_absolute(path.get_base_dir())
FileAccess.open(path, FileAccess.WRITE).store_buffer(
Image.create(16, 8, false, Image.FORMAT_RGB8).save_png_to_buffer())
for file_name: String in songs:
FileAccess.open(root.path_join(file_name), FileAccess.WRITE).store_buffer(_mp3)
return root
func _card_names() -> Array[String]:
var names: Array[String] = []
for card: CharacterCard in _quiz.character_select_popup.character_grid.get_children():
if !card.is_queued_for_deletion():
names.append(card.character_name)
return names
func _pick(player: PlayerObject, character_name: String) -> void:
_player_row(player).change_character()
await _runner.simulate_frames(1)
for card: CharacterCard in _quiz.character_select_popup.character_grid.get_children():
if card.character_name == character_name:
await _click_at(card.get_global_rect().get_center())
return
fail("No card for " + character_name)
func test_server_characters_are_shown_at_first() -> void:
assert_array(_card_names()).contains_exactly(["Crono.png", "Frog.png"])
assert_str(_settings.characters_label.text).is_equal("From the server")
assert_bool(_settings.use_server_characters_button.visible).is_false()
func test_picking_a_folder_shows_its_characters() -> void:
var folder: String = _folder(["Santa.png", "Elf.jpg"])
_settings.use_character_folder(folder)
await _runner.simulate_frames(1)
assert_array(_card_names()).contains_exactly(["Elf.jpg", "Santa.png"])
assert_str(_settings.characters_label.text).is_equal(folder.get_file())
assert_bool(_settings.use_server_characters_button.visible).is_true()
func test_character_from_a_folder_is_picked_with_its_picture_and_name() -> void:
_settings.use_character_folder(_folder(["Santa.png"]))
var crono: PlayerObject = _add_player("Crono")
await _runner.simulate_frames(1)
await _pick(crono, "Santa.png")
assert_str(crono.character_name).is_equal("Santa.png")
assert_vector(crono.character.get_size()).is_equal(Vector2(16, 8))
func test_picking_a_folder_resets_the_players_characters() -> void:
var crono: PlayerObject = _add_player("Crono")
await _pick(crono, "Frog.png")
assert_str(crono.character_name).is_equal("Frog.png")
_settings.use_character_folder(_folder(["Santa.png"]))
await _runner.simulate_frames(1)
assert_str(crono.character_name).is_empty()
assert_str(crono.character.resource_path).is_equal(PlayerObject.NO_CHARACTER_PATH)
assert_object(_player_row(crono).character.texture_normal).is_same(crono.character)
func test_folder_without_pictures_is_not_used() -> void:
var crono: PlayerObject = _add_player("Crono")
await _pick(crono, "Frog.png")
_settings.use_character_folder(_folder([], ["01. Song.mp3"]))
assert_bool(_settings.characters_error_label.visible).is_true()
assert_str(_settings.characters_error_label.text).starts_with("No pictures found in")
assert_str(Settings.character_folder).is_empty()
assert_array(_card_names()).contains_exactly(["Crono.png", "Frog.png"])
assert_str(crono.character_name).is_equal("Frog.png")
func test_use_server_goes_back_to_the_server_characters() -> void:
_settings.use_character_folder(_folder(["Santa.png"]))
var crono: PlayerObject = _add_player("Crono")
await _pick(crono, "Santa.png")
_settings.use_server_characters()
await _runner.simulate_frames(1)
assert_array(_card_names()).contains_exactly(["Crono.png", "Frog.png"])
assert_str(_settings.characters_label.text).is_equal("From the server")
assert_bool(_settings.use_server_characters_button.visible).is_false()
assert_str(crono.character_name).is_empty()
func test_music_folder_with_characters_brings_its_own() -> void:
var folder: String = _folder(["characters/Santa.png", "characters/Elf.png"],
["01. Jingle Bells.mp3"])
var crono: PlayerObject = _add_player("Crono")
await _pick(crono, "Frog.png")
_settings.use_music_folder(folder)
await _runner.simulate_frames(2)
assert_array(_card_names()).contains_exactly(["Elf.png", "Santa.png"])
assert_str(_settings.characters_label.text).is_equal("From " + folder.get_file())
assert_str(crono.character_name).is_empty()
# A prepared quiz with characters is still a prepared quiz
assert_bool(Settings.is_prepared_quiz()).is_true()
func test_music_folder_without_characters_keeps_the_server_characters() -> void:
var crono: PlayerObject = _add_player("Crono")
await _pick(crono, "Frog.png")
_settings.use_music_folder(_folder([], ["01. Song.mp3"]))
await _runner.simulate_frames(2)
assert_array(_card_names()).contains_exactly(["Crono.png", "Frog.png"])
assert_str(crono.character_name).is_equal("Frog.png")
func test_leaving_a_music_folder_with_characters_goes_back_to_the_server() -> void:
_settings.use_music_folder(_folder(["characters/Santa.png"], ["01. Song.mp3"]))
await _runner.simulate_frames(2)
var crono: PlayerObject = _add_player("Crono")
await _pick(crono, "Santa.png")
_settings.use_server()
await _runner.simulate_frames(2)
assert_array(_card_names()).contains_exactly(["Crono.png", "Frog.png"])
assert_str(crono.character_name).is_empty()
func test_picked_folder_is_used_before_the_music_folders_characters() -> void:
var picked: String = _folder(["Snowman.png"])
_settings.use_character_folder(picked)
await _runner.simulate_frames(1)
_settings.use_music_folder(_folder(["characters/Santa.png"], ["01. Song.mp3"]))
await _runner.simulate_frames(2)
assert_array(_card_names()).contains_exactly(["Snowman.png"])
assert_str(_settings.characters_label.text).is_equal(picked.get_file())
func test_loading_the_same_characters_again_keeps_the_players_characters() -> void:
var crono: PlayerObject = _add_player("Crono")
await _pick(crono, "Frog.png")
# A sync reloads the characters from the same server
_quiz.on_sync_finished()
await _runner.simulate_frames(2)
assert_str(crono.character_name).is_equal("Frog.png")
func test_the_characters_folder_is_kept_for_this_session_only() -> void:
_settings.use_character_folder(_folder(["Santa.png"]))
Settings.save_settings()
var saved: ConfigFile = ConfigFile.new()
saved.load(Settings.saved_settings_path())
for section: String in saved.get_sections():
assert_bool(saved.has_section_key(section, "character_folder")).is_false()