pabst-checker 0.12.0 → 0.12.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/cli.js +11 -7
- package/dist/contract.d.ts +46 -0
- package/dist/contract.js +52 -0
- package/dist/emit.js +3 -2
- package/dist/envelope.d.ts +12 -1
- package/dist/envelope.js +1 -1
- package/dist/issue-schema.d.ts +23 -0
- package/dist/issue-schema.js +60 -0
- package/dist/lower.js +2 -1
- package/dist/qualified-name.d.ts +9 -0
- package/dist/qualified-name.js +9 -0
- package/dist/run.d.ts +8 -9
- package/dist/run.js +15 -8
- package/dist/runtime.js +3 -3
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -90,13 +90,17 @@ function run(command, patterns, seedArg) {
|
|
|
90
90
|
console.error(`pabst: generated ${generated} propert${generated === 1 ? "y" : "ies"} across ${results.length} file(s) into .pabst/`);
|
|
91
91
|
if (command === "gen")
|
|
92
92
|
return 0;
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
const meta = { version, startedAt, cwd, seed, generated };
|
|
94
|
+
// Scope the run to the out-files generated by THIS invocation (issue #41):
|
|
95
|
+
// .pabst/ accumulates mirrors from earlier runs, and running the whole
|
|
96
|
+
// directory would re-execute them and mix their issues into this envelope.
|
|
97
|
+
// With nothing generated there is nothing to run — and an empty file list
|
|
98
|
+
// would tell vitest to run everything, so short-circuit instead.
|
|
99
|
+
if (results.length === 0) {
|
|
100
|
+
console.log(JSON.stringify({ ...meta, passed: 0, failed: 0, issues: [] }, null, 2));
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
const result = runTests(results.map((r) => r.outFile), meta);
|
|
100
104
|
if (result.kind === "no-results") {
|
|
101
105
|
process.stderr.write(result.stdout);
|
|
102
106
|
process.stderr.write(result.stderr);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The generated-code contract: every spelling that must agree across the
|
|
3
|
+
* seam between emitted test code, the runtime it imports, and the issue
|
|
4
|
+
* wire format the CLI parses back out of vitest. Each value here is either
|
|
5
|
+
* written into generated output or used to decode it — the two sides of
|
|
6
|
+
* each seam import this module instead of spelling the string twice.
|
|
7
|
+
*/
|
|
8
|
+
export type IssueKind = "falsified" | "threw" | "exhausted";
|
|
9
|
+
export interface Issue {
|
|
10
|
+
file: string;
|
|
11
|
+
function: string;
|
|
12
|
+
property: string;
|
|
13
|
+
kind: IssueKind;
|
|
14
|
+
counterexample?: Record<string, unknown>;
|
|
15
|
+
error?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Module specifier generated tests import the runtime from. Must match
|
|
19
|
+
* package.json's `name` + `exports` map (pinned by a test).
|
|
20
|
+
*/
|
|
21
|
+
export declare const RUNTIME_SPECIFIER = "pabst-checker/runtime";
|
|
22
|
+
/** Names the runtime module exports (pinned against src/runtime.ts by a test). */
|
|
23
|
+
export declare const BOOL_EXPORT = "bool";
|
|
24
|
+
export declare const REPORT_EXPORT = "report";
|
|
25
|
+
/** Aliases those exports are bound to inside generated test files. */
|
|
26
|
+
export declare const BOOL_ALIAS = "__bool";
|
|
27
|
+
export declare const REPORT_ALIAS = "__pabstReport";
|
|
28
|
+
/**
|
|
29
|
+
* The exact message fast-check puts on the error it synthesizes when a
|
|
30
|
+
* property returns false (as opposed to throwing). The runtime's
|
|
31
|
+
* falsified-vs-threw classification string-matches this because RunDetails
|
|
32
|
+
* carries no discriminator field — fast-check knows which case occurred and
|
|
33
|
+
* erases it into this prose. The principled fix is upstream: a `failureKind`
|
|
34
|
+
* field on RunDetails. Until then, a live pin test fails loudly if a
|
|
35
|
+
* fast-check upgrade rewords it.
|
|
36
|
+
*/
|
|
37
|
+
export declare const FC_PROPERTY_FAILED_MESSAGE = "Property failed by returning false";
|
|
38
|
+
export declare const ISSUE_SENTINEL = "PABST_ISSUE:";
|
|
39
|
+
/** Encode an issue for the wire: sentinel + single-line JSON, carried on an Error message. */
|
|
40
|
+
export declare function encodeIssue(issue: Issue): string;
|
|
41
|
+
/**
|
|
42
|
+
* Extract a pabst Issue from a vitest failure message, or null if the message
|
|
43
|
+
* carries no tagged payload. The payload is single-line JSON, so a stack trace
|
|
44
|
+
* on following lines is ignored.
|
|
45
|
+
*/
|
|
46
|
+
export declare function parseIssue(failureMessage: string): Issue | null;
|
package/dist/contract.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The generated-code contract: every spelling that must agree across the
|
|
3
|
+
* seam between emitted test code, the runtime it imports, and the issue
|
|
4
|
+
* wire format the CLI parses back out of vitest. Each value here is either
|
|
5
|
+
* written into generated output or used to decode it — the two sides of
|
|
6
|
+
* each seam import this module instead of spelling the string twice.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Module specifier generated tests import the runtime from. Must match
|
|
10
|
+
* package.json's `name` + `exports` map (pinned by a test).
|
|
11
|
+
*/
|
|
12
|
+
export const RUNTIME_SPECIFIER = "pabst-checker/runtime";
|
|
13
|
+
/** Names the runtime module exports (pinned against src/runtime.ts by a test). */
|
|
14
|
+
export const BOOL_EXPORT = "bool";
|
|
15
|
+
export const REPORT_EXPORT = "report";
|
|
16
|
+
/** Aliases those exports are bound to inside generated test files. */
|
|
17
|
+
export const BOOL_ALIAS = "__bool";
|
|
18
|
+
export const REPORT_ALIAS = "__pabstReport";
|
|
19
|
+
/**
|
|
20
|
+
* The exact message fast-check puts on the error it synthesizes when a
|
|
21
|
+
* property returns false (as opposed to throwing). The runtime's
|
|
22
|
+
* falsified-vs-threw classification string-matches this because RunDetails
|
|
23
|
+
* carries no discriminator field — fast-check knows which case occurred and
|
|
24
|
+
* erases it into this prose. The principled fix is upstream: a `failureKind`
|
|
25
|
+
* field on RunDetails. Until then, a live pin test fails loudly if a
|
|
26
|
+
* fast-check upgrade rewords it.
|
|
27
|
+
*/
|
|
28
|
+
export const FC_PROPERTY_FAILED_MESSAGE = "Property failed by returning false";
|
|
29
|
+
export const ISSUE_SENTINEL = "PABST_ISSUE:";
|
|
30
|
+
// Escaped so a future sentinel containing regex metacharacters can't
|
|
31
|
+
// silently change what the regex matches.
|
|
32
|
+
const ISSUE_RE = new RegExp(`${ISSUE_SENTINEL.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(\\{.*\\})`);
|
|
33
|
+
/** Encode an issue for the wire: sentinel + single-line JSON, carried on an Error message. */
|
|
34
|
+
export function encodeIssue(issue) {
|
|
35
|
+
return ISSUE_SENTINEL + JSON.stringify(issue);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Extract a pabst Issue from a vitest failure message, or null if the message
|
|
39
|
+
* carries no tagged payload. The payload is single-line JSON, so a stack trace
|
|
40
|
+
* on following lines is ignored.
|
|
41
|
+
*/
|
|
42
|
+
export function parseIssue(failureMessage) {
|
|
43
|
+
const m = ISSUE_RE.exec(failureMessage);
|
|
44
|
+
if (!m)
|
|
45
|
+
return null;
|
|
46
|
+
try {
|
|
47
|
+
return JSON.parse(m[1]);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
package/dist/emit.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
|
+
import { BOOL_ALIAS, BOOL_EXPORT, REPORT_ALIAS, REPORT_EXPORT, RUNTIME_SPECIFIER, } from "./contract.js";
|
|
2
3
|
import { arbitraryFor } from "./domains.js";
|
|
3
4
|
import { qualifiedName } from "./qualified-name.js";
|
|
4
5
|
const SRC_EXT = /\.(ts|tsx|mts|cts|js|mjs|cjs)$/;
|
|
@@ -12,7 +13,7 @@ export function emit(specs, sourceFile, outFile, seed) {
|
|
|
12
13
|
const lines = [];
|
|
13
14
|
lines.push(`import { describe } from "vitest";`);
|
|
14
15
|
lines.push(`import { test, fc } from "@fast-check/vitest";`);
|
|
15
|
-
lines.push(`import {
|
|
16
|
+
lines.push(`import { ${REPORT_EXPORT} as ${REPORT_ALIAS}, ${BOOL_EXPORT} as ${BOOL_ALIAS} } from "${RUNTIME_SPECIFIER}";`);
|
|
16
17
|
lines.push(`import * as __M from "${rel}";`);
|
|
17
18
|
if (allExports.length > 0)
|
|
18
19
|
lines.push(`const { ${allExports.join(", ")} } = __M;`);
|
|
@@ -61,7 +62,7 @@ function emitProp(s, sourceFile, seed, indent) {
|
|
|
61
62
|
const name = JSON.stringify(s.name);
|
|
62
63
|
const file = JSON.stringify(sourceFile);
|
|
63
64
|
const fn = JSON.stringify(qualifiedName(s.functionName, s.className, s.isStatic));
|
|
64
|
-
const reporter = `(d) =>
|
|
65
|
+
const reporter = `(d) => ${REPORT_ALIAS}(${file}, ${fn}, ${name}, [${varNames}], d)`;
|
|
65
66
|
const params = `{ seed: ${seed}, reporter: ${reporter} }`;
|
|
66
67
|
const out = [];
|
|
67
68
|
out.push(`${indent}test.prop([${arbs}], ${params})(${name}, (${vars}) => {`);
|
package/dist/envelope.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
import { type Issue
|
|
1
|
+
import { type Issue } from "./contract.js";
|
|
2
|
+
/** The full report of one pabst run: metadata, counts, and parsed issues. */
|
|
3
|
+
export interface Envelope {
|
|
4
|
+
version: string;
|
|
5
|
+
startedAt: string;
|
|
6
|
+
cwd: string;
|
|
7
|
+
seed: number;
|
|
8
|
+
generated: number;
|
|
9
|
+
passed: number;
|
|
10
|
+
failed: number;
|
|
11
|
+
issues: Issue[];
|
|
12
|
+
}
|
|
2
13
|
/** The subset of vitest's JSON reporter output the envelope consumes. */
|
|
3
14
|
export interface AssertionResult {
|
|
4
15
|
status: string;
|
package/dist/envelope.js
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const IssueSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
3
|
+
kind: z.ZodLiteral<"falsified">;
|
|
4
|
+
counterexample: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodNumber, z.ZodBoolean, z.ZodString]>>;
|
|
5
|
+
file: z.ZodString;
|
|
6
|
+
function: z.ZodString;
|
|
7
|
+
property: z.ZodString;
|
|
8
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
9
|
+
kind: z.ZodLiteral<"threw">;
|
|
10
|
+
counterexample: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodNumber, z.ZodBoolean, z.ZodString]>>;
|
|
11
|
+
error: z.ZodString;
|
|
12
|
+
file: z.ZodString;
|
|
13
|
+
function: z.ZodString;
|
|
14
|
+
property: z.ZodString;
|
|
15
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
16
|
+
kind: z.ZodLiteral<"exhausted">;
|
|
17
|
+
error: z.ZodString;
|
|
18
|
+
file: z.ZodString;
|
|
19
|
+
function: z.ZodString;
|
|
20
|
+
property: z.ZodString;
|
|
21
|
+
}, z.core.$strict>], "kind">;
|
|
22
|
+
/** The issue JSON Schema as a plain object — the generator and the sync test both call this. */
|
|
23
|
+
export declare function issueJsonSchema(): unknown;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { QUALIFIED_NAME_PATTERN } from "./qualified-name.js";
|
|
3
|
+
/**
|
|
4
|
+
* Single source of truth for the issue wire shape. The static type side is
|
|
5
|
+
* guarded one-way against the loose `Issue` interface in contract.ts (see
|
|
6
|
+
* tests/contract-pins.test.ts); the JSON side is generated into
|
|
7
|
+
* schemas/issue.schema.json (npm run generate:schema) and pinned by a
|
|
8
|
+
* deep-equal sync test.
|
|
9
|
+
*/
|
|
10
|
+
const functionName = z.string().regex(QUALIFIED_NAME_PATTERN).meta({
|
|
11
|
+
id: "functionName",
|
|
12
|
+
description: "Bare function name, or Class#method (instance) / Class.method (static).",
|
|
13
|
+
});
|
|
14
|
+
const counterexample = z
|
|
15
|
+
.record(z.string(), z.union([z.number(), z.boolean(), z.string()]))
|
|
16
|
+
.meta({ id: "counterexample" });
|
|
17
|
+
const common = {
|
|
18
|
+
file: z.string(),
|
|
19
|
+
function: functionName,
|
|
20
|
+
property: z.string().min(1),
|
|
21
|
+
};
|
|
22
|
+
export const IssueSchema = z
|
|
23
|
+
.discriminatedUnion("kind", [
|
|
24
|
+
z
|
|
25
|
+
.strictObject({
|
|
26
|
+
...common,
|
|
27
|
+
kind: z.literal("falsified"),
|
|
28
|
+
counterexample,
|
|
29
|
+
})
|
|
30
|
+
.meta({ title: "falsified" }),
|
|
31
|
+
z
|
|
32
|
+
.strictObject({
|
|
33
|
+
...common,
|
|
34
|
+
kind: z.literal("threw"),
|
|
35
|
+
counterexample,
|
|
36
|
+
error: z.string(),
|
|
37
|
+
})
|
|
38
|
+
.meta({ title: "threw" }),
|
|
39
|
+
z
|
|
40
|
+
.strictObject({
|
|
41
|
+
...common,
|
|
42
|
+
kind: z.literal("exhausted"),
|
|
43
|
+
error: z.string(),
|
|
44
|
+
})
|
|
45
|
+
.meta({ title: "exhausted" }),
|
|
46
|
+
])
|
|
47
|
+
.meta({
|
|
48
|
+
title: "Pabst Issue",
|
|
49
|
+
description: "A single property failure emitted by the pabst reporter.",
|
|
50
|
+
});
|
|
51
|
+
/** The issue JSON Schema as a plain object — the generator and the sync test both call this. */
|
|
52
|
+
export function issueJsonSchema() {
|
|
53
|
+
const schema = z.toJSONSchema(IssueSchema, { target: "draft-7" });
|
|
54
|
+
// zod ignores a root-level meta id, so the document identifier is stamped here.
|
|
55
|
+
return {
|
|
56
|
+
$schema: schema.$schema,
|
|
57
|
+
$id: "https://pabst.test/schemas/issue.schema.json",
|
|
58
|
+
...schema,
|
|
59
|
+
};
|
|
60
|
+
}
|
package/dist/lower.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { BOOL_ALIAS } from "./contract.js";
|
|
1
2
|
/** A pure boolean expression string for any sub-formula (implication = material). */
|
|
2
3
|
export function lowerExpr(f) {
|
|
3
4
|
switch (f.kind) {
|
|
4
5
|
case "atom":
|
|
5
|
-
return
|
|
6
|
+
return `${BOOL_ALIAS}(${f.js}, ${JSON.stringify(f.text)})`;
|
|
6
7
|
case "not":
|
|
7
8
|
return `!(${lowerExpr(f.arg)})`;
|
|
8
9
|
case "and":
|
package/dist/qualified-name.d.ts
CHANGED
|
@@ -3,3 +3,12 @@
|
|
|
3
3
|
* (instance) / `Class.method` (static) when it lives on a class.
|
|
4
4
|
*/
|
|
5
5
|
export declare function qualifiedName(functionName: string, className?: string, isStatic?: boolean): string;
|
|
6
|
+
/**
|
|
7
|
+
* Matches the strings qualifiedName() produces: a bare identifier, or two
|
|
8
|
+
* identifiers joined by `#` (instance) / `.` (static). Segments are ASCII
|
|
9
|
+
* TypeScript identifiers; unicode identifiers (e.g. `précis`) are legal
|
|
10
|
+
* TypeScript but not matched — a known gap, kept so the pattern stays within
|
|
11
|
+
* JSON Schema's ECMA-regex subset (schemas/issue.schema.json embeds it; a
|
|
12
|
+
* sync test keeps the two spellings identical).
|
|
13
|
+
*/
|
|
14
|
+
export declare const QUALIFIED_NAME_PATTERN: RegExp;
|
package/dist/qualified-name.js
CHANGED
|
@@ -9,3 +9,12 @@ export function qualifiedName(functionName, className, isStatic) {
|
|
|
9
9
|
? `${className}.${functionName}`
|
|
10
10
|
: `${className}#${functionName}`;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Matches the strings qualifiedName() produces: a bare identifier, or two
|
|
14
|
+
* identifiers joined by `#` (instance) / `.` (static). Segments are ASCII
|
|
15
|
+
* TypeScript identifiers; unicode identifiers (e.g. `précis`) are legal
|
|
16
|
+
* TypeScript but not matched — a known gap, kept so the pattern stays within
|
|
17
|
+
* JSON Schema's ECMA-regex subset (schemas/issue.schema.json embeds it; a
|
|
18
|
+
* sync test keeps the two spellings identical).
|
|
19
|
+
*/
|
|
20
|
+
export const QUALIFIED_NAME_PATTERN = /^[$A-Za-z_][$A-Za-z0-9_]*([#.][$A-Za-z_][$A-Za-z0-9_]*)?$/;
|
package/dist/run.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { type RunMeta } from "./envelope.js";
|
|
2
|
-
import type { Envelope } from "./issue.js";
|
|
1
|
+
import { type Envelope, type RunMeta } from "./envelope.js";
|
|
3
2
|
/** Where the spawned vitest writes its JSON results, relative to cwd. */
|
|
4
3
|
export declare const RESULTS_FILE = ".pabst/.last-run.json";
|
|
5
4
|
export type RunResult = {
|
|
@@ -16,11 +15,11 @@ export type RunResult = {
|
|
|
16
15
|
messages: string[];
|
|
17
16
|
};
|
|
18
17
|
/**
|
|
19
|
-
* Run vitest over `target` (the generated-
|
|
20
|
-
* file) and assemble the run envelope from its JSON
|
|
21
|
-
* produces no parseable results file (e.g. it died on
|
|
22
|
-
* reporter ran), the run yielded nothing trustworthy to
|
|
23
|
-
* envelope, return vitest's raw output and exit status
|
|
24
|
-
* surface the underlying error.
|
|
18
|
+
* Run vitest over `target` (the generated out-files of one invocation, or a
|
|
19
|
+
* single file or directory) and assemble the run envelope from its JSON
|
|
20
|
+
* results. When vitest produces no parseable results file (e.g. it died on
|
|
21
|
+
* startup before its reporter ran), the run yielded nothing trustworthy to
|
|
22
|
+
* report: instead of an envelope, return vitest's raw output and exit status
|
|
23
|
+
* so the caller can surface the underlying error.
|
|
25
24
|
*/
|
|
26
|
-
export declare function runTests(target: string, meta: RunMeta, resultsFile?: string): RunResult;
|
|
25
|
+
export declare function runTests(target: string | string[], meta: RunMeta, resultsFile?: string): RunResult;
|
package/dist/run.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import { readFileSync, rmSync } from "node:fs";
|
|
3
|
-
import { buildEnvelope } from "./envelope.js";
|
|
3
|
+
import { buildEnvelope, } from "./envelope.js";
|
|
4
4
|
/** Where the spawned vitest writes its JSON results, relative to cwd. */
|
|
5
5
|
export const RESULTS_FILE = ".pabst/.last-run.json";
|
|
6
6
|
/**
|
|
7
|
-
* Run vitest over `target` (the generated-
|
|
8
|
-
* file) and assemble the run envelope from its JSON
|
|
9
|
-
* produces no parseable results file (e.g. it died on
|
|
10
|
-
* reporter ran), the run yielded nothing trustworthy to
|
|
11
|
-
* envelope, return vitest's raw output and exit status
|
|
12
|
-
* surface the underlying error.
|
|
7
|
+
* Run vitest over `target` (the generated out-files of one invocation, or a
|
|
8
|
+
* single file or directory) and assemble the run envelope from its JSON
|
|
9
|
+
* results. When vitest produces no parseable results file (e.g. it died on
|
|
10
|
+
* startup before its reporter ran), the run yielded nothing trustworthy to
|
|
11
|
+
* report: instead of an envelope, return vitest's raw output and exit status
|
|
12
|
+
* so the caller can surface the underlying error.
|
|
13
13
|
*/
|
|
14
14
|
export function runTests(target, meta, resultsFile = RESULTS_FILE) {
|
|
15
15
|
// A stale results file from a previous run must not be mistaken for this
|
|
@@ -25,7 +25,14 @@ export function runTests(target, meta, resultsFile = RESULTS_FILE) {
|
|
|
25
25
|
stderr: `pabst: cannot clear stale results file ${resultsFile}: ${e instanceof Error ? e.message : String(e)}\n`,
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
const
|
|
28
|
+
const targets = Array.isArray(target) ? target : [target];
|
|
29
|
+
const res = spawnSync("npx", [
|
|
30
|
+
"vitest",
|
|
31
|
+
"run",
|
|
32
|
+
...targets,
|
|
33
|
+
"--reporter=json",
|
|
34
|
+
`--outputFile=${resultsFile}`,
|
|
35
|
+
], { encoding: "utf8" });
|
|
29
36
|
let json;
|
|
30
37
|
try {
|
|
31
38
|
json = JSON.parse(readFileSync(resultsFile, "utf8"));
|
package/dist/runtime.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { stringify } from "fast-check";
|
|
2
|
-
import {
|
|
2
|
+
import { encodeIssue, FC_PROPERTY_FAILED_MESSAGE, } from "./contract.js";
|
|
3
3
|
/**
|
|
4
4
|
* Encode a single counterexample value for JSON output: finite numbers,
|
|
5
5
|
* booleans, and strings round-trip as native JSON; everything else (bigint,
|
|
@@ -13,7 +13,7 @@ function encodeValue(v) {
|
|
|
13
13
|
return stringify(v);
|
|
14
14
|
}
|
|
15
15
|
function throwIssue(issue) {
|
|
16
|
-
throw new Error(
|
|
16
|
+
throw new Error(encodeIssue(issue));
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Assert that a property atom evaluated to a genuine boolean (no truthiness
|
|
@@ -54,7 +54,7 @@ export function report(file, functionName, name, varNames, d) {
|
|
|
54
54
|
counterexample[n] = encodeValue(d.counterexample[i]);
|
|
55
55
|
});
|
|
56
56
|
const err = d.errorInstance;
|
|
57
|
-
const threw = !!err && err.message !==
|
|
57
|
+
const threw = !!err && err.message !== FC_PROPERTY_FAILED_MESSAGE;
|
|
58
58
|
if (threw) {
|
|
59
59
|
throwIssue({ ...base, kind: "threw", counterexample, error: err.message });
|
|
60
60
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pabst-checker",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "Property-based testing from @ensures annotations, powered by fast-check.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -56,12 +56,12 @@
|
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@fast-check/vitest": "^0.4.1",
|
|
59
|
-
"fast-check": "^4.8.0",
|
|
60
59
|
"@stryker-mutator/core": "^9.6.1",
|
|
61
60
|
"@stryker-mutator/vitest-runner": "^9.6.1",
|
|
62
61
|
"@types/node": "^26.1.0",
|
|
63
62
|
"@vitest/coverage-v8": "^4.1.9",
|
|
64
63
|
"ajv": "^8.20.0",
|
|
64
|
+
"fast-check": "^4.8.0",
|
|
65
65
|
"prettier": "3.9.5"
|
|
66
66
|
}
|
|
67
67
|
}
|