@systemfsoftware/vitest 2.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/CHANGELOG.md +4 -58
- package/README.md +17 -1
- package/dist/{checks-DiuzHhQM.d.ts → checks-BHOX6fGC.d.ts} +2 -2
- package/dist/{engine-D7Q6-BxD.d.ts → engine-CYGdHvr8.d.ts} +68 -107
- package/dist/{failure-nvq5TwWX.mjs → failure-C67X1OAe.mjs} +189 -47
- package/dist/failure.d.ts +2 -2
- package/dist/failure.mjs +2 -2
- package/dist/{guard-BocOhXt2.mjs → guard-Ci0TyBYv.mjs} +18 -6
- package/dist/guard.mjs +2 -2
- package/dist/index.d.ts +20 -70
- package/dist/index.mjs +25 -76
- package/dist/integration.d.ts +1 -1
- package/dist/integration.mjs +1 -1
- package/dist/property-defaults.d.ts +11 -0
- package/dist/property-defaults.mjs +15 -0
- package/dist/{test-context-D_-acRSc.mjs → test-context-DelFkLBL.mjs} +10 -6
- package/dist/tiers-W0BWq1uh.mjs +36 -0
- package/package.json +16 -20
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
|
|
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-
|
|
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
|
|
10
|
+
import "effect/testing/TestConsole";
|
|
11
11
|
import * as Context from "effect/Context";
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
//#region src/internal/
|
|
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
|
-
|
|
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 |
|
|
213
|
-
<Eff, AEff>(body: Body<Eff, AEff> | BodyRefusal, timeout?: number |
|
|
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
|
|
3
|
-
import {
|
|
4
|
-
import { _ as refuseScopedLiveLane, d as refuseAsyncBody, f as refuseEffectLane, g as refuseScopedLane, i as markTask,
|
|
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]);
|
|
@@ -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,
|
|
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,
|
|
618
|
+
return rerunIfClean(ctx, second);
|
|
674
619
|
});
|
|
675
620
|
const registering = (registrar) => (name, body, timeout) => {
|
|
676
621
|
const lane = laneBodyOf(body);
|
|
677
|
-
|
|
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) =>
|
|
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 };
|
package/dist/integration.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { a as Expect, n as AssertedShape, r as Check, t as Asserted } from "./checks-
|
|
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
|
/**
|
package/dist/integration.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { r as Asserted, t as VitestTestContext } from "./test-context-
|
|
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-
|
|
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
|
-
|
|
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
|
-
|
|
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": "
|
|
4
|
+
"version": "4.1.1",
|
|
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": "^
|
|
55
|
-
"@systemfsoftware/
|
|
56
|
-
"@systemfsoftware/
|
|
57
|
-
"@systemfsoftware/
|
|
58
|
-
"@
|
|
59
|
-
"
|
|
60
|
-
"
|
|
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": "^6.0.1",
|
|
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.89.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 ."
|