@ripplo/testing 0.4.4 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/actions.d.ts CHANGED
@@ -192,9 +192,9 @@ interface HandleDialogOptions {
192
192
  readonly uiOnly?: boolean;
193
193
  }
194
194
  /**
195
- * Respond to a native browser dialog (`alert`, `confirm`, `prompt`). Set
196
- * `uiOnly: true` only when the dialog has no backend side effect — if it
197
- * triggers a mutation, wire an observer and keep `uiOnly` off.
195
+ * Register a one-shot listener for the next native dialog (`alert`, `confirm`,
196
+ * `prompt`). Pure client-side the backend mutation, if any, comes from the
197
+ * triggering action; observer assertions belong on that step, not here.
198
198
  */
199
199
  declare function handleDialog({ action, promptText, uiOnly }: HandleDialogOptions): UnlabeledStep<{
200
200
  action: "accept" | "dismiss";
package/dist/assert.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { O as ObserverHandle, a as ObserverInput, P as Primitive, b as ObserverBudgetTier } from './types-2i1Sm7_J.js';
1
+ import { O as ObserverHandle, a as ObserverInput, P as Primitive, b as ObserverBudgetTier } from './types-16SB7zjP.js';
2
2
  import { Variable, StaticStringRef, VariableRef } from './control.js';
3
3
  import { U as UnlabeledStep } from './step-De52hTLd.js';
4
4
  import { CheckLocator, AnyLocator } from './locators.js';
@@ -1,4 +1,4 @@
1
- import { P as Primitive, O as ObserverHandle, h as Precondition, m as PreconditionData, j as TestDefinition, f as ObserverDefinition, l as PreconditionDefinition, U as UnimplementedItems, e as ObserverContext, g as ObserverOutcome, S as SetupContext, k as TestValue, T as TeardownContext } from './types-2i1Sm7_J.js';
1
+ import { P as Primitive, O as ObserverHandle, h as Precondition, m as PreconditionData, j as TestDefinition, f as ObserverDefinition, l as PreconditionDefinition, U as UnimplementedItems, e as ObserverContext, g as ObserverOutcome, S as SetupContext, k as TestValue, T as TeardownContext } from './types-16SB7zjP.js';
2
2
  import { ObserverBudget } from '@ripplo/spec';
3
3
  import { S as Step } from './step-De52hTLd.js';
4
4
 
@@ -62,6 +62,7 @@ function compileTest(def, preconditionDefs) {
62
62
  preconditions: resolvedPreconditions,
63
63
  requiresKeys: { ...def.requiresKeys },
64
64
  slug,
65
+ sourcePath: def.sourcePath,
65
66
  spec,
66
67
  warnings
67
68
  };
@@ -14,7 +14,7 @@ var batchRequestSchema = z.object({
14
14
  preconditions: z.array(z.string().min(1))
15
15
  });
16
16
  var teardownRequestSchema = z.object({
17
- data: z.record(z.string(), z.record(z.string(), z.string())),
17
+ data: z.record(z.string(), z.record(z.string(), z.union([z.string(), z.number(), z.boolean()]))),
18
18
  preconditions: z.array(z.string().min(1))
19
19
  });
20
20
  var observerRequestSchema = z.object({
@@ -1,6 +1,6 @@
1
1
  import { Observer, Precondition, WorkflowSpec } from '@ripplo/spec';
2
- import { d as RipploBuilder } from './builder-mhjAdyNW.js';
3
- import './types-2i1Sm7_J.js';
2
+ import { d as RipploBuilder } from './builder-BMjy83Iy.js';
3
+ import './types-16SB7zjP.js';
4
4
  import './step-De52hTLd.js';
5
5
 
6
6
  interface CompileResult {
@@ -18,6 +18,7 @@ interface CompiledTest {
18
18
  readonly preconditions: ReadonlyArray<string>;
19
19
  readonly requiresKeys: Record<string, string>;
20
20
  readonly slug: string;
21
+ readonly sourcePath: string | undefined;
21
22
  readonly spec: WorkflowSpec;
22
23
  readonly warnings: ReadonlyArray<string>;
23
24
  }
package/dist/compiler.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  compile
3
- } from "./chunk-GWSEDWEF.js";
3
+ } from "./chunk-DL3HLCD7.js";
4
4
  import "./chunk-MGATMMCZ.js";
5
5
  import "./chunk-4MGIQFAJ.js";
6
6
  export {
package/dist/elysia.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Elysia } from 'elysia';
2
- import { R as RipploEngine } from './engine-B6MM4AEw.js';
3
- import './builder-mhjAdyNW.js';
4
- import './types-2i1Sm7_J.js';
2
+ import { R as RipploEngine } from './engine-DMOkJdjd.js';
3
+ import './builder-BMjy83Iy.js';
4
+ import './types-16SB7zjP.js';
5
5
  import './step-De52hTLd.js';
6
6
  import '@ripplo/spec';
7
7
 
package/dist/elysia.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  serializeCookie,
7
7
  teardownRequestSchema,
8
8
  verifyWebhookSignature
9
- } from "./chunk-EHAZBEHO.js";
9
+ } from "./chunk-V6LMXKGL.js";
10
10
  import "./chunk-4MGIQFAJ.js";
