@systemfsoftware/vitest 2.0.0 → 4.1.2

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/index.d.ts CHANGED
@@ -1,58 +1,17 @@
1
1
  /// <reference types="./compat.d.ts" />
2
- import { A as VacuousProperty, D as ReplayUnreadable, E as PropertyRefuted, N as __exportAll, O as SeedStoreUnreadable, T as NonBooleanVerdict, a as PropertySubject$1, c as LawApi, d as ProvidedCheckDefaults, f as checkDefaultsKey, i as PropertySpec$1, k as SelfModelLaw, l as kinds_d_exports, n as Gens$1, o as Values$1, s as engine_d_exports, t as ArbitraryInput, u as PropertyBudget, w as CoverageBelowMinimum } from "./engine-D7Q6-BxD.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 Clock from "effect/Clock";
13
- import * as Scheduler from "effect/Scheduler";
14
- //#region src/internal/virtual-time.d.ts
15
- /** @internal */
16
- interface VirtualRuntime {
17
- readonly clock: Clock.Clock;
18
- readonly scheduler: Scheduler.Scheduler;
19
- /** @internal */
20
- readonly observe: Effect.Effect<void, never, never>;
21
- /** @internal */
22
- readonly end: Effect.Effect<void, never, never>;
23
- }
24
- declare namespace runner_d_exports {
25
- 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 };
26
- }
27
- /** @internal */
28
- declare const addEqualityTesters$1: () => void;
29
- /** @internal */
30
- declare const testOptions: (timeout?: number | V.TestOptions) => V.TestOptions;
31
- /** @internal */
32
- declare const hookTimeout: (timeout?: Duration.Input) => number | undefined;
33
- /** @internal */
34
- interface RunEnv {
35
- readonly runtime: VirtualRuntime | undefined;
36
- readonly owned: boolean;
37
- }
38
- /** @internal */
39
- declare const realTime: RunEnv;
40
- /**
41
- * A run with its own virtual clock: the clock only ever advances when the run's fibers are idle.
42
- *
43
- * @internal
44
- */
45
- declare const perRun: () => RunEnv;
46
- /** @internal */
47
- declare const testEnv: (env: RunEnv) => Layer.Layer<TestConsole.TestConsole, never, never>;
48
- /** @internal */
49
- declare const prop$1: Vitest.SyncProperty;
50
- /**
51
- * The law kinds over the sync property family: the top-level `it.law`.
52
- *
53
- * @internal
54
- */
55
- declare const law$1: LawApi;
12
+ import "effect/Clock";
13
+ import "effect/Scheduler";
14
+ //#region src/internal/runner.d.ts
56
15
  /**
57
16
  * Options for the top-level `layer` and for `it.layer` inside a `Methods` block.
58
17
  *
@@ -87,11 +46,6 @@ type NestedLayer = {
87
46
  readonly shared?: boolean;
88
47
  };
89
48
  /** @internal */
