@contractspec/lib.testing 3.7.16 → 3.7.18

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.js CHANGED
@@ -1,220 +1,28 @@
1
1
  // @bun
2
- // src/generator/assertion-builder.ts
3
- function buildAssertions(testCase, ctx) {
4
- if (testCase.success) {
5
- return [
6
- `const result = await ${ctx.runnerCall};`,
7
- `expect(result).toEqual(${serialize(testCase.expectedOutput ?? null)});`
8
- ].join(`
9
- `);
10
- }
11
- return `await expect(${ctx.runnerCall}).rejects.toMatchObject(${serialize(testCase.expectedError ?? { message: "expected failure" })});`;
12
- }
13
- function serialize(value) {
14
- return JSON.stringify(value, (_key, val) => {
15
- if (val instanceof Date)
16
- return val.toISOString();
17
- if (typeof val === "undefined")
18
- return null;
19
- return val;
20
- }, 2);
21
- }
2
+ function T(e,r){if(e.success)return[`const result = await ${r.runnerCall};`,`expect(result).toEqual(${s(e.expectedOutput??null)});`].join(`
3
+ `);return`await expect(${r.runnerCall}).rejects.toMatchObject(${s(e.expectedError??{message:"expected failure"})});`}function s(e){return JSON.stringify(e,(r,t)=>{if(t instanceof Date)return t.toISOString();if(typeof t>"u")return null;return t},2)}function p(e){let r=e.cases.map((t)=>{let n=s(t.input),i=s(t.metadata??{}),a=`const result = await ${e.runnerFunction}(input${t.id}, metadata${t.id});
4
+ expect(result).toEqual(${s(t.expectedOutput??null)});`,o=`await expect(${e.runnerFunction}(input${t.id}, metadata${t.id})).rejects.toMatchObject(${s(t.expectedError??{message:"expected failure"})});`;return`
5
+ test('${t.name}', async () => {
6
+ const input${t.id} = ${n};
7
+ const metadata${t.id} = ${i};
8
+ ${t.success?a:o}
9
+ });`}).join(`
10
+ `);return`
11
+ import { ${e.runnerFunction} } from '${e.runnerImport}';
22
12
 
23
- // src/adapters/jest-adapter.ts
24
- function generateJestSuite(options) {
25
- const caseBlocks = options.cases.map((testCase) => {
26
- const inputConst = serialize(testCase.input);
27
- const metadataConst = serialize(testCase.metadata ?? {});
28
- const successBlock = `const result = await ${options.runnerFunction}(input${testCase.id}, metadata${testCase.id});
29
- expect(result).toEqual(${serialize(testCase.expectedOutput ?? null)});`;
30
- const failureBlock = `await expect(${options.runnerFunction}(input${testCase.id}, metadata${testCase.id})).rejects.toMatchObject(${serialize(testCase.expectedError ?? { message: "expected failure" })});`;
31
- return `
32
- test('${testCase.name}', async () => {
33
- const input${testCase.id} = ${inputConst};
34
- const metadata${testCase.id} = ${metadataConst};
35
- ${testCase.success ? successBlock : failureBlock}
36
- });`;
37
- }).join(`
38
- `);
39
- return `
40
- import { ${options.runnerFunction} } from '${options.runnerImport}';
41
-
42
- describe('${options.suiteName}', () => {${caseBlocks}
13
+ describe('${e.suiteName}', () => {${r}
43
14
  });
44
- `.trim();
45
- }
46
- // src/adapters/vitest-adapter.ts
47
- function generateVitestSuite(options) {
48
- const caseBlocks = options.cases.map((testCase) => {
49
- const inputConst = serialize(testCase.input);
50
- const metadataConst = serialize(testCase.metadata ?? {});
51
- const assertions = testCase.success ? [
52
- `const result = await ${options.runnerFunction}(input${testCase.id}, metadata${testCase.id});`,
53
- `expect(result).toEqual(${serialize(testCase.expectedOutput ?? null)});`
54
- ] : [
55
- `await expect(${options.runnerFunction}(input${testCase.id}, metadata${testCase.id})).rejects.toMatchObject(${serialize(testCase.expectedError ?? { message: "expected failure" })});`
56
- ];
57
- return `
58
- it('${testCase.name}', async () => {
59
- const input${testCase.id} = ${inputConst};
60
- const metadata${testCase.id} = ${metadataConst};
61
- ${assertions.join(`
15
+ `.trim()}function d(e){let r=e.cases.map((t)=>{let n=s(t.input),i=s(t.metadata??{}),a=t.success?[`const result = await ${e.runnerFunction}(input${t.id}, metadata${t.id});`,`expect(result).toEqual(${s(t.expectedOutput??null)});`]:[`await expect(${e.runnerFunction}(input${t.id}, metadata${t.id})).rejects.toMatchObject(${s(t.expectedError??{message:"expected failure"})});`];return`
16
+ it('${t.name}', async () => {
17
+ const input${t.id} = ${n};
18
+ const metadata${t.id} = ${i};
19
+ ${a.join(`
62
20
  `)}
63
- });`;
64
- }).join(`
65
- `);
66
- return `
21
+ });`}).join(`
22
+ `);return`
67
23
  import { describe, it, expect } from 'bun:test';
68
- import { ${options.runnerFunction} } from '${options.runnerImport}';
24
+ import { ${e.runnerFunction} } from '${e.runnerImport}';
69
25
 
70
- describe('${options.suiteName}', () => {${caseBlocks}
26
+ describe('${e.suiteName}', () => {${r}
71
27
  });
72
- `.trim();
73
- }
74
- // src/generator/golden-test-generator.ts
75
- import { performance } from "perf_hooks";
76
- import { randomUUID } from "crypto";
77
- class GoldenTestGenerator {
78
- serializeMetadata;
79
- constructor(serializeMetadata = (snapshot) => ({
80
- tenantId: snapshot.tenantId,
81
- userId: snapshot.userId,
82
- channel: snapshot.channel
83
- })) {
84
- this.serializeMetadata = serializeMetadata;
85
- }
86
- createCases(snapshots) {
87
- return snapshots.map((snapshot, index) => ({
88
- id: snapshot.id ?? randomUUID(),
89
- name: snapshot.success ? `case-${index + 1}-success` : `case-${index + 1}-failure`,
90
- input: snapshot.input,
91
- expectedOutput: snapshot.output,
92
- expectedError: snapshot.error,
93
- success: snapshot.success,
94
- metadata: this.serializeMetadata?.(snapshot)
95
- }));
96
- }
97
- generate(snapshots, options) {
98
- const cases = this.createCases(snapshots);
99
- if (options.framework === "jest") {
100
- return generateJestSuite({
101
- suiteName: options.suiteName,
102
- cases,
103
- runnerImport: options.runnerImport,
104
- runnerFunction: options.runnerFunction
105
- });
106
- }
107
- return generateVitestSuite({
108
- suiteName: options.suiteName,
109
- cases,
110
- runnerImport: options.runnerImport,
111
- runnerFunction: options.runnerFunction
112
- });
113
- }
114
- }
115
- async function runGoldenTests(cases, runner) {
116
- const results = [];
117
- for (const testCase of cases) {
118
- const startedAt = performance.now();
119
- try {
120
- const output = await runner(testCase.input, testCase.metadata);
121
- if (!testCase.success) {
122
- results.push({
123
- caseId: testCase.id,
124
- passed: false,
125
- durationMs: performance.now() - startedAt,
126
- error: new Error("Expected failure but runner resolved")
127
- });
128
- continue;
129
- }
130
- const matches = JSON.stringify(output) === JSON.stringify(testCase.expectedOutput ?? null);
131
- results.push({
132
- caseId: testCase.id,
133
- passed: matches,
134
- durationMs: performance.now() - startedAt,
135
- error: matches ? undefined : { expected: testCase.expectedOutput, received: output }
136
- });
137
- } catch (error) {
138
- const durationMs = performance.now() - startedAt;
139
- if (!testCase.success) {
140
- results.push({ caseId: testCase.id, passed: true, durationMs });
141
- } else {
142
- results.push({ caseId: testCase.id, passed: false, durationMs, error });
143
- }
144
- }
145
- }
146
- return results;
147
- }
148
- // src/recorder/traffic-recorder.ts
149
- import { randomUUID as randomUUID2 } from "crypto";
150
-
151
- class InMemoryTrafficStore {
152
- items = [];
153
- async save(snapshot) {
154
- this.items.push(snapshot);
155
- }
156
- async list(operation) {
157
- if (!operation)
158
- return [...this.items];
159
- return this.items.filter((item) => item.operation.name === operation);
160
- }
161
- }
162
-
163
- class TrafficRecorder {
164
- store;
165
- sampleRate;
166
- sanitize;
167
- constructor(options) {
168
- this.store = options.store;
169
- this.sampleRate = options.sampleRate ?? 1;
170
- this.sanitize = options.sanitize;
171
- }
172
- async record(input) {
173
- if (!this.shouldSample())
174
- return;
175
- const snapshot = {
176
- id: randomUUID2(),
177
- operation: input.operation,
178
- input: structuredCloneSafe(input.input),
179
- output: structuredCloneSafe(input.output),
180
- error: input.error ? structuredCloneSafe(input.error) : undefined,
181
- success: input.success,
182
- timestamp: new Date,
183
- durationMs: input.durationMs,
184
- tenantId: input.tenantId,
185
- userId: input.userId,
186
- channel: input.channel,
187
- metadata: input.metadata
188
- };
189
- const sanitized = this.sanitize ? this.sanitize(snapshot) : snapshot;
190
- await this.store.save(sanitized);
191
- }
192
- shouldSample() {
193
- if (this.sampleRate >= 1)
194
- return true;
195
- return Math.random() <= this.sampleRate;
196
- }
197
- }
198
- function structuredCloneSafe(value) {
199
- if (value == null)
200
- return value ?? undefined;
201
- try {
202
- const clone = globalThis.structuredClone;
203
- if (typeof clone === "function") {
204
- return clone(value);
205
- }
206
- return JSON.parse(JSON.stringify(value));
207
- } catch {
208
- return;
209
- }
210
- }
211
- export {
212
- serialize,
213
- runGoldenTests,
214
- generateVitestSuite,
215
- generateJestSuite,
216
- buildAssertions,
217
- TrafficRecorder,
218
- InMemoryTrafficStore,
219
- GoldenTestGenerator
220
- };
28
+ `.trim()}import{performance as c}from"perf_hooks";import{randomUUID as m}from"crypto";class f{serializeMetadata;constructor(e=(r)=>({tenantId:r.tenantId,userId:r.userId,channel:r.channel})){this.serializeMetadata=e}createCases(e){return e.map((r,t)=>({id:r.id??m(),name:r.success?`case-${t+1}-success`:`case-${t+1}-failure`,input:r.input,expectedOutput:r.output,expectedError:r.error,success:r.success,metadata:this.serializeMetadata?.(r)}))}generate(e,r){let t=this.createCases(e);if(r.framework==="jest")return p({suiteName:r.suiteName,cases:t,runnerImport:r.runnerImport,runnerFunction:r.runnerFunction});return d({suiteName:r.suiteName,cases:t,runnerImport:r.runnerImport,runnerFunction:r.runnerFunction})}}async function G(e,r){let t=[];for(let n of e){let i=c.now();try{let a=await r(n.input,n.metadata);if(!n.success){t.push({caseId:n.id,passed:!1,durationMs:c.now()-i,error:Error("Expected failure but runner resolved")});continue}let o=JSON.stringify(a)===JSON.stringify(n.expectedOutput??null);t.push({caseId:n.id,passed:o,durationMs:c.now()-i,error:o?void 0:{expected:n.expectedOutput,received:a}})}catch(a){let o=c.now()-i;if(!n.success)t.push({caseId:n.id,passed:!0,durationMs:o});else t.push({caseId:n.id,passed:!1,durationMs:o,error:a})}}return t}import{randomUUID as l}from"crypto";class h{items=[];async save(e){this.items.push(e)}async list(e){if(!e)return[...this.items];return this.items.filter((r)=>r.operation.name===e)}}class g{store;sampleRate;sanitize;constructor(e){this.store=e.store,this.sampleRate=e.sampleRate??1,this.sanitize=e.sanitize}async record(e){if(!this.shouldSample())return;let r={id:l(),operation:e.operation,input:u(e.input),output:u(e.output),error:e.error?u(e.error):void 0,success:e.success,timestamp:new Date,durationMs:e.durationMs,tenantId:e.tenantId,userId:e.userId,channel:e.channel,metadata:e.metadata},t=this.sanitize?this.sanitize(r):r;await this.store.save(t)}shouldSample(){if(this.sampleRate>=1)return!0;return Math.random()<=this.sampleRate}}function u(e){if(e==null)return e??void 0;try{let r=globalThis.structuredClone;if(typeof r==="function")return r(e);return JSON.parse(JSON.stringify(e))}catch{return}}export{s as serialize,G as runGoldenTests,d as generateVitestSuite,p as generateJestSuite,T as buildAssertions,g as TrafficRecorder,h as InMemoryTrafficStore,f as GoldenTestGenerator};
@@ -1,219 +1,27 @@
1
- // src/generator/assertion-builder.ts
2
- function buildAssertions(testCase, ctx) {
3
- if (testCase.success) {
4
- return [
5
- `const result = await ${ctx.runnerCall};`,
6
- `expect(result).toEqual(${serialize(testCase.expectedOutput ?? null)});`
7
- ].join(`
8
- `);
9
- }
10
- return `await expect(${ctx.runnerCall}).rejects.toMatchObject(${serialize(testCase.expectedError ?? { message: "expected failure" })});`;
11
- }
12
- function serialize(value) {
13
- return JSON.stringify(value, (_key, val) => {
14
- if (val instanceof Date)
15
- return val.toISOString();
16
- if (typeof val === "undefined")
17
- return null;
18
- return val;
19
- }, 2);
20
- }
1
+ function T(e,r){if(e.success)return[`const result = await ${r.runnerCall};`,`expect(result).toEqual(${s(e.expectedOutput??null)});`].join(`
2
+ `);return`await expect(${r.runnerCall}).rejects.toMatchObject(${s(e.expectedError??{message:"expected failure"})});`}function s(e){return JSON.stringify(e,(r,t)=>{if(t instanceof Date)return t.toISOString();if(typeof t>"u")return null;return t},2)}function p(e){let r=e.cases.map((t)=>{let n=s(t.input),i=s(t.metadata??{}),a=`const result = await ${e.runnerFunction}(input${t.id}, metadata${t.id});
3
+ expect(result).toEqual(${s(t.expectedOutput??null)});`,o=`await expect(${e.runnerFunction}(input${t.id}, metadata${t.id})).rejects.toMatchObject(${s(t.expectedError??{message:"expected failure"})});`;return`
4
+ test('${t.name}', async () => {
5
+ const input${t.id} = ${n};
6
+ const metadata${t.id} = ${i};
7
+ ${t.success?a:o}
8
+ });`}).join(`
9
+ `);return`
10
+ import { ${e.runnerFunction} } from '${e.runnerImport}';
21
11
 
22
- // src/adapters/jest-adapter.ts
23
- function generateJestSuite(options) {
24
- const caseBlocks = options.cases.map((testCase) => {
25
- const inputConst = serialize(testCase.input);
26
- const metadataConst = serialize(testCase.metadata ?? {});
27
- const successBlock = `const result = await ${options.runnerFunction}(input${testCase.id}, metadata${testCase.id});
28
- expect(result).toEqual(${serialize(testCase.expectedOutput ?? null)});`;
29
- const failureBlock = `await expect(${options.runnerFunction}(input${testCase.id}, metadata${testCase.id})).rejects.toMatchObject(${serialize(testCase.expectedError ?? { message: "expected failure" })});`;
30
- return `
31
- test('${testCase.name}', async () => {
32
- const input${testCase.id} = ${inputConst};
33
- const metadata${testCase.id} = ${metadataConst};
34
- ${testCase.success ? successBlock : failureBlock}
35
- });`;
36
- }).join(`
37
- `);
38
- return `
39
- import { ${options.runnerFunction} } from '${options.runnerImport}';
40
-
41
- describe('${options.suiteName}', () => {${caseBlocks}
12
+ describe('${e.suiteName}', () => {${r}
42
13
  });
43
- `.trim();
44
- }
45
- // src/adapters/vitest-adapter.ts
46
- function generateVitestSuite(options) {
47
- const caseBlocks = options.cases.map((testCase) => {
48
- const inputConst = serialize(testCase.input);
49
- const metadataConst = serialize(testCase.metadata ?? {});
50
- const assertions = testCase.success ? [
51
- `const result = await ${options.runnerFunction}(input${testCase.id}, metadata${testCase.id});`,
52
- `expect(result).toEqual(${serialize(testCase.expectedOutput ?? null)});`
53
- ] : [
54
- `await expect(${options.runnerFunction}(input${testCase.id}, metadata${testCase.id})).rejects.toMatchObject(${serialize(testCase.expectedError ?? { message: "expected failure" })});`
55
- ];
56
- return `
57
- it('${testCase.name}', async () => {
58
- const input${testCase.id} = ${inputConst};
59
- const metadata${testCase.id} = ${metadataConst};
60
- ${assertions.join(`
14
+ `.trim()}function d(e){let r=e.cases.map((t)=>{let n=s(t.input),i=s(t.metadata??{}),a=t.success?[`const result = await ${e.runnerFunction}(input${t.id}, metadata${t.id});`,`expect(result).toEqual(${s(t.expectedOutput??null)});`]:[`await expect(${e.runnerFunction}(input${t.id}, metadata${t.id})).rejects.toMatchObject(${s(t.expectedError??{message:"expected failure"})});`];return`
15
+ it('${t.name}', async () => {
16
+ const input${t.id} = ${n};
17
+ const metadata${t.id} = ${i};
18
+ ${a.join(`
61
19
  `)}
62
- });`;
63
- }).join(`
64
- `);
65
- return `
20
+ });`}).join(`
21
+ `);return`
66
22
  import { describe, it, expect } from 'bun:test';
67
- import { ${options.runnerFunction} } from '${options.runnerImport}';
23
+ import { ${e.runnerFunction} } from '${e.runnerImport}';
68
24
 
69
- describe('${options.suiteName}', () => {${caseBlocks}
25
+ describe('${e.suiteName}', () => {${r}
70
26
  });
71
- `.trim();
72
- }
73
- // src/generator/golden-test-generator.ts
74
- import { performance } from "node:perf_hooks";
75
- import { randomUUID } from "crypto";
76
- class GoldenTestGenerator {
77
- serializeMetadata;
78
- constructor(serializeMetadata = (snapshot) => ({
79
- tenantId: snapshot.tenantId,
80
- userId: snapshot.userId,
81
- channel: snapshot.channel
82
- })) {
83
- this.serializeMetadata = serializeMetadata;
84
- }
85
- createCases(snapshots) {
86
- return snapshots.map((snapshot, index) => ({
87
- id: snapshot.id ?? randomUUID(),
88
- name: snapshot.success ? `case-${index + 1}-success` : `case-${index + 1}-failure`,
89
- input: snapshot.input,
90
- expectedOutput: snapshot.output,
91
- expectedError: snapshot.error,
92
- success: snapshot.success,
93
- metadata: this.serializeMetadata?.(snapshot)
94
- }));
95
- }
96
- generate(snapshots, options) {
97
- const cases = this.createCases(snapshots);
98
- if (options.framework === "jest") {
99
- return generateJestSuite({
100
- suiteName: options.suiteName,
101
- cases,
102
- runnerImport: options.runnerImport,
103
- runnerFunction: options.runnerFunction
104
- });
105
- }
106
- return generateVitestSuite({
107
- suiteName: options.suiteName,
108
- cases,
109
- runnerImport: options.runnerImport,
110
- runnerFunction: options.runnerFunction
111
- });
112
- }
113
- }
114
- async function runGoldenTests(cases, runner) {
115
- const results = [];
116
- for (const testCase of cases) {
117
- const startedAt = performance.now();
118
- try {
119
- const output = await runner(testCase.input, testCase.metadata);
120
- if (!testCase.success) {
121
- results.push({
122
- caseId: testCase.id,
123
- passed: false,
124
- durationMs: performance.now() - startedAt,
125
- error: new Error("Expected failure but runner resolved")
126
- });
127
- continue;
128
- }
129
- const matches = JSON.stringify(output) === JSON.stringify(testCase.expectedOutput ?? null);
130
- results.push({
131
- caseId: testCase.id,
132
- passed: matches,
133
- durationMs: performance.now() - startedAt,
134
- error: matches ? undefined : { expected: testCase.expectedOutput, received: output }
135
- });
136
- } catch (error) {
137
- const durationMs = performance.now() - startedAt;
138
- if (!testCase.success) {
139
- results.push({ caseId: testCase.id, passed: true, durationMs });
140
- } else {
141
- results.push({ caseId: testCase.id, passed: false, durationMs, error });
142
- }
143
- }
144
- }
145
- return results;
146
- }
147
- // src/recorder/traffic-recorder.ts
148
- import { randomUUID as randomUUID2 } from "crypto";
149
-
150
- class InMemoryTrafficStore {
151
- items = [];
152
- async save(snapshot) {
153
- this.items.push(snapshot);
154
- }
155
- async list(operation) {
156
- if (!operation)
157
- return [...this.items];
158
- return this.items.filter((item) => item.operation.name === operation);
159
- }
160
- }
161
-
162
- class TrafficRecorder {
163
- store;
164
- sampleRate;
165
- sanitize;
166
- constructor(options) {
167
- this.store = options.store;
168
- this.sampleRate = options.sampleRate ?? 1;
169
- this.sanitize = options.sanitize;
170
- }
171
- async record(input) {
172
- if (!this.shouldSample())
173
- return;
174
- const snapshot = {
175
- id: randomUUID2(),
176
- operation: input.operation,
177
- input: structuredCloneSafe(input.input),
178
- output: structuredCloneSafe(input.output),
179
- error: input.error ? structuredCloneSafe(input.error) : undefined,
180
- success: input.success,
181
- timestamp: new Date,
182
- durationMs: input.durationMs,
183
- tenantId: input.tenantId,
184
- userId: input.userId,
185
- channel: input.channel,
186
- metadata: input.metadata
187
- };
188
- const sanitized = this.sanitize ? this.sanitize(snapshot) : snapshot;
189
- await this.store.save(sanitized);
190
- }
191
- shouldSample() {
192
- if (this.sampleRate >= 1)
193
- return true;
194
- return Math.random() <= this.sampleRate;
195
- }
196
- }
197
- function structuredCloneSafe(value) {
198
- if (value == null)
199
- return value ?? undefined;
200
- try {
201
- const clone = globalThis.structuredClone;
202
- if (typeof clone === "function") {
203
- return clone(value);
204
- }
205
- return JSON.parse(JSON.stringify(value));
206
- } catch {
207
- return;
208
- }
209
- }
210
- export {
211
- serialize,
212
- runGoldenTests,
213
- generateVitestSuite,
214
- generateJestSuite,
215
- buildAssertions,
216
- TrafficRecorder,
217
- InMemoryTrafficStore,
218
- GoldenTestGenerator
219
- };
27
+ `.trim()}import{performance as c}from"node:perf_hooks";import{randomUUID as m}from"crypto";class f{serializeMetadata;constructor(e=(r)=>({tenantId:r.tenantId,userId:r.userId,channel:r.channel})){this.serializeMetadata=e}createCases(e){return e.map((r,t)=>({id:r.id??m(),name:r.success?`case-${t+1}-success`:`case-${t+1}-failure`,input:r.input,expectedOutput:r.output,expectedError:r.error,success:r.success,metadata:this.serializeMetadata?.(r)}))}generate(e,r){let t=this.createCases(e);if(r.framework==="jest")return p({suiteName:r.suiteName,cases:t,runnerImport:r.runnerImport,runnerFunction:r.runnerFunction});return d({suiteName:r.suiteName,cases:t,runnerImport:r.runnerImport,runnerFunction:r.runnerFunction})}}async function G(e,r){let t=[];for(let n of e){let i=c.now();try{let a=await r(n.input,n.metadata);if(!n.success){t.push({caseId:n.id,passed:!1,durationMs:c.now()-i,error:Error("Expected failure but runner resolved")});continue}let o=JSON.stringify(a)===JSON.stringify(n.expectedOutput??null);t.push({caseId:n.id,passed:o,durationMs:c.now()-i,error:o?void 0:{expected:n.expectedOutput,received:a}})}catch(a){let o=c.now()-i;if(!n.success)t.push({caseId:n.id,passed:!0,durationMs:o});else t.push({caseId:n.id,passed:!1,durationMs:o,error:a})}}return t}import{randomUUID as l}from"crypto";class h{items=[];async save(e){this.items.push(e)}async list(e){if(!e)return[...this.items];return this.items.filter((r)=>r.operation.name===e)}}class g{store;sampleRate;sanitize;constructor(e){this.store=e.store,this.sampleRate=e.sampleRate??1,this.sanitize=e.sanitize}async record(e){if(!this.shouldSample())return;let r={id:l(),operation:e.operation,input:u(e.input),output:u(e.output),error:e.error?u(e.error):void 0,success:e.success,timestamp:new Date,durationMs:e.durationMs,tenantId:e.tenantId,userId:e.userId,channel:e.channel,metadata:e.metadata},t=this.sanitize?this.sanitize(r):r;await this.store.save(t)}shouldSample(){if(this.sampleRate>=1)return!0;return Math.random()<=this.sampleRate}}function u(e){if(e==null)return e??void 0;try{let r=globalThis.structuredClone;if(typeof r==="function")return r(e);return JSON.parse(JSON.stringify(e))}catch{return}}export{s as serialize,G as runGoldenTests,d as generateVitestSuite,p as generateJestSuite,T as buildAssertions,g as TrafficRecorder,h as InMemoryTrafficStore,f as GoldenTestGenerator};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contractspec/lib.testing",
3
- "version": "3.7.16",
3
+ "version": "3.7.18",
4
4
  "description": "Contract-aware testing utilities and runners",
5
5
  "keywords": [
6
6
  "contractspec",
@@ -23,20 +23,20 @@
23
23
  "dev": "contractspec-bun-build dev",
24
24
  "clean": "rimraf dist .turbo",
25
25
  "lint": "bun lint:fix",
26
- "lint:fix": "biome check --write --unsafe --only=nursery/useSortedClasses . && biome check --write .",
27
- "lint:check": "biome check .",
26
+ "lint:fix": "node ../../../scripts/biome.cjs check --write --unsafe --only=nursery/useSortedClasses . && node ../../../scripts/biome.cjs check --write .",
27
+ "lint:check": "node ../../../scripts/biome.cjs check .",
28
28
  "test": "bun test",
29
29
  "prebuild": "contractspec-bun-build prebuild",
30
30
  "typecheck": "tsc --noEmit"
31
31
  },
32
32
  "dependencies": {
33
- "@contractspec/lib.schema": "3.7.13",
34
- "@contractspec/lib.contracts-spec": "5.0.4"
33
+ "@contractspec/lib.schema": "3.7.14",
34
+ "@contractspec/lib.contracts-spec": "5.2.0"
35
35
  },
36
36
  "devDependencies": {
37
- "@contractspec/tool.typescript": "3.7.12",
37
+ "@contractspec/tool.typescript": "3.7.13",
38
38
  "typescript": "^5.9.3",
39
- "@contractspec/tool.bun": "3.7.12"
39
+ "@contractspec/tool.bun": "3.7.14"
40
40
  },
41
41
  "exports": {
42
42
  ".": {