Skip to content

Commit 9ce03a5

Browse files
authored
Merge pull request #185 from easyops-cn/jojiang/ui-test
fix(): refine custom brick record
2 parents 8318df0 + 492d020 commit 9ce03a5

File tree

5 files changed

+204
-54
lines changed

5 files changed

+204
-54
lines changed

bricks/ui-test/src/data-providers/preview/brick-recorder/basic-bricks.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// istanbul ignore file
22
import * as t from "@babel/types";
3-
import { generateCodeText } from "../recorder";
4-
import { generateBaseStep, createBrickEvtHandler } from "../utils";
3+
import {
4+
generateBaseStep,
5+
createBrickEvtHandler,
6+
generateCodeText,
7+
} from "../utils";
58

69
const basicBricksMap = {
710
"basic-bricks.general-button": {
@@ -11,6 +14,34 @@ const basicBricksMap = {
1114
generateBaseStep(event, text);
1215
},
1316
},
17+
"basic-bricks.general-modal": {
18+
"modal.open ": (event: CustomEvent<Record<string, string>>) => {
19+
const expr = t.callExpression(
20+
t.identifier("brick_waitForAnimationEnd"),
21+
[]
22+
);
23+
const text = generateCodeText(expr);
24+
generateBaseStep(event, text);
25+
},
26+
"basic-bricks.general-modal.confirm": (
27+
event: CustomEvent<Record<string, string>>
28+
) => {
29+
const expr = t.callExpression(t.identifier("brick_click"), [
30+
t.stringLiteral("ok"),
31+
]);
32+
const text = generateCodeText(expr);
33+
generateBaseStep(event, text);
34+
},
35+
"basic-bricks.general-modal.cancel": (
36+
event: CustomEvent<Record<string, string>>
37+
) => {
38+
const expr = t.callExpression(t.identifier("brick_click"), [
39+
t.stringLiteral("cancel"),
40+
]);
41+
const text = generateCodeText(expr);
42+
generateBaseStep(event, text);
43+
},
44+
},
1445
};
1546

1647
export const basicBricks = Object.keys(basicBricksMap);

bricks/ui-test/src/data-providers/preview/brick-recorder/forms.ts

