straywild/tests/title_credits_validation.gd

267 lines
8.3 KiB
GDScript

extends SceneTree
const TitleScreenScene := preload("res://ui/title_screen.tscn")
const TitleCreditsPageType = preload("res://ui/title_credits_page.gd")
var _failures: Array[String] = []
func _initialize() -> void:
_run.call_deferred()
func _run() -> void:
var original_size: Vector2i = root.size
root.size = Vector2i(1280, 720)
var title_screen := TitleScreenScene.instantiate() as TitleScreen
root.add_child(title_screen)
await process_frame
await process_frame
var credits_button := title_screen.get_node(
"%CreditsButton"
) as BubbleButton
var play_button := title_screen.get_node("%PlayButton") as BubbleButton
var continue_stats_drawer := title_screen.get_node(
"%ContinueStatsDrawer"
) as RichTextLabel
var credits_page := title_screen.get_node(
"%CreditsPage"
) as TitleCreditsPageType
var back_button: Button = credits_page.get_back_button()
var presentation := title_screen.get_node("%Center") as Control
var bubble_field := title_screen.get_node("%BubbleField") as Control
title_screen.call("_update_title_layout")
(title_screen.get_node("%ButtonCenter") as Control).show()
bubble_field.show()
title_screen.call("_set_title_bubbles_interactive", true)
await process_frame
_expect(credits_button != null, "title menu exposes a credits button")
_expect(play_button != null, "title menu exposes the play button")
_expect(
continue_stats_drawer != null,
"play button owns a dedicated save-preview drawer",
)
if play_button != null and continue_stats_drawer != null:
_expect(
continue_stats_drawer.get_parent() == play_button,
"save preview extends directly from the play button",
)
_expect(
continue_stats_drawer.position.y < play_button.size.y
and (
continue_stats_drawer.position.y
+ continue_stats_drawer.size.y
) > play_button.size.y,
"save preview overlaps the play edge and extends below it",
)
_expect(
continue_stats_drawer.mouse_filter
== Control.MOUSE_FILTER_IGNORE,
"save preview drawer cannot intercept menu input",
)
_expect(
credits_button.icon != null and credits_button.text.is_empty(),
"credits action uses its icon in the square-button presentation",
)
_expect(credits_page != null, "title screen contains the credits page")
_expect(not credits_page.visible, "credits page starts closed")
_expect(
Rect2(Vector2.ZERO, bubble_field.size).encloses(
Rect2(credits_button.position, credits_button.size)
),
"credits button stays inside the authored title field",
)
_expect(
credits_button.mouse_filter == Control.MOUSE_FILTER_STOP,
"credits button accepts pointer input",
)
if OS.has_environment("straywild_TITLE_MENU_CAPTURE"):
(title_screen.get_node("%StartPromptCenter") as Control).hide()
title_screen.set_process(true)
await create_timer(0.5).timeout
_expect(
_save_capture(
OS.get_environment("straywild_TITLE_MENU_CAPTURE")
) == OK,
"title menu validation capture saves successfully",
)
title_screen.set_process(false)
title_screen.set("_navigation_focus_active", false)
credits_button.call("_set_hovered", true)
credits_button.advance_emphasis(1.0)
_expect(
(credits_button.get_node("HoverDrawer") as Control).visible,
"pointer hover reveals the credits drawer before activation",
)
credits_button.pressed.emit()
await process_frame
_expect(credits_page.visible, "pointer activation opens credits")
_expect(not presentation.visible, "credits replace the primary title menu")
_expect(
not (credits_button.get_node("HoverDrawer") as Control).visible,
"opening a title page collapses its hover drawer",
)
_expect(
root.gui_get_focus_owner() != back_button,
"pointer activation does not pseudo-select back",
)
await create_timer(0.25).timeout
_expect(
credits_page.mouse_filter == Control.MOUSE_FILTER_PASS,
"credits page becomes pointer-interactive after entry motion",
)
_expect(
back_button.mouse_filter == Control.MOUSE_FILTER_STOP,
"credits back button accepts pointer clicks",
)
if OS.has_environment("straywild_CREDITS_CAPTURE"):
await process_frame
_expect(
_save_capture(
OS.get_environment("straywild_CREDITS_CAPTURE")
) == OK,
"credits validation capture saves successfully",
)
back_button.pressed.emit()
await process_frame
_expect(not credits_page.visible, "pointer back closes credits")
_expect(presentation.visible, "closing credits restores the title menu")
_expect(
root.gui_get_focus_owner() == null,
"pointer return leaves the title menu unfocused",
)
var online_button := title_screen.get_node(
"%JoinGameButton"
) as BubbleButton
var join_game_page := title_screen.get_node("%JoinGamePage") as Control
online_button.call("_set_hovered", true)
online_button.advance_emphasis(1.0)
_expect(
(online_button.get_node("HoverDrawer") as Control).visible,
"pointer hover reveals the online drawer before activation",
)
online_button.pressed.emit()
await process_frame
_expect(join_game_page.visible, "online activation opens the join page")
_expect(
not (online_button.get_node("HoverDrawer") as Control).visible,
"opening the join page collapses the online drawer",
)
title_screen.call("_close_join_game")
await process_frame
_expect(
not (online_button.get_node("HoverDrawer") as Control).visible,
"returning from the join page does not restore stale pointer hover",
)
title_screen.set("_navigation_focus_active", true)
credits_button.grab_focus()
credits_button.pressed.emit()
await process_frame
await process_frame
_expect(
root.gui_get_focus_owner() == back_button,
"keyboard or controller activation focuses the credits back button",
)
var pointer_motion := InputEventMouseMotion.new()
pointer_motion.position = Vector2(640.0, 360.0)
title_screen._input(pointer_motion)
await process_frame
_expect(
root.gui_get_focus_owner() == null,
"pointer motion clears credits navigation focus",
)
var navigate := InputEventAction.new()
navigate.action = &"ui_down"
navigate.pressed = true
title_screen._input(navigate)
await process_frame
_expect(
root.gui_get_focus_owner() == back_button,
"navigation input restores credits focus",
)
var cancel := InputEventAction.new()
cancel.action = &"ui_cancel"
cancel.pressed = true
title_screen._input(cancel)
await process_frame
_expect(not credits_page.visible, "ui cancel closes credits")
_expect(
root.gui_get_focus_owner() == credits_button,
"navigation return restores focus to the credits button",
)
var chillnfill_name := credits_page.get_node(
"Paper/Margin/Layout/Columns/CreativeCredits/ChillnfillName"
) as Label
var voyager_name := credits_page.get_node(
"Paper/Margin/Layout/Columns/CreativeCredits/VoyagerName"
) as Label
var endeavour_name := credits_page.get_node(
"Paper/Margin/Layout/Columns/CreativeCredits/EndeavourName"
) as Label
var chillnfill_credit := credits_page.get_node(
"Paper/Margin/Layout/Columns/CreativeCredits/ChillnfillCredit"
) as Label
var credits_paper := credits_page.get_node("Paper") as PanelContainer
var audio_credits := credits_page.get_node(
"Paper/Margin/Layout/Columns/AdditionalCredits/AudioCredits"
) as Label
_expect(voyager_name.text == "Voyager", "in-game credits use Voyager")
_expect(
endeavour_name.text == "Endeavour",
"in-game credits use Endeavour",
)
_expect(
chillnfill_name.text == "chillnfill",
"in-game credits name chillnfill",
)
_expect(
"trees and bridges" in chillnfill_credit.text.to_lower(),
"in-game credits describe the supplied model families",
)
_expect(
"kat • animalese source recording" in audio_credits.text,
"in-game credits name kat's animalese source contribution",
)
_expect(
"kim • animalese source recording" in audio_credits.text,
"in-game credits name kim's animalese source contribution",
)
_expect(
credits_paper.get_global_rect().encloses(
audio_credits.get_global_rect()
),
"audio credits stay inside the authored credits panel",
)
title_screen.queue_free()
root.size = original_size
await process_frame
await process_frame
if _failures.is_empty():
print("Title credits validation: PASS")
quit(0)
return
for failure: String in _failures:
push_error(failure)
quit(1)
func _expect(condition: bool, message: String) -> void:
if not condition:
_failures.append(message)
func _save_capture(path: String) -> Error:
var viewport_texture: Texture2D = root.get_texture()
if viewport_texture == null:
return ERR_UNAVAILABLE
return viewport_texture.get_image().save_png(path)