158 lines
6.5 KiB
GDScript
158 lines
6.5 KiB
GDScript
extends SceneTree
|
|
|
|
const Controller = preload("res://p10_1/runtime_controller.gd")
|
|
const Fixture = preload("res://tests/p10_1/runtime_fixture.gd")
|
|
const SaveV7 = preload("res://p10_1/save_v7_service.gd")
|
|
const ResolutionService = preload("res://p10_1/first_crossing_resolution_service.gd")
|
|
|
|
const VIEWPORTS := [Vector2i(760, 360), Vector2i(844, 390), Vector2i(1280, 720), Vector2i(390, 844)]
|
|
const LOCALES := ["zh_CN", "en"]
|
|
const TEXT_SCALES := [1.0, 1.3]
|
|
const ACCESSIBILITY := [
|
|
{"reduced": false, "low_power": false},
|
|
{"reduced": true, "low_power": true},
|
|
]
|
|
|
|
var failures: Array[String] = []
|
|
var experience
|
|
var save_cases := 0
|
|
var layout_cases := 0
|
|
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("run_test")
|
|
|
|
|
|
func run_test() -> void:
|
|
root.content_scale_mode = Window.CONTENT_SCALE_MODE_CANVAS_ITEMS
|
|
root.content_scale_aspect = Window.CONTENT_SCALE_ASPECT_EXPAND
|
|
verify_save_phase_matrix()
|
|
await verify_layout_matrix()
|
|
if is_instance_valid(experience):
|
|
experience.queue_free()
|
|
await settle_frames(45)
|
|
if failures.is_empty():
|
|
print("ABG_P10_1_CANDIDATE_MATRIX_OK save_cases=%d phases=market,prepared,recovery,market2,recovered layout_cases=%d viewports=760x360,844x390,1280x720,390x844 locales=zh_CN,en text=100,130 reduced_motion=true low_power=true mute=true controls=48 panels=0 cards=0 offline_rewards=0" % [save_cases, layout_cases])
|
|
quit(0)
|
|
else:
|
|
for failure in failures:
|
|
push_error(failure)
|
|
quit(1)
|
|
|
|
|
|
func verify_save_phase_matrix() -> void:
|
|
var recovery: Dictionary = Fixture.recovery_snapshot()
|
|
var resolver = ResolutionService.new(recovery)
|
|
var recovered: Dictionary = resolver.recover(
|
|
"candidate-matrix-recover",
|
|
resolver.state.revision,
|
|
String(resolver.state.current_run.last_battle_report.battle_hash),
|
|
int(resolver.state.current_run.recovery_cost)
|
|
)
|
|
expect(recovered.ok, "recovered Market fixture applies")
|
|
var cases := [
|
|
{"name": "market", "snapshot": Fixture.market_snapshot(), "phase": "market"},
|
|
{"name": "prepared", "snapshot": Fixture.prepared_snapshot(2), "phase": "prepared"},
|
|
{"name": "recovery", "snapshot": recovery, "phase": "recovery"},
|
|
{"name": "market2", "snapshot": Fixture.market_2_snapshot(), "phase": "market_2"},
|
|
{"name": "recovered", "snapshot": resolver.state.snapshot(), "phase": "market"},
|
|
]
|
|
for index in range(cases.size()):
|
|
var row: Dictionary = cases[index]
|
|
var sequence := 70 + index
|
|
var encoded: Dictionary = SaveV7.new().encode_snapshot(row.snapshot, sequence)
|
|
expect(encoded.ok, "%s Save-v7 encodes" % row.name)
|
|
if not encoded.ok:
|
|
continue
|
|
var decoded: Dictionary = SaveV7.new().decode_text(String(encoded.text), sequence)
|
|
expect(decoded.ok and decoded.snapshot == row.snapshot, "%s Save-v7 roundtrip is exact" % row.name)
|
|
expect(decoded.offline_delta == SaveV7.OFFLINE_ZERO, "%s reload grants zero offline value" % row.name)
|
|
expect(String(decoded.snapshot.current_run.phase) == String(row.phase), "%s reload preserves phase" % row.name)
|
|
save_cases += 1
|
|
|
|
|
|
func verify_layout_matrix() -> void:
|
|
var state_index := 0
|
|
for viewport in VIEWPORTS:
|
|
for locale in LOCALES:
|
|
for text_scale in TEXT_SCALES:
|
|
for access in ACCESSIBILITY:
|
|
var state_kind := state_index % 5
|
|
await mount(layout_snapshot(state_kind), viewport, locale, text_scale, bool(access.reduced), bool(access.low_power))
|
|
if state_kind == 4 and viewport.x > viewport.y:
|
|
experience.choose_region_plan("follow_tide")
|
|
experience.region_battle_paused = true
|
|
experience.advance_region_battle_ticks(52)
|
|
await settle_frames()
|
|
verify_layout(viewport, state_kind)
|
|
layout_cases += 1
|
|
state_index += 1
|
|
|
|
|
|
func layout_snapshot(state_kind: int) -> Dictionary:
|
|
match state_kind:
|
|
0:
|
|
return Fixture.market_snapshot()
|
|
1:
|
|
return Fixture.prepared_snapshot(2)
|
|
2:
|
|
return Fixture.recovery_snapshot()
|
|
3:
|
|
return Fixture.market_2_snapshot()
|
|
_:
|
|
return Fixture.prepared_snapshot(2)
|
|
|
|
|
|
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(8)
|
|
root.size = viewport
|
|
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_layout(viewport: Vector2i, state_kind: int) -> void:
|
|
var bounds := Rect2(Vector2.ZERO, Vector2(viewport))
|
|
if viewport.y > viewport.x:
|
|
expect(experience.find_child("P97RotateNotice", true, false) != null, "portrait matrix shows rotation guidance")
|
|
return
|
|
expect(experience.find_child("P97RotateNotice", true, false) == null, "landscape matrix renders the game world")
|
|
expect(float(experience.get_meta("visible_world_ratio", 0.0)) >= 0.80, "landscape matrix remains world-first")
|
|
expect(experience.find_children("*", "Panel", true, false).is_empty(), "matrix adds no app Panel surfaces")
|
|
for node in experience.find_children("*", "Control", true, false):
|
|
var control := node as Control
|
|
if not control.visible or control.is_queued_for_deletion():
|
|
continue
|
|
var lowered := String(control.name).to_lower()
|
|
expect("card" not in lowered and "modal" not in lowered and "dialog" not in lowered, "matrix adds no card/modal surface: %s" % control.name)
|
|
expect(is_finite(control.position.x) and is_finite(control.position.y) and control.size.x >= 0.0 and control.size.y >= 0.0, "matrix control %s has finite geometry" % control.name)
|
|
if control is Button:
|
|
expect(control.size.x >= 48.0 and control.size.y >= 48.0, "matrix button %s is at least 48px" % control.name)
|
|
expect(bounds.encloses(control.get_global_rect()), "matrix button %s remains inside %s" % [control.name, viewport])
|
|
if state_kind == 4:
|
|
expect(experience.screen == Controller.REGION_SCREEN_BATTLE, "battle matrix reaches the live battle")
|
|
expect(not experience.find_children("P101BattleActor_*", "TextureRect", true, false).is_empty(), "battle matrix renders Company motion actors")
|
|
expect(not experience.find_children("P101BattleEnemy_*", "TextureRect", true, false).is_empty(), "battle matrix renders staged enemies")
|
|
|
|
|
|
func settle_frames(count := 5) -> void:
|
|
for _index in count:
|
|
await process_frame
|
|
|
|
|
|
func expect(condition: bool, message: String) -> void:
|
|
if not condition:
|
|
failures.append("P10.1 candidate matrix: %s" % message)
|