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 detect-adb step to the state machine #2833

Merged
merged 4 commits into from
Jun 10, 2020
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
1 change: 0 additions & 1 deletion src/electron/flux/action/android-setup-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Action } from 'common/flux/action';
// So, for example, the 'next' action may represent 'continue', 'str again', or 'start scanning'
export class AndroidSetupActions {
public readonly cancel = new Action<void>();
public readonly close = new Action<void>();
public readonly next = new Action<void>();
public readonly rescan = new Action<void>();
public readonly saveAdbPath = new Action<string>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import {
AndroidSetupStepTransitionCallback,
} from 'electron/flux/types/android-setup-state-machine-types';
import { AndroidSetupStepId } from 'electron/platform/android/setup/android-setup-step-id';
import { createAndroidSetupSteps } from 'electron/platform/android/setup/android-setup-steps-factory';
import { StateMachine } from 'electron/platform/android/setup/state-machine/state-machine';
import { createStateMachineSteps } from 'electron/platform/android/setup/state-machine/state-machine-step-configs';
import { AndroidSetupStepDeps } from './android-setup-step-deps';
import { allAndroidSetupStepConfigs } from './android-setup-steps-configs';
import { StateMachineSteps } from './state-machine/state-machine-steps';

type AndroidSetupStepsFactory = (
Expand All @@ -25,7 +26,7 @@ const stepsFactory = (
stepTransition: stateMachineStepTransition,
};

return createAndroidSetupSteps(allDeps);
return createStateMachineSteps(allDeps, allAndroidSetupStepConfigs);
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
import { AndroidSetupStepId } from './android-setup-step-id';

export type AndroidSetupStepDeps = {
detectAdb: () => Promise<boolean>;
stepTransition: (nextStep: AndroidSetupStepId) => void;
};
37 changes: 37 additions & 0 deletions src/electron/platform/android/setup/android-setup-steps-configs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { AndroidSetupActions } from 'electron/flux/action/android-setup-actions';
import { AndroidSetupStepDeps } from 'electron/platform/android/setup/android-setup-step-deps';
import { AndroidSetupStepId } from 'electron/platform/android/setup/android-setup-step-id';
import {
StateMachineStepConfig,
StateMachineStepConfigs,
} from './state-machine/state-machine-step-configs';
import { detectAdb } from './steps/detect.adb';

export type AndroidSetupStepConfig = StateMachineStepConfig<
AndroidSetupActions,
AndroidSetupStepDeps
>;

type AndroidSetupStepConfigs = StateMachineStepConfigs<
AndroidSetupStepId,
AndroidSetupActions,
AndroidSetupStepDeps
>;

export const allAndroidSetupStepConfigs: AndroidSetupStepConfigs = {
'detect-adb': detectAdb,
'prompt-locate-adb': null,
'prompt-connect-to-device': null,
'detect-devices': null,
'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,
};
36 changes: 0 additions & 36 deletions src/electron/platform/android/setup/android-setup-steps-factory.ts

This file was deleted.

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

import { StateMachineSteps } from 'electron/platform/android/setup/state-machine/state-machine-steps';
import { mapValues } from 'lodash';
import { ActionBag } from './state-machine-action-callback';
import { StateMachineStep } from './state-machine-step';

export type StateMachineStepConfig<ActionT extends ActionBag<ActionT>, DepsT> = (
deps: DepsT,
) => StateMachineStep<ActionT>;

export type StateMachineStepConfigs<
StepIdT extends string,
ActionT extends ActionBag<ActionT>,
DepsT
> = {
[stepId in StepIdT]: StateMachineStepConfig<ActionT, DepsT>;
};

export const createStateMachineSteps = <
StepIdT extends string,
ActionT extends ActionBag<ActionT>,
DepsT
>(
deps: DepsT,
configs: StateMachineStepConfigs<StepIdT, ActionT, DepsT>,
): StateMachineSteps<StepIdT, ActionT> => {
return mapValues(configs, config => config && config(deps));
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ export type StateMachineStep<ActionT extends ActionBag<ActionT>> = {
// eg, 'adb-location-confirmed': (newAdbLocation) => { /* behavior */ }
[actionName in keyof ActionT]?: StateMachineActionCallback<ActionT, actionName>;
};
onEnter?: () => void;
onEnter?: () => Promise<void>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,15 @@ export class StateMachine<StepIdT extends string, ActionT extends ActionBag<Acti
return;
}

this.currentStep = nextStep;

if (this.steps[nextStep].onEnter != null) {
this.steps[nextStep].onEnter();
// exceptions are expected never to be thrown from onEnter.
this.steps[nextStep]
.onEnter()
.catch(error => console.log(`UnExpected error in ${nextStep}.onEnter: ${error}`));
}

this.currentStep = nextStep;

this.stepTransitionCallback(nextStep);
};
}
12 changes: 12 additions & 0 deletions src/electron/platform/android/setup/steps/detect.adb.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 detectAdb: AndroidSetupStepConfig = deps => ({
actions: {},
onEnter: async () => {
const detected = await deps.detectAdb();
deps.stepTransition(detected ? 'detect-devices' : 'prompt-locate-adb');
},
});
3 changes: 2 additions & 1 deletion src/electron/views/renderer-initializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import { createDeviceConfigFetcher } from 'electron/platform/android/device-conf
import { createScanResultsFetcher } from 'electron/platform/android/fetch-scan-results';
import { ScanController } from 'electron/platform/android/scan-controller';
import { createAndroidSetupStateMachineFactory } from 'electron/platform/android/setup/android-setup-state-machine-factory';
import { AndroidSetupStepDeps } from 'electron/platform/android/setup/android-setup-step-deps';
import { createDefaultBuilder } from 'electron/platform/android/unified-result-builder';
import { UnifiedSettingsProvider } from 'electron/settings/unified-settings-provider';
import { defaultAndroidSetupComponents } from 'electron/views/device-connect-view/components/android-setup/default-android-setup-components';
Expand Down Expand Up @@ -188,7 +189,7 @@ getPersistedData(indexedDBInstance, indexedDBDataKeysToFetch).then(

const androidSetupStore = new AndroidSetupStore(
androidSetupActions,
createAndroidSetupStateMachineFactory({}),
createAndroidSetupStateMachineFactory({} as AndroidSetupStepDeps),
);
androidSetupStore.initialize();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ describe('AndroidSetupStore', () => {
store.initialize();

setupActions.cancel.invoke();
setupActions.close.invoke();
setupActions.next.invoke();
setupActions.rescan.invoke();
setupActions.saveAdbPath.invoke('');
Expand Down

This file was deleted.

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

import { Action } from 'common/flux/action';
import { StateMachineStep } from 'electron/platform/android/setup/state-machine/state-machine-step';
import {
createStateMachineSteps,
StateMachineStepConfigs,
} from 'electron/platform/android/setup/state-machine/state-machine-step-configs';
import { StateMachineSteps } from 'electron/platform/android/setup/state-machine/state-machine-steps';

type MartiniStepId = 'gin' | 'vermouth' | 'olives';

class MartiniActions {
public shake = new Action<void>();
public stir = new Action<void>();
}

type MartiniDeps = {
chillGlass: () => string;
};

type MartiniStep = StateMachineStep<MartiniActions>;

describe('state machine step configs', () => {
const martiniDeps = {} as MartiniDeps;

it('calls config functions with expected deps', () => {
const testDeps = deps => {
expect(deps).toBe(martiniDeps);
expect(deps).toEqual(martiniDeps);
return null;
};

const configs: StateMachineStepConfigs<MartiniStepId, MartiniActions, MartiniDeps> = {
gin: deps => testDeps(deps),
vermouth: deps => testDeps(deps),
olives: deps => testDeps(deps),
};

createStateMachineSteps(martiniDeps, configs);
});

it('handles null config functions gracefully', () => {
const expectedSteps: StateMachineSteps<MartiniStepId, MartiniActions> = {
gin: null,
vermouth: null,
olives: null,
};

const configs: StateMachineStepConfigs<MartiniStepId, MartiniActions, MartiniDeps> = {
gin: null,
vermouth: null,
olives: null,
};

let testSteps: StateMachineSteps<MartiniStepId, MartiniActions>;
const testFunc = () => (testSteps = createStateMachineSteps(martiniDeps, configs));
expect(testFunc).not.toThrow();
expect(testSteps).toEqual(expectedSteps);
});

it('returns expected object', () => {
const ginStep: MartiniStep = {
actions: {
shake: null,
},
};

const vermouthStep: MartiniStep = {
actions: {
stir: null,
},
};

const configs: StateMachineStepConfigs<MartiniStepId, MartiniActions, MartiniDeps> = {
gin: _ => ginStep,
vermouth: _ => vermouthStep,
olives: null,
};

const testSteps = createStateMachineSteps(martiniDeps, configs);

expect(testSteps.gin).toBe(ginStep);
expect(testSteps.gin).toEqual(ginStep);

expect(testSteps.vermouth).toBe(vermouthStep);
expect(testSteps.vermouth).toEqual(vermouthStep);
});
});
Loading