test(print): scroll stage-2 via synthesized scroll wheel (#215) #216

Merged
gronod merged 1 commits from feat/215-stage2-scroll-wheel into develop 2026-09-18 10:59:33 +01:00
+18 -29
View File
@@ -114,18 +114,18 @@ final class Milestone3UITests: XCTestCase {
return recordedSpoolLog() return recordedSpoolLog()
} }
/// Drags `#galleryPage-0`'s TIFF upward so `identifier`'s button /// Scrolls `stage-2` with the synthesized scroll wheel so
/// moves up, clear of the Dock collision zone at the window's /// `identifier`'s button moves up, clear of the Dock collision
/// bottom edge (#132). /// zone at the window's bottom edge (#132).
/// ///
/// macOS overlay scrollbars are not in the AX tree — never use /// macOS overlay scrollbars are not in the AX tree — never use
/// `app.scrollBars` — and a synthesized scroll wheel is inert on /// `app.scrollBars` — and a click-drag does not scroll a macOS
/// this LazyVGrid, so the scroll is a real drag on the gallery /// ScrollView (content-drag scrolling is iOS-only); the scroll
/// cell's content. A stale/off-screen AX frame resolves to a screen /// wheel is the mechanism the platform supports (#215). A
/// point that can be a Dock icon — a coordinate click there once /// stale/off-screen AX frame resolves to a screen point that can
/// opened Calendar instead of Print. Callers must click only when /// be a Dock icon — a coordinate click there once opened Calendar
/// the returned element `isHittable`; never coordinate-click a /// instead of Print. Callers must click only when the returned
/// stale frame. /// element `isHittable`; never coordinate-click a stale frame.
@discardableResult @discardableResult
private func scrollStage2UntilHittable( private func scrollStage2UntilHittable(
_ identifier: String, _ identifier: String,
@@ -134,6 +134,8 @@ final class Milestone3UITests: XCTestCase {
var button = app.buttons[identifier] var button = app.buttons[identifier]
let cell = app.descendants(matching: .any)["galleryPage-0"].firstMatch let cell = app.descendants(matching: .any)["galleryPage-0"].firstMatch
XCTAssertTrue(cell.waitForExistence(timeout: 10), "galleryPage-0") XCTAssertTrue(cell.waitForExistence(timeout: 10), "galleryPage-0")
let scrollView = app.scrollViews["stage-2"]
XCTAssertTrue(scrollView.waitForExistence(timeout: 10), "stage-2")
let deadline = Date().addingTimeInterval(timeout) let deadline = Date().addingTimeInterval(timeout)
while Date() < deadline { while Date() < deadline {
@@ -142,25 +144,12 @@ final class Milestone3UITests: XCTestCase {
button.frame.maxY < windowBottom - 80 { button.frame.maxY < windowBottom - 80 {
return button return button
} }
// Grab the upper half of the cell (the TIFF, not the Print // Wheel-down inside the stage-2 viewport: content moves
// button / Dock) and drag toward the top of the window. // UP ⇒ Print leaves the Dock zone. Negative deltaY scrolls
// Mouse moves UP ⇒ gallery content moves UP ⇒ Print leaves // toward the document bottom (#215).
// the Dock zone. scrollView.coordinate(withNormalizedOffset:
if cell.isHittable { CGVector(dx: 0.5, dy: 0.5))
let start = cell.coordinate(withNormalizedOffset: .scroll(byDeltaX: 0, deltaY: -60)
CGVector(dx: 0.5, dy: 0.25))
let end = start.withOffset(CGVector(dx: 0, dy: -280))
start.press(forDuration: 0.15, thenDragTo: end)
} else {
// Cell not hit-testable: drag the stage-2 content
// directly — still content, still never scrollBars.
let scrollView = app.scrollViews["stage-2"]
scrollView.coordinate(withNormalizedOffset:
CGVector(dx: 0.5, dy: 0.55))
.press(forDuration: 0.15, thenDragTo:
scrollView.coordinate(withNormalizedOffset:
CGVector(dx: 0.5, dy: 0.15)))
}
RunLoop.current.run(until: Date().addingTimeInterval(0.4)) RunLoop.current.run(until: Date().addingTimeInterval(0.4))
button = app.buttons[identifier] button = app.buttons[identifier]
} }