@@ -70,6 +70,64 @@ pub fun ambient_feature_identity_test() : <div> test_result
7070 "resolved= " ++ resolved. show,
7171 passed)
7272
73+ fun lifecycle_seed_tree () : < div > list < state_entry >
74+ val (_unit , tree, _effects ) = run_local_state(Nil , fn () {
75+ feature_root("lifecycle " , "panel " ) {
76+ component("rows " , "left " ) {
77+ val (_draft , set_draft) = state_pair(name = "draft " , initial = "" )
78+ set_draft("left draft " )
79+ }
80+ component("rows " , "right " ) {
81+ val (_draft , set_draft) = state_pair(name = "draft " , initial = "" )
82+ set_draft("right draft " )
83+ }
84+ }
85+ })
86+ tree
87+
88+ pub fun ordinary_component_lifecycle_test () : < div > test_result
89+ val root_scope = component_local_path("lifecycle " , "panel " )
90+ val left_scope = component_child_path(root_scope, "rows " , "left " )
91+ val right_scope = component_child_path(root_scope, "rows " , "right " )
92+ val restored_tree = decode_state_snapshot(encode_state_snapshot(lifecycle_seed_tree()))
93+ val (_unit , next_tree, _effects ) = run_local_state(restored_tree, fn () {
94+ feature_root("lifecycle " , "panel " ) {
95+ component("rows " , "right " ) {
96+ state(name = "draft " , initial = "" )
97+ ()
98+ }
99+ }
100+ })
101+ val left_draft = read_named_local_state(next_tree, left_scope, "draft " , "<removed> " )
102+ val right_draft = read_named_local_state(next_tree, right_scope, "draft " , "<missing> " )
103+ val left_marker_removed = not(any(next_tree, fn (entry) entry. schema == "respo/component-scope " && entry. payload == left_scope))
104+ val right_marker_kept = any(next_tree, fn (entry) entry. schema == "respo/component-scope " && entry. payload == right_scope)
105+ Test_result (
106+ "Ordinary child state is swept after unmount " ,
107+ "left= " ++ left_draft ++ ", right= " ++ right_draft ++ ", markers= " ++ left_marker_removed. show ++ "/ " ++ right_marker_kept. show,
108+ left_draft == "<removed> " && right_draft == "right draft " && left_marker_removed && right_marker_kept)
109+
110+ pub fun persistent_feature_lifecycle_test () : < div > test_result
111+ val root_scope = component_local_path("lifecycle " , "panel " )
112+ val left_scope = component_child_path(root_scope, "rows " , "left " )
113+ val (_hidden , hidden_tree, _hidden_effects ) = run_local_state(lifecycle_seed_tree(), fn () {
114+ feature_root("other " , "panel " ) { () }
115+ })
116+ val restored_tree = decode_state_snapshot(encode_state_snapshot(hidden_tree))
117+ val (_returned , return_tree, _return_effects ) = run_local_state(restored_tree, fn () {
118+ feature_root("lifecycle " , "panel " ) {
119+ component("rows " , "left " ) {
120+ state(name = "draft " , initial = "" )
121+ ()
122+ }
123+ }
124+ })
125+ val restored_draft = read_named_local_state(return_tree, left_scope, "draft " , "<missing> " )
126+ Test_result (
127+ "Unmounted feature root preserves child snapshot " ,
128+ "draft= " ++ restored_draft ++ ", hidden-entries= " ++ hidden_tree. length. show,
129+ restored_draft == "left draft " )
130+
73131pub fun generic_state_codec_test () : < div > test_result
74132 val scope_name = component_local_path("tests " , "implicit-codec " )
75133 val ((draft, open_before), next_tree, _pending_effects ) = run_local_state(Nil , fn () {
0 commit comments