Skip to content

Commit 46dee7c

Browse files
committed
Test that lazy stacks resolve only what is asked for
1 parent 45bf818 commit 46dee7c

1 file changed

Lines changed: 71 additions & 0 deletions

File tree

AndroidSwiftUICore/Tests/AndroidSwiftUICoreTests/LazyTests.swift

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)