Files
OpenAppLock/OpenAppLockUITests/AppListUITests.swift
Brendan Chen cb9b2e8950 refactor: two-screen app-list editor with native List layout
Screen 1 is a plain List (name field, the apps the list contains via
FamilyControls token Labels, and an Edit Apps button); screen 2 pushes
Apple's FamilyActivityPicker whose Save applies the selection back.
Documents that the picker silently drops selections without real
FamilyControls authorization (mocked in -ui-testing launches).
2026-06-12 20:15:12 -04:00

115 lines
4.5 KiB
Swift

//
// AppListUITests.swift
// OpenAppLockUITests
//
import XCTest
/// App lists: the editor's App List row, the picker (select / create / edit),
/// rule-level Block vs Allow Only, and the Hard Mode list lockdown.
final class AppListUITests: XCTestCase {
override func setUpWithError() throws {
continueAfterFailure = false
}
func testScheduleEditorOffersModeChoice() throws {
let app = XCUIApplication.launchOpenAppLock()
app.buttons["newRuleButton"].waitToAppear().tap()
app.buttons["ruleKind-schedule"].waitToAppear().tap()
app.staticTexts["ruleEditorTitle"].waitToAppear()
app.swipeUp()
app.element("selectionModePicker").waitToAppear()
XCTAssertTrue(app.staticTexts["Apps are blocked"].exists)
}
func testLimitEditorsAreBlockOnly() throws {
let app = XCUIApplication.launchOpenAppLock()
app.buttons["newRuleButton"].waitToAppear().tap()
app.buttons["ruleKind-timeLimit"].waitToAppear().tap()
app.element("selectedAppsRow").waitToAppear()
XCTAssertFalse(
app.element("selectionModePicker").exists,
"Time-limit rules are always Block; the mode picker must not appear"
)
// Back to the rule-type list, then check the open-limit editor too.
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-openLimit"].waitToAppear().tap()
app.element("selectedAppsRow").waitToAppear()
XCTAssertFalse(app.element("selectionModePicker").exists)
}
func testCreateAppListFlowSelectsNewList() throws {
let app = XCUIApplication.launchOpenAppLock()
app.buttons["newRuleButton"].waitToAppear().tap()
app.buttons["ruleKind-timeLimit"].waitToAppear().tap()
app.element("selectedAppsRow").waitToAppear().tap()
// Fresh install: no lists yet, so the picker offers creation.
app.element("emptyAppListsLabel").waitToAppear()
app.buttons["newAppListButton"].tap()
let nameField = app.textFields["appListNameField"].waitToAppear()
nameField.tap()
nameField.typeText("Focus Apps\n")
// Screen 1 lists the (empty) selection; Edit Apps pushes the Screen
// Time picker, whose Save returns here.
app.element("emptySelectionLabel").waitToAppear()
app.buttons["editAppsButton"].tap()
app.element("selectionCountLabel").waitToAppear()
app.buttons["confirmSelectionButton"].tap()
app.buttons["saveAppListButton"].waitToAppear().tap()
// Saving pops back to the picker with the new list selected.
app.element("appListRow-Focus Apps").waitToAppear()
app.buttons["closeAppListPickerButton"].tap()
// The editor row now reports the chosen list.
let row = app.element("selectedAppsRow").waitToAppear()
XCTAssertTrue(row.label.contains("Focus Apps"), "Got: \(row.label)")
}
func testDetailShowsAppListName() throws {
let app = XCUIApplication.launchOpenAppLock(seedScenario: "standard")
app.buttons["ruleCard-Work Time"].waitToAppear().tap()
let row = app.element("detailRow-Block").waitToAppear()
XCTAssertTrue(row.label.contains("Distractions"), "Got: \(row.label)")
}
func testHardModeSessionLocksAppListEditing() throws {
let app = XCUIApplication.launchOpenAppLock(seedScenario: "hard-mode-active")
// "Sleep" is soft and editable even while "Locked In" hard-blocks.
app.buttons["ruleCard-Sleep"].waitToAppear().tap()
app.buttons["editRuleButton"].waitToAppear().tap()
app.element("selectedAppsRow").waitToAppear().tap()
app.element("appListRow-Distractions").waitToAppear()
app.element("appListsLockedNotice").waitToAppear()
XCTAssertFalse(
app.buttons["editAppListButton-Distractions"].exists,
"App lists must be read-only while a Hard Mode rule is blocking"
)
}
func testAppListsEditableWithoutHardSession() throws {
let app = XCUIApplication.launchOpenAppLock(seedScenario: "standard")
app.buttons["ruleCard-Sleep"].waitToAppear().tap()
app.buttons["editRuleButton"].waitToAppear().tap()
app.element("selectedAppsRow").waitToAppear().tap()
app.buttons["editAppListButton-Distractions"].waitToAppear()
XCTAssertFalse(app.element("appListsLockedNotice").exists)
}
}