From d677619983eab988d1d99847962cc0cecd3a5a78 Mon Sep 17 00:00:00 2001 From: Sergey Ilyevsky Date: Mon, 3 Jul 2017 13:43:33 +0300 Subject: [PATCH 1/2] Switched to booting the device directly (related to https://github.com/facebook/FBSimulatorControl/issues/423) --- detox/src/devices/Fbsimctl.js | 37 +++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/detox/src/devices/Fbsimctl.js b/detox/src/devices/Fbsimctl.js index 673deabce5..6a423fd4df 100644 --- a/detox/src/devices/Fbsimctl.js +++ b/detox/src/devices/Fbsimctl.js @@ -3,6 +3,7 @@ const fs = require('fs'); const _ = require('lodash'); const log = require('npmlog'); const exec = require('../utils/exec'); +const retry = require('../utils/retry'); // FBSimulatorControl command line docs // https://github.com/facebook/FBSimulatorControl/issues/250 @@ -39,13 +40,37 @@ class Fbsimctl { } async boot(udid) { - const statusLogs = { - trying: `trying to boot device...`, - successful: `device ${udid} booted` - }; + let initialState; + await retry({retries: 10, interval: 1000}, async() => { + const initialStateCmdResult = await this._execFbsimctlCommand({args: `${udid} list`}, undefined, 1); + initialState = _.get(initialStateCmdResult, 'stdout', '') === '' ? undefined : _.get(JSON.parse(_.get(initialStateCmdResult, 'stdout')), 'subject.state'); + if(initialState === 'Shutting Down') { + log.info(`Waiting until the device ${udid} shuts down`); + throw `The device is in 'Shutting Down' state`; + } + }); + + if(initialState === 'Booted') { + log.info(`The device ${udid} is already booted`); + return; + } + + if(initialState === 'Booting') { + log.info(`The device ${udid} is already booting`); + } else { + const launchBin = "bash -c '`xcode-select -p`/Applications/Simulator.app/Contents/MacOS/Simulator " + + "--args -CurrentDeviceUDID EB9B3A90-621B-4F6E-815C-1E5C17ED5ABE -ConnectHardwareKeyboard 0 " + + "-DeviceSetPath /Users/sergeyi/Library/Developer/CoreSimulator/Devices > /dev/null 2>&1 < /dev/null &'"; + await exec.execWithRetriesAndLogs(launchBin, undefined, { + trying: `launching the simulator ${udid}...`, + successful: 'the device launch initiated' + }, 1); + } - const options = {args: `--state=shutdown --state=shutting-down ${udid} boot`}; - return await this._execFbsimctlCommand(options, statusLogs); + return await this._execFbsimctlCommand({args: `--state booted ${udid} list`}, { + trying: `waiting for the device to boot...`, + successful: `device ${udid} booted` + }); } async install(udid, absPath) { From 7e3901cc80e1a460438853535e65130db6478fd3 Mon Sep 17 00:00:00 2001 From: Sergey Ilyevsky Date: Tue, 4 Jul 2017 11:25:20 +0300 Subject: [PATCH 2/2] Switched to booting the device directly (related to https://github.com/facebook/FBSimulatorControl/issues/423) - tests and fixes --- detox/src/devices/Fbsimctl.js | 11 +++++--- detox/src/devices/Fbsimctl.test.js | 43 ++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/detox/src/devices/Fbsimctl.js b/detox/src/devices/Fbsimctl.js index 6a423fd4df..54f34dcba8 100644 --- a/detox/src/devices/Fbsimctl.js +++ b/detox/src/devices/Fbsimctl.js @@ -43,7 +43,12 @@ class Fbsimctl { let initialState; await retry({retries: 10, interval: 1000}, async() => { const initialStateCmdResult = await this._execFbsimctlCommand({args: `${udid} list`}, undefined, 1); - initialState = _.get(initialStateCmdResult, 'stdout', '') === '' ? undefined : _.get(JSON.parse(_.get(initialStateCmdResult, 'stdout')), 'subject.state'); + initialState = _.get(initialStateCmdResult, 'stdout', '') === '' ? undefined : + _.get(JSON.parse(_.get(initialStateCmdResult, 'stdout')), 'subject.state'); + if(initialState === undefined) { + log.info(`Couldn't get the state of ${udid}`); + throw `Couldn't get the state of the device`; + } if(initialState === 'Shutting Down') { log.info(`Waiting until the device ${udid} shuts down`); throw `The device is in 'Shutting Down' state`; @@ -59,8 +64,8 @@ class Fbsimctl { log.info(`The device ${udid} is already booting`); } else { const launchBin = "bash -c '`xcode-select -p`/Applications/Simulator.app/Contents/MacOS/Simulator " + - "--args -CurrentDeviceUDID EB9B3A90-621B-4F6E-815C-1E5C17ED5ABE -ConnectHardwareKeyboard 0 " + - "-DeviceSetPath /Users/sergeyi/Library/Developer/CoreSimulator/Devices > /dev/null 2>&1 < /dev/null &'"; + `--args -CurrentDeviceUDID ${udid} -ConnectHardwareKeyboard 0 ` + + "-DeviceSetPath ~/Library/Developer/CoreSimulator/Devices > /dev/null 2>&1 < /dev/null &'"; await exec.execWithRetriesAndLogs(launchBin, undefined, { trying: `launching the simulator ${udid}...`, successful: 'the device launch initiated' diff --git a/detox/src/devices/Fbsimctl.test.js b/detox/src/devices/Fbsimctl.test.js index 2c91be37cd..2d7ad17a83 100644 --- a/detox/src/devices/Fbsimctl.test.js +++ b/detox/src/devices/Fbsimctl.test.js @@ -16,6 +16,9 @@ describe('Fbsimctl', () => { fs = require('fs'); jest.mock('../utils/exec'); exec = require('../utils/exec').execWithRetriesAndLogs; + jest.setMock('../utils/retry', async (options, func) => { + return await func(1); + }); Fbsimctl = require('./Fbsimctl'); fbsimctl = new Fbsimctl(); }); @@ -53,8 +56,44 @@ describe('Fbsimctl', () => { } }); - it(`boot() - is triggering fbsimctl boot`, async() => { - await validateFbsimctlisCalledOn(fbsimctl, async () => fbsimctl.boot(simUdid)); + it(`boot() - when shutting down, should wait for the device`, async() => { + fbsimctl._execFbsimctlCommand = jest.fn(() => ({stdout: `{"subject": {"state": "Shutting Down"}}`})); + + try { + await fbsimctl.boot(simUdid); + fail('should throw'); + } catch (ex) { + expect(ex).toBe("The device is in 'Shutting Down' state"); + } + }); + + it(`boot() - when state is undefined, should wait for the device`, async() => { + fbsimctl._execFbsimctlCommand = jest.fn(() => ({})); + + try { + await fbsimctl.boot(simUdid); + fail('should throw'); + } catch (ex) { + expect(ex).toBe("Couldn't get the state of the device"); + } + }); + + it(`boot() - when booted, should not wait for the device to boot`, async() => { + fbsimctl._execFbsimctlCommand = jest.fn(() => ({stdout: `{"subject": {"state": "Booted"}}`})); + await fbsimctl.boot(simUdid); + expect(exec).toHaveBeenCalledTimes(0); + }); + + it(`boot() - when booting, should not call exec`, async() => { + fbsimctl._execFbsimctlCommand = jest.fn(() => ({stdout: `{"subject": {"state": "Booting"}}`})); + await fbsimctl.boot(simUdid); + expect(exec).toHaveBeenCalledTimes(0); + }); + + it(`boot() - when shutdown, should call exec`, async() => { + fbsimctl._execFbsimctlCommand = jest.fn(() => ({stdout: `{"subject": {"state": "Shutdown"}}`})); + await fbsimctl.boot(simUdid); + expect(exec).toHaveBeenCalledTimes(1); }); it(`install() - is triggering fbsimctl install`, async() => {