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

feat(android-setup): Add most of the remaining state machine steps #2873

Merged
merged 7 commits into from
Jun 15, 2020
20 changes: 13 additions & 7 deletions src/electron/platform/android/setup/android-setup-steps-configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import { AndroidSetupStoreCallbacks } from 'electron/flux/types/android-setup-st
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 { detectPermissions } from 'electron/platform/android/setup/steps/detect-permissions';
import { detectService } from 'electron/platform/android/setup/steps/detect-service';
import { installingService } from 'electron/platform/android/setup/steps/installing-service';
import { promptConnectToDevice } from 'electron/platform/android/setup/steps/prompt-connect-to-device';
import { promptConnectedStartTesting } from 'electron/platform/android/setup/steps/prompt-connected-start-testing';
import { promptGrantPermissions } from 'electron/platform/android/setup/steps/prompt-grant-permissions';
import { promptInstallService } from 'electron/platform/android/setup/steps/prompt-install-service';
import { promptLocateAdb } from 'electron/platform/android/setup/steps/prompt-locate-adb';
import {
StateMachineStepConfig,
Expand All @@ -33,11 +39,11 @@ export const allAndroidSetupStepConfigs: AndroidSetupStepConfigs = {
'prompt-connect-to-device': promptConnectToDevice,
'detect-devices': detectDevices,
'prompt-choose-device': null,
'detect-service': null,
'prompt-install-service': null,
'installing-service': null,
'prompt-install-failed': null,
'detect-permissions': null,
'prompt-grant-permissions': null,
'prompt-connected-start-testing': null,
'detect-service': detectService,
'prompt-install-service': promptInstallService,
'installing-service': installingService,
'prompt-install-failed': promptInstallService,
'detect-permissions': detectPermissions,
'prompt-grant-permissions': promptGrantPermissions,
'prompt-connected-start-testing': promptConnectedStartTesting,
};
14 changes: 14 additions & 0 deletions src/electron/platform/android/setup/steps/detect-permissions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// 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 detectPermissions: AndroidSetupStepConfig = deps => ({
actions: {},
onEnter: async () => {
const detected = await deps.hasExpectedPermissions();
deps.stepTransition(
detected ? 'prompt-connected-start-testing' : 'prompt-grant-permissions',
);
},
});
12 changes: 12 additions & 0 deletions src/electron/platform/android/setup/steps/detect-service.ts
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 detectService: AndroidSetupStepConfig = deps => ({
actions: {},
onEnter: async () => {
const detected = await deps.hasExpectedServiceVersion();
deps.stepTransition(detected ? 'detect-permissions' : 'prompt-install-service');
},
});
16 changes: 16 additions & 0 deletions src/electron/platform/android/setup/steps/installing-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// 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 installingService: AndroidSetupStepConfig = deps => ({
actions: {
cancel: () => {
deps.stepTransition('prompt-install-service');
},
},
onEnter: async () => {
const installed = await deps.installService();
deps.stepTransition(installed ? 'prompt-grant-permissions' : 'prompt-install-failed');
},
});
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 promptConnectedStartTesting: AndroidSetupStepConfig = deps => ({
actions: {
rescan: () => {
deps.stepTransition('detect-adb');
},
},
});
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 promptGrantPermissions: AndroidSetupStepConfig = deps => ({
actions: {
next: () => {
deps.stepTransition('detect-permissions');
},
},
});
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 promptInstallService: AndroidSetupStepConfig = deps => ({
actions: {
next: () => {
deps.stepTransition('installing-service');
},
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

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

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

it('onEnter transitions to prompt-connected-start-testing as expected', async () => {
const p = new Promise<boolean>(resolve => resolve(true));

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

depsMock
.setup(m => m.stepTransition('prompt-connected-start-testing'))
.verifiable(Times.once());

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

depsMock.verifyAll();
});

it('onEnter transitions to prompt-install-service as expected', async () => {
const p = new Promise<boolean>(resolve => resolve(false));

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

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

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

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

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

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

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

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

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

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

depsMock.verifyAll();
});

it('onEnter transitions to prompt-install-service as expected', async () => {
const p = new Promise<boolean>(resolve => resolve(false));

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

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

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

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

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

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

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

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

depsMock.verifyAll();
});

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

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

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

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

depsMock.verifyAll();
});

it('onEnter transitions to prompt-install-service as expected', async () => {
const p = new Promise<boolean>(resolve => resolve(false));

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

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

const step = installingService(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 { promptConnectedStartTesting } from 'electron/platform/android/setup/steps/prompt-connected-start-testing';
import { Mock, MockBehavior, Times } from 'typemoq';
import { checkExpectedActionsAreDefined } from './actions-tester';

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

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

const step = promptConnectedStartTesting(depsMock.object);
step.actions.rescan();

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 { promptGrantPermissions } from 'electron/platform/android/setup/steps/prompt-grant-permissions';
import { Mock, MockBehavior, Times } from 'typemoq';
import { checkExpectedActionsAreDefined } from './actions-tester';

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

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

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

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 { promptInstallService } from 'electron/platform/android/setup/steps/prompt-install-service';
import { Mock, MockBehavior, Times } from 'typemoq';
import { checkExpectedActionsAreDefined } from './actions-tester';

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

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

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

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