11
11
 
12
12
  // src/adapters/elysia.ts
@@ -1,5 +1,5 @@
1
- import { c as PreconditionRegistry, a as ObserverRegistry, O as ObserverImplFn, P as PreconditionImpl, e as RipploInstance } from './builder-mhjAdyNW.js';
2
- import { P as Primitive, g as ObserverOutcome, C as CookieEntry, f as ObserverDefinition, l as PreconditionDefinition, U as UnimplementedItems, O as ObserverHandle, h as Precondition } from './types-2i1Sm7_J.js';
1
+ import { c as PreconditionRegistry, a as ObserverRegistry, O as ObserverImplFn, P as PreconditionImpl, e as RipploInstance } from './builder-BMjy83Iy.js';
2
+ import { P as Primitive, g as ObserverOutcome, C as CookieEntry, f as ObserverDefinition, l as PreconditionDefinition, U as UnimplementedItems, O as ObserverHandle, h as Precondition } from './types-16SB7zjP.js';
3
3
 
4
4
  interface EngineResult {
5
5
  readonly cookies: ReadonlyArray<CookieEntry>;
package/dist/express.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Router } from 'express';
2
- import { R as RipploEngine } from './engine-B6MM4AEw.js';
3
- import './builder-mhjAdyNW.js';
4
- import './types-2i1Sm7_J.js';
2
+ import { R as RipploEngine } from './engine-DMOkJdjd.js';
3
+ import './builder-BMjy83Iy.js';
4
+ import './types-16SB7zjP.js';
5
5
  import './step-De52hTLd.js';
6
6
  import '@ripplo/spec';
7
7
 
package/dist/express.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  serializeCookie,
6
6
  teardownRequestSchema,
7
7
  verifyWebhookSignature
8
- } from "./chunk-EHAZBEHO.js";
8
+ } from "./chunk-V6LMXKGL.js";
9
9
  import "./chunk-4MGIQFAJ.js";
10
10
 
11
11
  // src/adapters/express.ts
package/dist/fastify.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { FastifyInstance } from 'fastify';
2
- import { R as RipploEngine } from './engine-B6MM4AEw.js';
3
- import './builder-mhjAdyNW.js';
4
- import './types-2i1Sm7_J.js';
2
+ import { R as RipploEngine } from './engine-DMOkJdjd.js';
3
+ import './builder-BMjy83Iy.js';
4
+ import './types-16SB7zjP.js';
5
5
  import './step-De52hTLd.js';
6
6
  import '@ripplo/spec';
7
7
 
package/dist/fastify.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  serializeCookie,
7
7
  teardownRequestSchema,
8
8
  verifyWebhookSignature
9
- } from "./chunk-EHAZBEHO.js";
9
+ } from "./chunk-V6LMXKGL.js";
10
10
  import "./chunk-4MGIQFAJ.js";
11
11
 
12
12
  // src/adapters/fastify.ts
package/dist/hono.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Hono } from 'hono';
2
- import { R as RipploEngine } from './engine-B6MM4AEw.js';
3
- import './builder-mhjAdyNW.js';
4
- import './types-2i1Sm7_J.js';
2
+ import { R as RipploEngine } from './engine-DMOkJdjd.js';
3
+ import './builder-BMjy83Iy.js';
4
+ import './types-16SB7zjP.js';
5
5
  import './step-De52hTLd.js';
6
6
  import '@ripplo/spec';
7
7
 
package/dist/hono.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  serializeCookie,
7
7
  teardownRequestSchema,
8
8
  verifyWebhookSignature
9
- } from "./chunk-EHAZBEHO.js";
9
+ } from "./chunk-V6LMXKGL.js";
10
10
  import "./chunk-4MGIQFAJ.js";
11
11
 
