import XCTest
import MetaWearablesDAT
@MainActor
class MockDeviceKitTestCase: XCTestCase {
private var mockDevice: MockRaybanMeta?
private var cameraKit: MockCameraKit?
override func setUp() async throws {
try await super.setUp()
try? Wearables.configure()
mockDevice = MockDeviceKit.shared.pairRaybanMeta()
cameraKit = mockDevice?.getCameraKit()
}
override func tearDown() async throws {
MockDeviceKit.shared.pairedDevices.forEach { device in
MockDeviceKit.shared.unpairDevice(device)
}
mockDevice = nil
cameraKit = nil
try await super.tearDown()
}
}
guard let device = MockDeviceKit.shared.pairRaybanMeta() else { return }
let camera = device.getCameraKit()
await camera.setCameraFeed(fileURL: videoURL)
guard let device = MockDeviceKit.shared.pairRaybanMeta() else { return }
let camera = device.getCameraKit()
await camera.setCapturedImage(fileURL: imageURL)
Note: For more examples of how to leverage the MockDevice Test Server to test your apps, see the Camera Access sample code atExternalSampleApps/CameraAccess/CameraAccessUITests/.
/tmp directory on the simulator.┌─────────────────────────────────────┐ ┌──────────────────────────────────┐ │ App Process (DEBUG) │ HTTP (localhost) │ XCUITest Process │ │ │ │ │ │ MockDeviceKit │ POST /device/pair │ MockDeviceTestClient │ │ └─ startTestServer() │ POST /device/don │ │ │ │ POST /device/doff │ Port discovery: │ │ │ POST /device/power-on │ reads port from temp file │ │ │ GET /device/state │ written by server on start │ │ │ POST /camera/set-feed │ │ │ │ ... │ │ │ │◄────────────────────────│ │ └─────────────────────────────────────┘ └──────────────────────────────────┘
--ui-testing flag. The server should only be enabled in DEBUG builds.import MWDATMockDevice
if ProcessInfo.processInfo.arguments.contains("--ui-testing") {
MockDeviceKit.shared.enable(config: MockDeviceKitConfig(initiallyRegistered: false))
let portFilePath = ProcessInfo.processInfo.environment["MWDAT_TEST_SERVER_PORT_FILE"]
Task {
try await MockDeviceKit.shared.startTestServer(portFilePath: portFilePath)
// Server is now listening — tests drive mock device setup via HTTP
}
}
MWDATMockDeviceTestClient in your UI test target. The client reads the port from the temp file.import MWDATMockDeviceTestClient
import XCTest
final class MyUITests: XCTestCase {
var portFilePath: String {
NSTemporaryDirectory() + "mwdat_test_server_port.txt"
}
private let app = XCUIApplication()
private var mockClient: MockDeviceTestClient!
private var deviceId: String?
override func setUpWithError() throws {
// Remove any stale port file from a previous run
try? FileManager.default.removeItem(atPath: portFilePath)
app.launchArguments = ["--ui-testing"]
app.launchEnvironment["MWDAT_TEST_SERVER_PORT_FILE"] = portFilePath
app.launch()
// Initialize the client after launch so the server has time to write the port file
mockClient = MockDeviceTestClient(portFilePath: portFilePath)
XCTAssertTrue(mockClient.waitForServer(timeout: 10), "Test server should be running")
}
override func tearDownWithError() throws {
if let deviceId {
mockClient.unpairDevice(deviceId: deviceId)
}
deviceId = nil
}
func testStreaming() {
// Pair a device — pairDevice() powers it on and dons it automatically
guard let id = mockClient.pairDevice() else {
XCTFail("Failed to pair mock device")
return
}
deviceId = id
// Configure camera resources for this device
mockClient.setCameraFeed(deviceId: id, resourceName: "plant", ext: "mp4")
mockClient.setCapturedImage(deviceId: id, resourceName: "plant", ext: "png")
// Device is now paired, powered on, and donned
let startButton = app.buttons["Start streaming"]
XCTAssertTrue(startButton.waitForExistence(timeout: 15))
// Control device state mid-test
mockClient.doff(deviceId: id) // device becomes inactive
mockClient.don(deviceId: id) // device becomes active again
mockClient.fold(deviceId: id) // hinges close, streaming stops
mockClient.unfold(deviceId: id) // hinges open
// Query device state
let state = mockClient.getDeviceState()
XCTAssertEqual(state?["pairedDeviceCount"] as? Int, 1)
}
}
| Method | Description |
|---|---|
pairDevice() | Pairs a mock Ray-Ban Meta, powers on, dons; returns the device ID (nil on failure) |
unpairDevice(deviceId:) | Unpairs the specified mock device |
powerOn(deviceId:) / powerOff(deviceId:) | Controls device power state |
don(deviceId:) / doff(deviceId:) | Simulates wearing / removing the device |
fold(deviceId:) / unfold(deviceId:) | Simulates folding / unfolding the glasses |
captouchTap(deviceId:) | Simulates a single tap gesture (toggles pause/resume) |
captouchTapAndHold(deviceId:) | Simulates tap-and-hold (stops active session) |
setCameraFeed(deviceId:resourceName:ext:) | Sets the camera feed video resource from the test bundle |
setCapturedImage(deviceId:resourceName:ext:) | Sets the captured image resource from the test bundle |
getDeviceState() | Returns {"pairedDeviceCount": Int, "deviceIds": [String]} |
healthCheck() | Checks if the server is reachable |
waitForServer(timeout:) | Polls until the server responds or timeout expires |
MWDATMockDeviceTestClient as a dependency of your UI test target. The client has no dependency on MWDATMockDevice — it communicates purely over HTTP.