2026-09-28 22:56:40 +03:00
extends SceneTree
2026-09-30 08:08:27 +03:00
const E = preload ( "res://world/owniverse/math/exact.gd" )
2026-09-28 22:56:40 +03:00
var checks : int = 0
var failures : int = 0
func _initialize () -> void :
call_deferred ( "run" )
func check ( value : bool , message : String ) -> void :
2026-09-30 08:08:27 +03:00
checks = E . add ( checks , 1 )
if ( not value ):
failures = E . add ( failures , 1 )
2026-09-28 22:56:40 +03:00
push_error ( message )
func run () -> void :
var scene = load ( "res://world/world.tscn" ) . instantiate ()
var stage = scene . get_node ( "Stage" )
stage . owniverse . free ()
stage . set_script ( load ( "res://tests/fixtures/ui_stage.gd" ))
root . add_child ( scene )
await process_frame
await process_frame
var world = stage . owniverse
2026-09-30 08:08:27 +03:00
world . state . binds . RD = { "EON1" : 10 , "EON2" : 4 , "C0.0" : 3 }
world . state . amount . EON1 = 2
world . state . stats . total_amount . EON1 = 12
world . state . stats . total_amount . EON2 = 4
world . state . stats . total_amount [ "C0.0" ] = 3
2026-09-28 22:56:40 +03:00
var before : Dictionary = world . state . duplicate ( true )
stage . _refresh_universe_ui ()
2026-09-29 20:23:20 +03:00
var counts : Dictionary = world . presentation . amounts ( world . state , world . catalog )
2026-09-30 08:08:27 +03:00
check ((( E . eq ( counts . EON1 , 12 ) and E . eq ( counts . EON2 , 4 )) and E . eq ( counts . LP , 16 )), "Individual eons and their total include bound planets" )
check ((( E . eq ( counts [ "C0.0" ], 3 ) and E . eq ( counts . C0 , 3 )) and E . eq ( counts . Planet , 19 )), "Civilization detail does not double the planetary total" )
check (( E . eq ( world . presentation . amounts ( world . state , world . catalog , true ) . EON1 , 12 ) and E . eq ( world . presentation . amounts ( world . state , world . catalog , true ) . LP , 16 )), "Historical counts retain individual and aggregate values" )
check ( E . eq ( world . state , before ), "Presentation does not modify simulation state" )
2026-09-29 19:55:20 +03:00
var pending : Array = [ "EON1" , "EON2" , "EON3" , "C0.0" ]
var pending_before : Array = pending . duplicate ()
var decision : Dictionary = world . presentation . unlocks ( world . state , world . catalog , pending )
2026-09-30 08:08:27 +03:00
check ( E . eq ( decision . remaining , [ "EON3" ]), "Only unmet requirements remain pending" )
2026-09-29 19:55:20 +03:00
for id in [ "EON1" , "EON2" , "LP" , "C0.0" , "C0" ]:
2026-09-30 08:08:27 +03:00
check ( decision . visible . has ( id ), E . add ( "Unlock projection includes detail and alias: " , id ))
check (( E . eq ( pending , pending_before ) and E . eq ( world . state , before )), "Unlock evaluation leaves inputs untouched" )
2026-09-29 20:23:20 +03:00
var snapshot : Dictionary = world . presentation . pending_amounts . duplicate ()
world . presentation . deferred_updates = true
2026-09-30 08:08:27 +03:00
world . state . amount . EON1 = E . add ( world . state . amount . EON1 , 1 )
2026-09-29 20:23:20 +03:00
world . presentation . refresh ( world . state , world . catalog )
2026-09-30 08:08:27 +03:00
check (( world . presentation . dirty and E . eq ( world . presentation . pending_amounts , snapshot )), "Deferred refresh retains pending snapshot" )
2026-09-29 20:23:20 +03:00
world . presentation . refresh ( world . state , world . catalog , true )
2026-09-30 08:08:27 +03:00
check ((( not world . presentation . dirty ) and E . eq ( world . presentation . pending_amounts . EON1 , 13 )), "Forced refresh publishes latest amounts" )
world . state . amount . EON1 = E . subtract ( world . state . amount . EON1 , 1 )
2026-09-29 20:23:20 +03:00
world . presentation . deferred_updates = false
world . presentation . refresh ( world . state , world . catalog )
2026-09-28 22:56:40 +03:00
for id in [ "EON1" , "EON2" , "LP" , "C0.0" , "C0" ]:
2026-09-30 08:08:27 +03:00
check ( stage . owniverse_items [ id ] . visible , E . add ( "Unlock both levels: " , id ))
check ( E . ne ( stage . owniverse_items [ id ] . description . text , "" ), E . add ( "Populate the icon counter: " , id ))
check (( not stage . owniverse_items . EON3 . visible ), "Unreached eon remains locked" )
2026-09-28 22:56:40 +03:00
stage . item_activated ( stage . owniverse_items . LP )
check ( stage . owniverse_items . EON1 . is_visible_in_tree (), "Selecting LP shows its unlocked eons" )
stage . item_activated ( stage . owniverse_items . C0 )
2026-09-30 08:08:27 +03:00
check (( stage . owniverse_items [ "C0.0" ] . is_visible_in_tree () and ( not stage . owniverse_items . EON1 . is_visible_in_tree ())), "Selecting C0 switches the detail panel" )
world . state . binds . RD . EON2 = 0
2026-09-28 22:56:40 +03:00
stage . _refresh_universe_ui ()
2026-09-30 08:08:27 +03:00
check (( stage . owniverse_items . EON2 . visible and E . eq ( stage . owniverse_items . EON2 . description . text , "" )), "Previously reached stage stays unlocked after extinction with no stale count" )
2026-09-29 20:23:20 +03:00
for entity in world . catalog . entities . values (): entity . free ()
2026-09-28 22:56:40 +03:00
world . free ()
scene . free ()
2026-09-30 08:08:27 +03:00
print (( "Life icons: %d checks, %d failures" % [ checks , failures ]))
quit (( 0 if E . eq ( failures , 0 ) else 1 ))