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:
committed by
Facebook GitHub Bot
parent
aeb0b5f317
commit
ccae37aa71
@@ -8,6 +8,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
|
import iosUtil from './iOSContainerUtility';
|
||||||
|
|
||||||
import child_process from 'child_process';
|
import child_process from 'child_process';
|
||||||
import type {IOSDeviceParams} from 'flipper-common';
|
import type {IOSDeviceParams} from 'flipper-common';
|
||||||
import {DeviceType} from 'flipper-common';
|
import {DeviceType} from 'flipper-common';
|
||||||
@@ -42,10 +44,22 @@ export interface IOSBridge {
|
|||||||
serial: string,
|
serial: string,
|
||||||
outputFile: string,
|
outputFile: string,
|
||||||
) => child_process.ChildProcess;
|
) => child_process.ChildProcess;
|
||||||
|
getActiveDevices: (bootedOnly: boolean) => Promise<Array<IOSDeviceParams>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
class IDBBridge implements IOSBridge {
|
export class IDBBridge implements IOSBridge {
|
||||||
constructor(private idbPath: string) {}
|
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> {
|
async navigate(serial: string, location: string): Promise<void> {
|
||||||
this._execIdb(`open --udid ${serial} "${location}"`);
|
this._execIdb(`open --udid ${serial} "${location}"`);
|
||||||
@@ -216,11 +230,12 @@ export function getDeviceSetPath() {
|
|||||||
export async function makeIOSBridge(
|
export async function makeIOSBridge(
|
||||||
idbPath: string,
|
idbPath: string,
|
||||||
isXcodeDetected: boolean,
|
isXcodeDetected: boolean,
|
||||||
|
enablePhysicalDevices: boolean,
|
||||||
isAvailableFn: (idbPath: string) => Promise<boolean> = isAvailable,
|
isAvailableFn: (idbPath: string) => Promise<boolean> = isAvailable,
|
||||||
): Promise<IOSBridge> {
|
): Promise<IOSBridge> {
|
||||||
// prefer idb
|
// prefer idb
|
||||||
if (await isAvailableFn(idbPath)) {
|
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
|
// no idb, if it's a simulator and xcode is available, we can use xcrun
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ afterEach(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('uses xcrun with no idb when xcode is detected', async () => {
|
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');
|
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 () => {
|
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');
|
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 () => {
|
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');
|
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 () => {
|
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
|
expect(ib.startLogListener).toBeDefined(); // since we have xcode
|
||||||
});
|
});
|
||||||
|
|
||||||
test('throws if no iOS support', async () => {
|
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.',
|
'Neither Xcode nor idb available. Cannot provide iOS device functionality.',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -112,7 +122,7 @@ test('throws if no iOS support', async () => {
|
|||||||
test.unix(
|
test.unix(
|
||||||
'uses xcrun to take screenshots with no idb when xcode is detected',
|
'uses xcrun to take screenshots with no idb when xcode is detected',
|
||||||
async () => {
|
async () => {
|
||||||
const ib = await makeIOSBridge('', true);
|
const ib = await makeIOSBridge('', true, false);
|
||||||
|
|
||||||
await expect(() => ib.screenshot('deadbeef')).rejects.toThrow();
|
await expect(() => ib.screenshot('deadbeef')).rejects.toThrow();
|
||||||
|
|
||||||
@@ -123,7 +133,12 @@ test.unix(
|
|||||||
);
|
);
|
||||||
|
|
||||||
test.unix('uses idb to take screenshots when available', async () => {
|
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();
|
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 () => {
|
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');
|
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 () => {
|
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');
|
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 () => {
|
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');
|
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 () => {
|
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');
|
ib.recordVideo('deadbeef', '/tmo/video.mp4');
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import IOSDevice from './IOSDevice';
|
|||||||
import {
|
import {
|
||||||
ERR_NO_IDB_OR_XCODE_AVAILABLE,
|
ERR_NO_IDB_OR_XCODE_AVAILABLE,
|
||||||
IOSBridge,
|
IOSBridge,
|
||||||
|
IDBBridge,
|
||||||
makeIOSBridge,
|
makeIOSBridge,
|
||||||
SimctlBridge,
|
SimctlBridge,
|
||||||
} from './IOSBridge';
|
} from './IOSBridge';
|
||||||
@@ -174,7 +175,11 @@ export class IOSDeviceManager {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// Awaiting the promise here to trigger immediate error handling.
|
// 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();
|
this.queryDevicesForever();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// This case is expected if both Xcode and idb are missing.
|
// This case is expected if both Xcode and idb are missing.
|
||||||
@@ -252,10 +257,7 @@ function getActiveDevices(
|
|||||||
idbPath: string,
|
idbPath: string,
|
||||||
isPhysicalDeviceEnabled: boolean,
|
isPhysicalDeviceEnabled: boolean,
|
||||||
): Promise<Array<IOSDeviceParams>> {
|
): Promise<Array<IOSDeviceParams>> {
|
||||||
return iosUtil.targets(idbPath, isPhysicalDeviceEnabled).catch((e) => {
|
return new IDBBridge(idbPath, isPhysicalDeviceEnabled).getActiveDevices(true);
|
||||||
console.error('Failed to get active iOS devices:', e.message);
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseXcodeFromCoreSimPath(
|
export function parseXcodeFromCoreSimPath(
|
||||||
|
|||||||
Reference in New Issue
Block a user