12
12
  // src/adapters/hono.ts
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- export { C as CoverageRegistry, O as ObserverImplFn, a as ObserverRegistry, P as PreconditionImpl, b as PreconditionRecord, c as PreconditionRegistry, R as ResolveDeps, d as RipploBuilder, e as RipploInstance, f as RipploRegistries, g as createRipplo, o as observer, p as precondition, t as test } from './builder-mhjAdyNW.js';
1
+ export { C as CoverageRegistry, O as ObserverImplFn, a as ObserverRegistry, P as PreconditionImpl, b as PreconditionRecord, c as PreconditionRegistry, R as ResolveDeps, d as RipploBuilder, e as RipploInstance, f as RipploRegistries, g as createRipplo, o as observer, p as precondition, t as test } from './builder-BMjy83Iy.js';
2
2
  import { CompileResult } from './compiler.js';
3
3
  export { CompiledTest, compile } from './compiler.js';
4
- export { E as EngineImpls, a as EngineResult, b as ExecuteBatchOptions, N as NotImplemented, O as ObserverImplFnFor, P as PreconditionImplFor, R as RipploEngine, c as createEngine, n as notImplemented } from './engine-B6MM4AEw.js';
5
- import { C as CookieEntry } from './types-2i1Sm7_J.js';
6
- export { c as CookieOptions, D as DEFAULT_IGNORE_PATHS, d as DEFAULT_WATCH_PATHS, e as ObserverContext, f as ObserverDefinition, O as ObserverHandle, a as ObserverInput, g as ObserverOutcome, h as Precondition, i as PreconditionDeps, P as Primitive, S as SetupContext, T as TeardownContext, j as TestDefinition, k as TestValue } from './types-2i1Sm7_J.js';
4
+ export { E as EngineImpls, a as EngineResult, b as ExecuteBatchOptions, N as NotImplemented, O as ObserverImplFnFor, P as PreconditionImplFor, R as RipploEngine, c as createEngine, n as notImplemented } from './engine-DMOkJdjd.js';
5
+ import { C as CookieEntry } from './types-16SB7zjP.js';
6
+ export { c as CookieOptions, D as DEFAULT_IGNORE_PATHS, d as DEFAULT_WATCH_PATHS, e as ObserverContext, f as ObserverDefinition, O as ObserverHandle, a as ObserverInput, g as ObserverOutcome, h as Precondition, i as PreconditionDeps, P as Primitive, S as SetupContext, T as TeardownContext, j as TestDefinition, k as TestValue } from './types-16SB7zjP.js';
7
7
  export { D as DslNodeInput } from './step-De52hTLd.js';
8
8
  import '@ripplo/spec';
9
9
 
package/dist/index.js CHANGED
@@ -14,13 +14,13 @@ import {
14
14
  } from "./chunk-YQAEOH5W.js";
15
15
  import {
16
16
  compile
17
- } from "./chunk-GWSEDWEF.js";
17
+ } from "./chunk-DL3HLCD7.js";
18
18
  import "./chunk-MGATMMCZ.js";
19
19
  import {
20
20
  buildSetCookieHeader,
21
21
  serializeCookie,
22
22
  verifyWebhookSignature
23
- } from "./chunk-EHAZBEHO.js";
23
+ } from "./chunk-V6LMXKGL.js";
24
24
  import "./chunk-4MGIQFAJ.js";
25
25
 
26
26
  // src/chainable.ts
@@ -103,7 +103,21 @@ function observer(name) {
103
103
  }
104
104
  function test(id, options) {
105
105
  validateTestId(id);
106
- return buildTestName(id, options?.uiOnly);
106
+ const sourcePath = captureTestSourcePath();
107
+ return buildTestName({ id, sourcePath, uiOnly: options?.uiOnly });
108
+ }
109
+ var TESTS_ANCHOR_PATTERN = /[/\\]\.ripplo[/\\]tests[/\\]([^):]+?)(?::\d+:\d+\)?)?$/;
110
+ function captureTestSourcePath() {
111
+ const stack = new Error("capture").stack;
112
+ if (stack == null) {
113
+ return void 0;
114
+ }
115
+ const match = stack.split("\n").map((line) => TESTS_ANCHOR_PATTERN.exec(line)).find((m) => m != null);
116
+ const captured = match?.[1];
117
+ if (captured == null) {
118
+ return void 0;
119
+ }
120
+ return captured.replaceAll("\\", "/");
107
121
  }
108
122
  function createRipplo(registries) {
109
123
  const { observers, preconditions, tests } = registries;
@@ -223,15 +237,20 @@ function buildPreconditionWithDeps({
223
237
  })
224
238
  });
225
239
  }
