Skip to content

Commit

Permalink
feat: add available presets
Browse files Browse the repository at this point in the history
  • Loading branch information
vanilla-wave committed Aug 16, 2023
1 parent cd410e3 commit 4eb2809
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 118 deletions.
39 changes: 31 additions & 8 deletions src/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {createLogger} from './logger';
type Listener = () => void;

let instanceCounter = 0;
const defaultBaseState = {
const defaultBaseState: BaseState = {
availablePresets: [],
activePresets: [],
suggestedPresets: [],
wizardState: 'visible' as const,
Expand Down Expand Up @@ -259,22 +260,18 @@ export class Controller<HintParams, Presets extends string, Steps extends string
this.logger.debug('Add new preset', preset);

this.options.hooks?.onAddPreset?.({preset});
this.options.config.presets[preset]?.hooks?.onStart?.();

if (!this.options.config.presets[preset]) {
this.logger.error('No preset in config', preset);
return;
}

if (this.state.base.activePresets.includes(preset)) {
if (this.state.base.availablePresets.includes(preset)) {
return;
}

this.state.base.activePresets.push(preset);
this.state.base.suggestedPresets.push(preset);
this.state.base.availablePresets.push(preset);
await this.updateBaseState();

this.checkReachedHints();
};

suggestPresetOnce = async (preset: Presets) => {
Expand All @@ -286,7 +283,33 @@ export class Controller<HintParams, Presets extends string, Steps extends string
}

await this.setWizardState('visible');
await this.addPreset(preset);
await this.runPreset(preset);
};

runPreset = async (preset: Presets) => {
this.logger.debug('Run preset', preset);

this.options.hooks?.onRunPreset?.({preset});
this.options.config.presets[preset]?.hooks?.onStart?.();

if (!this.options.config.presets[preset]) {
this.logger.error('No preset in config', preset);
return;
}

if (!this.state.base.availablePresets.includes(preset)) {
this.state.base.availablePresets.push(preset);
}

if (this.state.base.activePresets.includes(preset)) {
return;
}

this.state.base.activePresets.push(preset);
this.state.base.suggestedPresets.push(preset);
await this.updateBaseState();

this.checkReachedHints();
};

finishPreset = async (preset: Presets, shouldSave = true) => {
Expand Down
49 changes: 2 additions & 47 deletions src/tests/controller.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import {Controller} from '../controller';
import {getAnchorElement, getOptions} from './utils';
import {getAnchorElement, getOptions, getOptionsWithHooks} from './utils';

describe('hooks', function () {
const getOptionsWithHooks = (...args: Parameters<typeof getOptions>) => ({
...getOptions(...args),
hooks: {
onShowHint: jest.fn(),
onStepPass: jest.fn(),
onAddPreset: jest.fn(),
onFinishPreset: jest.fn(),
},
});

it('reachElement -> onShowHint called', async function () {
const options = getOptionsWithHooks();
const controller = new Controller(options);
Expand Down Expand Up @@ -97,42 +87,7 @@ describe('hooks', function () {
});
});

it('add preset -> calls onAddPreset', async function () {
const options = getOptionsWithHooks();

const controller = new Controller(options);
await controller.addPreset('createQueue');

expect(options.hooks.onAddPreset).toHaveBeenCalledWith({
preset: 'createQueue',
});
});

describe('preset hooks', function () {
it('start preset -> calls onStart', async function () {
const options = getOptions();
const mock = jest.fn();
// @ts-ignore
options.config.presets.createQueue.hooks = {onStart: mock};

const controller = new Controller(options);
await controller.addPreset('createQueue');

expect(mock).toHaveBeenCalled();
});

it('finish preset -> calls enEnd', async function () {
const options = getOptions();
const mock = jest.fn();
// @ts-ignore
options.config.presets.createProject.hooks = {onEnd: mock};

const controller = new Controller(options);
await controller.finishPreset('createProject');

expect(mock).toHaveBeenCalled();
});
});
describe('preset hooks', function () {});
});

describe('store api', function () {
Expand Down
17 changes: 1 addition & 16 deletions src/tests/hints.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {getAnchorElement, getOptions, waitForNextTick} from './utils';
import {getAnchorElement, getOptions} from './utils';
import {Controller} from '../controller';

it('reachElement -> show hint', async function () {
Expand Down Expand Up @@ -91,21 +91,6 @@ it('not active onboarding -> nothing', async function () {
expect(options.showHint).not.toHaveBeenCalled();
});

it('add preset -> show hint for existing element', async function () {
const options = getOptions({activePresets: []});

const controller = new Controller(options);
await controller.stepElementReached({
stepSlug: 'createSprint',
element: getAnchorElement(),
});

await controller.addPreset('createProject');
await waitForNextTick();

await expect(options.showHint).toHaveBeenCalled();
});

describe('close hint', function () {
it('call closeHint -> hint closed', async function () {
const options = getOptions();
Expand Down
194 changes: 147 additions & 47 deletions src/tests/presets.test.ts
Original file line number Diff line number Diff line change
@@ -1,77 +1,177 @@
import {Controller} from '../controller';
import {getOptions} from './utils';
import {getAnchorElement, getOptions, getOptionsWithHooks, waitForNextTick} from './utils';

describe('preset management', function () {
it('add preset -> save base state', async function () {
const options = getOptions();
describe('add preset', function () {
it('add preset -> save base state', async function () {
const options = getOptions();

const controller = new Controller(options);
await controller.addPreset('createQueue');
const controller = new Controller(options);
await controller.addPreset('createQueue');

const newState = options.onSave.state.mock.calls[0][0];
const newState = options.onSave.state.mock.calls[0][0];

expect(newState.activePresets).toEqual(['createProject', 'createQueue']);
expect(newState.suggestedPresets).toEqual(['createProject', 'createQueue']);
});
expect(newState.availablePresets).toEqual(['createProject', 'createQueue']);
});

it('add same preset -> not duplicate', async function () {
const options = getOptions();
it('add same preset -> not duplicate', async function () {
const options = getOptions();

const controller = new Controller(options);
await controller.addPreset('createQueue');
await controller.addPreset('createQueue');
const controller = new Controller(options);
await controller.addPreset('createQueue');
await controller.addPreset('createQueue');

const newState =
options.onSave.state.mock.calls[options.onSave.state.mock.calls.length - 1][0];
const newState =
options.onSave.state.mock.calls[options.onSave.state.mock.calls.length - 1][0];

expect(newState.activePresets).toEqual(['createProject', 'createQueue']);
});
expect(newState.availablePresets).toContain('createQueue');
});

it('preset not from config -> nothing', async function () {
const options = getOptions();
it('preset not from config -> nothing', async function () {
const options = getOptions();

const controller = new Controller(options);
// @ts-ignore
await controller.addPreset('createQueue123');
const controller = new Controller(options);
// @ts-ignore
await controller.addPreset('createQueue123');

expect(options.onSave.state).not.toHaveBeenCalled();
expect(options.onSave.progress).not.toHaveBeenCalled();
});

expect(options.onSave.state).not.toHaveBeenCalled();
expect(options.onSave.progress).not.toHaveBeenCalled();
it('add preset -> calls onAddPreset', async function () {
const options = getOptionsWithHooks();

const controller = new Controller(options);
await controller.addPreset('createQueue');

expect(options.hooks.onAddPreset).toHaveBeenCalledWith({
preset: 'createQueue',
});
});
});

it('finish preset -> add to finished', async function () {
const options = getOptions();
describe('run preset', function () {
let options = getOptions({availablePresets: ['createProject', 'createBoard']});

const controller = new Controller(options);
await controller.finishPreset('createProject');
beforeEach(() => {
options = getOptions({availablePresets: ['createProject', 'createBoard']});
});

const newBaseState = options.onSave.state.mock.calls[0][0];
const newProgressState = options.onSave.progress.mock.calls[0][0];
it('run preset -> adds in active presets', async function () {
const controller = new Controller(options);
await controller.runPreset('createQueue');

expect(newBaseState.activePresets).toEqual([]);
expect(newProgressState.finishedPresets).toEqual(['createProject']);
});
const newState = options.onSave.state.mock.calls[0][0];

it('finish same preset -> not duplicate', async function () {
const options = getOptions();
expect(newState.activePresets).toEqual(['createProject', 'createQueue']);
expect(newState.suggestedPresets).toEqual(['createProject', 'createQueue']);
});

const controller = new Controller(options);
await controller.finishPreset('createProject');
await controller.finishPreset('createProject');
it('run same preset -> not duplicate', async function () {
const controller = new Controller(options);
await controller.runPreset('createQueue');
await controller.runPreset('createQueue');

const newState =
options.onSave.state.mock.calls[options.onSave.state.mock.calls.length - 1][0];

expect(newState.activePresets).toEqual(['createProject', 'createQueue']);
});

it('preset not from config -> nothing', async function () {
const controller = new Controller(options);
// @ts-ignore
await controller.runPreset('createQueue123');

const newProgressState = options.onSave.progress.mock.calls[1][0];
expect(options.onSave.state).not.toHaveBeenCalled();
expect(options.onSave.progress).not.toHaveBeenCalled();
});

expect(newProgressState.finishedPresets).toEqual(['createProject']);
it('start preset -> calls onStart', async function () {
const mock = jest.fn();
// @ts-ignore
options.config.presets.createQueue.hooks = {onStart: mock};

const controller = new Controller(options);
await controller.runPreset('createQueue');

expect(mock).toHaveBeenCalled();
});

it('run preset -> show hint for existing element', async function () {
options.baseState.activePresets = [];

const controller = new Controller(options);
await controller.stepElementReached({
stepSlug: 'createSprint',
element: getAnchorElement(),
});

await controller.runPreset('createProject');
await waitForNextTick();

await expect(options.showHint).toHaveBeenCalled();
});

it('can run unavailable preset', async function () {
const controller = new Controller(options);
await controller.runPreset('createQueue');

const newState = options.onSave.state.mock.calls[0][0];

expect(newState.availablePresets).toContain('createQueue');
expect(newState.activePresets).toContain('createQueue');
});
});

it('finish preset -> stay in suggested', async function () {
const options = getOptions();
describe('finish preset', function () {
it('finish preset -> add to finished', async function () {
const options = getOptions();

const controller = new Controller(options);
await controller.finishPreset('createProject');
const controller = new Controller(options);
await controller.finishPreset('createProject');

const newBaseState = options.onSave.state.mock.calls[0][0];
const newBaseState = options.onSave.state.mock.calls[0][0];
const newProgressState = options.onSave.progress.mock.calls[0][0];

expect(newBaseState.activePresets).toEqual([]);
expect(newProgressState.finishedPresets).toEqual(['createProject']);
});

it('finish same preset -> not duplicate', async function () {
const options = getOptions();

const controller = new Controller(options);
await controller.finishPreset('createProject');
await controller.finishPreset('createProject');

const newProgressState = options.onSave.progress.mock.calls[1][0];

expect(newProgressState.finishedPresets).toEqual(['createProject']);
});

it('finish preset -> calls enEnd', async function () {
const options = getOptions();
const mock = jest.fn();
// @ts-ignore
options.config.presets.createProject.hooks = {onEnd: mock};

const controller = new Controller(options);
await controller.finishPreset('createProject');

expect(mock).toHaveBeenCalled();
});

it('finish preset -> stay in suggested', async function () {
const options = getOptions();

const controller = new Controller(options);
await controller.finishPreset('createProject');

const newBaseState = options.onSave.state.mock.calls[0][0];

expect(newBaseState.suggestedPresets).toEqual(['createProject']);
expect(newBaseState.suggestedPresets).toEqual(['createProject']);
});
});

it('reset preset -> remove progress, remove from finished', async function () {
Expand Down
Loading

0 comments on commit 4eb2809

Please sign in to comment.