test-fns 1.7.2 → 1.9.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/contract/index.d.ts +10 -0
- package/dist/contract/index.js +27 -0
- package/dist/contract/index.js.map +1 -0
- package/dist/contract/vitest.setup.d.ts +48 -0
- package/dist/contract/vitest.setup.js +23 -0
- package/dist/contract/vitest.setup.js.map +1 -0
- package/dist/domain.operations/genTestUuid.js.map +1 -0
- package/dist/{givenWhenThen.d.ts → domain.operations/givenWhenThen.d.ts} +44 -6
- package/dist/domain.operations/givenWhenThen.js +143 -0
- package/dist/domain.operations/givenWhenThen.js.map +1 -0
- package/dist/{usePrep.d.ts → domain.operations/usePrep.d.ts} +1 -1
- package/dist/{usePrep.js → domain.operations/usePrep.js} +3 -2
- package/dist/domain.operations/usePrep.js.map +1 -0
- package/dist/domain.operations/useThen.d.ts +17 -0
- package/dist/domain.operations/useThen.js +54 -0
- package/dist/domain.operations/useThen.js.map +1 -0
- package/dist/domain.operations/useWhen.d.ts +18 -0
- package/dist/domain.operations/useWhen.js +30 -0
- package/dist/domain.operations/useWhen.js.map +1 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +19 -14
- package/dist/index.js.map +1 -1
- package/dist/infra/isomorph.test/detectTestRunner.d.ts +18 -0
- package/dist/infra/isomorph.test/detectTestRunner.js +50 -0
- package/dist/infra/isomorph.test/detectTestRunner.js.map +1 -0
- package/dist/infra/isomorph.test/getTestGlobals.d.ts +28 -0
- package/dist/infra/isomorph.test/getTestGlobals.js +56 -0
- package/dist/infra/isomorph.test/getTestGlobals.js.map +1 -0
- package/dist/infra/isomorph.test/runTest.d.ts +43 -0
- package/dist/infra/isomorph.test/runTest.js +79 -0
- package/dist/infra/isomorph.test/runTest.js.map +1 -0
- package/package.json +63 -42
- package/readme.md +224 -60
- package/dist/genTestUuid.js.map +0 -1
- package/dist/genTestUuid.test.d.ts +0 -1
- package/dist/genTestUuid.test.js +0 -20
- package/dist/genTestUuid.test.js.map +0 -1
- package/dist/givenWhenThen.js +0 -77
- package/dist/givenWhenThen.js.map +0 -1
- package/dist/givenWhenThen.test.d.ts +0 -1
- package/dist/givenWhenThen.test.js +0 -74
- package/dist/givenWhenThen.test.js.map +0 -1
- package/dist/usePrep.js.map +0 -1
- package/dist/usePrep.test.d.ts +0 -1
- package/dist/usePrep.test.js +0 -63
- package/dist/usePrep.test.js.map +0 -1
- /package/dist/{genTestUuid.d.ts → domain.operations/genTestUuid.d.ts} +0 -0
- /package/dist/{genTestUuid.js → domain.operations/genTestUuid.js} +0 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .what = public contract for test-fns library
|
|
3
|
+
* .why = provides the stable public API surface, re-exports from domain.operations
|
|
4
|
+
*/
|
|
5
|
+
export { getError } from 'helpful-errors';
|
|
6
|
+
export { genTestUuid } from '../domain.operations/genTestUuid';
|
|
7
|
+
export { bdd, given, then, when } from '../domain.operations/givenWhenThen';
|
|
8
|
+
export { useBeforeAll, useBeforeEach, usePrep, } from '../domain.operations/usePrep';
|
|
9
|
+
export { useThen } from '../domain.operations/useThen';
|
|
10
|
+
export { useWhen } from '../domain.operations/useWhen';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* .what = public contract for test-fns library
|
|
4
|
+
* .why = provides the stable public API surface, re-exports from domain.operations
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.useWhen = exports.useThen = exports.usePrep = exports.useBeforeEach = exports.useBeforeAll = exports.when = exports.then = exports.given = exports.bdd = exports.genTestUuid = exports.getError = void 0;
|
|
8
|
+
// forward the getError method since it is almost always needed with tests
|
|
9
|
+
var helpful_errors_1 = require("helpful-errors");
|
|
10
|
+
Object.defineProperty(exports, "getError", { enumerable: true, get: function () { return helpful_errors_1.getError; } });
|
|
11
|
+
// test utilities
|
|
12
|
+
var genTestUuid_1 = require("../domain.operations/genTestUuid");
|
|
13
|
+
Object.defineProperty(exports, "genTestUuid", { enumerable: true, get: function () { return genTestUuid_1.genTestUuid; } });
|
|
14
|
+
var givenWhenThen_1 = require("../domain.operations/givenWhenThen");
|
|
15
|
+
Object.defineProperty(exports, "bdd", { enumerable: true, get: function () { return givenWhenThen_1.bdd; } });
|
|
16
|
+
Object.defineProperty(exports, "given", { enumerable: true, get: function () { return givenWhenThen_1.given; } });
|
|
17
|
+
Object.defineProperty(exports, "then", { enumerable: true, get: function () { return givenWhenThen_1.then; } });
|
|
18
|
+
Object.defineProperty(exports, "when", { enumerable: true, get: function () { return givenWhenThen_1.when; } });
|
|
19
|
+
var usePrep_1 = require("../domain.operations/usePrep");
|
|
20
|
+
Object.defineProperty(exports, "useBeforeAll", { enumerable: true, get: function () { return usePrep_1.useBeforeAll; } });
|
|
21
|
+
Object.defineProperty(exports, "useBeforeEach", { enumerable: true, get: function () { return usePrep_1.useBeforeEach; } });
|
|
22
|
+
Object.defineProperty(exports, "usePrep", { enumerable: true, get: function () { return usePrep_1.usePrep; } });
|
|
23
|
+
var useThen_1 = require("../domain.operations/useThen");
|
|
24
|
+
Object.defineProperty(exports, "useThen", { enumerable: true, get: function () { return useThen_1.useThen; } });
|
|
25
|
+
var useWhen_1 = require("../domain.operations/useWhen");
|
|
26
|
+
Object.defineProperty(exports, "useWhen", { enumerable: true, get: function () { return useWhen_1.useWhen; } });
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/contract/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,0EAA0E;AAC1E,iDAA0C;AAAjC,0GAAA,QAAQ,OAAA;AAEjB,iBAAiB;AACjB,kEAAiE;AAAxD,0GAAA,WAAW,OAAA;AACpB,sEAA8E;AAArE,oGAAA,GAAG,OAAA;AAAE,sGAAA,KAAK,OAAA;AAAE,qGAAA,IAAI,OAAA;AAAE,qGAAA,IAAI,OAAA;AAC/B,0DAIwC;AAHtC,uGAAA,YAAY,OAAA;AACZ,wGAAA,aAAa,OAAA;AACb,kGAAA,OAAO,OAAA;AAET,0DAAyD;AAAhD,kGAAA,OAAO,OAAA;AAChB,0DAAyD;AAAhD,kGAAA,OAAO,OAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .what = vitest setup file to register BDD globals
|
|
3
|
+
* .why = direct `import { then }` triggers ESM thenable detection in vitest.
|
|
4
|
+
* this setup file registers given/when/then as globals via the `bdd` namespace,
|
|
5
|
+
* which bypasses thenable detection since `bdd` has no top-level `then`.
|
|
6
|
+
*
|
|
7
|
+
* .usage = add to vitest.config.ts:
|
|
8
|
+
* export default defineConfig({
|
|
9
|
+
* test: {
|
|
10
|
+
* setupFiles: ['test-fns/vitest.setup'],
|
|
11
|
+
* },
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* @see .agent/repo=.this/role=any/briefs/limitation.esm-thenable-then-export.md
|
|
15
|
+
*/
|
|
16
|
+
import { bdd } from './index';
|
|
17
|
+
declare global {
|
|
18
|
+
/**
|
|
19
|
+
* describe the scene (initial state or context) for a group of tests
|
|
20
|
+
* @example
|
|
21
|
+
* given('a dry plant', () => {
|
|
22
|
+
* when('water needs are checked', () => {
|
|
23
|
+
* then('it should return true', () => {
|
|
24
|
+
* expect(doesPlantNeedWater(plant)).toBe(true);
|
|
25
|
+
* });
|
|
26
|
+
* });
|
|
27
|
+
* });
|
|
28
|
+
*/
|
|
29
|
+
var given: typeof bdd.given;
|
|
30
|
+
/**
|
|
31
|
+
* describe the event (action or trigger) that occurs within a scene
|
|
32
|
+
* @example
|
|
33
|
+
* when('the user clicks submit', () => {
|
|
34
|
+
* then('the form should be submitted', () => {
|
|
35
|
+
* expect(form.submitted).toBe(true);
|
|
36
|
+
* });
|
|
37
|
+
* });
|
|
38
|
+
*/
|
|
39
|
+
var when: typeof bdd.when;
|
|
40
|
+
/**
|
|
41
|
+
* assert the effect (expected outcome) that should be observed
|
|
42
|
+
* @example
|
|
43
|
+
* then('it should return the correct value', () => {
|
|
44
|
+
* expect(result).toBe(expected);
|
|
45
|
+
* });
|
|
46
|
+
*/
|
|
47
|
+
var then: typeof bdd.then;
|
|
48
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* .what = vitest setup file to register BDD globals
|
|
5
|
+
* .why = direct `import { then }` triggers ESM thenable detection in vitest.
|
|
6
|
+
* this setup file registers given/when/then as globals via the `bdd` namespace,
|
|
7
|
+
* which bypasses thenable detection since `bdd` has no top-level `then`.
|
|
8
|
+
*
|
|
9
|
+
* .usage = add to vitest.config.ts:
|
|
10
|
+
* export default defineConfig({
|
|
11
|
+
* test: {
|
|
12
|
+
* setupFiles: ['test-fns/vitest.setup'],
|
|
13
|
+
* },
|
|
14
|
+
* });
|
|
15
|
+
*
|
|
16
|
+
* @see .agent/repo=.this/role=any/briefs/limitation.esm-thenable-then-export.md
|
|
17
|
+
*/
|
|
18
|
+
const index_1 = require("./index");
|
|
19
|
+
// register BDD helpers as globals
|
|
20
|
+
globalThis.given = index_1.bdd.given;
|
|
21
|
+
globalThis.when = index_1.bdd.when;
|
|
22
|
+
globalThis.then = index_1.bdd.then;
|
|
23
|
+
//# sourceMappingURL=vitest.setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest.setup.js","sourceRoot":"","sources":["../../src/contract/vitest.setup.ts"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;GAcG;AACH,mCAA8B;AAsC9B,kCAAkC;AAClC,UAAU,CAAC,KAAK,GAAG,WAAG,CAAC,KAAK,CAAC;AAC7B,UAAU,CAAC,IAAI,GAAG,WAAG,CAAC,IAAI,CAAC;AAC3B,UAAU,CAAC,IAAI,GAAG,WAAG,CAAC,IAAI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"genTestUuid.js","sourceRoot":"","sources":["../../src/domain.operations/genTestUuid.ts"],"names":[],"mappings":";;;AAAA,+BAAkC;AAElC;;;;;GAKG;AACI,MAAM,WAAW,GAAG,GAAW,EAAE;IACtC,OAAO,CAAC,MAAM,EAAE,IAAA,SAAI,GAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC,CAAC;AAFW,QAAA,WAAW,eAEtB;AAEF;;GAEG;AACI,MAAM,UAAU,GAAG,CAAC,QAAgB,EAAW,EAAE,CACtD,oCAAoC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AADzC,QAAA,UAAU,cAC+B"}
|
|
@@ -16,9 +16,9 @@ interface Describe {
|
|
|
16
16
|
(desc: string, fn: () => void): void;
|
|
17
17
|
/** Only runs the tests inside this `describe` for the current file */
|
|
18
18
|
only: (desc: string, fn: () => void) => void;
|
|
19
|
-
/**
|
|
19
|
+
/** Skip the tests inside this `describe` for the current file */
|
|
20
20
|
skip: (desc: string, fn: () => void) => void;
|
|
21
|
-
/**
|
|
21
|
+
/** Skip the tests inside this `describe` for the current file if the condition is satisfied */
|
|
22
22
|
skipIf: (condition: boolean) => (desc: string, fn: () => void) => void;
|
|
23
23
|
/** Runs the tests inside this `describe` for the current file only if the condition is satisfied */
|
|
24
24
|
runIf: (condition: boolean) => (desc: string, fn: () => void) => void;
|
|
@@ -27,11 +27,11 @@ interface Test {
|
|
|
27
27
|
(...input: TestInput<void>): void;
|
|
28
28
|
/** Only runs this test for the current file */
|
|
29
29
|
only: (...input: TestInput<void>) => void;
|
|
30
|
-
/**
|
|
30
|
+
/** Skip this test */
|
|
31
31
|
skip: (...input: TestInput<void>) => void;
|
|
32
32
|
/** Marks the test as one that still needs to be written */
|
|
33
33
|
todo: (...input: TestInput<void>) => void;
|
|
34
|
-
/**
|
|
34
|
+
/** Skip the test if the condition is satisfied */
|
|
35
35
|
skipIf: (condition: boolean) => (...input: TestInput<void>) => void;
|
|
36
36
|
/** Runs the test if the condition is satisfied */
|
|
37
37
|
runIf: (condition: boolean) => (...input: TestInput<void>) => void;
|
|
@@ -53,7 +53,45 @@ interface Test {
|
|
|
53
53
|
attempt: number;
|
|
54
54
|
}>) => void;
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* describe the scene (initial state or context) for a group of tests
|
|
58
|
+
* @example
|
|
59
|
+
* given('a dry plant', () => {
|
|
60
|
+
* when('water needs are checked', () => {
|
|
61
|
+
* then('it should return true', () => {
|
|
62
|
+
* expect(doesPlantNeedWater(plant)).toBe(true);
|
|
63
|
+
* });
|
|
64
|
+
* });
|
|
65
|
+
* });
|
|
66
|
+
*/
|
|
56
67
|
export declare const given: Describe;
|
|
68
|
+
/**
|
|
69
|
+
* describe the event (action or trigger) that occurs within a scene
|
|
70
|
+
* @example
|
|
71
|
+
* when('the user clicks submit', () => {
|
|
72
|
+
* then('the form should be submitted', () => {
|
|
73
|
+
* expect(form.submitted).toBe(true);
|
|
74
|
+
* });
|
|
75
|
+
* });
|
|
76
|
+
*/
|
|
57
77
|
export declare const when: Describe;
|
|
58
|
-
|
|
59
|
-
|
|
78
|
+
/**
|
|
79
|
+
* .what = namespace object for BDD-style test helpers
|
|
80
|
+
* .why = provides vitest-compatible access to given/when/then via `bdd.then()`
|
|
81
|
+
* since direct `then` export triggers ESM thenable detection in vitest.
|
|
82
|
+
*
|
|
83
|
+
* @see .agent/repo=.this/role=any/briefs/limitation.esm-thenable-then-export.md
|
|
84
|
+
*/
|
|
85
|
+
export declare const bdd: {
|
|
86
|
+
given: Describe;
|
|
87
|
+
when: Describe;
|
|
88
|
+
then: Test;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* .what = wraps `then` to handle vitest's thenable detection
|
|
92
|
+
* .why = vitest calls `then(resolve, reject)` on module import; we detect and resolve it
|
|
93
|
+
*
|
|
94
|
+
* @see .agent/repo=.this/role=any/briefs/limitation.esm-thenable-then-export.md
|
|
95
|
+
*/
|
|
96
|
+
declare const thenExportable: Test;
|
|
97
|
+
export { thenExportable as then };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.then = exports.bdd = exports.when = exports.given = exports.getNumberRange = void 0;
|
|
4
|
+
const helpful_errors_1 = require("helpful-errors");
|
|
5
|
+
const detectTestRunner_1 = require("../infra/isomorph.test/detectTestRunner");
|
|
6
|
+
const getTestGlobals_1 = require("../infra/isomorph.test/getTestGlobals");
|
|
7
|
+
const getNumberRange = (input) => {
|
|
8
|
+
// Calculate the length of the range
|
|
9
|
+
const length = input.end - input.start + 1;
|
|
10
|
+
// Create an array with the specified range
|
|
11
|
+
return Array.from({ length }, (_, i) => input.start + i);
|
|
12
|
+
};
|
|
13
|
+
exports.getNumberRange = getNumberRange;
|
|
14
|
+
const castToTestInput = ({ input, prefix, }) => {
|
|
15
|
+
const method = input.length === 3 ? input[2] : input[1]; // its always last
|
|
16
|
+
if (input.length === 3)
|
|
17
|
+
return [`${prefix}: ${input[0]}`, method]; // we allow users to specify the reason for code readability, but we dont expose this in the test report to decrease noise. folks can look in the code if they want to know "why"
|
|
18
|
+
return [`${prefix}: ${input[0]}`, method]; // otherwise, its the normal input
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* describe the scene (initial state or context) for a group of tests
|
|
22
|
+
* @example
|
|
23
|
+
* given('a dry plant', () => {
|
|
24
|
+
* when('water needs are checked', () => {
|
|
25
|
+
* then('it should return true', () => {
|
|
26
|
+
* expect(doesPlantNeedWater(plant)).toBe(true);
|
|
27
|
+
* });
|
|
28
|
+
* });
|
|
29
|
+
* });
|
|
30
|
+
*/
|
|
31
|
+
const given = (desc, fn) => {
|
|
32
|
+
(0, getTestGlobals_1.globals)().describe(`given: ${desc}`, fn);
|
|
33
|
+
};
|
|
34
|
+
exports.given = given;
|
|
35
|
+
exports.given.only = (desc, fn) => (0, getTestGlobals_1.globals)().describe.only(`given: ${desc}`, fn);
|
|
36
|
+
exports.given.skip = (desc, fn) => (0, getTestGlobals_1.globals)().describe.skip(`given: ${desc}`, fn);
|
|
37
|
+
exports.given.skipIf =
|
|
38
|
+
(condition) => (desc, fn) => condition ? exports.given.skip(desc, fn) : (0, exports.given)(desc, fn);
|
|
39
|
+
exports.given.runIf = (condition) => exports.given.skipIf(!condition);
|
|
40
|
+
/**
|
|
41
|
+
* describe the event (action or trigger) that occurs within a scene
|
|
42
|
+
* @example
|
|
43
|
+
* when('the user clicks submit', () => {
|
|
44
|
+
* then('the form should be submitted', () => {
|
|
45
|
+
* expect(form.submitted).toBe(true);
|
|
46
|
+
* });
|
|
47
|
+
* });
|
|
48
|
+
*/
|
|
49
|
+
const when = (desc, fn) => {
|
|
50
|
+
(0, getTestGlobals_1.globals)().describe(`when: ${desc}`, fn);
|
|
51
|
+
};
|
|
52
|
+
exports.when = when;
|
|
53
|
+
exports.when.only = (desc, fn) => (0, getTestGlobals_1.globals)().describe.only(`when: ${desc}`, fn);
|
|
54
|
+
exports.when.skip = (desc, fn) => (0, getTestGlobals_1.globals)().describe.skip(`when: ${desc}`, fn);
|
|
55
|
+
exports.when.skipIf =
|
|
56
|
+
(condition) => (desc, fn) => condition ? exports.when.skip(desc, fn) : (0, exports.when)(desc, fn);
|
|
57
|
+
exports.when.runIf = (condition) => exports.when.skipIf(!condition);
|
|
58
|
+
/**
|
|
59
|
+
* assert the effect (expected outcome) that should be observed
|
|
60
|
+
* @example
|
|
61
|
+
* then('it should return the correct value', () => {
|
|
62
|
+
* expect(result).toBe(expected);
|
|
63
|
+
* });
|
|
64
|
+
*/
|
|
65
|
+
const then = ((...input) => {
|
|
66
|
+
(0, getTestGlobals_1.globals)().test(...castToTestInput({ input, prefix: 'then' }));
|
|
67
|
+
});
|
|
68
|
+
// add methods to then
|
|
69
|
+
then.only = (...input) => (0, getTestGlobals_1.globals)().test.only(...castToTestInput({ input, prefix: 'then' }));
|
|
70
|
+
then.skip = (...input) => (0, getTestGlobals_1.globals)().test.skip(...castToTestInput({ input, prefix: 'then' }));
|
|
71
|
+
then.todo = (...input) => (0, getTestGlobals_1.globals)().test.todo(castToTestInput({ input: [input[0]], prefix: 'then' })[0]);
|
|
72
|
+
then.skipIf =
|
|
73
|
+
(condition) => (...input) => condition ? then.skip(...input) : then(...input);
|
|
74
|
+
then.runIf = (condition) => then.skipIf(!condition);
|
|
75
|
+
then.repeatably =
|
|
76
|
+
(configuration) => (...input) => {
|
|
77
|
+
if (input.length !== 2 && input.length !== 3)
|
|
78
|
+
throw new helpful_errors_1.UnexpectedCodePathError('unsupported input length', { input });
|
|
79
|
+
if (configuration.criteria === 'SOME') {
|
|
80
|
+
const runner = (0, detectTestRunner_1.getTestRunner)();
|
|
81
|
+
const testFn = (0, getTestGlobals_1.globals)().test;
|
|
82
|
+
let attempt = 0;
|
|
83
|
+
(0, getTestGlobals_1.globals)().beforeEach(() => attempt++);
|
|
84
|
+
const [name, fn] = castToTestInput({
|
|
85
|
+
input: input.length === 2
|
|
86
|
+
? [input[0], () => input[1]({ attempt })]
|
|
87
|
+
: [input[0], input[1], () => input[2]({ attempt })],
|
|
88
|
+
prefix: 'then',
|
|
89
|
+
});
|
|
90
|
+
if (runner === 'jest') {
|
|
91
|
+
jest.retryTimes(configuration.attempts, { logErrorsBeforeRetry: true });
|
|
92
|
+
testFn(name, fn);
|
|
93
|
+
}
|
|
94
|
+
if (runner === 'vitest') {
|
|
95
|
+
testFn(name, { retry: configuration.attempts }, fn);
|
|
96
|
+
}
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (configuration.criteria === 'EVERY') {
|
|
100
|
+
for (const attempt of (0, exports.getNumberRange)({
|
|
101
|
+
start: 1,
|
|
102
|
+
end: configuration.attempts,
|
|
103
|
+
})) {
|
|
104
|
+
if (input.length === 2)
|
|
105
|
+
then(input[0] + `, attempt ${attempt}`, () => input[1]({ attempt }));
|
|
106
|
+
if (input.length === 3)
|
|
107
|
+
then(input[0] + `, attempt ${attempt}`, input[1], () => input[2]({ attempt }));
|
|
108
|
+
}
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
throw new helpful_errors_1.UnexpectedCodePathError('configuration.criteria was neither EVERY nor SOME', { configuration });
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* .what = namespace object for BDD-style test helpers
|
|
115
|
+
* .why = provides vitest-compatible access to given/when/then via `bdd.then()`
|
|
116
|
+
* since direct `then` export triggers ESM thenable detection in vitest.
|
|
117
|
+
*
|
|
118
|
+
* @see .agent/repo=.this/role=any/briefs/limitation.esm-thenable-then-export.md
|
|
119
|
+
*/
|
|
120
|
+
exports.bdd = { given: exports.given, when: exports.when, then };
|
|
121
|
+
/**
|
|
122
|
+
* .what = wraps `then` to handle vitest's thenable detection
|
|
123
|
+
* .why = vitest calls `then(resolve, reject)` on module import; we detect and resolve it
|
|
124
|
+
*
|
|
125
|
+
* @see .agent/repo=.this/role=any/briefs/limitation.esm-thenable-then-export.md
|
|
126
|
+
*/
|
|
127
|
+
const thenExportable = ((...input) => {
|
|
128
|
+
// vitest treats modules with `then` as thenables and calls then(resolve, reject)
|
|
129
|
+
if (typeof input[0] === 'function') {
|
|
130
|
+
// resolve with exports that don't have a callable `then` (to break thenable cycle)
|
|
131
|
+
input[0]({ given: exports.given, when: exports.when, bdd: exports.bdd, getNumberRange: exports.getNumberRange });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
then(...input);
|
|
135
|
+
});
|
|
136
|
+
exports.then = thenExportable;
|
|
137
|
+
thenExportable.only = then.only;
|
|
138
|
+
thenExportable.skip = then.skip;
|
|
139
|
+
thenExportable.todo = then.todo;
|
|
140
|
+
thenExportable.skipIf = then.skipIf;
|
|
141
|
+
thenExportable.runIf = then.runIf;
|
|
142
|
+
thenExportable.repeatably = then.repeatably;
|
|
143
|
+
//# sourceMappingURL=givenWhenThen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"givenWhenThen.js","sourceRoot":"","sources":["../../src/domain.operations/givenWhenThen.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* .what = declare a resource to be prepared before tests
|
|
3
|
-
* .why = simplifies devexp
|
|
3
|
+
* .why = simplifies devexp via `const thing = usePrep(...)` syntax
|
|
4
4
|
* .mode =
|
|
5
5
|
* - 'beforeAll': prepare once for all tests
|
|
6
6
|
* - 'beforeEach': prepare fresh for each test run
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useBeforeEach = exports.useBeforeAll = exports.usePrep = void 0;
|
|
4
4
|
const helpful_errors_1 = require("helpful-errors");
|
|
5
|
+
const getTestGlobals_1 = require("../infra/isomorph.test/getTestGlobals");
|
|
5
6
|
/**
|
|
6
7
|
* .what = declare a resource to be prepared before tests
|
|
7
|
-
* .why = simplifies devexp
|
|
8
|
+
* .why = simplifies devexp via `const thing = usePrep(...)` syntax
|
|
8
9
|
* .mode =
|
|
9
10
|
* - 'beforeAll': prepare once for all tests
|
|
10
11
|
* - 'beforeEach': prepare fresh for each test run
|
|
@@ -30,7 +31,7 @@ const usePrep = (setup, options = { mode: 'beforeAll' }) => {
|
|
|
30
31
|
throw new Error('usePrep: value is not callable');
|
|
31
32
|
},
|
|
32
33
|
};
|
|
33
|
-
const register = options.mode === 'beforeEach' ? beforeEach : beforeAll;
|
|
34
|
+
const register = options.mode === 'beforeEach' ? (0, getTestGlobals_1.globals)().beforeEach : (0, getTestGlobals_1.globals)().beforeAll;
|
|
34
35
|
register(async () => {
|
|
35
36
|
toolbox = await setup();
|
|
36
37
|
// assign properties from toolbox to drawer so Object.keys(), for..in, etc work
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePrep.js","sourceRoot":"","sources":["../../src/domain.operations/usePrep.ts"],"names":[],"mappings":";;;AAAA,mDAAyD;AAEzD,4EAAkE;AAElE;;;;;;GAMG;AACI,MAAM,OAAO,GAAG,CACrB,KAAuB,EACvB,UAEI,EAAE,IAAI,EAAE,WAAW,EAAE,EACtB,EAAE;IACL,wEAAwE;IACxE,MAAM,MAAM,GAAe,EAAE,CAAC,CAAC,8BAA8B;IAC7D,IAAI,OAAsB,CAAC,CAAC,uCAAuC;IAEnE,qDAAqD;IACrD,MAAM,YAAY,GAAsB;QACtC,GAAG,CAAC,CAAC,EAAE,IAAI;YACT,IAAI,OAAO,KAAK,SAAS;gBACvB,MAAM,IAAI,wCAAuB,CAC/B,uDAAuD,CACxD,CAAC;YACJ,OAAQ,OAAe,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QACD,OAAO;YACL,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QACD,wBAAwB,CAAC,CAAC,EAAE,IAAI;YAC9B,OAAO,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACvD,CAAC;QACD,KAAK;YACH,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;KACF,CAAC;IAEF,MAAM,QAAQ,GACZ,OAAO,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,IAAA,wBAAO,GAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAA,wBAAO,GAAE,CAAC,SAAS,CAAC;IAE7E,QAAQ,CAAC,KAAK,IAAI,EAAE;QAClB,OAAO,GAAG,MAAM,KAAK,EAAE,CAAC;QAExB,+EAA+E;QAC/E,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAE/B,iEAAiE;QACjE,OAAO,YAAY,CAAC,GAAG,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,mDAAmD;IACnD,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE,YAAY,CAAM,CAAC;AAC9C,CAAC,CAAC;AA7CW,QAAA,OAAO,WA6ClB;AAEK,MAAM,YAAY,GAAG,CAC1B,KAAuC,EACR,EAAE,CAAC,IAAA,eAAO,EAAI,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;AAFhE,QAAA,YAAY,gBAEoD;AACtE,MAAM,aAAa,GAAG,CAC3B,KAAuC,EACR,EAAE,CAAC,IAAA,eAAO,EAAI,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;AAFjE,QAAA,aAAa,iBAEoD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .what = interface for useThen with modifiers
|
|
3
|
+
* .why = enables useThen.only, useThen.skip, etc.
|
|
4
|
+
*/
|
|
5
|
+
interface UseThen {
|
|
6
|
+
<T extends Record<string, any>>(desc: string, fn: () => Promise<T> | T): T;
|
|
7
|
+
only: <T extends Record<string, any>>(desc: string, fn: () => Promise<T> | T) => T;
|
|
8
|
+
skip: <T extends Record<string, any>>(desc: string, fn: () => Promise<T> | T) => T;
|
|
9
|
+
skipIf: (condition: boolean) => <T extends Record<string, any>>(desc: string, fn: () => Promise<T> | T) => T;
|
|
10
|
+
runIf: (condition: boolean) => <T extends Record<string, any>>(desc: string, fn: () => Promise<T> | T) => T;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* .what = register a test and capture its return value for subsequent assertions
|
|
14
|
+
* .why = eliminates `let` declarations for sharing operation results between then blocks
|
|
15
|
+
*/
|
|
16
|
+
export declare const useThen: UseThen;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useThen = void 0;
|
|
4
|
+
const helpful_errors_1 = require("helpful-errors");
|
|
5
|
+
const givenWhenThen_1 = require("./givenWhenThen");
|
|
6
|
+
// use bdd.then to avoid vitest thenable detection issues with direct then export
|
|
7
|
+
const { then } = givenWhenThen_1.bdd;
|
|
8
|
+
/**
|
|
9
|
+
* .what = helper to create the proxy pattern for useThen
|
|
10
|
+
* .why = reused by main function and all modifiers
|
|
11
|
+
*/
|
|
12
|
+
const createUseThenProxy = (input) => {
|
|
13
|
+
// metaphor: "drawer" = proxy target, "toolbox" = real resolved resource
|
|
14
|
+
const drawer = {};
|
|
15
|
+
let toolbox;
|
|
16
|
+
// declare proxy handler up front so we can mutate it
|
|
17
|
+
const proxyHandler = {
|
|
18
|
+
get(_, prop) {
|
|
19
|
+
if (toolbox === undefined)
|
|
20
|
+
throw new helpful_errors_1.UnexpectedCodePathError('useThen: tried to access value before test ran');
|
|
21
|
+
return toolbox[prop];
|
|
22
|
+
},
|
|
23
|
+
ownKeys() {
|
|
24
|
+
return Reflect.ownKeys(drawer);
|
|
25
|
+
},
|
|
26
|
+
getOwnPropertyDescriptor(_, prop) {
|
|
27
|
+
return Object.getOwnPropertyDescriptor(drawer, prop);
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
// register the test via the provided then function (or modifier)
|
|
31
|
+
input.thenFn(input.desc, async () => {
|
|
32
|
+
toolbox = await input.fn();
|
|
33
|
+
// assign properties for Object.keys() support
|
|
34
|
+
Object.assign(drawer, toolbox);
|
|
35
|
+
// remove get trap once test completes
|
|
36
|
+
delete proxyHandler.get;
|
|
37
|
+
});
|
|
38
|
+
// return proxy
|
|
39
|
+
return new Proxy(drawer, proxyHandler);
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* .what = register a test and capture its return value for subsequent assertions
|
|
43
|
+
* .why = eliminates `let` declarations for sharing operation results between then blocks
|
|
44
|
+
*/
|
|
45
|
+
const useThen = (desc, fn) => createUseThenProxy({ desc, fn, thenFn: then });
|
|
46
|
+
exports.useThen = useThen;
|
|
47
|
+
// modifiers
|
|
48
|
+
exports.useThen.only = (desc, fn) => createUseThenProxy({ desc, fn, thenFn: then.only });
|
|
49
|
+
exports.useThen.skip = (desc, fn) => createUseThenProxy({ desc, fn, thenFn: then.skip });
|
|
50
|
+
exports.useThen.skipIf =
|
|
51
|
+
(condition) => (desc, fn) => createUseThenProxy({ desc, fn, thenFn: then.skipIf(condition) });
|
|
52
|
+
exports.useThen.runIf =
|
|
53
|
+
(condition) => (desc, fn) => createUseThenProxy({ desc, fn, thenFn: then.runIf(condition) });
|
|
54
|
+
//# sourceMappingURL=useThen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useThen.js","sourceRoot":"","sources":["../../src/domain.operations/useThen.ts"],"names":[],"mappings":";;;AAAA,mDAAyD;AAEzD,mDAAsC;AAEtC,iFAAiF;AACjF,MAAM,EAAE,IAAI,EAAE,GAAG,mBAAG,CAAC;AAQrB;;;GAGG;AACH,MAAM,kBAAkB,GAAG,CAAgC,KAI1D,EAAK,EAAE;IACN,wEAAwE;IACxE,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,IAAI,OAAsB,CAAC;IAE3B,qDAAqD;IACrD,MAAM,YAAY,GAAsB;QACtC,GAAG,CAAC,CAAC,EAAE,IAAI;YACT,IAAI,OAAO,KAAK,SAAS;gBACvB,MAAM,IAAI,wCAAuB,CAC/B,gDAAgD,CACjD,CAAC;YACJ,OAAQ,OAAe,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QACD,OAAO;YACL,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QACD,wBAAwB,CAAC,CAAC,EAAE,IAAI;YAC9B,OAAO,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACvD,CAAC;KACF,CAAC;IAEF,iEAAiE;IACjE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;QAClC,OAAO,GAAG,MAAM,KAAK,CAAC,EAAE,EAAE,CAAC;QAE3B,8CAA8C;QAC9C,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAE/B,sCAAsC;QACtC,OAAO,YAAY,CAAC,GAAG,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,eAAe;IACf,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE,YAAY,CAAM,CAAC;AAC9C,CAAC,CAAC;AAkCF;;;GAGG;AACI,MAAM,OAAO,GAAY,CAC9B,IAAY,EACZ,EAAwB,EACrB,EAAE,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAH1C,QAAA,OAAO,WAGmC;AAEvD,YAAY;AACZ,eAAO,CAAC,IAAI,GAAG,CACb,IAAY,EACZ,EAAwB,EACrB,EAAE,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AAE5D,eAAO,CAAC,IAAI,GAAG,CACb,IAAY,EACZ,EAAwB,EACrB,EAAE,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AAE5D,eAAO,CAAC,MAAM;IACZ,CAAC,SAAkB,EAAE,EAAE,CACvB,CAAgC,IAAY,EAAE,EAAwB,EAAK,EAAE,CAC3E,kBAAkB,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;AAErE,eAAO,CAAC,KAAK;IACX,CAAC,SAAkB,EAAE,EAAE,CACvB,CAAgC,IAAY,EAAE,EAAwB,EAAK,EAAE,CAC3E,kBAAkB,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .what = interface for useWhen with modifiers
|
|
3
|
+
* .why = enables useWhen.only, useWhen.skip, etc.
|
|
4
|
+
*/
|
|
5
|
+
interface UseWhen {
|
|
6
|
+
<T>(desc: string, fn: () => T): T;
|
|
7
|
+
only: <T>(desc: string, fn: () => T) => T;
|
|
8
|
+
skip: <T>(desc: string, fn: () => T) => T;
|
|
9
|
+
skipIf: (condition: boolean) => <T>(desc: string, fn: () => T) => T;
|
|
10
|
+
runIf: (condition: boolean) => <T>(desc: string, fn: () => T) => T;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* .what = execute a fn synchronously and capture its return value for sibling blocks
|
|
14
|
+
* .why = enables sharing operation results across sequential blocks without let declarations
|
|
15
|
+
* .note = unlike useThen, does not create a test block - executes immediately during collection
|
|
16
|
+
*/
|
|
17
|
+
export declare const useWhen: UseWhen;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useWhen = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* .what = helper to create useWhen pattern
|
|
6
|
+
* .why = executes fn synchronously and returns result (no describe wrapper)
|
|
7
|
+
* .note = does not create a nested when block due to vitest describe timing issues
|
|
8
|
+
*/
|
|
9
|
+
const createUseWhen = (input) => {
|
|
10
|
+
// skip mode returns undefined - the result won't be used in skipped tests
|
|
11
|
+
if (input.skip)
|
|
12
|
+
return undefined;
|
|
13
|
+
// execute synchronously and return
|
|
14
|
+
return input.fn();
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* .what = execute a fn synchronously and capture its return value for sibling blocks
|
|
18
|
+
* .why = enables sharing operation results across sequential blocks without let declarations
|
|
19
|
+
* .note = unlike useThen, does not create a test block - executes immediately during collection
|
|
20
|
+
*/
|
|
21
|
+
const useWhen = (desc, fn) => createUseWhen({ desc, fn });
|
|
22
|
+
exports.useWhen = useWhen;
|
|
23
|
+
// modifiers
|
|
24
|
+
exports.useWhen.only = (desc, fn) => createUseWhen({ desc, fn }); // only has no special meaning for synchronous execution
|
|
25
|
+
exports.useWhen.skip = (desc, fn) => createUseWhen({ desc, fn, skip: true });
|
|
26
|
+
exports.useWhen.skipIf =
|
|
27
|
+
(condition) => (desc, fn) => createUseWhen({ desc, fn, skip: condition });
|
|
28
|
+
exports.useWhen.runIf =
|
|
29
|
+
(condition) => (desc, fn) => createUseWhen({ desc, fn, skip: !condition });
|
|
30
|
+
//# sourceMappingURL=useWhen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWhen.js","sourceRoot":"","sources":["../../src/domain.operations/useWhen.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,MAAM,aAAa,GAAG,CAAI,KAIzB,EAAK,EAAE;IACN,0EAA0E;IAC1E,IAAI,KAAK,CAAC,IAAI;QAAE,OAAO,SAAyB,CAAC;IAEjD,mCAAmC;IACnC,OAAO,KAAK,CAAC,EAAE,EAAE,CAAC;AACpB,CAAC,CAAC;AAkBF;;;;GAIG;AACI,MAAM,OAAO,GAAY,CAAI,IAAY,EAAE,EAAW,EAAK,EAAE,CAClE,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;AADjB,QAAA,OAAO,WACU;AAE9B,YAAY;AACZ,eAAO,CAAC,IAAI,GAAG,CAAI,IAAY,EAAE,EAAW,EAAK,EAAE,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,wDAAwD;AAEzI,eAAO,CAAC,IAAI,GAAG,CAAI,IAAY,EAAE,EAAW,EAAK,EAAE,CACjD,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AAE1C,eAAO,CAAC,MAAM;IACZ,CAAC,SAAkB,EAAE,EAAE,CACvB,CAAI,IAAY,EAAE,EAAW,EAAK,EAAE,CAClC,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AAEjD,eAAO,CAAC,KAAK;IACX,CAAC,SAAkB,EAAE,EAAE,CACvB,CAAI,IAAY,EAAE,EAAW,EAAK,EAAE,CAClC,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/**
|
|
2
|
+
* .what = package entry point for test-fns
|
|
3
|
+
* .why = re-exports from contract layer for public consumption
|
|
4
|
+
*/
|
|
5
|
+
export * from './contract';
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
var genTestUuid_1 = require("./genTestUuid");
|
|
9
|
-
Object.defineProperty(exports, "genTestUuid", { enumerable: true, get: function () { return genTestUuid_1.genTestUuid; } });
|
|
10
|
-
var usePrep_1 = require("./usePrep");
|
|
11
|
-
Object.defineProperty(exports, "usePrep", { enumerable: true, get: function () { return usePrep_1.usePrep; } });
|
|
12
|
-
Object.defineProperty(exports, "useBeforeAll", { enumerable: true, get: function () { return usePrep_1.useBeforeAll; } });
|
|
13
|
-
Object.defineProperty(exports, "useBeforeEach", { enumerable: true, get: function () { return usePrep_1.useBeforeEach; } });
|
|
14
|
-
// forward the getError method since it is almost always needed with tests
|
|
15
|
-
var helpful_errors_1 = require("helpful-errors");
|
|
16
|
-
Object.defineProperty(exports, "getError", { enumerable: true, get: function () { return helpful_errors_1.getError; } });
|
|
17
|
+
/**
|
|
18
|
+
* .what = package entry point for test-fns
|
|
19
|
+
* .why = re-exports from contract layer for public consumption
|
|
20
|
+
*/
|
|
21
|
+
__exportStar(require("./contract"), exports);
|
|
17
22
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;;GAGG;AACH,6CAA2B"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .what = the test runner currently executing the code
|
|
3
|
+
* .why = enables isomorphic behavior between vitest and jest
|
|
4
|
+
*/
|
|
5
|
+
export type TestRunner = 'vitest' | 'jest';
|
|
6
|
+
/**
|
|
7
|
+
* .what = detects which test runner is currently executing
|
|
8
|
+
* .why = enables runtime selection of test framework apis
|
|
9
|
+
*
|
|
10
|
+
* .note = vitest is checked first as it's more specific
|
|
11
|
+
*/
|
|
12
|
+
export declare const detectTestRunner: () => TestRunner;
|
|
13
|
+
export declare const getTestRunner: () => TestRunner;
|
|
14
|
+
/**
|
|
15
|
+
* .what = resets the cached runner (for testing only)
|
|
16
|
+
* .why = allows tests to verify detection logic with different env states
|
|
17
|
+
*/
|
|
18
|
+
export declare const resetTestRunnerCache: () => void;
|