blob: fe67a3d6518b7e37e6a4b72d9dd881d6d879040c [file]
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import XCTest
final class NativeUIKitSwiftExperimentUITests: XCTestCase {
override func setUp() {
continueAfterFailure = false
}
@MainActor
func testColdStartUniversalLink() throws {
guard #available(iOS 16.4, *) else {
throw XCTSkip("app.open(url) is only available on iOS 16.4+")
}
let app = XCUIApplication()
let url = URL(string: "https://flutter-dashboard.appspot.com/cold")!
app.open(url)
let button = app.buttons["Get Lifecycle Events"].firstMatch
XCTAssertTrue(button.waitForExistence(timeout: 10))
button.tap()
// Unmigrated plugins receive applicationDidFinishLaunchingWithOptions twice on cold start:
// once during plugin registration with FlutterEngine, and once when FlutterAppDelegate forwards it.
let expectedEvents = [
"applicationDidFinishLaunchingWithOptions",
"applicationDidFinishLaunchingWithOptions",
"url:https://flutter-dashboard.appspot.com/cold",
"applicationWillEnterForeground",
"applicationDidBecomeActive",
]
let eventsPredicate = NSPredicate(
format: "label == %@",
expectedEvents.joined(separator: "\n")
)
let eventsElement = app.staticTexts.element(matching: eventsPredicate)
if !eventsElement.waitForExistence(timeout: 5) {
let allLabels = app.staticTexts.allElementsBoundByIndex.map(\.label).joined(separator: "\n---\n")
XCTFail("Cold start Universal Link fallback lifecycle sequence failed. Actual:\n\(allLabels)")
}
}
@MainActor
func testColdStartCustomScheme() throws {
guard #available(iOS 16.4, *) else {
throw XCTSkip("app.open(url) is only available on iOS 16.4+")
}
let app = XCUIApplication()
let url = URL(string: "testscheme://flutter/cold")!
app.open(url)
let button = app.buttons["Get Lifecycle Events"].firstMatch
XCTAssertTrue(button.waitForExistence(timeout: 10))
button.tap()
// Unmigrated plugins receive applicationDidFinishLaunchingWithOptions twice on cold start:
// once during plugin registration with FlutterEngine, and once when FlutterAppDelegate forwards it.
let expectedEvents = [
"applicationDidFinishLaunchingWithOptions",
"applicationDidFinishLaunchingWithOptions",
"url:testscheme://flutter/cold",
"applicationWillEnterForeground",
"applicationDidBecomeActive",
]
let eventsPredicate = NSPredicate(
format: "label == %@",
expectedEvents.joined(separator: "\n")
)
let eventsElement = app.staticTexts.element(matching: eventsPredicate)
if !eventsElement.waitForExistence(timeout: 5) {
let allLabels = app.staticTexts.allElementsBoundByIndex.map(\.label).joined(separator: "\n---\n")
XCTFail("Cold start Custom Scheme fallback lifecycle sequence failed. Actual:\n\(allLabels)")
}
}
@MainActor
func testWarmStartUniversalLink() throws {
guard #available(iOS 16.4, *) else {
throw XCTSkip("system.open(url) is only available on iOS 16.4+")
}
let app = XCUIApplication()
app.launch()
let button = app.buttons["Get Lifecycle Events"].firstMatch
XCTAssertTrue(button.waitForExistence(timeout: 10))
// Background the app before sending deep link to test warm start
XCUIDevice.shared.press(.home)
let url = URL(string: "https://flutter-dashboard.appspot.com/warm")!
XCUIDevice.shared.system.open(url)
XCTAssertTrue(button.waitForExistence(timeout: 10))
button.tap()
// On warm start, the app was already launched so applicationDidFinishLaunchingWithOptions
// is only logged once. The deep link resumes the backgrounded app via scene continuation.
let expectedEvents = [
"applicationDidFinishLaunchingWithOptions",
"applicationWillEnterForeground",
"applicationDidBecomeActive",
"applicationWillResignActive",
"applicationDidEnterBackground",
"applicationWillEnterForeground",
"applicationContinueUserActivity",
"url:https://flutter-dashboard.appspot.com/warm",
"applicationDidBecomeActive",
]
let eventsPredicate = NSPredicate(
format: "label == %@",
expectedEvents.joined(separator: "\n")
)
let eventsElement = app.staticTexts.element(matching: eventsPredicate)
if !eventsElement.waitForExistence(timeout: 5) {
let allLabels = app.staticTexts.allElementsBoundByIndex.map(\.label).joined(separator: "\n---\n")
XCTFail("Warm start Universal Link fallback lifecycle sequence failed. Actual:\n\(allLabels)")
}
}
@MainActor
func testWarmStartCustomScheme() throws {
guard #available(iOS 16.4, *) else {
throw XCTSkip("system.open(url) is only available on iOS 16.4+")
}
let app = XCUIApplication()
app.launch()
let button = app.buttons["Get Lifecycle Events"].firstMatch
XCTAssertTrue(button.waitForExistence(timeout: 10))
// Background the app before sending deep link to test warm start
XCUIDevice.shared.press(.home)
let url = URL(string: "testscheme://flutter/warm")!
XCUIDevice.shared.system.open(url)
XCTAssertTrue(button.waitForExistence(timeout: 10))
button.tap()
// On warm start, applicationDidFinishLaunchingWithOptions was only logged once during initial launch.
// The custom scheme deep link resumes the backgrounded app via openURL.
let expectedEvents = [
"applicationDidFinishLaunchingWithOptions",
"applicationWillEnterForeground",
"applicationDidBecomeActive",
"applicationWillResignActive",
"applicationDidEnterBackground",
"applicationOpenURL",
"url:testscheme://flutter/warm",
"applicationWillEnterForeground",
"applicationDidBecomeActive",
]
let eventsPredicate = NSPredicate(
format: "label == %@",
expectedEvents.joined(separator: "\n")
)
let eventsElement = app.staticTexts.element(matching: eventsPredicate)
if !eventsElement.waitForExistence(timeout: 5) {
let allLabels = app.staticTexts.allElementsBoundByIndex.map(\.label).joined(separator: "\n---\n")
XCTFail("Warm start Custom Scheme fallback lifecycle sequence failed. Actual:\n\(allLabels)")
}
}
}