Skip to content

Commit

Permalink
feat(android-setup): Create three state machine steps (#2865)
Browse files Browse the repository at this point in the history
* feat(android-setup): Add prompt-locate-adb state machine step

* feat(android-setup): Add prompt-connect-to-device state machine step

* feat(android-setup): Add detect-devices state machine step

* feat(android-setup): Add new step configs to allAndroidSetupStateMachineConfigs
  • Loading branch information
RobGallo authored Jun 12, 2020
1 parent 108bc28 commit 37756d3
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ import { AndroidSetupActions } from 'electron/flux/action/android-setup-actions'
import { AndroidSetupStoreCallbacks } from 'electron/flux/types/android-setup-state-machine-types';
import { AndroidSetupDeps } from 'electron/platform/android/setup/android-setup-deps';
import { AndroidSetupStepId } from 'electron/platform/android/setup/android-setup-step-id';
import { detectDevices } from 'electron/platform/android/setup/steps/detect-devices';
import { promptConnectToDevice } from 'electron/platform/android/setup/steps/prompt-connect-to-device';
import { promptLocateAdb } from 'electron/platform/android/setup/steps/prompt-locate-adb';
import {
StateMachineStepConfig,
StateMachineStepConfigs,
} from './state-machine/state-machine-step-configs';
import { detectAdb } from './steps/detect.adb';
import { detectAdb } from './steps/detect-adb';

export type AndroidSetupStepConfigDeps = AndroidSetupDeps & AndroidSetupStoreCallbacks;

Expand All @@ -26,9 +29,9 @@ type AndroidSetupStepConfigs = StateMachineStepConfigs<

export const allAndroidSetupStepConfigs: AndroidSetupStepConfigs = {
'detect-adb': detectAdb,
'prompt-locate-adb': null,
'prompt-connect-to-device': null,
'detect-devices': null,
'prompt-locate-adb': promptLocateAdb,
'prompt-connect-to-device': promptConnectToDevice,
'detect-devices': detectDevices,
'prompt-choose-device': null,
'detect-service': null,
'prompt-install-service': null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ export const detectAdb: AndroidSetupStepConfig = deps => ({
actions: {},
onEnter: async () => {
const detected = await deps.hasAdbPath();
deps.stepTransition(detected ? 'detect-devices' : 'prompt-locate-adb');
deps.stepTransition(detected ? 'prompt-connect-to-device' : 'prompt-locate-adb');
},
});
33 changes: 33 additions & 0 deletions src/electron/platform/android/setup/steps/detect-devices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { AndroidSetupStepConfig } from 'electron/platform/android/setup/android-setup-steps-configs';

export const detectDevices: AndroidSetupStepConfig = deps => {
return {
actions: {
cancel: () => {
deps.stepTransition('prompt-connect-to-device');
},
},
onEnter: async () => {
const devices = await deps.getDevices();

switch (devices.length) {
case 0: {
deps.stepTransition('prompt-connect-to-device');
break;
}
case 1: {
deps.setSelectedDeviceId(devices[0].id);
deps.stepTransition('detect-service');
break;
}
default: {
deps.stepTransition('prompt-choose-device');
break;
}
}
},
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { AndroidSetupStepConfig } from 'electron/platform/android/setup/android-setup-steps-configs';

export const promptConnectToDevice: AndroidSetupStepConfig = deps => {
return {
actions: {
next: () => deps.stepTransition('detect-devices'),
},
};
};
15 changes: 15 additions & 0 deletions src/electron/platform/android/setup/steps/prompt-locate-adb.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { AndroidSetupStepConfig } from 'electron/platform/android/setup/android-setup-steps-configs';

export const promptLocateAdb: AndroidSetupStepConfig = deps => {
return {
actions: {
saveAdbPath: (path: string) => {
deps.setAdbPath(path);
deps.stepTransition('prompt-connect-to-device');
},
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the MIT License.

import { AndroidSetupStepConfigDeps } from 'electron/platform/android/setup/android-setup-steps-configs';
import { detectAdb } from 'electron/platform/android/setup/steps/detect.adb';
import { detectAdb } from 'electron/platform/android/setup/steps/detect-adb';
import { Mock, MockBehavior, Times } from 'typemoq';
import { checkExpectedActionsAreDefined } from './actions-tester';

Expand All @@ -14,7 +14,7 @@ describe('Android setup step: detectAdb', () => {
expect(step.onEnter).toBeDefined();
});

it('onEnter transitions to detect-devices as expected', async () => {
it('onEnter transitions to prompt-connect-to-device as expected', async () => {
const p = new Promise<boolean>(resolve => resolve(true));

const depsMock = Mock.ofType<AndroidSetupStepConfigDeps>(undefined, MockBehavior.Strict);
Expand All @@ -23,7 +23,7 @@ describe('Android setup step: detectAdb', () => {
.returns(_ => p)
.verifiable(Times.once());

depsMock.setup(m => m.stepTransition('detect-devices')).verifiable(Times.once());
depsMock.setup(m => m.stepTransition('prompt-connect-to-device')).verifiable(Times.once());

const step = detectAdb(depsMock.object);
await step.onEnter();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { DeviceInfo } from 'electron/platform/android/android-service-configurator';
import { AndroidSetupStepConfigDeps } from 'electron/platform/android/setup/android-setup-steps-configs';
import { detectDevices } from 'electron/platform/android/setup/steps/detect-devices';
import { Mock, MockBehavior, Times } from 'typemoq';
import { checkExpectedActionsAreDefined } from './actions-tester';

describe('Android setup step: detectDevices', () => {
it('has expected properties', () => {
const deps = {} as AndroidSetupStepConfigDeps;
const step = detectDevices(deps);
checkExpectedActionsAreDefined(step, ['cancel']);
expect(step.onEnter).toBeDefined();
});

it('cancel transitions to prompt-connect-to-device as expected', () => {
const depsMock = Mock.ofType<AndroidSetupStepConfigDeps>(undefined, MockBehavior.Strict);
depsMock.setup(m => m.stepTransition('prompt-connect-to-device')).verifiable(Times.once());

const step = detectDevices(depsMock.object);
step.actions.cancel();

depsMock.verifyAll();
});

it('onEnter transitions to prompt-connect-to-device as expected', async () => {
const devices: DeviceInfo[] = [];
const p = new Promise<DeviceInfo[]>(resolve => resolve(devices));

const depsMock = Mock.ofType<AndroidSetupStepConfigDeps>(undefined, MockBehavior.Strict);
depsMock
.setup(m => m.getDevices())
.returns(_ => p)
.verifiable(Times.once());

depsMock.setup(m => m.stepTransition('prompt-connect-to-device')).verifiable(Times.once());

const step = detectDevices(depsMock.object);
await step.onEnter();

depsMock.verifyAll();
});

it('onEnter transitions to detect-service as expected', async () => {
const devices: DeviceInfo[] = [
{
id: 'device1',
} as DeviceInfo,
];

const p = new Promise<DeviceInfo[]>(resolve => resolve(devices));

const depsMock = Mock.ofType<AndroidSetupStepConfigDeps>(undefined, MockBehavior.Strict);
depsMock
.setup(m => m.getDevices())
.returns(_ => p)
.verifiable(Times.once());

depsMock.setup(m => m.stepTransition('detect-service')).verifiable(Times.once());
depsMock.setup(m => m.setSelectedDeviceId('device1')).verifiable(Times.once());

const step = detectDevices(depsMock.object);
await step.onEnter();

depsMock.verifyAll();
});

it('onEnter transitions to prompt-choose-device as expected', async () => {
const devices: DeviceInfo[] = [
{
id: 'device1',
} as DeviceInfo,
{
id: 'device2',
} as DeviceInfo,
];

const p = new Promise<DeviceInfo[]>(resolve => resolve(devices));

const depsMock = Mock.ofType<AndroidSetupStepConfigDeps>(undefined, MockBehavior.Strict);
depsMock
.setup(m => m.getDevices())
.returns(_ => p)
.verifiable(Times.once());

depsMock.setup(m => m.stepTransition('prompt-choose-device')).verifiable(Times.once());

const step = detectDevices(depsMock.object);
await step.onEnter();

depsMock.verifyAll();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { AndroidSetupStepConfigDeps } from 'electron/platform/android/setup/android-setup-steps-configs';
import { promptConnectToDevice } from 'electron/platform/android/setup/steps/prompt-connect-to-device';
import { Mock, MockBehavior, Times } from 'typemoq';
import { checkExpectedActionsAreDefined } from './actions-tester';

describe('Android setup step: promptConnectToDevice', () => {
it('has expected properties', () => {
const deps = {} as AndroidSetupStepConfigDeps;
const step = promptConnectToDevice(deps);
checkExpectedActionsAreDefined(step, ['next']);
expect(step.onEnter).not.toBeDefined();
});

it('next transitions to detect-devices as expected', () => {
const depsMock = Mock.ofType<AndroidSetupStepConfigDeps>(undefined, MockBehavior.Strict);
depsMock.setup(m => m.stepTransition('detect-devices')).verifiable(Times.once());

const step = promptConnectToDevice(depsMock.object);
step.actions.next();

depsMock.verifyAll();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { AndroidSetupStepConfigDeps } from 'electron/platform/android/setup/android-setup-steps-configs';
import { promptLocateAdb } from 'electron/platform/android/setup/steps/prompt-locate-adb';
import { Mock, MockBehavior, Times } from 'typemoq';
import { checkExpectedActionsAreDefined } from './actions-tester';

describe('Android setup step: promptLocateAdb', () => {
it('has expected properties', () => {
const deps = {} as AndroidSetupStepConfigDeps;
const step = promptLocateAdb(deps);
checkExpectedActionsAreDefined(step, ['saveAdbPath']);
expect(step.onEnter).not.toBeDefined();
});

it('saveAdbPath transitions to prompt-connect-to-device as expected', () => {
const testPath = 'my test path';

const depsMock = Mock.ofType<AndroidSetupStepConfigDeps>(undefined, MockBehavior.Strict);
depsMock.setup(m => m.setAdbPath(testPath)).verifiable(Times.once());
depsMock.setup(m => m.stepTransition('prompt-connect-to-device')).verifiable(Times.once());

const step = promptLocateAdb(depsMock.object);
step.actions.saveAdbPath(testPath);

depsMock.verifyAll();
});
});

0 comments on commit 37756d3

Please sign in to comment.