Files
aetherbound-guild/runtime/tests/foundation/m50_responsive_ui_test.gd
T

73 lines
3.6 KiB
GDScript

extends SceneTree
const PageContext = preload("res://foundation/page_context.gd")
const UITokens = preload("res://foundation/ui_tokens.gd")
const MarketPageView = preload("res://entry/views/market_page_view.gd")
var failures: Array[String] = []
func _initialize() -> void:
call_deferred("run_test")
func run_test() -> void:
# Single authoritative size (owner policy).
for fixture in [{"width": 1280, "height": 720}]:
await _check_fixture(int(fixture.width), int(fixture.height))
if failures.is_empty():
print("ABG_M50_RESPONSIVE_UI_OK fixtures=1280x720 shared_surface=board,card shared_commands=true fixed_text=true intents=preserved")
quit(0)
else:
for failure in failures:
push_error(failure)
quit(1)
func _check_fixture(width: int, height: int) -> void:
var host := Control.new()
host.name = "M50FixtureHost"
host.size = Vector2(width, height)
root.add_child(host)
var view := MarketPageView.new()
view.size = host.size
view.configure_presentation({"safe_area": 18, "text_scale": 1.0, "locale": "zh_CN"})
view.mount(PageContext.new({"page_id": "market", "caller_id": "guild", "return_page_id": "guild"}))
host.add_child(view)
view.render(_fixture_data())
await process_frame
var board := view.find_child("MarketContextSurface", true, false) as Control
var first_card := view.find_child("MarketOfferR-001", true, false) as Button
var review := view.find_child("MarketReviewRecruit", true, false) as Button
expect(board != null, "%dx%d board NinePatch exists" % [width, height])
expect(first_card != null, "%dx%d recruit card exists" % [width, height])
expect(review != null and review.size.y >= 48.0, "%dx%d primary button keeps minimum height" % [width, height])
if board != null:
expect(board.size.x >= 260.0, "%dx%d board expands horizontally" % [width, height])
# The shared ledger owns its own shell/chrome (M52 module), not a page-local
# panel: assert the shared surface node exists inside the ledger.
expect(board.get_node_or_null("LedgerShell") != null, "%dx%d board uses a shared surface" % [width, height])
# Current card grammar: the name lives under the shared identity module.
var name_label := first_card.get_node_or_null("VisualLayer/IdentityModule/NameLabel") as Label if first_card != null else null
# Fixed type means token-sourced sizes, never raw page literals.
var token_sizes: Array = []
for role in ["caption", "micro", "label", "body", "heading", "title"]:
token_sizes.append(UITokens.font_size(role, 1.0))
token_sizes.append(UITokens.font_size(role, 2.0))
expect(name_label != null and name_label.get_theme_font_size("font_size") in token_sizes, "%dx%d card text stays on token type sizes" % [width, height])
host.queue_free()
await process_frame
func _fixture_data() -> Dictionary:
return {
"ok": true, "locale": "zh_CN", "category": "recruit", "selected_kind": "recruit", "selected_offer_id": "R-001",
"selected_offer": _recruit("R-001", "Ari"),
"offers": {"recruit": [_recruit("R-001", "Ari"), _recruit("R-002", "Bram"), _recruit("R-003", "Cera")]},
"company": {"owned_count": 2, "line_capacity": 4, "coin": 38},
"commands": {"return_contract": {"enabled": true, "reason": "ready"}}, "content": {},
}
func _recruit(offer_id: String, name: String) -> Dictionary:
return {"source_offer_id": offer_id, "display_name_tokens": ["name.%s" % name.to_lower()], "profession_id": "PF-B01", "trait_id": "TR-001", "list_price": 14, "attribute_rolls": {"vigor": 3, "force": 2, "finesse": 1, "resolve": 2, "focus": 1}}
func expect(condition: bool, message: String) -> void:
if not condition:
failures.append("M50 Responsive UI: %s" % message)