Files
MusicPlayer/tests/integration/test_character_folders.gd
SansanandClaude Opus 5.5 70e970b24c
Build / test (push) Successful in 1m30s
Build / build (push) Successful in 1m17s
Make the buttons consistent and rework the player list
Buttons get 12 px of side padding. The top bar buttons, the quiz toolbar and
Show answer/Next are laid out in rows with 12 px gaps and are all 36 px tall,
and the ±1 buttons use a compact StepButton style. "Randomize new track" is now
"Next song".

Player rows show the name and the score apart, alternate like the other lists
and highlight the character under the mouse. The name field is a LineEdit with
a 10-letter limit; blank and duplicate names are refused, and a full list says
"Up to 7 players". Remove buttons update when editing is switched instead of
every frame, and the spacer panels are gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:35:24 +02:00

193 lines
7.1 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:
await 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()