Files
MusicPlayer/tests/integration/test_music_player_scene.gd
Sansan 4a934840f6
Build / test (push) Successful in 1m11s
Build / build (push) Successful in 1m20s
Restyle the music player bar
The bar is rounded and a little taller, with a round orange play button
and a restart button that lights up orange under the mouse. The icons sit
inside their buttons with room around them, and are one colour, cropped to
their shape. Progress fills in orange, the volume slider gets a speaker
icon, and the buttons say their shortcut keys in their tooltips.

Buttons grow a little under the mouse and shrink while held down, and the
play button pops when it switches between play and pause. ButtonBounce
holds these animations so other buttons can use them too.
2026-10-09 17:38:38 +02:00

155 lines
5.2 KiB
GDScript

extends GdUnitTestSuite
## The music player scene: the player bar. Auto repeat is in the quiz settings card.
var _snapshot: AutoloadSnapshot
var _runner: GdUnitSceneRunner
var _player: MusicPlayer
func before_test() -> void:
_snapshot = AutoloadSnapshot.take([Settings])
Settings.auto_repeat_song = true
_runner = scene_runner("res://player/MusicPlayer.tscn")
_player = _runner.scene()
func after_test() -> void:
_snapshot.restore()
func _click(control: Control) -> void:
_runner.set_mouse_position(_player.get_viewport().get_final_transform()
* control.get_global_rect().get_center())
await _runner.simulate_mouse_button_pressed(MOUSE_BUTTON_LEFT)
await _runner.await_input_processed()
func test_empty_space_lets_clicks_through() -> void:
assert_int(_player.mouse_filter).is_equal(Control.MOUSE_FILTER_IGNORE)
func _song() -> AudioStreamMP3:
var song: AudioStreamMP3 = AudioStreamMP3.new()
song.data = FileAccess.get_file_as_bytes("res://tests/data/short.mp3")
return song
func _buttons() -> Array[Button]:
return [_player.play_button, _player.restart_button]
# Waits until the buttons' animations have finished
func _settle() -> void:
await await_millis(int(maxf(ButtonBounce.DURATION, ButtonBounce.POP_DURATION) * 1000) + 80)
# Icons
func test_icons_sit_inside_their_buttons_with_room_around_them() -> void:
await _runner.simulate_frames(1)
for button: Button in _buttons():
var style: StyleBox = button.get_theme_stylebox(&"normal")
for side: Side in [SIDE_LEFT, SIDE_TOP, SIDE_RIGHT, SIDE_BOTTOM]:
assert_float(style.get_content_margin(side)).override_failure_message(button.name) \
.is_greater_equal(8.0)
assert_bool(button.expand_icon).override_failure_message(button.name).is_true()
assert_int(button.icon_alignment).is_equal(HORIZONTAL_ALIGNMENT_CENTER)
# A square button, so the round background is a circle around the icon
assert_float(button.size.x).override_failure_message(button.name) \
.is_equal(button.size.y)
var icon_room: Vector2 = button.size - style.get_minimum_size()
assert_float(icon_room.x).override_failure_message(button.name).is_greater(12.0)
func test_buttons_are_centred_in_the_bar() -> void:
await _runner.simulate_frames(1)
var bar: Rect2 = _player.get_node("PlayerBar").get_global_rect()
for button: Button in _buttons():
var rect: Rect2 = button.get_global_rect()
assert_bool(bar.encloses(rect)).override_failure_message(button.name).is_true()
assert_float(rect.get_center().y).override_failure_message(button.name) \
.is_equal_approx(bar.get_center().y, 1.0)
func test_play_button_stands_out_from_restart() -> void:
assert_str(_player.play_button.theme_type_variation).is_equal("PlayerButtonPrimary")
assert_str(_player.restart_button.theme_type_variation).is_equal("PlayerButton")
assert_str(_player.progress_slider.theme_type_variation).is_equal("ProgressSlider")
assert_str(_player.volume_slider.theme_type_variation).is_equal("VolumeBar")
assert_str(_player.music_time_label.theme_type_variation).is_equal("PlayerTime")
func test_buttons_have_tooltips_with_their_keys() -> void:
assert_str(_player.play_button.tooltip_text).contains("Alt+X")
assert_str(_player.restart_button.tooltip_text).contains("Alt+Z")
# Play and pause
func test_play_button_shows_play_until_a_song_plays() -> void:
assert_bool(_player.shows_playing()).is_false()
_player.play_song(_song())
assert_bool(_player.shows_playing()).is_true()
assert_object(_player.play_button.icon).is_same(_player.pause_icon)
func test_pausing_shows_play_again() -> void:
await _runner.simulate_frames(1)
_player.play_song(_song())
await _click(_player.play_button)
assert_bool(_player.audio_player.stream_paused).is_true()
assert_bool(_player.shows_playing()).is_false()
func test_play_button_pops_when_it_changes() -> void:
await _runner.simulate_frames(1)
_player.play_song(_song())
assert_vector(_player.play_button.scale).is_equal(ButtonBounce.POP_SCALE)
await _settle()
assert_vector(_player.play_button.scale).is_equal_approx(Vector2.ONE, Vector2(0.01, 0.01))
func test_play_button_does_not_pop_when_it_stays_the_same() -> void:
_player.play_song(_song())
await _settle()
_player.play_song(_song())
assert_vector(_player.play_button.scale).is_equal_approx(Vector2.ONE, Vector2(0.01, 0.01))
# Hover
func test_buttons_grow_under_the_mouse_and_shrink_back() -> void:
await _runner.simulate_frames(1)
for button: Button in _buttons():
_runner.set_mouse_position(_player.get_viewport().get_final_transform()
* button.get_global_rect().get_center())
await _runner.simulate_frames(2)
await _settle()
assert_vector(button.scale).override_failure_message(button.name) \
.is_equal_approx(ButtonBounce.HOVER_SCALE, Vector2(0.01, 0.01))
_runner.set_mouse_position(Vector2.ZERO)
await _runner.simulate_frames(2)
await _settle()
assert_vector(button.scale).override_failure_message(button.name) \
.is_equal_approx(Vector2.ONE, Vector2(0.01, 0.01))
func test_growing_keeps_the_button_in_place() -> void:
await _runner.simulate_frames(1)
var before: Vector2 = _player.restart_button.get_global_rect().get_center()
_player.restart_button.mouse_entered.emit()
await _settle()
assert_vector(_player.restart_button.get_global_rect().get_center()) \
.is_equal_approx(before, Vector2(0.5, 0.5))