@fougere/testing 0.5.0-alpha.1 → 0.7.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/all.d.ts +2 -17
- package/dist/all.d.ts.map +1 -1
- package/dist/all.js +2 -17
- package/dist/all.js.map +1 -1
- package/dist/app.d.ts +4 -35
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +2 -17
- package/dist/app.js.map +1 -1
- package/dist/comparison.d.ts +3 -20
- package/dist/comparison.d.ts.map +1 -1
- package/dist/comparison.js +29 -58
- package/dist/comparison.js.map +1 -1
- package/dist/derive.d.ts +3 -9
- package/dist/derive.d.ts.map +1 -1
- package/dist/derive.js +1 -7
- package/dist/derive.js.map +1 -1
- package/dist/doors.d.ts +4 -22
- package/dist/doors.d.ts.map +1 -1
- package/dist/doors.js +6 -24
- package/dist/doors.js.map +1 -1
- package/dist/gql.d.ts +5 -24
- package/dist/gql.d.ts.map +1 -1
- package/dist/gql.js +11 -37
- package/dist/gql.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/load.d.ts +3 -20
- package/dist/load.d.ts.map +1 -1
- package/dist/load.js +6 -23
- package/dist/load.js.map +1 -1
- package/dist/remotes.d.ts +1 -6
- package/dist/remotes.d.ts.map +1 -1
- package/dist/remotes.js +1 -6
- package/dist/remotes.js.map +1 -1
- package/dist/sample.d.ts +2 -14
- package/dist/sample.d.ts.map +1 -1
- package/dist/sample.js +8 -16
- package/dist/sample.js.map +1 -1
- package/dist/scope.d.ts +5 -38
- package/dist/scope.d.ts.map +1 -1
- package/dist/scope.js +4 -26
- package/dist/scope.js.map +1 -1
- package/dist/stub.d.ts +3 -32
- package/dist/stub.d.ts.map +1 -1
- package/dist/stub.js +3 -32
- package/dist/stub.js.map +1 -1
- package/dist/sync.d.ts +2 -19
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +5 -22
- package/dist/sync.js.map +1 -1
- package/dist/vitest.d.ts +1 -20
- package/dist/vitest.d.ts.map +1 -1
- package/dist/vitest.js +1 -20
- package/dist/vitest.js.map +1 -1
- package/package.json +9 -9
- package/src/all.ts +2 -17
- package/src/app.ts +5 -41
- package/src/comparison.ts +34 -63
- package/src/derive.ts +3 -9
- package/src/doors.ts +7 -25
- package/src/gql.ts +9 -35
- package/src/index.ts +1 -1
- package/src/load.ts +7 -24
- package/src/remotes.ts +1 -6
- package/src/sample.ts +10 -30
- package/src/scope.ts +5 -38
- package/src/stub.ts +3 -32
- package/src/sync.ts +5 -22
- package/src/vitest.ts +1 -20
package/dist/scope.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { dirname, join, sep } from 'node:path';
|
|
3
3
|
import { DEFAULT_CONVENTIONS, loadConfig, resolveConventions } from '@fougere/core/node';
|
|
4
|
-
/**
|
|
5
|
-
* The frond a path sits in, or nothing.
|
|
6
|
-
*
|
|
7
|
-
* The LAST `fronds/` segment wins: a frond may hold a synced copy of a neighbour under
|
|
8
|
-
* `.fougere/remotes/`, and a test that ever lands beside one is about the inner frond.
|
|
9
|
-
*/
|
|
4
|
+
/** The frond a path sits in, or nothing. */
|
|
10
5
|
export function frondOf(path, frondsDir = DEFAULT_CONVENTIONS.fronds) {
|
|
11
6
|
const parts = path.split(sep);
|
|
12
7
|
const at = parts.lastIndexOf(frondsDir);
|
|
@@ -15,13 +10,7 @@ export function frondOf(path, frondsDir = DEFAULT_CONVENTIONS.fronds) {
|
|
|
15
10
|
const name = parts[at + 1];
|
|
16
11
|
return name && !name.endsWith('.ts') ? name : undefined;
|
|
17
12
|
}
|
|
18
|
-
/**
|
|
19
|
-
* Where the project starts: the first ancestor holding a config or a `fronds/`.
|
|
20
|
-
*
|
|
21
|
-
* The config is probed FIRST, which is what lets the rest of this file ask it where fronds
|
|
22
|
-
* live: a project that renamed the directory still declares one, and only a project with
|
|
23
|
-
* no config at all is found by the convention.
|
|
24
|
-
*/
|
|
13
|
+
/** Where the project starts. */
|
|
25
14
|
export function rootOf(path) {
|
|
26
15
|
let at = dirname(path);
|
|
27
16
|
let previous = '';
|
|
@@ -33,12 +22,7 @@ export function rootOf(path) {
|
|
|
33
22
|
}
|
|
34
23
|
return undefined;
|
|
35
24
|
}
|
|
36
|
-
/**
|
|
37
|
-
* The scope a test file declares by where it sits.
|
|
38
|
-
*
|
|
39
|
-
* Returns nothing when the file sits outside any project — a caller then states `root`
|
|
40
|
-
* itself, which is what this package's own tests do against their fixtures.
|
|
41
|
-
*/
|
|
25
|
+
/** The scope a test file declares by where it sits. */
|
|
42
26
|
export async function scopeOf(path) {
|
|
43
27
|
const root = rootOf(path);
|
|
44
28
|
if (!root)
|
|
@@ -49,13 +33,7 @@ export async function scopeOf(path) {
|
|
|
49
33
|
const frond = frondOf(path, fronds);
|
|
50
34
|
return { root, ...(frond ? { frond } : {}) };
|
|
51
35
|
}
|
|
52
|
-
/**
|
|
53
|
-
* The path of the running test file, from vitest.
|
|
54
|
-
*
|
|
55
|
-
* Read rather than guessed: `expect.getState()` is vitest's own API. Handed in by the
|
|
56
|
-
* caller because this module is ESM and cannot `require`, and because a package that
|
|
57
|
-
* imports vitest at the top level stops being loadable outside a test run.
|
|
58
|
-
*/
|
|
36
|
+
/** The path of the running test file, from vitest. */
|
|
59
37
|
export async function scopeOfRun(testPath) {
|
|
60
38
|
return testPath ? scopeOf(testPath) : undefined;
|
|
61
39
|
}
|
package/dist/scope.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAUzF,4CAA4C;AAC5C,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,SAAS,GAAW,mBAAmB,CAAC,MAAM;IAClF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IACxC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC3B,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1D,CAAC;AAED,gCAAgC;AAChC,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;QACvB,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,mBAAmB,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QAC7G,QAAQ,GAAG,EAAE,CAAC;QACd,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,uDAAuD;AACvD,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAY;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5B,sFAAsF;IACtF,mCAAmC;IACnC,MAAM,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAAC,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED,sDAAsD;AACtD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAA4B;IAC3D,OAAO,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAClD,CAAC"}
|
package/dist/stub.d.ts
CHANGED
|
@@ -6,39 +6,10 @@ export type Port = abstract new (...args: never[]) => unknown;
|
|
|
6
6
|
export type Stub<T> = {
|
|
7
7
|
[K in keyof T]: T[K] extends (...args: never[]) => unknown ? Mock : T[K];
|
|
8
8
|
};
|
|
9
|
-
/**
|
|
10
|
-
* The methods a port declares, read from the prototype chain at runtime.
|
|
11
|
-
*
|
|
12
|
-
* Not written by hand and not read from the AST: `ProviderEntry` keeps `ctor`, `deps` and
|
|
13
|
-
* `filePath` and never the methods, while the prototype has them all along. So a double
|
|
14
|
-
* carries exactly what the port carries and gains a method the day the port does — which
|
|
15
|
-
* is the failure `ports.test.ts` records, a `charge is not a function` from a stand-in
|
|
16
|
-
* that did not carry what its type promised.
|
|
17
|
-
*
|
|
18
|
-
* Walks the chain because a port may itself extend one; stops at `Object.prototype`,
|
|
19
|
-
* whose members belong to no port.
|
|
20
|
-
*/
|
|
9
|
+
/** The methods a port declares, read from the prototype chain at runtime. */
|
|
21
10
|
export declare function methodsOf(port: Port): string[];
|
|
22
|
-
/**
|
|
23
|
-
* A double for a port: every method present, every call recorded, nothing returned.
|
|
24
|
-
*
|
|
25
|
-
* What it RETURNS is not derivable and the value is the caller's to state — a service's
|
|
26
|
-
* return type is a bare TypeScript type, erased at runtime, with no declared fields for
|
|
27
|
-
* anything to build from. The same line the whole package sits on: what Fougere's
|
|
28
|
-
* vocabulary declares can be derived, arbitrary code cannot.
|
|
29
|
-
*/
|
|
11
|
+
/** A double for a port. */
|
|
30
12
|
export declare function stubOf<T>(port: Port): Stub<T>;
|
|
31
|
-
/**
|
|
32
|
-
* Put doubles in front of ports, in every frond scope that answers under their name.
|
|
33
|
-
*
|
|
34
|
-
* After the boot rather than through `ports:`, because the container resolves lazily: a
|
|
35
|
-
* provider is built on first `resolve`, so a value registered before any call is the one
|
|
36
|
-
* a handler receives. `registerValue` also marks it as not the container's to dispose,
|
|
37
|
-
* which is right — the test made it.
|
|
38
|
-
*
|
|
39
|
-
* A port nobody answers under is REFUSED by name, for the reason `ports:` refuses a key
|
|
40
|
-
* that matched nothing: a double that silently stands in front of no one reads as a test
|
|
41
|
-
* that covered a case it never reached.
|
|
42
|
-
*/
|
|
13
|
+
/** Put doubles in front of ports, in every frond scope that answers under their name. */
|
|
43
14
|
export declare function installStubs(app: App, ports: Port[]): Map<Port, Stub<unknown>>;
|
|
44
15
|
//# sourceMappingURL=stub.d.ts.map
|
package/dist/stub.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stub.d.ts","sourceRoot":"","sources":["../src/stub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAEzC,wFAAwF;AACxF,MAAM,MAAM,IAAI,GAAG,QAAQ,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC;AAE9D,mFAAmF;AACnF,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC;AAEnG
|
|
1
|
+
{"version":3,"file":"stub.d.ts","sourceRoot":"","sources":["../src/stub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAEzC,wFAAwF;AACxF,MAAM,MAAM,IAAI,GAAG,QAAQ,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC;AAE9D,mFAAmF;AACnF,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC;AAEnG,6EAA6E;AAC7E,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAY9C;AAED,2BAA2B;AAC3B,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAI7C;AAED,yFAAyF;AACzF,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAiB9E"}
|
package/dist/stub.js
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
import { vi } from 'vitest';
|
|
2
|
-
/**
|
|
3
|
-
* The methods a port declares, read from the prototype chain at runtime.
|
|
4
|
-
*
|
|
5
|
-
* Not written by hand and not read from the AST: `ProviderEntry` keeps `ctor`, `deps` and
|
|
6
|
-
* `filePath` and never the methods, while the prototype has them all along. So a double
|
|
7
|
-
* carries exactly what the port carries and gains a method the day the port does — which
|
|
8
|
-
* is the failure `ports.test.ts` records, a `charge is not a function` from a stand-in
|
|
9
|
-
* that did not carry what its type promised.
|
|
10
|
-
*
|
|
11
|
-
* Walks the chain because a port may itself extend one; stops at `Object.prototype`,
|
|
12
|
-
* whose members belong to no port.
|
|
13
|
-
*/
|
|
2
|
+
/** The methods a port declares, read from the prototype chain at runtime. */
|
|
14
3
|
export function methodsOf(port) {
|
|
15
4
|
const found = new Set();
|
|
16
5
|
let proto = port.prototype;
|
|
@@ -26,32 +15,14 @@ export function methodsOf(port) {
|
|
|
26
15
|
}
|
|
27
16
|
return [...found];
|
|
28
17
|
}
|
|
29
|
-
/**
|
|
30
|
-
* A double for a port: every method present, every call recorded, nothing returned.
|
|
31
|
-
*
|
|
32
|
-
* What it RETURNS is not derivable and the value is the caller's to state — a service's
|
|
33
|
-
* return type is a bare TypeScript type, erased at runtime, with no declared fields for
|
|
34
|
-
* anything to build from. The same line the whole package sits on: what Fougere's
|
|
35
|
-
* vocabulary declares can be derived, arbitrary code cannot.
|
|
36
|
-
*/
|
|
18
|
+
/** A double for a port. */
|
|
37
19
|
export function stubOf(port) {
|
|
38
20
|
const double = {};
|
|
39
21
|
for (const method of methodsOf(port))
|
|
40
22
|
double[method] = vi.fn();
|
|
41
23
|
return double;
|
|
42
24
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Put doubles in front of ports, in every frond scope that answers under their name.
|
|
45
|
-
*
|
|
46
|
-
* After the boot rather than through `ports:`, because the container resolves lazily: a
|
|
47
|
-
* provider is built on first `resolve`, so a value registered before any call is the one
|
|
48
|
-
* a handler receives. `registerValue` also marks it as not the container's to dispose,
|
|
49
|
-
* which is right — the test made it.
|
|
50
|
-
*
|
|
51
|
-
* A port nobody answers under is REFUSED by name, for the reason `ports:` refuses a key
|
|
52
|
-
* that matched nothing: a double that silently stands in front of no one reads as a test
|
|
53
|
-
* that covered a case it never reached.
|
|
54
|
-
*/
|
|
25
|
+
/** Put doubles in front of ports, in every frond scope that answers under their name. */
|
|
55
26
|
export function installStubs(app, ports) {
|
|
56
27
|
const doubles = new Map();
|
|
57
28
|
const scopes = app.fronds.map((frond) => app.resolve(`frond:${frond.name}`));
|
package/dist/stub.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stub.js","sourceRoot":"","sources":["../src/stub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAa,MAAM,QAAQ,CAAC;AAUvC
|
|
1
|
+
{"version":3,"file":"stub.js","sourceRoot":"","sources":["../src/stub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAa,MAAM,QAAQ,CAAC;AAUvC,6EAA6E;AAC7E,MAAM,UAAU,SAAS,CAAC,IAAU;IAClC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,IAAI,KAAK,GAAkB,IAAI,CAAC,SAAmB,CAAC;IACpD,OAAO,KAAK,IAAI,KAAK,KAAK,MAAM,CAAC,SAAS,EAAE,CAAC;QAC3C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;YACrD,IAAI,IAAI,KAAK,aAAa;gBAAE,SAAS;YACrC,MAAM,QAAQ,GAAG,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAC9D,IAAI,OAAO,QAAQ,EAAE,KAAK,KAAK,UAAU;gBAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7D,CAAC;QACD,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAkB,CAAC;IACxD,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;AACpB,CAAC;AAED,2BAA2B;AAC3B,MAAM,UAAU,MAAM,CAAI,IAAU;IAClC,MAAM,MAAM,GAAyB,EAAE,CAAC;IACxC,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC;QAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;IAC/D,OAAO,MAAiB,CAAC;AAC3B,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,YAAY,CAAC,GAAQ,EAAE,KAAa;IAClD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC/C,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAY,SAAS,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAExF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACjE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,UAAU,IAAI,CAAC,IAAI,mDAAmD;kBACpE,sFAAsF,CACzF,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5B,KAAK,MAAM,KAAK,IAAI,SAAS;YAAE,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/sync.d.ts
CHANGED
|
@@ -20,26 +20,9 @@ export interface SyncDrift {
|
|
|
20
20
|
}
|
|
21
21
|
/** The remotes a project synced, read from the file `fougere sync` writes. */
|
|
22
22
|
export declare function syncedRemotes(root: string): Promise<SyncedRemote[]>;
|
|
23
|
-
/**
|
|
24
|
-
* The shapes a consumer holds for one remote frond.
|
|
25
|
-
*
|
|
26
|
-
* Rebuilt from the classes rather than read back: `fougere sync` writes entities and an
|
|
27
|
-
* index and does NOT keep the card it received. So the consumer's copy of the OPERATIONS
|
|
28
|
-
* has no local counterpart at all, and only the shapes can be compared — which is the
|
|
29
|
-
* narrower half, and the one that breaks a caller silently.
|
|
30
|
-
*
|
|
31
|
-
* Closing that would mean `sync` writing the card beside the classes; it is a change to
|
|
32
|
-
* the CLI, not to this file.
|
|
33
|
-
*/
|
|
23
|
+
/** The shapes a consumer holds for one remote frond. */
|
|
34
24
|
export declare function heldShapes(remote: SyncedRemote): Promise<Map<string, SchemaDescriptor>>;
|
|
35
|
-
/**
|
|
36
|
-
* What the consumer's copy no longer matches.
|
|
37
|
-
*
|
|
38
|
-
* Compared by the shape's own `title` — the entity's name as the descriptor carries it —
|
|
39
|
-
* rather than by the door's, because a door is addressed in lowercase (`post`) and a class
|
|
40
|
-
* is not (`Post`), and matching those two by hand is where a name convention gets copied
|
|
41
|
-
* a third time.
|
|
42
|
-
*/
|
|
25
|
+
/** What the consumer's copy no longer matches. */
|
|
43
26
|
export declare function syncDriftOf(held: Map<string, SchemaDescriptor>, card: IdentityCard, frond: string): SyncDrift;
|
|
44
27
|
/** Whether the copy still matches. */
|
|
45
28
|
export declare function inSync(drift: SyncDrift): boolean;
|
package/dist/sync.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAGA,OAAO,EAAQ,KAAK,MAAM,EAAE,KAAK,gBAAgB,EAAmB,MAAM,iBAAiB,CAAC;AAC5F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,uEAAuE;AACvE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;CACd;AAED,mFAAmF;AACnF,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,gEAAgE;IAChE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;CAChD;AAED,8EAA8E;AAC9E,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CASzE;AAED
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAGA,OAAO,EAAQ,KAAK,MAAM,EAAE,KAAK,gBAAgB,EAAmB,MAAM,iBAAiB,CAAC;AAC5F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,uEAAuE;AACvE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;CACd;AAED,mFAAmF;AACnF,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,gEAAgE;IAChE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;CAChD;AAED,8EAA8E;AAC9E,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CASzE;AAED,wDAAwD;AACxD,wBAAsB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAW7F;AAYD,kDAAkD;AAClD,wBAAgB,WAAW,CACzB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACnC,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,MAAM,GACZ,SAAS,CAWX;AAED,sCAAsC;AACtC,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAEhD"}
|
package/dist/sync.js
CHANGED
|
@@ -14,28 +14,18 @@ export async function syncedRemotes(root) {
|
|
|
14
14
|
return [];
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
/**
|
|
18
|
-
* The shapes a consumer holds for one remote frond.
|
|
19
|
-
*
|
|
20
|
-
* Rebuilt from the classes rather than read back: `fougere sync` writes entities and an
|
|
21
|
-
* index and does NOT keep the card it received. So the consumer's copy of the OPERATIONS
|
|
22
|
-
* has no local counterpart at all, and only the shapes can be compared — which is the
|
|
23
|
-
* narrower half, and the one that breaks a caller silently.
|
|
24
|
-
*
|
|
25
|
-
* Closing that would mean `sync` writing the card beside the classes; it is a change to
|
|
26
|
-
* the CLI, not to this file.
|
|
27
|
-
*/
|
|
17
|
+
/** The shapes a consumer holds for one remote frond. */
|
|
28
18
|
export async function heldShapes(remote) {
|
|
29
|
-
const
|
|
19
|
+
const cards = new Map();
|
|
30
20
|
const index = pathToFileURL(join(remote.path, 'index.ts')).href;
|
|
31
21
|
const module = await import(index);
|
|
32
22
|
for (const [name, exported] of Object.entries(module)) {
|
|
33
23
|
const entity = exported;
|
|
34
24
|
if (typeof entity !== 'function' || typeof entity.getFields !== 'function')
|
|
35
25
|
continue;
|
|
36
|
-
|
|
26
|
+
cards.set(name, Card.fromSchema(entity).descriptor);
|
|
37
27
|
}
|
|
38
|
-
return
|
|
28
|
+
return cards;
|
|
39
29
|
}
|
|
40
30
|
/** The shapes a card announces, by the name a door carries. */
|
|
41
31
|
function servedShapes(card, frond) {
|
|
@@ -49,14 +39,7 @@ function servedShapes(card, frond) {
|
|
|
49
39
|
}
|
|
50
40
|
return served;
|
|
51
41
|
}
|
|
52
|
-
/**
|
|
53
|
-
* What the consumer's copy no longer matches.
|
|
54
|
-
*
|
|
55
|
-
* Compared by the shape's own `title` — the entity's name as the descriptor carries it —
|
|
56
|
-
* rather than by the door's, because a door is addressed in lowercase (`post`) and a class
|
|
57
|
-
* is not (`Post`), and matching those two by hand is where a name convention gets copied
|
|
58
|
-
* a third time.
|
|
59
|
-
*/
|
|
42
|
+
/** What the consumer's copy no longer matches. */
|
|
60
43
|
export function syncDriftOf(held, card, frond) {
|
|
61
44
|
const served = servedShapes(card, frond);
|
|
62
45
|
const drift = { frond, gone: [], moved: [] };
|
package/dist/sync.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,IAAI,EAAuD,MAAM,iBAAiB,CAAC;AAoB5F,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;QAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkD,CAAC;QAChF,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;IACzE,CAAC;IAAC,MAAM,CAAC;QACP,sEAAsE;QACtE,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
|
package/dist/vitest.d.ts
CHANGED
|
@@ -1,22 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The vitest configuration a Fougere project needs, so nobody has to discover it.
|
|
3
|
-
*
|
|
4
|
-
* One thing to know, and it is not obvious: `graphql` guards its types with `instanceOf`,
|
|
5
|
-
* so a schema built by one loaded copy is refused by another with *"from another module
|
|
6
|
-
* or realm"*. Under vitest a module is either transformed by Vite or externalized and
|
|
7
|
-
* loaded by node, and Pothos ending up on one side while `graphql()` sits on the other
|
|
8
|
-
* makes two copies of the same file. The alias pins the path, and the inlining makes the
|
|
9
|
-
* packages that touch it take that path — neither alone is enough, which is what made
|
|
10
|
-
* this cost an afternoon.
|
|
11
|
-
*
|
|
12
|
-
* An app that serves no GraphQL pays nothing for this: the alias resolves to whatever
|
|
13
|
-
* `graphql` the project has, and no `graphql` means the option is simply unused.
|
|
14
|
-
*
|
|
15
|
-
* ```ts
|
|
16
|
-
* // vitest.config.ts
|
|
17
|
-
* import { fougereTest } from '@fougere/testing/vitest';
|
|
18
|
-
* export default fougereTest();
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
1
|
+
/** The vitest configuration a Fougere project needs, so nobody has to discover it. */
|
|
21
2
|
export declare function fougereTest(overrides?: Record<string, unknown>): Record<string, unknown>;
|
|
22
3
|
//# sourceMappingURL=vitest.d.ts.map
|
package/dist/vitest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.d.ts","sourceRoot":"","sources":["../src/vitest.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"vitest.d.ts","sourceRoot":"","sources":["../src/vitest.ts"],"names":[],"mappings":"AAEA,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyB5F"}
|
package/dist/vitest.js
CHANGED
|
@@ -1,24 +1,5 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
|
-
/**
|
|
3
|
-
* The vitest configuration a Fougere project needs, so nobody has to discover it.
|
|
4
|
-
*
|
|
5
|
-
* One thing to know, and it is not obvious: `graphql` guards its types with `instanceOf`,
|
|
6
|
-
* so a schema built by one loaded copy is refused by another with *"from another module
|
|
7
|
-
* or realm"*. Under vitest a module is either transformed by Vite or externalized and
|
|
8
|
-
* loaded by node, and Pothos ending up on one side while `graphql()` sits on the other
|
|
9
|
-
* makes two copies of the same file. The alias pins the path, and the inlining makes the
|
|
10
|
-
* packages that touch it take that path — neither alone is enough, which is what made
|
|
11
|
-
* this cost an afternoon.
|
|
12
|
-
*
|
|
13
|
-
* An app that serves no GraphQL pays nothing for this: the alias resolves to whatever
|
|
14
|
-
* `graphql` the project has, and no `graphql` means the option is simply unused.
|
|
15
|
-
*
|
|
16
|
-
* ```ts
|
|
17
|
-
* // vitest.config.ts
|
|
18
|
-
* import { fougereTest } from '@fougere/testing/vitest';
|
|
19
|
-
* export default fougereTest();
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
2
|
+
/** The vitest configuration a Fougere project needs, so nobody has to discover it. */
|
|
22
3
|
export function fougereTest(overrides = {}) {
|
|
23
4
|
const require = createRequire(import.meta.url);
|
|
24
5
|
let graphqlDir;
|
package/dist/vitest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.js","sourceRoot":"","sources":["../src/vitest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C
|
|
1
|
+
{"version":3,"file":"vitest.js","sourceRoot":"","sources":["../src/vitest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,sFAAsF;AACtF,MAAM,UAAU,WAAW,CAAC,SAAS,GAA4B,EAAE;IACjE,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,UAA8B,CAAC;IACnC,IAAI,CAAC;QACH,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;IACjD,CAAC;IAED,MAAM,IAAI,GAAG;QACX,OAAO,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpF,IAAI,EAAE;YACJ,gFAAgF;YAChF,+CAA+C;YAC/C,OAAO,EAAE,CAAC,oBAAoB,EAAE,6BAA6B,CAAC;YAC9D,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,YAAY,EAAE,cAAc,CAAC,EAAE,EAAE;SAC7D;KACF,CAAC;IAEF,OAAO;QACL,GAAG,IAAI;QACP,GAAG,SAAS;QACZ,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,OAAiB,IAAI,EAAE,CAAC,EAAE;QACpE,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,IAAc,IAAI,EAAE,CAAC,EAAE;KAC5D,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fougere/testing",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0-alpha.0",
|
|
4
4
|
"description": "Tests derived from the declaration — cases, stubs and a gradient of realities.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fougere",
|
|
@@ -34,19 +34,19 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"json-schema-faker": "^0.6.3",
|
|
37
|
-
"@fougere/core": "0.
|
|
38
|
-
"@fougere/
|
|
39
|
-
"@fougere/
|
|
40
|
-
"@fougere/
|
|
41
|
-
"@fougere/
|
|
42
|
-
"@fougere/schema": "0.
|
|
37
|
+
"@fougere/core": "0.7.0-alpha.0",
|
|
38
|
+
"@fougere/defaults": "0.7.0-alpha.0",
|
|
39
|
+
"@fougere/app": "0.7.0-alpha.0",
|
|
40
|
+
"@fougere/transport-http": "0.7.0-alpha.0",
|
|
41
|
+
"@fougere/container": "0.7.0-alpha.0",
|
|
42
|
+
"@fougere/schema": "0.7.0-alpha.0"
|
|
43
43
|
},
|
|
44
44
|
"publishConfig": {
|
|
45
45
|
"access": "public"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"vitest": ">=2",
|
|
49
|
-
"@fougere/adapter-graphql": "0.
|
|
49
|
+
"@fougere/adapter-graphql": "0.7.0-alpha.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependenciesMeta": {
|
|
52
52
|
"vitest": {
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"vitest": "^4.1.0",
|
|
61
|
-
"@fougere/adapter-graphql": "0.
|
|
61
|
+
"@fougere/adapter-graphql": "0.7.0-alpha.0"
|
|
62
62
|
},
|
|
63
63
|
"scripts": {
|
|
64
64
|
"build": "rm -rf dist && tsc",
|
package/src/all.ts
CHANGED
|
@@ -11,13 +11,7 @@ export interface CheckAllOptions extends DoorOptions, CheckOptions {
|
|
|
11
11
|
doors?: boolean;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
/**
|
|
15
|
-
* Every entity the app SERVES, with its handler.
|
|
16
|
-
*
|
|
17
|
-
* Not every entity it scanned: one with no handler has no façade, so there is no door to
|
|
18
|
-
* ask — the distinction the NOT_FOUND message used to miss. A relation is not followed
|
|
19
|
-
* either; the entity it points at is checked on its own turn if it has a door.
|
|
20
|
-
*/
|
|
14
|
+
/** Every entity the app SERVES, with its handler. */
|
|
21
15
|
export function servedEntities(app: App): { name: string; entity: SchemaView }[] {
|
|
22
16
|
const served: { name: string; entity: SchemaView }[] = [];
|
|
23
17
|
for (const frond of app.fronds) {
|
|
@@ -29,16 +23,7 @@ export function servedEntities(app: App): { name: string; entity: SchemaView }[]
|
|
|
29
23
|
return served;
|
|
30
24
|
}
|
|
31
25
|
|
|
32
|
-
/**
|
|
33
|
-
* The whole suite, for every entity, from a file that names none of them.
|
|
34
|
-
*
|
|
35
|
-
* The list comes from the scan rather than from imports, and that is the point: a list of
|
|
36
|
-
* imports is a second copy of what the project already declares, and it goes stale the day
|
|
37
|
-
* an entity is added — silently, because a missing test cannot fail.
|
|
38
|
-
*
|
|
39
|
-
* An entity whose frond is declared in `remotes:` is not here at all: it is not this app's
|
|
40
|
-
* to serve, and `testApp` does not follow the topology in the first place.
|
|
41
|
-
*/
|
|
26
|
+
/** The whole suite, for every entity, from a file that names none of them. */
|
|
42
27
|
export function checkAll(app: App, options: CheckAllOptions = {}): void {
|
|
43
28
|
const except = new Set(options.except ?? []);
|
|
44
29
|
const served = servedEntities(app).filter((one) => !except.has(one.name));
|
package/src/app.ts
CHANGED
|
@@ -7,11 +7,7 @@ import { scopeOfRun } from './scope.js';
|
|
|
7
7
|
import { lowerFirst } from '@fougere/schema';
|
|
8
8
|
|
|
9
9
|
export interface TestAppOptions {
|
|
10
|
-
/**
|
|
11
|
-
* The project to scan. Read from the test file's own position when absent — a file
|
|
12
|
-
* under `fronds/blog/tests/` states that its subject is `blog` and that the project
|
|
13
|
-
* starts above `fronds/`.
|
|
14
|
-
*/
|
|
10
|
+
/** The project to scan. */
|
|
15
11
|
root?: string;
|
|
16
12
|
/** Boot only these fronds, by name. Deduced from the position when absent. */
|
|
17
13
|
fronds?: string[];
|
|
@@ -20,15 +16,7 @@ export interface TestAppOptions {
|
|
|
20
16
|
* through `expect.getState()`; anything else hands its own path in.
|
|
21
17
|
*/
|
|
22
18
|
testPath?: string;
|
|
23
|
-
/**
|
|
24
|
-
* Where the rows go. `':memory:'` by default — a real SQLite engine, so the DDL, the
|
|
25
|
-
* `CHECK` constraints, `unique` and real transactions are all exercised, and nothing is
|
|
26
|
-
* written to disk.
|
|
27
|
-
*
|
|
28
|
-
* Not an in-memory ORM: `createMemoryOrm` realizes the axes but is not the engine
|
|
29
|
-
* production runs, and a tool whose thesis is *the realizations must agree* cannot pick
|
|
30
|
-
* the one that does not ship.
|
|
31
|
-
*/
|
|
19
|
+
/** Where the rows go. */
|
|
32
20
|
db?: string;
|
|
33
21
|
/**
|
|
34
22
|
* Follow `remotes:` from the config. False by default — a test that meant to exercise
|
|
@@ -46,30 +34,11 @@ export interface TestAppOptions {
|
|
|
46
34
|
export interface TestApp extends App {
|
|
47
35
|
/** The double installed for a port, to state a return or read what was called. */
|
|
48
36
|
stub<T>(port: abstract new (...args: never[]) => T): Stub<T>;
|
|
49
|
-
/**
|
|
50
|
-
* What was announced under a fact's name, in order.
|
|
51
|
-
*
|
|
52
|
-
* Read from the carrier's own seat: `Emissions.announce` hands EVERY announced fact to
|
|
53
|
-
* `onEmit`, whether or not anything in this process listens. So watching costs nothing
|
|
54
|
-
* and adds no second dispatcher — the one thing `Emissions` refuses to become.
|
|
55
|
-
*
|
|
56
|
-
* Its dual needs no help at all: `app.deliver(fact, payload)` is already the carrier's
|
|
57
|
-
* door, and it rejects when a subscriber refuses.
|
|
58
|
-
*/
|
|
37
|
+
/** What was announced under a fact's name, in order. */
|
|
59
38
|
announced(fact: { name: string } | string): unknown[];
|
|
60
39
|
}
|
|
61
40
|
|
|
62
|
-
/**
|
|
63
|
-
* An app to ask questions of, wired the conventional way.
|
|
64
|
-
*
|
|
65
|
-
* Wraps `boot()`, which already loads the config, creates the container, sets the storage
|
|
66
|
-
* up and seeds — its own comment names tests among the surfaces it serves. What this adds
|
|
67
|
-
* is the two decisions a test makes differently: the rows live in memory, and the
|
|
68
|
-
* topology is not followed.
|
|
69
|
-
*
|
|
70
|
-
* Storage still goes through `resolveStorage`, the single place that knows a storage
|
|
71
|
-
* package; calling `setupSqlite` here would be a second one.
|
|
72
|
-
*/
|
|
41
|
+
/** An app to ask questions of, wired the conventional way. */
|
|
73
42
|
export async function testApp(options: TestAppOptions = {}): Promise<TestApp> {
|
|
74
43
|
const db: DbConfig = { dialect: 'sqlite', path: options.db ?? ':memory:' };
|
|
75
44
|
// The position is consulted only for what the caller did not state: an explicit `root`
|
|
@@ -113,12 +82,7 @@ export async function testApp(options: TestAppOptions = {}): Promise<TestApp> {
|
|
|
113
82
|
});
|
|
114
83
|
}
|
|
115
84
|
|
|
116
|
-
/**
|
|
117
|
-
* Vitest's own answer to "which file is running", or nothing.
|
|
118
|
-
*
|
|
119
|
-
* Imported dynamically: a package that imports vitest at the top level stops being
|
|
120
|
-
* loadable outside a test run, and `testApp` is meant to work under any host.
|
|
121
|
-
*/
|
|
85
|
+
/** Vitest's own answer to "which file is running", or nothing. */
|
|
122
86
|
function currentTestPath(): string | undefined {
|
|
123
87
|
const globals = globalThis as { __vitest_worker__?: { filepath?: string } };
|
|
124
88
|
return globals.__vitest_worker__?.filepath;
|