Add UI test covering layout + core flows

Verifies:
- Title lives in the top 25% of the screen (guards against letterboxing regressions)
- Plus button opens Add Connection sheet; Cancel dismisses
- Settings gear opens Settings sheet; Done dismisses
- Search field accepts input and keeps the top chrome visible
- Empty-state CTA routes to Add Connection

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey T
2026-04-16 21:59:30 -05:00
parent 876d08cbf3
commit 497b8a42be
2 changed files with 77 additions and 0 deletions

View File

@@ -43,3 +43,17 @@ targets:
product: VNCCore
- package: VNCUI
product: VNCUI
ScreensUITests:
type: bundle.ui-testing
platform: iOS
deploymentTarget: "18.0"
sources:
- path: ScreensUITests
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.tt.screens.uitests
TEST_TARGET_NAME: Screens
GENERATE_INFOPLIST_FILE: YES
dependencies:
- target: Screens

View File

@@ -0,0 +1,63 @@
import XCTest
final class ScreensUITests: XCTestCase {
override func setUp() {
continueAfterFailure = false
}
@MainActor
func testLayoutFillsScreenAndCoreFlows() {
let app = XCUIApplication()
app.launch()
// ---- Top chrome is present and flush with the safe area top.
let title = app.staticTexts["Screens"]
XCTAssertTrue(title.waitForExistence(timeout: 5), "Title should appear")
let screenFrame = app.windows.firstMatch.frame
let titleY = title.frame.midY
XCTAssertLessThan(titleY, screenFrame.height * 0.25,
"Title should sit in the top 25% of the screen; actual Y \(titleY) in screen \(screenFrame.height)")
// ---- Tap + to open Add Connection sheet.
let addButton = app.buttons["Add connection"]
XCTAssertTrue(addButton.exists, "Add button should exist")
addButton.tap()
let displayNameField = app.textFields["Display name"]
XCTAssertTrue(displayNameField.waitForExistence(timeout: 2),
"Add Connection sheet should present and show Display name field")
app.buttons["Cancel"].tap()
XCTAssertFalse(displayNameField.waitForExistence(timeout: 1),
"Add sheet should dismiss on Cancel")
// ---- Settings gear opens Settings sheet.
app.buttons["Settings"].tap()
let settingsTitle = app.navigationBars.staticTexts["Settings"]
XCTAssertTrue(settingsTitle.waitForExistence(timeout: 2),
"Settings sheet should present")
app.buttons["Done"].tap()
// ---- Search field accepts input and clears.
let search = app.textFields.matching(NSPredicate(format: "placeholderValue == %@", "Search connections")).firstMatch
XCTAssertTrue(search.waitForExistence(timeout: 2), "Search field should exist")
search.tap()
search.typeText("mini")
XCTAssertEqual(search.value as? String, "mini",
"Search text should round-trip")
// Title should still be visible (top chrome does not scroll off)
XCTAssertTrue(title.isHittable, "Title should remain on screen during search")
// ---- Empty-state CTA routes to Add Connection.
let emptyCTA = app.buttons["Add a computer"]
if emptyCTA.waitForExistence(timeout: 1) {
// clear search first
app.buttons["Clear search"].tap()
emptyCTA.tap()
XCTAssertTrue(displayNameField.waitForExistence(timeout: 2),
"Empty-state CTA should present Add Connection sheet")
app.buttons["Cancel"].tap()
}
}
}