@vnejs/plugins.scenario.point_and_click 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +10 -2
- package/dist/modules/emit.d.ts +9 -0
- package/dist/modules/emit.js +27 -0
- package/dist/modules/logs.d.ts +12 -0
- package/dist/modules/logs.js +19 -0
- package/dist/modules/option.d.ts +8 -0
- package/dist/modules/option.js +17 -0
- package/dist/modules/point_and_click.d.ts +3 -6
- package/dist/modules/point_and_click.js +5 -48
- package/dist/modules/scenario.module.js +1 -1
- package/dist/modules/skip.d.ts +7 -0
- package/dist/modules/skip.js +20 -0
- package/package.json +1 -1
- package/src/index.ts +10 -2
- package/src/modules/emit.ts +47 -0
- package/src/modules/logs.ts +32 -0
- package/src/modules/option.ts +31 -0
- package/src/modules/point_and_click.ts +6 -74
- package/src/modules/scenario.module.ts +1 -1
- package/src/modules/skip.ts +35 -0
- package/src/tests/logs.test.ts +77 -0
- package/src/tests/point_and_click.test.ts +41 -21
- package/src/tests/setup.ts +28 -2
package/dist/index.js
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import "@vnejs/contracts.scenario.point_and_click";
|
|
2
2
|
import { regPlugin } from "@vnejs/shared";
|
|
3
3
|
import { CONSTANTS, PARAMS, PLUGIN_NAME, SUBSCRIBE_EVENTS } from "@vnejs/contracts.scenario.point_and_click";
|
|
4
|
-
import {
|
|
4
|
+
import { PointAndClickEmit } from "./modules/emit.js";
|
|
5
5
|
import { PointAndClickExec } from "./modules/exec.js";
|
|
6
|
+
import { PointAndClickLogs } from "./modules/logs.js";
|
|
7
|
+
import { PointAndClickOption } from "./modules/option.js";
|
|
8
|
+
import { PointAndClickState } from "./modules/point_and_click.js";
|
|
6
9
|
import { PointAndClickScenario } from "./modules/scenario.block.js";
|
|
7
10
|
import { PointAndClickScenarioModule } from "./modules/scenario.module.js";
|
|
8
11
|
import { PointAndClickScenarioOption } from "./modules/scenario.option.js";
|
|
12
|
+
import { PointAndClickSkip } from "./modules/skip.js";
|
|
9
13
|
regPlugin(PLUGIN_NAME, { constants: CONSTANTS, events: SUBSCRIBE_EVENTS, params: PARAMS }, [
|
|
10
|
-
|
|
14
|
+
PointAndClickState,
|
|
15
|
+
PointAndClickEmit,
|
|
16
|
+
PointAndClickOption,
|
|
17
|
+
PointAndClickSkip,
|
|
18
|
+
PointAndClickLogs,
|
|
11
19
|
PointAndClickExec,
|
|
12
20
|
PointAndClickScenario,
|
|
13
21
|
PointAndClickScenarioModule,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ModuleCore } from "@vnejs/module.core";
|
|
2
|
+
import type { PointAndClickPluginConstants, PointAndClickPluginEvents, PointAndClickPluginParams, PointAndClickPluginSettings } from "../types.js";
|
|
3
|
+
import type { PointAndClickEmitPayload, PointAndClickOption } from "../utils/point-and-click.js";
|
|
4
|
+
export declare class PointAndClickEmit extends ModuleCore<PointAndClickPluginEvents, PointAndClickPluginConstants, PointAndClickPluginSettings, PointAndClickPluginParams> {
|
|
5
|
+
name: string;
|
|
6
|
+
subscribe: () => void;
|
|
7
|
+
onEmit: ({ options, args }?: PointAndClickEmitPayload) => Promise<unknown[] | undefined>;
|
|
8
|
+
mapOptions: ({ optionLine: { line, args }, index }: NonNullable<PointAndClickEmitPayload["options"]>[number]) => Promise<PointAndClickOption>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { splitLineKeywords, tokenizeExecLine } from "@vnejs/helpers";
|
|
2
|
+
import { ModuleCore } from "@vnejs/module.core";
|
|
3
|
+
export class PointAndClickEmit extends ModuleCore {
|
|
4
|
+
name = "point_and_click.emit";
|
|
5
|
+
subscribe = () => {
|
|
6
|
+
this.on(this.EVENTS.POINT_AND_CLICK.EMIT, this.onEmit);
|
|
7
|
+
};
|
|
8
|
+
onEmit = async ({ options = [], args = {} } = {}) => {
|
|
9
|
+
const mappedOptions = await Promise.all(options.map(this.mapOptions));
|
|
10
|
+
if (!mappedOptions.length || mappedOptions.every((option) => option.hided)) {
|
|
11
|
+
return this.emit(this.EVENTS.POINT_AND_CLICK.SKIP);
|
|
12
|
+
}
|
|
13
|
+
await this.emit(this.EVENTS.POINT_AND_CLICK.STATE_UPDATE, { isShow: true, options: mappedOptions, args });
|
|
14
|
+
return this.emit(this.EVENTS.POINT_AND_CLICK.SHOW);
|
|
15
|
+
};
|
|
16
|
+
mapOptions = async ({ optionLine: { line = "", args = {} }, index }) => {
|
|
17
|
+
const [, , icon, x, y] = tokenizeExecLine(line).map(String);
|
|
18
|
+
const result = { index, coords: [x, y].map(Number), icon, ...args };
|
|
19
|
+
await Promise.all(Object.keys(args).map(async (key) => {
|
|
20
|
+
if (typeof args[key] !== "string" || !args[key].startsWith(this.CONST.SCENARIO.LINE_PREFIXES.MODULE))
|
|
21
|
+
return;
|
|
22
|
+
const { line: execLine = "", module = "", keywords = [] } = splitLineKeywords(String(args[key]));
|
|
23
|
+
result[key] = await this.emitOne(this.EVENTS.POINT_AND_CLICK.EXEC_GET, { line: execLine, module, keywords });
|
|
24
|
+
}));
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ModuleCore } from "@vnejs/module.core";
|
|
2
|
+
import type { PointAndClickPluginConstants, PointAndClickPluginEvents, PointAndClickPluginParams, PointAndClickPluginSettings } from "../types.js";
|
|
3
|
+
import type { PointAndClickEmitPayload, PointAndClickOptionPayload } from "../utils/point-and-click.js";
|
|
4
|
+
export declare class PointAndClickLogs extends ModuleCore<PointAndClickPluginEvents, PointAndClickPluginConstants, PointAndClickPluginSettings, PointAndClickPluginParams> {
|
|
5
|
+
name: string;
|
|
6
|
+
subscribe: () => void;
|
|
7
|
+
onEmit: ({ options, args }?: PointAndClickEmitPayload) => undefined;
|
|
8
|
+
onOption: ({ index }?: PointAndClickOptionPayload) => undefined;
|
|
9
|
+
onSkip: () => void;
|
|
10
|
+
onShow: () => undefined;
|
|
11
|
+
onHide: () => undefined;
|
|
12
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ModuleCore } from "@vnejs/module.core";
|
|
2
|
+
export class PointAndClickLogs extends ModuleCore {
|
|
3
|
+
name = "point_and_click.logs";
|
|
4
|
+
subscribe = () => {
|
|
5
|
+
this.on(this.EVENTS.POINT_AND_CLICK.EMIT, this.onEmit, this.CONST.LOGS.FILTER_FROM_RESULT_OPTIONS);
|
|
6
|
+
this.on(this.EVENTS.POINT_AND_CLICK.OPTION, this.onOption, this.CONST.LOGS.FILTER_FROM_RESULT_OPTIONS);
|
|
7
|
+
this.on(this.EVENTS.POINT_AND_CLICK.SKIP, this.onSkip, this.CONST.LOGS.FILTER_FROM_RESULT_OPTIONS);
|
|
8
|
+
this.on(this.EVENTS.POINT_AND_CLICK.SHOW, this.onShow, this.CONST.LOGS.FILTER_FROM_RESULT_OPTIONS);
|
|
9
|
+
this.on(this.EVENTS.POINT_AND_CLICK.HIDE, this.onHide, this.CONST.LOGS.FILTER_FROM_RESULT_OPTIONS);
|
|
10
|
+
};
|
|
11
|
+
onEmit = ({ options = [], args = {} } = {}) => void this.emitLog({ action: this.CONST.POINT_AND_CLICK.LOGS_ACTIONS.EMIT, options, args });
|
|
12
|
+
onOption = ({ index = 0 } = {}) => void this.emitLog({ action: this.CONST.POINT_AND_CLICK.LOGS_ACTIONS.OPTION, index });
|
|
13
|
+
onSkip = () => {
|
|
14
|
+
const { curLine = 0, label } = this.globalState.scenario;
|
|
15
|
+
void this.emitLog({ action: this.CONST.POINT_AND_CLICK.LOGS_ACTIONS.SKIP, label, from: curLine });
|
|
16
|
+
};
|
|
17
|
+
onShow = () => void this.emitLog({ action: this.CONST.POINT_AND_CLICK.LOGS_ACTIONS.SHOW });
|
|
18
|
+
onHide = () => void this.emitLog({ action: this.CONST.POINT_AND_CLICK.LOGS_ACTIONS.HIDE });
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ModuleCore } from "@vnejs/module.core";
|
|
2
|
+
import type { PointAndClickPluginConstants, PointAndClickPluginEvents, PointAndClickPluginParams, PointAndClickPluginSettings } from "../types.js";
|
|
3
|
+
import type { PointAndClickOptionPayload } from "../utils/point-and-click.js";
|
|
4
|
+
export declare class PointAndClickOption extends ModuleCore<PointAndClickPluginEvents, PointAndClickPluginConstants, PointAndClickPluginSettings, PointAndClickPluginParams> {
|
|
5
|
+
name: string;
|
|
6
|
+
subscribe: () => void;
|
|
7
|
+
onOption: ({ index }?: PointAndClickOptionPayload) => Promise<void>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ModuleCore } from "@vnejs/module.core";
|
|
2
|
+
export class PointAndClickOption extends ModuleCore {
|
|
3
|
+
name = "point_and_click.option";
|
|
4
|
+
subscribe = () => {
|
|
5
|
+
this.on(this.EVENTS.POINT_AND_CLICK.OPTION, this.onOption);
|
|
6
|
+
};
|
|
7
|
+
onOption = async ({ index = 0 } = {}) => {
|
|
8
|
+
await this.emit(this.EVENTS.POINT_AND_CLICK.HIDE);
|
|
9
|
+
this.globalState.scenario.curLine = this.globalState.point_and_click.options[index].index + 1;
|
|
10
|
+
await this.emit(this.EVENTS.POINT_AND_CLICK.STATE_UPDATE, {
|
|
11
|
+
options: [],
|
|
12
|
+
args: {},
|
|
13
|
+
isShow: false,
|
|
14
|
+
});
|
|
15
|
+
this.emitNext();
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { ModuleCore, type ModuleGlobalStateRegistry } from "@vnejs/module.core";
|
|
2
2
|
import type { PointAndClickPluginConstants, PointAndClickPluginEvents, PointAndClickPluginParams, PointAndClickPluginSettings } from "../types.js";
|
|
3
|
-
import type {
|
|
4
|
-
export declare class
|
|
3
|
+
import type { PointAndClickPluginModelState } from "../utils/point-and-click.js";
|
|
4
|
+
export declare class PointAndClickState extends ModuleCore<PointAndClickPluginEvents, PointAndClickPluginConstants, PointAndClickPluginSettings, PointAndClickPluginParams, PointAndClickPluginModelState> {
|
|
5
5
|
name: string;
|
|
6
6
|
subscribe: () => void;
|
|
7
|
-
|
|
8
|
-
onSkip: () => Promise<undefined>;
|
|
9
|
-
onOption: ({ index }?: PointAndClickOptionPayload) => Promise<void>;
|
|
7
|
+
onStateUpdate: (state?: Partial<PointAndClickPluginModelState>) => void;
|
|
10
8
|
onStateSet: (payload: ModuleGlobalStateRegistry) => Promise<unknown[] | undefined>;
|
|
11
9
|
onStateClear: () => Promise<unknown[]> | undefined;
|
|
12
|
-
mapOptions: ({ optionLine: { line, args }, index }: NonNullable<PointAndClickEmitPayload["options"]>[number]) => Promise<PointAndClickOption>;
|
|
13
10
|
getDefaultState: () => PointAndClickPluginModelState;
|
|
14
11
|
}
|
|
@@ -1,65 +1,22 @@
|
|
|
1
|
-
import { splitLineKeywords, tokenizeExecLine } from "@vnejs/helpers";
|
|
2
1
|
import { ModuleCore } from "@vnejs/module.core";
|
|
3
|
-
export class
|
|
2
|
+
export class PointAndClickState extends ModuleCore {
|
|
4
3
|
name = "point_and_click";
|
|
5
4
|
subscribe = () => {
|
|
6
|
-
this.on(this.EVENTS.POINT_AND_CLICK.
|
|
7
|
-
this.on(this.EVENTS.POINT_AND_CLICK.OPTION, this.onOption);
|
|
8
|
-
this.on(this.EVENTS.POINT_AND_CLICK.SKIP, this.onSkip);
|
|
5
|
+
this.on(this.EVENTS.POINT_AND_CLICK.STATE_UPDATE, this.onStateUpdate);
|
|
9
6
|
this.on(this.EVENTS.STATE.SET, this.onStateSet);
|
|
10
7
|
this.on(this.EVENTS.STATE.CLEAR, this.onStateClear);
|
|
11
8
|
};
|
|
12
|
-
|
|
13
|
-
this.emitLog({ action: "emit", options, args });
|
|
14
|
-
const mappedOptions = await Promise.all(options.map(this.mapOptions));
|
|
15
|
-
if (!mappedOptions.length || mappedOptions.every((option) => option.hided)) {
|
|
16
|
-
return this.emit(this.EVENTS.POINT_AND_CLICK.SKIP);
|
|
17
|
-
}
|
|
18
|
-
this.updateState({ isShow: true, options: mappedOptions, args });
|
|
19
|
-
return this.emit(this.EVENTS.POINT_AND_CLICK.OPENED);
|
|
20
|
-
};
|
|
21
|
-
onSkip = async () => {
|
|
22
|
-
const { curLine = 0, label } = this.globalState.scenario;
|
|
23
|
-
const lines = (await this.emitOne(this.EVENTS.SCENARIO.LINES_GET, { label }));
|
|
24
|
-
const parentIndent = lines[curLine]?.indent ?? 0;
|
|
25
|
-
let indexShift = 1;
|
|
26
|
-
let curLineObj = lines[curLine + indexShift];
|
|
27
|
-
while (curLineObj && (curLineObj.indent ?? 0) > parentIndent) {
|
|
28
|
-
indexShift++;
|
|
29
|
-
curLineObj = lines[curLine + indexShift];
|
|
30
|
-
}
|
|
31
|
-
this.emitLog({ action: "skip", label, from: curLine, to: curLine + indexShift });
|
|
32
|
-
this.globalState.scenario.curLine = curLine + indexShift;
|
|
33
|
-
return this.emitNext();
|
|
34
|
-
};
|
|
35
|
-
onOption = async ({ index = 0 } = {}) => {
|
|
36
|
-
this.emitLog({ action: "point_and_click", index });
|
|
37
|
-
await this.emit(this.EVENTS.POINT_AND_CLICK.CLOSED);
|
|
38
|
-
this.globalState.scenario.curLine = this.state.options[index].index + 1;
|
|
39
|
-
this.setDefaultState();
|
|
40
|
-
this.emitNext();
|
|
41
|
-
};
|
|
9
|
+
onStateUpdate = (state = {}) => this.updateState(state);
|
|
42
10
|
onStateSet = async (payload) => {
|
|
43
11
|
const moduleState = this.getStateSlice(payload);
|
|
44
12
|
if (!moduleState || this.state.isShow === moduleState.isShow)
|
|
45
13
|
return;
|
|
46
14
|
const clonedState = await this.emitClone(moduleState);
|
|
47
15
|
this.setState(clonedState);
|
|
48
|
-
return this.emit(clonedState.isShow ? this.EVENTS.POINT_AND_CLICK.
|
|
16
|
+
return this.emit(clonedState.isShow ? this.EVENTS.POINT_AND_CLICK.SHOW : this.EVENTS.POINT_AND_CLICK.HIDE, {
|
|
49
17
|
isForce: true,
|
|
50
18
|
});
|
|
51
19
|
};
|
|
52
|
-
onStateClear = () => this.emit(this.EVENTS.POINT_AND_CLICK.
|
|
53
|
-
mapOptions = async ({ optionLine: { line = "", args = {} }, index }) => {
|
|
54
|
-
const [, , icon, x, y] = tokenizeExecLine(line).map(String);
|
|
55
|
-
const result = { index, coords: [x, y].map(Number), icon, ...args };
|
|
56
|
-
await Promise.all(Object.keys(args).map(async (key) => {
|
|
57
|
-
if (typeof args[key] !== "string" || !args[key].startsWith(this.CONST.SCENARIO.LINE_PREFIXES.MODULE))
|
|
58
|
-
return;
|
|
59
|
-
const { line: execLine = "", module = "", keywords = [] } = splitLineKeywords(String(args[key]));
|
|
60
|
-
result[key] = await this.emitOne(this.EVENTS.POINT_AND_CLICK.EXEC_GET, { line: execLine, module, keywords });
|
|
61
|
-
}));
|
|
62
|
-
return result;
|
|
63
|
-
};
|
|
20
|
+
onStateClear = () => this.emit(this.EVENTS.POINT_AND_CLICK.HIDE, { isForce: true });
|
|
64
21
|
getDefaultState = () => ({ options: [], args: {}, isShow: false });
|
|
65
22
|
}
|
|
@@ -16,7 +16,7 @@ export class PointAndClickScenarioModule extends ModuleCore {
|
|
|
16
16
|
this.globalState.scenario.curLine = curLine + 1;
|
|
17
17
|
return this.emitNext();
|
|
18
18
|
}
|
|
19
|
-
this.emitLog({ action: this.CONST.POINT_AND_CLICK.
|
|
19
|
+
this.emitLog({ action: this.CONST.POINT_AND_CLICK.LOGS_ACTIONS.REPEAT, label, from: curLine, to: targetIndex });
|
|
20
20
|
this.globalState.scenario.curLine = targetIndex;
|
|
21
21
|
return this.emitNext();
|
|
22
22
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ModuleCore } from "@vnejs/module.core";
|
|
2
|
+
import type { PointAndClickPluginConstants, PointAndClickPluginEvents, PointAndClickPluginParams, PointAndClickPluginSettings } from "../types.js";
|
|
3
|
+
export declare class PointAndClickSkip extends ModuleCore<PointAndClickPluginEvents, PointAndClickPluginConstants, PointAndClickPluginSettings, PointAndClickPluginParams> {
|
|
4
|
+
name: string;
|
|
5
|
+
subscribe: () => void;
|
|
6
|
+
onSkip: () => Promise<undefined>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ModuleCore } from "@vnejs/module.core";
|
|
2
|
+
export class PointAndClickSkip extends ModuleCore {
|
|
3
|
+
name = "point_and_click.skip";
|
|
4
|
+
subscribe = () => {
|
|
5
|
+
this.on(this.EVENTS.POINT_AND_CLICK.SKIP, this.onSkip);
|
|
6
|
+
};
|
|
7
|
+
onSkip = async () => {
|
|
8
|
+
const { curLine = 0, label } = this.globalState.scenario;
|
|
9
|
+
const lines = (await this.emitOne(this.EVENTS.SCENARIO.LINES_GET, { label }));
|
|
10
|
+
const parentIndent = lines[curLine]?.indent ?? 0;
|
|
11
|
+
let indexShift = 1;
|
|
12
|
+
let curLineObj = lines[curLine + indexShift];
|
|
13
|
+
while (curLineObj && (curLineObj.indent ?? 0) > parentIndent) {
|
|
14
|
+
indexShift++;
|
|
15
|
+
curLineObj = lines[curLine + indexShift];
|
|
16
|
+
}
|
|
17
|
+
this.globalState.scenario.curLine = curLine + indexShift;
|
|
18
|
+
return this.emitNext();
|
|
19
|
+
};
|
|
20
|
+
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -3,14 +3,22 @@ import "@vnejs/contracts.scenario.point_and_click";
|
|
|
3
3
|
import { regPlugin } from "@vnejs/shared";
|
|
4
4
|
import { CONSTANTS, PARAMS, PLUGIN_NAME, SUBSCRIBE_EVENTS } from "@vnejs/contracts.scenario.point_and_click";
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { PointAndClickEmit } from "./modules/emit.js";
|
|
7
7
|
import { PointAndClickExec } from "./modules/exec.js";
|
|
8
|
+
import { PointAndClickLogs } from "./modules/logs.js";
|
|
9
|
+
import { PointAndClickOption } from "./modules/option.js";
|
|
10
|
+
import { PointAndClickState } from "./modules/point_and_click.js";
|
|
8
11
|
import { PointAndClickScenario } from "./modules/scenario.block.js";
|
|
9
12
|
import { PointAndClickScenarioModule } from "./modules/scenario.module.js";
|
|
10
13
|
import { PointAndClickScenarioOption } from "./modules/scenario.option.js";
|
|
14
|
+
import { PointAndClickSkip } from "./modules/skip.js";
|
|
11
15
|
|
|
12
16
|
regPlugin(PLUGIN_NAME, { constants: CONSTANTS, events: SUBSCRIBE_EVENTS, params: PARAMS }, [
|
|
13
|
-
|
|
17
|
+
PointAndClickState,
|
|
18
|
+
PointAndClickEmit,
|
|
19
|
+
PointAndClickOption,
|
|
20
|
+
PointAndClickSkip,
|
|
21
|
+
PointAndClickLogs,
|
|
14
22
|
PointAndClickExec,
|
|
15
23
|
PointAndClickScenario,
|
|
16
24
|
PointAndClickScenarioModule,
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { splitLineKeywords, tokenizeExecLine } from "@vnejs/helpers";
|
|
2
|
+
import { ModuleCore } from "@vnejs/module.core";
|
|
3
|
+
|
|
4
|
+
import type { PointAndClickPluginConstants, PointAndClickPluginEvents, PointAndClickPluginParams, PointAndClickPluginSettings } from "../types.js";
|
|
5
|
+
import type { PointAndClickEmitPayload, PointAndClickExecGetPayload, PointAndClickOption, PointAndClickPluginModelState } from "../utils/point-and-click.js";
|
|
6
|
+
|
|
7
|
+
export class PointAndClickEmit extends ModuleCore<
|
|
8
|
+
PointAndClickPluginEvents,
|
|
9
|
+
PointAndClickPluginConstants,
|
|
10
|
+
PointAndClickPluginSettings,
|
|
11
|
+
PointAndClickPluginParams
|
|
12
|
+
> {
|
|
13
|
+
name = "point_and_click.emit";
|
|
14
|
+
|
|
15
|
+
subscribe = () => {
|
|
16
|
+
this.on(this.EVENTS.POINT_AND_CLICK.EMIT, this.onEmit);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
onEmit = async ({ options = [], args = {} }: PointAndClickEmitPayload = {}) => {
|
|
20
|
+
const mappedOptions = await Promise.all(options.map(this.mapOptions));
|
|
21
|
+
|
|
22
|
+
if (!mappedOptions.length || mappedOptions.every((option) => option.hided)) {
|
|
23
|
+
return this.emit(this.EVENTS.POINT_AND_CLICK.SKIP);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
await this.emit(this.EVENTS.POINT_AND_CLICK.STATE_UPDATE, { isShow: true, options: mappedOptions, args } satisfies Partial<PointAndClickPluginModelState>);
|
|
27
|
+
|
|
28
|
+
return this.emit(this.EVENTS.POINT_AND_CLICK.SHOW);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
mapOptions = async ({ optionLine: { line = "", args = {} }, index }: NonNullable<PointAndClickEmitPayload["options"]>[number]) => {
|
|
32
|
+
const [, , icon, x, y] = tokenizeExecLine(line).map(String);
|
|
33
|
+
const result: PointAndClickOption = { index, coords: [x, y].map(Number), icon, ...args };
|
|
34
|
+
|
|
35
|
+
await Promise.all(
|
|
36
|
+
Object.keys(args).map(async (key) => {
|
|
37
|
+
if (typeof args[key] !== "string" || !args[key].startsWith(this.CONST.SCENARIO.LINE_PREFIXES.MODULE)) return;
|
|
38
|
+
|
|
39
|
+
const { line: execLine = "", module = "", keywords = [] } = splitLineKeywords(String(args[key]));
|
|
40
|
+
|
|
41
|
+
result[key] = await this.emitOne(this.EVENTS.POINT_AND_CLICK.EXEC_GET, { line: execLine, module, keywords } satisfies PointAndClickExecGetPayload);
|
|
42
|
+
}),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ModuleCore } from "@vnejs/module.core";
|
|
2
|
+
|
|
3
|
+
import type { PointAndClickPluginConstants, PointAndClickPluginEvents, PointAndClickPluginParams, PointAndClickPluginSettings } from "../types.js";
|
|
4
|
+
import type { PointAndClickEmitPayload, PointAndClickOptionPayload } from "../utils/point-and-click.js";
|
|
5
|
+
|
|
6
|
+
export class PointAndClickLogs extends ModuleCore<
|
|
7
|
+
PointAndClickPluginEvents,
|
|
8
|
+
PointAndClickPluginConstants,
|
|
9
|
+
PointAndClickPluginSettings,
|
|
10
|
+
PointAndClickPluginParams
|
|
11
|
+
> {
|
|
12
|
+
name = "point_and_click.logs";
|
|
13
|
+
|
|
14
|
+
subscribe = () => {
|
|
15
|
+
this.on(this.EVENTS.POINT_AND_CLICK.EMIT, this.onEmit, this.CONST.LOGS.FILTER_FROM_RESULT_OPTIONS);
|
|
16
|
+
this.on(this.EVENTS.POINT_AND_CLICK.OPTION, this.onOption, this.CONST.LOGS.FILTER_FROM_RESULT_OPTIONS);
|
|
17
|
+
this.on(this.EVENTS.POINT_AND_CLICK.SKIP, this.onSkip, this.CONST.LOGS.FILTER_FROM_RESULT_OPTIONS);
|
|
18
|
+
this.on(this.EVENTS.POINT_AND_CLICK.SHOW, this.onShow, this.CONST.LOGS.FILTER_FROM_RESULT_OPTIONS);
|
|
19
|
+
this.on(this.EVENTS.POINT_AND_CLICK.HIDE, this.onHide, this.CONST.LOGS.FILTER_FROM_RESULT_OPTIONS);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
onEmit = ({ options = [], args = {} }: PointAndClickEmitPayload = {}) =>
|
|
23
|
+
void this.emitLog({ action: this.CONST.POINT_AND_CLICK.LOGS_ACTIONS.EMIT, options, args });
|
|
24
|
+
onOption = ({ index = 0 }: PointAndClickOptionPayload = {}) => void this.emitLog({ action: this.CONST.POINT_AND_CLICK.LOGS_ACTIONS.OPTION, index });
|
|
25
|
+
onSkip = () => {
|
|
26
|
+
const { curLine = 0, label } = this.globalState.scenario;
|
|
27
|
+
|
|
28
|
+
void this.emitLog({ action: this.CONST.POINT_AND_CLICK.LOGS_ACTIONS.SKIP, label, from: curLine });
|
|
29
|
+
};
|
|
30
|
+
onShow = () => void this.emitLog({ action: this.CONST.POINT_AND_CLICK.LOGS_ACTIONS.SHOW });
|
|
31
|
+
onHide = () => void this.emitLog({ action: this.CONST.POINT_AND_CLICK.LOGS_ACTIONS.HIDE });
|
|
32
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ModuleCore } from "@vnejs/module.core";
|
|
2
|
+
|
|
3
|
+
import type { PointAndClickPluginConstants, PointAndClickPluginEvents, PointAndClickPluginParams, PointAndClickPluginSettings } from "../types.js";
|
|
4
|
+
import type { PointAndClickOptionPayload, PointAndClickPluginModelState } from "../utils/point-and-click.js";
|
|
5
|
+
|
|
6
|
+
export class PointAndClickOption extends ModuleCore<
|
|
7
|
+
PointAndClickPluginEvents,
|
|
8
|
+
PointAndClickPluginConstants,
|
|
9
|
+
PointAndClickPluginSettings,
|
|
10
|
+
PointAndClickPluginParams
|
|
11
|
+
> {
|
|
12
|
+
name = "point_and_click.option";
|
|
13
|
+
|
|
14
|
+
subscribe = () => {
|
|
15
|
+
this.on(this.EVENTS.POINT_AND_CLICK.OPTION, this.onOption);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
onOption = async ({ index = 0 }: PointAndClickOptionPayload = {}) => {
|
|
19
|
+
await this.emit(this.EVENTS.POINT_AND_CLICK.HIDE);
|
|
20
|
+
|
|
21
|
+
this.globalState.scenario.curLine = this.globalState.point_and_click.options[index].index + 1;
|
|
22
|
+
|
|
23
|
+
await this.emit(this.EVENTS.POINT_AND_CLICK.STATE_UPDATE, {
|
|
24
|
+
options: [],
|
|
25
|
+
args: {},
|
|
26
|
+
isShow: false,
|
|
27
|
+
} satisfies Partial<PointAndClickPluginModelState>);
|
|
28
|
+
|
|
29
|
+
this.emitNext();
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -1,18 +1,9 @@
|
|
|
1
|
-
import { splitLineKeywords, tokenizeExecLine } from "@vnejs/helpers";
|
|
2
1
|
import { ModuleCore, type ModuleGlobalStateRegistry } from "@vnejs/module.core";
|
|
3
2
|
|
|
4
3
|
import type { PointAndClickPluginConstants, PointAndClickPluginEvents, PointAndClickPluginParams, PointAndClickPluginSettings } from "../types.js";
|
|
5
|
-
import type {
|
|
6
|
-
PointAndClickEmitPayload,
|
|
7
|
-
PointAndClickExecGetPayload,
|
|
8
|
-
PointAndClickOption,
|
|
9
|
-
PointAndClickOptionLine,
|
|
10
|
-
PointAndClickOptionPayload,
|
|
11
|
-
PointAndClickPluginModelState,
|
|
12
|
-
PointAndClickVisibilityPayload,
|
|
13
|
-
} from "../utils/point-and-click.js";
|
|
4
|
+
import type { PointAndClickPluginModelState, PointAndClickVisibilityPayload } from "../utils/point-and-click.js";
|
|
14
5
|
|
|
15
|
-
export class
|
|
6
|
+
export class PointAndClickState extends ModuleCore<
|
|
16
7
|
PointAndClickPluginEvents,
|
|
17
8
|
PointAndClickPluginConstants,
|
|
18
9
|
PointAndClickPluginSettings,
|
|
@@ -22,55 +13,13 @@ export class PointAndClick extends ModuleCore<
|
|
|
22
13
|
name = "point_and_click";
|
|
23
14
|
|
|
24
15
|
subscribe = () => {
|
|
25
|
-
this.on(this.EVENTS.POINT_AND_CLICK.
|
|
26
|
-
this.on(this.EVENTS.POINT_AND_CLICK.OPTION, this.onOption);
|
|
27
|
-
this.on(this.EVENTS.POINT_AND_CLICK.SKIP, this.onSkip);
|
|
16
|
+
this.on(this.EVENTS.POINT_AND_CLICK.STATE_UPDATE, this.onStateUpdate);
|
|
28
17
|
|
|
29
18
|
this.on(this.EVENTS.STATE.SET, this.onStateSet);
|
|
30
19
|
this.on(this.EVENTS.STATE.CLEAR, this.onStateClear);
|
|
31
20
|
};
|
|
32
21
|
|
|
33
|
-
|
|
34
|
-
this.emitLog({ action: "emit", options, args });
|
|
35
|
-
const mappedOptions = await Promise.all(options.map(this.mapOptions));
|
|
36
|
-
|
|
37
|
-
if (!mappedOptions.length || mappedOptions.every((option) => option.hided)) {
|
|
38
|
-
return this.emit(this.EVENTS.POINT_AND_CLICK.SKIP);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
this.updateState({ isShow: true, options: mappedOptions, args });
|
|
42
|
-
|
|
43
|
-
return this.emit(this.EVENTS.POINT_AND_CLICK.OPENED);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
onSkip = async () => {
|
|
47
|
-
const { curLine = 0, label } = this.globalState.scenario;
|
|
48
|
-
const lines = (await this.emitOne(this.EVENTS.SCENARIO.LINES_GET, { label })) as PointAndClickOptionLine[];
|
|
49
|
-
const parentIndent = lines[curLine]?.indent ?? 0;
|
|
50
|
-
|
|
51
|
-
let indexShift = 1;
|
|
52
|
-
let curLineObj = lines[curLine + indexShift];
|
|
53
|
-
|
|
54
|
-
while (curLineObj && (curLineObj.indent ?? 0) > parentIndent) {
|
|
55
|
-
indexShift++;
|
|
56
|
-
curLineObj = lines[curLine + indexShift];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
this.emitLog({ action: "skip", label, from: curLine, to: curLine + indexShift });
|
|
60
|
-
this.globalState.scenario.curLine = curLine + indexShift;
|
|
61
|
-
|
|
62
|
-
return this.emitNext();
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
onOption = async ({ index = 0 }: PointAndClickOptionPayload = {}) => {
|
|
66
|
-
this.emitLog({ action: "point_and_click", index });
|
|
67
|
-
|
|
68
|
-
await this.emit(this.EVENTS.POINT_AND_CLICK.CLOSED);
|
|
69
|
-
|
|
70
|
-
this.globalState.scenario.curLine = this.state.options[index].index + 1;
|
|
71
|
-
this.setDefaultState();
|
|
72
|
-
this.emitNext();
|
|
73
|
-
};
|
|
22
|
+
onStateUpdate = (state: Partial<PointAndClickPluginModelState> = {}) => this.updateState(state);
|
|
74
23
|
|
|
75
24
|
onStateSet = async (payload: ModuleGlobalStateRegistry) => {
|
|
76
25
|
const moduleState = this.getStateSlice(payload);
|
|
@@ -81,29 +30,12 @@ export class PointAndClick extends ModuleCore<
|
|
|
81
30
|
|
|
82
31
|
this.setState(clonedState);
|
|
83
32
|
|
|
84
|
-
return this.emit(clonedState.isShow ? this.EVENTS.POINT_AND_CLICK.
|
|
33
|
+
return this.emit(clonedState.isShow ? this.EVENTS.POINT_AND_CLICK.SHOW : this.EVENTS.POINT_AND_CLICK.HIDE, {
|
|
85
34
|
isForce: true,
|
|
86
35
|
} satisfies PointAndClickVisibilityPayload);
|
|
87
36
|
};
|
|
88
37
|
|
|
89
|
-
onStateClear = () => this.emit(this.EVENTS.POINT_AND_CLICK.
|
|
90
|
-
|
|
91
|
-
mapOptions = async ({ optionLine: { line = "", args = {} }, index }: NonNullable<PointAndClickEmitPayload["options"]>[number]) => {
|
|
92
|
-
const [, , icon, x, y] = tokenizeExecLine(line).map(String);
|
|
93
|
-
const result: PointAndClickOption = { index, coords: [x, y].map(Number), icon, ...args };
|
|
94
|
-
|
|
95
|
-
await Promise.all(
|
|
96
|
-
Object.keys(args).map(async (key) => {
|
|
97
|
-
if (typeof args[key] !== "string" || !args[key].startsWith(this.CONST.SCENARIO.LINE_PREFIXES.MODULE)) return;
|
|
98
|
-
|
|
99
|
-
const { line: execLine = "", module = "", keywords = [] } = splitLineKeywords(String(args[key]));
|
|
100
|
-
|
|
101
|
-
result[key] = await this.emitOne(this.EVENTS.POINT_AND_CLICK.EXEC_GET, { line: execLine, module, keywords } satisfies PointAndClickExecGetPayload);
|
|
102
|
-
}),
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
return result;
|
|
106
|
-
};
|
|
38
|
+
onStateClear = () => this.emit(this.EVENTS.POINT_AND_CLICK.HIDE, { isForce: true } satisfies PointAndClickVisibilityPayload);
|
|
107
39
|
|
|
108
40
|
getDefaultState = (): PointAndClickPluginModelState => ({ options: [], args: {}, isShow: false });
|
|
109
41
|
}
|
|
@@ -32,7 +32,7 @@ export class PointAndClickScenarioModule extends ModuleCore<
|
|
|
32
32
|
return this.emitNext();
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
this.emitLog({ action: this.CONST.POINT_AND_CLICK.
|
|
35
|
+
this.emitLog({ action: this.CONST.POINT_AND_CLICK.LOGS_ACTIONS.REPEAT, label, from: curLine, to: targetIndex });
|
|
36
36
|
this.globalState.scenario.curLine = targetIndex;
|
|
37
37
|
|
|
38
38
|
return this.emitNext();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ModuleCore } from "@vnejs/module.core";
|
|
2
|
+
|
|
3
|
+
import type { PointAndClickPluginConstants, PointAndClickPluginEvents, PointAndClickPluginParams, PointAndClickPluginSettings } from "../types.js";
|
|
4
|
+
import type { PointAndClickOptionLine } from "../utils/point-and-click.js";
|
|
5
|
+
|
|
6
|
+
export class PointAndClickSkip extends ModuleCore<
|
|
7
|
+
PointAndClickPluginEvents,
|
|
8
|
+
PointAndClickPluginConstants,
|
|
9
|
+
PointAndClickPluginSettings,
|
|
10
|
+
PointAndClickPluginParams
|
|
11
|
+
> {
|
|
12
|
+
name = "point_and_click.skip";
|
|
13
|
+
|
|
14
|
+
subscribe = () => {
|
|
15
|
+
this.on(this.EVENTS.POINT_AND_CLICK.SKIP, this.onSkip);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
onSkip = async () => {
|
|
19
|
+
const { curLine = 0, label } = this.globalState.scenario;
|
|
20
|
+
const lines = (await this.emitOne(this.EVENTS.SCENARIO.LINES_GET, { label })) as PointAndClickOptionLine[];
|
|
21
|
+
const parentIndent = lines[curLine]?.indent ?? 0;
|
|
22
|
+
|
|
23
|
+
let indexShift = 1;
|
|
24
|
+
let curLineObj = lines[curLine + indexShift];
|
|
25
|
+
|
|
26
|
+
while (curLineObj && (curLineObj.indent ?? 0) > parentIndent) {
|
|
27
|
+
indexShift++;
|
|
28
|
+
curLineObj = lines[curLine + indexShift];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.globalState.scenario.curLine = curLine + indexShift;
|
|
32
|
+
|
|
33
|
+
return this.emitNext();
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { SUBSCRIBE_EVENTS as LOGS_EVENTS } from "@vnejs/contracts.core.logs";
|
|
4
|
+
import { spyEvent } from "@vnejs/test-utils";
|
|
5
|
+
|
|
6
|
+
import { PointAndClickLogs } from "../modules/logs.js";
|
|
7
|
+
import { CONSTANTS, createPointAndClickTestModule, registerPointAndClickPluginVne, SUBSCRIBE_EVENTS } from "./setup.js";
|
|
8
|
+
|
|
9
|
+
describe("PointAndClickLogs", () => {
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
registerPointAndClickPluginVne();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("EMIT emits LOGS.EMIT with emit action", async () => {
|
|
15
|
+
const { observer } = createPointAndClickTestModule(PointAndClickLogs);
|
|
16
|
+
const logs = spyEvent(observer, LOGS_EVENTS.EMIT);
|
|
17
|
+
const options = [{ index: 0, optionLine: { line: "% point-and-click.option star 1 2", args: {} } }];
|
|
18
|
+
|
|
19
|
+
await observer.emit(SUBSCRIBE_EVENTS.EMIT, { options, args: { a: 1 } });
|
|
20
|
+
|
|
21
|
+
expect(logs).toHaveBeenCalledExactlyOnceWith({
|
|
22
|
+
module: "point_and_click.logs",
|
|
23
|
+
value: { action: CONSTANTS.LOGS_ACTIONS.EMIT, options, args: { a: 1 } },
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("OPTION emits LOGS.EMIT with option action and index", async () => {
|
|
28
|
+
const { observer } = createPointAndClickTestModule(PointAndClickLogs);
|
|
29
|
+
const logs = spyEvent(observer, LOGS_EVENTS.EMIT);
|
|
30
|
+
|
|
31
|
+
await observer.emit(SUBSCRIBE_EVENTS.OPTION, { index: 2 });
|
|
32
|
+
|
|
33
|
+
expect(logs).toHaveBeenCalledExactlyOnceWith({
|
|
34
|
+
module: "point_and_click.logs",
|
|
35
|
+
value: { action: CONSTANTS.LOGS_ACTIONS.OPTION, index: 2 },
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("SKIP emits LOGS.EMIT with skip action and scenario cursor", async () => {
|
|
40
|
+
const { observer, state } = createPointAndClickTestModule(PointAndClickLogs);
|
|
41
|
+
const logs = spyEvent(observer, LOGS_EVENTS.EMIT);
|
|
42
|
+
|
|
43
|
+
state.scenario.curLine = 3;
|
|
44
|
+
state.scenario.label = "lab";
|
|
45
|
+
|
|
46
|
+
await observer.emit(SUBSCRIBE_EVENTS.SKIP);
|
|
47
|
+
|
|
48
|
+
expect(logs).toHaveBeenCalledExactlyOnceWith({
|
|
49
|
+
module: "point_and_click.logs",
|
|
50
|
+
value: { action: CONSTANTS.LOGS_ACTIONS.SKIP, label: "lab", from: 3 },
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("SHOW emits LOGS.EMIT with show action", async () => {
|
|
55
|
+
const { observer } = createPointAndClickTestModule(PointAndClickLogs);
|
|
56
|
+
const logs = spyEvent(observer, LOGS_EVENTS.EMIT);
|
|
57
|
+
|
|
58
|
+
await observer.emit(SUBSCRIBE_EVENTS.SHOW);
|
|
59
|
+
|
|
60
|
+
expect(logs).toHaveBeenCalledExactlyOnceWith({
|
|
61
|
+
module: "point_and_click.logs",
|
|
62
|
+
value: { action: CONSTANTS.LOGS_ACTIONS.SHOW },
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("HIDE emits LOGS.EMIT with hide action", async () => {
|
|
67
|
+
const { observer } = createPointAndClickTestModule(PointAndClickLogs);
|
|
68
|
+
const logs = spyEvent(observer, LOGS_EVENTS.EMIT);
|
|
69
|
+
|
|
70
|
+
await observer.emit(SUBSCRIBE_EVENTS.HIDE);
|
|
71
|
+
|
|
72
|
+
expect(logs).toHaveBeenCalledExactlyOnceWith({
|
|
73
|
+
module: "point_and_click.logs",
|
|
74
|
+
value: { action: CONSTANTS.LOGS_ACTIONS.HIDE },
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -2,32 +2,52 @@ import { beforeEach, describe, expect, it } from "vitest";
|
|
|
2
2
|
|
|
3
3
|
import { spyEvent } from "@vnejs/test-utils";
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { PointAndClickState } from "../modules/point_and_click.js";
|
|
6
|
+
import {
|
|
7
|
+
createPointAndClickFlowModules,
|
|
8
|
+
createPointAndClickTestModule,
|
|
9
|
+
registerPointAndClickPluginVne,
|
|
10
|
+
SCENARIO_EVENTS,
|
|
11
|
+
SUBSCRIBE_EVENTS,
|
|
12
|
+
} from "./setup.js";
|
|
13
|
+
|
|
14
|
+
describe("PointAndClickState", () => {
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
registerPointAndClickPluginVne();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("STATE_UPDATE merges partial point_and_click state", async () => {
|
|
20
|
+
const { module, observer } = createPointAndClickTestModule(PointAndClickState);
|
|
21
|
+
|
|
22
|
+
await observer.emit(SUBSCRIBE_EVENTS.STATE_UPDATE, { isShow: true });
|
|
7
23
|
|
|
8
|
-
|
|
24
|
+
expect((module as PointAndClickState).state.isShow).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe("PointAndClick flow", () => {
|
|
9
29
|
beforeEach(() => {
|
|
10
30
|
registerPointAndClickPluginVne();
|
|
11
31
|
});
|
|
12
32
|
|
|
13
|
-
it("EMIT stores options and emits
|
|
14
|
-
const {
|
|
15
|
-
const
|
|
33
|
+
it("EMIT stores options and emits SHOW", async () => {
|
|
34
|
+
const { stateModule, observer } = createPointAndClickFlowModules();
|
|
35
|
+
const show = spyEvent(observer, SUBSCRIBE_EVENTS.SHOW);
|
|
16
36
|
const skip = spyEvent(observer, SUBSCRIBE_EVENTS.SKIP);
|
|
17
37
|
|
|
18
38
|
await observer.emit(SUBSCRIBE_EVENTS.EMIT, {
|
|
19
39
|
options: [{ index: 0, optionLine: { line: "% point-and-click.option star 100 200", args: {} } }],
|
|
20
40
|
});
|
|
21
41
|
|
|
22
|
-
expect(
|
|
23
|
-
expect(
|
|
24
|
-
expect(
|
|
42
|
+
expect(stateModule.state.isShow).toBe(true);
|
|
43
|
+
expect(stateModule.state.options[0]).toMatchObject({ index: 0, icon: "star", coords: [100, 200] });
|
|
44
|
+
expect(show).toHaveBeenCalledOnce();
|
|
25
45
|
expect(skip).not.toHaveBeenCalled();
|
|
26
46
|
});
|
|
27
47
|
|
|
28
48
|
it("EMIT with all hided options emits SKIP and advances past the block", async () => {
|
|
29
|
-
const {
|
|
30
|
-
const
|
|
49
|
+
const { stateModule, observer, state } = createPointAndClickFlowModules();
|
|
50
|
+
const show = spyEvent(observer, SUBSCRIBE_EVENTS.SHOW);
|
|
31
51
|
const skip = spyEvent(observer, SUBSCRIBE_EVENTS.SKIP);
|
|
32
52
|
const next = spyEvent(observer, SCENARIO_EVENTS.NEXT);
|
|
33
53
|
const lines = [
|
|
@@ -44,14 +64,14 @@ describe("PointAndClick", () => {
|
|
|
44
64
|
});
|
|
45
65
|
|
|
46
66
|
expect(skip).toHaveBeenCalledOnce();
|
|
47
|
-
expect(
|
|
48
|
-
expect(
|
|
67
|
+
expect(show).not.toHaveBeenCalled();
|
|
68
|
+
expect(stateModule.state.isShow).toBe(false);
|
|
49
69
|
expect(state.scenario.curLine).toBe(2);
|
|
50
70
|
expect(next).toHaveBeenCalledOnce();
|
|
51
71
|
});
|
|
52
72
|
|
|
53
73
|
it("EMIT with empty options emits SKIP and advances past the block", async () => {
|
|
54
|
-
const { observer, state } =
|
|
74
|
+
const { observer, state } = createPointAndClickFlowModules();
|
|
55
75
|
const skip = spyEvent(observer, SUBSCRIBE_EVENTS.SKIP);
|
|
56
76
|
const next = spyEvent(observer, SCENARIO_EVENTS.NEXT);
|
|
57
77
|
const lines = [
|
|
@@ -69,20 +89,20 @@ describe("PointAndClick", () => {
|
|
|
69
89
|
expect(next).toHaveBeenCalledOnce();
|
|
70
90
|
});
|
|
71
91
|
|
|
72
|
-
it("OPTION emits
|
|
73
|
-
const {
|
|
74
|
-
const
|
|
92
|
+
it("OPTION emits HIDE, updates curLine and resets state", async () => {
|
|
93
|
+
const { stateModule, observer, state } = createPointAndClickFlowModules();
|
|
94
|
+
const hide = spyEvent(observer, SUBSCRIBE_EVENTS.HIDE);
|
|
75
95
|
|
|
76
|
-
(
|
|
96
|
+
stateModule.setState({
|
|
77
97
|
options: [{ index: 3, icon: "star", coords: [0, 0] }],
|
|
78
98
|
args: {},
|
|
79
99
|
isShow: true,
|
|
80
|
-
};
|
|
100
|
+
});
|
|
81
101
|
|
|
82
102
|
await observer.emit(SUBSCRIBE_EVENTS.OPTION, { index: 0 });
|
|
83
103
|
|
|
84
|
-
expect(
|
|
104
|
+
expect(hide).toHaveBeenCalledOnce();
|
|
85
105
|
expect(state.scenario.curLine).toBe(4);
|
|
86
|
-
expect(
|
|
106
|
+
expect(stateModule.state.isShow).toBe(false);
|
|
87
107
|
});
|
|
88
108
|
});
|
package/src/tests/setup.ts
CHANGED
|
@@ -3,6 +3,11 @@ import { CONSTANTS, PARAMS, PLUGIN_NAME, SUBSCRIBE_EVENTS } from "@vnejs/contrac
|
|
|
3
3
|
import { SourcesSet } from "@vnejs/sources-set";
|
|
4
4
|
import { createTestModule as baseCreateTestModule, registerCoreVne, registerVnePlugin, stubSilentEvent } from "@vnejs/test-utils";
|
|
5
5
|
|
|
6
|
+
import { PointAndClickEmit } from "../modules/emit.js";
|
|
7
|
+
import { PointAndClickOption } from "../modules/option.js";
|
|
8
|
+
import { PointAndClickState } from "../modules/point_and_click.js";
|
|
9
|
+
import { PointAndClickSkip } from "../modules/skip.js";
|
|
10
|
+
|
|
6
11
|
export const registerPointAndClickPluginVne = () => {
|
|
7
12
|
registerCoreVne();
|
|
8
13
|
registerVnePlugin(PLUGIN_NAME, { constants: CONSTANTS, events: SUBSCRIBE_EVENTS, params: PARAMS });
|
|
@@ -25,10 +30,31 @@ export const createPointAndClickTestModule = <T extends Parameters<typeof baseCr
|
|
|
25
30
|
...options,
|
|
26
31
|
});
|
|
27
32
|
|
|
28
|
-
stubSilentEvent(result.observer, SUBSCRIBE_EVENTS.
|
|
29
|
-
stubSilentEvent(result.observer, SUBSCRIBE_EVENTS.
|
|
33
|
+
stubSilentEvent(result.observer, SUBSCRIBE_EVENTS.SHOW);
|
|
34
|
+
stubSilentEvent(result.observer, SUBSCRIBE_EVENTS.HIDE);
|
|
30
35
|
|
|
31
36
|
return result;
|
|
32
37
|
};
|
|
33
38
|
|
|
39
|
+
export const createPointAndClickFlowModules = (options: Parameters<typeof baseCreateTestModule>[1] = {}) => {
|
|
40
|
+
const { module: stateModule, observer, state, shared } = createPointAndClickTestModule(PointAndClickState, options);
|
|
41
|
+
|
|
42
|
+
const attach = <T extends new () => InstanceType<T>>(ModuleClass: T) => {
|
|
43
|
+
const module = new ModuleClass();
|
|
44
|
+
module.inject({ observer, state, shared, media: {} });
|
|
45
|
+
module.subscribe();
|
|
46
|
+
return module;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
stateModule: stateModule as PointAndClickState,
|
|
51
|
+
emitModule: attach(PointAndClickEmit),
|
|
52
|
+
optionModule: attach(PointAndClickOption),
|
|
53
|
+
skipModule: attach(PointAndClickSkip),
|
|
54
|
+
observer,
|
|
55
|
+
state,
|
|
56
|
+
shared,
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
|
|
34
60
|
export { CONSTANTS, SUBSCRIBE_EVENTS, PARAMS, PLUGIN_NAME, SCENARIO_EVENTS };
|