90
- declare const layer$1: {
91
- <R, E>(layer_: Layer.Layer<R, E>, options?: LayerOptions$1): BlockRegistrar<R>;
92
- <R, E>(options?: LayerOptions$1): (layer_: Layer.Layer<R, E>) => BlockRegistrar<R>;
93
- };
94
- /** @internal */
95
49
  declare const flakyTest$1: {
96
50
  <A, E, R>(self: Effect.Effect<A, E, R | Scope.Scope>, timeout?: Duration.Input): Effect.Effect<A, never, R>;
97
51
  (timeout?: Duration.Input): <A, E, R>(self: Effect.Effect<A, E, R | Scope.Scope>) => Effect.Effect<A, never, R>;
@@ -112,21 +66,8 @@ declare const afterEach$1: {
112
66
  (this: HookRefusal, fn: AfterEachFirst, timeout?: number): never;
113
67
  (this: HookRefusal, timeout?: number): (fn: AfterEachFirst) => never;
114
68
  };
115
- /**
116
- * The fork's `it`: the generator lanes on virtual time, the real-clock lane, the lawful property lanes and the
117
- * layer blocks, callable data-first (`it(name, body)`) or data-last (`it(body, timeout?)(name)`).
118
- *
119
- * @internal
120
- */
121
- declare const makeMethods$1: (it: V.TestAPI) => Vitest.Methods;
122
- /** @internal */
123
- declare const describeWrapped$1: {
124
- (name: string, f: (it: Vitest.Methods) => void): V.SuiteCollector;
125
- (f: (it: Vitest.Methods) => void): (name: string) => V.SuiteCollector;
126
- };
127
- declare namespace mod_d_exports {
128
- export { Asserted, Check, Checks, CoverageBelowMinimum, Expect, Gate, NonBooleanVerdict, PropertyBudget, PropertyRefuted, ReplayUnreadable, SeedStoreUnreadable, SelfModelLaw, VacuousProperty, 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 };
129
- }
69
+ //#endregion
70
+ //#region src/mod.d.ts
130
71
  declare module 'vitest' {
131
72
  interface ProvidedContext {
132
73
  [checkDefaultsKey]?: ProvidedCheckDefaults;
@@ -202,6 +143,15 @@ export declare namespace Vitest {
202
143
  * @since 4.0.0
203
144
  */
204
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
+ }
205
155
  /**
206
156
  * A test lane: `it(name, function* ({ expect }) { ... })`. `R` is what the lane's own environment provides
207
157
  * besides the checks — its scope, and the services of the `layer` block it is written in.
@@ -209,8 +159,8 @@ export declare namespace Vitest {
209
159
  * @since 4.0.0
210
160
  */
211
161
  interface Test<R> {
212
- <Eff, AEff>(name: NoInfer<Gate<RequirementOf<Eff>, Lane<R>>>, body: Body<Eff, AEff> | BodyRefusal, timeout?: number | V.TestOptions): void;
213
- <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;
214
164
  }
215
165
  /**
216
166
  * A row lane: `it.each(rows)(name, function* (row, { expect }) { ... })`.
@@ -488,4 +438,4 @@ export declare const VitestTestContext: Context.Reference<V.TestContext | null>;
488
438
  */
489
439
  export type Gate<R, Provided = never> = Vitest.Gate<R, Provided>;
490
440
  //#endregion
491
- export { type Asserted, type Check, type Checks, CoverageBelowMinimum, type Expect, NonBooleanVerdict, type PropertyBudget, PropertyRefuted, ReplayUnreadable, SeedStoreUnreadable, SelfModelLaw, VacuousProperty, 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 { C as Slop, D as providedCheckDefaults, S as LeakedState, _ as testIdentityOf, a as makeProperty, b as providedRoot, c as NonBooleanVerdict, d as SeedStoreUnreadable, f as SelfModelLaw, i as createSpanRecorder, l as PropertyRefuted, m as isFailureRecordError, o as makeFileLedger, p as VacuousProperty, s as CoverageBelowMinimum, u as ReplayUnreadable, v as throwFailureRecord, x as InvalidBudget } from "./failure-nvq5TwWX.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-B094O43o.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]);
@@ -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. */
@@ -477,7 +422,7 @@ const propertyLedger = makeFileLedger();
477
422
  V.afterAll(() => {
478
423
  const refused = propertyLedger.finalise();
479
424
  if (refused !== void 0) throw new VacuousProperty(refused);
480
- });
425
+ }, 0);
481
426
  const property = makeProperty({
482
427
  register: (name, program) => marked(() => V.it(name, (ctx) => runProperty(ctx, program))),
483
428
  provide: (effect) => effect,
@@ -587,7 +532,7 @@ const freshBlock = (layer_, options) => {
587
532
  excludeTestServices
588
533
  }, void 0);
589
534
  const nestedLayer = Function.dual(byLayer, nestedOpen);
590
- 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);
591
536
  return blockOpener((f) => f(makeIt(V.it)), (name, f) => {
592
537
  V.describe(name, describeOptions(options, false), () => f(makeIt(V.it)));
593
538
  });
@@ -668,13 +613,14 @@ const makeTesterWith = (mapEffect, it, envFor, rerunnable) => {
668
613
  const rerun = (ctx, body) => outcomeOf(runOnce(ctx, body)).then(leakedOrNothing);
669
614
  const shouldRerun = (ctx) => rerunnable && isClean(ctx);
670
615
  const rerunIfClean = (ctx, body) => shouldRerun(ctx) ? rerun(ctx, body) : Promise.resolve();
671
- const run = (ctx, body) => outcomeOf(runOnce(ctx, body)).then((error) => {
616
+ const run = (ctx, body, second) => outcomeOf(runOnce(ctx, body)).then((error) => {
672
617
  if (error !== void 0) throw error;
673
- return rerunIfClean(ctx, body);
618
+ return rerunIfClean(ctx, second);
674
619
  });
675
620
  const registering = (registrar) => (name, body, timeout) => {
676
621
  const lane = laneBodyOf(body);
677
- 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)));
678
624
  };
679
625
  const dualLane = (registrar) => Function.dual(byName, registering(registrar));
680
626
  const base = dualLane(it);
@@ -684,7 +630,10 @@ const makeTesterWith = (mapEffect, it, envFor, rerunnable) => {
684
630
  const only = dualLane(it.only);
685
631
  const fails = dualLane(it.fails);
686
632
  const each = (cases) => (name, body, timeout) => {
687
- 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
+ }));
688
637
  };
