@ripplo/testing 0.4.1 → 0.4.3
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 +24 -3
- package/dist/assert.d.ts +3 -3
- package/dist/assert.js +3 -3
- package/dist/{builder-0oT23S0W.d.ts → builder-mhjAdyNW.d.ts} +13 -13
- package/dist/{chunk-UFHSNW4E.js → chunk-EHAZBEHO.js} +1 -1
- package/dist/{chunk-SBZJDJP4.js → chunk-YQAEOH5W.js} +7 -6
- package/dist/compiler.d.ts +2 -2
- package/dist/elysia.d.ts +3 -3
- package/dist/elysia.js +1 -1
- package/dist/{engine-BdKDGBYw.d.ts → engine-B6MM4AEw.d.ts} +6 -6
- package/dist/express.d.ts +3 -3
- package/dist/express.js +1 -1
- package/dist/fastify.d.ts +3 -3
- package/dist/fastify.js +1 -1
- package/dist/hono.d.ts +3 -3
- package/dist/hono.js +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +79 -31
- package/dist/koa.d.ts +3 -3
- package/dist/koa.js +1 -1
- package/dist/lockfile.d.ts +3 -3
- package/dist/lockfile.js +8 -1
- package/dist/nestjs.d.ts +3 -3
- package/dist/nestjs.js +1 -1
- package/dist/nextjs.d.ts +3 -3
- package/dist/nextjs.js +1 -1
- package/dist/{types-B7YljrTz.d.ts → types-2i1Sm7_J.d.ts} +13 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ export const dataProject = precondition("data:project")
|
|
|
75
75
|
export const preconditions = { authLoggedIn, dataProject };
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
`precondition(name)` → `.description()` → `.requires()` (optional) → `.contract<T>()`. Each field in `T` must be a `string` (run-scoped value).
|
|
78
|
+
`precondition(name)` → `.description()` → `.requires()` (optional) → `.contract<T>()`. Each field in `T` must be a primitive — `string`, `number`, or `boolean` (run-scoped value).
|
|
79
79
|
|
|
80
80
|
### Observers
|
|
81
81
|
|
|
@@ -91,6 +91,25 @@ export const orgNameIs = observer("org:name-is")
|
|
|
91
91
|
export const observers = { orgNameIs };
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
Observer `.input<T>()` and precondition `.contract<T>()` fields can be any primitive — `string`, `number`, or `boolean`. Model each field as the type it actually is; no stringification at the boundary.
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
export const orgOverageCapIs = observer("org:overage-cap-is")
|
|
98
|
+
.description("Org has the given overageCapCents")
|
|
99
|
+
.budget("fast")
|
|
100
|
+
.input<{ orgId: string; expectedCapCents: number }>()
|
|
101
|
+
.contract();
|
|
102
|
+
|
|
103
|
+
export const orgHasLogo = observer("org:has-logo")
|
|
104
|
+
.description("Organization logo is set / unset")
|
|
105
|
+
.budget("fast")
|
|
106
|
+
.input<{ orgId: string; expectLogo: boolean }>()
|
|
107
|
+
.contract();
|
|
108
|
+
|
|
109
|
+
assert.backend(orgOverageCapIs, { orgId: project.orgId, expectedCapCents: 2500 });
|
|
110
|
+
assert.backend(orgHasLogo, { orgId: project.orgId, expectLogo: true });
|
|
111
|
+
```
|
|
112
|
+
|
|
94
113
|
**Budget tiers** (poll behavior, not numeric timeouts):
|
|
95
114
|
|
|
96
115
|
| Tier | Window | Backoff | Use for |
|
|
@@ -275,11 +294,13 @@ export const engine = createEngine(ripplo, {
|
|
|
275
294
|
`ctx` passed to each precondition `setup`:
|
|
276
295
|
|
|
277
296
|
- `ctx.runId` — unique 12-char id for this run
|
|
278
|
-
- `ctx.fixed(value)` — static test value
|
|
297
|
+
- `ctx.fixed<T extends string | number | boolean>(value: T)` — static test value (any primitive)
|
|
279
298
|
- `ctx.uniqueId(prefix)` — `ripplo-test-<prefix>-<runId>`
|
|
280
299
|
- `ctx.uniqueEmail()` — `ripplo-test-<runId>@test.ripplo.ai`
|
|
281
300
|
- `ctx.setCookie(name, value, options?)` — forwarded to the test browser as `Set-Cookie`
|
|
282
301
|
|
|
302
|
+
Helpers return plain primitives — interpolate, JSON.stringify, or pass through observer params directly. The return type is type-branded, so a hardcoded literal in a `setup` return fails at compile time.
|
|
303
|
+
|
|
283
304
|
### Observer context
|
|
284
305
|
|
|
285
306
|
- `ctx.pass()` — assertion satisfied; stop polling.
|
|
@@ -470,7 +491,7 @@ The CLI lives in [`ripplo`](https://www.npmjs.com/package/ripplo). Most-used com
|
|
|
470
491
|
```bash
|
|
471
492
|
ripplo auth login # authenticate
|
|
472
493
|
ripplo init # scaffold .ripplo/ + write env vars
|
|
473
|
-
ripplo watch # local executor —
|
|
494
|
+
ripplo watch # local executor — run as a standalone background process
|
|
474
495
|
ripplo lint [ids..] # compile + lint
|
|
475
496
|
ripplo run [ids..] # run tests in parallel
|
|
476
497
|
```
|
package/dist/assert.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { O as ObserverHandle, a as ObserverInput, b as ObserverBudgetTier } from './types-
|
|
1
|
+
import { O as ObserverHandle, a as ObserverInput, P as Primitive, b as ObserverBudgetTier } from './types-2i1Sm7_J.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';
|
|
@@ -72,12 +72,12 @@ declare const assert: {
|
|
|
72
72
|
* polling) and `ctx.fail(reason)` only for invariant violations (stop
|
|
73
73
|
* early). The observer's `.budget()` governs poll interval and timeout.
|
|
74
74
|
*/
|
|
75
|
-
backend<THandle extends ObserverHandle>(observer: THandle, params: ObserverInput<THandle> & Record<string,
|
|
75
|
+
backend<THandle extends ObserverHandle>(observer: THandle, params: ObserverInput<THandle> & Record<string, Primitive>): UnlabeledStep<{
|
|
76
76
|
budget: ObserverBudgetTier;
|
|
77
77
|
observer: string;
|
|
78
78
|
params: Record<string, {
|
|
79
79
|
readonly type: "static";
|
|
80
|
-
readonly value:
|
|
80
|
+
readonly value: Primitive;
|
|
81
81
|
}>;
|
|
82
82
|
type: "assertObserver";
|
|
83
83
|
}>;
|
package/dist/assert.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
readObserverBudget,
|
|
3
3
|
readObserverName
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-YQAEOH5W.js";
|
|
5
5
|
import {
|
|
6
6
|
toSpecLocator,
|
|
7
7
|
toStringValueRef
|
|
@@ -48,7 +48,7 @@ var assert = {
|
|
|
48
48
|
return createStep({
|
|
49
49
|
budget: readObserverBudget(observer),
|
|
50
50
|
observer: readObserverName(observer),
|
|
51
|
-
params:
|
|
51
|
+
params: paramsToValueRefs(params),
|
|
52
52
|
type: "assertObserver"
|
|
53
53
|
});
|
|
54
54
|
},
|
|
@@ -99,7 +99,7 @@ var assert = {
|
|
|
99
99
|
return createStep({ locator: toSpecLocator(locator), type: "assertVisible" });
|
|
100
100
|
}
|
|
101
101
|
};
|
|
102
|
-
function
|
|
102
|
+
function paramsToValueRefs(params) {
|
|
103
103
|
const out = {};
|
|
104
104
|
Object.entries(params).forEach(([key, value]) => {
|
|
105
105
|
out[key] = { type: "static", value };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { O as ObserverHandle,
|
|
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';
|
|
2
2
|
import { ObserverBudget } from '@ripplo/spec';
|
|
3
3
|
import { S as Step } from './step-De52hTLd.js';
|
|
4
4
|
|
|
@@ -15,9 +15,9 @@ interface ObserverNeedsBudget {
|
|
|
15
15
|
readonly budget: (tier: ObserverBudget) => ObserverNeedsInput;
|
|
16
16
|
}
|
|
17
17
|
interface ObserverNeedsInput {
|
|
18
|
-
readonly input: <TInput extends Record<string,
|
|
18
|
+
readonly input: <TInput extends Record<string, Primitive>>() => ObserverReady<TInput>;
|
|
19
19
|
}
|
|
20
|
-
interface ObserverReady<TInput extends Record<string,
|
|
20
|
+
interface ObserverReady<TInput extends Record<string, Primitive>> {
|
|
21
21
|
readonly contract: () => ObserverHandle<TInput>;
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -31,12 +31,12 @@ type ResolveDeps<TDeps extends PreconditionRecord> = {
|
|
|
31
31
|
readonly [K in keyof TDeps]: PreconditionData<TDeps[K]>;
|
|
32
32
|
};
|
|
33
33
|
interface PreconditionNeedsSetup {
|
|
34
|
-
readonly contract: <TData extends Record<string,
|
|
34
|
+
readonly contract: <TData extends Record<string, Primitive>>() => Precondition<TData>;
|
|
35
35
|
readonly description: (text: string) => PreconditionNeedsSetup;
|
|
36
36
|
readonly requires: <TDeps extends PreconditionRecord>(deps: TDeps) => PreconditionNeedsSetupWithDeps<TDeps>;
|
|
37
37
|
}
|
|
38
38
|
interface PreconditionNeedsSetupWithDeps<TDeps extends PreconditionRecord> {
|
|
39
|
-
readonly contract: <TData extends Record<string,
|
|
39
|
+
readonly contract: <TData extends Record<string, Primitive>>() => Precondition<TData, ResolveDeps<TDeps>>;
|
|
40
40
|
}
|
|
41
41
|
interface TestNeedsName {
|
|
42
42
|
readonly name: (displayName: string) => TestNeedsRequires;
|
|
@@ -52,11 +52,11 @@ interface TestNeedsRequires {
|
|
|
52
52
|
*/
|
|
53
53
|
readonly requires: <TReqs extends PreconditionRecord>(reqs: TReqs) => TestNeedsOutcome<ResolveDeps<TReqs>>;
|
|
54
54
|
}
|
|
55
|
-
interface TestNeedsOutcome<TVars extends Record<string, Record<string,
|
|
55
|
+
interface TestNeedsOutcome<TVars extends Record<string, Record<string, Primitive>>> {
|
|
56
56
|
readonly expectedOutcome: (text: string) => TestNeedsStartsAt<TVars>;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
interface TestNeedsStartsAt<TVars extends Record<string, Record<string,
|
|
59
|
+
interface TestNeedsStartsAt<TVars extends Record<string, Record<string, Primitive>>> {
|
|
60
60
|
/**
|
|
61
61
|
* Skip implementation — compiles as a planning stub and is reported in
|
|
62
62
|
* `getUnimplemented()`. The test appears in the lockfile but is not run.
|
|
@@ -69,7 +69,7 @@ interface TestNeedsStartsAt<TVars extends Record<string, Record<string, string>>
|
|
|
69
69
|
*/
|
|
70
70
|
readonly startsAt: (fn: (vars: TVars) => string) => TestNeedsSteps<TVars>;
|
|
71
71
|
}
|
|
72
|
-
interface TestNeedsSteps<TVars extends Record<string, Record<string,
|
|
72
|
+
interface TestNeedsSteps<TVars extends Record<string, Record<string, Primitive>>> {
|
|
73
73
|
/**
|
|
74
74
|
* Declare the ordered step list. Receives destructured precondition data as
|
|
75
75
|
* typed proxies (same as `.startsAt`). Every step must be labeled with
|
|
@@ -87,19 +87,19 @@ interface TestNeedsCoverage {
|
|
|
87
87
|
readonly coverage: (...ids: ReadonlyArray<CoverageStatementId>) => TestDefinition;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
type PreconditionSetupResult<TData extends Record<string,
|
|
91
|
-
readonly [K in keyof TData]: TestValue
|
|
90
|
+
type PreconditionSetupResult<TData extends Record<string, Primitive>> = {
|
|
91
|
+
readonly [K in keyof TData]: TestValue<TData[K]>;
|
|
92
92
|
};
|
|
93
|
-
interface PreconditionImpl<TData extends Record<string,
|
|
93
|
+
interface PreconditionImpl<TData extends Record<string, Primitive>, TDeps extends Record<string, Record<string, Primitive>>> {
|
|
94
94
|
readonly setup: (ctx: SetupContext, deps: TDeps) => Promise<PreconditionSetupResult<TData>>;
|
|
95
95
|
readonly teardown: (ctx: TeardownContext<TData>) => Promise<void>;
|
|
96
96
|
}
|
|
97
|
-
type ObserverImplFn<TInput extends Record<string,
|
|
97
|
+
type ObserverImplFn<TInput extends Record<string, Primitive>> = (ctx: ObserverContext, params: TInput) => Promise<ObserverOutcome>;
|
|
98
98
|
interface TestOptions {
|
|
99
99
|
readonly uiOnly?: boolean;
|
|
100
100
|
}
|
|
101
101
|
type PreconditionRegistry = Record<string, Precondition>;
|
|
102
|
-
type ObserverRegistry = Record<string, ObserverHandle<Record<string,
|
|
102
|
+
type ObserverRegistry = Record<string, ObserverHandle<Record<string, Primitive>>>;
|
|
103
103
|
interface RipploRegistries<P extends PreconditionRegistry, O extends ObserverRegistry> {
|
|
104
104
|
readonly observers: O;
|
|
105
105
|
readonly preconditions: P;
|
|
@@ -19,7 +19,7 @@ var teardownRequestSchema = z.object({
|
|
|
19
19
|
});
|
|
20
20
|
var observerRequestSchema = z.object({
|
|
21
21
|
observer: z.string().min(1).max(200),
|
|
22
|
-
params: z.record(z.string().max(200), z.string())
|
|
22
|
+
params: z.record(z.string().max(200), z.union([z.string(), z.number(), z.boolean()]))
|
|
23
23
|
});
|
|
24
24
|
var observerOutcomeSchema = z.discriminatedUnion("kind", [
|
|
25
25
|
z.object({ kind: z.literal("pass") }),
|
|
@@ -59,11 +59,12 @@ var DEFAULT_IGNORE_PATHS = [
|
|
|
59
59
|
"**/prisma/migrations/**",
|
|
60
60
|
"**/scripts/**"
|
|
61
61
|
];
|
|
62
|
-
function
|
|
63
|
-
return value
|
|
62
|
+
function brandTestValue(value) {
|
|
63
|
+
return value;
|
|
64
64
|
}
|
|
65
|
-
function
|
|
66
|
-
|
|
65
|
+
function isPrimitive(value) {
|
|
66
|
+
const t = typeof value;
|
|
67
|
+
return t === "string" || t === "number" || t === "boolean";
|
|
67
68
|
}
|
|
68
69
|
function readPreconditionName(p) {
|
|
69
70
|
return p.name;
|
|
@@ -97,8 +98,8 @@ function makeObserverHandle({
|
|
|
97
98
|
export {
|
|
98
99
|
DEFAULT_WATCH_PATHS,
|
|
99
100
|
DEFAULT_IGNORE_PATHS,
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
brandTestValue,
|
|
102
|
+
isPrimitive,
|
|
102
103
|
readPreconditionName,
|
|
103
104
|
readPreconditionDescription,
|
|
104
105
|
readPreconditionDependsOn,
|
package/dist/compiler.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Observer, Precondition, WorkflowSpec } from '@ripplo/spec';
|
|
2
|
-
import { d as RipploBuilder } from './builder-
|
|
3
|
-
import './types-
|
|
2
|
+
import { d as RipploBuilder } from './builder-mhjAdyNW.js';
|
|
3
|
+
import './types-2i1Sm7_J.js';
|
|
4
4
|
import './step-De52hTLd.js';
|
|
5
5
|
|
|
6
6
|
interface CompileResult {
|
package/dist/elysia.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Elysia } from 'elysia';
|
|
2
|
-
import { R as RipploEngine } from './engine-
|
|
3
|
-
import './builder-
|
|
4
|
-
import './types-
|
|
2
|
+
import { R as RipploEngine } from './engine-B6MM4AEw.js';
|
|
3
|
+
import './builder-mhjAdyNW.js';
|
|
4
|
+
import './types-2i1Sm7_J.js';
|
|
5
5
|
import './step-De52hTLd.js';
|
|
6
6
|
import '@ripplo/spec';
|
|
7
7
|
|
package/dist/elysia.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { c as PreconditionRegistry, a as ObserverRegistry, O as ObserverImplFn, P as PreconditionImpl, e as RipploInstance } from './builder-
|
|
2
|
-
import { g as ObserverOutcome, C as CookieEntry, f as ObserverDefinition,
|
|
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';
|
|
3
3
|
|
|
4
4
|
interface EngineResult {
|
|
5
5
|
readonly cookies: ReadonlyArray<CookieEntry>;
|
|
6
|
-
readonly data: Record<string, Record<string,
|
|
6
|
+
readonly data: Record<string, Record<string, Primitive>>;
|
|
7
7
|
readonly error: string | undefined;
|
|
8
8
|
readonly executed: ReadonlyArray<string>;
|
|
9
9
|
readonly runId: string;
|
|
@@ -18,12 +18,12 @@ interface ObserverExecutionResult {
|
|
|
18
18
|
readonly success: boolean;
|
|
19
19
|
}
|
|
20
20
|
interface RipploEngine {
|
|
21
|
-
readonly executeObserver: (name: string, params: Record<string,
|
|
21
|
+
readonly executeObserver: (name: string, params: Record<string, Primitive>) => Promise<ObserverExecutionResult>;
|
|
22
22
|
readonly executePreconditions: (names: ReadonlyArray<string>, options?: ExecuteBatchOptions) => Promise<EngineResult>;
|
|
23
23
|
readonly getObservers: () => ReadonlyArray<ObserverDefinition>;
|
|
24
24
|
readonly getPreconditions: () => ReadonlyArray<PreconditionDefinition>;
|
|
25
25
|
readonly getUnimplemented: () => UnimplementedItems;
|
|
26
|
-
readonly teardown: (names: ReadonlyArray<string>, data: Record<string, Record<string,
|
|
26
|
+
readonly teardown: (names: ReadonlyArray<string>, data: Record<string, Record<string, Primitive>>) => Promise<void>;
|
|
27
27
|
}
|
|
28
28
|
declare const NOT_IMPLEMENTED_BRAND: unique symbol;
|
|
29
29
|
interface NotImplemented {
|
|
@@ -32,7 +32,7 @@ interface NotImplemented {
|
|
|
32
32
|
}
|
|
33
33
|
declare function notImplemented(reason?: string): NotImplemented;
|
|
34
34
|
type PreconditionImplFor<P> = P extends Precondition<infer TData, infer TDeps> ? PreconditionImpl<TData, TDeps> : never;
|
|
35
|
-
type ObserverImplFnFor<O> = O extends ObserverHandle<infer TInput> ? TInput extends Record<string,
|
|
35
|
+
type ObserverImplFnFor<O> = O extends ObserverHandle<infer TInput> ? TInput extends Record<string, Primitive> ? ObserverImplFn<TInput> : never : never;
|
|
36
36
|
interface EngineImpls<P extends PreconditionRegistry, O extends ObserverRegistry> {
|
|
37
37
|
readonly observers: {
|
|
38
38
|
readonly [K in keyof O]: NotImplemented | ObserverImplFnFor<O[K]>;
|
package/dist/express.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
-
import { R as RipploEngine } from './engine-
|
|
3
|
-
import './builder-
|
|
4
|
-
import './types-
|
|
2
|
+
import { R as RipploEngine } from './engine-B6MM4AEw.js';
|
|
3
|
+
import './builder-mhjAdyNW.js';
|
|
4
|
+
import './types-2i1Sm7_J.js';
|
|
5
5
|
import './step-De52hTLd.js';
|
|
6
6
|
import '@ripplo/spec';
|
|
7
7
|
|
package/dist/express.js
CHANGED
package/dist/fastify.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FastifyInstance } from 'fastify';
|
|
2
|
-
import { R as RipploEngine } from './engine-
|
|
3
|
-
import './builder-
|
|
4
|
-
import './types-
|
|
2
|
+
import { R as RipploEngine } from './engine-B6MM4AEw.js';
|
|
3
|
+
import './builder-mhjAdyNW.js';
|
|
4
|
+
import './types-2i1Sm7_J.js';
|
|
5
5
|
import './step-De52hTLd.js';
|
|
6
6
|
import '@ripplo/spec';
|
|
7
7
|
|
package/dist/fastify.js
CHANGED
package/dist/hono.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
|
-
import { R as RipploEngine } from './engine-
|
|
3
|
-
import './builder-
|
|
4
|
-
import './types-
|
|
2
|
+
import { R as RipploEngine } from './engine-B6MM4AEw.js';
|
|
3
|
+
import './builder-mhjAdyNW.js';
|
|
4
|
+
import './types-2i1Sm7_J.js';
|
|
5
5
|
import './step-De52hTLd.js';
|
|
6
6
|
import '@ripplo/spec';
|
|
7
7
|
|
package/dist/hono.js
CHANGED
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-
|
|
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';
|
|
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-
|
|
5
|
-
import { C as CookieEntry } from './types-
|
|
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,
|
|
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';
|
|
7
7
|
export { D as DslNodeInput } from './step-De52hTLd.js';
|
|
8
8
|
import '@ripplo/spec';
|
|
9
9
|
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DEFAULT_IGNORE_PATHS,
|
|
3
3
|
DEFAULT_WATCH_PATHS,
|
|
4
|
-
|
|
4
|
+
brandTestValue,
|
|
5
|
+
isPrimitive,
|
|
5
6
|
makeObserverHandle,
|
|
6
7
|
readObserverBudget,
|
|
7
8
|
readObserverDescription,
|
|
@@ -9,9 +10,8 @@ import {
|
|
|
9
10
|
readPreconditionDepMapping,
|
|
10
11
|
readPreconditionDependsOn,
|
|
11
12
|
readPreconditionDescription,
|
|
12
|
-
readPreconditionName
|
|
13
|
-
|
|
14
|
-
} from "./chunk-SBZJDJP4.js";
|
|
13
|
+
readPreconditionName
|
|
14
|
+
} from "./chunk-YQAEOH5W.js";
|
|
15
15
|
import {
|
|
16
16
|
compile
|
|
17
17
|
} from "./chunk-GWSEDWEF.js";
|
|
@@ -20,9 +20,52 @@ import {
|
|
|
20
20
|
buildSetCookieHeader,
|
|
21
21
|
serializeCookie,
|
|
22
22
|
verifyWebhookSignature
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-EHAZBEHO.js";
|
|
24
24
|
import "./chunk-4MGIQFAJ.js";
|
|
25
25
|
|
|
26
|
+
// src/chainable.ts
|
|
27
|
+
var BuilderChainError = class _BuilderChainError extends Error {
|
|
28
|
+
missingMethod;
|
|
29
|
+
validNext;
|
|
30
|
+
constructor(missingMethod, validNext) {
|
|
31
|
+
const valid = validNext.length === 0 ? "<chain is terminal>" : validNext.map((m) => `.${m}`).join(", ");
|
|
32
|
+
super(`\`.${missingMethod}\` is not a valid step in this builder chain. Valid next: ${valid}.`);
|
|
33
|
+
this.name = "BuilderChainError";
|
|
34
|
+
this.missingMethod = missingMethod;
|
|
35
|
+
this.validNext = validNext;
|
|
36
|
+
if (typeof Error.captureStackTrace === "function") {
|
|
37
|
+
Error.captureStackTrace(this, _BuilderChainError);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var PASSTHROUGH_PROPS = /* @__PURE__ */ new Set([
|
|
42
|
+
"then",
|
|
43
|
+
"catch",
|
|
44
|
+
"finally",
|
|
45
|
+
"toJSON",
|
|
46
|
+
"toString",
|
|
47
|
+
"valueOf",
|
|
48
|
+
"constructor",
|
|
49
|
+
"nodeType"
|
|
50
|
+
]);
|
|
51
|
+
function chainable(target) {
|
|
52
|
+
return new Proxy(target, {
|
|
53
|
+
get(t, prop, receiver) {
|
|
54
|
+
if (Reflect.has(t, prop)) {
|
|
55
|
+
return Reflect.get(t, prop, receiver);
|
|
56
|
+
}
|
|
57
|
+
if (typeof prop === "symbol") {
|
|
58
|
+
return void 0;
|
|
59
|
+
}
|
|
60
|
+
if (PASSTHROUGH_PROPS.has(prop)) {
|
|
61
|
+
return void 0;
|
|
62
|
+
}
|
|
63
|
+
const validNext = Object.keys(t).filter((k) => typeof Reflect.get(t, k) === "function");
|
|
64
|
+
throw new BuilderChainError(prop, validNext);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
26
69
|
// src/observer.ts
|
|
27
70
|
function createPassOutcome() {
|
|
28
71
|
return { kind: "pass" };
|
|
@@ -34,21 +77,21 @@ function createFailOutcome(reason) {
|
|
|
34
77
|
return { kind: "fail", reason };
|
|
35
78
|
}
|
|
36
79
|
function buildReady(state) {
|
|
37
|
-
return {
|
|
80
|
+
return chainable({
|
|
38
81
|
contract: () => makeObserverHandle(state)
|
|
39
|
-
};
|
|
82
|
+
});
|
|
40
83
|
}
|
|
41
84
|
function buildNeedsInput(state) {
|
|
42
|
-
return {
|
|
85
|
+
return chainable({
|
|
43
86
|
input: () => buildReady(state)
|
|
44
|
-
};
|
|
87
|
+
});
|
|
45
88
|
}
|
|
46
89
|
function buildObserver(name) {
|
|
47
|
-
return {
|
|
48
|
-
description: (description) => ({
|
|
90
|
+
return chainable({
|
|
91
|
+
description: (description) => chainable({
|
|
49
92
|
budget: (budget) => buildNeedsInput({ budget, description, name })
|
|
50
93
|
})
|
|
51
|
-
};
|
|
94
|
+
});
|
|
52
95
|
}
|
|
53
96
|
|
|
54
97
|
// src/builder.ts
|
|
@@ -146,7 +189,7 @@ function buildDepMapping(deps) {
|
|
|
146
189
|
}
|
|
147
190
|
function buildPreconditionStart(name) {
|
|
148
191
|
let description = "";
|
|
149
|
-
const self = {
|
|
192
|
+
const self = chainable({
|
|
150
193
|
contract: () => makePrecondition({
|
|
151
194
|
dependsOn: [],
|
|
152
195
|
depMapping: [],
|
|
@@ -160,7 +203,7 @@ function buildPreconditionStart(name) {
|
|
|
160
203
|
requires(deps) {
|
|
161
204
|
return buildPreconditionWithDeps({ deps, name, getDescription: () => description });
|
|
162
205
|
}
|
|
163
|
-
};
|
|
206
|
+
});
|
|
164
207
|
return self;
|
|
165
208
|
}
|
|
166
209
|
function buildPreconditionWithDeps({
|
|
@@ -171,26 +214,26 @@ function buildPreconditionWithDeps({
|
|
|
171
214
|
const description = getDescription();
|
|
172
215
|
const depMapping = buildDepMapping(deps);
|
|
173
216
|
const dependsOn = depMapping.map(([, depName]) => depName);
|
|
174
|
-
return {
|
|
217
|
+
return chainable({
|
|
175
218
|
contract: () => makePrecondition({
|
|
176
219
|
dependsOn,
|
|
177
220
|
depMapping,
|
|
178
221
|
description,
|
|
179
222
|
name
|
|
180
223
|
})
|
|
181
|
-
};
|
|
224
|
+
});
|
|
182
225
|
}
|
|
183
226
|
function buildTestName(id, uiOnly) {
|
|
184
|
-
return {
|
|
227
|
+
return chainable({
|
|
185
228
|
name: (displayName) => buildTestRequires({ id, name: displayName, uiOnly })
|
|
186
|
-
};
|
|
229
|
+
});
|
|
187
230
|
}
|
|
188
231
|
function castOutcome(value) {
|
|
189
232
|
return value;
|
|
190
233
|
}
|
|
191
234
|
function buildTestRequires({ id, name, uiOnly }) {
|
|
192
235
|
let description = "";
|
|
193
|
-
const self = {
|
|
236
|
+
const self = chainable({
|
|
194
237
|
description(text) {
|
|
195
238
|
description = text;
|
|
196
239
|
return self;
|
|
@@ -212,7 +255,7 @@ function buildTestRequires({ id, name, uiOnly }) {
|
|
|
212
255
|
})
|
|
213
256
|
);
|
|
214
257
|
}
|
|
215
|
-
};
|
|
258
|
+
});
|
|
216
259
|
return self;
|
|
217
260
|
}
|
|
218
261
|
function buildTestOutcome({
|
|
@@ -224,7 +267,7 @@ function buildTestOutcome({
|
|
|
224
267
|
uiOnly
|
|
225
268
|
}) {
|
|
226
269
|
const description = getDescription();
|
|
227
|
-
return {
|
|
270
|
+
return chainable({
|
|
228
271
|
expectedOutcome(text) {
|
|
229
272
|
return buildTestStartsAt({
|
|
230
273
|
description,
|
|
@@ -236,7 +279,7 @@ function buildTestOutcome({
|
|
|
236
279
|
uiOnly
|
|
237
280
|
});
|
|
238
281
|
}
|
|
239
|
-
};
|
|
282
|
+
});
|
|
240
283
|
}
|
|
241
284
|
function buildTestStartsAt({
|
|
242
285
|
description,
|
|
@@ -247,7 +290,7 @@ function buildTestStartsAt({
|
|
|
247
290
|
requiresKeys,
|
|
248
291
|
uiOnly
|
|
249
292
|
}) {
|
|
250
|
-
return {
|
|
293
|
+
return chainable({
|
|
251
294
|
notImplemented: () => ({
|
|
252
295
|
coverage: [],
|
|
253
296
|
description,
|
|
@@ -273,7 +316,7 @@ function buildTestStartsAt({
|
|
|
273
316
|
uiOnly
|
|
274
317
|
});
|
|
275
318
|
}
|
|
276
|
-
};
|
|
319
|
+
});
|
|
277
320
|
}
|
|
278
321
|
function buildTestSteps({
|
|
279
322
|
description,
|
|
@@ -285,8 +328,8 @@ function buildTestSteps({
|
|
|
285
328
|
startsAtFn,
|
|
286
329
|
uiOnly
|
|
287
330
|
}) {
|
|
288
|
-
return {
|
|
289
|
-
steps: (stepsFn) => ({
|
|
331
|
+
return chainable({
|
|
332
|
+
steps: (stepsFn) => chainable({
|
|
290
333
|
coverage: (...ids) => ({
|
|
291
334
|
coverage: ids,
|
|
292
335
|
description,
|
|
@@ -301,7 +344,7 @@ function buildTestSteps({
|
|
|
301
344
|
uiOnly
|
|
302
345
|
})
|
|
303
346
|
})
|
|
304
|
-
};
|
|
347
|
+
});
|
|
305
348
|
}
|
|
306
349
|
|
|
307
350
|
// src/lint.ts
|
|
@@ -930,7 +973,12 @@ async function executeOnePrecondition(state, name) {
|
|
|
930
973
|
const result = await def.setup(state.ctx, state.data);
|
|
931
974
|
const resolved = {};
|
|
932
975
|
Object.entries(result).forEach(([key, value]) => {
|
|
933
|
-
|
|
976
|
+
if (!isPrimitive(value)) {
|
|
977
|
+
throw new TypeError(
|
|
978
|
+
`Precondition "${name}" returned non-primitive value at key "${key}". Setup return values must be string, number, or boolean \u2014 produced via ctx.fixed/uniqueEmail/uniqueId.`
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
resolved[key] = value;
|
|
934
982
|
});
|
|
935
983
|
state.data[name] = resolved;
|
|
936
984
|
state.executed.push(name);
|
|
@@ -1002,13 +1050,13 @@ function createSetupContext({
|
|
|
1002
1050
|
}) {
|
|
1003
1051
|
return {
|
|
1004
1052
|
runId,
|
|
1005
|
-
fixed: (value) =>
|
|
1053
|
+
fixed: (value) => brandTestValue(value),
|
|
1006
1054
|
setCookie: (name, value, options) => {
|
|
1007
1055
|
const resolvedOptions = options != null && options.domain == null && defaultDomain != null ? { ...options, domain: defaultDomain } : options ?? void 0;
|
|
1008
1056
|
cookies.push({ name, options: resolvedOptions, value });
|
|
1009
1057
|
},
|
|
1010
|
-
uniqueEmail: () =>
|
|
1011
|
-
uniqueId: (prefix) =>
|
|
1058
|
+
uniqueEmail: () => brandTestValue(`ripplo-test-${runId}@test.ripplo.ai`),
|
|
1059
|
+
uniqueId: (prefix) => brandTestValue(`ripplo-test-${prefix}-${runId}`)
|
|
1012
1060
|
};
|
|
1013
1061
|
}
|
|
1014
1062
|
function deriveDefaultDomain(baseUrl) {
|
package/dist/koa.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Middleware } from 'koa';
|
|
2
|
-
import { R as RipploEngine } from './engine-
|
|
3
|
-
import './builder-
|
|
4
|
-
import './types-
|
|
2
|
+
import { R as RipploEngine } from './engine-B6MM4AEw.js';
|
|
3
|
+
import './builder-mhjAdyNW.js';
|
|
4
|
+
import './types-2i1Sm7_J.js';
|
|
5
5
|
import './step-De52hTLd.js';
|
|
6
6
|
import '@ripplo/spec';
|
|
7
7
|
|
package/dist/koa.js
CHANGED
package/dist/lockfile.d.ts
CHANGED
|
@@ -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-
|
|
5
|
-
import './types-
|
|
4
|
+
import './builder-mhjAdyNW.js';
|
|
5
|
+
import './types-2i1Sm7_J.js';
|
|
6
6
|
import './step-De52hTLd.js';
|
|
7
7
|
|
|
8
8
|
declare const LOCKFILE_RELATIVE_PATH = ".ripplo/ripplo.lock";
|
|
@@ -647,7 +647,7 @@ declare const lockfileBodySchema: z.ZodObject<{
|
|
|
647
647
|
observer: z.ZodString;
|
|
648
648
|
params: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
649
649
|
type: z.ZodLiteral<"static">;
|
|
650
|
-
value: z.ZodString
|
|
650
|
+
value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>;
|
|
651
651
|
}, z.core.$strip>, z.ZodObject<{
|
|
652
652
|
name: z.ZodString;
|
|
653
653
|
type: z.ZodLiteral<"variable">;
|
package/dist/lockfile.js
CHANGED
|
@@ -194,6 +194,13 @@ var numericValueRefSchema = z5.discriminatedUnion("type", [
|
|
|
194
194
|
z5.object({ type: z5.literal("static"), value: z5.number().int().nonnegative() }),
|
|
195
195
|
variableRefSchema
|
|
196
196
|
]);
|
|
197
|
+
var primitiveValueRefSchema = z5.discriminatedUnion("type", [
|
|
198
|
+
z5.object({
|
|
199
|
+
type: z5.literal("static"),
|
|
200
|
+
value: z5.union([z5.string(), z5.number(), z5.boolean()])
|
|
201
|
+
}),
|
|
202
|
+
variableRefSchema
|
|
203
|
+
]);
|
|
197
204
|
|
|
198
205
|
// ../spec/src/variables.ts
|
|
199
206
|
import { z as z6 } from "zod";
|
|
@@ -413,7 +420,7 @@ var assertObserverNode = z7.object({
|
|
|
413
420
|
...nodeBase,
|
|
414
421
|
budget: z7.enum(["fast", "slow", "async"]),
|
|
415
422
|
observer: z7.string().min(1).max(200),
|
|
416
|
-
params: z7.record(z7.string().max(200),
|
|
423
|
+
params: z7.record(z7.string().max(200), primitiveValueRefSchema),
|
|
417
424
|
type: z7.literal("assertObserver")
|
|
418
425
|
});
|
|
419
426
|
var specNodeSchema = z7.discriminatedUnion("type", [
|
package/dist/nestjs.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DynamicModule } from '@nestjs/common';
|
|
2
|
-
import { R as RipploEngine } from './engine-
|
|
3
|
-
import './builder-
|
|
4
|
-
import './types-
|
|
2
|
+
import { R as RipploEngine } from './engine-B6MM4AEw.js';
|
|
3
|
+
import './builder-mhjAdyNW.js';
|
|
4
|
+
import './types-2i1Sm7_J.js';
|
|
5
5
|
import './step-De52hTLd.js';
|
|
6
6
|
import '@ripplo/spec';
|
|
7
7
|
|
package/dist/nestjs.js
CHANGED
package/dist/nextjs.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { R as RipploEngine } from './engine-
|
|
2
|
-
import './builder-
|
|
3
|
-
import './types-
|
|
1
|
+
import { R as RipploEngine } from './engine-B6MM4AEw.js';
|
|
2
|
+
import './builder-mhjAdyNW.js';
|
|
3
|
+
import './types-2i1Sm7_J.js';
|
|
4
4
|
import './step-De52hTLd.js';
|
|
5
5
|
import '@ripplo/spec';
|
|
6
6
|
|
package/dist/nextjs.js
CHANGED
|
@@ -16,23 +16,24 @@ interface CookieEntry {
|
|
|
16
16
|
readonly value: string;
|
|
17
17
|
}
|
|
18
18
|
declare const TEST_VALUE_BRAND: unique symbol;
|
|
19
|
-
|
|
19
|
+
type Primitive = boolean | number | string;
|
|
20
|
+
type TestValue<T extends Primitive> = T & {
|
|
20
21
|
readonly [TEST_VALUE_BRAND]: true;
|
|
21
|
-
}
|
|
22
|
+
};
|
|
22
23
|
interface SetupContext {
|
|
23
24
|
readonly runId: string;
|
|
24
|
-
fixed(value:
|
|
25
|
+
fixed<T extends Primitive>(value: T): TestValue<T>;
|
|
25
26
|
setCookie(name: string, value: string, options?: CookieOptions): void;
|
|
26
|
-
uniqueEmail(): TestValue
|
|
27
|
-
uniqueId(prefix: string): TestValue
|
|
27
|
+
uniqueEmail(): TestValue<string>;
|
|
28
|
+
uniqueId(prefix: string): TestValue<string>;
|
|
28
29
|
}
|
|
29
|
-
interface TeardownContext<TData extends Record<string,
|
|
30
|
+
interface TeardownContext<TData extends Record<string, Primitive>> {
|
|
30
31
|
readonly data: TData;
|
|
31
32
|
}
|
|
32
33
|
declare const PRECONDITION_DATA: unique symbol;
|
|
33
34
|
declare const PRECONDITION_DEPS: unique symbol;
|
|
34
35
|
declare const PRECONDITION_NAME: unique symbol;
|
|
35
|
-
interface Precondition<TData extends Record<string,
|
|
36
|
+
interface Precondition<TData extends Record<string, Primitive> = Record<string, Primitive>, TDeps extends Record<string, Record<string, Primitive>> = Record<string, Record<string, Primitive>>> {
|
|
36
37
|
readonly [PRECONDITION_DATA]: TData;
|
|
37
38
|
readonly [PRECONDITION_DEPS]: TDeps;
|
|
38
39
|
readonly [PRECONDITION_NAME]: string;
|
|
@@ -46,10 +47,10 @@ interface PreconditionDefinition {
|
|
|
46
47
|
readonly implemented: boolean;
|
|
47
48
|
readonly name: string;
|
|
48
49
|
readonly returns: ReadonlyArray<string>;
|
|
49
|
-
readonly teardown: ((ctx: TeardownContext<Record<string,
|
|
50
|
-
readonly setup: (ctx: SetupContext, deps: Record<string, Record<string,
|
|
50
|
+
readonly teardown: ((ctx: TeardownContext<Record<string, Primitive>>) => Promise<void>) | undefined;
|
|
51
|
+
readonly setup: (ctx: SetupContext, deps: Record<string, Record<string, Primitive>>) => Promise<Record<string, Primitive>>;
|
|
51
52
|
}
|
|
52
|
-
type VarsFn<T> = (vars: Record<string, Record<string,
|
|
53
|
+
type VarsFn<T> = (vars: Record<string, Record<string, Primitive>>) => T;
|
|
53
54
|
interface TestDefinition {
|
|
54
55
|
readonly coverage: ReadonlyArray<string>;
|
|
55
56
|
readonly description: string;
|
|
@@ -100,7 +101,7 @@ interface ObserverDefinition {
|
|
|
100
101
|
readonly description: string;
|
|
101
102
|
readonly implemented: boolean;
|
|
102
103
|
readonly name: string;
|
|
103
|
-
readonly run: (ctx: ObserverContext, params: Record<string,
|
|
104
|
+
readonly run: (ctx: ObserverContext, params: Record<string, Primitive>) => Promise<ObserverOutcome>;
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
export { type CookieEntry as C, DEFAULT_IGNORE_PATHS as D, type ObserverHandle as O, type
|
|
107
|
+
export { type CookieEntry as C, DEFAULT_IGNORE_PATHS as D, type ObserverHandle as O, type Primitive as P, type SetupContext as S, type TeardownContext as T, type UnimplementedItems as U, type ObserverInput as a, type ObserverBudgetTier as b, type CookieOptions as c, DEFAULT_WATCH_PATHS as d, type ObserverContext as e, type ObserverDefinition as f, type ObserverOutcome as g, type Precondition as h, type PreconditionDeps as i, type TestDefinition as j, type TestValue as k, type PreconditionDefinition as l, type PreconditionData as m };
|