@ripplo/testing 0.0.6 → 0.0.7

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/README.md CHANGED
@@ -14,9 +14,20 @@ npm install @ripplo/testing
14
14
  2. Define preconditions in `.ripplo/preconditions/`, then add `import "./preconditions/<file>.js";` to `.ripplo/index.ts`. Exports set up test data (users, projects, etc.)
15
15
  3. Write tests in `.ripplo/tests/`, then add `import "./tests/<id>.js";` to `.ripplo/index.ts`. The CLI only loads what that file imports.
16
16
  4. Run `npx ripplo lint` to validate, `npx ripplo run` to execute
17
+ 5. Commit the generated `.ripplo/ripplo.lock` alongside your DSL changes (see Lockfile below)
17
18
 
18
19
  Every test gets a clean slate via preconditions — no shared state, no ordering dependencies, fully parallelizable.
19
20
 
21
+ ## Lockfile
22
+
23
+ `npx ripplo compile` (and `ripplo lint`, and the dashboard's file watcher) writes `.ripplo/ripplo.lock` — a JSON artifact containing the compiled graph + tests, plus a `lockfileVersion` field. **Commit it.**
24
+
25
+ The Ripplo server reads the lockfile on every GitHub push webhook. If the lockfile is missing or out of date, the branch does not sync and the webhook returns 422.
26
+
27
+ - `ripplo compile` — compile + write (default).
28
+ - `ripplo compile --check` — exit non-zero if the lockfile is missing or stale. Use in pre-commit hooks or CI.
29
+ - `ripplo doctor` — surfaces stale lockfiles and a missing pre-commit hook.
30
+
20
31
  ## DSL API
21
32
 
22
33
  ### Test Builder
@@ -0,0 +1,723 @@
1
+ import { z } from 'zod';
2
+ import { CompileResult } from './compiler.js';
3
+ import '@ripplo/spec';
4
+ import './builder-DTWMrbuv.js';
5
+ import './step-DLfkKI3V.js';
6
+
7
+ declare const LOCKFILE_VERSION = 1;
8
+ declare const LOCKFILE_RELATIVE_PATH = ".ripplo/ripplo.lock";
9
+ declare const lockfileSchema: z.ZodObject<{
10
+ graph: z.ZodObject<{
11
+ edges: z.ZodArray<z.ZodObject<{
12
+ from: z.ZodString;
13
+ requiresKeys: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
14
+ to: z.ZodString;
15
+ workflow: z.ZodString;
16
+ }, z.core.$strip>>;
17
+ preconditions: z.ZodRecord<z.ZodString, z.ZodObject<{
18
+ depends: z.ZodOptional<z.ZodArray<z.ZodString>>;
19
+ description: z.ZodString;
20
+ returns: z.ZodOptional<z.ZodArray<z.ZodString>>;
21
+ }, z.core.$strip>>;
22
+ states: z.ZodRecord<z.ZodString, z.ZodObject<{
23
+ preconditions: z.ZodArray<z.ZodString>;
24
+ route: z.ZodString;
25
+ }, z.core.$strip>>;
26
+ version: z.ZodLiteral<3>;
27
+ }, z.core.$strip>;
28
+ lockfileVersion: z.ZodNumber;
29
+ tests: z.ZodArray<z.ZodObject<{
30
+ additionalChecks: z.ZodArray<z.ZodString>;
31
+ description: z.ZodString;
32
+ expectedOutcome: z.ZodString;
33
+ implemented: z.ZodBoolean;
34
+ name: z.ZodString;
35
+ slug: z.ZodString;
36
+ spec: z.ZodObject<{
37
+ entryNode: z.ZodString;
38
+ nodes: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
39
+ type: z.ZodLiteral<"goto">;
40
+ url: z.ZodDiscriminatedUnion<[z.ZodObject<{
41
+ type: z.ZodLiteral<"static">;
42
+ value: z.ZodString;
43
+ }, z.core.$strip>, z.ZodObject<{
44
+ name: z.ZodString;
45
+ type: z.ZodLiteral<"variable">;
46
+ }, z.core.$strip>], "type">;
47
+ comment: z.ZodOptional<z.ZodString>;
48
+ id: z.ZodString;
49
+ label: z.ZodOptional<z.ZodString>;
50
+ next: z.ZodOptional<z.ZodString>;
51
+ timeout: z.ZodOptional<z.ZodNumber>;
52
+ }, z.core.$strip>, z.ZodObject<{
53
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
54
+ by: z.ZodLiteral<"testId">;
55
+ value: z.ZodString;
56
+ }, z.core.$strip>, z.ZodObject<{
57
+ by: z.ZodLiteral<"role">;
58
+ name: z.ZodOptional<z.ZodString>;
59
+ role: z.ZodString;
60
+ }, z.core.$strip>], "by">;
61
+ type: z.ZodLiteral<"click">;
62
+ comment: z.ZodOptional<z.ZodString>;
63
+ id: z.ZodString;
64
+ label: z.ZodOptional<z.ZodString>;
65
+ next: z.ZodOptional<z.ZodString>;
66
+ timeout: z.ZodOptional<z.ZodNumber>;
67
+ }, z.core.$strip>, z.ZodObject<{
68
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
69
+ by: z.ZodLiteral<"testId">;
70
+ value: z.ZodString;
71
+ }, z.core.$strip>, z.ZodObject<{
72
+ by: z.ZodLiteral<"role">;
73
+ name: z.ZodOptional<z.ZodString>;
74
+ role: z.ZodString;
75
+ }, z.core.$strip>], "by">;
76
+ type: z.ZodLiteral<"fill">;
77
+ value: z.ZodDiscriminatedUnion<[z.ZodObject<{
78
+ type: z.ZodLiteral<"static">;
79
+ value: z.ZodString;
80
+ }, z.core.$strip>, z.ZodObject<{
81
+ name: z.ZodString;
82
+ type: z.ZodLiteral<"variable">;
83
+ }, z.core.$strip>], "type">;
84
+ comment: z.ZodOptional<z.ZodString>;
85
+ id: z.ZodString;
86
+ label: z.ZodOptional<z.ZodString>;
87
+ next: z.ZodOptional<z.ZodString>;
88
+ timeout: z.ZodOptional<z.ZodNumber>;
89
+ }, z.core.$strip>, z.ZodObject<{
90
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
91
+ by: z.ZodLiteral<"testId">;
92
+ value: z.ZodString;
93
+ }, z.core.$strip>, z.ZodObject<{
94
+ by: z.ZodLiteral<"role">;
95
+ name: z.ZodOptional<z.ZodString>;
96
+ role: z.ZodString;
97
+ }, z.core.$strip>], "by">;
98
+ type: z.ZodLiteral<"select">;
99
+ value: z.ZodDiscriminatedUnion<[z.ZodObject<{
100
+ type: z.ZodLiteral<"static">;
101
+ value: z.ZodString;
102
+ }, z.core.$strip>, z.ZodObject<{
103
+ name: z.ZodString;
104
+ type: z.ZodLiteral<"variable">;
105
+ }, z.core.$strip>], "type">;
106
+ comment: z.ZodOptional<z.ZodString>;
107
+ id: z.ZodString;
108
+ label: z.ZodOptional<z.ZodString>;
109
+ next: z.ZodOptional<z.ZodString>;
110
+ timeout: z.ZodOptional<z.ZodNumber>;
111
+ }, z.core.$strip>, z.ZodObject<{
112
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
113
+ by: z.ZodLiteral<"testId">;
114
+ value: z.ZodString;
115
+ }, z.core.$strip>, z.ZodObject<{
116
+ by: z.ZodLiteral<"role">;
117
+ name: z.ZodOptional<z.ZodString>;
118
+ role: z.ZodString;
119
+ }, z.core.$strip>], "by">;
120
+ type: z.ZodLiteral<"hover">;
121
+ comment: z.ZodOptional<z.ZodString>;
122
+ id: z.ZodString;
123
+ label: z.ZodOptional<z.ZodString>;
124
+ next: z.ZodOptional<z.ZodString>;
125
+ timeout: z.ZodOptional<z.ZodNumber>;
126
+ }, z.core.$strip>, z.ZodObject<{
127
+ key: z.ZodString;
128
+ locator: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
129
+ by: z.ZodLiteral<"testId">;
130
+ value: z.ZodString;
131
+ }, z.core.$strip>, z.ZodObject<{
132
+ by: z.ZodLiteral<"role">;
133
+ name: z.ZodOptional<z.ZodString>;
134
+ role: z.ZodString;
135
+ }, z.core.$strip>], "by">>;
136
+ type: z.ZodLiteral<"press">;
137
+ comment: z.ZodOptional<z.ZodString>;
138
+ id: z.ZodString;
139
+ label: z.ZodOptional<z.ZodString>;
140
+ next: z.ZodOptional<z.ZodString>;
141
+ timeout: z.ZodOptional<z.ZodNumber>;
142
+ }, z.core.$strip>, z.ZodObject<{
143
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
144
+ by: z.ZodLiteral<"testId">;
145
+ value: z.ZodString;
146
+ }, z.core.$strip>, z.ZodObject<{
147
+ by: z.ZodLiteral<"role">;
148
+ name: z.ZodOptional<z.ZodString>;
149
+ role: z.ZodString;
150
+ }, z.core.$strip>], "by">;
151
+ type: z.ZodLiteral<"check">;
152
+ comment: z.ZodOptional<z.ZodString>;
153
+ id: z.ZodString;
154
+ label: z.ZodOptional<z.ZodString>;
155
+ next: z.ZodOptional<z.ZodString>;
156
+ timeout: z.ZodOptional<z.ZodNumber>;
157
+ }, z.core.$strip>, z.ZodObject<{
158
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
159
+ by: z.ZodLiteral<"testId">;
160
+ value: z.ZodString;
161
+ }, z.core.$strip>, z.ZodObject<{
162
+ by: z.ZodLiteral<"role">;
163
+ name: z.ZodOptional<z.ZodString>;
164
+ role: z.ZodString;
165
+ }, z.core.$strip>], "by">;
166
+ type: z.ZodLiteral<"uncheck">;
167
+ comment: z.ZodOptional<z.ZodString>;
168
+ id: z.ZodString;
169
+ label: z.ZodOptional<z.ZodString>;
170
+ next: z.ZodOptional<z.ZodString>;
171
+ timeout: z.ZodOptional<z.ZodNumber>;
172
+ }, z.core.$strip>, z.ZodObject<{
173
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
174
+ by: z.ZodLiteral<"testId">;
175
+ value: z.ZodString;
176
+ }, z.core.$strip>, z.ZodObject<{
177
+ by: z.ZodLiteral<"role">;
178
+ name: z.ZodOptional<z.ZodString>;
179
+ role: z.ZodString;
180
+ }, z.core.$strip>], "by">;
181
+ type: z.ZodLiteral<"assertVisible">;
182
+ comment: z.ZodOptional<z.ZodString>;
183
+ id: z.ZodString;
184
+ label: z.ZodOptional<z.ZodString>;
185
+ next: z.ZodOptional<z.ZodString>;
186
+ timeout: z.ZodOptional<z.ZodNumber>;
187
+ }, z.core.$strip>, z.ZodObject<{
188
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
189
+ by: z.ZodLiteral<"testId">;
190
+ value: z.ZodString;
191
+ }, z.core.$strip>, z.ZodObject<{
192
+ by: z.ZodLiteral<"role">;
193
+ name: z.ZodOptional<z.ZodString>;
194
+ role: z.ZodString;
195
+ }, z.core.$strip>], "by">;
196
+ type: z.ZodLiteral<"assertNotVisible">;
197
+ comment: z.ZodOptional<z.ZodString>;
198
+ id: z.ZodString;
199
+ label: z.ZodOptional<z.ZodString>;
200
+ next: z.ZodOptional<z.ZodString>;
201
+ timeout: z.ZodOptional<z.ZodNumber>;
202
+ }, z.core.$strip>, z.ZodObject<{
203
+ expected: z.ZodDiscriminatedUnion<[z.ZodObject<{
204
+ type: z.ZodLiteral<"static">;
205
+ value: z.ZodString;
206
+ }, z.core.$strip>, z.ZodObject<{
207
+ name: z.ZodString;
208
+ type: z.ZodLiteral<"variable">;
209
+ }, z.core.$strip>], "type">;
210
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
211
+ by: z.ZodLiteral<"testId">;
212
+ value: z.ZodString;
213
+ }, z.core.$strip>, z.ZodObject<{
214
+ by: z.ZodLiteral<"role">;
215
+ name: z.ZodOptional<z.ZodString>;
216
+ role: z.ZodString;
217
+ }, z.core.$strip>], "by">;
218
+ operator: z.ZodEnum<{
219
+ equals: "equals";
220
+ notEquals: "notEquals";
221
+ contains: "contains";
222
+ startsWith: "startsWith";
223
+ endsWith: "endsWith";
224
+ matches: "matches";
225
+ }>;
226
+ type: z.ZodLiteral<"assertText">;
227
+ comment: z.ZodOptional<z.ZodString>;
228
+ id: z.ZodString;
229
+ label: z.ZodOptional<z.ZodString>;
230
+ next: z.ZodOptional<z.ZodString>;
231
+ timeout: z.ZodOptional<z.ZodNumber>;
232
+ }, z.core.$strip>, z.ZodObject<{
233
+ expected: z.ZodDiscriminatedUnion<[z.ZodObject<{
234
+ type: z.ZodLiteral<"static">;
235
+ value: z.ZodString;
236
+ }, z.core.$strip>, z.ZodObject<{
237
+ name: z.ZodString;
238
+ type: z.ZodLiteral<"variable">;
239
+ }, z.core.$strip>], "type">;
240
+ operator: z.ZodEnum<{
241
+ equals: "equals";
242
+ notEquals: "notEquals";
243
+ contains: "contains";
244
+ startsWith: "startsWith";
245
+ endsWith: "endsWith";
246
+ matches: "matches";
247
+ }>;
248
+ type: z.ZodLiteral<"assertUrl">;
249
+ comment: z.ZodOptional<z.ZodString>;
250
+ id: z.ZodString;
251
+ label: z.ZodOptional<z.ZodString>;
252
+ next: z.ZodOptional<z.ZodString>;
253
+ timeout: z.ZodOptional<z.ZodNumber>;
254
+ }, z.core.$strip>, z.ZodObject<{
255
+ expected: z.ZodDiscriminatedUnion<[z.ZodObject<{
256
+ type: z.ZodLiteral<"static">;
257
+ value: z.ZodNumber;
258
+ }, z.core.$strip>, z.ZodObject<{
259
+ name: z.ZodString;
260
+ type: z.ZodLiteral<"variable">;
261
+ }, z.core.$strip>], "type">;
262
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
263
+ by: z.ZodLiteral<"testId">;
264
+ value: z.ZodString;
265
+ }, z.core.$strip>, z.ZodObject<{
266
+ by: z.ZodLiteral<"role">;
267
+ name: z.ZodOptional<z.ZodString>;
268
+ role: z.ZodString;
269
+ }, z.core.$strip>], "by">;
270
+ operator: z.ZodEnum<{
271
+ equals: "equals";
272
+ notEquals: "notEquals";
273
+ greaterThan: "greaterThan";
274
+ greaterThanOrEqual: "greaterThanOrEqual";
275
+ lessThan: "lessThan";
276
+ lessThanOrEqual: "lessThanOrEqual";
277
+ }>;
278
+ type: z.ZodLiteral<"assertCount">;
279
+ comment: z.ZodOptional<z.ZodString>;
280
+ id: z.ZodString;
281
+ label: z.ZodOptional<z.ZodString>;
282
+ next: z.ZodOptional<z.ZodString>;
283
+ timeout: z.ZodOptional<z.ZodNumber>;
284
+ }, z.core.$strip>, z.ZodObject<{
285
+ expected: z.ZodDiscriminatedUnion<[z.ZodObject<{
286
+ type: z.ZodLiteral<"static">;
287
+ value: z.ZodString;
288
+ }, z.core.$strip>, z.ZodObject<{
289
+ name: z.ZodString;
290
+ type: z.ZodLiteral<"variable">;
291
+ }, z.core.$strip>], "type">;
292
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
293
+ by: z.ZodLiteral<"testId">;
294
+ value: z.ZodString;
295
+ }, z.core.$strip>, z.ZodObject<{
296
+ by: z.ZodLiteral<"role">;
297
+ name: z.ZodOptional<z.ZodString>;
298
+ role: z.ZodString;
299
+ }, z.core.$strip>], "by">;
300
+ operator: z.ZodEnum<{
301
+ equals: "equals";
302
+ notEquals: "notEquals";
303
+ contains: "contains";
304
+ startsWith: "startsWith";
305
+ endsWith: "endsWith";
306
+ matches: "matches";
307
+ }>;
308
+ type: z.ZodLiteral<"assertValue">;
309
+ comment: z.ZodOptional<z.ZodString>;
310
+ id: z.ZodString;
311
+ label: z.ZodOptional<z.ZodString>;
312
+ next: z.ZodOptional<z.ZodString>;
313
+ timeout: z.ZodOptional<z.ZodNumber>;
314
+ }, z.core.$strip>, z.ZodObject<{
315
+ attribute: z.ZodString;
316
+ expected: z.ZodDiscriminatedUnion<[z.ZodObject<{
317
+ type: z.ZodLiteral<"static">;
318
+ value: z.ZodString;
319
+ }, z.core.$strip>, z.ZodObject<{
320
+ name: z.ZodString;
321
+ type: z.ZodLiteral<"variable">;
322
+ }, z.core.$strip>], "type">;
323
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
324
+ by: z.ZodLiteral<"testId">;
325
+ value: z.ZodString;
326
+ }, z.core.$strip>, z.ZodObject<{
327
+ by: z.ZodLiteral<"role">;
328
+ name: z.ZodOptional<z.ZodString>;
329
+ role: z.ZodString;
330
+ }, z.core.$strip>], "by">;
331
+ operator: z.ZodEnum<{
332
+ equals: "equals";
333
+ notEquals: "notEquals";
334
+ contains: "contains";
335
+ startsWith: "startsWith";
336
+ endsWith: "endsWith";
337
+ matches: "matches";
338
+ }>;
339
+ type: z.ZodLiteral<"assertAttribute">;
340
+ comment: z.ZodOptional<z.ZodString>;
341
+ id: z.ZodString;
342
+ label: z.ZodOptional<z.ZodString>;
343
+ next: z.ZodOptional<z.ZodString>;
344
+ timeout: z.ZodOptional<z.ZodNumber>;
345
+ }, z.core.$strip>, z.ZodObject<{
346
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
347
+ by: z.ZodLiteral<"testId">;
348
+ value: z.ZodString;
349
+ }, z.core.$strip>, z.ZodObject<{
350
+ by: z.ZodLiteral<"role">;
351
+ name: z.ZodOptional<z.ZodString>;
352
+ role: z.ZodString;
353
+ }, z.core.$strip>], "by">;
354
+ type: z.ZodLiteral<"assertEnabled">;
355
+ comment: z.ZodOptional<z.ZodString>;
356
+ id: z.ZodString;
357
+ label: z.ZodOptional<z.ZodString>;
358
+ next: z.ZodOptional<z.ZodString>;
359
+ timeout: z.ZodOptional<z.ZodNumber>;
360
+ }, z.core.$strip>, z.ZodObject<{
361
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
362
+ by: z.ZodLiteral<"testId">;
363
+ value: z.ZodString;
364
+ }, z.core.$strip>, z.ZodObject<{
365
+ by: z.ZodLiteral<"role">;
366
+ name: z.ZodOptional<z.ZodString>;
367
+ role: z.ZodString;
368
+ }, z.core.$strip>], "by">;
369
+ type: z.ZodLiteral<"assertDisabled">;
370
+ comment: z.ZodOptional<z.ZodString>;
371
+ id: z.ZodString;
372
+ label: z.ZodOptional<z.ZodString>;
373
+ next: z.ZodOptional<z.ZodString>;
374
+ timeout: z.ZodOptional<z.ZodNumber>;
375
+ }, z.core.$strip>, z.ZodObject<{
376
+ height: z.ZodNumber;
377
+ type: z.ZodLiteral<"setViewport">;
378
+ width: z.ZodNumber;
379
+ comment: z.ZodOptional<z.ZodString>;
380
+ id: z.ZodString;
381
+ label: z.ZodOptional<z.ZodString>;
382
+ next: z.ZodOptional<z.ZodString>;
383
+ timeout: z.ZodOptional<z.ZodNumber>;
384
+ }, z.core.$strip>, z.ZodObject<{
385
+ message: z.ZodString;
386
+ type: z.ZodLiteral<"fail">;
387
+ comment: z.ZodOptional<z.ZodString>;
388
+ id: z.ZodString;
389
+ label: z.ZodOptional<z.ZodString>;
390
+ next: z.ZodOptional<z.ZodString>;
391
+ timeout: z.ZodOptional<z.ZodNumber>;
392
+ }, z.core.$strip>, z.ZodObject<{
393
+ type: z.ZodLiteral<"setVariable">;
394
+ value: z.ZodDiscriminatedUnion<[z.ZodObject<{
395
+ type: z.ZodLiteral<"static">;
396
+ value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>;
397
+ }, z.core.$strip>, z.ZodObject<{
398
+ name: z.ZodString;
399
+ type: z.ZodLiteral<"variable">;
400
+ }, z.core.$strip>], "type">;
401
+ variable: z.ZodString;
402
+ comment: z.ZodOptional<z.ZodString>;
403
+ id: z.ZodString;
404
+ label: z.ZodOptional<z.ZodString>;
405
+ next: z.ZodOptional<z.ZodString>;
406
+ timeout: z.ZodOptional<z.ZodNumber>;
407
+ }, z.core.$strip>, z.ZodObject<{
408
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
409
+ by: z.ZodLiteral<"testId">;
410
+ value: z.ZodString;
411
+ }, z.core.$strip>, z.ZodObject<{
412
+ by: z.ZodLiteral<"role">;
413
+ name: z.ZodOptional<z.ZodString>;
414
+ role: z.ZodString;
415
+ }, z.core.$strip>], "by">;
416
+ type: z.ZodLiteral<"extractText">;
417
+ variable: z.ZodString;
418
+ comment: z.ZodOptional<z.ZodString>;
419
+ id: z.ZodString;
420
+ label: z.ZodOptional<z.ZodString>;
421
+ next: z.ZodOptional<z.ZodString>;
422
+ timeout: z.ZodOptional<z.ZodNumber>;
423
+ }, z.core.$strip>, z.ZodObject<{
424
+ files: z.ZodArray<z.ZodString>;
425
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
426
+ by: z.ZodLiteral<"testId">;
427
+ value: z.ZodString;
428
+ }, z.core.$strip>, z.ZodObject<{
429
+ by: z.ZodLiteral<"role">;
430
+ name: z.ZodOptional<z.ZodString>;
431
+ role: z.ZodString;
432
+ }, z.core.$strip>], "by">;
433
+ type: z.ZodLiteral<"upload">;
434
+ comment: z.ZodOptional<z.ZodString>;
435
+ id: z.ZodString;
436
+ label: z.ZodOptional<z.ZodString>;
437
+ next: z.ZodOptional<z.ZodString>;
438
+ timeout: z.ZodOptional<z.ZodNumber>;
439
+ }, z.core.$strip>, z.ZodObject<{
440
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
441
+ by: z.ZodLiteral<"testId">;
442
+ value: z.ZodString;
443
+ }, z.core.$strip>, z.ZodObject<{
444
+ by: z.ZodLiteral<"role">;
445
+ name: z.ZodOptional<z.ZodString>;
446
+ role: z.ZodString;
447
+ }, z.core.$strip>], "by">;
448
+ type: z.ZodLiteral<"dblclick">;
449
+ comment: z.ZodOptional<z.ZodString>;
450
+ id: z.ZodString;
451
+ label: z.ZodOptional<z.ZodString>;
452
+ next: z.ZodOptional<z.ZodString>;
453
+ timeout: z.ZodOptional<z.ZodNumber>;
454
+ }, z.core.$strip>, z.ZodObject<{
455
+ source: z.ZodDiscriminatedUnion<[z.ZodObject<{
456
+ by: z.ZodLiteral<"testId">;
457
+ value: z.ZodString;
458
+ }, z.core.$strip>, z.ZodObject<{
459
+ by: z.ZodLiteral<"role">;
460
+ name: z.ZodOptional<z.ZodString>;
461
+ role: z.ZodString;
462
+ }, z.core.$strip>], "by">;
463
+ target: z.ZodDiscriminatedUnion<[z.ZodObject<{
464
+ by: z.ZodLiteral<"testId">;
465
+ value: z.ZodString;
466
+ }, z.core.$strip>, z.ZodObject<{
467
+ by: z.ZodLiteral<"role">;
468
+ name: z.ZodOptional<z.ZodString>;
469
+ role: z.ZodString;
470
+ }, z.core.$strip>], "by">;
471
+ type: z.ZodLiteral<"drag">;
472
+ comment: z.ZodOptional<z.ZodString>;
473
+ id: z.ZodString;
474
+ label: z.ZodOptional<z.ZodString>;
475
+ next: z.ZodOptional<z.ZodString>;
476
+ timeout: z.ZodOptional<z.ZodNumber>;
477
+ }, z.core.$strip>, z.ZodObject<{
478
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
479
+ by: z.ZodLiteral<"testId">;
480
+ value: z.ZodString;
481
+ }, z.core.$strip>, z.ZodObject<{
482
+ by: z.ZodLiteral<"role">;
483
+ name: z.ZodOptional<z.ZodString>;
484
+ role: z.ZodString;
485
+ }, z.core.$strip>], "by">;
486
+ type: z.ZodLiteral<"scrollIntoView">;
487
+ comment: z.ZodOptional<z.ZodString>;
488
+ id: z.ZodString;
489
+ label: z.ZodOptional<z.ZodString>;
490
+ next: z.ZodOptional<z.ZodString>;
491
+ timeout: z.ZodOptional<z.ZodNumber>;
492
+ }, z.core.$strip>, z.ZodObject<{
493
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
494
+ by: z.ZodLiteral<"testId">;
495
+ value: z.ZodString;
496
+ }, z.core.$strip>, z.ZodObject<{
497
+ by: z.ZodLiteral<"role">;
498
+ name: z.ZodOptional<z.ZodString>;
499
+ role: z.ZodString;
500
+ }, z.core.$strip>], "by">;
501
+ type: z.ZodLiteral<"type">;
502
+ value: z.ZodDiscriminatedUnion<[z.ZodObject<{
503
+ type: z.ZodLiteral<"static">;
504
+ value: z.ZodString;
505
+ }, z.core.$strip>, z.ZodObject<{
506
+ name: z.ZodString;
507
+ type: z.ZodLiteral<"variable">;
508
+ }, z.core.$strip>], "type">;
509
+ comment: z.ZodOptional<z.ZodString>;
510
+ id: z.ZodString;
511
+ label: z.ZodOptional<z.ZodString>;
512
+ next: z.ZodOptional<z.ZodString>;
513
+ timeout: z.ZodOptional<z.ZodNumber>;
514
+ }, z.core.$strip>, z.ZodObject<{
515
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
516
+ by: z.ZodLiteral<"testId">;
517
+ value: z.ZodString;
518
+ }, z.core.$strip>, z.ZodObject<{
519
+ by: z.ZodLiteral<"role">;
520
+ name: z.ZodOptional<z.ZodString>;
521
+ role: z.ZodString;
522
+ }, z.core.$strip>], "by">;
523
+ type: z.ZodLiteral<"focus">;
524
+ comment: z.ZodOptional<z.ZodString>;
525
+ id: z.ZodString;
526
+ label: z.ZodOptional<z.ZodString>;
527
+ next: z.ZodOptional<z.ZodString>;
528
+ timeout: z.ZodOptional<z.ZodNumber>;
529
+ }, z.core.$strip>, z.ZodObject<{
530
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
531
+ by: z.ZodLiteral<"testId">;
532
+ value: z.ZodString;
533
+ }, z.core.$strip>, z.ZodObject<{
534
+ by: z.ZodLiteral<"role">;
535
+ name: z.ZodOptional<z.ZodString>;
536
+ role: z.ZodString;
537
+ }, z.core.$strip>], "by">;
538
+ type: z.ZodLiteral<"clear">;
539
+ comment: z.ZodOptional<z.ZodString>;
540
+ id: z.ZodString;
541
+ label: z.ZodOptional<z.ZodString>;
542
+ next: z.ZodOptional<z.ZodString>;
543
+ timeout: z.ZodOptional<z.ZodNumber>;
544
+ }, z.core.$strip>, z.ZodObject<{
545
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
546
+ by: z.ZodLiteral<"testId">;
547
+ value: z.ZodString;
548
+ }, z.core.$strip>, z.ZodObject<{
549
+ by: z.ZodLiteral<"role">;
550
+ name: z.ZodOptional<z.ZodString>;
551
+ role: z.ZodString;
552
+ }, z.core.$strip>], "by">;
553
+ type: z.ZodLiteral<"rightClick">;
554
+ comment: z.ZodOptional<z.ZodString>;
555
+ id: z.ZodString;
556
+ label: z.ZodOptional<z.ZodString>;
557
+ next: z.ZodOptional<z.ZodString>;
558
+ timeout: z.ZodOptional<z.ZodNumber>;
559
+ }, z.core.$strip>, z.ZodObject<{
560
+ action: z.ZodEnum<{
561
+ accept: "accept";
562
+ dismiss: "dismiss";
563
+ }>;
564
+ promptText: z.ZodOptional<z.ZodString>;
565
+ type: z.ZodLiteral<"handleDialog">;
566
+ comment: z.ZodOptional<z.ZodString>;
567
+ id: z.ZodString;
568
+ label: z.ZodOptional<z.ZodString>;
569
+ next: z.ZodOptional<z.ZodString>;
570
+ timeout: z.ZodOptional<z.ZodNumber>;
571
+ }, z.core.$strip>, z.ZodObject<{
572
+ action: z.ZodEnum<{
573
+ read: "read";
574
+ write: "write";
575
+ }>;
576
+ type: z.ZodLiteral<"clipboard">;
577
+ value: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
578
+ type: z.ZodLiteral<"static">;
579
+ value: z.ZodString;
580
+ }, z.core.$strip>, z.ZodObject<{
581
+ name: z.ZodString;
582
+ type: z.ZodLiteral<"variable">;
583
+ }, z.core.$strip>], "type">>;
584
+ variable: z.ZodOptional<z.ZodString>;
585
+ comment: z.ZodOptional<z.ZodString>;
586
+ id: z.ZodString;
587
+ label: z.ZodOptional<z.ZodString>;
588
+ next: z.ZodOptional<z.ZodString>;
589
+ timeout: z.ZodOptional<z.ZodNumber>;
590
+ }, z.core.$strip>, z.ZodObject<{
591
+ permission: z.ZodString;
592
+ state: z.ZodEnum<{
593
+ granted: "granted";
594
+ prompt: "prompt";
595
+ }>;
596
+ type: z.ZodLiteral<"setPermission">;
597
+ comment: z.ZodOptional<z.ZodString>;
598
+ id: z.ZodString;
599
+ label: z.ZodOptional<z.ZodString>;
600
+ next: z.ZodOptional<z.ZodString>;
601
+ timeout: z.ZodOptional<z.ZodNumber>;
602
+ }, z.core.$strip>, z.ZodObject<{
603
+ expected: z.ZodDiscriminatedUnion<[z.ZodObject<{
604
+ type: z.ZodLiteral<"static">;
605
+ value: z.ZodString;
606
+ }, z.core.$strip>, z.ZodObject<{
607
+ name: z.ZodString;
608
+ type: z.ZodLiteral<"variable">;
609
+ }, z.core.$strip>], "type">;
610
+ operator: z.ZodEnum<{
611
+ equals: "equals";
612
+ notEquals: "notEquals";
613
+ contains: "contains";
614
+ startsWith: "startsWith";
615
+ endsWith: "endsWith";
616
+ matches: "matches";
617
+ }>;
618
+ type: z.ZodLiteral<"assertTitle">;
619
+ comment: z.ZodOptional<z.ZodString>;
620
+ id: z.ZodString;
621
+ label: z.ZodOptional<z.ZodString>;
622
+ next: z.ZodOptional<z.ZodString>;
623
+ timeout: z.ZodOptional<z.ZodNumber>;
624
+ }, z.core.$strip>, z.ZodObject<{
625
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
626
+ by: z.ZodLiteral<"testId">;
627
+ value: z.ZodString;
628
+ }, z.core.$strip>, z.ZodObject<{
629
+ by: z.ZodLiteral<"role">;
630
+ name: z.ZodOptional<z.ZodString>;
631
+ role: z.ZodString;
632
+ }, z.core.$strip>], "by">;
633
+ type: z.ZodLiteral<"assertChecked">;
634
+ comment: z.ZodOptional<z.ZodString>;
635
+ id: z.ZodString;
636
+ label: z.ZodOptional<z.ZodString>;
637
+ next: z.ZodOptional<z.ZodString>;
638
+ timeout: z.ZodOptional<z.ZodNumber>;
639
+ }, z.core.$strip>, z.ZodObject<{
640
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
641
+ by: z.ZodLiteral<"testId">;
642
+ value: z.ZodString;
643
+ }, z.core.$strip>, z.ZodObject<{
644
+ by: z.ZodLiteral<"role">;
645
+ name: z.ZodOptional<z.ZodString>;
646
+ role: z.ZodString;
647
+ }, z.core.$strip>], "by">;
648
+ type: z.ZodLiteral<"assertNotChecked">;
649
+ comment: z.ZodOptional<z.ZodString>;
650
+ id: z.ZodString;
651
+ label: z.ZodOptional<z.ZodString>;
652
+ next: z.ZodOptional<z.ZodString>;
653
+ timeout: z.ZodOptional<z.ZodNumber>;
654
+ }, z.core.$strip>, z.ZodObject<{
655
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
656
+ by: z.ZodLiteral<"testId">;
657
+ value: z.ZodString;
658
+ }, z.core.$strip>, z.ZodObject<{
659
+ by: z.ZodLiteral<"role">;
660
+ name: z.ZodOptional<z.ZodString>;
661
+ role: z.ZodString;
662
+ }, z.core.$strip>], "by">;
663
+ type: z.ZodLiteral<"assertFocused">;
664
+ comment: z.ZodOptional<z.ZodString>;
665
+ id: z.ZodString;
666
+ label: z.ZodOptional<z.ZodString>;
667
+ next: z.ZodOptional<z.ZodString>;
668
+ timeout: z.ZodOptional<z.ZodNumber>;
669
+ }, z.core.$strip>, z.ZodObject<{
670
+ locator: z.ZodDiscriminatedUnion<[z.ZodObject<{
671
+ by: z.ZodLiteral<"testId">;
672
+ value: z.ZodString;
673
+ }, z.core.$strip>, z.ZodObject<{
674
+ by: z.ZodLiteral<"role">;
675
+ name: z.ZodOptional<z.ZodString>;
676
+ role: z.ZodString;
677
+ }, z.core.$strip>], "by">;
678
+ type: z.ZodLiteral<"assertNotFocused">;
679
+ comment: z.ZodOptional<z.ZodString>;
680
+ id: z.ZodString;
681
+ label: z.ZodOptional<z.ZodString>;
682
+ next: z.ZodOptional<z.ZodString>;
683
+ timeout: z.ZodOptional<z.ZodNumber>;
684
+ }, z.core.$strip>], "type">>;
685
+ variableNamespaces: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
686
+ variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
687
+ default: z.ZodOptional<z.ZodString>;
688
+ type: z.ZodLiteral<"string">;
689
+ }, z.core.$strip>, z.ZodObject<{
690
+ default: z.ZodOptional<z.ZodNumber>;
691
+ type: z.ZodLiteral<"number">;
692
+ }, z.core.$strip>, z.ZodObject<{
693
+ default: z.ZodOptional<z.ZodBoolean>;
694
+ type: z.ZodLiteral<"boolean">;
695
+ }, z.core.$strip>, z.ZodObject<{
696
+ key: z.ZodString;
697
+ type: z.ZodLiteral<"env">;
698
+ }, z.core.$strip>], "type">>>;
699
+ version: z.ZodLiteral<2>;
700
+ }, z.core.$strip>;
701
+ warnings: z.ZodArray<z.ZodString>;
702
+ }, z.core.$strip>>;
703
+ }, z.core.$strip>;
704
+ type Lockfile = z.infer<typeof lockfileSchema>;
705
+ declare function compileResultToLockfile(result: CompileResult): Lockfile;
706
+ declare function serializeLockfile(lockfile: Lockfile): string;
707
+ interface ReadLockfileParams {
708
+ readonly cwd: string;
709
+ }
710
+ declare function readLockfile({ cwd }: ReadLockfileParams): Promise<Lockfile | null>;
711
+ interface WriteLockfileParams {
712
+ readonly cwd: string;
713
+ readonly result: CompileResult;
714
+ }
715
+ declare function writeLockfile({ cwd, result }: WriteLockfileParams): Promise<void>;
716
+ type LockfileComparison = "match" | "missing" | "stale";
717
+ interface CompareLockfileParams {
718
+ readonly compiled: CompileResult;
719
+ readonly existing: Lockfile | null;
720
+ }
721
+ declare function compareCompileToLockfile({ compiled, existing, }: CompareLockfileParams): LockfileComparison;
722
+
723
+ export { type CompareLockfileParams, LOCKFILE_RELATIVE_PATH, LOCKFILE_VERSION, type Lockfile, type LockfileComparison, type ReadLockfileParams, type WriteLockfileParams, compareCompileToLockfile, compileResultToLockfile, lockfileSchema, readLockfile, serializeLockfile, writeLockfile };
@@ -0,0 +1,470 @@
1
+ // src/lockfile.ts
2
+ import fs from "fs/promises";
3
+ import path from "path";
4
+
5
+ // ../spec/src/edge.ts
6
+ import { z } from "zod";
7
+ var edgeSchema = z.object({
8
+ from: z.string().min(1).describe("Key of the source state in the states record"),
9
+ requiresKeys: z.record(z.string(), z.string()).optional().describe(
10
+ "Maps workflow variable namespace to precondition name. Used by the runtime to namespace batch precondition data into dot-namespaced variables (e.g. { project: 'data:project' } maps projectId \u2192 project.projectId)."
11
+ ),
12
+ to: z.string().min(1).describe("Key of the target state in the states record"),
13
+ workflow: z.string().min(1).describe(
14
+ "Filename (without .json) of the workflow in .ripplo/workflows/ that executes this edge"
15
+ )
16
+ }).describe("A directed edge between two states, executed by a workflow");
17
+
18
+ // ../spec/src/graph.ts
19
+ import { z as z4 } from "zod";
20
+
21
+ // ../spec/src/precondition.ts
22
+ import { z as z2 } from "zod";
23
+ var preconditionSchema = z2.object({
24
+ depends: z2.array(z2.string().min(1)).optional().describe(
25
+ "Names of other preconditions that must be satisfied first. Resolved via topological sort; cycles are rejected at validation time."
26
+ ),
27
+ description: z2.string().min(1).describe("Human-readable description of what this precondition ensures"),
28
+ returns: z2.array(z2.string().min(1)).optional().describe(
29
+ "Keys that the execute response's data field will contain. e.g. ['projectId', 'workflowId']. These are used for route param interpolation ({{projectId}}) and workflow variables. Declared here so generated types are strongly typed per precondition."
30
+ )
31
+ }).describe("A named precondition declared at the graph level. States reference these by name.");
32
+
33
+ // ../spec/src/state.ts
34
+ import { z as z3 } from "zod";
35
+ var stateNodeSchema = z3.object({
36
+ preconditions: z3.array(z3.string().min(1)).describe("Ordered list of precondition names to satisfy before entering this state"),
37
+ route: z3.string().min(1).describe(
38
+ "URL pattern with {{placeholders}} for dynamic segments, e.g. '/projects/{{projectId}}/settings'"
39
+ )
40
+ }).describe(
41
+ "A distinct application state \u2014 a unique combination of location, auth context, and data conditions"
42
+ );
43
+
44
+ // ../spec/src/graph.ts
45
+ var stateGraphSchema = z4.object({
46
+ edges: z4.array(edgeSchema).describe("Directed edges between states, each executed by a workflow"),
47
+ preconditions: z4.record(z4.string(), preconditionSchema).describe(
48
+ "Named preconditions keyed by name (e.g. 'auth:admin', 'data:three-projects'). States reference these by name."
49
+ ),
50
+ states: z4.record(z4.string(), stateNodeSchema).describe("States keyed by stable ID (kebab-case)"),
51
+ version: z4.literal(3).describe("Schema version, always 3")
52
+ }).describe(
53
+ "Ripplo State Graph v3 \u2014 models application states, edges, and executable preconditions"
54
+ );
55
+
56
+ // ../spec/src/schema.ts
57
+ import { z as z9 } from "zod";
58
+
59
+ // ../spec/src/locators.ts
60
+ import { z as z5 } from "zod";
61
+ var testIdLocator = z5.object({
62
+ by: z5.literal("testId"),
63
+ value: z5.string().min(1)
64
+ });
65
+ var roleLocator = z5.object({
66
+ by: z5.literal("role"),
67
+ name: z5.string().optional(),
68
+ role: z5.string().min(1)
69
+ });
70
+ var locatorSchema = z5.discriminatedUnion("by", [testIdLocator, roleLocator]);
71
+
72
+ // ../spec/src/operators.ts
73
+ import { z as z6 } from "zod";
74
+ var comparisonOperator = z6.enum([
75
+ "equals",
76
+ "notEquals",
77
+ "contains",
78
+ "startsWith",
79
+ "endsWith",
80
+ "matches"
81
+ ]);
82
+ var numericOperator = z6.enum([
83
+ "equals",
84
+ "notEquals",
85
+ "greaterThan",
86
+ "greaterThanOrEqual",
87
+ "lessThan",
88
+ "lessThanOrEqual"
89
+ ]);
90
+
91
+ // ../spec/src/value-ref.ts
92
+ import { z as z7 } from "zod";
93
+ var staticValueSchema = z7.object({
94
+ type: z7.literal("static"),
95
+ value: z7.union([z7.string(), z7.number(), z7.boolean()])
96
+ });
97
+ var variableRefSchema = z7.object({
98
+ name: z7.string().min(1),
99
+ type: z7.literal("variable")
100
+ });
101
+ var valueRefSchema = z7.discriminatedUnion("type", [staticValueSchema, variableRefSchema]);
102
+ var stringValueRefSchema = z7.discriminatedUnion("type", [
103
+ z7.object({ type: z7.literal("static"), value: z7.string() }),
104
+ variableRefSchema
105
+ ]);
106
+ var numericValueRefSchema = z7.discriminatedUnion("type", [
107
+ z7.object({ type: z7.literal("static"), value: z7.number().int().nonnegative() }),
108
+ variableRefSchema
109
+ ]);
110
+
111
+ // ../spec/src/variables.ts
112
+ import { z as z8 } from "zod";
113
+ var variableDefSchema = z8.discriminatedUnion("type", [
114
+ z8.object({
115
+ default: z8.string().optional(),
116
+ type: z8.literal("string")
117
+ }),
118
+ z8.object({
119
+ default: z8.number().optional(),
120
+ type: z8.literal("number")
121
+ }),
122
+ z8.object({
123
+ default: z8.boolean().optional(),
124
+ type: z8.literal("boolean")
125
+ }),
126
+ z8.object({
127
+ key: z8.string().min(1),
128
+ type: z8.literal("env")
129
+ })
130
+ ]);
131
+
132
+ // ../spec/src/schema.ts
133
+ var nodeBase = {
134
+ comment: z9.string().optional(),
135
+ id: z9.string().min(1),
136
+ label: z9.string().optional(),
137
+ next: z9.string().optional(),
138
+ timeout: z9.number().int().positive().optional()
139
+ };
140
+ var gotoNode = z9.object({
141
+ ...nodeBase,
142
+ type: z9.literal("goto"),
143
+ url: stringValueRefSchema
144
+ });
145
+ var clickNode = z9.object({ ...nodeBase, locator: locatorSchema, type: z9.literal("click") });
146
+ var fillNode = z9.object({
147
+ ...nodeBase,
148
+ locator: locatorSchema,
149
+ type: z9.literal("fill"),
150
+ value: stringValueRefSchema
151
+ });
152
+ var selectNode = z9.object({
153
+ ...nodeBase,
154
+ locator: locatorSchema,
155
+ type: z9.literal("select"),
156
+ value: stringValueRefSchema
157
+ });
158
+ var hoverNode = z9.object({ ...nodeBase, locator: locatorSchema, type: z9.literal("hover") });
159
+ var pressNode = z9.object({
160
+ ...nodeBase,
161
+ key: z9.string().min(1),
162
+ locator: locatorSchema.optional(),
163
+ type: z9.literal("press")
164
+ });
165
+ var checkNode = z9.object({ ...nodeBase, locator: locatorSchema, type: z9.literal("check") });
166
+ var uncheckNode = z9.object({ ...nodeBase, locator: locatorSchema, type: z9.literal("uncheck") });
167
+ var setViewportNode = z9.object({
168
+ ...nodeBase,
169
+ height: z9.number().int().positive(),
170
+ type: z9.literal("setViewport"),
171
+ width: z9.number().int().positive()
172
+ });
173
+ var failNode = z9.object({ ...nodeBase, message: z9.string().min(1), type: z9.literal("fail") });
174
+ var setVariableNode = z9.object({
175
+ ...nodeBase,
176
+ type: z9.literal("setVariable"),
177
+ value: valueRefSchema,
178
+ variable: z9.string().min(1)
179
+ });
180
+ var extractTextNode = z9.object({
181
+ ...nodeBase,
182
+ locator: locatorSchema,
183
+ type: z9.literal("extractText"),
184
+ variable: z9.string().min(1)
185
+ });
186
+ var uploadNode = z9.object({
187
+ ...nodeBase,
188
+ files: z9.array(z9.string()).min(1),
189
+ locator: locatorSchema,
190
+ type: z9.literal("upload")
191
+ });
192
+ var dblclickNode = z9.object({
193
+ ...nodeBase,
194
+ locator: locatorSchema,
195
+ type: z9.literal("dblclick")
196
+ });
197
+ var dragNode = z9.object({
198
+ ...nodeBase,
199
+ source: locatorSchema,
200
+ target: locatorSchema,
201
+ type: z9.literal("drag")
202
+ });
203
+ var scrollIntoViewNode = z9.object({
204
+ ...nodeBase,
205
+ locator: locatorSchema,
206
+ type: z9.literal("scrollIntoView")
207
+ });
208
+ var typeNode = z9.object({
209
+ ...nodeBase,
210
+ locator: locatorSchema,
211
+ type: z9.literal("type"),
212
+ value: stringValueRefSchema
213
+ });
214
+ var focusNode = z9.object({
215
+ ...nodeBase,
216
+ locator: locatorSchema,
217
+ type: z9.literal("focus")
218
+ });
219
+ var clearNode = z9.object({ ...nodeBase, locator: locatorSchema, type: z9.literal("clear") });
220
+ var rightClickNode = z9.object({
221
+ ...nodeBase,
222
+ locator: locatorSchema,
223
+ type: z9.literal("rightClick")
224
+ });
225
+ var handleDialogNode = z9.object({
226
+ ...nodeBase,
227
+ action: z9.enum(["accept", "dismiss"]),
228
+ promptText: z9.string().optional(),
229
+ type: z9.literal("handleDialog")
230
+ });
231
+ var clipboardNode = z9.object({
232
+ ...nodeBase,
233
+ action: z9.enum(["read", "write"]),
234
+ type: z9.literal("clipboard"),
235
+ value: stringValueRefSchema.optional(),
236
+ variable: z9.string().min(1).optional()
237
+ });
238
+ var setPermissionNode = z9.object({
239
+ ...nodeBase,
240
+ permission: z9.string().min(1),
241
+ state: z9.enum(["granted", "prompt"]),
242
+ type: z9.literal("setPermission")
243
+ });
244
+ var assertVisibleNode = z9.object({
245
+ ...nodeBase,
246
+ locator: locatorSchema,
247
+ type: z9.literal("assertVisible")
248
+ });
249
+ var assertNotVisibleNode = z9.object({
250
+ ...nodeBase,
251
+ locator: locatorSchema,
252
+ type: z9.literal("assertNotVisible")
253
+ });
254
+ var assertTextNode = z9.object({
255
+ ...nodeBase,
256
+ expected: stringValueRefSchema,
257
+ locator: locatorSchema,
258
+ operator: comparisonOperator,
259
+ type: z9.literal("assertText")
260
+ });
261
+ var assertUrlNode = z9.object({
262
+ ...nodeBase,
263
+ expected: stringValueRefSchema,
264
+ operator: comparisonOperator,
265
+ type: z9.literal("assertUrl")
266
+ });
267
+ var assertCountNode = z9.object({
268
+ ...nodeBase,
269
+ expected: numericValueRefSchema,
270
+ locator: locatorSchema,
271
+ operator: numericOperator,
272
+ type: z9.literal("assertCount")
273
+ });
274
+ var assertValueNode = z9.object({
275
+ ...nodeBase,
276
+ expected: stringValueRefSchema,
277
+ locator: locatorSchema,
278
+ operator: comparisonOperator,
279
+ type: z9.literal("assertValue")
280
+ });
281
+ var assertAttributeNode = z9.object({
282
+ ...nodeBase,
283
+ attribute: z9.string().min(1),
284
+ expected: stringValueRefSchema,
285
+ locator: locatorSchema,
286
+ operator: comparisonOperator,
287
+ type: z9.literal("assertAttribute")
288
+ });
289
+ var assertEnabledNode = z9.object({
290
+ ...nodeBase,
291
+ locator: locatorSchema,
292
+ type: z9.literal("assertEnabled")
293
+ });
294
+ var assertDisabledNode = z9.object({
295
+ ...nodeBase,
296
+ locator: locatorSchema,
297
+ type: z9.literal("assertDisabled")
298
+ });
299
+ var assertTitleNode = z9.object({
300
+ ...nodeBase,
301
+ expected: stringValueRefSchema,
302
+ operator: comparisonOperator,
303
+ type: z9.literal("assertTitle")
304
+ });
305
+ var assertCheckedNode = z9.object({
306
+ ...nodeBase,
307
+ locator: locatorSchema,
308
+ type: z9.literal("assertChecked")
309
+ });
310
+ var assertNotCheckedNode = z9.object({
311
+ ...nodeBase,
312
+ locator: locatorSchema,
313
+ type: z9.literal("assertNotChecked")
314
+ });
315
+ var assertFocusedNode = z9.object({
316
+ ...nodeBase,
317
+ locator: locatorSchema,
318
+ type: z9.literal("assertFocused")
319
+ });
320
+ var assertNotFocusedNode = z9.object({
321
+ ...nodeBase,
322
+ locator: locatorSchema,
323
+ type: z9.literal("assertNotFocused")
324
+ });
325
+ var specNodeSchema = z9.discriminatedUnion("type", [
326
+ gotoNode,
327
+ clickNode,
328
+ fillNode,
329
+ selectNode,
330
+ hoverNode,
331
+ pressNode,
332
+ checkNode,
333
+ uncheckNode,
334
+ assertVisibleNode,
335
+ assertNotVisibleNode,
336
+ assertTextNode,
337
+ assertUrlNode,
338
+ assertCountNode,
339
+ assertValueNode,
340
+ assertAttributeNode,
341
+ assertEnabledNode,
342
+ assertDisabledNode,
343
+ setViewportNode,
344
+ failNode,
345
+ setVariableNode,
346
+ extractTextNode,
347
+ uploadNode,
348
+ dblclickNode,
349
+ dragNode,
350
+ scrollIntoViewNode,
351
+ typeNode,
352
+ focusNode,
353
+ clearNode,
354
+ rightClickNode,
355
+ handleDialogNode,
356
+ clipboardNode,
357
+ setPermissionNode,
358
+ assertTitleNode,
359
+ assertCheckedNode,
360
+ assertNotCheckedNode,
361
+ assertFocusedNode,
362
+ assertNotFocusedNode
363
+ ]);
364
+ var workflowSpecSchema = z9.object({
365
+ entryNode: z9.string().min(1),
366
+ nodes: z9.record(z9.string(), specNodeSchema),
367
+ variableNamespaces: z9.record(z9.string(), z9.string()).optional(),
368
+ variables: z9.record(z9.string(), variableDefSchema).optional(),
369
+ version: z9.literal(2)
370
+ });
371
+
372
+ // src/lockfile.ts
373
+ import { z as z10 } from "zod";
374
+ var LOCKFILE_VERSION = 1;
375
+ var LOCKFILE_RELATIVE_PATH = ".ripplo/ripplo.lock";
376
+ var compiledTestSchema = z10.object({
377
+ additionalChecks: z10.array(z10.string()),
378
+ description: z10.string(),
379
+ expectedOutcome: z10.string(),
380
+ implemented: z10.boolean(),
381
+ name: z10.string(),
382
+ slug: z10.string(),
383
+ spec: workflowSpecSchema,
384
+ warnings: z10.array(z10.string())
385
+ });
386
+ var lockfileSchema = z10.object({
387
+ graph: stateGraphSchema,
388
+ lockfileVersion: z10.number().int().positive(),
389
+ tests: z10.array(compiledTestSchema)
390
+ });
391
+ function compileResultToLockfile(result) {
392
+ return {
393
+ graph: result.graph,
394
+ lockfileVersion: LOCKFILE_VERSION,
395
+ tests: result.tests.map((test) => ({
396
+ additionalChecks: [...test.additionalChecks],
397
+ description: test.description,
398
+ expectedOutcome: test.expectedOutcome,
399
+ implemented: test.implemented,
400
+ name: test.name,
401
+ slug: test.slug,
402
+ spec: test.spec,
403
+ warnings: [...test.warnings]
404
+ }))
405
+ };
406
+ }
407
+ function serializeLockfile(lockfile) {
408
+ return `${JSON.stringify(lockfile, sortedReplacer(lockfile), 2)}
409
+ `;
410
+ }
411
+ async function readLockfile({ cwd }) {
412
+ const lockfilePath = path.join(cwd, LOCKFILE_RELATIVE_PATH);
413
+ const raw = await readFileOrNull(lockfilePath);
414
+ if (raw == null) {
415
+ return null;
416
+ }
417
+ const parsed = JSON.parse(raw);
418
+ return lockfileSchema.parse(parsed);
419
+ }
420
+ async function writeLockfile({ cwd, result }) {
421
+ const lockfile = compileResultToLockfile(result);
422
+ const lockfilePath = path.join(cwd, LOCKFILE_RELATIVE_PATH);
423
+ await fs.mkdir(path.dirname(lockfilePath), { recursive: true });
424
+ await fs.writeFile(lockfilePath, serializeLockfile(lockfile), "utf8");
425
+ }
426
+ function compareCompileToLockfile({
427
+ compiled,
428
+ existing
429
+ }) {
430
+ if (existing == null) {
431
+ return "missing";
432
+ }
433
+ const fresh = serializeLockfile(compileResultToLockfile(compiled));
434
+ const current = serializeLockfile(existing);
435
+ return fresh === current ? "match" : "stale";
436
+ }
437
+ async function readFileOrNull(filePath) {
438
+ try {
439
+ return await fs.readFile(filePath, "utf8");
440
+ } catch (error) {
441
+ if (isNodeError(error) && error.code === "ENOENT") {
442
+ return null;
443
+ }
444
+ throw error;
445
+ }
446
+ }
447
+ function isNodeError(value) {
448
+ return value instanceof Error && "code" in value;
449
+ }
450
+ function sortedReplacer(root) {
451
+ return function replacer(_key, value) {
452
+ if (value === root || !isPlainObject(value)) {
453
+ return value;
454
+ }
455
+ return Object.fromEntries(Object.entries(value).toSorted(([a], [b]) => a.localeCompare(b)));
456
+ };
457
+ }
458
+ function isPlainObject(value) {
459
+ return typeof value === "object" && value !== null && !Array.isArray(value);
460
+ }
461
+ export {
462
+ LOCKFILE_RELATIVE_PATH,
463
+ LOCKFILE_VERSION,
464
+ compareCompileToLockfile,
465
+ compileResultToLockfile,
466
+ lockfileSchema,
467
+ readLockfile,
468
+ serializeLockfile,
469
+ writeLockfile
470
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ripplo/testing",
3
3
  "description": "TypeScript DSL for defining and running Ripplo e2e workflow tests",
4
- "version": "0.0.6",
4
+ "version": "0.0.7",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"
@@ -37,6 +37,11 @@
37
37
  "import": "./dist/compiler.js",
38
38
  "default": "./dist/compiler.js"
39
39
  },
40
+ "./lockfile": {
41
+ "types": "./dist/lockfile.d.ts",
42
+ "import": "./dist/lockfile.js",
43
+ "default": "./dist/lockfile.js"
44
+ },
40
45
  "./express": {
41
46
  "types": "./dist/express.d.ts",
42
47
  "import": "./dist/express.js",