From 37f4eb37bb3f80fe901d9cc8c3a3c00c3a9c71ff Mon Sep 17 00:00:00 2001 From: Muhammed Furkan Boran Date: Fri, 2 Aug 2024 21:28:46 +0300 Subject: [PATCH] Add installApp command for IOS (#1665) --- maestro-client/src/main/java/maestro/Driver.kt | 2 +- maestro-client/src/main/java/maestro/Maestro.kt | 5 ++--- .../src/main/java/maestro/drivers/AndroidDriver.kt | 5 +++-- .../src/main/java/maestro/drivers/IOSDriver.kt | 4 ++-- .../src/main/java/maestro/drivers/WebDriver.kt | 2 +- .../src/main/kotlin/util/LocalSimulatorUtils.kt | 12 ++++++++++++ maestro-ios/src/main/java/ios/IOSDevice.kt | 2 ++ maestro-ios/src/main/java/ios/LocalIOSDevice.kt | 4 ++++ .../src/main/java/ios/simctl/SimctlIOSDevice.kt | 7 +++++++ .../src/main/java/ios/xctest/XCTestIOSDevice.kt | 4 ++++ .../src/main/java/maestro/orchestra/Commands.kt | 4 ++-- .../src/main/java/maestro/orchestra/Orchestra.kt | 6 +++--- .../java/maestro/orchestra/yaml/YamlFluentCommand.kt | 2 +- .../java/maestro/orchestra/yaml/YamlInstallApp.kt | 6 +++--- .../main/kotlin/maestro/test/drivers/FakeDriver.kt | 2 +- 15 files changed, 48 insertions(+), 19 deletions(-) diff --git a/maestro-client/src/main/java/maestro/Driver.kt b/maestro-client/src/main/java/maestro/Driver.kt index a541a3aeea..1875083919 100644 --- a/maestro-client/src/main/java/maestro/Driver.kt +++ b/maestro-client/src/main/java/maestro/Driver.kt @@ -103,5 +103,5 @@ interface Driver { fun setAirplaneMode(enabled: Boolean) - fun installApk(apk: File) + fun installApp(path: String) } diff --git a/maestro-client/src/main/java/maestro/Maestro.kt b/maestro-client/src/main/java/maestro/Maestro.kt index 8406381bd7..4fa7638b71 100644 --- a/maestro-client/src/main/java/maestro/Maestro.kt +++ b/maestro-client/src/main/java/maestro/Maestro.kt @@ -595,9 +595,8 @@ class Maestro(private val driver: Driver) : AutoCloseable { driver.setAirplaneMode(enabled) } - fun installApk(apkPath: String?) { - val apkFile = File(apkPath.orEmpty()) - driver.installApk(apkFile) + fun installApp(path: String?) { + driver.installApp(path.orEmpty()) } companion object { diff --git a/maestro-client/src/main/java/maestro/drivers/AndroidDriver.kt b/maestro-client/src/main/java/maestro/drivers/AndroidDriver.kt index 115cbd5dae..15bb3e0807 100644 --- a/maestro-client/src/main/java/maestro/drivers/AndroidDriver.kt +++ b/maestro-client/src/main/java/maestro/drivers/AndroidDriver.kt @@ -712,8 +712,9 @@ class AndroidDriver( shell("cmd connectivity airplane-mode $value") } - override fun installApk(apk: File) { - install(apk) + override fun installApp(path: String) { + val apkFile = File(path) + install(apkFile) } diff --git a/maestro-client/src/main/java/maestro/drivers/IOSDriver.kt b/maestro-client/src/main/java/maestro/drivers/IOSDriver.kt index 60363d9633..fa69eade76 100644 --- a/maestro-client/src/main/java/maestro/drivers/IOSDriver.kt +++ b/maestro-client/src/main/java/maestro/drivers/IOSDriver.kt @@ -454,8 +454,8 @@ class IOSDriver( LOGGER.warn("Airplane mode is not available on iOS simulators") } - override fun installApk(apk: File) { - LOGGER.warn("Install app is not available on iOS simulators") + override fun installApp(path: String) { + iosDevice.installApp(path) } private fun addMediaToDevice(mediaFile: File) { diff --git a/maestro-client/src/main/java/maestro/drivers/WebDriver.kt b/maestro-client/src/main/java/maestro/drivers/WebDriver.kt index 9d50f3db71..46a3b0ec0b 100644 --- a/maestro-client/src/main/java/maestro/drivers/WebDriver.kt +++ b/maestro-client/src/main/java/maestro/drivers/WebDriver.kt @@ -391,7 +391,7 @@ class WebDriver(val isStudio: Boolean) : Driver { TODO("Not yet implemented") } - override fun installApk(apk: File) { + override fun installApp(path: String) { TODO("Not yet implemented") } diff --git a/maestro-ios-driver/src/main/kotlin/util/LocalSimulatorUtils.kt b/maestro-ios-driver/src/main/kotlin/util/LocalSimulatorUtils.kt index acc61c2d30..0d7eabd202 100644 --- a/maestro-ios-driver/src/main/kotlin/util/LocalSimulatorUtils.kt +++ b/maestro-ios-driver/src/main/kotlin/util/LocalSimulatorUtils.kt @@ -269,6 +269,18 @@ object LocalSimulatorUtils { ) } + fun install(deviceId: String, path: String) { + runCommand( + listOf( + "xcrun", + "simctl", + "install", + deviceId, + path, + ) + ) + } + fun uninstall(deviceId: String, bundleId: String) { runCommand( listOf( diff --git a/maestro-ios/src/main/java/ios/IOSDevice.kt b/maestro-ios/src/main/java/ios/IOSDevice.kt index 1669a8ba28..d3455b5bbe 100644 --- a/maestro-ios/src/main/java/ios/IOSDevice.kt +++ b/maestro-ios/src/main/java/ios/IOSDevice.kt @@ -150,6 +150,8 @@ interface IOSDevice : AutoCloseable { fun eraseText(charactersToErase: Int) fun addMedia(path: String) + + fun installApp(path: String) } interface IOSScreenRecording : AutoCloseable diff --git a/maestro-ios/src/main/java/ios/LocalIOSDevice.kt b/maestro-ios/src/main/java/ios/LocalIOSDevice.kt index 10fdd75b9c..f0f1034c1d 100644 --- a/maestro-ios/src/main/java/ios/LocalIOSDevice.kt +++ b/maestro-ios/src/main/java/ios/LocalIOSDevice.kt @@ -155,4 +155,8 @@ class LocalIOSDevice( override fun addMedia(path: String) { simctlIOSDevice.addMedia(path) } + + override fun installApp(path: String) { + simctlIOSDevice.installApp(path) + } } diff --git a/maestro-ios/src/main/java/ios/simctl/SimctlIOSDevice.kt b/maestro-ios/src/main/java/ios/simctl/SimctlIOSDevice.kt index f25e4f794c..db8c3224de 100644 --- a/maestro-ios/src/main/java/ios/simctl/SimctlIOSDevice.kt +++ b/maestro-ios/src/main/java/ios/simctl/SimctlIOSDevice.kt @@ -172,4 +172,11 @@ class SimctlIOSDevice( stopScreenRecording() } + override fun installApp(path: String) { + LocalSimulatorUtils.install( + deviceId = deviceId, + path = path + ) + } + } diff --git a/maestro-ios/src/main/java/ios/xctest/XCTestIOSDevice.kt b/maestro-ios/src/main/java/ios/xctest/XCTestIOSDevice.kt index 29495173eb..f900910f8a 100644 --- a/maestro-ios/src/main/java/ios/xctest/XCTestIOSDevice.kt +++ b/maestro-ios/src/main/java/ios/xctest/XCTestIOSDevice.kt @@ -213,6 +213,10 @@ class XCTestIOSDevice( execute { client.eraseText(charactersToErase, appIds) } } + override fun installApp(path: String) { + error("Not supported") + } + private fun activeAppId(): String { return execute { val appIds = getInstalledApps() diff --git a/maestro-orchestra-models/src/main/java/maestro/orchestra/Commands.kt b/maestro-orchestra-models/src/main/java/maestro/orchestra/Commands.kt index ba40696f09..991e89b98f 100644 --- a/maestro-orchestra-models/src/main/java/maestro/orchestra/Commands.kt +++ b/maestro-orchestra-models/src/main/java/maestro/orchestra/Commands.kt @@ -921,11 +921,11 @@ data class ToggleAirplaneModeCommand( } data class InstallApplicationCommand( - val apkPath: String? = null, + val path: String? = null, val label: String? = null, ): Command { override fun description(): String { - return label ?: "Installing $apkPath" + return label ?: "Installing $path" } override fun evaluateScripts(jsEngine: JsEngine): Command { diff --git a/maestro-orchestra/src/main/java/maestro/orchestra/Orchestra.kt b/maestro-orchestra/src/main/java/maestro/orchestra/Orchestra.kt index fc984b35fa..c580cb046b 100644 --- a/maestro-orchestra/src/main/java/maestro/orchestra/Orchestra.kt +++ b/maestro-orchestra/src/main/java/maestro/orchestra/Orchestra.kt @@ -281,7 +281,7 @@ class Orchestra( is AddMediaCommand -> addMediaCommand(command.mediaPaths) is SetAirplaneModeCommand -> setAirplaneMode(command) is ToggleAirplaneModeCommand -> toggleAirplaneMode() - is InstallApplicationCommand -> installApk(command) + is InstallApplicationCommand -> installApp(command) else -> true }.also { mutating -> if (mutating) { @@ -290,8 +290,8 @@ class Orchestra( } } - private fun installApk(command: InstallApplicationCommand): Boolean { - maestro.installApk(command.apkPath) + private fun installApp(command: InstallApplicationCommand): Boolean { + maestro.installApp(command.path) return true } diff --git a/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlFluentCommand.kt b/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlFluentCommand.kt index 7aeb3ba3c3..89191f3080 100644 --- a/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlFluentCommand.kt +++ b/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlFluentCommand.kt @@ -228,7 +228,7 @@ data class YamlFluentCommand( installApp != null -> listOf( MaestroCommand( InstallApplicationCommand( - apkPath = installApp.apkPath, + path = installApp.path, label = installApp.label ) ) diff --git a/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlInstallApp.kt b/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlInstallApp.kt index a345f161d5..6970e163f5 100644 --- a/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlInstallApp.kt +++ b/maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlInstallApp.kt @@ -3,14 +3,14 @@ package maestro.orchestra.yaml import com.fasterxml.jackson.annotation.JsonCreator data class YamlInstallApp( - val apkPath: String? = null, + val path: String? = null, val label: String? = null, ) { companion object { @JvmStatic @JsonCreator(mode = JsonCreator.Mode.DELEGATING) - fun parse(apkPath: String) = YamlInstallApp( - apkPath = apkPath, + fun parse(path: String) = YamlInstallApp( + path = path, ) } } diff --git a/maestro-test/src/main/kotlin/maestro/test/drivers/FakeDriver.kt b/maestro-test/src/main/kotlin/maestro/test/drivers/FakeDriver.kt index 9f1461997f..87638baa90 100644 --- a/maestro-test/src/main/kotlin/maestro/test/drivers/FakeDriver.kt +++ b/maestro-test/src/main/kotlin/maestro/test/drivers/FakeDriver.kt @@ -394,7 +394,7 @@ class FakeDriver : Driver { this.airplaneMode = enabled } - override fun installApk(apk: File) { + override fun installApp(path: String) { events.add(Event.InstallApp) }