Replace the Opal-style custom presentation with the bare iOS design language, keeping the backend, flows, and accessibility identifiers: - Home: NavigationStack + List; rules now presented as list rows with kind icon, block summary, and trailing live status; '+' in the toolbar - New Rule: plain list of rule types and presets; editor still pushed via navigationDestination - Editor: native Form (DatePicker rows, day circles with summary in the section header, toggle rows with footers, stepper rows); create commits with a prominent 'Add Rule' button replacing Hold to Commit; edit uses toolbar Done plus red Disable/Delete rows - Detail: sheet with inline title + status caption, LabeledContent rows; Edit Rule pushes the editor natively - Default color scheme: drop forced dark mode and custom tint; system appearance and accent throughout - Delete Theme, HoldToCommitButton, RuleCardView and custom chrome - Use concrete Color.primary/secondary in button row labels (the hierarchical styles resolve against the button tint) - Tests: 93 passing; only delta is holdToCommitButton press → commitRuleButton tap in 5 call sites - Spec: add §6 mapping the original presentation to the native one
135 lines
5.5 KiB
Swift
135 lines
5.5 KiB
Swift
//
|
|
// RuleCreationUITests.swift
|
|
// SeveredUITests
|
|
//
|
|
|
|
import XCTest
|
|
|
|
final class RuleCreationUITests: XCTestCase {
|
|
override func setUpWithError() throws {
|
|
continueAfterFailure = false
|
|
}
|
|
|
|
func testCreateScheduleRuleFromTypeCard() throws {
|
|
let app = XCUIApplication.launchSevered()
|
|
app.element("emptyRulesCard").waitToAppear()
|
|
|
|
app.buttons["newRuleButton"].tap()
|
|
app.staticTexts["New Rule"].waitToAppear()
|
|
app.buttons["ruleKind-schedule"].waitToAppear().tap()
|
|
|
|
// Editor opens with the schedule defaults.
|
|
XCTAssertEqual(app.staticTexts["ruleEditorTitle"].waitToAppear().label, "In the Zone")
|
|
XCTAssertTrue(app.staticTexts["During this time"].exists)
|
|
|
|
// Hold to commit saves the rule and returns home.
|
|
app.buttons["commitRuleButton"].waitToAppear().tap()
|
|
app.buttons["ruleCard-In the Zone"].waitToAppear()
|
|
XCTAssertFalse(app.element("emptyRulesCard").exists)
|
|
}
|
|
|
|
func testCreateRuleFromPreset() throws {
|
|
let app = XCUIApplication.launchSevered()
|
|
app.buttons["newRuleButton"].waitToAppear().tap()
|
|
|
|
app.buttons["preset-work-time"].waitToAppear().tap()
|
|
XCTAssertEqual(app.staticTexts["ruleEditorTitle"].waitToAppear().label, "Work Time")
|
|
|
|
app.buttons["commitRuleButton"].waitToAppear().tap()
|
|
app.buttons["ruleCard-Work Time"].waitToAppear()
|
|
}
|
|
|
|
func testRenameRuleInEditor() throws {
|
|
let app = XCUIApplication.launchSevered()
|
|
app.buttons["newRuleButton"].waitToAppear().tap()
|
|
app.buttons["ruleKind-schedule"].waitToAppear().tap()
|
|
|
|
app.buttons["renameButton"].waitToAppear().tap()
|
|
let nameField = app.textFields.firstMatch.waitToAppear()
|
|
nameField.tap()
|
|
// Clear the prefilled name, then type the new one.
|
|
let deletions = String(repeating: XCUIKeyboardKey.delete.rawValue, count: 24)
|
|
nameField.typeText(deletions + "My Focus")
|
|
app.buttons["OK"].tap()
|
|
|
|
XCTAssertEqual(app.staticTexts["ruleEditorTitle"].label, "My Focus")
|
|
app.buttons["commitRuleButton"].waitToAppear().tap()
|
|
app.buttons["ruleCard-My Focus"].waitToAppear()
|
|
}
|
|
|
|
func testDayTogglesUpdateSummary() throws {
|
|
let app = XCUIApplication.launchSevered()
|
|
app.buttons["newRuleButton"].waitToAppear().tap()
|
|
app.buttons["ruleKind-schedule"].waitToAppear().tap()
|
|
|
|
// Default is Weekdays; enabling Saturday and Sunday makes it Every day.
|
|
XCTAssertTrue(app.staticTexts["Weekdays"].waitToAppear().exists)
|
|
app.buttons["dayToggle-1"].tap()
|
|
app.buttons["dayToggle-7"].tap()
|
|
XCTAssertTrue(app.staticTexts["Every day"].waitToAppear().exists)
|
|
}
|
|
|
|
func testCreateTimeLimitRule() throws {
|
|
let app = XCUIApplication.launchSevered()
|
|
app.buttons["newRuleButton"].waitToAppear().tap()
|
|
app.buttons["ruleKind-timeLimit"].waitToAppear().tap()
|
|
|
|
XCTAssertEqual(app.staticTexts["ruleEditorTitle"].waitToAppear().label, "Time Keeper")
|
|
XCTAssertTrue(app.staticTexts["When I use"].exists)
|
|
XCTAssertEqual(app.staticTexts["dailyLimitStepperValue"].label, "45m")
|
|
|
|
app.steppers["dailyLimitStepper"].buttons["Increment"].tap()
|
|
XCTAssertEqual(app.staticTexts["dailyLimitStepperValue"].label, "60m")
|
|
|
|
app.buttons["commitRuleButton"].waitToAppear().tap()
|
|
app.buttons["ruleCard-Time Keeper"].waitToAppear()
|
|
}
|
|
|
|
func testAdultContentToggleFlowsToDetail() throws {
|
|
let app = XCUIApplication.launchSevered()
|
|
app.buttons["newRuleButton"].waitToAppear().tap()
|
|
app.buttons["ruleKind-schedule"].waitToAppear().tap()
|
|
|
|
app.switches["adultContentToggle"].waitToAppear().tap()
|
|
app.buttons["commitRuleButton"].waitToAppear().tap()
|
|
|
|
app.buttons["ruleCard-In the Zone"].waitToAppear().tap()
|
|
let row = app.element("detailRow-Adult websites").waitToAppear()
|
|
XCTAssertTrue(row.label.contains("Blocked"), "Got: \(row.label)")
|
|
}
|
|
|
|
func testAdultContentDefaultsToAllowed() throws {
|
|
let app = XCUIApplication.launchSevered(seedScenario: "standard")
|
|
app.buttons["ruleCard-Work Time"].waitToAppear().tap()
|
|
let row = app.element("detailRow-Adult websites").waitToAppear()
|
|
XCTAssertTrue(row.label.contains("Allowed"), "Got: \(row.label)")
|
|
}
|
|
|
|
func testEditorSupportsNativeSwipeBack() throws {
|
|
let app = XCUIApplication.launchSevered()
|
|
app.buttons["newRuleButton"].waitToAppear().tap()
|
|
app.buttons["ruleKind-schedule"].waitToAppear().tap()
|
|
app.staticTexts["ruleEditorTitle"].waitToAppear()
|
|
|
|
// Native push navigation supports the edge-swipe back gesture.
|
|
let edge = app.coordinate(withNormalizedOffset: CGVector(dx: 0.02, dy: 0.5))
|
|
let middle = app.coordinate(withNormalizedOffset: CGVector(dx: 0.9, dy: 0.5))
|
|
edge.press(forDuration: 0.05, thenDragTo: middle)
|
|
|
|
app.buttons["ruleKind-schedule"].waitToAppear()
|
|
XCTAssertTrue(app.staticTexts["New Rule"].exists)
|
|
}
|
|
|
|
func testNewRuleSheetShowsTypesAndPresets() throws {
|
|
let app = XCUIApplication.launchSevered()
|
|
app.buttons["newRuleButton"].waitToAppear().tap()
|
|
|
|
app.buttons["ruleKind-schedule"].waitToAppear()
|
|
XCTAssertTrue(app.buttons["ruleKind-timeLimit"].exists)
|
|
XCTAssertTrue(app.buttons["ruleKind-openLimit"].exists)
|
|
XCTAssertTrue(app.staticTexts["Get More Done"].exists)
|
|
XCTAssertTrue(app.buttons["preset-work-time"].exists)
|
|
XCTAssertTrue(app.buttons["preset-laser-focus"].exists)
|
|
}
|
|
}
|