Reduce fixture UI test time in CI (#8244)

* Reduce fixture UI test time in CI

* Check fixture UI conditions before waits

* Reuse the app across carousel close checks

* Run fixture UI tests on release branches
This commit is contained in:
Facundo Menzella authored and GitHub committed 2026-11-09 16:37:35 +01:00
1 parent 3d8461686f
commit f0ee44df93
6 files changed
+40 -15

No files matched your search

+6 -1
View File
@@ -1755,7 +1755,7 @@ jobs:
when: always
run-paywall-accessibility-ui-tests:
description: "Assert paywall accessibility labels against the real accessibility tree"
description: "Run the paywall fixture UI tests"
executor:
name: macos-executor
xcode_version: "27.0.0"
@@ -1774,6 +1774,9 @@ jobs:
bundle exec fastlane paywall_accessibility_ui_tests
environment:
SCAN_DEVICE: iPhone 17 (27.0)
SCAN_XCARGS: -collect-test-diagnostics never
SCAN_PARALLEL_TESTING: "true"
SCAN_CONCURRENT_WORKERS: "2"
no_output_timeout: 15m
- store_test_results:
path: fastlane/test_output
@@ -3090,6 +3093,7 @@ workflows:
pattern: "^(release/.*|main)$"
value: << pipeline.git.branch >>
jobs:
- run-paywall-accessibility-ui-tests
- check-api-changes:
context:
- slack-secrets-ios
@@ -3218,6 +3222,7 @@ workflows:
state: success
requires:
- check-api-changes
- run-paywall-accessibility-ui-tests
- run-all-maestro-e2e-tests
- run-workflow-maestro-tests
- run-sdk-update-test
@@ -27,11 +27,19 @@ struct NativeNavigationFixtureView: View {
var body: some View {
NavigationStack(path: self.$path) {
if self.dismissed {
if self.presentation != "push" {
VStack {
if self.dismissed {
Text("Paywall dismissed")
}
Button("Show native paywall") {
self.dismissed = false
self.modalPresented = true
}
}
.navigationTitle("Fixture host")
} else if self.dismissed {
Text("Paywall dismissed")
} else if self.presentation != "push" {
Button("Show native paywall") { self.modalPresented = true }
.navigationTitle("Fixture host")
} else {
NavigationLink("Show native paywall", value: true)
.navigationDestination(for: Bool.self) { _ in
@@ -50,6 +50,7 @@ final class CarouselTabsUITests: XCTestCase {
let centered = NSPredicate { _, _ in
Self.centeredPage(label, in: app) != nil
}
if centered.evaluate(with: nil) { return }
let result = XCTWaiter.wait(
for: [XCTNSPredicateExpectation(predicate: centered, object: nil)],
timeout: 5
@@ -39,7 +39,7 @@ final class CustomerCenterPreviewUITests: XCTestCase {
for configured in [false, true] {
let app = launch(mode: "legacy", configured: configured)
let button = app.descendants(matching: .any).matching(identifier: "Contact support").firstMatch
XCTAssertTrue(button.waitForExistence(timeout: 10), app.debugDescription)
XCTAssertTrue(button.exists || button.waitForExistence(timeout: 10), app.debugDescription)
button.tap()
assertEvent("mailto:support@example.invalid", in: app)
XCTAssertEqual(app.webViews.count, 0)
@@ -188,13 +188,14 @@ final class CustomerCenterPreviewUITests: XCTestCase {
app.launchEnvironment["PREVIEW_ACTION_OUTCOME"] = outcome
app.launchEnvironment["PREVIEW_CONFIGURE_SDK"] = configured ? "1" : "0"
app.launch()
XCTAssertTrue(app.staticTexts[configured ? "SDK configured" : "SDK unconfigured"].waitForExistence(timeout: 15))
let status = app.staticTexts[configured ? "SDK configured" : "SDK unconfigured"]
XCTAssertTrue(status.exists || status.waitForExistence(timeout: 15))
return app
}
private func openPreview(_ app: XCUIApplication) {
let button = app.buttons["Open preview"]
XCTAssertTrue(button.waitForExistence(timeout: 10), app.debugDescription)
XCTAssertTrue(button.exists || button.waitForExistence(timeout: 10), app.debugDescription)
button.tap()
}
@@ -127,9 +127,10 @@ final class NativeNavigationUITests: XCTestCase {
}
private func assertCarouselCloseDismisses(native: Bool) {
let app = self.launch("native_inline_sheet", presentation: "sheet", carouselNative: native)
for page in 1...5 {
let app = self.launch("native_inline_sheet", presentation: "sheet", carouselNative: native)
self.assertVisible(app.staticTexts["Carousel page 1"], in: app)
XCTAssertFalse(app.staticTexts["Paywall dismissed"].exists, app.debugDescription)
for previous in 1..<page {
let title = app.staticTexts["Carousel page \(previous)"]
let origin = app.coordinate(withNormalizedOffset: .zero)
@@ -150,7 +151,11 @@ final class NativeNavigationUITests: XCTestCase {
}
close.tap()
self.assertVisible(app.staticTexts["Paywall dismissed"], in: app)
app.terminate()
if page < 5 {
let showPaywall = app.buttons["Show native paywall"]
self.assertVisible(showPaywall, in: app)
showPaywall.tap()
}
}
}
@@ -277,7 +282,7 @@ final class NativeNavigationUITests: XCTestCase {
}
private func assertNativeControls(in app: XCUIApplication, back: Bool, close: Bool) {
let ready = XCTNSPredicateExpectation(predicate: NSPredicate { _, _ in
let ready = NSPredicate { _, _ in
let backButton = app.buttons[self.backIdentifier]
let closeButton = app.buttons[self.closeIdentifier]
return app.buttons.matching(identifier: self.backIdentifier).count == (back ? 1 : 0)
@@ -285,8 +290,10 @@ final class NativeNavigationUITests: XCTestCase {
&& (!back || (backButton.isEnabled && backButton.isHittable))
&& (!close || (closeButton.isEnabled && closeButton.isHittable))
&& (!(back || close) || !app.buttons["BackButton"].exists)
}, object: nil)
XCTAssertEqual(XCTWaiter.wait(for: [ready], timeout: 10), .completed, app.debugDescription)
}
if ready.evaluate(with: nil) { return }
let expectation = XCTNSPredicateExpectation(predicate: ready, object: nil)
XCTAssertEqual(XCTWaiter.wait(for: [expectation], timeout: 10), .completed, app.debugDescription)
}
private func launch(
@@ -303,12 +310,13 @@ final class NativeNavigationUITests: XCTestCase {
}
app.launch()
let showPaywall = app.buttons["Show native paywall"]
XCTAssertTrue(showPaywall.waitForExistence(timeout: 30), app.debugDescription)
XCTAssertTrue(showPaywall.exists || showPaywall.waitForExistence(timeout: 30), app.debugDescription)
showPaywall.tap()
return app
}
private func assertVisible(_ element: XCUIElement, in app: XCUIApplication) {
if element.exists && element.isHittable { return }
let visible = XCTNSPredicateExpectation(predicate: NSPredicate(format: "exists == true AND hittable == true"),
object: element)
XCTAssertEqual(XCTWaiter.wait(for: [visible], timeout: 10), .completed, app.debugDescription)
@@ -44,7 +44,8 @@ final class NestedBillingTabsUITests: XCTestCase {
line: UInt = #line
) {
let card = app.buttons.matching(NSPredicate(format: "label BEGINSWITH %@", billingID)).firstMatch
XCTAssertTrue(card.waitForExistence(timeout: 5), "Missing \(billingID) card", file: file, line: line)
XCTAssertTrue(card.exists || card.waitForExistence(timeout: 5),
"Missing \(billingID) card", file: file, line: line)
XCTAssertTrue(card.isHittable, file: file, line: line)
let selected = app.staticTexts.matching(NSPredicate(format: "label BEGINSWITH 'Selected '")).firstMatch
@@ -53,6 +54,7 @@ final class NestedBillingTabsUITests: XCTestCase {
let price = String(selected.label.dropFirst("Selected ".count))
return !price.isEmpty && card.label.contains(price)
}
if selectionMatches.evaluate(with: nil) { return }
XCTAssertEqual(
XCTWaiter.wait(for: [XCTNSPredicateExpectation(predicate: selectionMatches, object: nil)], timeout: 5),
.completed,