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
60 lines
3.0 KiB
Swift
60 lines
3.0 KiB
Swift
import XCTest
|
|
|
|
/// 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 {
|
|
|
|
@MainActor
|
|
func testSettingsAboutSection() throws {
|
|
let (app, _) = XCUIApplication.launchedWithFixtureBoard()
|
|
|
|
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
|
|
// fit on screen.
|
|
app.swipeUp()
|
|
|
|
// `IndieAbout`'s version line is three sibling `Text` views (prefix, the tappable
|
|
// "1.0-<build>" link, suffix) — none of them wrapped in a control that would flatten them
|
|
// into one accessibility element, so the link is addressable on its own by the substring
|
|
// only it carries. `MARKETING_VERSION` for KanbanMobile is "1.0" (project.yml).
|
|
let versionLink = app.staticTexts.matching(NSPredicate(format: "label CONTAINS %@", "1.0")).firstMatch
|
|
XCTAssertTrue(
|
|
versionLink.waitForExistence(timeout: XCUIApplication.uiTimeout),
|
|
"no version label containing \"1.0\" appeared in Settings"
|
|
)
|
|
|
|
let licenseLink = app.staticTexts["License"]
|
|
XCTAssertTrue(licenseLink.waitForExistence(timeout: XCUIApplication.uiTimeout), "the License link never appeared")
|
|
|
|
let copyright = app.element(labelContaining: "2026 rzen")
|
|
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 `SettingsScreen`).
|
|
app.scrollUntilHittable(versionLink)
|
|
versionLink.tap()
|
|
let changelogText = app.element(labelContaining: "August 2026")
|
|
XCTAssertTrue(
|
|
changelogText.waitForExistence(timeout: XCUIApplication.uiTimeout),
|
|
"the changelog sheet never showed \"August 2026\" (KanbanMobile/CHANGELOG.md)"
|
|
)
|
|
// 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)
|
|
licenseLink.tap()
|
|
let licenseText = app.element(labelContaining: "ISC License")
|
|
XCTAssertTrue(
|
|
licenseText.waitForExistence(timeout: XCUIApplication.uiTimeout),
|
|
"the license sheet never showed \"ISC License\" (LICENSE.md)"
|
|
)
|
|
// Same scoping reason as the changelog Done tap above.
|
|
app.navigationBars["License"].buttons["Done"].tap()
|
|
}
|
|
}
|