@playfast/reform-proof-vitest 0.0.5 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@playfast/reform-proof-vitest",
3
3
  "playbook": "./playbook",
4
- "version": "0.0.5",
4
+ "version": "0.1.0",
5
5
  "type": "module",
6
6
  "description": "Vitest adapter for reform-proof — a vite plugin that auto-registers every *.proof.ts suite as native vitest tests, run through the proof engine.",
7
7
  "keywords": [
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { isProofSuite, type ProofSuite, withProofRunner } from '@playfast/reform-proof'
2
- import { describe, test } from 'vitest'
2
+ import { describe, expect, test } from 'vitest'
3
3
 
4
4
  // reform-proof vitest adapter — turns a reform proof `ProofSuite` into native
5
5
  // vitest tests (a `describe` per product, a `test` per requirement), each run
@@ -30,21 +30,19 @@ export const setProofTestHook = (hook: () => void): void => {
30
30
  }
31
31
 
32
32
  const runSetupHooks = (): void => {
33
- for (const hook of setupHooks) hook()
33
+ setupHooks.forEach((hook) => hook())
34
34
  }
35
35
 
36
36
  const registerSuite = (suite: ProofSuite): void => {
37
37
  describe(suite.product.manifest.name, () => {
38
- for (const proof of suite.proofs) {
38
+ suite.proofs.forEach((proof) => {
39
39
  const statement = proof.requirement.manifest.statement
40
40
  test(statement, async () => {
41
41
  runSetupHooks()
42
- const result = await withProofRunner((runner) => runner.executeProof(proof))
43
- if (!result.ok) {
44
- throw new Error(`reform-proof: ${statement} — ${result.error ?? 'failed'}`)
45
- }
42
+ const outcome = await withProofRunner((runner) => runner.executeProof(proof))
43
+ expect(outcome.ok, `reform-proof: ${statement} — ${outcome.error ?? 'failed'}`).toBe(true)
46
44
  })
47
- }
45
+ })
48
46
  })
49
47
  }
50
48
 
@@ -53,10 +51,12 @@ const registerSuite = (suite: ProofSuite): void => {
53
51
  * values are ignored, so a whole module's exports can be passed verbatim — which
54
52
  * is exactly what `reformProofPlugin` does.
55
53
  */
56
- export const registerSuites = (values: ReadonlyArray<unknown>): void => {
57
- for (const value of values) {
58
- if (!isProofSuite(value) || registered.has(value)) continue
59
- registered.add(value)
60
- registerSuite(value)
61
- }
54
+ export const registerSuites = (candidates: ReadonlyArray<unknown>): void => {
55
+ candidates.forEach((candidate) => {
56
+ if (!isProofSuite(candidate) || registered.has(candidate)) {
57
+ return
58
+ }
59
+ registered.add(candidate)
60
+ registerSuite(candidate)
61
+ })
62
62
  }
package/src/plugin.ts CHANGED
@@ -9,8 +9,8 @@ import { init, parse } from 'es-module-lexer'
9
9
 
10
10
  const PROOF_RE = /\.proof\.ts$/
11
11
 
12
- /** Options for `reformProofPlugin`. */
13
- export interface ReformProofPluginOptions {
12
+ /** Options for `reformProofPlugin`. ExternalApi: vite-plugin config boundary. */
13
+ export interface ReformProofPluginOptionsExternalApi {
14
14
  /**
15
15
  * Module specifier(s) the plugin side-effect-imports into every `*.proof.ts`,
16
16
  * before registering its suites. Use to register per-proof-test setup
@@ -23,7 +23,7 @@ export interface ReformProofPluginOptions {
23
23
 
24
24
  /** The minimal vite plugin shape this adapter needs — structurally a `Plugin`,
25
25
  * declared locally so the package need not depend on vite's types. */
26
- export interface ReformProofPlugin {
26
+ export interface ReformProofPluginExternalApi {
27
27
  readonly name: string
28
28
  readonly enforce: 'post'
29
29
  transform(
@@ -32,16 +32,20 @@ export interface ReformProofPlugin {
32
32
  ): Promise<{ readonly code: string; readonly map: null } | null>
33
33
  }
34
34
 
35
- const sourcePath = (id: string): string => id.split('?')[0] ?? id
35
+ const sourcePath = (id: string): string => id.replace(/\?.*$/, '')
36
36
 
37
- const setupList = (setup: ReformProofPluginOptions['setup']): ReadonlyArray<string> =>
37
+ const setupList = (
38
+ setup: ReformProofPluginOptionsExternalApi['setup'],
39
+ ): ReadonlyArray<string> =>
38
40
  setup === undefined ? [] : typeof setup === 'string' ? [setup] : setup
39
41
 
40
42
  /**
41
43
  * The plugin. Runs `post` (after TS→JS), so it lexes plain JS exports reliably.
42
44
  * Only `*.proof.ts` modules are touched; everything else passes through.
43
45
  */
44
- export const reformProofPlugin = (options?: ReformProofPluginOptions): ReformProofPlugin => {
46
+ export const reformProofPlugin = (
47
+ options?: ReformProofPluginOptionsExternalApi,
48
+ ): ReformProofPluginExternalApi => {
45
49
  const setupImports = setupList(options?.setup)
46
50
  .map((spec) => `import '${spec}'`)
47
51
  .join('\n')
@@ -49,7 +53,9 @@ export const reformProofPlugin = (options?: ReformProofPluginOptions): ReformPro
49
53
  name: 'reform-proof-vitest',
50
54
  enforce: 'post',
51
55
  async transform(code, id) {
52
- if (!PROOF_RE.test(sourcePath(id))) return null
56
+ if (!PROOF_RE.test(sourcePath(id))) {
57
+ return null
58
+ }
53
59
  await init
54
60
  const [, exports] = parse(code)
55
61
  // Reference each export's LOCAL binding (in scope after the module body); a
@@ -57,7 +63,9 @@ export const reformProofPlugin = (options?: ReformProofPluginOptions): ReformPro
57
63
  const names = exports
58
64
  .map((exportSpec) => exportSpec.ln)
59
65
  .filter((local): local is string => typeof local === 'string' && local.length > 0)
60
- if (names.length === 0) return null
66
+ if (names.length === 0) {
67
+ return null
68
+ }
61
69
  const epilogue =
62
70
  `\n${setupImports}\n` +
63
71
  `import { registerSuites as __registerReformProofSuites } from '@playfast/reform-proof-vitest'\n` +