Extract idb device querying to IOSBridge

Summary:
Again this is just a code move for now.

However, we now have a common method between simctl and idb cases. This means that the next diff can call an `IOSBridge` with polymorpism taking over. This is still delegated out, but there's an argument to be made to move `iosUtil` functionality back so that this all lives in the same place.

Reviewed By: passy

Differential Revision: D33843093

fbshipit-source-id: 5cd884140817df851cccf63e5780582b16d4231c
This commit is contained in:
Lawrence Lomax
2022-01-31 07:23:29 -08:00
committed by Facebook GitHub Bot
parent aeb0b5f317
commit ccae37aa71
3 changed files with 61 additions and 19 deletions

View File

@@ -8,6 +8,8 @@
*/
import fs from 'fs-extra';
import iosUtil from './iOSContainerUtility';
import child_process from 'child_process';
import type {IOSDeviceParams} from 'flipper-common';
import {DeviceType} from 'flipper-common';
@@ -42,10 +44,22 @@ export interface IOSBridge {
serial: string,
outputFile: string,
) => child_process.ChildProcess;
getActiveDevices: (bootedOnly: boolean) => Promise<Array<IOSDeviceParams>>;
}
class IDBBridge implements IOSBridge {
constructor(private idbPath: string) {}
export class IDBBridge implements IOSBridge {
constructor(
private idbPath: string,
private enablePhysicalDevices: boolean,
) {}
async getActiveDevices(_bootedOnly: boolean): Promise<IOSDeviceParams[]> {
return iosUtil
.targets(this.idbPath, this.enablePhysicalDevices)
.catch((e) => {
console.error('Failed to get active iOS devices:', e.message);
return [];
});
}
async navigate(serial: string, location: string): Promise<void> {
this._execIdb(`open --udid ${serial} "${location}"`);
@@ -216,11 +230,12 @@ export function getDeviceSetPath() {
export async function makeIOSBridge(
idbPath: string,
isXcodeDetected: boolean,
enablePhysicalDevices: boolean,
isAvailableFn: (idbPath: string) => Promise<boolean> = isAvailable,
): Promise<IOSBridge> {
// prefer idb
if (await isAvailableFn(idbPath)) {
return new IDBBridge(idbPath);
return new IDBBridge(idbPath, enablePhysicalDevices);
}
// no idb, if it's a simulator and xcode is available, we can use xcrun

View File

@@ -26,7 +26,7 @@ afterEach(() => {
});
test('uses xcrun with no idb when xcode is detected', async () => {
const ib = await makeIOSBridge('', true);
const ib = await makeIOSBridge('', true, false);
ib.startLogListener('deadbeef', 'emulator');
@@ -50,7 +50,12 @@ test('uses xcrun with no idb when xcode is detected', async () => {
});
test('uses idb when present and xcode detected', async () => {
const ib = await makeIOSBridge('/usr/local/bin/idb', true, async (_) => true);
const ib = await makeIOSBridge(
'/usr/local/bin/idb',
true,
true,
async (_) => true,
);
ib.startLogListener('deadbeef', 'emulator');
@@ -77,7 +82,12 @@ test('uses idb when present and xcode detected', async () => {
});
test('uses idb when present and xcode detected and physical device connected', async () => {
const ib = await makeIOSBridge('/usr/local/bin/idb', true, async (_) => true);
const ib = await makeIOSBridge(
'/usr/local/bin/idb',
true,
true,
async (_) => true,
);
ib.startLogListener('deadbeef', 'physical');
@@ -99,12 +109,12 @@ test('uses idb when present and xcode detected and physical device connected', a
});
test("without idb physical devices can't log", async () => {
const ib = await makeIOSBridge('', true);
const ib = await makeIOSBridge('', true, false);
expect(ib.startLogListener).toBeDefined(); // since we have xcode
});
test('throws if no iOS support', async () => {
await expect(makeIOSBridge('', false)).rejects.toThrow(
await expect(makeIOSBridge('', false, false)).rejects.toThrow(
'Neither Xcode nor idb available. Cannot provide iOS device functionality.',
);
});
@@ -112,7 +122,7 @@ test('throws if no iOS support', async () => {
test.unix(
'uses xcrun to take screenshots with no idb when xcode is detected',
async () => {
const ib = await makeIOSBridge('', true);
const ib = await makeIOSBridge('', true, false);
await expect(() => ib.screenshot('deadbeef')).rejects.toThrow();
@@ -123,7 +133,12 @@ test.unix(
);
test.unix('uses idb to take screenshots when available', async () => {
const ib = await makeIOSBridge('/usr/local/bin/idb', true, async (_) => true);
const ib = await makeIOSBridge(
'/usr/local/bin/idb',
true,
true,
async (_) => true,
);
await expect(() => ib.screenshot('deadbeef')).rejects.toThrow();
@@ -133,7 +148,7 @@ test.unix('uses idb to take screenshots when available', async () => {
});
test('uses xcrun to navigate with no idb when xcode is detected', async () => {
const ib = await makeIOSBridge('', true);
const ib = await makeIOSBridge('', true, false);
await ib.navigate('deadbeef', 'fb://dummy');
@@ -143,7 +158,12 @@ test('uses xcrun to navigate with no idb when xcode is detected', async () => {
});
test('uses idb to navigate when available', async () => {
const ib = await makeIOSBridge('/usr/local/bin/idb', true, async (_) => true);
const ib = await makeIOSBridge(
'/usr/local/bin/idb',
true,
true,
async (_) => true,
);
await ib.navigate('deadbeef', 'fb://dummy');
@@ -153,7 +173,7 @@ test('uses idb to navigate when available', async () => {
});
test('uses xcrun to record with no idb when xcode is detected', async () => {
const ib = await makeIOSBridge('', true);
const ib = await makeIOSBridge('', true, false);
ib.recordVideo('deadbeef', '/tmp/video.mp4');
@@ -163,7 +183,12 @@ test('uses xcrun to record with no idb when xcode is detected', async () => {
});
test('uses idb to record when available', async () => {
const ib = await makeIOSBridge('/usr/local/bin/idb', true, async (_) => true);
const ib = await makeIOSBridge(
'/usr/local/bin/idb',
true,
true,
async (_) => true,
);
ib.recordVideo('deadbeef', '/tmo/video.mp4');

View File

@@ -17,6 +17,7 @@ import IOSDevice from './IOSDevice';
import {
ERR_NO_IDB_OR_XCODE_AVAILABLE,
IOSBridge,
IDBBridge,
makeIOSBridge,
SimctlBridge,
} from './IOSBridge';
@@ -174,7 +175,11 @@ export class IOSDeviceManager {
}
try {
// Awaiting the promise here to trigger immediate error handling.
this.iosBridge = await makeIOSBridge(settings.idbPath, isDetected);
this.iosBridge = await makeIOSBridge(
settings.idbPath,
isDetected,
settings.enablePhysicalIOS,
);
this.queryDevicesForever();
} catch (err) {
// This case is expected if both Xcode and idb are missing.
@@ -252,10 +257,7 @@ function getActiveDevices(
idbPath: string,
isPhysicalDeviceEnabled: boolean,
): Promise<Array<IOSDeviceParams>> {
return iosUtil.targets(idbPath, isPhysicalDeviceEnabled).catch((e) => {
console.error('Failed to get active iOS devices:', e.message);
return [];
});
return new IDBBridge(idbPath, isPhysicalDeviceEnabled).getActiveDevices(true);
}
export function parseXcodeFromCoreSimPath(