Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions TablePro/Views/Main/EditorTabInteractionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,18 @@ internal final class EditorTabInteractionView: NSView {
return self
}

/// Answers from the SwiftUI tree, which is where the tabs publish themselves. The pointer's
/// claim is lifted for the length of the question.
/// Answers from the SwiftUI tree, which is where the tabs publish themselves.
///
/// The subviews are asked directly rather than through `super`, which will not walk into them
/// from a receiver that is not itself an accessibility element: lifting the pointer's claim and
/// deferring to `super` left every tab unreachable exactly as before. The point arrives in
/// screen coordinates and is passed on unchanged, because that is what the children expect too.
override internal func accessibilityHitTest(_ point: NSPoint) -> Any? {
isResolvingAccessibilityHit = true
defer { isResolvingAccessibilityHit = false }
for subview in subviews.reversed() {
if let hit = subview.accessibilityHitTest(point) { return hit }
}
return super.accessibilityHitTest(point)
}

Expand Down
26 changes: 21 additions & 5 deletions TableProUITests/EditorTabDetachUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@ final class EditorTabDetachUITests: UITestCase {
waitForPredicate(timeout: 20) { app.windows.count >= 2 },
"Move Tab to New Window must open a second window"
)
/// Asked of every window rather than of `window`, which is a query and re-resolves: once
/// the move opens a second window, `app.windows.firstMatch` can be that one, and the
/// assertion then reads the tab it was looking for in the window it was moved into.
XCTAssertTrue(
waitForPredicate(timeout: 20) { !self.tabLabels(in: window).contains(moved) },
"The tab must leave the window it was moved out of, still shows \(tabLabels(in: window))"
waitForPredicate(timeout: 20) { self.someWindow(in: app, holds: before.filter { $0 != moved }) },
"A window must hold the tabs that stayed behind, windows show \(self.tabsPerWindow(in: app))"
)
XCTAssertTrue(
waitForPredicate(timeout: 20) {
Expand All @@ -49,7 +52,8 @@ final class EditorTabDetachUITests: UITestCase {
openTables(Self.tables, in: window)
XCTAssertTrue(waitForPredicate(timeout: 25) { self.tabLabels(in: window).count >= 3 })

let moved = try XCTUnwrap(tabLabels(in: window).last)
let before = tabLabels(in: window)
let moved = try XCTUnwrap(before.last)
detach(tabNamed: moved, in: window, of: app)
XCTAssertTrue(waitForPredicate(timeout: 20) { app.windows.count >= 2 })

Expand All @@ -63,9 +67,12 @@ final class EditorTabDetachUITests: UITestCase {
waitForPredicate(timeout: 20) { app.windows.count == 1 },
"Closing the detached window must close it rather than empty it"
)
/// Compared against what the strip held before the move rather than against a number: the
/// sample database opens a tab of its own, so the total is not the count of tables opened
/// here.
XCTAssertTrue(
waitForPredicate(timeout: 20) { self.tabLabels(in: window).count == 2 },
"The original window keeps its remaining tabs, shows \(tabLabels(in: window))"
waitForPredicate(timeout: 20) { self.someWindow(in: app, holds: before.filter { $0 != moved }) },
"The remaining window keeps the other tabs, windows show \(self.tabsPerWindow(in: app)) of \(before)"
)
}

Expand Down Expand Up @@ -124,6 +131,15 @@ final class EditorTabDetachUITests: UITestCase {
.map { $0.label }
}

/// Whether any window's strip holds exactly these tabs, in this order.
private func someWindow(in app: XCUIApplication, holds tabs: [String]) -> Bool {
app.windows.allElementsBoundByIndex.contains { tabLabels(in: $0) == tabs }
}

private func tabsPerWindow(in app: XCUIApplication) -> [[String]] {
app.windows.allElementsBoundByIndex.map { tabLabels(in: $0) }
}

private func windowTitles(in app: XCUIApplication) -> [String] {
app.windows.allElementsBoundByIndex.map { $0.title }
}
Expand Down
Loading