From e428eb2367ce64e012baf2fefa5d62efc765ffc0 Mon Sep 17 00:00:00 2001 From: Lahfir Date: Wed, 10 Jun 2026 20:23:49 -0700 Subject: [PATCH] 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. --- tests/fixture-app/AgentDeskFixture.swift | 28 +------------------ tests/fixture-app/FixtureCards.swift | 33 +++++++++++++++++++++++ tests/fixture-app/FixtureComponents.swift | 7 ++++- 3 files changed, 40 insertions(+), 28 deletions(-) create mode 100644 tests/fixture-app/FixtureCards.swift diff --git a/tests/fixture-app/AgentDeskFixture.swift b/tests/fixture-app/AgentDeskFixture.swift index 1a5f9d4..11693f6 100644 --- a/tests/fixture-app/AgentDeskFixture.swift +++ b/tests/fixture-app/AgentDeskFixture.swift @@ -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 diff --git a/tests/fixture-app/FixtureCards.swift b/tests/fixture-app/FixtureCards.swift new file mode 100644 index 0000000..76d9fb2 --- /dev/null +++ b/tests/fixture-app/FixtureCards.swift @@ -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") + } + } +} diff --git a/tests/fixture-app/FixtureComponents.swift b/tests/fixture-app/FixtureComponents.swift index 7133c6a..4089745 100644 --- a/tests/fixture-app/FixtureComponents.swift +++ b/tests/fixture-app/FixtureComponents.swift @@ -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 {