@systemfsoftware/vitest 1.0.0 → 4.1.1

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/failure.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
 
2
- import { a as Values, i as PropertySubject, l as Breach, n as Gens, o as engine_d_exports, r as PropertySpec } from "./engine-CMvYG5V0.js";
3
- import { i as Checks, t as Asserted } from "./checks-DiuzHhQM.js";
4
- import * as Cause from "effect/Cause";
2
+ import { A as VacuousProperty, M as Breach, _ as renderFailureRecord, a as PropertySubject, b as throwFailureRecord, d as AttributeValue, f as FailureRecord, g as TestIdentity, h as ReplayValue, i as PropertySpec, j as Witness, l as ProvidedCheckDefaults, m as JsonValue, n as Gens, o as Values, p as FailureRecordInput, r as PropApi, v as summaryOf, x as witnessOf, y as testIdentityOf } from "./engine-CYGdHvr8.js";
3
+ import { i as Checks, t as Asserted } from "./checks-BHOX6fGC.js";
5
4
  import * as Effect$1 from "effect/Effect";
6
5
  import * as Tracer from "effect/Tracer";
7
6
  import { Option, Schema } from "effect";
@@ -16,116 +15,6 @@ export declare const withRaisingFrame: {
16
15
  (frame: string | undefined): <A extends Error>(error: A) => A;
17
16
  };
18
17
  //#endregion
19
- //#region src/internal/failure-record.d.ts
20
- /** A value the renderer narrows rather than assumes. */
21
- type Opaque<A = unknown> = A;
22
- /**
23
- * A value a recorded span attribute or a replay path carries. Structured values stay structured on the span
24
- * (KTD2); the renderer decides the text.
25
- *
26
- * @internal
27
- */
28
- type AttributeValue = string | number | boolean | null | ReadonlyArray<AttributeValue> | {
29
- readonly [key: string]: AttributeValue;
30
- };
31
- /**
32
- * The test a failure happened in, as Vitest knows it. `file` is the path the rerun command names, so a caller
33
- * that holds an absolute path derives the repo-relative one before handing it over.
34
- *
35
- * @internal
36
- */
37
- interface TestIdentity {
38
- /**
39
- * The npm package the test file belongs to, e.g. `@systemfsoftware/effect-readiness`. Empty when the run
40
- * provided no name: the rerun command then drops its `pnpm --filter` prefix and runs from the package
41
- * directory, which is not a breach (R6).
42
- */
43
- readonly package: string;
44
- /** The test file, as the rerun command writes it. */
45
- readonly file: string;
46
- /** The scenario name the rerun command filters on with `-t`. */
47
- readonly name: string;
48
- }
49
- /**
50
- * The value a generator chose a run by: the kernel's seed and decision path, or a property counterexample's
51
- * seed and path. A path without a seed is a replay value offered for a baseline run, which R6 refuses (KTD5).
52
- *
53
- * @internal
54
- */
55
- interface ReplayValue {
56
- /** The generator's seed, or `undefined` when only a path was recorded. */
57
- readonly seed: number | undefined;
58
- /** The decisions the generator chose, in order; a decision is the index the scheduler picked (KTD5). */
59
- readonly path: ReadonlyArray<number>;
60
- }
61
- /**
62
- * A contract rule a rendered record breaks; the runner refuses such a record (R10, KTD7).
63
- *
64
- * @internal
65
- */
66
- /**
67
- * What a rendered failure gives Vitest: the tag the error carries, the record text, and the rules it breaks.
68
- *
69
- * @internal
70
- */
71
- interface FailureRecord {
72
- /** The headline's failure tag, e.g. `StepError`; the runner sets it as the thrown error's `name`. */
73
- readonly name: string;
74
- /** The text Vitest prints as the failure's message. */
75
- readonly record: string;
76
- /** The contract rules the record breaks: `R1` empty headline, `R2` no location, `R6` replay or rerun. */
77
- readonly breaches: ReadonlyArray<Breach>;
78
- }
79
- /**
80
- * Everything one failure is rendered from: the failure, its run's spans, the test and the replay value.
81
- *
82
- * @internal
83
- */
84
- interface FailureRecordInput<E = never> {
85
- /** The failure itself: a `Cause`, or the value a program threw or failed with. */
86
- readonly failure: Cause.Cause<E> | E;
87
- /** Every span the failing run recorded, in creation order. */
88
- readonly spans: ReadonlyArray<Tracer.NativeSpan>;
89
- /** The test the run belonged to. */
90
- readonly identity: TestIdentity;
91
- /** The generator that chose this run, or `undefined` on a run no generator chose. */
92
- readonly replay: ReplayValue | undefined;
93
- /**
94
- * The seed the kernel's scheduler chose. The kernel knows its own scheduler, so it hands the note over rather
95
- * than the renderer guessing it; a run no scheduler chose renders no note (KTD5).
96
- */
97
- readonly schedule?: {
98
- readonly seed: number;
99
- } | undefined;
100
- /**
101
- * The workspace root the rendered paths are relativized against, provided by the shared config the same way the
102
- * package name is. Omitted, paths print absolute.
103
- */
104
- readonly root?: string | undefined;
105
- }
106
- /** @internal */
107
- export declare const summaryOf: (value: Opaque) => string;
108
- /**
109
- * Renders the record Vitest prints for one spec failure, and the contract rules it breaks.
110
- *
111
- * Never throws: a `Cause` renders layer by layer, a thrown `Error` renders as one layer, and any other value
112
- * renders as itself. The first location the record names is the raising frame — the first stack frame outside
113
- * `node_modules` and outside the spec libraries' own `src/` and `dist/` — and when no layer has one, the
114
- * innermost failed span's site stands in, or the innermost unfinished cell's decide site for a deadlock (KTD6).
115
- *
116
- * @internal
117
- */
118
- export declare const renderFailureRecord: <E>(input: FailureRecordInput<E>) => FailureRecord;
119
- /** @internal */
120
- export declare const throwFailureRecord: <E>(input: FailureRecordInput<E>) => never;
121
- interface TaskLike {
122
- readonly name?: string | undefined;
123
- readonly fullName?: string | undefined;
124
- readonly fullTestName?: string | undefined;
125
- }
126
- /** @internal */
127
- export declare const testIdentityOf: (task?: TaskLike | null) => TestIdentity;
128
- //#endregion
129
18
  //#region src/internal/provided.schema.d.ts
