quidproquo-testing 0.1.11 → 0.1.12
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/lib/commonjs/generatorExpect.d.ts +3 -12
- package/lib/commonjs/generatorExpect.js +3 -23
- package/lib/commonjs/generatorExpect.js.map +1 -1
- package/lib/commonjs/index.js +2 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/vitestMatchers.d.ts +2 -5
- package/lib/commonjs/vitestMatchers.js +8 -5
- package/lib/commonjs/vitestMatchers.js.map +1 -1
- package/lib/esm/generatorExpect.d.ts +3 -12
- package/lib/esm/generatorExpect.js +5 -21
- package/lib/esm/generatorExpect.js.map +1 -1
- package/lib/esm/index.js +2 -3
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/vitestMatchers.d.ts +2 -5
- package/lib/esm/vitestMatchers.js +8 -4
- package/lib/esm/vitestMatchers.js.map +1 -1
- package/package.json +4 -3
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
type GeneratorStep = {
|
|
2
2
|
type: 'yield' | 'return';
|
|
3
3
|
value: any;
|
|
4
4
|
input?: any;
|
|
5
|
-
}
|
|
5
|
+
};
|
|
6
6
|
export declare class GeneratorExpectChain<T = any> {
|
|
7
7
|
private generator;
|
|
8
8
|
private steps;
|
|
@@ -20,15 +20,6 @@ export declare class GeneratorExpectChain<T = any> {
|
|
|
20
20
|
getSteps(): GeneratorStep[];
|
|
21
21
|
toMatchSnapshot(name?: string): void;
|
|
22
22
|
}
|
|
23
|
+
/** Drive a generator step by step, asserting each yielded action and the final return. */
|
|
23
24
|
export declare function expectGenerator<T>(gen: Generator<any, T, any>, expect?: any): GeneratorExpectChain<T>;
|
|
24
|
-
/**
|
|
25
|
-
* Helper to create a generator that returns immediately without yielding
|
|
26
|
-
* Useful for mocking sub-generators in tests
|
|
27
|
-
*/
|
|
28
|
-
export declare function mockGeneratorReturn<T>(value: T): Generator<any, T, any>;
|
|
29
|
-
/**
|
|
30
|
-
* Helper to create a generator that yields once then returns
|
|
31
|
-
* Useful for mocking sub-generators that need to yield an action
|
|
32
|
-
*/
|
|
33
|
-
export declare function mockGeneratorYieldReturn<Y, R>(yieldValue: Y, returnValue: R): Generator<Y, R, any>;
|
|
34
25
|
export {};
|
|
@@ -2,13 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GeneratorExpectChain = void 0;
|
|
4
4
|
exports.expectGenerator = expectGenerator;
|
|
5
|
-
exports.mockGeneratorReturn = mockGeneratorReturn;
|
|
6
|
-
exports.mockGeneratorYieldReturn = mockGeneratorYieldReturn;
|
|
7
5
|
class GeneratorExpectChain {
|
|
8
6
|
constructor(generator, expect) {
|
|
9
7
|
this.generator = generator;
|
|
10
8
|
this.steps = [];
|
|
11
|
-
// Use global expect if available, otherwise use provided expect
|
|
12
9
|
this.expect = expect || globalThis.expect;
|
|
13
10
|
if (!this.expect) {
|
|
14
11
|
throw new Error('expect function not found. Please ensure Vitest or another test framework is available.');
|
|
@@ -21,14 +18,15 @@ class GeneratorExpectChain {
|
|
|
21
18
|
this.steps.push({ type: 'yield', value });
|
|
22
19
|
return this;
|
|
23
20
|
}
|
|
21
|
+
// Alias of toYield kept for published-API compatibility.
|
|
24
22
|
toYieldAction(expected) {
|
|
25
23
|
return this.toYield(expected);
|
|
26
24
|
}
|
|
27
|
-
// Multiple name options for clarity in different contexts
|
|
28
25
|
whenGiven(input) {
|
|
29
26
|
this.lastInput = input;
|
|
30
27
|
return this;
|
|
31
28
|
}
|
|
29
|
+
// Aliases of whenGiven kept for published-API compatibility.
|
|
32
30
|
andReceive(input) {
|
|
33
31
|
return this.whenGiven(input);
|
|
34
32
|
}
|
|
@@ -64,26 +62,8 @@ class GeneratorExpectChain {
|
|
|
64
62
|
}
|
|
65
63
|
}
|
|
66
64
|
exports.GeneratorExpectChain = GeneratorExpectChain;
|
|
65
|
+
/** Drive a generator step by step, asserting each yielded action and the final return. */
|
|
67
66
|
function expectGenerator(gen, expect) {
|
|
68
67
|
return new GeneratorExpectChain(gen, expect);
|
|
69
68
|
}
|
|
70
|
-
/**
|
|
71
|
-
* Helper to create a generator that returns immediately without yielding
|
|
72
|
-
* Useful for mocking sub-generators in tests
|
|
73
|
-
*/
|
|
74
|
-
function mockGeneratorReturn(value) {
|
|
75
|
-
return (function* () {
|
|
76
|
-
return value;
|
|
77
|
-
})();
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Helper to create a generator that yields once then returns
|
|
81
|
-
* Useful for mocking sub-generators that need to yield an action
|
|
82
|
-
*/
|
|
83
|
-
function mockGeneratorYieldReturn(yieldValue, returnValue) {
|
|
84
|
-
return (function* () {
|
|
85
|
-
yield yieldValue;
|
|
86
|
-
return returnValue;
|
|
87
|
-
})();
|
|
88
|
-
}
|
|
89
69
|
//# sourceMappingURL=generatorExpect.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generatorExpect.js","sourceRoot":"","sources":["../../src/generatorExpect.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"generatorExpect.js","sourceRoot":"","sources":["../../src/generatorExpect.ts"],"names":[],"mappings":"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","sourcesContent":["type GeneratorStep = {\n type: 'yield' | 'return';\n value: any;\n input?: any;\n};\n\nexport class GeneratorExpectChain<T = any> {\n private steps: GeneratorStep[] = [];\n private lastInput: any;\n // `any` because this is the host test framework's expect function; typing it\n // would couple this framework-agnostic chain to vitest's types.\n private expect: any;\n\n constructor(\n private generator: Generator<any, any, any>,\n expect?: any,\n ) {\n this.expect = expect || (globalThis as any).expect;\n if (!this.expect) {\n throw new Error('expect function not found. Please ensure Vitest or another test framework is available.');\n }\n }\n\n toYield(expected: any): this {\n const { value, done } = this.generator.next();\n this.expect(done).toBe(false);\n this.expect(value).toEqual(expected);\n this.steps.push({ type: 'yield', value });\n return this;\n }\n\n // Alias of toYield kept for published-API compatibility.\n toYieldAction(expected: any): this {\n return this.toYield(expected);\n }\n\n whenGiven(input: any): this {\n this.lastInput = input;\n return this;\n }\n\n // Aliases of whenGiven kept for published-API compatibility.\n andReceive(input: any): this {\n return this.whenGiven(input);\n }\n\n withResponse(input: any): this {\n return this.whenGiven(input);\n }\n\n thenYield(expected: any): this {\n const { value, done } = this.generator.next(this.lastInput);\n this.expect(done).toBe(false);\n this.expect(value).toEqual(expected);\n this.steps.push({ type: 'yield', value, input: this.lastInput });\n this.lastInput = undefined;\n return this;\n }\n\n thenReturn(expected: any): void {\n const { value, done } = this.generator.next(this.lastInput);\n this.expect(done).toBe(true);\n this.expect(value).toStrictEqual(expected);\n this.steps.push({ type: 'return', value, input: this.lastInput });\n }\n\n // Alternative terminator that doesn't check the return value\n thenComplete(): void {\n const { done } = this.generator.next(this.lastInput);\n this.expect(done).toBe(true);\n }\n\n // For debugging - returns current execution steps\n getSteps(): GeneratorStep[] {\n return [...this.steps];\n }\n\n // Snapshot support for recording generator behavior\n toMatchSnapshot(name?: string): void {\n this.expect(this.steps).toMatchSnapshot(name);\n }\n}\n\n/** Drive a generator step by step, asserting each yielded action and the final return. */\nexport function expectGenerator<T>(gen: Generator<any, T, any>, expect?: any): GeneratorExpectChain<T> {\n return new GeneratorExpectChain(gen, expect);\n}\n"]}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -19,7 +19,6 @@ var generatorExpect_1 = require("./generatorExpect");
|
|
|
19
19
|
Object.defineProperty(exports, "expectGenerator", { enumerable: true, get: function () { return generatorExpect_1.expectGenerator; } });
|
|
20
20
|
Object.defineProperty(exports, "GeneratorExpectChain", { enumerable: true, get: function () { return generatorExpect_1.GeneratorExpectChain; } });
|
|
21
21
|
__exportStar(require("./types"), exports);
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
// We don't auto-import since not all users may be using Vitest
|
|
22
|
+
// The vitest matchers are NOT exported here: they register globally as a side
|
|
23
|
+
// effect, so vitest users opt in explicitly via `import 'quidproquo-testing/vitest'`.
|
|
25
24
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,qDAA0E;AAAjE,kHAAA,eAAe,OAAA;AAAE,uHAAA,oBAAoB,OAAA;AAC9C,0CAAwB;AAExB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,qDAA0E;AAAjE,kHAAA,eAAe,OAAA;AAAE,uHAAA,oBAAoB,OAAA;AAC9C,0CAAwB;AAExB,8EAA8E;AAC9E,sFAAsF","sourcesContent":["export { expectGenerator, GeneratorExpectChain } from './generatorExpect';\nexport * from './types';\n\n// The vitest matchers are NOT exported here: they register globally as a side\n// effect, so vitest users opt in explicitly via `import 'quidproquo-testing/vitest'`.\n"]}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
+
type GeneratorTestSequence = import('./types').GeneratorTestSequence;
|
|
1
2
|
interface CustomMatchers<R = unknown> {
|
|
2
3
|
toYieldValue(expected: any): R;
|
|
3
4
|
toCompleteWith(expected: any): R;
|
|
4
|
-
toYieldSequence(sequence:
|
|
5
|
-
yields?: any;
|
|
6
|
-
given?: any;
|
|
7
|
-
returns?: any;
|
|
8
|
-
}>): R;
|
|
5
|
+
toYieldSequence(sequence: GeneratorTestSequence): R;
|
|
9
6
|
}
|
|
10
7
|
declare module 'vitest' {
|
|
11
8
|
interface Assertion<T = any> extends CustomMatchers<T> {
|
|
@@ -44,12 +44,15 @@ if (typeof globalThis !== 'undefined' && globalThis.expect) {
|
|
|
44
44
|
};
|
|
45
45
|
},
|
|
46
46
|
toYieldSequence(received, sequence) {
|
|
47
|
-
var _a;
|
|
48
47
|
const results = [];
|
|
49
48
|
let currentStep = 0;
|
|
49
|
+
// A step's `given` is the input for the generator's NEXT resumption,
|
|
50
|
+
// whether that resumption is a `yields` or a `returns` step.
|
|
51
|
+
let pendingInput = undefined;
|
|
50
52
|
for (const step of sequence) {
|
|
51
53
|
if (step.yields !== undefined) {
|
|
52
|
-
const { value, done } = received.next();
|
|
54
|
+
const { value, done } = received.next(pendingInput);
|
|
55
|
+
pendingInput = undefined;
|
|
53
56
|
results.push({ step: currentStep, yielded: value, done });
|
|
54
57
|
if (done) {
|
|
55
58
|
return {
|
|
@@ -70,11 +73,11 @@ if (typeof globalThis !== 'undefined' && globalThis.expect) {
|
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
if (step.given !== undefined) {
|
|
73
|
-
|
|
76
|
+
pendingInput = step.given;
|
|
74
77
|
}
|
|
75
78
|
if (step.returns !== undefined) {
|
|
76
|
-
const
|
|
77
|
-
|
|
79
|
+
const { value, done } = received.next(pendingInput);
|
|
80
|
+
pendingInput = undefined;
|
|
78
81
|
results.push({ step: currentStep, returned: value, done });
|
|
79
82
|
if (!done) {
|
|
80
83
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitestMatchers.js","sourceRoot":"","sources":["../../src/vitestMatchers.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"vitestMatchers.js","sourceRoot":"","sources":["../../src/vitestMatchers.ts"],"names":[],"mappings":"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","sourcesContent":["// NO top-level imports here: they would make this file a module, turning the\n// `declare module 'vitest'` below into an augmentation that node10 module\n// resolution cannot resolve. The import() type syntax keeps it a script.\ntype GeneratorTestSequence = import('./types').GeneratorTestSequence;\n\n// Extend Vitest's expect with custom matchers for generators.\n// An interface (not a type) because it participates in declaration merging\n// with vitest's Assertion/AsymmetricMatchersContaining below.\ninterface CustomMatchers<R = unknown> {\n toYieldValue(expected: any): R;\n toCompleteWith(expected: any): R;\n toYieldSequence(sequence: GeneratorTestSequence): R;\n}\n\ndeclare module 'vitest' {\n interface Assertion<T = any> extends CustomMatchers<T> {}\n interface AsymmetricMatchersContaining extends CustomMatchers {}\n}\n\n// Only register matchers if expect is available\nif (typeof globalThis !== 'undefined' && (globalThis as any).expect) {\n const expect = (globalThis as any).expect;\n expect.extend({\n toYieldValue(received: Generator, expected: any) {\n const { value, done } = received.next();\n\n if (done) {\n return {\n pass: false,\n message: () => `Expected generator to yield a value, but it completed`,\n actual: { done: true, value },\n expected,\n };\n }\n\n const pass = this.equals(value, expected);\n return {\n pass,\n message: () =>\n pass\n ? `Expected generator not to yield ${this.utils.printExpected(expected)}`\n : `Expected generator to yield ${this.utils.printExpected(expected)}, but yielded ${this.utils.printReceived(value)}`,\n actual: value,\n expected,\n };\n },\n\n toCompleteWith(received: Generator, expected: any) {\n const { value, done } = received.next(expected);\n\n if (!done) {\n return {\n pass: false,\n message: () => `Expected generator to complete, but it yielded ${this.utils.printReceived(value)}`,\n actual: { done: false, value },\n expected: { done: true, value: expected },\n };\n }\n\n const pass = value === expected;\n return {\n pass,\n message: () =>\n pass\n ? `Expected generator not to return ${this.utils.printExpected(expected)}`\n : `Expected generator to return ${this.utils.printExpected(expected)}, but returned ${this.utils.printReceived(value)}`,\n actual: value,\n expected,\n };\n },\n\n toYieldSequence(received: Generator, sequence: GeneratorTestSequence) {\n const results: any[] = [];\n let currentStep = 0;\n // A step's `given` is the input for the generator's NEXT resumption,\n // whether that resumption is a `yields` or a `returns` step.\n let pendingInput: any = undefined;\n\n for (const step of sequence) {\n if (step.yields !== undefined) {\n const { value, done } = received.next(pendingInput);\n pendingInput = undefined;\n results.push({ step: currentStep, yielded: value, done });\n\n if (done) {\n return {\n pass: false,\n message: () => `Expected generator to yield at step ${currentStep}, but it completed`,\n actual: results,\n expected: sequence,\n };\n }\n\n if (!this.equals(value, step.yields)) {\n return {\n pass: false,\n message: () =>\n `At step ${currentStep}: expected to yield ${this.utils.printExpected(step.yields)}, ` +\n `but yielded ${this.utils.printReceived(value)}`,\n actual: value,\n expected: step.yields,\n };\n }\n }\n\n if (step.given !== undefined) {\n pendingInput = step.given;\n }\n\n if (step.returns !== undefined) {\n const { value, done } = received.next(pendingInput);\n pendingInput = undefined;\n results.push({ step: currentStep, returned: value, done });\n\n if (!done) {\n return {\n pass: false,\n message: () => `Expected generator to complete at step ${currentStep}, but it yielded`,\n actual: results,\n expected: sequence,\n };\n }\n\n if (!this.equals(value, step.returns)) {\n return {\n pass: false,\n message: () =>\n `At step ${currentStep}: expected to return ${this.utils.printExpected(step.returns)}, ` +\n `but returned ${this.utils.printReceived(value)}`,\n actual: value,\n expected: step.returns,\n };\n }\n }\n\n currentStep++;\n }\n\n return {\n pass: true,\n message: () => `Expected generator not to match sequence`,\n actual: results,\n expected: sequence,\n };\n },\n });\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
type GeneratorStep = {
|
|
2
2
|
type: 'yield' | 'return';
|
|
3
3
|
value: any;
|
|
4
4
|
input?: any;
|
|
5
|
-
}
|
|
5
|
+
};
|
|
6
6
|
export declare class GeneratorExpectChain<T = any> {
|
|
7
7
|
private generator;
|
|
8
8
|
private steps;
|
|
@@ -20,15 +20,6 @@ export declare class GeneratorExpectChain<T = any> {
|
|
|
20
20
|
getSteps(): GeneratorStep[];
|
|
21
21
|
toMatchSnapshot(name?: string): void;
|
|
22
22
|
}
|
|
23
|
+
/** Drive a generator step by step, asserting each yielded action and the final return. */
|
|
23
24
|
export declare function expectGenerator<T>(gen: Generator<any, T, any>, expect?: any): GeneratorExpectChain<T>;
|
|
24
|
-
/**
|
|
25
|
-
* Helper to create a generator that returns immediately without yielding
|
|
26
|
-
* Useful for mocking sub-generators in tests
|
|
27
|
-
*/
|
|
28
|
-
export declare function mockGeneratorReturn<T>(value: T): Generator<any, T, any>;
|
|
29
|
-
/**
|
|
30
|
-
* Helper to create a generator that yields once then returns
|
|
31
|
-
* Useful for mocking sub-generators that need to yield an action
|
|
32
|
-
*/
|
|
33
|
-
export declare function mockGeneratorYieldReturn<Y, R>(yieldValue: Y, returnValue: R): Generator<Y, R, any>;
|
|
34
25
|
export {};
|
|
@@ -2,10 +2,11 @@ export class GeneratorExpectChain {
|
|
|
2
2
|
generator;
|
|
3
3
|
steps = [];
|
|
4
4
|
lastInput;
|
|
5
|
+
// `any` because this is the host test framework's expect function; typing it
|
|
6
|
+
// would couple this framework-agnostic chain to vitest's types.
|
|
5
7
|
expect;
|
|
6
8
|
constructor(generator, expect) {
|
|
7
9
|
this.generator = generator;
|
|
8
|
-
// Use global expect if available, otherwise use provided expect
|
|
9
10
|
this.expect = expect || globalThis.expect;
|
|
10
11
|
if (!this.expect) {
|
|
11
12
|
throw new Error('expect function not found. Please ensure Vitest or another test framework is available.');
|
|
@@ -18,14 +19,15 @@ export class GeneratorExpectChain {
|
|
|
18
19
|
this.steps.push({ type: 'yield', value });
|
|
19
20
|
return this;
|
|
20
21
|
}
|
|
22
|
+
// Alias of toYield kept for published-API compatibility.
|
|
21
23
|
toYieldAction(expected) {
|
|
22
24
|
return this.toYield(expected);
|
|
23
25
|
}
|
|
24
|
-
// Multiple name options for clarity in different contexts
|
|
25
26
|
whenGiven(input) {
|
|
26
27
|
this.lastInput = input;
|
|
27
28
|
return this;
|
|
28
29
|
}
|
|
30
|
+
// Aliases of whenGiven kept for published-API compatibility.
|
|
29
31
|
andReceive(input) {
|
|
30
32
|
return this.whenGiven(input);
|
|
31
33
|
}
|
|
@@ -60,26 +62,8 @@ export class GeneratorExpectChain {
|
|
|
60
62
|
this.expect(this.steps).toMatchSnapshot(name);
|
|
61
63
|
}
|
|
62
64
|
}
|
|
65
|
+
/** Drive a generator step by step, asserting each yielded action and the final return. */
|
|
63
66
|
export function expectGenerator(gen, expect) {
|
|
64
67
|
return new GeneratorExpectChain(gen, expect);
|
|
65
68
|
}
|
|
66
|
-
/**
|
|
67
|
-
* Helper to create a generator that returns immediately without yielding
|
|
68
|
-
* Useful for mocking sub-generators in tests
|
|
69
|
-
*/
|
|
70
|
-
export function mockGeneratorReturn(value) {
|
|
71
|
-
return (function* () {
|
|
72
|
-
return value;
|
|
73
|
-
})();
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Helper to create a generator that yields once then returns
|
|
77
|
-
* Useful for mocking sub-generators that need to yield an action
|
|
78
|
-
*/
|
|
79
|
-
export function mockGeneratorYieldReturn(yieldValue, returnValue) {
|
|
80
|
-
return (function* () {
|
|
81
|
-
yield yieldValue;
|
|
82
|
-
return returnValue;
|
|
83
|
-
})();
|
|
84
|
-
}
|
|
85
69
|
//# sourceMappingURL=generatorExpect.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generatorExpect.js","sourceRoot":"","sources":["../../src/generatorExpect.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,oBAAoB;
|
|
1
|
+
{"version":3,"file":"generatorExpect.js","sourceRoot":"","sources":["../../src/generatorExpect.ts"],"names":[],"mappings":"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","sourcesContent":["type GeneratorStep = {\n type: 'yield' | 'return';\n value: any;\n input?: any;\n};\n\nexport class GeneratorExpectChain<T = any> {\n private steps: GeneratorStep[] = [];\n private lastInput: any;\n // `any` because this is the host test framework's expect function; typing it\n // would couple this framework-agnostic chain to vitest's types.\n private expect: any;\n\n constructor(\n private generator: Generator<any, any, any>,\n expect?: any,\n ) {\n this.expect = expect || (globalThis as any).expect;\n if (!this.expect) {\n throw new Error('expect function not found. Please ensure Vitest or another test framework is available.');\n }\n }\n\n toYield(expected: any): this {\n const { value, done } = this.generator.next();\n this.expect(done).toBe(false);\n this.expect(value).toEqual(expected);\n this.steps.push({ type: 'yield', value });\n return this;\n }\n\n // Alias of toYield kept for published-API compatibility.\n toYieldAction(expected: any): this {\n return this.toYield(expected);\n }\n\n whenGiven(input: any): this {\n this.lastInput = input;\n return this;\n }\n\n // Aliases of whenGiven kept for published-API compatibility.\n andReceive(input: any): this {\n return this.whenGiven(input);\n }\n\n withResponse(input: any): this {\n return this.whenGiven(input);\n }\n\n thenYield(expected: any): this {\n const { value, done } = this.generator.next(this.lastInput);\n this.expect(done).toBe(false);\n this.expect(value).toEqual(expected);\n this.steps.push({ type: 'yield', value, input: this.lastInput });\n this.lastInput = undefined;\n return this;\n }\n\n thenReturn(expected: any): void {\n const { value, done } = this.generator.next(this.lastInput);\n this.expect(done).toBe(true);\n this.expect(value).toStrictEqual(expected);\n this.steps.push({ type: 'return', value, input: this.lastInput });\n }\n\n // Alternative terminator that doesn't check the return value\n thenComplete(): void {\n const { done } = this.generator.next(this.lastInput);\n this.expect(done).toBe(true);\n }\n\n // For debugging - returns current execution steps\n getSteps(): GeneratorStep[] {\n return [...this.steps];\n }\n\n // Snapshot support for recording generator behavior\n toMatchSnapshot(name?: string): void {\n this.expect(this.steps).toMatchSnapshot(name);\n }\n}\n\n/** Drive a generator step by step, asserting each yielded action and the final return. */\nexport function expectGenerator<T>(gen: Generator<any, T, any>, expect?: any): GeneratorExpectChain<T> {\n return new GeneratorExpectChain(gen, expect);\n}\n"]}
|
package/lib/esm/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { expectGenerator, GeneratorExpectChain } from './generatorExpect';
|
|
2
2
|
export * from './types';
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// We don't auto-import since not all users may be using Vitest
|
|
3
|
+
// The vitest matchers are NOT exported here: they register globally as a side
|
|
4
|
+
// effect, so vitest users opt in explicitly via `import 'quidproquo-testing/vitest'`.
|
|
6
5
|
//# sourceMappingURL=index.js.map
|
package/lib/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC1E,cAAc,SAAS,CAAC;AAExB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC1E,cAAc,SAAS,CAAC;AAExB,8EAA8E;AAC9E,sFAAsF","sourcesContent":["export { expectGenerator, GeneratorExpectChain } from './generatorExpect';\nexport * from './types';\n\n// The vitest matchers are NOT exported here: they register globally as a side\n// effect, so vitest users opt in explicitly via `import 'quidproquo-testing/vitest'`.\n"]}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
+
type GeneratorTestSequence = import('./types').GeneratorTestSequence;
|
|
1
2
|
interface CustomMatchers<R = unknown> {
|
|
2
3
|
toYieldValue(expected: any): R;
|
|
3
4
|
toCompleteWith(expected: any): R;
|
|
4
|
-
toYieldSequence(sequence:
|
|
5
|
-
yields?: any;
|
|
6
|
-
given?: any;
|
|
7
|
-
returns?: any;
|
|
8
|
-
}>): R;
|
|
5
|
+
toYieldSequence(sequence: GeneratorTestSequence): R;
|
|
9
6
|
}
|
|
10
7
|
declare module 'vitest' {
|
|
11
8
|
interface Assertion<T = any> extends CustomMatchers<T> {
|
|
@@ -46,9 +46,13 @@ if (typeof globalThis !== 'undefined' && globalThis.expect) {
|
|
|
46
46
|
toYieldSequence(received, sequence) {
|
|
47
47
|
const results = [];
|
|
48
48
|
let currentStep = 0;
|
|
49
|
+
// A step's `given` is the input for the generator's NEXT resumption,
|
|
50
|
+
// whether that resumption is a `yields` or a `returns` step.
|
|
51
|
+
let pendingInput = undefined;
|
|
49
52
|
for (const step of sequence) {
|
|
50
53
|
if (step.yields !== undefined) {
|
|
51
|
-
const { value, done } = received.next();
|
|
54
|
+
const { value, done } = received.next(pendingInput);
|
|
55
|
+
pendingInput = undefined;
|
|
52
56
|
results.push({ step: currentStep, yielded: value, done });
|
|
53
57
|
if (done) {
|
|
54
58
|
return {
|
|
@@ -69,11 +73,11 @@ if (typeof globalThis !== 'undefined' && globalThis.expect) {
|
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
75
|
if (step.given !== undefined) {
|
|
72
|
-
|
|
76
|
+
pendingInput = step.given;
|
|
73
77
|
}
|
|
74
78
|
if (step.returns !== undefined) {
|
|
75
|
-
const
|
|
76
|
-
|
|
79
|
+
const { value, done } = received.next(pendingInput);
|
|
80
|
+
pendingInput = undefined;
|
|
77
81
|
results.push({ step: currentStep, returned: value, done });
|
|
78
82
|
if (!done) {
|
|
79
83
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitestMatchers.js","sourceRoot":"","sources":["../../src/vitestMatchers.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"vitestMatchers.js","sourceRoot":"","sources":["../../src/vitestMatchers.ts"],"names":[],"mappings":"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","sourcesContent":["// NO top-level imports here: they would make this file a module, turning the\n// `declare module 'vitest'` below into an augmentation that node10 module\n// resolution cannot resolve. The import() type syntax keeps it a script.\ntype GeneratorTestSequence = import('./types').GeneratorTestSequence;\n\n// Extend Vitest's expect with custom matchers for generators.\n// An interface (not a type) because it participates in declaration merging\n// with vitest's Assertion/AsymmetricMatchersContaining below.\ninterface CustomMatchers<R = unknown> {\n toYieldValue(expected: any): R;\n toCompleteWith(expected: any): R;\n toYieldSequence(sequence: GeneratorTestSequence): R;\n}\n\ndeclare module 'vitest' {\n interface Assertion<T = any> extends CustomMatchers<T> {}\n interface AsymmetricMatchersContaining extends CustomMatchers {}\n}\n\n// Only register matchers if expect is available\nif (typeof globalThis !== 'undefined' && (globalThis as any).expect) {\n const expect = (globalThis as any).expect;\n expect.extend({\n toYieldValue(received: Generator, expected: any) {\n const { value, done } = received.next();\n\n if (done) {\n return {\n pass: false,\n message: () => `Expected generator to yield a value, but it completed`,\n actual: { done: true, value },\n expected,\n };\n }\n\n const pass = this.equals(value, expected);\n return {\n pass,\n message: () =>\n pass\n ? `Expected generator not to yield ${this.utils.printExpected(expected)}`\n : `Expected generator to yield ${this.utils.printExpected(expected)}, but yielded ${this.utils.printReceived(value)}`,\n actual: value,\n expected,\n };\n },\n\n toCompleteWith(received: Generator, expected: any) {\n const { value, done } = received.next(expected);\n\n if (!done) {\n return {\n pass: false,\n message: () => `Expected generator to complete, but it yielded ${this.utils.printReceived(value)}`,\n actual: { done: false, value },\n expected: { done: true, value: expected },\n };\n }\n\n const pass = value === expected;\n return {\n pass,\n message: () =>\n pass\n ? `Expected generator not to return ${this.utils.printExpected(expected)}`\n : `Expected generator to return ${this.utils.printExpected(expected)}, but returned ${this.utils.printReceived(value)}`,\n actual: value,\n expected,\n };\n },\n\n toYieldSequence(received: Generator, sequence: GeneratorTestSequence) {\n const results: any[] = [];\n let currentStep = 0;\n // A step's `given` is the input for the generator's NEXT resumption,\n // whether that resumption is a `yields` or a `returns` step.\n let pendingInput: any = undefined;\n\n for (const step of sequence) {\n if (step.yields !== undefined) {\n const { value, done } = received.next(pendingInput);\n pendingInput = undefined;\n results.push({ step: currentStep, yielded: value, done });\n\n if (done) {\n return {\n pass: false,\n message: () => `Expected generator to yield at step ${currentStep}, but it completed`,\n actual: results,\n expected: sequence,\n };\n }\n\n if (!this.equals(value, step.yields)) {\n return {\n pass: false,\n message: () =>\n `At step ${currentStep}: expected to yield ${this.utils.printExpected(step.yields)}, ` +\n `but yielded ${this.utils.printReceived(value)}`,\n actual: value,\n expected: step.yields,\n };\n }\n }\n\n if (step.given !== undefined) {\n pendingInput = step.given;\n }\n\n if (step.returns !== undefined) {\n const { value, done } = received.next(pendingInput);\n pendingInput = undefined;\n results.push({ step: currentStep, returned: value, done });\n\n if (!done) {\n return {\n pass: false,\n message: () => `Expected generator to complete at step ${currentStep}, but it yielded`,\n actual: results,\n expected: sequence,\n };\n }\n\n if (!this.equals(value, step.returns)) {\n return {\n pass: false,\n message: () =>\n `At step ${currentStep}: expected to return ${this.utils.printExpected(step.returns)}, ` +\n `but returned ${this.utils.printReceived(value)}`,\n actual: value,\n expected: step.returns,\n };\n }\n }\n\n currentStep++;\n }\n\n return {\n pass: true,\n message: () => `Expected generator not to match sequence`,\n actual: results,\n expected: sequence,\n };\n },\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quidproquo-testing",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/commonjs/index.js",
|
|
6
6
|
"module": "./lib/esm/index.js",
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"lib/**/*"
|
|
23
23
|
],
|
|
24
24
|
"scripts": {
|
|
25
|
-
"test": "
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"test:watch": "vitest",
|
|
26
27
|
"clean": "npx rimraf lib && npx rimraf node_modules",
|
|
27
28
|
"build": "npm run clean && npm run build:esm && npm run build:cjs",
|
|
28
29
|
"watch": "tsc -p tsconfig.esm.json -w",
|
|
@@ -44,7 +45,7 @@
|
|
|
44
45
|
},
|
|
45
46
|
"homepage": "https://github.com/joe-coady/quidproquo#readme",
|
|
46
47
|
"devDependencies": {
|
|
47
|
-
"quidproquo-tsconfig": "0.1.
|
|
48
|
+
"quidproquo-tsconfig": "0.1.12",
|
|
48
49
|
"typescript": "^5.8.2",
|
|
49
50
|
"vitest": "^3.2.4"
|
|
50
51
|
},
|