From 124afe65c2ce354d8c15b4398acada56016045b1 Mon Sep 17 00:00:00 2001 From: Sergey Ilyevsky Date: Sun, 25 Jun 2017 18:38:04 +0300 Subject: [PATCH] Session per configuration (#173) Support for session per configuration --- detox/src/Detox.js | 89 ++++++++++++++++++-------------- detox/src/Detox.test.js | 66 +++++++++++++++++------ detox/src/configurations.mock.js | 47 ++++++++++++++++- detox/test/package.json | 8 ++- 4 files changed, 149 insertions(+), 61 deletions(-) diff --git a/detox/src/Detox.js b/detox/src/Detox.js index fec855c045..259c5beb14 100644 --- a/detox/src/Detox.js +++ b/detox/src/Detox.js @@ -20,33 +20,30 @@ class Detox { throw new Error(`No configuration was passed to detox, make sure you pass a config when calling 'detox.init(config)'`); } - this.client = null; this.userConfig = userConfig; - this.detoxConfig = {}; + this.client = null; + this.device = null; } - async config() { + async init() { if (!(this.userConfig.configurations && _.size(this.userConfig.configurations) >= 1)) { throw new Error(`no configured devices`); } - this.detoxConfig.configurations = this.userConfig.configurations; + const deviceConfig = await this._getDeviceConfig(); + const [session, shouldStartServer] = await this._chooseSession(deviceConfig); + const deviceClass = await this._chooseDeviceClass(deviceConfig); - if (this.userConfig.session) { - configuration.validateSession(this.userConfig.session); - this.detoxConfig.session = this.userConfig.session; - } else { - this.detoxConfig.session = await configuration.defaultSession(); - const server = new DetoxServer(new URL(this.detoxConfig.session.server).port); + if(shouldStartServer) { + this.server = new DetoxServer(new URL(session.server).port); } - return this.detoxConfig; - } - async init() { - await this.config(); - this.client = new Client(this.detoxConfig.session); - await this.client.connect(); - await this.initConfiguration(); + const client = new Client(session); + await client.connect(); + await this._initIosExpectations(client); + await this._setDevice(session, deviceClass, deviceConfig, client); + + this.client = client } async cleanup() { @@ -59,53 +56,65 @@ class Detox { } } - async initConfiguration() { + async _chooseSession(deviceConfig) { + var session = deviceConfig.session; + var shouldStartServer = false; + + if(!session) { + session = this.userConfig.session; + } + + if(!session) { + session = await configuration.defaultSession(); + shouldStartServer = true; + } + + configuration.validateSession(session); + + return [session, shouldStartServer]; + } + + async _getDeviceConfig() { const configurationName = argparse.getArgValue('configuration'); + const configurations = this.userConfig.configurations; let deviceConfig; - if (!configurationName && _.size(this.detoxConfig.configurations) === 1) { - deviceConfig = _.values(this.detoxConfig.configurations)[0]; + if (!configurationName && _.size(configurations) === 1) { + deviceConfig = _.values(configurations)[0]; } else { - deviceConfig = this.detoxConfig.configurations[configurationName]; + deviceConfig = configurations[configurationName]; } if (!deviceConfig) { throw new Error(`Cannot determine which configuration to use. use --configuration to choose one of the following: - ${Object.keys(this.detoxConfig.configurations)}`); + ${Object.keys(configurations)}`); } + return deviceConfig; + } + + async _chooseDeviceClass(deviceConfig) + { switch (deviceConfig.type) { case "ios.simulator": - await this.initIosSimulator(deviceConfig); - break; + return Simulator; case "ios.none": - await this.initIosNoneDevice(deviceConfig); - break; + return IosNoneDevice; default: throw new Error('only simulator is supported currently'); } } - async setDevice(device, deviceConfig) { - this.device = new device(this.client, this.detoxConfig.session, deviceConfig); + async _setDevice(session, deviceClass, deviceConfig, client) { + this.device = new deviceClass(client, session, deviceConfig); await this.device.prepare(); global.device = this.device; } - async initIosExpectations() { + async _initIosExpectations(client) { this.expect = require('./ios/expect'); this.expect.exportGlobals(); - this.expect.setInvocationManager(new InvocationManager(this.client)); - } - - async initIosSimulator(deviceConfig) { - await this.initIosExpectations(); - await this.setDevice(Simulator, deviceConfig); - } - - async initIosNoneDevice(deviceConfig) { - await this.initIosExpectations(); - await this.setDevice(IosNoneDevice, deviceConfig); + this.expect.setInvocationManager(new InvocationManager(client)); } } diff --git a/detox/src/Detox.test.js b/detox/src/Detox.test.js index 1e23d1e3b6..15717353a5 100644 --- a/detox/src/Detox.test.js +++ b/detox/src/Detox.test.js @@ -1,16 +1,31 @@ +import _ from 'lodash'; + const schemes = require('./configurations.mock'); describe('Detox', () => { let Detox; let detox; let minimist; + let clientMockData = {lastConstructorArguments: null}; + let simulatorMockData = {lastConstructorArguments: null}; beforeEach(async () => { + function setCustomMock(modulePath, dataObject) { + const JestMock = jest.genMockFromModule(modulePath); + class FinalMock extends JestMock { + constructor() { + super(...arguments); + dataObject.lastConstructorArguments = arguments; + } + } + jest.setMock(modulePath, FinalMock); + } + jest.mock('minimist'); minimist = require('minimist'); jest.mock('./ios/expect'); - jest.mock('./client/Client'); - jest.mock('./devices/Simulator'); + setCustomMock('./client/Client', clientMockData); + setCustomMock('./devices/Simulator', simulatorMockData); jest.mock('detox-server'); }); @@ -64,8 +79,7 @@ describe('Detox', () => { Detox = require('./Detox'); detox = new Detox(schemes.validOneDeviceNoSession); await detox.init(); - - expect(detox.detoxConfig.session.server).toBeDefined(); + expect(clientMockData.lastConstructorArguments[0]).toBeDefined(); }); it(`One valid device, detox should use session config and default to this device`, async () => { @@ -73,8 +87,7 @@ describe('Detox', () => { detox = new Detox(schemes.validOneDeviceAndSession); await detox.init(); - expect(detox.detoxConfig.session.server).toBe(schemes.validOneDeviceAndSession.session.server); - expect(detox.detoxConfig.session.sessionId).toBe(schemes.validOneDeviceAndSession.session.sessionId); + expect(clientMockData.lastConstructorArguments[0]).toBe(schemes.validOneDeviceAndSession.session); }); it(`Two valid devices, detox should init with the device passed in '--configuration' cli option`, async () => { @@ -84,17 +97,7 @@ describe('Detox', () => { detox = new Detox(schemes.validTwoDevicesNoSession); await detox.init(); - expect(detox.detoxConfig.configurations).toEqual(schemes.validTwoDevicesNoSession.configurations); - }); - - it(`Two valid devices, detox should init an ios.none device`, async () => { - mockCommandLineArgs({configuration: 'ios.sim.none'}); - Detox = require('./Detox'); - - detox = new Detox(schemes.validOneIosNoneDeviceNoSession); - await detox.init(); - - expect(detox.detoxConfig.configurations).toEqual(schemes.validOneIosNoneDeviceNoSession.configurations); + expect(simulatorMockData.lastConstructorArguments[2]).toEqual(schemes.validTwoDevicesNoSession.configurations['ios.sim.debug']); }); it(`Two valid devices, detox should throw if device passed in '--configuration' cli option doesn't exist`, async () => { @@ -142,6 +145,35 @@ describe('Detox', () => { detox.cleanup(); }); + it(`Detox should use session defined per configuration - none`, async () => { + mockCommandLineArgs({configuration: 'ios.sim.none'}); + Detox = require('./Detox'); + detox = new Detox(schemes.sessionPerConfiguration); + await detox.init(); + + let expectedSession = schemes.sessionPerConfiguration.configurations['ios.sim.none'].session; + expect(clientMockData.lastConstructorArguments[0]).toBe(expectedSession); + }); + + it(`Detox should use session defined per configuration - release`, async () => { + mockCommandLineArgs({configuration: 'ios.sim.release'}); + Detox = require('./Detox'); + detox = new Detox(schemes.sessionPerConfiguration); + await detox.init(); + + let expectedSession = schemes.sessionPerConfiguration.configurations['ios.sim.release'].session; + expect(clientMockData.lastConstructorArguments[0]).toBe(expectedSession); + }); + + it(`Detox should prefer session defined per configuration over common session`, async () => { + Detox = require('./Detox'); + detox = new Detox(schemes.sessionInCommonAndInConfiguration); + await detox.init(); + + let expectedSession = schemes.sessionInCommonAndInConfiguration.configurations['ios.sim.none'].session; + expect(clientMockData.lastConstructorArguments[0]).toBe(expectedSession); + }); + function mockCommandLineArgs(args) { minimist.mockReturnValue(args); } diff --git a/detox/src/configurations.mock.js b/detox/src/configurations.mock.js index b7562f45bb..324588f62e 100644 --- a/detox/src/configurations.mock.js +++ b/detox/src/configurations.mock.js @@ -14,7 +14,7 @@ const validOneIosNoneDeviceNoSession = { "binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app", "type": "ios.none", "name": "iPhone 7 Plus, iOS 10.2" - } + }, } }; @@ -101,6 +101,47 @@ const invalidOneDeviceTypeEmulatorNoSession = { } }; +const sessionPerConfiguration = { + "configurations": { + "ios.sim.none": { + "binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app", + "type": "ios.none", + "name": "iPhone 7 Plus, iOS 10.2", + "session": { + "server": "ws://localhost:1111", + "sessionId": "test_1111" + } + }, + "ios.sim.release": { + "binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app", + "type": "ios.none", + "name": "iPhone 7 Plus, iOS 10.2", + "session": { + "server": "ws://localhost:2222", + "sessionId": "test_2222" + } + } + } +}; + +const sessionInCommonAndInConfiguration = { + "session": { + "server": "ws://localhost:1111", + "sessionId": "test_1" + }, + "configurations": { + "ios.sim.none": { + "binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app", + "type": "ios.none", + "name": "iPhone 7 Plus, iOS 10.2", + "session": { + "server": "ws://localhost:2222", + "sessionId": "test_2" + } + } + } +}; + module.exports = { validOneDeviceNoSession, validOneIosNoneDeviceNoSession, @@ -112,5 +153,7 @@ module.exports = { validOneDeviceAndSession, invalidSessionNoSessionId, invalidSessionNoServer, - invalidOneDeviceTypeEmulatorNoSession + invalidOneDeviceTypeEmulatorNoSession, + sessionPerConfiguration, + sessionInCommonAndInConfiguration }; diff --git a/detox/test/package.json b/detox/test/package.json index 5c345605c9..a1a66a518b 100644 --- a/detox/test/package.json +++ b/detox/test/package.json @@ -41,8 +41,12 @@ }, "ios.none": { "type": "ios.none", - "name": "iPhone 7 Plus" - } + "name": "iPhone 7 Plus", + "session": { + "server": "ws://localhost:8099", + "sessionId": "test" + } + } } } }