130
19
  /**
131
20
  * The workspace root every rendered path is relativized against.
@@ -150,6 +39,10 @@ interface RecordedProperty<G extends Gens, S extends PropertySubject, N extends
150
39
  readonly name: string;
151
40
  readonly spec: PropertySpec<G, S, N>;
152
41
  readonly holds: (subject: S, values: Values<G>) => boolean;
42
+ /** The provided budget the run supplies in place of the configured default, e.g. a derandomizing `seed`. */
43
+ readonly budget?: ProvidedCheckDefaults | undefined;
44
+ /** The path of the test file whose seed store to read and write; absent, the run keeps no store. */
45
+ readonly store?: string | undefined;
153
46
  }
154
47
  /**
155
48
  * Runs one program as the runner runs a lane, with a fresh ledger and its own recorder, and resolves with the
@@ -158,6 +51,11 @@ interface RecordedProperty<G extends Gens, S extends PropertySubject, N extends
158
51
  * @internal
159
52
  */
160
53
  export declare const recordOfRun: <A, E>(program: RecordedRun<A, E>) => Promise<FailureRecord | undefined>;
54
+ /** @internal */
55
+ interface RecordedFile {
56
+ readonly records: ReadonlyArray<FailureRecord | undefined>;
57
+ readonly vacuous: VacuousProperty | undefined;
58
+ }
161
59
  /**
162
60
  * Runs one property the way the runner runs `it.prop`, with a fresh ledger and its own recorder, and resolves with
163
61
  * the record its falsification rendered — or `undefined` when it held.
@@ -165,6 +63,21 @@ export declare const recordOfRun: <A, E>(program: RecordedRun<A, E>) => Promise<
165
63
  * @internal
166
64
  */
167
65
  export declare const recordOfProperty: <const G extends Gens, S extends PropertySubject, N extends number>(input: RecordedProperty<G, S, N>) => Promise<FailureRecord | undefined>;
66
+ interface RecordedFileOptions {
67
+ readonly budget?: ProvidedCheckDefaults | undefined;
68
+ readonly store?: string | undefined;
69
+ }
70
+ /**
71
+ * Runs every property and law a file registers, in registration order, then finalises the file's one ledger:
72
+ * resolves with each property's rendered failure and the file's single vacuous verdict, or `undefined` when the
73
+ * file holds. The name a property is recorded under is the name it was registered with.
74
+ *
75
+ * @internal
76
+ */
77
+ export declare const recordOfFile: {
78
+ (register: (api: PropApi<never>) => void, options?: RecordedFileOptions): Promise<RecordedFile>;
79
+ (options?: RecordedFileOptions): (register: (api: PropApi<never>) => void) => Promise<RecordedFile>;
80
+ };
168
81
  //#endregion
169
82
  //#region src/internal/span-recorder.d.ts
170
83
  /** @internal */
@@ -191,8 +104,8 @@ export type Replay = typeof Replay.Type;
191
104
  */
192
105
  export declare const replayOfText: (text: string) => Replay;
193
106
  /**
194
- * The replay codec: `Schema.String` in, a replay out. A text that names no seed and path fails the decode, and
195
- * every replay encodes back to the text it was read from.
107
+ * The kernel's replay codec: `Schema.String` in, a replay out. A text that names no seed and path fails the decode,
108
+ * and every replay encodes back to the text it was read from.
196
109
  *
197
110
  * @since 4.0.0
198
111
  */
@@ -201,4 +114,4 @@ export declare const ReplayFromText: Schema.decodeTo<Schema.Struct<{
201
114
  readonly path: Schema.$Array<Schema.brand<Schema.Int, "ReplayStep">>;
202
115
  }>, Schema.String, never, never>;
203
116
  //#endregion
204
- export { type AttributeValue, type Breach, type FailureRecord, type FailureRecordInput, type RecordedProperty, type RecordedRun, type ReplayValue, type SpanRecorder, type TestIdentity, providedRoot as providedWorkspaceRoot };
117
+ export { type AttributeValue, type Breach, type FailureRecord, type FailureRecordInput, type JsonValue, type RecordedFile, type RecordedProperty, type RecordedRun, type ReplayValue, type SpanRecorder, type TestIdentity, type Witness, providedRoot as providedWorkspaceRoot, renderFailureRecord, summaryOf, testIdentityOf, throwFailureRecord, witnessOf };
package/dist/failure.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
 
