wyreframe 0.1.0 → 0.1.5
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/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,322 +0,0 @@
|
|
|
1
|
-
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
-
|
|
3
|
-
import * as Grid from "../Grid.mjs";
|
|
4
|
-
import * as Types from "../Types.mjs";
|
|
5
|
-
import * as Vitest from "rescript-vitest/src/Vitest.mjs";
|
|
6
|
-
import * as Core__Array from "@rescript/core/src/Core__Array.mjs";
|
|
7
|
-
|
|
8
|
-
Vitest.describe("Grid", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
|
|
9
|
-
Vitest.describe("fromLines", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
|
|
10
|
-
Vitest.test("creates correct dimensions for equal-length lines", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
11
|
-
let lines = [
|
|
12
|
-
"abc",
|
|
13
|
-
"def",
|
|
14
|
-
"ghi"
|
|
15
|
-
];
|
|
16
|
-
let grid = Grid.fromLines(lines);
|
|
17
|
-
t.expect(grid.width).toBe(3);
|
|
18
|
-
t.expect(grid.height).toBe(3);
|
|
19
|
-
});
|
|
20
|
-
Vitest.test("normalizes uneven line lengths by padding", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
21
|
-
let lines = [
|
|
22
|
-
"abc",
|
|
23
|
-
"de",
|
|
24
|
-
"f"
|
|
25
|
-
];
|
|
26
|
-
let grid = Grid.fromLines(lines);
|
|
27
|
-
t.expect(grid.width).toBe(3);
|
|
28
|
-
t.expect(grid.height).toBe(3);
|
|
29
|
-
let line = Grid.getLine(grid, 1);
|
|
30
|
-
if (line !== undefined) {
|
|
31
|
-
t.expect(line.length).toBe(3);
|
|
32
|
-
return t.expect(line[2]).toEqual("Space");
|
|
33
|
-
} else {
|
|
34
|
-
return t.expect(true).toBe(false);
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
Vitest.test("handles empty input", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
38
|
-
let grid = Grid.fromLines([]);
|
|
39
|
-
t.expect(grid.width).toBe(0);
|
|
40
|
-
t.expect(grid.height).toBe(0);
|
|
41
|
-
});
|
|
42
|
-
Vitest.test("correctly identifies special characters", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
43
|
-
let lines = [
|
|
44
|
-
"+--+",
|
|
45
|
-
"| |",
|
|
46
|
-
"+==+"
|
|
47
|
-
];
|
|
48
|
-
let grid = Grid.fromLines(lines);
|
|
49
|
-
t.expect(grid.cornerIndex.length).toBe(4);
|
|
50
|
-
t.expect(grid.hLineIndex.length).toBe(2);
|
|
51
|
-
t.expect(grid.vLineIndex.length).toBe(2);
|
|
52
|
-
t.expect(grid.dividerIndex.length).toBe(2);
|
|
53
|
-
});
|
|
54
|
-
Vitest.test("builds character indices with correct positions", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
55
|
-
let lines = ["+--+"];
|
|
56
|
-
let grid = Grid.fromLines(lines);
|
|
57
|
-
t.expect(grid.cornerIndex[0]).toEqual({
|
|
58
|
-
row: 0,
|
|
59
|
-
col: 0
|
|
60
|
-
});
|
|
61
|
-
t.expect(grid.cornerIndex[1]).toEqual({
|
|
62
|
-
row: 0,
|
|
63
|
-
col: 3
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
Vitest.describe("get", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
|
|
68
|
-
let grid = Grid.fromLines([
|
|
69
|
-
"+--+",
|
|
70
|
-
"| |",
|
|
71
|
-
"+--+"
|
|
72
|
-
]);
|
|
73
|
-
Vitest.test("returns character at valid position", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
74
|
-
t.expect(Grid.get(grid, Types.Position.make(0, 0))).toEqual("Corner");
|
|
75
|
-
t.expect(Grid.get(grid, Types.Position.make(0, 1))).toEqual("HLine");
|
|
76
|
-
t.expect(Grid.get(grid, Types.Position.make(1, 0))).toEqual("VLine");
|
|
77
|
-
});
|
|
78
|
-
Vitest.test("returns None for out of bounds positions", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
79
|
-
t.expect(Grid.get(grid, Types.Position.make(-1, 0))).toBe(undefined);
|
|
80
|
-
t.expect(Grid.get(grid, Types.Position.make(0, -1))).toBe(undefined);
|
|
81
|
-
t.expect(Grid.get(grid, Types.Position.make(10, 0))).toBe(undefined);
|
|
82
|
-
t.expect(Grid.get(grid, Types.Position.make(0, 10))).toBe(undefined);
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
Vitest.describe("getLine", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
|
|
86
|
-
let grid = Grid.fromLines([
|
|
87
|
-
"+--+",
|
|
88
|
-
"| |",
|
|
89
|
-
"+--+"
|
|
90
|
-
]);
|
|
91
|
-
Vitest.test("returns entire line at valid row", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
92
|
-
let line = Grid.getLine(grid, 0);
|
|
93
|
-
if (line !== undefined) {
|
|
94
|
-
t.expect(line.length).toBe(4);
|
|
95
|
-
return t.expect(line[0]).toEqual("Corner");
|
|
96
|
-
} else {
|
|
97
|
-
return t.expect(true).toBe(false);
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
Vitest.test("returns None for out of bounds row", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
101
|
-
t.expect(Grid.getLine(grid, -1)).toBe(undefined);
|
|
102
|
-
t.expect(Grid.getLine(grid, 10)).toBe(undefined);
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
Vitest.describe("getRange", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
|
|
106
|
-
let grid = Grid.fromLines(["+--Name--+"]);
|
|
107
|
-
Vitest.test("returns range of characters", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
108
|
-
let range = Grid.getRange(grid, 0, 1, 3);
|
|
109
|
-
if (range !== undefined) {
|
|
110
|
-
t.expect(range.length).toBe(3);
|
|
111
|
-
return t.expect(range[0]).toEqual("HLine");
|
|
112
|
-
} else {
|
|
113
|
-
return t.expect(true).toBe(false);
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
Vitest.test("handles negative start column", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
117
|
-
let range = Grid.getRange(grid, 0, -1, 2);
|
|
118
|
-
if (range !== undefined) {
|
|
119
|
-
return t.expect(range.length).toBe(3);
|
|
120
|
-
} else {
|
|
121
|
-
return t.expect(true).toBe(false);
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
Vitest.test("returns None for invalid row", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => t.expect(Grid.getRange(grid, -1, 0, 2)).toBe(undefined));
|
|
125
|
-
});
|
|
126
|
-
Vitest.describe("scanRight", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
|
|
127
|
-
let grid = Grid.fromLines(["+----+"]);
|
|
128
|
-
Vitest.test("scans right until predicate fails", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
129
|
-
let start = Types.Position.make(0, 0);
|
|
130
|
-
let results = Grid.scanRight(grid, start, cell => {
|
|
131
|
-
if (typeof cell === "object") {
|
|
132
|
-
return false;
|
|
133
|
-
}
|
|
134
|
-
switch (cell) {
|
|
135
|
-
case "Corner" :
|
|
136
|
-
case "HLine" :
|
|
137
|
-
return true;
|
|
138
|
-
default:
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
t.expect(results.length).toBe(6);
|
|
143
|
-
});
|
|
144
|
-
Vitest.test("stops at grid boundary", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
145
|
-
let start = Types.Position.make(0, 0);
|
|
146
|
-
let results = Grid.scanRight(grid, start, _cell => true);
|
|
147
|
-
t.expect(results.length).toBe(6);
|
|
148
|
-
});
|
|
149
|
-
Vitest.test("returns empty array if predicate fails immediately", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
150
|
-
let start = Types.Position.make(0, 0);
|
|
151
|
-
let results = Grid.scanRight(grid, start, cell => {
|
|
152
|
-
if (typeof cell !== "object") {
|
|
153
|
-
return cell === "HLine";
|
|
154
|
-
} else {
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
t.expect(results.length).toBe(0);
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
Vitest.describe("scanDown", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
|
|
162
|
-
let grid = Grid.fromLines([
|
|
163
|
-
"+",
|
|
164
|
-
"|",
|
|
165
|
-
"|",
|
|
166
|
-
"+"
|
|
167
|
-
]);
|
|
168
|
-
Vitest.test("scans down until predicate fails", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
169
|
-
let start = Types.Position.make(0, 0);
|
|
170
|
-
let results = Grid.scanDown(grid, start, cell => {
|
|
171
|
-
if (typeof cell === "object") {
|
|
172
|
-
return false;
|
|
173
|
-
}
|
|
174
|
-
switch (cell) {
|
|
175
|
-
case "Corner" :
|
|
176
|
-
case "VLine" :
|
|
177
|
-
return true;
|
|
178
|
-
default:
|
|
179
|
-
return false;
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
t.expect(results.length).toBe(4);
|
|
183
|
-
});
|
|
184
|
-
Vitest.test("stops at grid boundary", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
185
|
-
let start = Types.Position.make(0, 0);
|
|
186
|
-
let results = Grid.scanDown(grid, start, _cell => true);
|
|
187
|
-
t.expect(results.length).toBe(4);
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
Vitest.describe("scanLeft", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
|
|
191
|
-
let grid = Grid.fromLines(["+----+"]);
|
|
192
|
-
Vitest.test("scans left until predicate fails", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
193
|
-
let start = Types.Position.make(0, 5);
|
|
194
|
-
let results = Grid.scanLeft(grid, start, cell => {
|
|
195
|
-
if (typeof cell === "object") {
|
|
196
|
-
return false;
|
|
197
|
-
}
|
|
198
|
-
switch (cell) {
|
|
199
|
-
case "Corner" :
|
|
200
|
-
case "HLine" :
|
|
201
|
-
return true;
|
|
202
|
-
default:
|
|
203
|
-
return false;
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
t.expect(results.length).toBe(6);
|
|
207
|
-
});
|
|
208
|
-
Vitest.test("stops at grid boundary", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
209
|
-
let start = Types.Position.make(0, 5);
|
|
210
|
-
let results = Grid.scanLeft(grid, start, _cell => true);
|
|
211
|
-
t.expect(results.length).toBe(6);
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
Vitest.describe("scanUp", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
|
|
215
|
-
let grid = Grid.fromLines([
|
|
216
|
-
"+",
|
|
217
|
-
"|",
|
|
218
|
-
"|",
|
|
219
|
-
"+"
|
|
220
|
-
]);
|
|
221
|
-
Vitest.test("scans up until predicate fails", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
222
|
-
let start = Types.Position.make(3, 0);
|
|
223
|
-
let results = Grid.scanUp(grid, start, cell => {
|
|
224
|
-
if (typeof cell === "object") {
|
|
225
|
-
return false;
|
|
226
|
-
}
|
|
227
|
-
switch (cell) {
|
|
228
|
-
case "Corner" :
|
|
229
|
-
case "VLine" :
|
|
230
|
-
return true;
|
|
231
|
-
default:
|
|
232
|
-
return false;
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
t.expect(results.length).toBe(4);
|
|
236
|
-
});
|
|
237
|
-
Vitest.test("stops at grid boundary", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
238
|
-
let start = Types.Position.make(3, 0);
|
|
239
|
-
let results = Grid.scanUp(grid, start, _cell => true);
|
|
240
|
-
t.expect(results.length).toBe(4);
|
|
241
|
-
});
|
|
242
|
-
});
|
|
243
|
-
Vitest.describe("findAll", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
|
|
244
|
-
let grid = Grid.fromLines([
|
|
245
|
-
"+--+",
|
|
246
|
-
"| |",
|
|
247
|
-
"+--+"
|
|
248
|
-
]);
|
|
249
|
-
Vitest.test("finds all corners using index", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
250
|
-
let corners = Grid.findAll(grid, "Corner");
|
|
251
|
-
t.expect(corners.length).toBe(4);
|
|
252
|
-
});
|
|
253
|
-
Vitest.test("finds all horizontal lines using index", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
254
|
-
let hlines = Grid.findAll(grid, "HLine");
|
|
255
|
-
t.expect(hlines.length).toBe(4);
|
|
256
|
-
});
|
|
257
|
-
Vitest.test("finds all vertical lines using index", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
258
|
-
let vlines = Grid.findAll(grid, "VLine");
|
|
259
|
-
t.expect(vlines.length).toBe(2);
|
|
260
|
-
});
|
|
261
|
-
Vitest.test("finds spaces through scanning", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
262
|
-
let spaces = Grid.findAll(grid, "Space");
|
|
263
|
-
t.expect(spaces.length).toBe(2);
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
Vitest.describe("findInRange", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
|
|
267
|
-
let grid = Grid.fromLines([
|
|
268
|
-
"+--+",
|
|
269
|
-
"| |",
|
|
270
|
-
"+--+",
|
|
271
|
-
"| |",
|
|
272
|
-
"+--+"
|
|
273
|
-
]);
|
|
274
|
-
Vitest.test("finds characters within bounds", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
275
|
-
let corners = Grid.findInRange(grid, "Corner", {
|
|
276
|
-
top: 0,
|
|
277
|
-
left: 0,
|
|
278
|
-
bottom: 3,
|
|
279
|
-
right: 4
|
|
280
|
-
});
|
|
281
|
-
t.expect(corners.length).toBe(4);
|
|
282
|
-
});
|
|
283
|
-
Vitest.test("excludes characters outside bounds", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
284
|
-
let corners = Grid.findInRange(grid, "Corner", {
|
|
285
|
-
top: 1,
|
|
286
|
-
left: 1,
|
|
287
|
-
bottom: 2,
|
|
288
|
-
right: 2
|
|
289
|
-
});
|
|
290
|
-
t.expect(corners.length).toBe(0);
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
Vitest.describe("isValidPosition", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
|
|
294
|
-
let grid = Grid.fromLines([
|
|
295
|
-
"+--+",
|
|
296
|
-
"| |",
|
|
297
|
-
"+--+"
|
|
298
|
-
]);
|
|
299
|
-
Vitest.test("returns true for valid positions", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
300
|
-
t.expect(Grid.isValidPosition(grid, Types.Position.make(0, 0))).toBe(true);
|
|
301
|
-
t.expect(Grid.isValidPosition(grid, Types.Position.make(1, 2))).toBe(true);
|
|
302
|
-
t.expect(Grid.isValidPosition(grid, Types.Position.make(2, 3))).toBe(true);
|
|
303
|
-
});
|
|
304
|
-
Vitest.test("returns false for out of bounds positions", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
305
|
-
t.expect(Grid.isValidPosition(grid, Types.Position.make(-1, 0))).toBe(false);
|
|
306
|
-
t.expect(Grid.isValidPosition(grid, Types.Position.make(0, -1))).toBe(false);
|
|
307
|
-
t.expect(Grid.isValidPosition(grid, Types.Position.make(10, 0))).toBe(false);
|
|
308
|
-
t.expect(Grid.isValidPosition(grid, Types.Position.make(0, 10))).toBe(false);
|
|
309
|
-
});
|
|
310
|
-
});
|
|
311
|
-
Vitest.describe("Performance", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => Vitest.test("handles large grids efficiently", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
|
|
312
|
-
let lines = Core__Array.make(1000, "+----+");
|
|
313
|
-
let startTime = Date.now();
|
|
314
|
-
let grid = Grid.fromLines(lines);
|
|
315
|
-
let endTime = Date.now();
|
|
316
|
-
let duration = endTime - startTime;
|
|
317
|
-
t.expect(grid.height).toBe(1000);
|
|
318
|
-
t.expect(duration).toBeLessThan(10.0);
|
|
319
|
-
}));
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
/* Not a pure module */
|
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
// Grid_test.res
|
|
2
|
-
// Unit tests for Grid module
|
|
3
|
-
|
|
4
|
-
open Vitest
|
|
5
|
-
|
|
6
|
-
describe("Grid", () => {
|
|
7
|
-
open Grid
|
|
8
|
-
|
|
9
|
-
describe("fromLines", () => {
|
|
10
|
-
test("creates correct dimensions for equal-length lines", t => {
|
|
11
|
-
let lines = ["abc", "def", "ghi"]
|
|
12
|
-
let grid = fromLines(lines)
|
|
13
|
-
|
|
14
|
-
t->expect(grid.width)->Expect.toBe(3)
|
|
15
|
-
t->expect(grid.height)->Expect.toBe(3)
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
test("normalizes uneven line lengths by padding", t => {
|
|
19
|
-
let lines = ["abc", "de", "f"]
|
|
20
|
-
let grid = fromLines(lines)
|
|
21
|
-
|
|
22
|
-
t->expect(grid.width)->Expect.toBe(3)
|
|
23
|
-
t->expect(grid.height)->Expect.toBe(3)
|
|
24
|
-
|
|
25
|
-
// Check that shorter lines are padded with spaces
|
|
26
|
-
switch getLine(grid, 1) {
|
|
27
|
-
| Some(line) => {
|
|
28
|
-
t->expect(Array.length(line))->Expect.toBe(3)
|
|
29
|
-
t->expect(Array.get(line, 2))->Expect.toEqual(Some(Types.Space))
|
|
30
|
-
}
|
|
31
|
-
| None => t->expect(true)->Expect.toBe(false) // fail
|
|
32
|
-
}
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
test("handles empty input", t => {
|
|
36
|
-
let grid = fromLines([])
|
|
37
|
-
t->expect(grid.width)->Expect.toBe(0)
|
|
38
|
-
t->expect(grid.height)->Expect.toBe(0)
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
test("correctly identifies special characters", t => {
|
|
42
|
-
let lines = ["+--+", "| |", "+==+"]
|
|
43
|
-
let grid = fromLines(lines)
|
|
44
|
-
|
|
45
|
-
t->expect(Array.length(grid.cornerIndex))->Expect.toBe(4)
|
|
46
|
-
// HLine (-) only appears on row 0: positions (0,1) and (0,2) = 2
|
|
47
|
-
// Divider (=) appears on row 2: positions (2,1) and (2,2) = 2
|
|
48
|
-
t->expect(Array.length(grid.hLineIndex))->Expect.toBe(2)
|
|
49
|
-
t->expect(Array.length(grid.vLineIndex))->Expect.toBe(2)
|
|
50
|
-
t->expect(Array.length(grid.dividerIndex))->Expect.toBe(2)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
test("builds character indices with correct positions", t => {
|
|
54
|
-
let lines = ["+--+"]
|
|
55
|
-
let grid = fromLines(lines)
|
|
56
|
-
|
|
57
|
-
// Check corner positions
|
|
58
|
-
t->expect(Array.get(grid.cornerIndex, 0))->Expect.toEqual(Some({Types.Position.row: 0, col: 0}))
|
|
59
|
-
t->expect(Array.get(grid.cornerIndex, 1))->Expect.toEqual(Some({Types.Position.row: 0, col: 3}))
|
|
60
|
-
})
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
describe("get", () => {
|
|
64
|
-
let grid = fromLines(["+--+", "| |", "+--+"])
|
|
65
|
-
|
|
66
|
-
test("returns character at valid position", t => {
|
|
67
|
-
t->expect(get(grid, Types.Position.make(0, 0)))->Expect.toEqual(Some(Types.Corner))
|
|
68
|
-
t->expect(get(grid, Types.Position.make(0, 1)))->Expect.toEqual(Some(Types.HLine))
|
|
69
|
-
t->expect(get(grid, Types.Position.make(1, 0)))->Expect.toEqual(Some(Types.VLine))
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
test("returns None for out of bounds positions", t => {
|
|
73
|
-
t->expect(get(grid, Types.Position.make(-1, 0)))->Expect.toBe(None)
|
|
74
|
-
t->expect(get(grid, Types.Position.make(0, -1)))->Expect.toBe(None)
|
|
75
|
-
t->expect(get(grid, Types.Position.make(10, 0)))->Expect.toBe(None)
|
|
76
|
-
t->expect(get(grid, Types.Position.make(0, 10)))->Expect.toBe(None)
|
|
77
|
-
})
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
describe("getLine", () => {
|
|
81
|
-
let grid = fromLines(["+--+", "| |", "+--+"])
|
|
82
|
-
|
|
83
|
-
test("returns entire line at valid row", t => {
|
|
84
|
-
switch getLine(grid, 0) {
|
|
85
|
-
| Some(line) => {
|
|
86
|
-
t->expect(Array.length(line))->Expect.toBe(4)
|
|
87
|
-
t->expect(Array.get(line, 0))->Expect.toEqual(Some(Types.Corner))
|
|
88
|
-
}
|
|
89
|
-
| None => t->expect(true)->Expect.toBe(false) // fail
|
|
90
|
-
}
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
test("returns None for out of bounds row", t => {
|
|
94
|
-
t->expect(getLine(grid, -1))->Expect.toBe(None)
|
|
95
|
-
t->expect(getLine(grid, 10))->Expect.toBe(None)
|
|
96
|
-
})
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
describe("getRange", () => {
|
|
100
|
-
let grid = fromLines(["+--Name--+"])
|
|
101
|
-
|
|
102
|
-
test("returns range of characters", t => {
|
|
103
|
-
switch getRange(grid, 0, ~startCol=1, ~endCol=3) {
|
|
104
|
-
| Some(range) => {
|
|
105
|
-
t->expect(Array.length(range))->Expect.toBe(3)
|
|
106
|
-
t->expect(Array.get(range, 0))->Expect.toEqual(Some(Types.HLine))
|
|
107
|
-
}
|
|
108
|
-
| None => t->expect(true)->Expect.toBe(false) // fail
|
|
109
|
-
}
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
test("handles negative start column", t => {
|
|
113
|
-
switch getRange(grid, 0, ~startCol=-1, ~endCol=2) {
|
|
114
|
-
| Some(range) => {
|
|
115
|
-
t->expect(Array.length(range))->Expect.toBe(3)
|
|
116
|
-
}
|
|
117
|
-
| None => t->expect(true)->Expect.toBe(false) // fail
|
|
118
|
-
}
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
test("returns None for invalid row", t => {
|
|
122
|
-
t->expect(getRange(grid, -1, ~startCol=0, ~endCol=2))->Expect.toBe(None)
|
|
123
|
-
})
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
describe("scanRight", () => {
|
|
127
|
-
let grid = fromLines(["+----+"])
|
|
128
|
-
|
|
129
|
-
test("scans right until predicate fails", t => {
|
|
130
|
-
let start = Types.Position.make(0, 0)
|
|
131
|
-
let results = scanRight(grid, start, cell =>
|
|
132
|
-
switch cell {
|
|
133
|
-
| Types.Corner | Types.HLine => true
|
|
134
|
-
| _ => false
|
|
135
|
-
}
|
|
136
|
-
)
|
|
137
|
-
|
|
138
|
-
t->expect(Array.length(results))->Expect.toBe(6)
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
test("stops at grid boundary", t => {
|
|
142
|
-
let start = Types.Position.make(0, 0)
|
|
143
|
-
let results = scanRight(grid, start, _cell => true)
|
|
144
|
-
|
|
145
|
-
t->expect(Array.length(results))->Expect.toBe(6)
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
test("returns empty array if predicate fails immediately", t => {
|
|
149
|
-
let start = Types.Position.make(0, 0)
|
|
150
|
-
let results = scanRight(grid, start, cell =>
|
|
151
|
-
switch cell {
|
|
152
|
-
| Types.HLine => true
|
|
153
|
-
| _ => false
|
|
154
|
-
}
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
t->expect(Array.length(results))->Expect.toBe(0)
|
|
158
|
-
})
|
|
159
|
-
})
|
|
160
|
-
|
|
161
|
-
describe("scanDown", () => {
|
|
162
|
-
let grid = fromLines(["+", "|", "|", "+"])
|
|
163
|
-
|
|
164
|
-
test("scans down until predicate fails", t => {
|
|
165
|
-
let start = Types.Position.make(0, 0)
|
|
166
|
-
let results = scanDown(grid, start, cell =>
|
|
167
|
-
switch cell {
|
|
168
|
-
| Types.Corner | Types.VLine => true
|
|
169
|
-
| _ => false
|
|
170
|
-
}
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
t->expect(Array.length(results))->Expect.toBe(4)
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
test("stops at grid boundary", t => {
|
|
177
|
-
let start = Types.Position.make(0, 0)
|
|
178
|
-
let results = scanDown(grid, start, _cell => true)
|
|
179
|
-
|
|
180
|
-
t->expect(Array.length(results))->Expect.toBe(4)
|
|
181
|
-
})
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
describe("scanLeft", () => {
|
|
185
|
-
let grid = fromLines(["+----+"])
|
|
186
|
-
|
|
187
|
-
test("scans left until predicate fails", t => {
|
|
188
|
-
let start = Types.Position.make(0, 5)
|
|
189
|
-
let results = scanLeft(grid, start, cell =>
|
|
190
|
-
switch cell {
|
|
191
|
-
| Types.Corner | Types.HLine => true
|
|
192
|
-
| _ => false
|
|
193
|
-
}
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
t->expect(Array.length(results))->Expect.toBe(6)
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
test("stops at grid boundary", t => {
|
|
200
|
-
let start = Types.Position.make(0, 5)
|
|
201
|
-
let results = scanLeft(grid, start, _cell => true)
|
|
202
|
-
|
|
203
|
-
t->expect(Array.length(results))->Expect.toBe(6)
|
|
204
|
-
})
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
describe("scanUp", () => {
|
|
208
|
-
let grid = fromLines(["+", "|", "|", "+"])
|
|
209
|
-
|
|
210
|
-
test("scans up until predicate fails", t => {
|
|
211
|
-
let start = Types.Position.make(3, 0)
|
|
212
|
-
let results = scanUp(grid, start, cell =>
|
|
213
|
-
switch cell {
|
|
214
|
-
| Types.Corner | Types.VLine => true
|
|
215
|
-
| _ => false
|
|
216
|
-
}
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
t->expect(Array.length(results))->Expect.toBe(4)
|
|
220
|
-
})
|
|
221
|
-
|
|
222
|
-
test("stops at grid boundary", t => {
|
|
223
|
-
let start = Types.Position.make(3, 0)
|
|
224
|
-
let results = scanUp(grid, start, _cell => true)
|
|
225
|
-
|
|
226
|
-
t->expect(Array.length(results))->Expect.toBe(4)
|
|
227
|
-
})
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
describe("findAll", () => {
|
|
231
|
-
let grid = fromLines(["+--+", "| |", "+--+"])
|
|
232
|
-
|
|
233
|
-
test("finds all corners using index", t => {
|
|
234
|
-
let corners = findAll(grid, Types.Corner)
|
|
235
|
-
t->expect(Array.length(corners))->Expect.toBe(4)
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
test("finds all horizontal lines using index", t => {
|
|
239
|
-
let hlines = findAll(grid, Types.HLine)
|
|
240
|
-
t->expect(Array.length(hlines))->Expect.toBe(4)
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
test("finds all vertical lines using index", t => {
|
|
244
|
-
let vlines = findAll(grid, Types.VLine)
|
|
245
|
-
t->expect(Array.length(vlines))->Expect.toBe(2)
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
test("finds spaces through scanning", t => {
|
|
249
|
-
let spaces = findAll(grid, Types.Space)
|
|
250
|
-
t->expect(Array.length(spaces))->Expect.toBe(2)
|
|
251
|
-
})
|
|
252
|
-
})
|
|
253
|
-
|
|
254
|
-
describe("findInRange", () => {
|
|
255
|
-
let grid = fromLines(["+--+", "| |", "+--+", "| |", "+--+"])
|
|
256
|
-
|
|
257
|
-
test("finds characters within bounds", t => {
|
|
258
|
-
// Create bounds that only include first box
|
|
259
|
-
let bounds: Types.Bounds.t = {
|
|
260
|
-
top: 0,
|
|
261
|
-
left: 0,
|
|
262
|
-
bottom: 3,
|
|
263
|
-
right: 4,
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
let corners = findInRange(grid, Types.Corner, bounds)
|
|
267
|
-
t->expect(Array.length(corners))->Expect.toBe(4)
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
test("excludes characters outside bounds", t => {
|
|
271
|
-
// Create tight bounds that exclude all corners
|
|
272
|
-
// Corners are at (0,0), (0,3), (2,0), (2,3), (4,0), (4,3)
|
|
273
|
-
// These bounds (row 1-2, col 1-2) don't contain any corners
|
|
274
|
-
let bounds: Types.Bounds.t = {
|
|
275
|
-
top: 1,
|
|
276
|
-
left: 1,
|
|
277
|
-
bottom: 2,
|
|
278
|
-
right: 2,
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
let corners = findInRange(grid, Types.Corner, bounds)
|
|
282
|
-
t->expect(Array.length(corners))->Expect.toBe(0)
|
|
283
|
-
})
|
|
284
|
-
})
|
|
285
|
-
|
|
286
|
-
describe("isValidPosition", () => {
|
|
287
|
-
let grid = fromLines(["+--+", "| |", "+--+"])
|
|
288
|
-
|
|
289
|
-
test("returns true for valid positions", t => {
|
|
290
|
-
t->expect(isValidPosition(grid, Types.Position.make(0, 0)))->Expect.toBe(true)
|
|
291
|
-
t->expect(isValidPosition(grid, Types.Position.make(1, 2)))->Expect.toBe(true)
|
|
292
|
-
t->expect(isValidPosition(grid, Types.Position.make(2, 3)))->Expect.toBe(true)
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
test("returns false for out of bounds positions", t => {
|
|
296
|
-
t->expect(isValidPosition(grid, Types.Position.make(-1, 0)))->Expect.toBe(false)
|
|
297
|
-
t->expect(isValidPosition(grid, Types.Position.make(0, -1)))->Expect.toBe(false)
|
|
298
|
-
t->expect(isValidPosition(grid, Types.Position.make(10, 0)))->Expect.toBe(false)
|
|
299
|
-
t->expect(isValidPosition(grid, Types.Position.make(0, 10)))->Expect.toBe(false)
|
|
300
|
-
})
|
|
301
|
-
})
|
|
302
|
-
|
|
303
|
-
describe("Performance", () => {
|
|
304
|
-
test("handles large grids efficiently", t => {
|
|
305
|
-
// Generate a large grid (1000 lines)
|
|
306
|
-
let lines = Array.make(~length=1000, "+----+")
|
|
307
|
-
|
|
308
|
-
let startTime = Date.now()
|
|
309
|
-
let grid = fromLines(lines)
|
|
310
|
-
let endTime = Date.now()
|
|
311
|
-
|
|
312
|
-
let duration = endTime -. startTime
|
|
313
|
-
|
|
314
|
-
t->expect(grid.height)->Expect.toBe(1000)
|
|
315
|
-
// Performance requirement: should be < 10ms
|
|
316
|
-
t->expect(duration)->Expect.Float.toBeLessThan(10.0)
|
|
317
|
-
})
|
|
318
|
-
})
|
|
319
|
-
})
|