Lines changed: 124 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// istanbul ignore file
22
import * as t from "@babel/types";
3-
import { generateCodeText } from "../recorder";
3+
import { generateCodeText } from "../utils";
44
import { BrickEvtMapField } from "../interfaces";
5+
import type { MenuIcon } from "@next-shared/general/types";
56
import {
67
generateBaseStep,
78
generateBrickInputStep,
@@ -60,12 +61,11 @@ const formBricksMap: BrickEvtMapField = {
6061
},
6162
"forms.general-auto-complete": {
6263
"general.auto-complete.change": (event: CustomEvent<string>) => {
63-
const expr =
64-
event.detail === null
65-
? t.callExpression(t.identifier("brick_clear"), [])
66-
: t.callExpression(t.identifier("brick_type"), [
67-
t.stringLiteral(event.detail),
68-
]);
64+
const expr = !event.detail
65+
? t.callExpression(t.identifier("brick_clear"), [])
66+
: t.callExpression(t.identifier("brick_type"), [
67+
t.stringLiteral(event.detail),
68+
]);
6969
const text = generateCodeText(expr);
7070

7171
generateBrickInputStep(event, text, {
@@ -97,12 +97,11 @@ const formBricksMap: BrickEvtMapField = {
9797
},
9898
"forms.general-date-picker": {
9999
"general.date.change": (event: CustomEvent<string>) => {
100-
const expr =
101-
event.detail === null
102-
? t.callExpression(t.identifier("brick_clear"), [])
103-
: t.callExpression(t.identifier("brick_type"), [
104-
t.stringLiteral(event.detail),
105-
]);
100+
const expr = !event.detail
101+
? t.callExpression(t.identifier("brick_clear"), [])
102+
: t.callExpression(t.identifier("brick_type"), [
103+
t.stringLiteral(event.detail),
104+
]);
106105
const text = generateCodeText(expr);
107106

108107
generateBrickInputStep(event, text, {
@@ -114,29 +113,41 @@ const formBricksMap: BrickEvtMapField = {
114113
"time.range.change": (
115114
event: CustomEvent<{ startTime: string; endTime: string }>
116115
) => {
117-
[event.detail.startTime, event.detail.endTime].forEach((time, index) => {
118-
const typeLiteral = t.stringLiteral(index === 0 ? "start" : "end");
119-
const expr = time
120-
? t.callExpression(t.identifier("brick_type"), [
121-
typeLiteral,
122-
t.stringLiteral(time),
123-
])
124-
: t.callExpression(t.identifier("brick_clear"), [typeLiteral]);
116+
const { startTime, endTime } = event.detail;
125117

126-
const text = generateCodeText(expr);
118+
const baseExpr = startTime
119+
? t.callExpression(t.identifier("brick_type"), [
120+
t.stringLiteral("start"),
121+
t.stringLiteral(startTime),
122+
])
123+
: t.callExpression(t.identifier("brick_clear"), [
124+
t.stringLiteral("start"),
125+
]);
126+
127+
const expr = t.callExpression(
128+
t.memberExpression(
129+
baseExpr,
130+
t.identifier(endTime ? "brick_type" : "brick_clear")
131+
),
132+
endTime
133+
? [t.stringLiteral("end"), t.stringLiteral(endTime)]
134+
: [t.stringLiteral("end")]
135+
);
136+
137+
const text = generateCodeText(expr);
127138

128-
generateBaseStep(event, text);
139+
generateBrickInputStep(event, text, {
140+
brickEvtName: "time.range.change",
129141
});
130142
},
131143
},
132144
"forms.input-with-unit": {
133145
"general.input-with-unit.change": (event: CustomEvent<number>) => {
134-
const expr =
135-
event.detail === null
136-
? t.callExpression(t.identifier("brick_clear"), [])
137-
: t.callExpression(t.identifier("brick_type"), [
138-
t.numericLiteral(event.detail),
139-
]);
146+
const expr = !event.detail
147+
? t.callExpression(t.identifier("brick_clear"), [])
148+
: t.callExpression(t.identifier("brick_type"), [
149+
t.numericLiteral(event.detail),
150+
]);
140151
const text = generateCodeText(expr);
141152

142153
generateBrickInputStep(event, text, {
@@ -146,12 +157,91 @@ const formBricksMap: BrickEvtMapField = {
146157
},
147158
"forms.general-checkbox": {
148159
"general.checkbox.change.v2": (event: CustomEvent<OptionItem[]>) => {
149-
event.detail?.forEach((item) => {
150-
const expr = t.callExpression(t.identifier("brick_clickItem"), [
151-
t.stringLiteral(item.label),
152-
]);
160+
let expr: t.Expression | undefined;
161+
event.detail.forEach((item, index) => {
162+
if (index === 0) {
163+
expr = t.callExpression(t.identifier("brick_clickItem"), [
164+
t.stringLiteral(item.label),
165+
]);
166+
} else {
167+
expr = t.callExpression(
168+
t.memberExpression(expr!, t.identifier("brick_clickItem")),
169+
[t.stringLiteral(item.label)]
170+
);
171+
}
172+
});
173+
174+
if (expr) {
153175
const text = generateCodeText(expr);
154-
generateBaseStep(event, text);
176+
177+
generateBrickInputStep(event, text, {
178+
brickEvtName: "general.checkbox.change.v2",
179+
});
180+
}
181+
},
182+
},
183+
"forms.dynamic-form-item-v2": {
184+
"item.change": (event: CustomEvent<unknown[]>) => {
185+
const expr = t.callExpression(t.identifier("brick_type"), [
186+
t.objectExpression([
187+
t.objectProperty(t.identifier("type"), t.stringLiteral("jsonStr")),
188+
t.objectProperty(
189+
t.identifier("value"),
190+
t.stringLiteral(JSON.stringify(event.detail))
191+
),
192+
]),
193+
]);
194+
195+
const text = generateCodeText(expr);
196+
197+
generateBrickInputStep(event, text, {
198+
brickEvtName: "item.change",
199+
});
200+
},
201+
},
202+
"forms.general-buttons": {
203+
"submit.button.click": (event: CustomEvent<null>) => {
204+
const expr = t.callExpression(t.identifier("brick_click"), [
205+
t.stringLiteral("submit"),
206+
]);
207+
const text = generateCodeText(expr);
208+
generateBaseStep(event, text);
209+
},
210+
"cancel.button.click": (event: CustomEvent<null>) => {
211+
const expr = t.callExpression(t.identifier("brick_click"), [
212+
t.stringLiteral("cancel"),
213+
]);
214+
const text = generateCodeText(expr);
215+
generateBaseStep(event, text);
216+
},
217+
},
218+
"forms.general-time-picker": {
219+
"general.time.change": (event: CustomEvent<string>) => {
220+
const expr = !event.detail
221+
? t.callExpression(t.identifier("brick_clear"), [])
222+
: t.callExpression(t.identifier("brick_type"), [
223+
t.stringLiteral(event.detail),
224+
]);
225+
const text = generateCodeText(expr);
226+
generateBrickInputStep(event, text, {
227+
brickEvtName: "general.time.change",
228+
});
229+
},
230+
},
231+
"forms.icon-select": {
232+
"icon.change": (event: CustomEvent<MenuIcon>) => {
233+
const expr = t.callExpression(t.identifier("brick_fill"), [
234+
t.objectExpression(
235+
Object.entries(event.detail)
236+
.filter(([, v]) => !!v)
237+
.map(([key, v]) =>
238+
t.objectProperty(t.identifier(key), t.stringLiteral(v as string))
239+
)
240+
),
241+
]);
242+
const text = generateCodeText(expr);
243+
generateBrickInputStep(event, text, {
244+
brickEvtName: "icon.change",
155245
});
156246
},
157247
},

bricks/ui-test/src/data-providers/preview/recorder.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
// istanbul ignore file: working in progress
2-
import * as t from "@babel/types";
3-
import { transformFromAst } from "@babel/standalone";
42
import {
53
getPossibleTargets,
64
getTagName,
@@ -35,22 +33,6 @@ function shouldIgnoreRecording(targets: EventTarget[]): boolean {
3533
});
3634
}
3735

38-
/**
39-
* Use Babel to generate the code from AST, instead of construct the code manually.
40-
*/
41-
export function generateCodeText(expr: t.Expression): string {
42-
const program = t.program([t.expressionStatement(expr)], undefined, "module");
43-
const result = transformFromAst(program, undefined, {
44-
generatorOpts: {
45-
jsescOption: {
46-
minimal: true,
47-
},
48-
},
49-
cloneInputAst: false,
50-
});
51-
return result.code as string;
52-
}
53-
5436
/**
5537
* When using custom recorders, always append the event target as the last target.
5638
*/

bricks/ui-test/src/data-providers/preview/utils.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import {
33
createBrickEvtHandler,
44
generateBaseStep,
55
generateBrickInputStep,
6+
generateCodeText,
67
} from "./utils";
78
import { recordContext } from "./RecordContext";
89
import { getTagName, getPossibleTargets } from "./inspector";
10+
import * as t from "@babel/types";
911
jest.mock("./inspector");
1012

1113
describe("createBrickEvtHandler processor", () => {
@@ -108,3 +110,30 @@ describe("generateBrickInputStep", () => {
108110
expect(steps[0].text).toBe("input code");
109111
});
110112
});
113+
114+
describe("generateCodeText", () => {
115+
it("should generate code from string literal expression", () => {
116+
const expr = t.stringLiteral("hello world");
117+
const result = generateCodeText(expr);
118+
expect(result).toEqual('"hello world";');
119+
});
120+
121+
it("should generate code from array expression", () => {
122+
const expr = t.arrayExpression([
123+
t.stringLiteral("item1"),
124+
t.stringLiteral("item2"),
125+
t.numericLiteral(3),
126+
]);
127+
const result = generateCodeText(expr);
128+
expect(result).toEqual('["item1", "item2", 3];');
129+
});
130+
131+
it("should generate code from object expression", () => {
132+
const expr = t.objectExpression([
133+
t.objectProperty(t.identifier("name"), t.stringLiteral("John")),
134+
t.objectProperty(t.identifier("age"), t.numericLiteral(30)),
135+
]);
136+
const result = generateCodeText(expr);
137+
expect(result).toEqual('({\n name: "John",\n age: 30\n});');
138+
});
139+
});

bricks/ui-test/src/data-providers/preview/utils.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { getTagName, getPossibleTargets } from "./inspector";
33
import { hasOwnProperty } from "@next-core/utils/general";
44
import { appendTarget } from "./recorder";
55
import { recordContext } from "./RecordContext";
6+
import * as t from "@babel/types";
7+
import { transformFromAst } from "@babel/standalone";
68

79
export function brickEvtHandler(
810
event: CustomEvent<string | null>,
@@ -92,3 +94,19 @@ export function generateBrickInputStep(
9294
}
9395
}
9496
}
97+
98+
/**
99+
* Use Babel to generate the code from AST, instead of construct the code manually.
100+
*/
101+
export function generateCodeText(expr: t.Expression): string {
102+
const program = t.program([t.expressionStatement(expr)], undefined, "module");
103+
const result = transformFromAst(program, undefined, {
104+
generatorOpts: {
105+
jsescOption: {
106+
minimal: true,
107+
},
108+
},
109+
cloneInputAst: false,
110+
});
111+
return result.code as string;
112+
}

0 commit comments

Comments
 (0)