The tab bar retires — boards are the app, settings behind the gear, recency the default order
The boards stack becomes the root screen: Settings moves from its own tab to a sheet behind a leading gearshape button, the sort pickers trade their text segments for symbols (hand.draw, textformat.abc, clock) with the words kept for accessibility, and every list now opens sorted by most recent change. UI tests re-aimed at the gear button and Done-button scoping fixed for the sheet-over-sheet nav bars — 4/4 green in the simulator. Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -8,9 +8,9 @@ final class BoardsNavigationUITests: XCTestCase {
|
||||
func testBoardsNavigationAndTitleEdit() throws {
|
||||
let (app, root) = XCUIApplication.launchedWithFixtureBoard()
|
||||
|
||||
// Boards is the first tab (`RootTabView`), so no tab switch is needed here. The row's
|
||||
// label is the flattened `BoardSummaryRow` — title plus the "N lanes · N cards · modified"
|
||||
// subtitle `BoardIndexStore`'s first scan fills in.
|
||||
// Boards is the app's root screen (`BoardsTabView`), so no navigation is needed to reach
|
||||
// it. The row's label is the flattened `BoardSummaryRow` — title plus the "N lanes · N
|
||||
// cards · modified" subtitle `BoardIndexStore`'s first scan fills in.
|
||||
let boardRow = app.element(labelContaining: RichBoard.title)
|
||||
XCTAssertTrue(
|
||||
boardRow.waitForExistence(timeout: XCUIApplication.uiTimeout),
|
||||
|
||||
@@ -156,9 +156,10 @@ extension XCUIApplication {
|
||||
|
||||
/// Swipes a board row open and taps its Settings action.
|
||||
///
|
||||
/// The label is scoped to the list because the tab bar carries a "Settings" button of its own —
|
||||
/// same word, entirely different destination — and an unscoped `buttons["Settings"]` is a coin
|
||||
/// flip between them.
|
||||
/// The label is scoped to the list because the boards screen's own nav bar carries a
|
||||
/// "Settings" button of its own — the leading gear button that presents `SettingsScreen` as a
|
||||
/// sheet, same word, entirely different destination — and an unscoped `buttons["Settings"]` is
|
||||
/// a coin flip between them.
|
||||
@MainActor
|
||||
func openBoardSettings(for title: String) {
|
||||
let row = boardRow(title)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import XCTest
|
||||
|
||||
/// The Settings tab's last section — `SettingsTabView`'s `IndieAbout` block: version/build (which
|
||||
/// Settings' only section — `SettingsScreen`'s `IndieAbout` block: version/build (which
|
||||
/// doubles as the changelog link), the License document link, and the copyright line.
|
||||
final class SettingsAboutUITests: XCTestCase {
|
||||
|
||||
@@ -8,7 +8,7 @@ final class SettingsAboutUITests: XCTestCase {
|
||||
func testSettingsAboutSection() throws {
|
||||
let (app, _) = XCUIApplication.launchedWithFixtureBoard()
|
||||
|
||||
app.tabBars.buttons["Settings"].tap()
|
||||
app.navigationBars.buttons["Settings"].tap()
|
||||
|
||||
// The About section is the only section in the form — a speculative swipe settles the
|
||||
// list near the bottom before anything here is queried, harmless if the content already
|
||||
@@ -32,7 +32,7 @@ final class SettingsAboutUITests: XCTestCase {
|
||||
XCTAssertTrue(copyright.waitForExistence(timeout: XCUIApplication.uiTimeout), "the copyright text never appeared")
|
||||
|
||||
// Tap the version link — opens the changelog (`IndieAbout.versionLineView`'s
|
||||
// `.onTapGesture`, wired to `changelogDocument: .changelog()` in `SettingsTabView`).
|
||||
// `.onTapGesture`, wired to `changelogDocument: .changelog()` in `SettingsScreen`).
|
||||
app.scrollUntilHittable(versionLink)
|
||||
versionLink.tap()
|
||||
let changelogText = app.element(labelContaining: "August 2026")
|
||||
@@ -40,7 +40,10 @@ final class SettingsAboutUITests: XCTestCase {
|
||||
changelogText.waitForExistence(timeout: XCUIApplication.uiTimeout),
|
||||
"the changelog sheet never showed \"August 2026\" (KanbanMobile/CHANGELOG.md)"
|
||||
)
|
||||
app.navigationBars.buttons["Done"].tap()
|
||||
// Scoped to the "Changelog" nav bar specifically — `SettingsScreen` is itself a sheet with
|
||||
// its own "Done" button, and that nav bar stays in the accessibility tree underneath this
|
||||
// one, so an unscoped `app.navigationBars.buttons["Done"]` would match both.
|
||||
app.navigationBars["Changelog"].buttons["Done"].tap()
|
||||
|
||||
// Tap License — opens the bundled ISC license.
|
||||
app.scrollUntilHittable(licenseLink)
|
||||
@@ -50,6 +53,7 @@ final class SettingsAboutUITests: XCTestCase {
|
||||
licenseText.waitForExistence(timeout: XCUIApplication.uiTimeout),
|
||||
"the license sheet never showed \"ISC License\" (LICENSE.md)"
|
||||
)
|
||||
app.navigationBars.buttons["Done"].tap()
|
||||
// Same scoping reason as the changelog Done tap above.
|
||||
app.navigationBars["License"].buttons["Done"].tap()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user