From 661678761479ddb7455787456d1b2893c01ae36a Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 16 Nov 2021 12:49:28 -0500 Subject: [PATCH 1/4] Server supports simulatorDeviceSet --- Sources/MusselServer/ServerManager.swift | 26 +++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/Sources/MusselServer/ServerManager.swift b/Sources/MusselServer/ServerManager.swift index a95dbe8..6a83834 100644 --- a/Sources/MusselServer/ServerManager.swift +++ b/Sources/MusselServer/ServerManager.swift @@ -24,6 +24,7 @@ class ServerManager { private func setupPushEndpoint() { let response: ((HttpRequest) -> HttpResponse) = { [weak self] request in + guard let self = self else { return .internalServerError } guard let serializedObject = try? JSONSerialization.jsonObject(with: Data(request.body), options: []), let json = serializedObject as? JSON, let simId = json["simulatorId"] as? String, @@ -33,9 +34,16 @@ class ServerManager { return HttpResponse.badRequest(nil) } - if let pushFileUrl = self?.createTemporaryPushFile(payload: payload) { - let command = "xcrun simctl push \(simId) \(appBundleId) \(pushFileUrl.path)" - self?.run(command: command) + let simctlOptions: String + if let simulatorDeviceSet = json["simulatorDeviceSet"] as? String { + simctlOptions = "--set \(simulatorDeviceSet) " + } else { + simctlOptions = "" + } + + if let pushFileUrl = self.createTemporaryPushFile(payload: payload) { + let command = "xcrun simctl \(simctlOptions)push \(simId) \(appBundleId) \(pushFileUrl.path)" + self.run(command: command) do { try FileManager.default.removeItem(at: pushFileUrl) @@ -54,6 +62,7 @@ class ServerManager { private func setupUniversalLinkEndpoint() { let response: ((HttpRequest) -> HttpResponse) = { [weak self] request in + guard let self = self else { return .internalServerError } guard let serializedObject = try? JSONSerialization.jsonObject(with: Data(request.body), options: []), let json = serializedObject as? JSON, let simId = json["simulatorId"] as? String, @@ -62,8 +71,15 @@ class ServerManager { return HttpResponse.badRequest(nil) } - let command = "xcrun simctl openurl \(simId) \(universalLink)" - self?.run(command: command) + let simctlOptions: String + if let simulatorDeviceSet = json["simulatorDeviceSet"] as? String { + simctlOptions = "--set \(simulatorDeviceSet) " + } else { + simctlOptions = "" + } + + let command = "xcrun simctl \(simctlOptions)openurl \(simId) \(universalLink)" + self.run(command: command) return .ok(.text("Ran command: \(command)")) } From 86075419626991373c4d6c17ea5a2ed5d3b45565 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 16 Nov 2021 13:06:35 -0500 Subject: [PATCH 2/4] Dry up Tester initialization and simulatorId --- Sources/Mussel/MusselNotificationTester.swift | 16 ++-------- Sources/Mussel/MusselTester.swift | 29 ++++++++++++------- .../Mussel/MusselUniversalLinkTester.swift | 16 ++-------- 3 files changed, 22 insertions(+), 39 deletions(-) diff --git a/Sources/Mussel/MusselNotificationTester.swift b/Sources/Mussel/MusselNotificationTester.swift index 80eb33a..60eef89 100644 --- a/Sources/Mussel/MusselNotificationTester.swift +++ b/Sources/Mussel/MusselNotificationTester.swift @@ -3,15 +3,6 @@ import Foundation public class MusselNotificationTester: MusselTester { - var targetAppBundleId: String - var serverHost: String = "localhost" - var serverPort: in_port_t = 10004 - var serverEndpoint: String = "simulatorPush" - - public required init(targetAppBundleId: String) { - self.targetAppBundleId = targetAppBundleId - } - public func triggerSimulatorNotification(withMessage message: String, additionalKeys: [String: Any]? = nil) { var innerAlert: [String: Any] = ["alert": message] if let additionalKeys = additionalKeys { @@ -22,14 +13,11 @@ public class MusselNotificationTester: MusselTester { } public func triggerSimulatorNotification(withFullPayload payload: [String: Any]) { - let endpoint = "http://\(serverHost):\(serverPort)/\(serverEndpoint)" - - let json: [String: Any?] = [ - "simulatorId": ProcessInfo.processInfo.environment["SIMULATOR_UDID"], + let options: [String: Any?] = [ "appBundleId": targetAppBundleId, "pushPayload": payload, ] - serverRequest(endpoint: endpoint, json: json) + serverRequestTask("simulatorPush", options: options) } } diff --git a/Sources/Mussel/MusselTester.swift b/Sources/Mussel/MusselTester.swift index 9b0f2f3..f7f74f4 100644 --- a/Sources/Mussel/MusselTester.swift +++ b/Sources/Mussel/MusselTester.swift @@ -2,24 +2,31 @@ import Foundation -protocol MusselTester: AnyObject { - var targetAppBundleId: String { get set } - var serverHost: String { get set } - var serverPort: in_port_t { get set } - var serverEndpoint: String { get set } +open class MusselTester { + var targetAppBundleId: String + private var simulatorId: String? + var serverHost: String = "localhost" + var serverPort: in_port_t = 10004 - init(targetAppBundleId: String) -} + public init(targetAppBundleId: String) { + self.targetAppBundleId = targetAppBundleId + self.simulatorId = ProcessInfo.processInfo.environment["SIMULATOR_UDID"] + } + + func serverRequestTask(_ task: String, options taskOptions: [String: Any?]) { + let endpoint = "http://\(serverHost):\(serverPort)/\(task)" -extension MusselTester { - func serverRequest(endpoint: String, json: [String: Any?]) { guard let endpointUrl = URL(string: endpoint) else { print("Invalid endpoint URL: \(endpoint)") return } - guard let data = try? JSONSerialization.data(withJSONObject: json, options: []) else { - print("Invalid JSON: \(json)") + let requestOptions = taskOptions.merging([ + "simulatorId": self.simulatorId, + ], uniquingKeysWith: { $1 }) + + guard let data = try? JSONSerialization.data(withJSONObject: requestOptions, options: []) else { + print("Invalid JSON: \(requestOptions)") return } diff --git a/Sources/Mussel/MusselUniversalLinkTester.swift b/Sources/Mussel/MusselUniversalLinkTester.swift index 95ec6c1..4104a2a 100644 --- a/Sources/Mussel/MusselUniversalLinkTester.swift +++ b/Sources/Mussel/MusselUniversalLinkTester.swift @@ -3,23 +3,11 @@ import Foundation public class MusselUniversalLinkTester: MusselTester { - var targetAppBundleId: String - var serverHost: String = "localhost" - var serverPort: in_port_t = 10004 - var serverEndpoint: String = "simulatorUniversalLink" - - public required init(targetAppBundleId: String) { - self.targetAppBundleId = targetAppBundleId - } - public func open(_ link: String) { - let endpoint = "http://\(serverHost):\(serverPort)/\(serverEndpoint)" - - let json: [String: Any?] = [ - "simulatorId": ProcessInfo.processInfo.environment["SIMULATOR_UDID"], + let options: [String: Any?] = [ "link": link, ] - serverRequest(endpoint: endpoint, json: json) + serverRequestTask("simulatorUniversalLink", options: options) } } From 348f3caec3d38064ba5cf873be9539e3085535b9 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 16 Nov 2021 13:06:57 -0500 Subject: [PATCH 3/4] simulatorDeviceSet inferred from environment --- Sources/Mussel/MusselTester.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Sources/Mussel/MusselTester.swift b/Sources/Mussel/MusselTester.swift index f7f74f4..934fa50 100644 --- a/Sources/Mussel/MusselTester.swift +++ b/Sources/Mussel/MusselTester.swift @@ -5,12 +5,14 @@ import Foundation open class MusselTester { var targetAppBundleId: String private var simulatorId: String? + private var simulatorDeviceSet: String? var serverHost: String = "localhost" var serverPort: in_port_t = 10004 public init(targetAppBundleId: String) { self.targetAppBundleId = targetAppBundleId self.simulatorId = ProcessInfo.processInfo.environment["SIMULATOR_UDID"] + self.simulatorDeviceSet = (ProcessInfo.processInfo.environment["HOME"]?.contains("XCTestDevices") ?? false) ? "testing" : nil } func serverRequestTask(_ task: String, options taskOptions: [String: Any?]) { @@ -23,6 +25,7 @@ open class MusselTester { let requestOptions = taskOptions.merging([ "simulatorId": self.simulatorId, + "simulatorDeviceSet": self.simulatorDeviceSet, ], uniquingKeysWith: { $1 }) guard let data = try? JSONSerialization.data(withJSONObject: requestOptions, options: []) else { From b2a7482fe8a5aeec4de5053b177a9a31f3bf8e89 Mon Sep 17 00:00:00 2001 From: Robin Daugherty Date: Tue, 16 Nov 2021 14:47:12 -0500 Subject: [PATCH 4/4] Comment on how to improve --- Sources/Mussel/MusselTester.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Sources/Mussel/MusselTester.swift b/Sources/Mussel/MusselTester.swift index 934fa50..5bea74c 100644 --- a/Sources/Mussel/MusselTester.swift +++ b/Sources/Mussel/MusselTester.swift @@ -11,7 +11,11 @@ open class MusselTester { public init(targetAppBundleId: String) { self.targetAppBundleId = targetAppBundleId + self.simulatorId = ProcessInfo.processInfo.environment["SIMULATOR_UDID"] + + // Infer whether the "testing" set is in use. + // Instead of this, we could provide the path to the set, which is HOME truncated at the simulator ID. self.simulatorDeviceSet = (ProcessInfo.processInfo.environment["HOME"]?.contains("XCTestDevices") ?? false) ? "testing" : nil }