diff --git a/desktop/app/src/server/devices/IOSDevice.tsx b/desktop/app/src/server/devices/IOSDevice.tsx index 751e62617..8e3e2d996 100644 --- a/desktop/app/src/server/devices/IOSDevice.tsx +++ b/desktop/app/src/server/devices/IOSDevice.tsx @@ -213,8 +213,9 @@ export default class IOSDevice extends BaseDevice { } async startScreenCapture(destination: string) { - this.recordingProcess = exec( - `xcrun simctl io ${this.serial} recordVideo --codec=h264 --force ${destination}`, + this.recordingProcess = this.iOSBridge.recordVideo( + this.serial, + destination, ); this.recordingLocation = destination; } diff --git a/desktop/app/src/server/utils/IOSBridge.tsx b/desktop/app/src/server/utils/IOSBridge.tsx index 8a37389dd..4067f8627 100644 --- a/desktop/app/src/server/utils/IOSBridge.tsx +++ b/desktop/app/src/server/utils/IOSBridge.tsx @@ -28,6 +28,10 @@ export interface IOSBridge { ) => child_process.ChildProcessWithoutNullStreams; screenshot: (serial: string) => Promise; navigate: (serial: string, location: string) => Promise; + recordVideo: ( + serial: string, + outputFile: string, + ) => child_process.ChildProcess; } async function isAvailable(idbPath: string): Promise { @@ -134,6 +138,24 @@ export async function idbNavigate( exec(`idb open --udid ${serial} "${location}"`); } +export function xcrunRecordVideo( + serial: string, + outputFile: string, +): child_process.ChildProcess { + console.log(`Starting screen record via xcrun to ${outputFile}.`); + return exec( + `xcrun simctl io ${serial} recordVideo --codec=h264 --force ${outputFile}`, + ); +} + +export function idbRecordVideo( + serial: string, + outputFile: string, +): child_process.ChildProcess { + console.log(`Starting screen record via idb to ${outputFile}.`); + return exec(`idb record-video --udid ${serial} ${outputFile}`); +} + export async function makeIOSBridge( idbPath: string, isXcodeDetected: boolean, @@ -145,6 +167,7 @@ export async function makeIOSBridge( startLogListener: idbStartLogListener.bind(null, idbPath), screenshot: idbScreenshot, navigate: idbNavigate, + recordVideo: idbRecordVideo, }; } @@ -154,6 +177,7 @@ export async function makeIOSBridge( startLogListener: xcrunStartLogListener, screenshot: xcrunScreenshot, navigate: xcrunNavigate, + recordVideo: xcrunRecordVideo, }; } diff --git a/desktop/app/src/server/utils/__tests__/IOSBridge.node.tsx b/desktop/app/src/server/utils/__tests__/IOSBridge.node.tsx index f055fc671..25a3e9661 100644 --- a/desktop/app/src/server/utils/__tests__/IOSBridge.node.tsx +++ b/desktop/app/src/server/utils/__tests__/IOSBridge.node.tsx @@ -134,3 +134,23 @@ test('uses idb to navigate when available', async () => { expect(exec).toHaveBeenCalledWith('idb open --udid deadbeef "fb://dummy"'); }); + +test('uses xcrun to record with no idb when xcode is detected', async () => { + const ib = await makeIOSBridge('', true); + + ib.recordVideo('deadbeef', '/tmp/video.mp4'); + + expect(exec).toHaveBeenCalledWith( + 'xcrun simctl io deadbeef recordVideo --codec=h264 --force /tmp/video.mp4', + ); +}); + +test('uses idb to record when available', async () => { + const ib = await makeIOSBridge('/usr/local/bin/idb', true, async (_) => true); + + ib.recordVideo('deadbeef', '/tmo/video.mp4'); + + expect(exec).toHaveBeenCalledWith( + 'idb record-video --udid deadbeef /tmo/video.mp4', + ); +});