@systemfsoftware/vitest 0.0.0 → 0.2.0

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.
@@ -0,0 +1,336 @@
1
+
2
+ import * as V from "vitest";
3
+ import * as Cause from "effect/Cause";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Tracer from "effect/Tracer";
6
+ import * as Context from "effect/Context";
7
+ //#region src/internal/failure-record.d.ts
8
+ /** A value the renderer narrows rather than assumes. */
9
+ type Opaque$1<A = unknown> = A;
10
+ /**
11
+ * A value a recorded span attribute or a replay path carries. Structured values stay structured on the span
12
+ * (KTD2); the renderer decides the text.
13
+ *
14
+ * @internal
15
+ */
16
+ type AttributeValue = string | number | boolean | null | ReadonlyArray<AttributeValue> | {
17
+ readonly [key: string]: AttributeValue;
18
+ };
19
+ /**
20
+ * The test a failure happened in, as Vitest knows it. `file` is the path the rerun command names, so a caller
21
+ * that holds an absolute path derives the repo-relative one before handing it over.
22
+ *
23
+ * @internal
24
+ */
25
+ interface TestIdentity {
26
+ /**
27
+ * The npm package the test file belongs to, e.g. `@systemfsoftware/effect-readiness`. Empty when the run
28
+ * provided no name: the rerun command then drops its `pnpm --filter` prefix and runs from the package
29
+ * directory, which is not a breach (R6).
30
+ */
31
+ readonly package: string;
32
+ /** The test file, as the rerun command writes it. */
33
+ readonly file: string;
34
+ /** The scenario name the rerun command filters on with `-t`. */
35
+ readonly name: string;
36
+ }
37
+ /**
38
+ * The value a generator chose a run by: the kernel's seed and decision path, or a property counterexample's
39
+ * seed and path. A path without a seed is a replay value offered for a baseline run, which R6 refuses (KTD5).
40
+ *
41
+ * @internal
42
+ */
43
+ interface ReplayValue {
44
+ /** The generator's seed, or `undefined` when only a path was recorded. */
45
+ readonly seed: number | undefined;
46
+ /** The decisions or inputs the generator chose, in order. */
47
+ readonly path: ReadonlyArray<AttributeValue>;
48
+ }
49
+ /**
50
+ * A contract rule a rendered record breaks; the runner refuses such a record (R10, KTD7).
51
+ *
52
+ * @internal
53
+ */
54
+ type Breach = 'R1' | 'R2' | 'R6';
55
+ /**
56
+ * What a rendered failure gives Vitest: the tag the error carries, the record text, and the rules it breaks.
57
+ *
58
+ * @internal
59
+ */
60
+ interface FailureRecord {
61
+ /** The headline's failure tag, e.g. `StepError`; the runner sets it as the thrown error's `name`. */
62
+ readonly name: string;
63
+ /** The text Vitest prints as the failure's message. */
64
+ readonly record: string;
65
+ /** The contract rules the record breaks: `R1` empty headline, `R2` no location, `R6` replay or rerun. */
66
+ readonly breaches: ReadonlyArray<Breach>;
67
+ }
68
+ /**
69
+ * Everything one failure is rendered from: the failure, its run's spans, the test and the replay value.
70
+ *
71
+ * @internal
72
+ */
73
+ interface FailureRecordInput<E = never> {
74
+ /** The failure itself: a `Cause`, or the value a program threw or failed with. */
75
+ readonly failure: Cause.Cause<E> | E;
76
+ /** Every span the failing run recorded, in creation order. */
77
+ readonly spans: ReadonlyArray<Tracer.NativeSpan>;
78
+ /** The test the run belonged to. */
79
+ readonly identity: TestIdentity;
80
+ /** The generator that chose this run, or `undefined` on a run no generator chose. */
81
+ readonly replay: ReplayValue | undefined;
82
+ /**
83
+ * The seed the kernel's scheduler chose. The kernel knows its own scheduler, so it hands the note over rather
84
+ * than the renderer guessing it; a run no scheduler chose renders no note (KTD5).
85
+ */
86
+ readonly schedule?: {
87
+ readonly seed: number;
88
+ } | undefined;
89
+ /**
90
+ * The workspace root the rendered paths are relativized against, provided by the shared config the same way the
91
+ * package name is. Omitted, paths print absolute.
92
+ */
93
+ readonly root?: string | undefined;
94
+ }
95
+ /** @internal */
96
+ declare const summaryOf: (value: Opaque$1) => string;
97
+ /**
98
+ * Renders the record Vitest prints for one spec failure, and the contract rules it breaks.
99
+ *
100
+ * Never throws: a `Cause` renders layer by layer, a thrown `Error` renders as one layer, and any other value
101
+ * renders as itself. The first location the record names is the raising frame — the first stack frame outside
102
+ * `node_modules` and outside the spec libraries' own `src/` and `dist/` — and when no layer has one, the
103
+ * innermost failed span's site stands in, or the innermost unfinished cell's decide site for a deadlock (KTD6).
104
+ *
105
+ * @internal
106
+ */
107
+ declare const renderFailureRecord: <E>(input: FailureRecordInput<E>) => FailureRecord;
108
+ //#endregion
109
+ //#region src/internal/refusals.d.ts
110
+ /** @internal */
111
+ declare const refusedText: {
112
+ readonly toBeDefined: '✗ toBeDefined passes for almost any value the code returns. Assert the value: yield* expect(actual).toEqual(expected).';
113
+ readonly toBeTruthy: '✗ toBeTruthy passes for almost any value the code returns. Assert the value: yield* expect(actual).toEqual(expected).';
114
+ readonly toBeFalsy: '✗ toBeFalsy passes for almost any value the code returns. Assert the value: yield* expect(actual).toEqual(expected).';
115
+ readonly toHaveLength: '✗ toHaveLength checks how many, not which. Assert the contents: toEqual([...]); only some of them: toEqual(expect.arrayContaining([...])).';
116
+ readonly toHaveProperty: '✗ toHaveProperty checks one key at a time. Assert the shape once: toMatchObject({ key: value, ... }).';
117
+ readonly toBeInstanceOf: '✗ toBeInstanceOf checks the kind of value, not the value. Assert the value: toEqual(expected); only its shape: toEqual(expect.schemaMatching(Schema)).';
118
+ readonly toBeTypeOf: '✗ toBeTypeOf checks the kind of value, not the value. Assert the value: toEqual(expected); only its shape: toEqual(expect.schemaMatching(Schema)).';
119
+ readonly toHaveBeenCalled: '✗ toHaveBeenCalled passes for any call with any arguments. Assert what the call carried: toHaveBeenCalledExactlyOnceWith(...args).';
120
+ readonly toHaveBeenCalledTimes: '✗ toHaveBeenCalledTimes counts calls, not what they carried. Assert the calls: toHaveBeenNthCalledWith(n, ...args), or all of them: expect(spy.mock.calls).toEqual([[...], [...]]).';
121
+ readonly toMatchSnapshot: '✗ a snapshot records what the code does now, not what it should do, and cannot fail on the run that writes it. State the expected value: toEqual(expected).';
122
+ readonly toMatchInlineSnapshot: '✗ a snapshot records what the code does now, not what it should do, and cannot fail on the run that writes it. State the expected value: toEqual(expected).';
123
+ readonly toMatchFileSnapshot: '✗ a snapshot records what the code does now, not what it should do, and cannot fail on the run that writes it. State the expected value: toEqual(expected).';
124
+ readonly toThrowErrorMatchingSnapshot: '✗ a snapshot records what the code does now, not what it should do, and cannot fail on the run that writes it. Name the error: toThrow(MyError).';
125
+ readonly toThrowErrorMatchingInlineSnapshot: '✗ a snapshot records what the code does now, not what it should do, and cannot fail on the run that writes it. Name the error: toThrow(MyError).';
126
+ readonly resolves: '✗ .resolves/.rejects assert on a Promise outside the test runtime. Yield the Effect: const value = yield* program; its failure: const error = yield* Effect.flip(program); then yield* expect(error).toEqual(new MyError(...)).';
127
+ readonly rejects: '✗ .resolves/.rejects assert on a Promise outside the test runtime. Yield the Effect: const value = yield* program; its failure: const error = yield* Effect.flip(program); then yield* expect(error).toEqual(new MyError(...)).';
128
+ readonly anything: '✗ expect.anything() matches every value. Say what the value must be: expect.any(Money), expect.objectContaining({ ... }), expect.schemaMatching(Schema).';
129
+ readonly poll: '✗ expect.poll waits on the real clock, outside the runner\'s virtual time. Let time pass inside the test: yield* TestClock.adjust("3 seconds"); then yield* expect(value).toEqual(expected).';
130
+ readonly soft: '✗ expect.soft reports several failures on one state; the fork reports the state once. Assert the state once: yield* expect(actual).toEqual(expected).';
131
+ };
132
+ /** @internal */
133
+ type refusedText = typeof refusedText;
134
+ /** @internal */
135
+ declare const negatedText: {
136
+ readonly toBeDefined: '✗ toBeDefined passes for almost any value the code returns. Assert the value: yield* expect(actual).toEqual(expected).';
137
+ readonly toBeTruthy: '✗ toBeTruthy passes for almost any value the code returns. Assert the value: yield* expect(actual).toEqual(expected).';
138
+ readonly toBeFalsy: '✗ toBeFalsy passes for almost any value the code returns. Assert the value: yield* expect(actual).toEqual(expected).';
139
+ readonly toHaveLength: '✗ toHaveLength checks how many, not which. Assert the contents: toEqual([...]); only some of them: toEqual(expect.arrayContaining([...])).';
140
+ readonly toHaveProperty: '✗ toHaveProperty checks one key at a time. Assert the shape once: toMatchObject({ key: value, ... }).';
141
+ readonly toBeInstanceOf: '✗ toBeInstanceOf checks the kind of value, not the value. Assert the value: toEqual(expected); only its shape: toEqual(expect.schemaMatching(Schema)).';
142
+ readonly toBeTypeOf: '✗ toBeTypeOf checks the kind of value, not the value. Assert the value: toEqual(expected); only its shape: toEqual(expect.schemaMatching(Schema)).';
143
+ readonly toHaveBeenCalled: '✗ toHaveBeenCalled passes for any call with any arguments. Assert what the call carried: toHaveBeenCalledExactlyOnceWith(...args).';
144
+ readonly toHaveBeenCalledTimes: '✗ toHaveBeenCalledTimes counts calls, not what they carried. Assert the calls: toHaveBeenNthCalledWith(n, ...args), or all of them: expect(spy.mock.calls).toEqual([[...], [...]]).';
145
+ readonly toMatchSnapshot: '✗ a snapshot records what the code does now, not what it should do, and cannot fail on the run that writes it. State the expected value: toEqual(expected).';
146
+ readonly toMatchInlineSnapshot: '✗ a snapshot records what the code does now, not what it should do, and cannot fail on the run that writes it. State the expected value: toEqual(expected).';
147
+ readonly toMatchFileSnapshot: '✗ a snapshot records what the code does now, not what it should do, and cannot fail on the run that writes it. State the expected value: toEqual(expected).';
148
+ readonly toThrowErrorMatchingSnapshot: '✗ a snapshot records what the code does now, not what it should do, and cannot fail on the run that writes it. Name the error: toThrow(MyError).';
149
+ readonly toThrowErrorMatchingInlineSnapshot: '✗ a snapshot records what the code does now, not what it should do, and cannot fail on the run that writes it. Name the error: toThrow(MyError).';
150
+ readonly resolves: '✗ .resolves/.rejects assert on a Promise outside the test runtime. Yield the Effect: const value = yield* program; its failure: const error = yield* Effect.flip(program); then yield* expect(error).toEqual(new MyError(...)).';
151
+ readonly rejects: '✗ .resolves/.rejects assert on a Promise outside the test runtime. Yield the Effect: const value = yield* program; its failure: const error = yield* Effect.flip(program); then yield* expect(error).toEqual(new MyError(...)).';
152
+ readonly anything: '✗ expect.anything() matches every value. Say what the value must be: expect.any(Money), expect.objectContaining({ ... }), expect.schemaMatching(Schema).';
153
+ readonly poll: '✗ expect.poll waits on the real clock, outside the runner\'s virtual time. Let time pass inside the test: yield* TestClock.adjust("3 seconds"); then yield* expect(value).toEqual(expected).';
154
+ readonly soft: '✗ expect.soft reports several failures on one state; the fork reports the state once. Assert the state once: yield* expect(actual).toEqual(expected).';
155
+ readonly toBeNull: '✗ not.toBeNull passes for almost any value the code returns. Assert the value: yield* expect(actual).toEqual(expected).';
156
+ readonly toBeUndefined: '✗ not.toBeUndefined passes for almost any value the code returns. Assert the value: yield* expect(actual).toEqual(expected).';
157
+ };
158
+ /** @internal */
159
+ type negatedText = typeof negatedText;
160
+ /** @internal */
161
+ declare const neededText: {
162
+ readonly toThrow: '✗ toThrow() passes for any error. Name the one expected: toThrow(MyError) or toThrow("message"). An Effect failure is a value: const error = yield* Effect.flip(program); yield* expect(error).toEqual(new MyError(...)).';
163
+ readonly toThrowError: '✗ toThrowError() passes for any error. Name the one expected: toThrow(MyError) or toThrow("message"). An Effect failure is a value: const error = yield* Effect.flip(program); yield* expect(error).toEqual(new MyError(...)).';
164
+ readonly toSatisfy: '✗ toSatisfy(predicate) fails with \'expected x to satisfy [Function]\'. Say what must hold: toSatisfy(predicate, "every line has a positive quantity").';
165
+ readonly toMatchObject: '✗ toMatchObject({}) matches every object. Name the fields that must hold: toMatchObject({ status: "Pending" }).';
166
+ };
167
+ /** @internal */
168
+ type neededText = typeof neededText;
169
+ /** @internal */
170
+ declare const booleanRefusal = "✗ expect(<boolean>) can only report 'expected false to be true'. Pass the two values instead: yield* expect(a).toEqual(b), which uses Effect Equal. A predicate: yield* expect(value).toSatisfy(predicate, \"what must hold\").";
171
+ /** @internal */
172
+ type booleanRefusal = typeof booleanRefusal;
173
+ /** @internal */
174
+ declare const noCheckRefusal = "✗ this test yields no check, so it cannot fail. Yield one from the test's own expect: it(name, function* ({ expect }) { yield* expect(actual).toEqual(expected) }). An expect imported from vitest does not count.";
175
+ /** @internal */
176
+ type noCheckRefusal = typeof noCheckRefusal;
177
+ /** @internal */
178
+ type NoCheckRefusal = typeof noCheckRefusal;
179
+ /** @internal */
180
+ declare const unprovidedText = "✗ the test needs a service that nothing provides. Write the test inside layer(Service.layer)((it) => { it(name, ...) }); every test gets its own fresh build.";
181
+ /** @internal */
182
+ type unprovidedText = typeof unprovidedText;
183
+ /** @internal */
184
+ type UnprovidedRefusal = typeof unprovidedText;
185
+ /** @internal */
186
+ declare const refuseEffectBody = "✗ the body returned an Effect, so the runner cannot see its steps. Pass the generator itself: it(name, function* ({ expect }) { ... }).";
187
+ /** @internal */
188
+ type refuseEffectBody = typeof refuseEffectBody;
189
+ /** @internal */
190
+ type RefuseEffectBody = typeof refuseEffectBody;
191
+ /** @internal */
192
+ declare const refuseAsyncBody = "✗ an async body runs outside the test runtime. Pass a generator: it(name, function* ({ expect }) { yield* expect(actual).toEqual(expected) }).";
193
+ /** @internal */
194
+ type refuseAsyncBody = typeof refuseAsyncBody;
195
+ /** @internal */
196
+ type RefuseAsyncBody = typeof refuseAsyncBody;
197
+ /** @internal */
198
+ declare const refuseSyncBody = "✗ the body must be a generator that yields its checks: it(name, function* ({ expect }) { const x = yield* program; yield* expect(x).toEqual(expected) }).";
199
+ /** @internal */
200
+ type refuseSyncBody = typeof refuseSyncBody;
201
+ /** @internal */
202
+ type RefuseSyncBody = typeof refuseSyncBody;
203
+ /** @internal */
204
+ declare const refuseEffectLane = "✗ it.effect is removed: the body is the generator itself, so the runner sees every step. it(name, function* ({ expect }) { const x = yield* program; yield* expect(x).toEqual(expected) }).";
205
+ /** @internal */
206
+ type refuseEffectLane = typeof refuseEffectLane;
207
+ /** @internal */
208
+ type EffectLaneRefusal = typeof refuseEffectLane;
209
+ /** @internal */
210
+ declare const refuseScopedLane = "✗ it.scoped is removed: the body is the generator itself, so the runner sees every step. it(name, function* ({ expect }) { const x = yield* program; yield* expect(x).toEqual(expected) }).";
211
+ /** @internal */
212
+ type refuseScopedLane = typeof refuseScopedLane;
213
+ /** @internal */
214
+ type ScopedLaneRefusal = typeof refuseScopedLane;
215
+ /** @internal */
216
+ declare const refuseScopedLiveLane = "✗ it.scopedLive is removed: the body is the generator itself, so the runner sees every step. it(name, function* ({ expect }) { const x = yield* program; yield* expect(x).toEqual(expected) }).";
217
+ /** @internal */
218
+ type refuseScopedLiveLane = typeof refuseScopedLiveLane;
219
+ /** @internal */
220
+ type ScopedLiveLaneRefusal = typeof refuseScopedLiveLane;
221
+ /** @internal */
222
+ declare const refuseHook = "✗ hooks share state between tests. Build what a test needs inside it; services come fresh per test from layer(Service.layer)((it) => { ... }).";
223
+ /** @internal */
224
+ type refuseHook = typeof refuseHook;
225
+ /** @internal */
226
+ type HookRefusal = typeof refuseHook;
227
+ //#endregion
228
+ //#region src/internal/checks.d.ts
229
+ /** An opaque runtime value: the fork does not read it, only hands it back. */
230
+ type Opaque<A = unknown> = A;
231
+ type Assertion<A> = V.Assertion<void, A>;
232
+ /** @internal */
233
+ type MakeAssertion = <A>(actual: A, message?: string) => Assertion<A>;
234
+ /** @internal */
235
+ type Judgement = (make: MakeAssertion) => void;
236
+ /**
237
+ * The service a check needs. `judge` counts the check and throws {@link refusePiecewise} when a check already ran
238
+ * since the last {@link AssertedShape.step}; `step` opens a new observed state.
239
+ *
240
+ * @internal
241
+ */
242
+ interface AssertedShape {
243
+ readonly judge: (judgement: Judgement) => void;
244
+ readonly step: () => void;
245
+ }
246
+ declare const Asserted_base: Context.ServiceClass<Asserted, "@systemfsoftware/vitest/Asserted", AssertedShape>;
247
+ /** @internal */
248
+ declare class Asserted extends Asserted_base {}
249
+ /**
250
+ * An Effect that performs one check. Only the runner can provide what it needs.
251
+ *
252
+ * @internal
253
+ */
254
+ type Check = Effect.Effect<void, never, Asserted>;
255
+ type Refusal<T extends string> = (this: T, ...args: ReadonlyArray<Opaque>) => Check;
256
+ type StaticRefusal<T extends string> = (this: T, ...args: ReadonlyArray<Opaque>) => never;
257
+ /** Callable only with the arguments that make it specific; the empty call's `this` type is the rewrite. */
258
+ interface Needs<Args extends ReadonlyArray<Opaque>, T extends string> {
259
+ (...args: Args): Check;
260
+ (this: T, ...args: ReadonlyArray<Opaque>): Check;
261
+ }
262
+ type MatcherName = Extract<keyof Assertion<Opaque>, `to${string}`>;
263
+ type ArgsOf<A, K extends MatcherName> = Assertion<A>[K] extends ((...args: infer P) => infer _) ? P : never;
264
+ type Refused = Extract<keyof typeof refusedText, MatcherName>;
265
+ type Needed = keyof typeof neededText;
266
+ type NegatedRefused = Extract<keyof typeof negatedText, MatcherName>;
267
+ /** The values `toThrow(X)` names the error with: a message, a pattern, an error class, or an error instance. */
268
+ type ThrowExpected = string | RegExp | (abstract new (...args: ReadonlyArray<never>) => Opaque) | Error;
269
+ /** @internal */
270
+ type Positive<A> = { readonly [K in Exclude<MatcherName, Refused | Needed>]: (...args: ArgsOf<A, K>) => Check; } & { readonly [K in Refused]: Refusal<(typeof refusedText)[K]>; } & {
271
+ readonly toThrow: Needs<[expected: ThrowExpected], (typeof neededText)['toThrow']>;
272
+ readonly toThrowError: Needs<[expected: ThrowExpected], (typeof neededText)['toThrowError']>;
273
+ readonly toSatisfy: Needs<[predicate: (value: A) => boolean, holds: string], (typeof neededText)['toSatisfy']>;
274
+ readonly toMatchObject: Needs<ArgsOf<A, 'toMatchObject'>, (typeof neededText)['toMatchObject']>;
275
+ readonly resolves: (typeof refusedText)['resolves'];
276
+ readonly rejects: (typeof refusedText)['rejects'];
277
+ };
278
+ /** @internal */
279
+ type Negative<A> = { readonly [K in Exclude<MatcherName, NegatedRefused>]: (...args: ArgsOf<A, K>) => Check; } & { readonly [K in NegatedRefused]: Refusal<(typeof negatedText)[K]>; };
280
+ /** @internal */
281
+ type Checked<A> = Positive<A> & {
282
+ readonly not: Negative<A>;
283
+ };
284
+ /** An asymmetric matcher: an opaque value vitest reads when the check runs. */
285
+ type Matcher = object;
286
+ /**
287
+ * The asymmetric matchers vitest builds: each names what a value must be, and only vitest reads the result.
288
+ *
289
+ * @internal
290
+ */
291
+ interface Matchers {
292
+ readonly objectContaining: <T = Opaque>(expected: V.DeeplyAllowMatchers<T>) => Matcher;
293
+ readonly arrayContaining: <T = Opaque>(expected: Array<V.DeeplyAllowMatchers<T>>) => Matcher;
294
+ readonly stringContaining: (expected: string) => Matcher;
295
+ readonly stringMatching: (expected: string | RegExp) => Matcher;
296
+ readonly closeTo: (expected: number, precision?: number) => Matcher;
297
+ /** Accepts an Effect Schema directly, or any Standard Schema. */
298
+ readonly schemaMatching: (schema: Opaque) => Matcher;
299
+ }
300
+ /**
301
+ * `expect.not.<matcher>`: the four asymmetric matchers whose negation states an absence honestly.
302
+ *
303
+ * @internal
304
+ */
305
+ type NegatedMatchers = Pick<Matchers, 'objectContaining' | 'arrayContaining' | 'stringContaining' | 'stringMatching'>;
306
+ /**
307
+ * The asymmetric matchers that name what a value must be, the same matchers negated, and the statics the fork
308
+ * refuses by name.
309
+ *
310
+ * @internal
311
+ */
312
+ interface Shapes extends Matchers {
313
+ readonly any: (constructor: Opaque) => Matcher;
314
+ /**
315
+ * `expect.not.<matcher>`, forwarded to vitest's own negated statics (`@vitest/expect/dist/index.d.ts:172`
316
+ * declares `not: AsymmetricMatchersContaining`); only the four honest absences are exposed.
317
+ */
318
+ readonly not: NegatedMatchers;
319
+ readonly anything: StaticRefusal<(typeof refusedText)['anything']>;
320
+ readonly poll: StaticRefusal<(typeof refusedText)['poll']>;
321
+ readonly soft: StaticRefusal<(typeof refusedText)['soft']>;
322
+ }
323
+ /** @internal */
324
+ interface Expect extends Shapes {
325
+ <A>(actual: [A] extends [boolean] ? (typeof booleanRefusal) : A, message?: string): Checked<A>;
326
+ }
327
+ /**
328
+ * What a test body receives.
329
+ *
330
+ * @internal
331
+ */
332
+ interface Checks {
333
+ readonly expect: Expect;
334
+ }
335
+ //#endregion
336
+ export { summaryOf as S, FailureRecord as _, Expect as a, TestIdentity as b, NoCheckRefusal as c, RefuseSyncBody as d, ScopedLaneRefusal as f, Breach as g, AttributeValue as h, Checks as i, RefuseAsyncBody as l, UnprovidedRefusal as m, AssertedShape as n, EffectLaneRefusal as o, ScopedLiveLaneRefusal as p, Check as r, HookRefusal as s, Asserted as t, RefuseEffectBody as u, FailureRecordInput as v, renderFailureRecord as x, ReplayValue as y };
@@ -0,0 +1,158 @@
1
+
2
+ import * as Cause from "effect/Cause";
3
+ import * as Effect from "effect/Effect";
4
+ import * as Schema$1 from "effect/Schema";
5
+ import { Schema } from "effect";
6
+ import * as Arbitrary from "effect/unstable/arbitrary/Arbitrary";
7
+ //#endregion
8
+ //#region src/internal/errors.schema.d.ts
9
+ declare const NonBooleanVerdict_base: Schema.Class<NonBooleanVerdict, Schema.TaggedStruct<"NonBooleanVerdict", {
10
+ readonly detail: Schema.String;
11
+ }>, import("effect/Cause").YieldableError>;
12
+ /** @internal */
13
+ declare class NonBooleanVerdict extends NonBooleanVerdict_base {
14
+ get message(): string;
15
+ }
16
+ //#endregion
17
+ //#region src/internal/property/impostor.d.ts
18
+ /**
19
+ * @internal The constant impostor of R12: a fake of the subject under test that
20
+ * returns the first output it ever produced, for every later call, whatever the
21
+ * input it was given.
22
+ *
23
+ * A property that still holds for the impostor does not constrain the subject.
24
+ * Whether that is fatal is a per-file question — a subject's impostor must be
25
+ * refuted by some property in its file — so this module builds the fake and
26
+ * collects the verdicts; the engine decides them once, when the file finishes
27
+ * (KTD10).
28
+ */
29
+ /**
30
+ * A value the fork hands over without inspecting: an argument to the subject, or one of its outputs.
31
+ *
32
+ * @internal
33
+ */
34
+ type Opaque<A = unknown> = A;
35
+ /**
36
+ * A function under test: any argument, any output.
37
+ *
38
+ * @internal
39
+ */
40
+ type SubjectFunction = (...values: ReadonlyArray<never>) => Opaque;
41
+ /**
42
+ * A record of functions under test; every member is replaced by a constant.
43
+ *
44
+ * @internal
45
+ */
46
+ type MemberRecord = {
47
+ readonly [key: string]: SubjectFunction;
48
+ };
49
+ /**
50
+ * The function under test, or a record of them.
51
+ *
52
+ * @internal
53
+ */
54
+ type Subject = SubjectFunction | MemberRecord;
55
+ declare namespace kinds_d_exports {
56
+ export { LawApi, LawKind, LawSubject, MetamorphicRelation, deterministicHolds, idempotentHolds, invariantHolds, metamorphicHolds, modelHolds, roundTripHolds, spreadValues };
57
+ }
58
+ /** @internal */
59
+ type LawKind = 'model' | 'metamorphic' | 'roundTrip' | 'invariant' | 'idempotent' | 'deterministic';
60
+ /**
61
+ * A subject of a law kind: a function of the generated values.
62
+ *
63
+ * @internal
64
+ */
65
+ type LawSubject<G extends Gens, A> = (...values: ReadonlyArray<ElementValues<G>>) => A;
66
+ /**
67
+ * A metamorphic relation: the input transform, and how the two outputs relate (structural equality by default).
68
+ *
69
+ * @internal
70
+ */
71
+ interface MetamorphicRelation<G extends Gens, A> {
72
+ readonly transform: (...values: ReadonlyArray<ElementValues<G>>) => Values<G>;
73
+ readonly relate?: (original: A, transformed: A) => boolean;
74
+ }
75
+ /**
76
+ * The R13 law surface: four gated kinds and two declared exemptions.
77
+ *
78
+ * @internal
79
+ */
80
+ interface LawApi {
81
+ readonly model: <const G extends Gens, A, N extends number, S extends LawSubject<G, A>>(name: string, spec: PropertySpec<G, S, N>, oracle: LawSubject<G, A>) => void;
82
+ readonly metamorphic: <const G extends Gens, A, N extends number, S extends LawSubject<G, A>>(name: string, spec: PropertySpec<G, S, N>, relation: MetamorphicRelation<G, A>) => void;
83
+ readonly roundTrip: <const G extends Gens, E, N extends number, S extends LawSubject<G, E>>(name: string, spec: PropertySpec<G, S, N>, decode: (encoded: E) => Values<G>) => void;
84
+ readonly invariant: <const G extends Gens, A, N extends number, S extends LawSubject<G, A>>(name: string, spec: PropertySpec<G, S, N>, holds: (output: A, ...values: ReadonlyArray<ElementValues<G>>) => boolean) => void;
85
+ readonly idempotent: <const G extends Gens, N extends number, S extends (value: ElementValues<G>) => ElementValues<G>>(name: string, spec: PropertySpec<G, S, N>) => void;
86
+ readonly deterministic: <const G extends Gens, A, N extends number, S extends LawSubject<G, A>>(name: string, spec: PropertySpec<G, S, N>) => void;
87
+ }
88
+ /**
89
+ * The generated values as the argument list a law subject is called with.
90
+ *
91
+ * @internal
92
+ */
93
+ declare const spreadValues: <G extends Gens>(values: Values<G>) => ReadonlyArray<ElementValues<G>>;
94
+ /** @internal */
95
+ declare const modelHolds: <G extends Gens, A>(oracle: LawSubject<G, A>) => (subject: LawSubject<G, A>, values: Values<G>) => boolean;
96
+ /** @internal */
97
+ declare const metamorphicHolds: <G extends Gens, A>(relation: MetamorphicRelation<G, A>) => (subject: LawSubject<G, A>, values: Values<G>) => boolean;
98
+ /** @internal */
99
+ declare const roundTripHolds: <G extends Gens, E>(decode: (encoded: E) => Values<G>) => (subject: LawSubject<G, E>, values: Values<G>) => boolean;
100
+ /** @internal */
101
+ declare const invariantHolds: <G extends Gens, A>(holds: (output: A, ...values: ReadonlyArray<ElementValues<G>>) => boolean) => (subject: LawSubject<G, A>, values: Values<G>) => boolean;
102
+ /** @internal */
103
+ declare const idempotentHolds: <G extends Gens>() => (subject: (value: ElementValues<G>) => ElementValues<G>, values: Values<G>) => boolean;
104
+ /** @internal */
105
+ declare const deterministicHolds: <G extends Gens, A>() => (subject: LawSubject<G, A>, values: Values<G>) => boolean;
106
+ declare namespace engine_d_exports {
107
+ export { ArbitraryInput, CoveragePredicate, ElementValues, Gens, PropApi, PropertyRuntime, PropertySpec, PropertySubject, Values, makeProperty };
108
+ }
109
+ /** @internal */
110
+ type ArbitraryInput = Schema$1.Top | Arbitrary.Arbitrary<Schema$1.Top['Type']>;
111
+ /** @internal */
112
+ type Gens = ReadonlyArray<ArbitraryInput> | {
113
+ readonly [key: string]: ArbitraryInput;
114
+ };
115
+ type Generated<I> = I extends Schema$1.Schema<infer T> ? T : I extends Arbitrary.Arbitrary<infer A> ? A : never;
116
+ /** @internal */
117
+ type Values<G extends Gens> = { readonly [K in keyof G]: Generated<G[K]>; };
118
+ /** @internal */
119
+ type ElementValues<G extends Gens> = G extends ReadonlyArray<ArbitraryInput> ? Generated<G[number]> : never;
120
+ /** @internal */
121
+ type PropertySubject = Subject;
122
+ /** @internal */
123
+ type CoveragePredicate<G extends Gens> = (...values: ReadonlyArray<ElementValues<G>>) => boolean;
124
+ type PropertyRuns<N extends number> = number extends N ? number : `${N}` extends `-${bigint}` ? never : `${N}` extends `${bigint}` ? (N extends 0 ? never : N) : never;
125
+ /** @internal */
126
+ interface PropertySpec<G extends Gens, S extends PropertySubject, N extends number> {
127
+ readonly of: G;
128
+ readonly subject: S;
129
+ /**
130
+ * The property's own run count. Omitted, the configured default applies; when the run provides none,
131
+ * the built-in default of 100 does.
132
+ */
133
+ readonly runs?: N & PropertyRuns<N>;
134
+ /** Labelled input predicates, each with the minimum share of runs it must see (R14). */
135
+ readonly cover?: Readonly<Record<string, readonly [CoveragePredicate<G>, number]>>;
136
+ /** The property's own check options, merged field by field over the provided and built-in defaults. */
137
+ readonly arbitrary?: Arbitrary.CheckOptions;
138
+ }
139
+ /** @internal */
140
+ interface PropertyRuntime<R> {
141
+ /** Registers the property's program; the runtime runs it inside the test it registers, under that test's binding. */
142
+ readonly register: (name: string, program: () => Effect.Effect<void, Cause.Cause<NonBooleanVerdict>, never>) => void;
143
+ readonly provide: <A, E>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, never>;
144
+ }
145
+ /** @internal */
146
+ interface PropApi<R> {
147
+ readonly prop: <const G extends Gens, S extends PropertySubject, N extends number>(name: string, spec: PropertySpec<G, S, N>, holds: (subject: S, values: Values<G>) => boolean) => void;
148
+ readonly effectProp: <const G extends Gens, S extends PropertySubject, N extends number, E>(name: string, spec: PropertySpec<G, S, N>, holds: (subject: S, values: Values<G>) => Effect.Effect<boolean, E, R>) => void;
149
+ readonly law: LawApi;
150
+ }
151
+ /**
152
+ * The property surface over one runtime: `prop`, `effectProp`, and the R13 law kinds routed through the gate.
153
+ *
154
+ * @internal
155
+ */
156
+ declare const makeProperty: <R>(runtime: PropertyRuntime<R>) => PropApi<R>;
157
+ //#endregion
158
+ export { Values as a, kinds_d_exports as c, PropertySubject as i, __exportAll as l, Gens as n, engine_d_exports as o, PropertySpec as r, LawApi as s, ArbitraryInput as t };