test: extract the scroll card and document drag-canvas data flow

AgentDeskFixture.swift sat at exactly 400 lines; the scroll card is
fully self-contained (its offset state never leaves the card), so it
moves to FixtureCards.swift as a standalone view with zero bindings,
landing the main file at 374. Harness-facing labels are byte-identical.
DragCanvas gains two intent comments distinguishing the deliberately
empty updateNSView from a forgotten sync.
This commit is contained in:
Lahfir 2026-06-10 20:23:49 -07:00
parent 11f14ee116
commit e428eb2367
3 changed files with 40 additions and 28 deletions

View file

@ -44,8 +44,6 @@ struct ContentView: View {
@State private var dropStatus = "empty"
@State private var rowDropStatus = "empty"
@State private var dragCanvasResult = "idle"
// scroll
@State private var scrollOffset = 0
// native AppKit controls (genuinely AX-settable, unlike SwiftUI's)
@State private var nativeSliderValue = 0.0
@State private var nativeStepperValue = 0.0
@ -90,7 +88,7 @@ struct ContentView: View {
HStack(alignment: .top, spacing: 16) {
dragCard
surfacesCard
scrollCard
ScrollCard()
}
}
@ -344,30 +342,6 @@ struct ContentView: View {
.frame(width: 320, height: 200)
}
// MARK: scroll
private var scrollCard: some View {
Card(title: "Scroll") {
StatusReadout(name: "scroll-offset", value: String(scrollOffset))
ScrollView {
VStack(alignment: .leading) {
GeometryReader { geo in
Color.clear.preference(
key: ScrollOffsetKey.self,
value: geo.frame(in: .named("scroll-space")).minY)
}
.frame(height: 0)
ForEach(1...60, id: \.self) { i in
Text("Scroll Row \(i)").accessibilityLabel("scroll-row-\(i)")
}
}
}
.coordinateSpace(name: "scroll-space")
.onPreferenceChange(ScrollOffsetKey.self) { scrollOffset = Int(-$0) }
.frame(width: 220, height: 160)
.accessibilityLabel("scroll-area")
}
}
}
@main

View file

@ -0,0 +1,33 @@
import SwiftUI
// Overflow card extracted from AgentDeskFixture.swift to keep that file under
// the 400-LOC limit. All accessibility labels are preserved byte-for-byte so
// the E2E harness (tests/e2e/run.sh) continues to resolve them unchanged.
// The build compiles every .swift file in this directory as one module.
struct ScrollCard: View {
@State private var scrollOffset = 0
var body: some View {
Card(title: "Scroll") {
StatusReadout(name: "scroll-offset", value: String(scrollOffset))
ScrollView {
VStack(alignment: .leading) {
GeometryReader { geo in
Color.clear.preference(
key: ScrollOffsetKey.self,
value: geo.frame(in: .named("scroll-space")).minY)
}
.frame(height: 0)
ForEach(1...60, id: \.self) { i in
Text("Scroll Row \(i)").accessibilityLabel("scroll-row-\(i)")
}
}
}
.coordinateSpace(name: "scroll-space")
.onPreferenceChange(ScrollOffsetKey.self) { scrollOffset = Int(-$0) }
.frame(width: 220, height: 160)
.accessibilityLabel("scroll-area")
}
}
}

View file

@ -75,10 +75,15 @@ struct DragCanvas: NSViewRepresentable {
@Binding var result: String
func makeNSView(context: Context) -> DragCanvasView {
let v = DragCanvasView()
// The closure captures `result` by reference; DragCanvasView calls it
// directly on each mouseUp, so updateNSView needs no re-sync.
v.onDrag = { result = $0 }
return v
}
func updateNSView(_ view: DragCanvasView, context: Context) {}
func updateNSView(_ view: DragCanvasView, context: Context) {
// Intentionally empty: gesture results flow *out* through the captured
// binding (via onDrag), never *in* from SwiftUI state nothing to sync.
}
}
final class DragCanvasView: NSView {