extends RefCounted ## Deterministic headless tests for the first-shift tutorial state machine. const Tutorial := preload("res://src/game/tutorial.gd") func test_tutorial_advances_only_on_the_expected_action() -> bool: var tutorial := Tutorial.new() tutorial.start() var a := TestUtils.check(tutorial.current()["id"] == "arrive", "starts at arrival") var b := TestUtils.check(not tutorial.advance("wheel_opened"), "wrong action is ignored") var c := TestUtils.check(tutorial.advance("moved"), "movement advances") var d := TestUtils.check(tutorial.current()["id"] == "focus", "moves to focus") var e := TestUtils.check(tutorial.advance("cycled"), "target cycling advances") var f := TestUtils.check(tutorial.current()["id"] == "wheel", "moves to the action wheel") return a and b and c and d and e and f func test_tutorial_runs_all_beats_and_completes() -> bool: var tutorial := Tutorial.new() tutorial.start() var events := ["moved", "cycled", "wheel_opened", "inspected", "polite_direction", "formal_warning", "radio_submitted", "review_opened"] var ok := true for event in events: ok = ok and tutorial.advance(event) ok = ok and tutorial.is_complete() ok = ok and not tutorial.is_skipped() ok = ok and tutorial.progress() == Vector2i(Tutorial.BEATS.size(), Tutorial.BEATS.size()) return TestUtils.check(ok, "all eight beats complete in order") func test_tutorial_accepts_body_camera_for_warning() -> bool: var tutorial := Tutorial.new() tutorial.start() for event in ["moved", "cycled", "wheel_opened", "inspected", "polite_direction"]: tutorial.advance(event) var a := TestUtils.check(tutorial.advance("body_camera"), "body camera satisfies warning") var b := TestUtils.check(tutorial.current()["id"] == "radio", "advances to radio") return a and b func test_tutorial_skip_and_restart() -> bool: var tutorial := Tutorial.new() tutorial.start() var a := TestUtils.check(tutorial.advance("moved"), "one beat completed") tutorial.skip() var b := TestUtils.check(tutorial.is_complete() and tutorial.is_skipped(), "skip completes tutorial") var c := TestUtils.check(not tutorial.advance("moved"), "completed tutorial is inert") tutorial.restart() var d := TestUtils.check(not tutorial.is_complete() and not tutorial.is_skipped(), "restart clears flags") var e := TestUtils.check(tutorial.current()["id"] == "arrive", "restart returns to beat one") return a and b and c and d and e