The popover/sheet split reverses — settings fold into the Git tab, the widget stacks name over branch
The titlebar widget becomes a two-line identity block: the board glyph at 22pt spanning both lines, the title over the branch (git-mode only, smaller and secondary), the em-dash retired. New Branch… returns to the switch menu behind a divider, revealing an inline name field — the pre-split shape. The board settings sheet retires whole: add-git and commit identity render inline in the Git tab's postures (BoardGitSetup.swift), the availability rule collapses into BoardGitSetupSection.resolve, and Board ▸ Board Settings… leaves the menu bar. Where 07's remote/credential setup surfaces land is deliberately left open — filed on the Redesign board. Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -7,20 +7,28 @@ import XCTest
|
||||
/// > runs in UI tests over every surface — board (trash shown and hidden), card window (Preview, Edit,
|
||||
/// > raw source), welcome, template chooser, board popover, board settings sheet.
|
||||
///
|
||||
/// The last of those is **one surface shorter than the design's sentence** since 2026-08-07: the
|
||||
/// board settings sheet retired that day (03-board-ui.md ▸ Board settings sheet, marked retired —
|
||||
/// the 2026-07-31 popover/sheet split reversed), and everything it held now renders inside the board
|
||||
/// popover's Git tab. So the popover's own audit is where those controls are looked at, and the
|
||||
/// every-surface claim is satisfied by there being one surface fewer rather than by a test skipping
|
||||
/// one.
|
||||
///
|
||||
/// One test per surface, one audit call each. `performAccessibilityAudit` audits **the app's
|
||||
/// currently displayed UI** rather than a subtree, so each test's job is entirely navigation: get the
|
||||
/// surface on screen, then let the audit look at whatever is there.
|
||||
///
|
||||
/// ### The board settings sheet is reachable since the 2026-08-07 pivot
|
||||
/// ### The settings sheet's audit, and where it went
|
||||
///
|
||||
/// The sheet was Pro-only, and this suite could not reach it: the fixture launch had no tier
|
||||
/// control, and a `--ui-test-pro` launch argument was rejected as a subscription bypass anyone could
|
||||
/// type into Terminal (`UITestLaunch` ships in the app binary on purpose). Since the pivot
|
||||
/// (12-editions.md ▸ PIVOT 2026-08-07 — git left the paywall), `BoardSettingsAvailability` asks only
|
||||
/// the board's mode, the fixture board is mode `none`, and the sheet opens for the audit like any
|
||||
/// other surface — the deferral to the manual VoiceOver pass is retired with the gate. The
|
||||
/// no-bypass objection stands as precedent for whatever the next split gates. See
|
||||
/// `testBoardSettingsSheetOpensFromTheMenuAndAudits`.
|
||||
/// The sheet was Pro-only and this suite could not reach it: the fixture launch had no tier control,
|
||||
/// and a `--ui-test-pro` launch argument was rejected as a subscription bypass anyone could type
|
||||
/// into Terminal (`UITestLaunch` ships in the app binary on purpose). The 2026-08-07 pivot
|
||||
/// (12-editions.md ▸ PIVOT 2026-08-07 — git left the paywall) made it reachable and it gained a test
|
||||
/// here; the **reversal later the same day retired the sheet outright**, and the test with it. What
|
||||
/// remains is the precedent — the no-bypass objection stands for whatever the next split gates — and
|
||||
/// one live consequence for this file: the surfaces that sheet held are now the board popover's Git
|
||||
/// tab, which `testBoardInfoPopover` opens onto its Info tab. Auditing the Git tab specifically wants
|
||||
/// a click on the popover's segmented strip and is a card of its own, filed rather than faked here.
|
||||
///
|
||||
/// ### No waiving
|
||||
///
|
||||
@@ -199,43 +207,4 @@ final class AccessibilityAuditTests: XCTestCase {
|
||||
)
|
||||
try app.performAccessibilityAudit()
|
||||
}
|
||||
|
||||
// MARK: - The board settings sheet
|
||||
|
||||
/// **The settings sheet's audit**, reachable since the 2026-08-07 pivot (this file's header):
|
||||
/// the fixture board is mode `none`, `BoardSettingsAvailability` asks only the mode, so the menu
|
||||
/// row opens the sheet — add-git's home (03-board-ui.md ▸ Board settings sheet) — and the audit
|
||||
/// looks at the sheet itself rather than deferring to the manual VoiceOver pass.
|
||||
@MainActor
|
||||
func testBoardSettingsSheetOpensFromTheMenuAndAudits() throws {
|
||||
let app = XCUIApplication.launchedWithFixtureBoard()
|
||||
|
||||
let bar = app.menuBars.firstMatch
|
||||
let boardMenu = bar.menuBarItems["Board"]
|
||||
XCTAssertTrue(
|
||||
boardMenu.waitForExistence(timeout: XCUIApplication.uiTimeout),
|
||||
"the Board menu is missing from the menu bar"
|
||||
)
|
||||
boardMenu.click()
|
||||
|
||||
let row = bar.menuItems["Board Settings…"]
|
||||
XCTAssertTrue(
|
||||
row.waitForExistence(timeout: XCUIApplication.uiTimeout),
|
||||
"Board ▸ Board Settings… is missing — the row ships in every mode that can host the sheet"
|
||||
)
|
||||
XCTAssertTrue(
|
||||
row.isEnabled,
|
||||
"a mode-none board hosts the sheet (add-git's home) — the pivot retired the tier gate that disabled this row"
|
||||
)
|
||||
row.click()
|
||||
|
||||
let sheet = app.sheets.firstMatch
|
||||
XCTAssertTrue(
|
||||
sheet.waitForExistence(timeout: XCUIApplication.uiTimeout),
|
||||
"the Board Settings sheet did not present from its menu row"
|
||||
)
|
||||
try app.performAccessibilityAudit()
|
||||
|
||||
app.typeKey(.escape, modifierFlags: [])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ Have a scratch board to hand for Part 2 — a new one from File ▸ New Board…
|
||||
|
||||
## Part 1 — run the audit suite
|
||||
|
||||
`KanbanUITests/AccessibilityAuditTests.swift` runs Xcode's accessibility audit over the surfaces the design names — nine of the ten automatically, the tenth (the **board settings sheet**) by hand in Part 3, because it is Pro-only and the fixture launch has no tier control. **Violations are test failures, not warnings**, and nothing is waived: the audits pass no issue handler at all.
|
||||
`KanbanUITests/AccessibilityAuditTests.swift` runs Xcode's accessibility audit over the surfaces the design names — all of them automatically since 2026-08-07, when the **board settings sheet** retired and its controls rehomed into the board popover's Git tab (03-board-ui.md ▸ Board settings sheet, marked retired). The by-hand pass below is now about that tab, not about a surface the suite cannot reach. **Violations are test failures, not warnings**, and nothing is waived: the audits pass no issue handler at all.
|
||||
|
||||
```
|
||||
xcodebuild test -project Kanban.xcodeproj -scheme Kanban \
|
||||
@@ -38,7 +38,7 @@ xcodebuild test -project Kanban.xcodeproj -scheme Kanban \
|
||||
-only-testing:KanbanUITests/AccessibilityAuditTests
|
||||
```
|
||||
|
||||
The nine surfaces, and how each test gets there:
|
||||
The surfaces, and how each test gets there:
|
||||
|
||||
| Test | Surface | Navigation |
|
||||
| --- | --- | --- |
|
||||
@@ -51,22 +51,21 @@ The nine surfaces, and how each test gets there:
|
||||
| `testWelcomeWindow` | Welcome, with a recents row | Window ▸ Welcome to Lanework |
|
||||
| `testTemplateChooser` | Template chooser | File ▸ New Board… |
|
||||
| `testBoardInfoPopover` | Board popover | File ▸ Board Info |
|
||||
| `testBoardSettingsRowIsPresentAndDisabledOnTheFreeFixture` | Board window, with Board ▸ Board Settings… checked | Opens the Board menu, asserts the row is present and disabled, closes it |
|
||||
|
||||
Every test launches the app with `--ui-test-fixture-board`, which makes the app build a known board inside its own container and open it — three lanes ("To Do", "Doing", "Done"), six cards, one card with a rich Markdown body, an attachment and a three-comment thread (one unattributed, one edited), one card already in the trash. That is the `standard` fixture variant; the bare flag means it, and the other two shapes (`large`, `malformed`) belong to the end-to-end pass. The board and the registry both live in a scratch directory that is wiped on every launch, so an audit run never touches your real boards or your recents list. See `Kanban/App/UITestLaunch.swift` for why the board cannot simply be handed to the app on the command line (the sandbox).
|
||||
|
||||
If a test fails, read the issue's `compactDescription` and fix the app. Adding a waiver is a design change and needs an entry on the Redesign board first.
|
||||
|
||||
### The board settings sheet, by hand
|
||||
### The popover's Git tab, by hand
|
||||
|
||||
The sheet (03-board-ui.md ▸ Board settings sheet) needs **Pro on a board with app-managed git**, and there is deliberately no launch argument that grants Pro: `UITestLaunch` is compiled into the shipping binary, so a tier flag would be a subscription bypass anyone could type into Terminal. Until a fixture can reach Pro honestly, run this by hand once per release on a Pro build, with a git-mode board open:
|
||||
The automated audit opens the popover on its **Info** tab, and switching tabs is a click the suite doesn't make yet — so the git surface's own keyboard and VoiceOver behaviour is a by-hand pass, once per release, with a git-mode board open. (This section was the **board settings sheet's** until 2026-08-07; the sheet retired and its controls came here, so the checks moved with them rather than being dropped.)
|
||||
|
||||
- [ ] **Open both doors.** Board ▸ Board Settings…, and the popover's **Board Settings…** row (File ▸ Board Info ▸ Git). The popover dismisses as the sheet appears — never both at once.
|
||||
- [ ] **Sectioned, and navigable by heading.** With VoiceOver on, the rotor's heading list holds "Board Settings" and each section's title ("Branch", "Commit Identity"; "Git" on a board with no repository yet).
|
||||
- [ ] **Tab reaches every control** with VoiceOver off and Full Keyboard Access on — the branch name field, Create, both identity fields, Done.
|
||||
- [ ] **One door.** File ▸ Board Info (⌘I) ▸ **Git**. There is no second configuration surface and no Board ▸ Board Settings… row — both retired with the sheet.
|
||||
- [ ] **Navigable by heading.** With VoiceOver on, the rotor's heading list holds "Commit Identity" on a git-mode board.
|
||||
- [ ] **Tab reaches every control** with VoiceOver off and Full Keyboard Access on — the branch menu, the New Branch… field and Create when revealed, both identity fields.
|
||||
- [ ] **⌘Z inside a field is the field's**, not the board's: type into Commit Identity ▸ Name, press ⌘Z, and the *typing* reverts — no tree checkout, no board step consumed (06-history-undo.md ▸ Undo routing).
|
||||
- [ ] **Escape and Done both dismiss**; Escape in a dirty branch-name field clears the field first (one layer per press).
|
||||
- [ ] **The read-only lock disables in place**: the sheet stays open and its controls grey out, with the banner naming why.
|
||||
- [ ] **Escape steps outward one layer per press**: in a dirty New Branch… field it clears the field; in an empty one it closes the reveal; again, it dismisses the popover.
|
||||
- [ ] **The read-only lock disables in place**: the popover stays open and its controls grey out, with the banner naming why.
|
||||
|
||||
## Part 2 — the VoiceOver smoke script
|
||||
|
||||
|
||||
Reference in New Issue
Block a user