@@ -103,3 +103,74 @@ struct LazyTests {
103103 #expect( node. props [ " trackCount " ] == nil )
104104 }
105105}
106+
107+ @Suite ( " Lazy stacks " )
108+ struct LazyStackTests {
109+
110+ @Test ( " LazyVStack over a ForEach resolves only the elements asked for " )
111+ func lazyVStackIsLazy( ) {
112+ // a counter proves elements aren't built until requested
113+ final class Probe : @unchecked Sendable { var built = 0 }
114+ let probe = Probe ( )
115+ struct Row : View {
116+ let index : Int
117+ let probe : Probe
118+ var body : some View {
119+ probe. built += 1
120+ return Text ( " Row \( index) " )
121+ }
122+ }
123+ let host = ViewHost (
124+ LazyVStack {
125+ ForEach ( 0 ..< 10_000 , id: \. self) { index in Row ( index: index, probe: probe) }
126+ }
127+ )
128+ let node = host. evaluate ( )
129+ #expect( node. type == " LazyVStack " )
130+ #expect( node. count == 10_000 )
131+ #expect( probe. built == 0 ) // nothing resolved up front
132+
133+ guard case . int( let provider) ? = node. props [ " itemProvider " ] else {
134+ Issue . record ( " missing item provider " ) ; return
135+ }
136+ let row = host. callbacks. item ( Int64 ( provider) , 42 )
137+ #expect( firstTextString ( row!) == " Row 42 " )
138+ #expect( probe. built == 1 ) // exactly the one requested
139+ }
140+
141+ @Test ( " A lazy stack keys its elements by identity, not position " )
142+ func lazyVStackKeys( ) {
143+ let node = ViewHost (
144+ LazyVStack {
145+ ForEach ( [ " a " , " b " , " c " ] , id: \. self) { Text ( $0) }
146+ }
147+ ) . evaluate ( )
148+ guard case . array( let keys) ? = node. props [ " keys " ] else {
149+ Issue . record ( " missing keys " ) ; return
150+ }
151+ #expect( keys == [ . string( " a " ) , . string( " b " ) , . string( " c " ) ] )
152+ }
153+
154+ @Test ( " Content that isn't a single ForEach still renders, eagerly " )
155+ func lazyVStackFallback( ) {
156+ let node = ViewHost (
157+ LazyVStack {
158+ Text ( " header " )
159+ Text ( " footer " )
160+ }
161+ ) . evaluate ( )
162+ #expect( node. type == " LazyVStack " )
163+ #expect( node. props [ " itemProvider " ] == nil ) // no lazy path
164+ #expect( node. children. count == 2 ) // but the content is intact
165+ }
166+
167+ @Test ( " LazyHStack carries the same provider shape " )
168+ func lazyHStack( ) {
169+ let node = ViewHost (
170+ LazyHStack { ForEach ( 0 ..< 50 , id: \. self) { Text ( " \( $0) " ) } }
171+ ) . evaluate ( )
172+ #expect( node. type == " LazyHStack " )
173+ #expect( node. count == 50 )
174+ #expect( node. props [ " itemProvider " ] != nil )
175+ }
176+ }
0 commit comments