wyreframe 0.1.0 → 0.1.1
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/LICENSE +692 -0
- package/README.md +65 -5
- package/package.json +8 -7
- package/src/index.ts +425 -0
- package/src/renderer/Renderer.gen.tsx +49 -0
- package/src/renderer/Renderer.mjs +41 -1
- package/src/renderer/Renderer.res +78 -0
- package/src/test/Expect.mjs +9 -0
- package/src/parser/Core/__tests__/Bounds_test.mjs +0 -326
- package/src/parser/Core/__tests__/Bounds_test.res +0 -412
- package/src/parser/Core/__tests__/Grid_test.mjs +0 -322
- package/src/parser/Core/__tests__/Grid_test.res +0 -319
- package/src/parser/Core/__tests__/Types_test.mjs +0 -614
- package/src/parser/Core/__tests__/Types_test.res +0 -650
- package/src/parser/Detector/__tests__/BoxTracer_test.mjs +0 -70
- package/src/parser/Detector/__tests__/BoxTracer_test.res +0 -92
- package/src/parser/Detector/__tests__/HierarchyBuilder_test.mjs +0 -489
- package/src/parser/Detector/__tests__/HierarchyBuilder_test.res +0 -849
- package/src/parser/Detector/__tests__/ShapeDetector_test.mjs +0 -377
- package/src/parser/Detector/__tests__/ShapeDetector_test.res +0 -563
- package/src/parser/Interactions/__tests__/InteractionMerger_test.mjs +0 -576
- package/src/parser/Interactions/__tests__/InteractionMerger_test.res +0 -646
- package/src/parser/Scanner/__tests__/Grid_manual.mjs +0 -214
- package/src/parser/Scanner/__tests__/Grid_manual.res +0 -141
- package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.mjs +0 -189
- package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.res +0 -257
- package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.mjs +0 -202
- package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.res +0 -250
- package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.mjs +0 -293
- package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.res +0 -134
- package/src/parser/Semantic/Elements/__tests__/InputParser_test.mjs +0 -253
- package/src/parser/Semantic/Elements/__tests__/InputParser_test.res +0 -304
- package/src/parser/Semantic/Elements/__tests__/LinkParser_test.mjs +0 -289
- package/src/parser/Semantic/Elements/__tests__/LinkParser_test.res +0 -402
- package/src/parser/Semantic/Elements/__tests__/TextParser_test.mjs +0 -149
- package/src/parser/Semantic/Elements/__tests__/TextParser_test.res +0 -167
- package/src/parser/Semantic/__tests__/ASTBuilder_test.mjs +0 -187
- package/src/parser/Semantic/__tests__/ASTBuilder_test.res +0 -192
- package/src/parser/Semantic/__tests__/ParserRegistry_test.mjs +0 -154
- package/src/parser/Semantic/__tests__/ParserRegistry_test.res +0 -191
- package/src/parser/Semantic/__tests__/SemanticParser_integration_test.mjs +0 -768
- package/src/parser/Semantic/__tests__/SemanticParser_integration_test.res +0 -1069
- package/src/parser/Semantic/__tests__/SemanticParser_manual.mjs +0 -1329
- package/src/parser/Semantic/__tests__/SemanticParser_manual.res +0 -544
- package/src/parser/__tests__/GridScanner_integration.test.mjs +0 -632
- package/src/parser/__tests__/GridScanner_integration.test.res +0 -816
- package/src/parser/__tests__/Performance.test.mjs +0 -244
- package/src/parser/__tests__/Performance.test.res +0 -371
- package/src/parser/__tests__/PerformanceFixtures.mjs +0 -200
- package/src/parser/__tests__/PerformanceFixtures.res +0 -284
- package/src/parser/__tests__/WyreframeParser_integration.test.mjs +0 -770
- package/src/parser/__tests__/WyreframeParser_integration.test.res +0 -1008
- package/src/parser/__tests__/fixtures/alignment-test.txt +0 -9
- package/src/parser/__tests__/fixtures/all-elements.txt +0 -16
- package/src/parser/__tests__/fixtures/login-scene.txt +0 -17
- package/src/parser/__tests__/fixtures/multi-scene.txt +0 -25
- package/src/parser/__tests__/fixtures/nested-boxes.txt +0 -15
- package/src/parser/__tests__/fixtures/simple-box.txt +0 -5
- package/src/parser/__tests__/fixtures/with-dividers.txt +0 -14
|
@@ -1,768 +0,0 @@
|
|
|
1
|
-
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
-
|
|
3
|
-
import * as Parser from "../../Parser.mjs";
|
|
4
|
-
import * as Vitest from "rescript-vitest/src/Vitest.mjs";
|
|
5
|
-
|
|
6
|
-
function collectAllElements(elements) {
|
|
7
|
-
return elements.flatMap(el => {
|
|
8
|
-
if (el.TAG === "Box") {
|
|
9
|
-
return [el].concat(collectAllElements(el.children));
|
|
10
|
-
} else {
|
|
11
|
-
return [el];
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function hasElement(elements, predicate) {
|
|
17
|
-
let allElements = collectAllElements(elements);
|
|
18
|
-
return allElements.some(predicate);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
Vitest.describe("SemanticParser Integration - Login Scene", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
22
|
-
Vitest.test("SP-01: parses complete login scene with all elements", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
23
|
-
let ast = Parser.parse(`
|
|
24
|
-
@scene: login
|
|
25
|
-
@title: Login Page
|
|
26
|
-
|
|
27
|
-
+--Login----------------+
|
|
28
|
-
| |
|
|
29
|
-
| * Welcome |
|
|
30
|
-
| |
|
|
31
|
-
| Email: #email |
|
|
32
|
-
| |
|
|
33
|
-
| Password: #password |
|
|
34
|
-
| |
|
|
35
|
-
| [ Login ] |
|
|
36
|
-
| |
|
|
37
|
-
+-----------------------+
|
|
38
|
-
`);
|
|
39
|
-
if (ast.TAG === "Ok") {
|
|
40
|
-
let ast$1 = ast._0;
|
|
41
|
-
t.expect(ast$1.scenes.length).toBe(1);
|
|
42
|
-
let scene = ast$1.scenes[0];
|
|
43
|
-
t.expect(scene.id).toBe("login");
|
|
44
|
-
t.expect(scene.title).toBe("Login Page");
|
|
45
|
-
let emphasisFound = hasElement(scene.elements, el => {
|
|
46
|
-
if (el.TAG === "Text" && el.emphasis) {
|
|
47
|
-
return el.content.includes("Welcome");
|
|
48
|
-
} else {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
t.expect(emphasisFound).toBe(true);
|
|
53
|
-
let emailInputFound = hasElement(scene.elements, el => {
|
|
54
|
-
if (el.TAG === "Input") {
|
|
55
|
-
return el.id === "email";
|
|
56
|
-
} else {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
t.expect(emailInputFound).toBe(true);
|
|
61
|
-
let passwordInputFound = hasElement(scene.elements, el => {
|
|
62
|
-
if (el.TAG === "Input") {
|
|
63
|
-
return el.id === "password";
|
|
64
|
-
} else {
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
t.expect(passwordInputFound).toBe(true);
|
|
69
|
-
let loginButtonFound = hasElement(scene.elements, el => {
|
|
70
|
-
if (el.TAG === "Button") {
|
|
71
|
-
return el.text === "Login";
|
|
72
|
-
} else {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
t.expect(loginButtonFound).toBe(true);
|
|
77
|
-
return t.expect(scene.elements.length).toBeGreaterThan(0);
|
|
78
|
-
}
|
|
79
|
-
console.error(ast._0);
|
|
80
|
-
t.expect(true).toBe(false);
|
|
81
|
-
});
|
|
82
|
-
Vitest.test("SP-01a: login scene elements have correct positions", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
83
|
-
let ast = Parser.parse(`
|
|
84
|
-
@scene: login
|
|
85
|
-
|
|
86
|
-
+--Login---+
|
|
87
|
-
| #email |
|
|
88
|
-
| [ OK ] |
|
|
89
|
-
+----------+
|
|
90
|
-
`);
|
|
91
|
-
if (ast.TAG !== "Ok") {
|
|
92
|
-
return t.expect(true).toBe(false);
|
|
93
|
-
}
|
|
94
|
-
let scene = ast._0.scenes[0];
|
|
95
|
-
scene.elements.forEach(el => {
|
|
96
|
-
switch (el.TAG) {
|
|
97
|
-
case "Button" :
|
|
98
|
-
case "Input" :
|
|
99
|
-
break;
|
|
100
|
-
default:
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
let position = el.position;
|
|
104
|
-
t.expect(position.row).toBeGreaterThanOrEqual(0);
|
|
105
|
-
t.expect(position.col).toBeGreaterThanOrEqual(0);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
Vitest.describe("SemanticParser Integration - Multiple Scenes", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
111
|
-
Vitest.test("SP-02: parses multiple scenes separated by dividers", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
112
|
-
let ast = Parser.parse(`
|
|
113
|
-
@scene: home
|
|
114
|
-
@title: Home Screen
|
|
115
|
-
|
|
116
|
-
+----------+
|
|
117
|
-
| Home |
|
|
118
|
-
+----------+
|
|
119
|
-
|
|
120
|
-
---
|
|
121
|
-
|
|
122
|
-
@scene: settings
|
|
123
|
-
@title: Settings Screen
|
|
124
|
-
|
|
125
|
-
+--------------+
|
|
126
|
-
| Settings |
|
|
127
|
-
+--------------+
|
|
128
|
-
`);
|
|
129
|
-
if (ast.TAG === "Ok") {
|
|
130
|
-
let ast$1 = ast._0;
|
|
131
|
-
t.expect(ast$1.scenes.length).toBe(2);
|
|
132
|
-
let homeScene = ast$1.scenes[0];
|
|
133
|
-
t.expect(homeScene.id).toBe("home");
|
|
134
|
-
t.expect(homeScene.title).toBe("Home Screen");
|
|
135
|
-
let settingsScene = ast$1.scenes[1];
|
|
136
|
-
t.expect(settingsScene.id).toBe("settings");
|
|
137
|
-
t.expect(settingsScene.title).toBe("Settings Screen");
|
|
138
|
-
return t.expect(homeScene.id).not.toBe(settingsScene.id);
|
|
139
|
-
}
|
|
140
|
-
console.error(ast._0);
|
|
141
|
-
t.expect(true).toBe(false);
|
|
142
|
-
});
|
|
143
|
-
Vitest.test("SP-02a: handles three or more scenes", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
144
|
-
let ast = Parser.parse(`
|
|
145
|
-
@scene: one
|
|
146
|
-
+----+
|
|
147
|
-
| 1 |
|
|
148
|
-
+----+
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
@scene: two
|
|
153
|
-
+----+
|
|
154
|
-
| 2 |
|
|
155
|
-
+----+
|
|
156
|
-
|
|
157
|
-
---
|
|
158
|
-
|
|
159
|
-
@scene: three
|
|
160
|
-
+----+
|
|
161
|
-
| 3 |
|
|
162
|
-
+----+
|
|
163
|
-
`);
|
|
164
|
-
if (ast.TAG !== "Ok") {
|
|
165
|
-
return t.expect(true).toBe(false);
|
|
166
|
-
}
|
|
167
|
-
let ast$1 = ast._0;
|
|
168
|
-
t.expect(ast$1.scenes.length).toBe(3);
|
|
169
|
-
t.expect(ast$1.scenes[0].id).toBe("one");
|
|
170
|
-
t.expect(ast$1.scenes[1].id).toBe("two");
|
|
171
|
-
t.expect(ast$1.scenes[2].id).toBe("three");
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
Vitest.describe("SemanticParser Integration - Nested Boxes", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
176
|
-
Vitest.test("SP-03: parses nested box hierarchy correctly", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
177
|
-
let ast = Parser.parse(`
|
|
178
|
-
@scene: nested
|
|
179
|
-
|
|
180
|
-
+--Outer-------------+
|
|
181
|
-
| |
|
|
182
|
-
| +--Inner-------+ |
|
|
183
|
-
| | | |
|
|
184
|
-
| | [ Button ] | |
|
|
185
|
-
| | | |
|
|
186
|
-
| +--------------+ |
|
|
187
|
-
| |
|
|
188
|
-
+--------------------+
|
|
189
|
-
`);
|
|
190
|
-
if (ast.TAG === "Ok") {
|
|
191
|
-
let scene = ast._0.scenes[0];
|
|
192
|
-
let outerBox = scene.elements.find(el => {
|
|
193
|
-
if (el.TAG !== "Box") {
|
|
194
|
-
return false;
|
|
195
|
-
}
|
|
196
|
-
let match = el.name;
|
|
197
|
-
return match === "Outer";
|
|
198
|
-
});
|
|
199
|
-
if (outerBox === undefined) {
|
|
200
|
-
return t.expect(true).toBe(false);
|
|
201
|
-
}
|
|
202
|
-
if (outerBox.TAG !== "Box") {
|
|
203
|
-
return t.expect(true).toBe(false);
|
|
204
|
-
}
|
|
205
|
-
let children = outerBox.children;
|
|
206
|
-
t.expect(outerBox.name).toBe("Outer");
|
|
207
|
-
t.expect(children.length).toBeGreaterThan(0);
|
|
208
|
-
let hasInnerBox = children.some(child => {
|
|
209
|
-
if (child.TAG !== "Box") {
|
|
210
|
-
return false;
|
|
211
|
-
}
|
|
212
|
-
let match = child.name;
|
|
213
|
-
return match === "Inner";
|
|
214
|
-
});
|
|
215
|
-
return t.expect(hasInnerBox).toBe(true);
|
|
216
|
-
}
|
|
217
|
-
console.error(ast._0);
|
|
218
|
-
t.expect(true).toBe(false);
|
|
219
|
-
});
|
|
220
|
-
Vitest.test("SP-03a: handles three-level nesting", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
221
|
-
let ast = Parser.parse(`
|
|
222
|
-
@scene: deep
|
|
223
|
-
|
|
224
|
-
+--Level1---------------+
|
|
225
|
-
| |
|
|
226
|
-
| +--Level2-----------+ |
|
|
227
|
-
| | | |
|
|
228
|
-
| | +--Level3------+ | |
|
|
229
|
-
| | | [ OK ] | | |
|
|
230
|
-
| | +--------------+ | |
|
|
231
|
-
| | | |
|
|
232
|
-
| +-------------------+ |
|
|
233
|
-
| |
|
|
234
|
-
+-----------------------+
|
|
235
|
-
`);
|
|
236
|
-
if (ast.TAG !== "Ok") {
|
|
237
|
-
return t.expect(true).toBe(false);
|
|
238
|
-
}
|
|
239
|
-
let scene = ast._0.scenes[0];
|
|
240
|
-
let hasLevel1 = scene.elements.some(el => {
|
|
241
|
-
if (el.TAG !== "Box") {
|
|
242
|
-
return false;
|
|
243
|
-
}
|
|
244
|
-
let n = el.name;
|
|
245
|
-
if (n !== undefined) {
|
|
246
|
-
return n.includes("Level1");
|
|
247
|
-
} else {
|
|
248
|
-
return false;
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
t.expect(hasLevel1).toBe(true);
|
|
252
|
-
});
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
Vitest.describe("SemanticParser Integration - Dividers", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
256
|
-
Vitest.test("SP-04: detects horizontal dividers within boxes", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
257
|
-
let ast = Parser.parse(`
|
|
258
|
-
@scene: sections
|
|
259
|
-
|
|
260
|
-
+------------------+
|
|
261
|
-
| Section 1 |
|
|
262
|
-
| |
|
|
263
|
-
+==================+
|
|
264
|
-
| Section 2 |
|
|
265
|
-
| |
|
|
266
|
-
+------------------+
|
|
267
|
-
`);
|
|
268
|
-
if (ast.TAG === "Ok") {
|
|
269
|
-
let scene = ast._0.scenes[0];
|
|
270
|
-
scene.elements.some(el => el.TAG === "Divider");
|
|
271
|
-
return t.expect(scene.elements.length).toBeGreaterThan(0);
|
|
272
|
-
}
|
|
273
|
-
console.error(ast._0);
|
|
274
|
-
t.expect(true).toBe(false);
|
|
275
|
-
});
|
|
276
|
-
Vitest.test("SP-04a: handles multiple dividers in one box", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
277
|
-
let ast = Parser.parse(`
|
|
278
|
-
@scene: multi
|
|
279
|
-
|
|
280
|
-
+----------+
|
|
281
|
-
| Part 1 |
|
|
282
|
-
+==========+
|
|
283
|
-
| Part 2 |
|
|
284
|
-
+==========+
|
|
285
|
-
| Part 3 |
|
|
286
|
-
+----------+
|
|
287
|
-
`);
|
|
288
|
-
if (ast.TAG !== "Ok") {
|
|
289
|
-
return t.expect(true).toBe(false);
|
|
290
|
-
}
|
|
291
|
-
let ast$1 = ast._0;
|
|
292
|
-
t.expect(ast$1.scenes.length).toBe(1);
|
|
293
|
-
let scene = ast$1.scenes[0];
|
|
294
|
-
t.expect(scene.elements.length).toBeGreaterThan(0);
|
|
295
|
-
});
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
Vitest.describe("SemanticParser Integration - All Element Types", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => Vitest.test("SP-05: recognizes all supported element types in one scene", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
299
|
-
let ast = Parser.parse(`
|
|
300
|
-
@scene: alltypes
|
|
301
|
-
|
|
302
|
-
+----------------------+
|
|
303
|
-
| * Emphasis Text |
|
|
304
|
-
| |
|
|
305
|
-
| Plain Text |
|
|
306
|
-
| |
|
|
307
|
-
| [ Button ] |
|
|
308
|
-
| |
|
|
309
|
-
| #input |
|
|
310
|
-
| |
|
|
311
|
-
| "Link Text" |
|
|
312
|
-
| |
|
|
313
|
-
| [x] Checked Box |
|
|
314
|
-
| |
|
|
315
|
-
| [ ] Unchecked Box |
|
|
316
|
-
+----------------------+
|
|
317
|
-
`);
|
|
318
|
-
if (ast.TAG === "Ok") {
|
|
319
|
-
let scene = ast._0.scenes[0];
|
|
320
|
-
let hasEmphasis = scene.elements.some(el => {
|
|
321
|
-
if (el.TAG === "Text") {
|
|
322
|
-
return el.emphasis;
|
|
323
|
-
} else {
|
|
324
|
-
return false;
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
t.expect(hasEmphasis).toBe(true);
|
|
328
|
-
let hasPlainText = scene.elements.some(el => {
|
|
329
|
-
if (el.TAG === "Text") {
|
|
330
|
-
return !el.emphasis;
|
|
331
|
-
} else {
|
|
332
|
-
return false;
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
t.expect(hasPlainText).toBe(true);
|
|
336
|
-
let hasButton = scene.elements.some(el => el.TAG === "Button");
|
|
337
|
-
t.expect(hasButton).toBe(true);
|
|
338
|
-
let hasInput = scene.elements.some(el => el.TAG === "Input");
|
|
339
|
-
t.expect(hasInput).toBe(true);
|
|
340
|
-
let hasLink = scene.elements.some(el => el.TAG === "Link");
|
|
341
|
-
t.expect(hasLink).toBe(true);
|
|
342
|
-
let hasCheckedBox = scene.elements.some(el => {
|
|
343
|
-
if (el.TAG === "Checkbox") {
|
|
344
|
-
return el.checked;
|
|
345
|
-
} else {
|
|
346
|
-
return false;
|
|
347
|
-
}
|
|
348
|
-
});
|
|
349
|
-
t.expect(hasCheckedBox).toBe(true);
|
|
350
|
-
let hasUncheckedBox = scene.elements.some(el => {
|
|
351
|
-
if (el.TAG === "Checkbox") {
|
|
352
|
-
return !el.checked;
|
|
353
|
-
} else {
|
|
354
|
-
return false;
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
return t.expect(hasUncheckedBox).toBe(true);
|
|
358
|
-
}
|
|
359
|
-
console.error(ast._0);
|
|
360
|
-
t.expect(true).toBe(false);
|
|
361
|
-
}));
|
|
362
|
-
|
|
363
|
-
Vitest.describe("SemanticParser Integration - Alignment", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => Vitest.test("SP-06: calculates element alignment based on position", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
364
|
-
let ast = Parser.parse(`
|
|
365
|
-
@scene: alignment
|
|
366
|
-
|
|
367
|
-
+---------------------------+
|
|
368
|
-
| [ Left ] |
|
|
369
|
-
| |
|
|
370
|
-
| [ Center ] |
|
|
371
|
-
| |
|
|
372
|
-
| [ Right ] |
|
|
373
|
-
+---------------------------+
|
|
374
|
-
`);
|
|
375
|
-
if (ast.TAG === "Ok") {
|
|
376
|
-
let scene = ast._0.scenes[0];
|
|
377
|
-
let buttons = scene.elements.filter(el => el.TAG === "Button");
|
|
378
|
-
t.expect(buttons.length).toBe(3);
|
|
379
|
-
let hasLeft = buttons.some(el => {
|
|
380
|
-
if (el.TAG !== "Button") {
|
|
381
|
-
return false;
|
|
382
|
-
}
|
|
383
|
-
switch (el.align) {
|
|
384
|
-
case "Left" :
|
|
385
|
-
return true;
|
|
386
|
-
case "Center" :
|
|
387
|
-
case "Right" :
|
|
388
|
-
return false;
|
|
389
|
-
}
|
|
390
|
-
});
|
|
391
|
-
t.expect(hasLeft).toBe(true);
|
|
392
|
-
let hasCenter = buttons.some(el => {
|
|
393
|
-
if (el.TAG !== "Button") {
|
|
394
|
-
return false;
|
|
395
|
-
}
|
|
396
|
-
switch (el.align) {
|
|
397
|
-
case "Center" :
|
|
398
|
-
return true;
|
|
399
|
-
case "Left" :
|
|
400
|
-
case "Right" :
|
|
401
|
-
return false;
|
|
402
|
-
}
|
|
403
|
-
});
|
|
404
|
-
t.expect(hasCenter).toBe(true);
|
|
405
|
-
let hasRight = buttons.some(el => {
|
|
406
|
-
if (el.TAG !== "Button") {
|
|
407
|
-
return false;
|
|
408
|
-
}
|
|
409
|
-
switch (el.align) {
|
|
410
|
-
case "Left" :
|
|
411
|
-
case "Center" :
|
|
412
|
-
return false;
|
|
413
|
-
case "Right" :
|
|
414
|
-
return true;
|
|
415
|
-
}
|
|
416
|
-
});
|
|
417
|
-
return t.expect(hasRight).toBe(true);
|
|
418
|
-
}
|
|
419
|
-
console.error(ast._0);
|
|
420
|
-
t.expect(true).toBe(false);
|
|
421
|
-
}));
|
|
422
|
-
|
|
423
|
-
Vitest.describe("SemanticParser Integration - Button Elements", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
424
|
-
Vitest.test("SP-07: parses button with simple text", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
425
|
-
let ast = Parser.parse(`
|
|
426
|
-
@scene: btn
|
|
427
|
-
+------------+
|
|
428
|
-
| [ Submit ] |
|
|
429
|
-
+------------+
|
|
430
|
-
`);
|
|
431
|
-
if (ast.TAG !== "Ok") {
|
|
432
|
-
return t.expect(true).toBe(false);
|
|
433
|
-
}
|
|
434
|
-
let scene = ast._0.scenes[0];
|
|
435
|
-
let button = scene.elements.find(el => el.TAG === "Button");
|
|
436
|
-
if (button === undefined) {
|
|
437
|
-
return t.expect(true).toBe(false);
|
|
438
|
-
}
|
|
439
|
-
if (button.TAG !== "Button") {
|
|
440
|
-
return t.expect(true).toBe(false);
|
|
441
|
-
}
|
|
442
|
-
t.expect(button.text).toBe("Submit");
|
|
443
|
-
t.expect(button.id).toBe("submit");
|
|
444
|
-
});
|
|
445
|
-
Vitest.test("SP-07a: parses button with multi-word text", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
446
|
-
let ast = Parser.parse(`
|
|
447
|
-
@scene: btn
|
|
448
|
-
+--------------------+
|
|
449
|
-
| [ Create Account ] |
|
|
450
|
-
+--------------------+
|
|
451
|
-
`);
|
|
452
|
-
if (ast.TAG !== "Ok") {
|
|
453
|
-
return t.expect(true).toBe(false);
|
|
454
|
-
}
|
|
455
|
-
let button = ast._0.scenes[0].elements.find(el => {
|
|
456
|
-
if (el.TAG === "Button") {
|
|
457
|
-
return el.text === "Create Account";
|
|
458
|
-
} else {
|
|
459
|
-
return false;
|
|
460
|
-
}
|
|
461
|
-
});
|
|
462
|
-
if (button !== undefined && button.TAG === "Button") {
|
|
463
|
-
return t.expect(button.id).toBe("create-account");
|
|
464
|
-
} else {
|
|
465
|
-
return t.expect(true).toBe(false);
|
|
466
|
-
}
|
|
467
|
-
});
|
|
468
|
-
});
|
|
469
|
-
|
|
470
|
-
Vitest.describe("SemanticParser Integration - Input Elements", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
471
|
-
Vitest.test("SP-08: parses input field with ID", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
472
|
-
let ast = Parser.parse(`
|
|
473
|
-
@scene: inp
|
|
474
|
-
+----------+
|
|
475
|
-
| #email |
|
|
476
|
-
+----------+
|
|
477
|
-
`);
|
|
478
|
-
if (ast.TAG !== "Ok") {
|
|
479
|
-
return t.expect(true).toBe(false);
|
|
480
|
-
}
|
|
481
|
-
let input = ast._0.scenes[0].elements.find(el => el.TAG === "Input");
|
|
482
|
-
if (input !== undefined && input.TAG === "Input") {
|
|
483
|
-
return t.expect(input.id).toBe("email");
|
|
484
|
-
} else {
|
|
485
|
-
return t.expect(true).toBe(false);
|
|
486
|
-
}
|
|
487
|
-
});
|
|
488
|
-
Vitest.test("SP-08a: parses input with label prefix", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
489
|
-
let ast = Parser.parse(`
|
|
490
|
-
@scene: inp
|
|
491
|
-
+-----------------+
|
|
492
|
-
| Email: #email |
|
|
493
|
-
+-----------------+
|
|
494
|
-
`);
|
|
495
|
-
if (ast.TAG !== "Ok") {
|
|
496
|
-
return t.expect(true).toBe(false);
|
|
497
|
-
}
|
|
498
|
-
let input = ast._0.scenes[0].elements.find(el => {
|
|
499
|
-
if (el.TAG === "Input") {
|
|
500
|
-
return el.id === "email";
|
|
501
|
-
} else {
|
|
502
|
-
return false;
|
|
503
|
-
}
|
|
504
|
-
});
|
|
505
|
-
t.expect(input).not.toBe(undefined);
|
|
506
|
-
});
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
Vitest.describe("SemanticParser Integration - Link Elements", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => Vitest.test("SP-09: parses link with quoted text", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
510
|
-
let ast = Parser.parse(`
|
|
511
|
-
@scene: lnk
|
|
512
|
-
+------------------+
|
|
513
|
-
| "Click Here" |
|
|
514
|
-
+------------------+
|
|
515
|
-
`);
|
|
516
|
-
if (ast.TAG !== "Ok") {
|
|
517
|
-
return t.expect(true).toBe(false);
|
|
518
|
-
}
|
|
519
|
-
let link = ast._0.scenes[0].elements.find(el => el.TAG === "Link");
|
|
520
|
-
if (link === undefined) {
|
|
521
|
-
return t.expect(true).toBe(false);
|
|
522
|
-
}
|
|
523
|
-
if (link.TAG !== "Link") {
|
|
524
|
-
return t.expect(true).toBe(false);
|
|
525
|
-
}
|
|
526
|
-
t.expect(link.text).toBe("Click Here");
|
|
527
|
-
t.expect(link.id).toBe("click-here");
|
|
528
|
-
}));
|
|
529
|
-
|
|
530
|
-
Vitest.describe("SemanticParser Integration - Checkbox Elements", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
531
|
-
Vitest.test("SP-10: parses checked checkbox", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
532
|
-
let ast = Parser.parse(`
|
|
533
|
-
@scene: chk
|
|
534
|
-
+-------------------+
|
|
535
|
-
| [x] Accept terms |
|
|
536
|
-
+-------------------+
|
|
537
|
-
`);
|
|
538
|
-
if (ast.TAG !== "Ok") {
|
|
539
|
-
return t.expect(true).toBe(false);
|
|
540
|
-
}
|
|
541
|
-
let checkbox = ast._0.scenes[0].elements.find(el => {
|
|
542
|
-
if (el.TAG === "Checkbox") {
|
|
543
|
-
return el.checked;
|
|
544
|
-
} else {
|
|
545
|
-
return false;
|
|
546
|
-
}
|
|
547
|
-
});
|
|
548
|
-
if (checkbox !== undefined && checkbox.TAG === "Checkbox") {
|
|
549
|
-
return t.expect(checkbox.label).toBe("Accept terms");
|
|
550
|
-
} else {
|
|
551
|
-
return t.expect(true).toBe(false);
|
|
552
|
-
}
|
|
553
|
-
});
|
|
554
|
-
Vitest.test("SP-10a: parses unchecked checkbox", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
555
|
-
let ast = Parser.parse(`
|
|
556
|
-
@scene: chk
|
|
557
|
-
+---------------------+
|
|
558
|
-
| [ ] Decline offer |
|
|
559
|
-
+---------------------+
|
|
560
|
-
`);
|
|
561
|
-
if (ast.TAG !== "Ok") {
|
|
562
|
-
return t.expect(true).toBe(false);
|
|
563
|
-
}
|
|
564
|
-
let checkbox = ast._0.scenes[0].elements.find(el => {
|
|
565
|
-
if (el.TAG === "Checkbox") {
|
|
566
|
-
return !el.checked;
|
|
567
|
-
} else {
|
|
568
|
-
return false;
|
|
569
|
-
}
|
|
570
|
-
});
|
|
571
|
-
t.expect(checkbox).not.toBe(undefined);
|
|
572
|
-
});
|
|
573
|
-
});
|
|
574
|
-
|
|
575
|
-
Vitest.describe("SemanticParser Integration - Emphasis Text", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => Vitest.test("SP-11: parses emphasis text with asterisk", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
576
|
-
let ast = Parser.parse(`
|
|
577
|
-
@scene: emp
|
|
578
|
-
+-----------------+
|
|
579
|
-
| * Important |
|
|
580
|
-
+-----------------+
|
|
581
|
-
`);
|
|
582
|
-
if (ast.TAG !== "Ok") {
|
|
583
|
-
return t.expect(true).toBe(false);
|
|
584
|
-
}
|
|
585
|
-
let emphasisText = ast._0.scenes[0].elements.find(el => {
|
|
586
|
-
if (el.TAG === "Text") {
|
|
587
|
-
return el.emphasis;
|
|
588
|
-
} else {
|
|
589
|
-
return false;
|
|
590
|
-
}
|
|
591
|
-
});
|
|
592
|
-
if (emphasisText !== undefined && emphasisText.TAG === "Text") {
|
|
593
|
-
return t.expect(emphasisText.content).toContain("Important");
|
|
594
|
-
} else {
|
|
595
|
-
return t.expect(true).toBe(false);
|
|
596
|
-
}
|
|
597
|
-
}));
|
|
598
|
-
|
|
599
|
-
Vitest.describe("SemanticParser Integration - Mixed Content", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => Vitest.test("SP-12: parses complex scene with mixed element types", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
600
|
-
let ast = Parser.parse(`
|
|
601
|
-
@scene: mixed
|
|
602
|
-
|
|
603
|
-
+-------------------------+
|
|
604
|
-
| * Registration Form |
|
|
605
|
-
| |
|
|
606
|
-
| Name: #name |
|
|
607
|
-
| Email: #email |
|
|
608
|
-
| |
|
|
609
|
-
| [x] Accept terms |
|
|
610
|
-
| |
|
|
611
|
-
| [ Sign Up ] |
|
|
612
|
-
| |
|
|
613
|
-
| "Already registered?" |
|
|
614
|
-
+-------------------------+
|
|
615
|
-
`);
|
|
616
|
-
if (ast.TAG === "Ok") {
|
|
617
|
-
let scene = ast._0.scenes[0];
|
|
618
|
-
let emphasisCount = scene.elements.filter(el => {
|
|
619
|
-
if (el.TAG === "Text") {
|
|
620
|
-
return el.emphasis;
|
|
621
|
-
} else {
|
|
622
|
-
return false;
|
|
623
|
-
}
|
|
624
|
-
}).length;
|
|
625
|
-
let inputCount = scene.elements.filter(el => el.TAG === "Input").length;
|
|
626
|
-
let checkboxCount = scene.elements.filter(el => el.TAG === "Checkbox").length;
|
|
627
|
-
let buttonCount = scene.elements.filter(el => el.TAG === "Button").length;
|
|
628
|
-
let linkCount = scene.elements.filter(el => el.TAG === "Link").length;
|
|
629
|
-
t.expect(emphasisCount).toBeGreaterThan(0);
|
|
630
|
-
t.expect(inputCount).toBeGreaterThanOrEqual(2);
|
|
631
|
-
t.expect(checkboxCount).toBeGreaterThan(0);
|
|
632
|
-
t.expect(buttonCount).toBeGreaterThan(0);
|
|
633
|
-
t.expect(linkCount).toBeGreaterThan(0);
|
|
634
|
-
return t.expect(scene.elements.length).toBeGreaterThan(5);
|
|
635
|
-
}
|
|
636
|
-
console.error(ast._0);
|
|
637
|
-
t.expect(true).toBe(false);
|
|
638
|
-
}));
|
|
639
|
-
|
|
640
|
-
Vitest.describe("SemanticParser Integration - Scene Directives", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
641
|
-
Vitest.test("SP-14: parses scene directives correctly", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
642
|
-
let ast = Parser.parse(`
|
|
643
|
-
@scene: test
|
|
644
|
-
@title: Test Scene
|
|
645
|
-
@transition: fade
|
|
646
|
-
|
|
647
|
-
+----------+
|
|
648
|
-
| Content |
|
|
649
|
-
+----------+
|
|
650
|
-
`);
|
|
651
|
-
if (ast.TAG === "Ok") {
|
|
652
|
-
let scene = ast._0.scenes[0];
|
|
653
|
-
t.expect(scene.id).toBe("test");
|
|
654
|
-
t.expect(scene.title).toBe("Test Scene");
|
|
655
|
-
return t.expect(scene.transition).toBe("fade");
|
|
656
|
-
}
|
|
657
|
-
console.error(ast._0);
|
|
658
|
-
t.expect(true).toBe(false);
|
|
659
|
-
});
|
|
660
|
-
Vitest.test("SP-14a: handles missing optional directives", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
661
|
-
let ast = Parser.parse(`
|
|
662
|
-
@scene: minimal
|
|
663
|
-
|
|
664
|
-
+----------+
|
|
665
|
-
| Content |
|
|
666
|
-
+----------+
|
|
667
|
-
`);
|
|
668
|
-
if (ast.TAG !== "Ok") {
|
|
669
|
-
return t.expect(true).toBe(false);
|
|
670
|
-
}
|
|
671
|
-
let ast$1 = ast._0;
|
|
672
|
-
let scene = ast$1.scenes[0];
|
|
673
|
-
t.expect(scene.id).toBe("minimal");
|
|
674
|
-
t.expect(ast$1.scenes.length).toBe(1);
|
|
675
|
-
});
|
|
676
|
-
});
|
|
677
|
-
|
|
678
|
-
Vitest.describe("SemanticParser Integration - Empty Scenes", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
679
|
-
Vitest.test("SP-15: handles empty scene gracefully", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
680
|
-
let ast = Parser.parse(`
|
|
681
|
-
@scene: empty
|
|
682
|
-
|
|
683
|
-
+-------+
|
|
684
|
-
| |
|
|
685
|
-
+-------+
|
|
686
|
-
`);
|
|
687
|
-
if (ast.TAG !== "Ok") {
|
|
688
|
-
return t.expect(true).toBe(false);
|
|
689
|
-
}
|
|
690
|
-
let ast$1 = ast._0;
|
|
691
|
-
t.expect(ast$1.scenes.length).toBe(1);
|
|
692
|
-
let scene = ast$1.scenes[0];
|
|
693
|
-
t.expect(scene.id).toBe("empty");
|
|
694
|
-
t.expect(Array.isArray(scene.elements)).toBe(true);
|
|
695
|
-
});
|
|
696
|
-
Vitest.test("SP-15a: handles scene with only whitespace", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
697
|
-
let ast = Parser.parse(`
|
|
698
|
-
@scene: whitespace
|
|
699
|
-
|
|
700
|
-
+-----------+
|
|
701
|
-
| |
|
|
702
|
-
| |
|
|
703
|
-
| |
|
|
704
|
-
+-----------+
|
|
705
|
-
`);
|
|
706
|
-
if (ast.TAG !== "Ok") {
|
|
707
|
-
return t.expect(true).toBe(false);
|
|
708
|
-
}
|
|
709
|
-
let ast$1 = ast._0;
|
|
710
|
-
t.expect(ast$1.scenes.length).toBe(1);
|
|
711
|
-
let scene = ast$1.scenes[0];
|
|
712
|
-
t.expect(scene.id).toBe("whitespace");
|
|
713
|
-
});
|
|
714
|
-
});
|
|
715
|
-
|
|
716
|
-
Vitest.describe("SemanticParser Integration - Edge Cases", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
717
|
-
Vitest.test("handles very long element text", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
718
|
-
let ast = Parser.parse(`
|
|
719
|
-
@scene: long
|
|
720
|
-
|
|
721
|
-
+---------------------------------------------------+
|
|
722
|
-
| [ Very Long Button Text That Spans ] |
|
|
723
|
-
+---------------------------------------------------+
|
|
724
|
-
`);
|
|
725
|
-
if (ast.TAG !== "Ok") {
|
|
726
|
-
return t.expect(true).toBe(false);
|
|
727
|
-
}
|
|
728
|
-
let button = ast._0.scenes[0].elements.find(el => el.TAG === "Button");
|
|
729
|
-
t.expect(button).not.toBe(undefined);
|
|
730
|
-
});
|
|
731
|
-
Vitest.test("handles special characters in text", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
732
|
-
let ast = Parser.parse(`
|
|
733
|
-
@scene: special
|
|
734
|
-
|
|
735
|
-
+-------------------+
|
|
736
|
-
| "Sign Up & Go!" |
|
|
737
|
-
+-------------------+
|
|
738
|
-
`);
|
|
739
|
-
if (ast.TAG === "Ok") {
|
|
740
|
-
return t.expect(ast._0.scenes.length).toBe(1);
|
|
741
|
-
} else {
|
|
742
|
-
return t.expect(true).toBe(false);
|
|
743
|
-
}
|
|
744
|
-
});
|
|
745
|
-
Vitest.test("handles unicode characters", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
746
|
-
let ast = Parser.parse(`
|
|
747
|
-
@scene: unicode
|
|
748
|
-
|
|
749
|
-
+-------------+
|
|
750
|
-
| * Hello |
|
|
751
|
-
+-------------+
|
|
752
|
-
`);
|
|
753
|
-
if (ast.TAG === "Ok") {
|
|
754
|
-
return t.expect(ast._0.scenes.length).toBe(1);
|
|
755
|
-
} else {
|
|
756
|
-
return t.expect(true).toBe(false);
|
|
757
|
-
}
|
|
758
|
-
});
|
|
759
|
-
});
|
|
760
|
-
|
|
761
|
-
let pass;
|
|
762
|
-
|
|
763
|
-
export {
|
|
764
|
-
pass,
|
|
765
|
-
collectAllElements,
|
|
766
|
-
hasElement,
|
|
767
|
-
}
|
|
768
|
-
/* Not a pure module */
|