2
- import { _ as ReplayFromText, c as summaryOf, d as providedRoot, g as Replay, l as testIdentityOf, n as recordOfRun, r as createSpanRecorder, s as renderFailureRecord, t as recordOfProperty, u as throwFailureRecord, v as replayOfText } from "./failure-D8mPXwf4.mjs";
3
- import { c as callFrameOutside, l as callSite, p as withRaisingFrame } from "./test-context-D_-acRSc.mjs";
4
- export { Replay, ReplayFromText, callFrameOutside, callSite, createSpanRecorder, providedRoot as providedWorkspaceRoot, recordOfProperty, recordOfRun, renderFailureRecord, replayOfText, summaryOf, testIdentityOf, throwFailureRecord, withRaisingFrame };
2
+ import { C as providedRoot, D as Replay, O as ReplayFromText, S as witnessOf, b as testIdentityOf, i as createSpanRecorder, k as replayOfText, n as recordOfProperty, r as recordOfRun, t as recordOfFile, v as renderFailureRecord, x as throwFailureRecord, y as summaryOf } from "./failure-C67X1OAe.mjs";
3
+ import { c as callFrameOutside, l as callSite, p as withRaisingFrame } from "./test-context-DelFkLBL.mjs";
4
+ export { Replay, ReplayFromText, callFrameOutside, callSite, createSpanRecorder, providedRoot as providedWorkspaceRoot, recordOfFile, recordOfProperty, recordOfRun, renderFailureRecord, replayOfText, summaryOf, testIdentityOf, throwFailureRecord, withRaisingFrame, witnessOf };
@@ -1,5 +1,6 @@
1
1
 
2
2
  import { chai } from "vitest";
3
+ import * as Predicate from "effect/Predicate";
3
4
  //#region src/internal/refusals.ts
4
5
  /**
5
6
  * Every refusal the fork prints, as the one text it uses on both channels: the `this` type (or parameter union)
@@ -108,9 +109,13 @@ const refuseRawIt = "✗ this test was registered with vitest's it; import it fr
108
109
  * `new Assertion(...)` on the same class (`chai/index.js:3367`, `:3394`).
109
110
  *
110
111
  * So this module wraps that prototype once, and every method, chainable method and property on it refuses
111
- * unless a check opened the window with {@link authorize} for the duration of its matcher call. Nothing
112
- * asynchronous may run inside that window, so a plain synchronous depth counter is enough; the counter is
113
- * nested-safe because chai's own matchers build further assertions inside the one call.
112
+ * unless a check opened the window with {@link authorize} for the duration of its matcher call. A matcher that
113
+ * returns a promise keeps its window open until that promise settles, so an async matcher such as
114
+ * `toMatchScreenshot` can build chai assertions after it awaits. Each call closes exactly the window it opened,
115
+ * so the depth counter stays nested-safe: chai's own matchers build further assertions inside the one call.
116
+ * The counter is global to the worker, not scoped to the test that opened it: while an async matcher is
117
+ * pending, a raw `expect` from a concurrently running test in the same worker is let through too. Once the
118
+ * promise settles the window closes and a raw `expect` is refused again.
114
119
  *
115
120
  * The window, the install flag and the wrapper marks live on `globalThis` under `Symbol.for` keys rather than
116
121
  * in module scope. A worker can hold two copies of this file at once — the setup file resolves through Node's
@@ -151,13 +156,20 @@ const authorized = () => state.depth > 0;
151
156
  const refuse = () => {
152
157
  throw refusalOf(refuseRawExpect);
153
158
  };
159
+ const close = () => {
160
+ state.depth -= 1;
161
+ };
162
+ const closeWhenSettled = (outcome) => Predicate.isPromiseLike(outcome) ? void Promise.resolve(outcome).then(close, close) : close();
154
163
  /** @internal */
155
164
  const authorize = (run) => {
156
165
  state.depth += 1;
157
166
  try {
158
- return run();
159
- } finally {
160
- state.depth -= 1;
167
+ const outcome = run();
168
+ closeWhenSettled(outcome);
169
+ return outcome;
170
+ } catch (failure) {
171
+ close();
172
+ throw failure;
161
173
  }
162
174
  };
163
175
  /** @internal */
package/dist/guard.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- import { h as refuseRawIt, n as installGuard, r as isMarked, u as refusalOf } from "./guard-BocOhXt2.mjs";
2
+ import { h as refuseRawIt, n as installGuard, r as isMarked, u as refusalOf } from "./guard-Ci0TyBYv.mjs";
3
3
  import { beforeEach } from "vitest";
4
4
  //#region src/guard.ts
