extends SceneTree const Controller = preload("res://p9_8/runtime_controller.gd") const Fixture = preload("res://tests/p9_8/runtime_fixture.gd") const BossService = preload("res://p9_8/boss_service.gd") const BossBattleService = preload("res://p9_8/boss_battle_service.gd") var failures: Array[String] = [] var experience var capture_root := "" var captures := 0 func _initialize() -> void: call_deferred("run_test") func run_test() -> void: capture_root = OS.get_environment("ABG_P9_8_LAYOUT_CAPTURE_ROOT") if not capture_root.is_empty(): DirAccess.make_dir_recursive_absolute(capture_root) var market8 := Fixture.market8() await fixture("01-artifact-small-zh", market8, Vector2i(760, 360), "zh_CN", 1.0, false, false) var promotion := BossService.new(market8) promotion.choose_artifact("layout-artifact", "AR-002") await fixture("02-promotion-reference-en130", promotion.state.snapshot(), Vector2i(844, 390), "en", 1.3, false, false) if not promotion.state.promotion_draft.is_empty(): var recruit_id := String(promotion.state.promotion_draft.recruit_id) promotion.confirm_promotion("layout-promotion", recruit_id, String(promotion.state.promotion_draft.offer_ids[1])) await fixture("03-market-large-reduced", promotion.state.snapshot(), Vector2i(1280, 720), "zh_CN", 1.0, true, false) var muster := Fixture.boss_muster() await fixture("04-boss-muster-reference", muster, Vector2i(844, 390), "zh_CN", 1.0, false, false) await mount(muster, Vector2i(844, 390), "en", 1.0, false, true) experience.choose_boss_plan("rotate") for _tick in 90: experience.advance_battle_ticks(1) await settle_frames() verify_current("05-boss-battle-low-power", Vector2i(844, 390), false) await capture("05-boss-battle-low-power") var recovery := boss_recovery_state(muster) await fixture("06-boss-recovery-zh130", recovery, Vector2i(844, 390), "zh_CN", 1.3, true, false) var result := boss_result_state(muster) await fixture("07-contract-result-en", result, Vector2i(844, 390), "en", 1.0, false, false) var closed_service = BossService.new() closed_service.state.restore_snapshot(result) closed_service.close_contract("layout-close") await fixture("08-persistent-result-large", closed_service.state.snapshot(), Vector2i(1280, 720), "zh_CN", 1.0, false, false) await fixture("09-portrait-rotate", market8, Vector2i(390, 844), "zh_CN", 1.0, false, false, true) if is_instance_valid(experience): experience.queue_free() for _index in 45: await process_frame if failures.is_empty(): print("ABG_P9_8_LAYOUT_ACCESSIBILITY_OK fixtures=9 states=artifact,promotion,market,boss_muster,boss_battle,recovery,contract_result,persistent,rotate viewports=760x360,844x390,1280x720,390x844 locales=zh_CN,en text_130=true reduced_motion=true muted=true low_power=true controls=48 cards=0 captures=%d" % captures) quit(0) else: for failure in failures: push_error(failure) quit(1) func fixture(label: String, snapshot: Dictionary, viewport: Vector2i, locale: String, text_scale: float, reduced: bool, low_power: bool, portrait := false) -> void: await mount(snapshot, viewport, locale, text_scale, reduced, low_power) verify_current(label, viewport, portrait) await capture(label) func mount(snapshot: Dictionary, viewport: Vector2i, locale: String, text_scale: float, reduced: bool, low_power: bool) -> void: if is_instance_valid(experience): experience.queue_free() await settle_frames() root.size = viewport root.content_scale_mode = Window.CONTENT_SCALE_MODE_CANVAS_ITEMS root.content_scale_aspect = Window.CONTENT_SCALE_ASPECT_EXPAND root.content_scale_size = viewport experience = Controller.new() experience.persistence_enabled = false experience.battle_auto_advance = false experience.locale = locale experience.text_scale = text_scale experience.reduced_motion = reduced experience.muted = true experience.low_power = low_power experience.size = Vector2(viewport) experience.configure_entry(snapshot) root.add_child(experience) await settle_frames() func verify_current(label: String, viewport: Vector2i, portrait: bool) -> void: var bounds := Rect2(Vector2.ZERO, Vector2(viewport)) if portrait: expect(experience.find_child("P97RotateNotice", true, false) != null, "%s shows the landscape notice" % label) return expect(experience.find_child("P97RotateNotice", true, false) == null, "%s renders the game world" % label) expect(experience.get_meta("visible_world_ratio", 0.0) >= 0.80, "%s keeps a world-first composition" % label) expect(experience.find_children("*", "Panel", true, false).is_empty(), "%s adds no app panels" % label) for node in experience.find_children("*", "Button", true, false): var button := node as Button expect(button.size.x >= 48 and button.size.y >= 48, "%s target %s is at least 48px" % [label, button.name]) expect(bounds.encloses(button.get_global_rect()), "%s target %s stays inside the viewport" % [label, button.name]) for node in experience.find_children("*", "Control", true, false): var lowered := String(node.name).to_lower() expect("card" not in lowered and "modal" not in lowered and "dialog" not in lowered, "%s has no card/modal surface" % label) func boss_recovery_state(muster: Dictionary) -> Dictionary: var service = BossService.new() service.state.restore_snapshot(muster) var fragile_id := "Farstring" if "Farstring" in service.state.company else String(service.state.company[-1]) var line: Array[String] = [fragile_id] service.commit_deployment("layout-fragile", line) service.commit_boss_plan("layout-defeat-plan", "rotate") var battle = BossBattleService.new() battle.start_from_contract(service.state) var guard := 0 while not battle.state.terminal and guard < 1800: battle.advance_ticks(1) guard += 1 service.settle_boss("layout-defeat-settle", battle.state.snapshot()) return service.state.snapshot() func boss_result_state(muster: Dictionary) -> Dictionary: var service = BossService.new() service.state.restore_snapshot(muster) service.commit_boss_plan("layout-win-plan", "brace") var battle = BossBattleService.new() battle.start_from_contract(service.state) var guard := 0 while not battle.state.terminal and guard < 1800: battle.advance_ticks(1) guard += 1 service.settle_boss("layout-win-settle", battle.state.snapshot()) return service.state.snapshot() func capture(label: String) -> void: if capture_root.is_empty(): return await RenderingServer.frame_post_draw var error := root.get_texture().get_image().save_png(capture_root.path_join(label + ".png")) expect(error == OK, "%s capture writes" % label) if error == OK: captures += 1 await process_frame func settle_frames() -> void: await process_frame await process_frame func expect(condition: bool, message: String) -> void: if not condition: failures.append("P9.8 layout: %s" % message)