226
- function buildTestName(id, uiOnly) {
240
+ function buildTestName({ id, sourcePath, uiOnly }) {
227
241
  return chainable({
228
- name: (displayName) => buildTestRequires({ id, name: displayName, uiOnly })
242
+ name: (displayName) => buildTestRequires({ id, name: displayName, sourcePath, uiOnly })
229
243
  });
230
244
  }
231
245
  function castOutcome(value) {
232
246
  return value;
233
247
  }
234
- function buildTestRequires({ id, name, uiOnly }) {
248
+ function buildTestRequires({
249
+ id,
250
+ name,
251
+ sourcePath,
252
+ uiOnly
253
+ }) {
235
254
  let description = "";
236
255
  const self = chainable({
237
256
  description(text) {
@@ -250,6 +269,7 @@ function buildTestRequires({ id, name, uiOnly }) {
250
269
  name,
251
270
  reqNames,
252
271
  requiresKeys,
272
+ sourcePath,
253
273
  uiOnly,
254
274
  getDescription: () => description
255
275
  })
@@ -264,6 +284,7 @@ function buildTestOutcome({
264
284
  name,
265
285
  reqNames,
266
286
  requiresKeys,
287
+ sourcePath,
267
288
  uiOnly
268
289
  }) {
269
290
  const description = getDescription();
@@ -276,6 +297,7 @@ function buildTestOutcome({
276
297
  name,
277
298
  reqNames,
278
299
  requiresKeys,
300
+ sourcePath,
279
301
  uiOnly
280
302
  });
281
303
  }
@@ -288,6 +310,7 @@ function buildTestStartsAt({
288
310
  name,
289
311
  reqNames,
290
312
  requiresKeys,
313
+ sourcePath,
291
314
  uiOnly
292
315
  }) {
293
316
  return chainable({
@@ -300,6 +323,7 @@ function buildTestStartsAt({
300
323
  name,
301
324
  requires: [...reqNames],
302
325
  requiresKeys,
326
+ sourcePath,
303
327
  startsAtFn: void 0,
304
328
  stepsFn: void 0,
305
329
  uiOnly
@@ -312,6 +336,7 @@ function buildTestStartsAt({
312
336
  name,
313
337
  reqNames,
314
338
  requiresKeys,
339
+ sourcePath,
315
340
  startsAtFn: fn,
316
341
  uiOnly
317
342
  });
@@ -325,6 +350,7 @@ function buildTestSteps({
325
350
  name,
326
351
  reqNames,
327
352
  requiresKeys,
353
+ sourcePath,
328
354
  startsAtFn,
329
355
  uiOnly
330
356
  }) {
@@ -339,6 +365,7 @@ function buildTestSteps({
339
365
  name,
340
366
  requires: [...reqNames],
341
367
  requiresKeys,
368
+ sourcePath,
342
369
  startsAtFn,
343
370
  stepsFn,
344
371
  uiOnly
@@ -450,18 +477,21 @@ function noDuplicateLabels(nodes, _test, report) {
450
477
  }
451
478
  function assertAfterAction(nodes, _test, report) {
452
479
  let consecutiveActions = 0;
453
- nodes.forEach((node) => {
480
+ nodes.forEach((node, index) => {
481
+ if (index === 0 && node.type === "goto") {
482
+ return;
483
+ }
454
484
  if (isAssertionNode(node)) {
455
485
  consecutiveActions = 0;
456
- } else {
457
- consecutiveActions++;
458
- if (consecutiveActions === 3) {
459
- report({
460
- message: "3+ consecutive actions without an assertion \u2014 add verification between actions",
461
- rule: "assert-after-action",
462
- step: node.label ?? node.id
463
- });
464
- }
486
+ return;
487
+ }
488
+ consecutiveActions++;
489
+ if (consecutiveActions === 3) {
490
+ report({
491
+ message: "3+ consecutive actions without an assertion \u2014 add verification between actions",
492
+ rule: "assert-after-action",
493
+ step: node.label ?? node.id
494
+ });
465
495
  }
466
496
  });
467
497
  }
@@ -691,9 +721,6 @@ function isLikelyBackendMutation(node) {
691
721
  if (node.type === "upload") {
692
722
  return true;
693
723
  }
694
- if (node.type === "handleDialog" && node.action === "accept") {
695
- return true;
696
- }
697
724
  if (node.type !== "click") {
698
725
  return false;
699
726
  }
package/dist/koa.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Middleware } from 'koa';
2
- import { R as RipploEngine } from './engine-B6MM4AEw.js';
3
- import './builder-mhjAdyNW.js';
4
- import './types-2i1Sm7_J.js';
2
+ import { R as RipploEngine } from './engine-DMOkJdjd.js';
3
+ import './builder-BMjy83Iy.js';
4
+ import './types-16SB7zjP.js';
5
5
  import './step-De52hTLd.js';
6
6
  import '@ripplo/spec';
7
7
 
package/dist/koa.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  serializeCookie,
7
7
  teardownRequestSchema,
8
8
  verifyWebhookSignature
9
- } from "./chunk-EHAZBEHO.js";
9
+ } from "./chunk-V6LMXKGL.js";
10
10
  import "./chunk-4MGIQFAJ.js";
11
11
 
12
12
  // src/adapters/koa.ts
@@ -1,8 +1,8 @@
1
1
  import { Codec } from '@ripplo/spec';
2
2
  import { z } from 'zod';
3
3
  import { CompileResult } from './compiler.js';
4
- import './builder-mhjAdyNW.js';
5
- import './types-2i1Sm7_J.js';
4
+ import './builder-BMjy83Iy.js';
5
+ import './types-16SB7zjP.js';
6
6
  import './step-De52hTLd.js';
7
7
 
8
8
  declare const LOCKFILE_RELATIVE_PATH = ".ripplo/ripplo.lock";
@@ -27,6 +27,7 @@ declare const lockfileBodySchema: z.ZodObject<{
27
27
  preconditions: z.ZodArray<z.ZodString>;
28
28
  requiresKeys: z.ZodRecord<z.ZodString, z.ZodString>;
29
29
  slug: z.ZodString;
30
+ sourcePath: z.ZodOptional<z.ZodString>;
30
31
  spec: z.ZodObject<{
31
32
  entryNode: z.ZodString;
32
33
  nodes: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
package/dist/lockfile.js CHANGED
@@ -509,6 +509,7 @@ var compiledTestSchema = z10.object({
509
509
  preconditions: z10.array(z10.string().max(200)).max(1e3),
510
510
  requiresKeys: requiresKeysSchema,
511
511
  slug: z10.string().max(200),
512
+ sourcePath: z10.string().max(500).optional(),
512
513
  spec: workflowSpecSchema
513
514
  });
514
515
  var lockfileBodySchema = z10.object({
@@ -528,6 +529,7 @@ function compileResultToLockfile(result) {
528
529
  preconditions: [...test.preconditions],
529
530
  requiresKeys: { ...test.requiresKeys },
530
531
  slug: test.slug,
532
+ sourcePath: test.sourcePath,
531
533
  spec: test.spec
532
534
  }))
533
535
  };
package/dist/nestjs.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { DynamicModule } from '@nestjs/common';
2
- import { R as RipploEngine } from './engine-B6MM4AEw.js';
3
- import './builder-mhjAdyNW.js';
4
- import './types-2i1Sm7_J.js';
2
+ import { R as RipploEngine } from './engine-DMOkJdjd.js';
3
+ import './builder-BMjy83Iy.js';
4
+ import './types-16SB7zjP.js';
5
5
  import './step-De52hTLd.js';
6
6
  import '@ripplo/spec';
7
7
 
package/dist/nestjs.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  serializeCookie,
7
7
  teardownRequestSchema,
8
8
  verifyWebhookSignature
9
- } from "./chunk-EHAZBEHO.js";
9
+ } from "./chunk-V6LMXKGL.js";
10
10
  import {
11
11
  __decorateClass,
12
12
  __decorateParam
package/dist/nextjs.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { R as RipploEngine } from './engine-B6MM4AEw.js';
2
- import './builder-mhjAdyNW.js';
3
- import './types-2i1Sm7_J.js';
1
+ import { R as RipploEngine } from './engine-DMOkJdjd.js';
2
+ import './builder-BMjy83Iy.js';
3
+ import './types-16SB7zjP.js';
4
4
  import './step-De52hTLd.js';
5
5
  import '@ripplo/spec';
6
6
 
package/dist/nextjs.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  serializeCookie,
7
7
  teardownRequestSchema,
8
8
  verifyWebhookSignature
9
- } from "./chunk-EHAZBEHO.js";
9
+ } from "./chunk-V6LMXKGL.js";
10
10
  import "./chunk-4MGIQFAJ.js";
11
11
 
12
12
  // src/adapters/nextjs.ts
@@ -60,6 +60,7 @@ interface TestDefinition {
60
60
  readonly name: string;
61
61
  readonly requires: ReadonlyArray<string>;
62
62
  readonly requiresKeys: Record<string, string>;
63
+ readonly sourcePath: string | undefined;
63
64
  readonly startsAtFn: VarsFn<string> | undefined;
64
65
  readonly stepsFn: VarsFn<ReadonlyArray<Step>> | undefined;
65
66
  readonly uiOnly: boolean | undefined;
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.4.4",
4
+ "version": "0.4.6",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"