5
5
  /**
@@ -14,6 +14,6 @@ import { beforeEach } from "vitest";
14
14
  installGuard();
15
15
  beforeEach((context) => {
16
16
  if (!isMarked(context.task)) throw refusalOf(refuseRawIt);
17
- });
17
+ }, 0);
18
18
  //#endregion
19
19
  export {};
package/dist/index.d.ts CHANGED
@@ -1,65 +1,17 @@
1
1
  /// <reference types="./compat.d.ts" />
2
- import { a as Values$1, c as kinds_d_exports, i as PropertySubject$1, n as Gens$1, o as engine_d_exports, r as PropertySpec$1, s as LawApi, t as ArbitraryInput, u as __exportAll } from "./engine-CMvYG5V0.js";
3
- import { a as Expect, c as NoCheckRefusal, d as RefuseSyncBody, f as ScopedLaneRefusal, i as Checks, l as RefuseAsyncBody, m as UnprovidedRefusal, o as EffectLaneRefusal, p as ScopedLiveLaneRefusal, r as Check, s as HookRefusal, t as Asserted, u as RefuseEffectBody } from "./checks-DiuzHhQM.js";
2
+ import { A as VacuousProperty, C as NonBooleanVerdict, D as ReplayUnreadable, E as ReplayNoLongerReproduces, O as SeedStoreUnreadable, S as CoverageBelowMinimum, T as PropertyRefuted, a as PropertySubject$1, c as PropertyBudget, i as PropertySpec$1, k as SelfModelLaw, l as ProvidedCheckDefaults, n as Gens$1, o as Values$1, s as LawApi, t as ArbitraryInput, u as checkDefaultsKey, w as PropertyExhausted } from "./engine-CYGdHvr8.js";
3
+ import { a as Expect, c as NoCheckRefusal, d as RefuseSyncBody, f as ScopedLaneRefusal, i as Checks, l as RefuseAsyncBody, m as UnprovidedRefusal, o as EffectLaneRefusal, p as ScopedLiveLaneRefusal, r as Check, s as HookRefusal, t as Asserted, u as RefuseEffectBody } from "./checks-BHOX6fGC.js";
4
4
  import * as V from "vitest";
5
5
  import { afterAll, assertType, beforeAll, expectTypeOf, inject, onTestFailed, onTestFinished, recordArtifact, vi, vitest } from "vitest";
6
6
  import * as Duration from "effect/Duration";
7
7
  import * as Effect from "effect/Effect";
8
8
  import * as Layer from "effect/Layer";
9
9
  import * as Scope from "effect/Scope";
10
- import * as TestConsole from "effect/testing/TestConsole";
10
+ import "effect/testing/TestConsole";
11
11
  import * as Context from "effect/Context";
12
- import * as Arbitrary from "effect/Arbitrary";
13
- import * as Clock from "effect/Clock";
14
- import * as Scheduler from "effect/Scheduler";
15
- //#region src/internal/property/defaults.d.ts
16
- /** @internal The `test.provide` key the shared config fills with this run's tier's check options. */
17
- declare const checkDefaultsKey = "@systemfsoftware/vitest:property-check";
18
- /** @internal The check options a run supplies as its property default, minus `replay`. */
19
- type ProvidedCheckDefaults = Omit<Arbitrary.CheckOptions, 'replay'>;
20
- //#endregion
21
- //#region src/internal/virtual-time.d.ts
22
- /** @internal */
23
- interface VirtualRuntime {
24
- readonly clock: Clock.Clock;
25
- readonly scheduler: Scheduler.Scheduler;
26
- /** @internal */
27
- readonly observe: Effect.Effect<void, never, never>;
28
- /** @internal */
29
- readonly end: Effect.Effect<void, never, never>;
30
- }
31
- declare namespace runner_d_exports {
32
- export { BlockRegistrar, LayerOptions$1 as LayerOptions, NestedLayer, RunEnv, addEqualityTesters$1 as addEqualityTesters, afterEach$1 as afterEach, beforeEach$2 as beforeEach, describeWrapped$1 as describeWrapped, flakyTest$1 as flakyTest, hookTimeout, law$1 as law, layer$1 as layer, makeMethods$1 as makeMethods, perRun, prop$1 as prop, realTime, testEnv, testOptions };
33
- }
34
- /** @internal */
35
- declare const addEqualityTesters$1: () => void;
36
- /** @internal */
37
- declare const testOptions: (timeout?: number | V.TestOptions) => V.TestOptions;
38
- /** @internal */
39
- declare const hookTimeout: (timeout?: Duration.Input) => number | undefined;
40
- /** @internal */
41
- interface RunEnv {
42
- readonly runtime: VirtualRuntime | undefined;
43
- readonly owned: boolean;
44
- }
45
- /** @internal */
46
- declare const realTime: RunEnv;
47
- /**
48
- * A run with its own virtual clock: the clock only ever advances when the run's fibers are idle.
49
- *
50
- * @internal
51
- */
52
- declare const perRun: () => RunEnv;
53
- /** @internal */
54
- declare const testEnv: (env: RunEnv) => Layer.Layer<TestConsole.TestConsole, never, never>;
55
- /** @internal */
56
- declare const prop$1: Vitest.SyncProperty;
57
- /**
58
- * The law kinds over the sync property family: the top-level `it.law`.
59
- *
60
- * @internal
61
- */
62
- declare const law$1: LawApi;
12
+ import "effect/Clock";
13
+ import "effect/Scheduler";
14
+ //#region src/internal/runner.d.ts
63
15
  /**
64
16
  * Options for the top-level `layer` and for `it.layer` inside a `Methods` block.
65
17
  *
@@ -94,11 +46,6 @@ type NestedLayer = {
94
46
  readonly shared?: boolean;
95
47
  };
96
48
  /** @internal */
