Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Session per configuration #173

Merged
merged 3 commits into from
Jun 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 49 additions & 40 deletions detox/src/Detox.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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));
}
}

Expand Down
66 changes: 49 additions & 17 deletions detox/src/Detox.test.js
Original file line number Diff line number Diff line change
@@ -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');
});

Expand Down Expand Up @@ -64,17 +79,15 @@ 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 () => {
Detox = require('./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 () => {
Expand All @@ -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 () => {
Expand Down Expand Up @@ -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);
}
Expand Down
47 changes: 45 additions & 2 deletions detox/src/configurations.mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
},
}
};

Expand Down Expand Up @@ -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,
Expand All @@ -112,5 +153,7 @@ module.exports = {
validOneDeviceAndSession,
invalidSessionNoSessionId,
invalidSessionNoServer,
invalidOneDeviceTypeEmulatorNoSession
invalidOneDeviceTypeEmulatorNoSession,
sessionPerConfiguration,
sessionInCommonAndInConfiguration
};
8 changes: 6 additions & 2 deletions detox/test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@
},
"ios.none": {
"type": "ios.none",
"name": "iPhone 7 Plus"
}
"name": "iPhone 7 Plus",
"session": {
"server": "ws://localhost:8099",
"sessionId": "test"
}
}
}
}
}