689
638
  const effectProperty = makeProperty({
690
639
  register: (name, program) => marked(() => it(name, (ctx) => runProperty(ctx, program))),
@@ -851,4 +800,4 @@ const vitestTestContextKey = vitestTestContextKey$1;
851
800
  */
852
801
  const VitestTestContext = VitestTestContext$1;
853
802
  //#endregion
854
- export { CoverageBelowMinimum, NonBooleanVerdict, PropertyRefuted, 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 };
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 };
@@ -1,11 +1,12 @@
1
1
 
2
- import { a as booleanRefusal, b as refusedText, c as negatedText, m as refusePiecewise, s as neededText, t as authorize, u as refusalOf } from "./guard-BocOhXt2.mjs";
2
+ import { a as booleanRefusal, b as refusedText, c as negatedText, m as refusePiecewise, s as neededText, t as authorize, u as refusalOf } from "./guard-Ci0TyBYv.mjs";
3
3
  import * as V from "vitest";
4
4
  import * as Effect from "effect/Effect";
5
5
  import * as Function from "effect/Function";
6
6
  import * as Schema from "effect/Schema";
7
7
  import * as Option from "effect/Option";
8
8
  import * as Context from "effect/Context";
9
+ import * as Predicate from "effect/Predicate";
9
10
  //#region src/internal/call-site.ts
10
11
  /**
11
12
  * The one rule that reads a frame out of a stack: which frame a failure is raised from, and which frame an author
@@ -126,10 +127,12 @@ const branded = /* @__PURE__ */ new WeakSet();
126
127
  const isObject = (value) => typeof value === "object" && value !== null;
127
128
  /** @internal */
128
129
  const isCheck = (value) => isObject(value) && branded.has(value);
130
+ const settled = (outcome) => Predicate.isPromiseLike(outcome) ? Effect.asVoid(Effect.promise(() => outcome)) : Effect.void;
129
131
  const makeCheck = (judgement, written) => {
130
132
  written(judgement);
131
133
  const check = Effect.gen(function* () {
132
- (yield* Asserted).judge(judgement);
134
+ const asserted = yield* Asserted;
135
+ yield* settled(asserted.judge(judgement));
133
136
  });
134
137
  branded.add(check);
135
138
  return check;
@@ -176,21 +179,22 @@ const memberAt = (target, property) => Reflect.get(target, property, target);
176
179
  const isCallable = (value) => typeof value === "function";
177
180
  const invokeMember = (target, property, args) => {
178
181
  const member = memberAt(target, property);
179
- if (isCallable(member)) Reflect.apply(member, target, args);
182
+ return isCallable(member) ? Reflect.apply(member, target, args) : void 0;
180
183
  };
181
184
  const judgedBy = (view, property, args, make) => {
182
185
  const assertion = make(view.actual, view.message);
183
186
  const target = view.negated ? assertion.not : assertion;
184
- invokeMember(target, property, args);
187
+ return invokeMember(target, property, args);
185
188
  };
186
189
  const raisedFailure = (thrown, site) => thrown instanceof Error ? withRaisingFrame(thrown, site) : thrown;
190
+ const framedOutcome = (outcome, site) => Predicate.isPromiseLike(outcome) ? outcome.then(void 0, (thrown) => Promise.reject(raisedFailure(thrown, site))) : outcome;
187
191
  /**
188
192
  * A failed judgement is a failure the fork raised: by now the stack holds only the fork's frames, so the site the
189
193
  * body called `expect` from is prepended to the error's stack (R2, KTD6).
190
194
  */
191
195
  const judgementOf = (view, property, args) => (make) => {
192
196
  try {
193
- judgedBy(view, property, args, make);
197
+ return framedOutcome(judgedBy(view, property, args, make), view.site);
194
198
  } catch (thrown) {
195
199
  throw raisedFailure(thrown, view.site);
196
200
  }
@@ -294,7 +298,7 @@ const makeLedger = (ctx) => {
294
298
  counter.judged += 1;
295
299
  counter.since += 1;
296
300
  if (counter.since > 1) throw refusalOf(refusePiecewise);
297
- authorize(() => judgement(hard));
301
+ return authorize(() => judgement(hard));
298
302
  },
299
303
  step: () => {
300
304
  counter.since = 0;
@@ -0,0 +1,36 @@
1
+
2
+ //#region src/internal/property/tiers.ts
3
+ const RUNS = {
4
+ mutation: 30,
5
+ ci: 1e3,
6
+ local: 100
7
+ };
8
+ const CI_OFF_VALUES = [
9
+ void 0,
10
+ "",
11
+ "false",
12
+ "0"
13
+ ];
14
+ const isCi = (env) => env["AGENT"] === void 0 && !CI_OFF_VALUES.includes(env["CI"]);
15
+ const isMutationWorker = (env) => env["STRYKER_MUTATOR_WORKER"] !== void 0;
16
+ const ciOrLocal = (env) => isCi(env) ? "ci" : "local";
17
+ /** @internal A Stryker worker wants fast mutant runs; CI wants the thorough tier; everything else is local. */
18
+ const tierOf = (env) => isMutationWorker(env) ? "mutation" : ciOrLocal(env);
19
+ /**
20
+ * @internal The check options direct `Arbitrary` checks use by default: `{ check: { runs } }` for the tier. A property
21
+ * test that passes its own `runs` still wins over this default.
22
+ */
23
+ const propertyTestDefaults = (env) => ({ check: { runs: RUNS[tierOf(env)] } });
24
+ /**
25
+ * @internal The property budget a run uses when it provides none: the tier's runs, and no seed-store writes in CI or a
26
+ * Stryker worker, where a checkout is discarded or a mutant run fails on purpose.
27
+ */
28
+ const providedBudgetOf = (env) => {
29
+ const tier = tierOf(env);
30
+ return tier === "local" ? { runs: RUNS.local } : {
31
+ runs: RUNS[tier],
32
+ record: false
33
+ };
34
+ };
35
+ //#endregion
36
+ export { providedBudgetOf as n, propertyTestDefaults as t };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@systemfsoftware/vitest",
3
3
  "license": "MIT",
4
- "version": "2.0.0",
4
+ "version": "4.1.2",
5
5
  "author": "Ryan Lee <drdgvhbh@gmail.com>",
6
6
  "repository": {
7
7
  "type": "git",
@@ -37,6 +37,10 @@
37
37
  "types": "./dist/integration.d.ts",
38
38
  "default": "./dist/integration.mjs"
39
39
  },
40
+ "./property-defaults": {
41
+ "types": "./dist/property-defaults.d.ts",
42
+ "default": "./dist/property-defaults.mjs"
43
+ },
40
44
  "./TestClock": {
41
45
  "types": "./dist/TestClock.d.ts",
42
46
  "default": "./dist/TestClock.mjs"
@@ -47,32 +51,25 @@
47
51
  "dist"
48
52
  ],
49
53
  "dependencies": {
50
- "@effect/platform-node": "^4"
54
+ "@effect/platform-node": "^4.1.2"
51
55
  },
52
56
  "devDependencies": {
53
57
  "@systemfsoftware/arethetypeswrong-cli": "^4.2.0",
54
- "@systemfsoftware/oxlint-config-recommended": "^4.0.0",
55
- "@systemfsoftware/stryker-config": "^0.1.0",
56
- "@systemfsoftware/stryker-ignorer-effect-schema-declarations": "latest",
57
- "@systemfsoftware/stryker-ignorer-in-source-vitest-block": "latest",
58
- "@systemfsoftware/stryker-js": "latest",
59
- "@systemfsoftware/stryker-js-typescript-checker": "latest",
60
- "@systemfsoftware/stryker-js-vitest-runner": "latest",
61
- "@systemfsoftware/stryker-test-contribution": "latest",
62
- "@systemfsoftware/tsconfig": "^2.0.1",
63
- "@systemfsoftware/tsdown-config": "^0.1.0",
64
- "@systemfsoftware/vitest-config": "^0.1.0",
65
- "@types/node": "^26",
66
- "effect": "^4",
67
- "oxlint": "~1.82.0",
58
+ "@systemfsoftware/oxlint-config-recommended": "^7.0.0",
59
+ "@systemfsoftware/tsconfig": "^2.1.0",
60
+ "@systemfsoftware/tsdown-config": "^0.1.2",
61
+ "@systemfsoftware/vitest-config": "^0.1.3",
62
+ "@types/node": "^26.6.5",
63
+ "effect": "^4.1.2",
64
+ "oxlint": "~1.93.0",
68
65
  "rimraf": "^6.1.3",
69
66
  "tsdown": "^0.23.0",
70
67
  "tstyche": "^7.2.5",
71
- "vitest": "^5"
68
+ "vitest": "^5.1.0"
72
69
  },
73
70
  "peerDependencies": {
74
- "effect": "^4",
75
- "vitest": "^5"
71
+ "effect": "^4.1.2",
72
+ "vitest": "^5.1.0"
76
73
  },
77
74
  "publishConfig": {
78
75
  "access": "public",
@@ -83,7 +80,6 @@
83
80
  "build": "tsdown -l warn",
84
81
  "typecheck": "tsc -b",
85
82
  "test": "vitest run",
86
- "mutation": "stryker run",
87
83
  "test:types": "TSTYCHE_TYPESCRIPT_MODULE=tstyche-typescript tstyche",
88
84
  "lint": "f=${OXLINT_FORMAT:-${AGENT:+agent}}; oxlint . --format=${f:-default}",
89
85
  "attw": "attw --pack ."