97
- declare const layer$1: {
98
- <R, E>(layer_: Layer.Layer<R, E>, options?: LayerOptions$1): BlockRegistrar<R>;
99
- <R, E>(options?: LayerOptions$1): (layer_: Layer.Layer<R, E>) => BlockRegistrar<R>;
100
- };
101
- /** @internal */
102
49
  declare const flakyTest$1: {
103
50
  <A, E, R>(self: Effect.Effect<A, E, R | Scope.Scope>, timeout?: Duration.Input): Effect.Effect<A, never, R>;
104
51
  (timeout?: Duration.Input): <A, E, R>(self: Effect.Effect<A, E, R | Scope.Scope>) => Effect.Effect<A, never, R>;
@@ -119,21 +66,8 @@ declare const afterEach$1: {
119
66
  (this: HookRefusal, fn: AfterEachFirst, timeout?: number): never;
120
67
  (this: HookRefusal, timeout?: number): (fn: AfterEachFirst) => never;
121
68
  };
122
- /**
123
- * The fork's `it`: the generator lanes on virtual time, the real-clock lane, the lawful property lanes and the
124
- * layer blocks, callable data-first (`it(name, body)`) or data-last (`it(body, timeout?)(name)`).
125
- *
126
- * @internal
127
- */
128
- declare const makeMethods$1: (it: V.TestAPI) => Vitest.Methods;
129
- /** @internal */
130
- declare const describeWrapped$1: {
131
- (name: string, f: (it: Vitest.Methods) => void): V.SuiteCollector;
132
- (f: (it: Vitest.Methods) => void): (name: string) => V.SuiteCollector;
133
- };
134
- declare namespace mod_d_exports {
135
- export { Asserted, Check, Checks, Expect, Gate, Vitest, VitestTestContext, addEqualityTesters, afterAll, afterEach, assertType, beforeAll, beforeEach, describe, describeWrapped, expectTypeOf, flakyTest, inject, it, law, layer, makeMethods, onTestFailed, onTestFinished, prop, recordArtifact, test, vi, vitest, vitestTestContextKey };
136
- }
69
+ //#endregion
70
+ //#region src/mod.d.ts
137
71
  declare module 'vitest' {
138
72
  interface ProvidedContext {
139
73
  [checkDefaultsKey]?: ProvidedCheckDefaults;
@@ -209,6 +143,15 @@ export declare namespace Vitest {
209
143
  * @since 4.0.0
210
144
  */
211
145
  type BodyRefusal = RefuseSyncBody | RefuseAsyncBody | RefuseEffectBody;
146
+ /**
147
+ * A registration's options: Vitest's own, plus `rerun` — the body the leak-check second run runs in place of
148
+ * the registered one. Without it, a clean first run is followed by a second run of the registered body.
149
+ *
150
+ * @since 4.0.0
151
+ */
152
+ interface TestOptions<Eff, AEff> extends V.TestOptions {
153
+ readonly rerun?: Body<Eff, AEff>;
154
+ }
212
155
  /**
213
156
  * A test lane: `it(name, function* ({ expect }) { ... })`. `R` is what the lane's own environment provides
214
157
  * besides the checks — its scope, and the services of the `layer` block it is written in.
@@ -216,8 +159,8 @@ export declare namespace Vitest {
216
159
  * @since 4.0.0
217
160
  */
218
161
  interface Test<R> {
219
- <Eff, AEff>(name: NoInfer<Gate<RequirementOf<Eff>, Lane<R>>>, body: Body<Eff, AEff> | BodyRefusal, timeout?: number | V.TestOptions): void;
220
- <Eff, AEff>(body: Body<Eff, AEff> | BodyRefusal, timeout?: number | V.TestOptions): (name: NoInfer<Gate<RequirementOf<Eff>, Lane<R>>>) => void;
162
+ <Eff, AEff>(name: NoInfer<Gate<RequirementOf<Eff>, Lane<R>>>, body: Body<Eff, AEff> | BodyRefusal, timeout?: number | TestOptions<Eff, AEff>): void;
163
+ <Eff, AEff>(body: Body<Eff, AEff> | BodyRefusal, timeout?: number | TestOptions<Eff, AEff>): (name: NoInfer<Gate<RequirementOf<Eff>, Lane<R>>>) => void;
221
164
  }
222
165
  /**
223
166
  * A row lane: `it.each(rows)(name, function* (row, { expect }) { ... })`.
@@ -495,4 +438,4 @@ export declare const VitestTestContext: Context.Reference<V.TestContext | null>;
495
438
  */
496
439
  export type Gate<R, Provided = never> = Vitest.Gate<R, Provided>;
497
440
  //#endregion
498
- export { type Asserted, type Check, type Checks, type Expect, afterAll, assertType, beforeAll, expectTypeOf, inject, onTestFailed, onTestFinished, recordArtifact, vi, vitest };
441
+ export { type Asserted, type Check, type Checks, CoverageBelowMinimum, type Expect, NonBooleanVerdict, type PropertyBudget, PropertyExhausted, PropertyRefuted, ReplayNoLongerReproduces, ReplayUnreadable, SeedStoreUnreadable, SelfModelLaw, VacuousProperty, afterAll, assertType, beforeAll, expectTypeOf, inject, onTestFailed, onTestFinished, recordArtifact, vi, vitest };
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
- import { a as replayOfFailure, d as providedRoot, f as InvalidBudget, h as Slop, i as makeProperty, l as testIdentityOf, m as NonBooleanVerdict, o as isFailureRecordError, p as LeakedState, r as createSpanRecorder, u as throwFailureRecord } from "./failure-D8mPXwf4.mjs";
3
- import { a as isCheck, i as checksFor, n as vitestTestContextKey$1, o as makeLedger, r as Asserted, t as VitestTestContext$1 } from "./test-context-D_-acRSc.mjs";
4
- import { _ as refuseScopedLiveLane, d as refuseAsyncBody, f as refuseEffectLane, g as refuseScopedLane, i as markTask, l as noCheckRefusal, o as isRefusal$1, p as refuseHook, u as refusalOf$1, v as refuseSyncBody, x as unprovidedText, y as refuseUnyielded } from "./guard-BocOhXt2.mjs";
2
+ import { A as providedCheckDefaults, C as providedRoot, E as Slop, T as LeakedState, _ as isFailureRecordError, a as makeProperty, b as testIdentityOf, c as NonBooleanVerdict, d as ReplayNoLongerReproduces, f as ReplayUnreadable, g as drive, h as VacuousProperty, i as createSpanRecorder, l as PropertyExhausted, m as SelfModelLaw, o as makeFileLedger, p as SeedStoreUnreadable, s as CoverageBelowMinimum, u as PropertyRefuted, w as InvalidBudget, x as throwFailureRecord } from "./failure-C67X1OAe.mjs";
3
+ import { i as checksFor, n as vitestTestContextKey$1, o as makeLedger, t as VitestTestContext$1 } from "./test-context-DelFkLBL.mjs";
4
+ import { _ as refuseScopedLiveLane, d as refuseAsyncBody, f as refuseEffectLane, g as refuseScopedLane, i as markTask, o as isRefusal$1, p as refuseHook, u as refusalOf$1, v as refuseSyncBody, x as unprovidedText } from "./guard-Ci0TyBYv.mjs";
5
5
  import * as V from "vitest";
6
6
  import { afterAll, assertType, beforeAll, expectTypeOf, inject, onTestFailed, onTestFinished, recordArtifact, vi, vitest } from "vitest";
7
7
  import * as Cause from "effect/Cause";
@@ -18,72 +18,6 @@ import * as TestClock from "effect/testing/TestClock";
18
18
  import * as TestConsole from "effect/testing/TestConsole";
19
19
  import * as Clock from "effect/Clock";
20
20
  import * as Scheduler from "effect/Scheduler";
21
- //#region src/internal/driver.ts
22
- /**
23
- * The driver: one Effect that steps the body's generator in the fiber the test runs in.
24
- *
25
- * A `yield*` is a step, so the runner sees every one of them (KTD1):
26
- * - a branded check is judged against this test's ledger, so it counts, and a failed judgement fails the check
27
- * itself and stops the test right there (R8);
28
- * - anything else opens a new observed state and then runs, which is what makes a second check on one state a
29
- * second check in one window (R5), and a check inside a loop the same window as its siblings.
30
- *
31
- * The steps run in the same fiber as the test, so layers, virtual time, concurrency, the second run and scope
32
- * finalizers keep working through the runner unchanged. A step that fails, and the test being interrupted, both
33
- * return the generator: its `finally` blocks run and the steps after it never start (R8). When the body returns,
34
- * the gate refuses what the body wrote and never judged, then a body that judged nothing at all (R4).
35
- */
36
- /**
37
- * A value the body yielded, as the driver runs it. What a body needs of its environment belongs to the layer the
38
- * runner provides around this whole Effect, so the driver erases the channels here, exactly as the runner erases
39
- * a body's own (`outputIsEffect` in `runner.ts`): the layer block is where a requirement is checked, and a body
40
- * that needs a service nothing provides is refused by the runner at run time (R9).
41
- */
42
- const isRunnable = (value) => Effect.isEffect(value);
43
- /** A body that yielded something the driver cannot run ran nothing, so nothing in the test could fail. */
44
- const refuseUnsteppable = "✗ the body yielded a value that is not an Effect. Yield the Effect itself, or a check: yield* expect(actual).toEqual(expected).";
45
- /**
46
- * A yielded Effect: a branded check judges itself, and anything else opens a new observed state before it runs,
47
- * which is what resets the ledger's one-check window (R5).
48
- */
49
- const runEffect = (value, ledger) => isCheck(value) ? value : Effect.andThen(Effect.sync(() => ledger.asserted.step()), value);
50
- /** One step: anything the driver cannot run is refused, because then no step of the test ran at all. */
51
- const runStep = (value, ledger) => isRunnable(value) ? runEffect(value, ledger) : Effect.die(refusalOf$1(refuseUnsteppable));
52
- /** Steps the iterator to its end, feeding each yielded Effect's result back into the body. */
53
- const stepThrough = (steps, ledger, input) => Effect.suspend(() => {
54
- const state = steps.next(input);
55
- if (state.done === true) return Effect.void;
56
- return Effect.flatMap(runStep(state.value, ledger), (value) => stepThrough(steps, ledger, value));
57
- });
58
- /**
59
- * After the body returns: a check written and never yielded is refused first, then a body that judged none.
60
- * Both carry the same text the refusal carries on its compile channel, branded by `refusalOf` so the runner's
61
- * second run re-throws them as the refusals they are.
62
- */
63
- const gate = (ledger) => Effect.suspend(() => ledger.unyielded() > 0 ? refuse(refuseUnyielded) : judgedNone(ledger));
64
- const judgedNone = (ledger) => ledger.judged() === 0 ? refuse(noCheckRefusal) : Effect.void;
65
- const refuse = (text) => Effect.die(refusalOf$1(text));
66
- /**
67
- * A failure or an interruption returns the generator, so its `finally` blocks run and the step after the failed
68
- * check never does (R8).
69
- */
70
- const unwind = (steps) => Effect.sync(() => {
71
- steps.return?.(void 0);
72
- });
73
- const driveBody = (body, args, ledger) => Effect.suspend(() => {
74
- const steps = body(...args);
75
- return Effect.onExit(Effect.flatMap(stepThrough(steps, ledger, void 0), () => gate(ledger)), (exit) => Exit.isSuccess(exit) ? Effect.void : unwind(steps));
76
- });
77
- /** The body's steps, with this test's ledger provided as the `Asserted` every check in it reaches for. */
78
- const driven = (body, args, ledger) => Effect.provideService(driveBody(body, args, ledger), Asserted, ledger.asserted);
79
- /**
80
- * Runs one test's body: `body` called with `args`, stepped against `ledger`, with the ledger's `asserted`
81
- * provided as `Asserted` so every check in the body — including one yielded inside a forked fiber — reaches it.
82
- *
83
- * @internal
84
- */
85
- const drive = Function.dual(3, driven);
86
- //#endregion
87
21
  //#region src/internal/virtual-time.ts
88
22
  const roundNanos = (millis) => BigInt(Math.round(millis * 1e6));
89
23
  const byWakeOrder = (first, second) => {
@@ -285,8 +219,15 @@ const numbered = (timeout) => ({ timeout });
285
219
  const givenOptions = (timeout) => timeout ?? {};
286
220
  /** @internal */
287
221
  const testOptions = (timeout) => typeof timeout === "number" ? numbered(timeout) : givenOptions(timeout);
222
+ /** Vitest's own options from a registration's: the fork's `rerun` body never reaches Vitest's registrar. */
223
+ const vitestOptionsOf = (given) => {
224
+ const { rerun: _rerun, ...options } = given;
225
+ return options;
226
+ };
227
+ const registrationOptions = (timeout) => typeof timeout === "object" ? vitestOptionsOf(timeout) : testOptions(timeout);
288
228
  /** @internal */
289
229
  const hookTimeout = (timeout) => timeout === void 0 ? void 0 : Duration.toMillis(Duration.fromInputUnsafe(timeout));
230
+ const rerunOf = (timeout) => typeof timeout === "object" ? timeout.rerun : void 0;
290
231
  const isName = (first) => typeof first === "string";
291
232
  const byName = (args) => isName(args[0]);
292
233
  const byLayer = (args) => Layer.isLayer(args[0]);
@@ -374,7 +315,7 @@ const throwRecorded = (cause, recorder, ctx) => {
374
315
  failure,
375
316
  spans: recorder.spans,
376
317
  identity: testIdentityOf(ctx.task),
377
- replay: replayOfFailure(failure),
318
+ replay: void 0,
378
319
  root: providedRoot()
379
320
  });
380
321
  };
@@ -426,6 +367,10 @@ const stepsOfRow = (row, body, checks) => isGeneratorBody(body) ? asSteps(body(r
426
367
  const bodyOf = (ledger, body) => () => asSteps(body(checksFor(ledger)));
427
368
  /** The body a lane registered, closed over its checks: the generator itself, or the refusal for what it is not. */
428
369
  const laneBodyOf = (body) => (checks) => typeof body === "string" ? refuseBody(refuseSyncBody) : stepsOfBody(body, checks);
370
+ const rerunBodyOf = (timeout, registered) => {
371
+ const rerun = rerunOf(timeout);
372
+ return rerun === void 0 ? registered : laneBodyOf(rerun);
373
+ };
429
374
  /** The row body a lane registered: Vitest's `it.for` order is the row first, then the checks (R9). */
430
375
  const rowBodyOf = (row, body) => (checks) => typeof body === "string" ? refuseBody(refuseSyncBody) : stepsOfRow(row, body, checks);
431
376
  /** One test's run: a fresh ledger, and the lane's own services around the program the driver built. */
@@ -462,14 +407,26 @@ const NO_ERRORS = [];
462
407
  const presentErrors = (errors) => errors === void 0 ? NO_ERRORS : errors;
463
408
  /** Whether a run left no failure behind: only a clean first run is worth running a second time. */
464
409
  const isClean = (ctx) => presentErrors(ctx.task.result?.errors).length === 0;
410
+ const propertyTaskOf = (ctx) => ({
411
+ identity: testIdentityOf(ctx.task),
412
+ filepath: ctx.task.file.filepath,
413
+ budget: providedCheckDefaults()
414
+ });
465
415
  /**
466
416
  * Runs a property's program as the test that registered it, under the same context the generator lanes use. The
467
417
  * env is the bare `propertyEnv`: a `false` verdict is the property's own shrink path, so nothing interrupts it.
468
418
  */
469
- const runProperty = (ctx, program) => runRecorded(bindRun(Effect.suspend(program), ctx), ctx, propertyEnv);
419
+ const runProperty = (ctx, program) => runRecorded(bindRun(Effect.suspend(() => program(propertyTaskOf(ctx))), ctx), ctx, propertyEnv);
420
+ /** The sync and effect property lanes of one test file share this ledger; it is judged once, at file end (R20). */
421
+ const propertyLedger = makeFileLedger();
422
+ V.afterAll(() => {
423
+ const refused = propertyLedger.finalise();
424
+ if (refused !== void 0) throw new VacuousProperty(refused);
425
+ }, 0);
470
426
  const property = makeProperty({
471
427
  register: (name, program) => marked(() => V.it(name, (ctx) => runProperty(ctx, program))),
472
- provide: (effect) => effect
428
+ provide: (effect) => effect,
429
+ ledger: propertyLedger
473
430
  });
474
431
  const propImpl = (name, spec, holds) => {
475
432
  refusePositional(spec);
@@ -575,7 +532,7 @@ const freshBlock = (layer_, options) => {
575
532
  excludeTestServices
576
533
  }, void 0);
577
534
  const nestedLayer = Function.dual(byLayer, nestedOpen);
578
- const makeIt = (it) => methodsFor((effect, env) => effect.pipe(Effect.scoped, (scoped) => Effect.provide(scoped, Layer.orDie(Layer.fresh(withTestEnv(env))))), it, perRun, true, nestedLayer);
535
+ const makeIt = (it) => methodsFor((effect, env) => effect.pipe(Effect.scoped, (scoped) => Effect.provide(scoped, withTestEnv(env).pipe(Layer.fresh, Layer.orDie))), it, perRun, true, nestedLayer);
579
536
  return blockOpener((f) => f(makeIt(V.it)), (name, f) => {
580
537
  V.describe(name, describeOptions(options, false), () => f(makeIt(V.it)));
581
538
  });
@@ -656,13 +613,14 @@ const makeTesterWith = (mapEffect, it, envFor, rerunnable) => {
656
613
  const rerun = (ctx, body) => outcomeOf(runOnce(ctx, body)).then(leakedOrNothing);
657
614
  const shouldRerun = (ctx) => rerunnable && isClean(ctx);
658
615
  const rerunIfClean = (ctx, body) => shouldRerun(ctx) ? rerun(ctx, body) : Promise.resolve();
659
- const run = (ctx, body) => outcomeOf(runOnce(ctx, body)).then((error) => {
616
+ const run = (ctx, body, second) => outcomeOf(runOnce(ctx, body)).then((error) => {
660
617
  if (error !== void 0) throw error;
661
- return rerunIfClean(ctx, body);
618
+ return rerunIfClean(ctx, second);
662
619
  });
663
620
  const registering = (registrar) => (name, body, timeout) => {
664
621
  const lane = laneBodyOf(body);
665
- marked(() => registrar(name, testOptions(timeout), (ctx) => run(ctx, lane)));
622
+ const second = rerunBodyOf(timeout, lane);
623
+ marked(() => registrar(name, registrationOptions(timeout), (ctx) => run(ctx, lane, second)));
666
624
  };
667
625
  const dualLane = (registrar) => Function.dual(byName, registering(registrar));
668
626
  const base = dualLane(it);
@@ -672,11 +630,15 @@ const makeTesterWith = (mapEffect, it, envFor, rerunnable) => {
672
630
  const only = dualLane(it.only);
673
631
  const fails = dualLane(it.fails);
674
632
  const each = (cases) => (name, body, timeout) => {
675
- marked(() => it.for(cases)(name, testOptions(timeout), (row, ctx) => run(ctx, rowBodyOf(row, body))));
633
+ marked(() => it.for(cases)(name, testOptions(timeout), (row, ctx) => {
634
+ const lane = rowBodyOf(row, body);
635
+ return run(ctx, lane, lane);
636
+ }));
676
637
  };
677
638
  const effectProperty = makeProperty({
678
639
  register: (name, program) => marked(() => it(name, (ctx) => runProperty(ctx, program))),
679
- provide: (effect) => mapEffect(effect, envFor())
640
+ provide: (effect) => mapEffect(effect, envFor()),
641
+ ledger: propertyLedger
680
642
  });
681
643
  const prop = (name, spec, holds) => {
682
644
  refusePositional(spec);
@@ -838,4 +800,4 @@ const vitestTestContextKey = vitestTestContextKey$1;
838
800
  */
839
801
  const VitestTestContext = VitestTestContext$1;
840
802
  //#endregion
841
- export { VitestTestContext, addEqualityTesters, afterAll, afterEach, assertType, beforeAll, beforeEach, describe, describeWrapped, expectTypeOf, flakyTest, inject, it, law, layer, makeMethods, onTestFailed, onTestFinished, prop, recordArtifact, test, vi, vitest, vitestTestContextKey };
803
+ export { CoverageBelowMinimum, NonBooleanVerdict, PropertyExhausted, PropertyRefuted, ReplayNoLongerReproduces, ReplayUnreadable, SeedStoreUnreadable, SelfModelLaw, VacuousProperty, VitestTestContext, addEqualityTesters, afterAll, afterEach, assertType, beforeAll, beforeEach, describe, describeWrapped, expectTypeOf, flakyTest, inject, it, law, layer, makeMethods, onTestFailed, onTestFinished, prop, recordArtifact, test, vi, vitest, vitestTestContextKey };
@@ -1,5 +1,5 @@
1
1
 
2
- import { a as Expect, n as AssertedShape, r as Check, t as Asserted } from "./checks-DiuzHhQM.js";
2
+ import { a as Expect, n as AssertedShape, r as Check, t as Asserted } from "./checks-BHOX6fGC.js";
3
3
  import * as Effect from "effect/Effect";
4
4
  //#region src/integration.d.ts
5
5
  /**
@@ -1,5 +1,5 @@
1
1
 
2
- import { r as Asserted, t as VitestTestContext } from "./test-context-D_-acRSc.mjs";
2
+ import { r as Asserted, t as VitestTestContext } from "./test-context-DelFkLBL.mjs";
3
3
  import * as Effect from "effect/Effect";
4
4
  import * as Option from "effect/Option";
5
5
  //#region src/integration.ts
@@ -0,0 +1,11 @@
1
+
2
+ import * as Arbitrary from "effect/Arbitrary";
3
+ //#region src/internal/property/tiers.d.ts
4
+ type Env = Readonly<Record<string, string | undefined>>;
5
+ /**
6
+ * @internal The check options direct `Arbitrary` checks use by default: `{ check: { runs } }` for the tier. A property
7
+ * test that passes its own `runs` still wins over this default.
8
+ */
9
+ export declare const propertyTestDefaults: (env: Env) => Arbitrary.GlobalOptions;
10
+ //#endregion
11
+ export {};
@@ -0,0 +1,15 @@
1
+
2
+ import { t as propertyTestDefaults } from "./tiers-W0BWq1uh.mjs";
3
+ import * as Arbitrary from "effect/Arbitrary";
4
+ //#region src/property-defaults.ts
5
+ /**
6
+ * The setup file that sets the run count of direct `Arbitrary` checks from the environment, published as
7
+ * `@systemfsoftware/vitest/property-defaults` and listed beside the guard in the shared Vitest config's `setupFiles`.
8
+ * The table it reads is `propertyTestDefaults`, re-exported here so a test can supply its own environment record.
9
+ *
10
+ * @since 4.1.0
11
+ */
12
+ const processEnvironment = () => ({ ...typeof process === "undefined" ? void 0 : process.env });
13
+ Arbitrary.configureGlobal(propertyTestDefaults(processEnvironment()));
14
+ //#endregion
15
+ export { propertyTestDefaults };