mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 11:07:10 +00:00
feat(companion): launch and terminate apps through the automation session
This commit is contained in:
1 parent
4e02615aa4
commit
63de54ed4a
2 files changed
+60
No files matched your search
@@ -0,0 +1,51 @@
|
||||
import XCTest
|
||||
|
||||
// Launches and terminates apps through the automation session. Lifecycle
|
||||
// performed outside the session leaves its cached app proxies bound to dead
|
||||
// processes, after which snapshots hang and typing asserts.
|
||||
enum AppLifecycle {
|
||||
enum LifecycleError: Error {
|
||||
case failed(String)
|
||||
}
|
||||
|
||||
static func launch(bundleIdentifier: String, foregroundIfRunning: Bool) throws {
|
||||
try onMainCatching {
|
||||
let application = XCUIApplication(bundleIdentifier: bundleIdentifier)
|
||||
if foregroundIfRunning {
|
||||
// activate starts the app when needed and foregrounds it when
|
||||
// already running, without a forced relaunch.
|
||||
application.activate()
|
||||
} else {
|
||||
application.launch()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func terminate(bundleIdentifier: String) throws {
|
||||
try onMainCatching {
|
||||
let application = XCUIApplication(bundleIdentifier: bundleIdentifier)
|
||||
if application.state == .notRunning {
|
||||
return
|
||||
}
|
||||
application.terminate()
|
||||
}
|
||||
}
|
||||
|
||||
// onMainCatching runs automation work on the main thread and converts a
|
||||
// framework assertion into a thrown error so the server survives it.
|
||||
private static func onMainCatching(_ work: @escaping () -> Void) throws {
|
||||
var caughtError: NSError?
|
||||
var completed = false
|
||||
let run = {
|
||||
completed = CompanionRunCatching(work, &caughtError)
|
||||
}
|
||||
if Thread.isMainThread {
|
||||
run()
|
||||
} else {
|
||||
DispatchQueue.main.sync(execute: run)
|
||||
}
|
||||
if !completed {
|
||||
throw LifecycleError.failed(caughtError?.localizedDescription ?? "unknown")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,15 @@ final class Server {
|
||||
return ["ok": true]
|
||||
case "gestureProbe":
|
||||
return Gesture.probe()
|
||||
case "launch":
|
||||
let bundleIdentifier = params["bundleId"] as? String ?? currentBundleIdentifier
|
||||
let foregroundIfRunning = params["foregroundIfRunning"] as? Bool ?? false
|
||||
try AppLifecycle.launch(bundleIdentifier: bundleIdentifier, foregroundIfRunning: foregroundIfRunning)
|
||||
return ["ok": true]
|
||||
case "terminate":
|
||||
let bundleIdentifier = params["bundleId"] as? String ?? currentBundleIdentifier
|
||||
try AppLifecycle.terminate(bundleIdentifier: bundleIdentifier)
|
||||
return ["ok": true]
|
||||
case "typeText":
|
||||
let text = params["text"] as? String ?? ""
|
||||
let replace = params["replace"] as? Bool ?? false
|
||||
|
||||
Reference in new issue
Block a user