@noego/wood 0.6.2 → 0.7.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 +7 -0
- package/dist/browser-test-setup.cjs +29 -0
- package/dist/browser-test-setup.cjs.map +1 -0
- package/dist/browser-test-setup.d.cts +8 -0
- package/dist/browser-test-setup.d.ts +8 -0
- package/dist/browser-test-setup.js +9 -0
- package/dist/browser-test-setup.js.map +1 -0
- package/dist/client/global_polyfill.d.cts +1 -0
- package/dist/client/global_polyfill.d.ts +1 -0
- package/dist/client/index.cjs +7 -0
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +7 -4
- package/dist/client/index.d.ts +7 -4
- package/dist/client/index.js +6 -1
- package/dist/client/index.js.map +1 -1
- package/dist/codegen/renderer_app_generator.cjs +97 -24
- package/dist/codegen/renderer_app_generator.cjs.map +1 -1
- package/dist/codegen/renderer_app_generator.js +97 -24
- package/dist/codegen/renderer_app_generator.js.map +1 -1
- package/dist/codegen/type_generator.cjs +9 -0
- package/dist/codegen/type_generator.cjs.map +1 -1
- package/dist/codegen/type_generator.js +9 -0
- package/dist/codegen/type_generator.js.map +1 -1
- package/dist/config/config_parser.cjs +10 -0
- package/dist/config/config_parser.cjs.map +1 -1
- package/dist/config/config_parser.js +10 -0
- package/dist/config/config_parser.js.map +1 -1
- package/dist/fetch.cjs +38 -0
- package/dist/fetch.cjs.map +1 -0
- package/dist/fetch.d.cts +7 -0
- package/dist/fetch.d.ts +7 -0
- package/dist/fetch.js +12 -0
- package/dist/fetch.js.map +1 -0
- package/dist/frontend/frontend_page.cjs +3 -3
- package/dist/frontend/frontend_page.cjs.map +1 -1
- package/dist/frontend/frontend_page.d.cts +1 -1
- package/dist/frontend/frontend_page.d.ts +1 -1
- package/dist/frontend/frontend_page.js +3 -3
- package/dist/frontend/frontend_page.js.map +1 -1
- package/dist/frontend/frontend_surface.cjs +31 -17
- package/dist/frontend/frontend_surface.cjs.map +1 -1
- package/dist/frontend/frontend_surface.d.cts +12 -2
- package/dist/frontend/frontend_surface.d.ts +12 -2
- package/dist/frontend/frontend_surface.js +37 -17
- package/dist/frontend/frontend_surface.js.map +1 -1
- package/dist/frontend/index.d.cts +2 -0
- package/dist/frontend/index.d.ts +2 -0
- package/dist/index.cjs +5 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/loader/index.cjs +19 -2
- package/dist/loader/index.cjs.map +1 -1
- package/dist/loader/index.d.cts +1 -0
- package/dist/loader/index.d.ts +1 -0
- package/dist/loader/index.js +19 -1
- package/dist/loader/index.js.map +1 -1
- package/dist/loader/loader_orchestration.cjs +82 -0
- package/dist/loader/loader_orchestration.cjs.map +1 -0
- package/dist/loader/loader_orchestration.d.cts +66 -0
- package/dist/loader/loader_orchestration.d.ts +66 -0
- package/dist/loader/loader_orchestration.js +51 -0
- package/dist/loader/loader_orchestration.js.map +1 -0
- package/dist/loader/loader_runner.cjs +46 -41
- package/dist/loader/loader_runner.cjs.map +1 -1
- package/dist/loader/loader_runner.d.cts +12 -6
- package/dist/loader/loader_runner.d.ts +12 -6
- package/dist/loader/loader_runner.js +50 -41
- package/dist/loader/loader_runner.js.map +1 -1
- package/dist/native_browser.types-BY2daUOS.d.ts +189 -0
- package/dist/native_browser.types-vWXtE4rM.d.cts +189 -0
- package/dist/navigation/index.cjs +15 -2
- package/dist/navigation/index.cjs.map +1 -1
- package/dist/navigation/index.d.cts +2 -0
- package/dist/navigation/index.d.ts +2 -0
- package/dist/navigation/index.js +8 -1
- package/dist/navigation/index.js.map +1 -1
- package/dist/runtime/get_container.cjs +2 -0
- package/dist/runtime/get_container.cjs.map +1 -1
- package/dist/runtime/get_container.js +2 -0
- package/dist/runtime/get_container.js.map +1 -1
- package/dist/runtime/index.cjs +5 -0
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +2 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.js +3 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/runtime_capabilities.cjs +35 -0
- package/dist/runtime/runtime_capabilities.cjs.map +1 -0
- package/dist/runtime/runtime_capabilities.d.cts +6 -0
- package/dist/runtime/runtime_capabilities.d.ts +6 -0
- package/dist/runtime/runtime_capabilities.js +11 -0
- package/dist/runtime/runtime_capabilities.js.map +1 -0
- package/dist/runtime/runtime_module.cjs +2 -0
- package/dist/runtime/runtime_module.cjs.map +1 -1
- package/dist/runtime/runtime_module.js +2 -0
- package/dist/runtime/runtime_module.js.map +1 -1
- package/dist/test-wood.cjs +150 -0
- package/dist/test-wood.cjs.map +1 -0
- package/dist/test-wood.d.cts +62 -0
- package/dist/test-wood.d.ts +62 -0
- package/dist/test-wood.js +115 -0
- package/dist/test-wood.js.map +1 -0
- package/dist/testing/browser.cjs +92 -163
- package/dist/testing/browser.cjs.map +1 -1
- package/dist/testing/browser.d.cts +14 -13
- package/dist/testing/browser.d.ts +14 -13
- package/dist/testing/browser.js +88 -162
- package/dist/testing/browser.js.map +1 -1
- package/dist/testing/create_controller_harness.d.cts +2 -1
- package/dist/testing/create_controller_harness.d.ts +2 -1
- package/dist/testing/create_router_bridge.cjs +19 -15
- package/dist/testing/create_router_bridge.cjs.map +1 -1
- package/dist/testing/create_router_bridge.d.cts +8 -1
- package/dist/testing/create_router_bridge.d.ts +8 -1
- package/dist/testing/create_router_bridge.js +18 -15
- package/dist/testing/create_router_bridge.js.map +1 -1
- package/dist/testing/index.cjs +12 -4
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +11 -5
- package/dist/testing/index.d.ts +11 -5
- package/dist/testing/index.js +9 -3
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/native_browser/browser_pool.cjs +31 -0
- package/dist/testing/native_browser/browser_pool.cjs.map +1 -0
- package/dist/testing/native_browser/browser_pool.d.cts +1 -0
- package/dist/testing/native_browser/browser_pool.d.ts +1 -0
- package/dist/testing/native_browser/browser_pool.js +6 -0
- package/dist/testing/native_browser/browser_pool.js.map +1 -0
- package/dist/testing/native_browser/happy_dom_tab.cjs +107 -0
- package/dist/testing/native_browser/happy_dom_tab.cjs.map +1 -0
- package/dist/testing/native_browser/happy_dom_tab.d.cts +35 -0
- package/dist/testing/native_browser/happy_dom_tab.d.ts +35 -0
- package/dist/testing/native_browser/happy_dom_tab.js +73 -0
- package/dist/testing/native_browser/happy_dom_tab.js.map +1 -0
- package/dist/testing/native_browser/happy_dom_transfer.cjs +29 -0
- package/dist/testing/native_browser/happy_dom_transfer.cjs.map +1 -0
- package/dist/testing/native_browser/happy_dom_transfer.d.cts +1 -0
- package/dist/testing/native_browser/happy_dom_transfer.d.ts +1 -0
- package/dist/testing/native_browser/happy_dom_transfer.js +5 -0
- package/dist/testing/native_browser/happy_dom_transfer.js.map +1 -0
- package/dist/testing/native_browser/host_transport.cjs +89 -0
- package/dist/testing/native_browser/host_transport.cjs.map +1 -0
- package/dist/testing/native_browser/host_transport.d.cts +44 -0
- package/dist/testing/native_browser/host_transport.d.ts +44 -0
- package/dist/testing/native_browser/host_transport.js +65 -0
- package/dist/testing/native_browser/host_transport.js.map +1 -0
- package/dist/testing/native_browser/native_browser.types.cjs +17 -0
- package/dist/testing/native_browser/native_browser.types.cjs.map +1 -0
- package/dist/testing/native_browser/native_browser.types.d.cts +31 -0
- package/dist/testing/native_browser/native_browser.types.d.ts +31 -0
- package/dist/testing/native_browser/native_browser.types.js +1 -0
- package/dist/testing/native_browser/native_browser.types.js.map +1 -0
- package/dist/testing/native_browser/native_browser_environment.cjs +143 -0
- package/dist/testing/native_browser/native_browser_environment.cjs.map +1 -0
- package/dist/testing/native_browser/native_browser_environment.d.cts +36 -0
- package/dist/testing/native_browser/native_browser_environment.d.ts +36 -0
- package/dist/testing/native_browser/native_browser_environment.js +109 -0
- package/dist/testing/native_browser/native_browser_environment.js.map +1 -0
- package/dist/testing/native_browser/native_browser_lifecycle.cjs +31 -0
- package/dist/testing/native_browser/native_browser_lifecycle.cjs.map +1 -0
- package/dist/testing/native_browser/native_browser_lifecycle.d.cts +1 -0
- package/dist/testing/native_browser/native_browser_lifecycle.d.ts +1 -0
- package/dist/testing/native_browser/native_browser_lifecycle.js +6 -0
- package/dist/testing/native_browser/native_browser_lifecycle.js.map +1 -0
- package/dist/testing/native_browser/playwright_tab.cjs +124 -0
- package/dist/testing/native_browser/playwright_tab.cjs.map +1 -0
- package/dist/testing/native_browser/playwright_tab.d.cts +35 -0
- package/dist/testing/native_browser/playwright_tab.d.ts +35 -0
- package/dist/testing/native_browser/playwright_tab.js +100 -0
- package/dist/testing/native_browser/playwright_tab.js.map +1 -0
- package/dist/testing/native_browser/renderer_compilation.cjs +149 -0
- package/dist/testing/native_browser/renderer_compilation.cjs.map +1 -0
- package/dist/testing/native_browser/renderer_compilation.d.cts +35 -0
- package/dist/testing/native_browser/renderer_compilation.d.ts +35 -0
- package/dist/testing/native_browser/renderer_compilation.js +115 -0
- package/dist/testing/native_browser/renderer_compilation.js.map +1 -0
- package/dist/testing/native_browser/renderer_entry.cjs +148 -0
- package/dist/testing/native_browser/renderer_entry.cjs.map +1 -0
- package/dist/testing/native_browser/renderer_entry.d.cts +13 -0
- package/dist/testing/native_browser/renderer_entry.d.ts +13 -0
- package/dist/testing/native_browser/renderer_entry.js +114 -0
- package/dist/testing/native_browser/renderer_entry.js.map +1 -0
- package/dist/testing/registration_only_root.cjs +61 -5
- package/dist/testing/registration_only_root.cjs.map +1 -1
- package/dist/testing/registration_only_root.d.cts +25 -4
- package/dist/testing/registration_only_root.d.ts +25 -4
- package/dist/testing/registration_only_root.js +60 -5
- package/dist/testing/registration_only_root.js.map +1 -1
- package/dist/testing/runner_importer.cjs +75 -0
- package/dist/testing/runner_importer.cjs.map +1 -0
- package/dist/testing/runner_importer.d.cts +8 -0
- package/dist/testing/runner_importer.d.ts +8 -0
- package/dist/testing/runner_importer.js +41 -0
- package/dist/testing/runner_importer.js.map +1 -0
- package/dist/testing/test_wood_config.cjs +387 -272
- package/dist/testing/test_wood_config.cjs.map +1 -1
- package/dist/testing/test_wood_config.d.cts +18 -123
- package/dist/testing/test_wood_config.d.ts +18 -123
- package/dist/testing/test_wood_config.js +396 -270
- package/dist/testing/test_wood_config.js.map +1 -1
- package/dist/testing/wood_config_source.cjs +12 -0
- package/dist/testing/wood_config_source.cjs.map +1 -1
- package/dist/testing/wood_config_source.d.cts +10 -0
- package/dist/testing/wood_config_source.d.ts +10 -0
- package/dist/testing/wood_config_source.js +12 -0
- package/dist/testing/wood_config_source.js.map +1 -1
- package/dist/testing/wood_env_renderer.cjs +28 -3
- package/dist/testing/wood_env_renderer.cjs.map +1 -1
- package/dist/testing/wood_env_renderer.d.cts +12 -1
- package/dist/testing/wood_env_renderer.d.ts +12 -1
- package/dist/testing/wood_env_renderer.js +28 -3
- package/dist/testing/wood_env_renderer.js.map +1 -1
- package/dist/testing/wood_lazy_runtime.cjs +109 -0
- package/dist/testing/wood_lazy_runtime.cjs.map +1 -0
- package/dist/testing/wood_lazy_runtime.d.cts +36 -0
- package/dist/testing/wood_lazy_runtime.d.ts +36 -0
- package/dist/testing/wood_lazy_runtime.js +84 -0
- package/dist/testing/wood_lazy_runtime.js.map +1 -0
- package/dist/testing/wood_test_selection.cjs +34 -55
- package/dist/testing/wood_test_selection.cjs.map +1 -1
- package/dist/testing/wood_test_selection.d.cts +18 -24
- package/dist/testing/wood_test_selection.d.ts +18 -24
- package/dist/testing/wood_test_selection.js +30 -54
- package/dist/testing/wood_test_selection.js.map +1 -1
- package/dist/testing-api.cjs +17 -0
- package/dist/testing-api.cjs.map +1 -0
- package/dist/testing-api.d.cts +18 -0
- package/dist/testing-api.d.ts +18 -0
- package/dist/testing-api.js +1 -0
- package/dist/testing-api.js.map +1 -0
- package/dist/types/config.cjs.map +1 -1
- package/dist/types/config.d.cts +4 -0
- package/dist/types/config.d.ts +4 -0
- package/docs/native-browser-testing.md +164 -0
- package/package.json +31 -5
- package/src/components/NavigationShell.browser.test.ts +10 -10
- package/src/components/NavigationShell.cleanup.browser.test.ts +57 -0
- package/src/components/NavigationShell.scopes.browser.test.ts +5 -5
- package/src/components/NavigationShell.svelte +50 -24
|
@@ -1,5 +1,24 @@
|
|
|
1
|
+
import { defineModule, LoadAs } from "@noego/ioc";
|
|
1
2
|
import { createWoodRoot } from "../runtime/get_container.js";
|
|
2
3
|
import { TestWoodError } from "./test_wood.js";
|
|
4
|
+
const APPLICATION_TEST_MARK = /* @__PURE__ */ Symbol.for("@noego/testing.application.v1");
|
|
5
|
+
function refine(binding, lifetime) {
|
|
6
|
+
if (lifetime === "singleton") binding.singleton();
|
|
7
|
+
else if (lifetime === "scoped") binding.scoped();
|
|
8
|
+
else if (lifetime === "transient") binding.transient();
|
|
9
|
+
}
|
|
10
|
+
function lifetimeOf(options) {
|
|
11
|
+
switch (options?.loadAs) {
|
|
12
|
+
case LoadAs.Singleton:
|
|
13
|
+
return "singleton";
|
|
14
|
+
case LoadAs.Scoped:
|
|
15
|
+
return "scoped";
|
|
16
|
+
case LoadAs.Transient:
|
|
17
|
+
return "transient";
|
|
18
|
+
default:
|
|
19
|
+
return void 0;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
3
22
|
function errorMessage(error) {
|
|
4
23
|
const message = error instanceof Error ? error.message : String(error);
|
|
5
24
|
const nested = error?.failures;
|
|
@@ -28,12 +47,24 @@ async function cleanupAll(message, actions) {
|
|
|
28
47
|
if (failures.length) throw new TestWoodCleanupError(message, failures);
|
|
29
48
|
}
|
|
30
49
|
class RegistrationOnlyRoot {
|
|
31
|
-
|
|
50
|
+
/**
|
|
51
|
+
* @param hookName the app hook that may register on this root
|
|
52
|
+
* @param applicationTest the config path identifying the application test;
|
|
53
|
+
* registered on the ACTUAL root under the shared
|
|
54
|
+
* `@noego/testing.application.v1` marker before any hook runs, so
|
|
55
|
+
* frameworks reading the IoC async-context ABI (e.g. Proper's migration
|
|
56
|
+
* guard) recognize Wood startup/invocation as an application test.
|
|
57
|
+
* Production roots are never marked.
|
|
58
|
+
*/
|
|
59
|
+
constructor(hookName, applicationTest) {
|
|
32
60
|
this.hookName = hookName;
|
|
33
61
|
this.owners = /* @__PURE__ */ new Set();
|
|
34
62
|
this.actualRoot = createWoodRoot();
|
|
35
63
|
this.target = null;
|
|
36
64
|
this.replayed = false;
|
|
65
|
+
/** Every production registration as a declarative binding (the shared overlay catalog input). */
|
|
66
|
+
this.declarations = [];
|
|
67
|
+
this.actualRoot.registerFunction(APPLICATION_TEST_MARK, () => applicationTest, { owned: false });
|
|
37
68
|
const registrationOnly = this;
|
|
38
69
|
this.root = new Proxy(this.actualRoot, {
|
|
39
70
|
get(_target, property) {
|
|
@@ -41,6 +72,8 @@ class RegistrationOnlyRoot {
|
|
|
41
72
|
return (classDefinition, options) => {
|
|
42
73
|
registrationOnly.assertRecording("registerClass");
|
|
43
74
|
registrationOnly.declare(classDefinition);
|
|
75
|
+
const lifetime = lifetimeOf(options);
|
|
76
|
+
registrationOnly.declarations.push((bind) => refine(bind(classDefinition).toSelf(), lifetime));
|
|
44
77
|
registrationOnly.actualRoot.registerClass(classDefinition, options);
|
|
45
78
|
};
|
|
46
79
|
}
|
|
@@ -48,9 +81,10 @@ class RegistrationOnlyRoot {
|
|
|
48
81
|
return (token, factory, options) => {
|
|
49
82
|
registrationOnly.assertRecording("registerFunction");
|
|
50
83
|
registrationOnly.declare(token);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
84
|
+
const dependencies = [...options?.param ?? []];
|
|
85
|
+
for (const dependency of dependencies) registrationOnly.declare(dependency);
|
|
86
|
+
const lifetime = lifetimeOf(options);
|
|
87
|
+
registrationOnly.declarations.push((bind) => refine(bind(token).toFactory(factory, dependencies), lifetime));
|
|
54
88
|
registrationOnly.actualRoot.registerFunction(token, factory, options);
|
|
55
89
|
};
|
|
56
90
|
}
|
|
@@ -88,6 +122,25 @@ class RegistrationOnlyRoot {
|
|
|
88
122
|
this.declare(injected?.has(index) ? injected.get(index) : design[index]);
|
|
89
123
|
}
|
|
90
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Declare a token this root binds later (at runtime initialization) as a
|
|
127
|
+
* provider so the shared overlay catalog can resolve replacements for it.
|
|
128
|
+
* The placeholder factory is description only and never resolves.
|
|
129
|
+
*/
|
|
130
|
+
declareBinding(token, lifetime) {
|
|
131
|
+
this.declare(token);
|
|
132
|
+
const hookName = this.hookName;
|
|
133
|
+
this.declarations.push((bind) => refine(bind(token).toFactory(() => {
|
|
134
|
+
throw new TestWoodError(`${hookName} declared-only binding ${String(token)} has no production factory`);
|
|
135
|
+
}, []), lifetime));
|
|
136
|
+
}
|
|
137
|
+
/** The recorded production registrations as a declarative module (description only, never built). */
|
|
138
|
+
module() {
|
|
139
|
+
const declarations = [...this.declarations];
|
|
140
|
+
return defineModule(`@noego/wood/testing/${this.hookName}`, (bind) => {
|
|
141
|
+
for (const declaration of declarations) declaration(bind);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
91
144
|
replay(root) {
|
|
92
145
|
if (this.replayed) throw new TestWoodError(`${this.hookName} registrations were already replayed`);
|
|
93
146
|
this.replayed = true;
|
|
@@ -105,11 +158,12 @@ class RegistrationOnlyRoot {
|
|
|
105
158
|
}
|
|
106
159
|
}
|
|
107
160
|
}
|
|
108
|
-
async function buildRecordedEnvironment(builder, recorded, owner) {
|
|
161
|
+
async function buildRecordedEnvironment(builder, recorded, owner, borrowedTokens = []) {
|
|
109
162
|
const partial = { root: recorded.actualRoot };
|
|
110
163
|
try {
|
|
111
164
|
const environment = await builder.build({
|
|
112
165
|
root: recorded.actualRoot,
|
|
166
|
+
borrowedTokens,
|
|
113
167
|
prepare: (freshRoot) => {
|
|
114
168
|
partial.root = freshRoot;
|
|
115
169
|
recorded.replay(freshRoot);
|
|
@@ -133,6 +187,7 @@ async function buildRecordedEnvironment(builder, recorded, owner) {
|
|
|
133
187
|
}
|
|
134
188
|
}
|
|
135
189
|
export {
|
|
190
|
+
APPLICATION_TEST_MARK,
|
|
136
191
|
RegistrationOnlyRoot,
|
|
137
192
|
TestWoodCleanupError,
|
|
138
193
|
buildRecordedEnvironment,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/testing/registration_only_root.ts"],"sourcesContent":["import type { IContainer } from '@noego/ioc';\nimport { createWoodRoot } from '../runtime/get_container.js';\nimport type { TestEnvironment, TestIocBuilder } from '@noego/testing';\nimport { TestWoodError } from './test_wood.js';\n\n\nexport interface CleanupFailure {\n readonly owner: string;\n readonly error: unknown;\n}\n\nfunction errorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n const nested = (error as { failures?: Array<{ error: unknown }> } | null)?.failures;\n return Array.isArray(nested) ? message + ': ' + nested.map(failure => errorMessage(failure.error)).join('; ') : message;\n}\n\n/**\n * Error raised after every requested owner has been given a chance to clean up.\n * The structured failures are retained for assertions and callers that need to\n * inspect the original errors.\n */\nexport class TestWoodCleanupError extends TestWoodError {\n readonly failures: readonly CleanupFailure[];\n\n constructor(message: string, failures: readonly CleanupFailure[], cause?: unknown) {\n super(\n `${message} (${failures.length} failure(s)):\\n ` +\n failures.map(({ owner, error }) => `${owner}: ${errorMessage(error)}`).join('\\n '),\n );\n this.name = 'TestWoodCleanupError';\n this.failures = failures;\n if (cause !== undefined) (this as Error & { cause?: unknown }).cause = cause;\n }\n}\n\n/** Run every cleanup action in order, collecting rather than short-circuiting. */\nexport async function cleanupAll(\n message: string,\n actions: ReadonlyArray<readonly [owner: string, action: () => void | Promise<void>]>,\n): Promise<void> {\n const failures: CleanupFailure[] = [];\n for (const [owner, action] of actions) {\n try {\n await action();\n } catch (error) {\n failures.push({ owner, error });\n }\n }\n if (failures.length) throw new TestWoodCleanupError(message, failures);\n}\n\n/**\n * A registration-only view of the real root owned by this environment.\n *\n * Registrations land immediately on that root; shared @noego/testing applies\n * scenario overlays to it without replay. Resolution is unavailable until it has been\n * built and the test overlays and method decorator are installed.\n */\nexport class RegistrationOnlyRoot {\n readonly owners = new Set<unknown>();\n readonly root: IContainer;\n\n readonly actualRoot = createWoodRoot();\n private target: IContainer | null = null;\n private replayed = false;\n\n constructor(private readonly hookName: string) {\n const registrationOnly = this;\n this.root = new Proxy(this.actualRoot, {\n get(_target, property) {\n if (property === 'registerClass') {\n return (classDefinition: new (...args: any[]) => unknown, options?: unknown): void => {\n registrationOnly.assertRecording('registerClass');\n registrationOnly.declare(classDefinition);\n registrationOnly.actualRoot.registerClass(classDefinition, options as never);\n };\n }\n if (property === 'registerFunction') {\n return (token: unknown, factory: (...args: any[]) => unknown, options?: unknown): void => {\n registrationOnly.assertRecording('registerFunction');\n registrationOnly.declare(token);\n for (const dependency of (options as { param?: unknown[] } | undefined)?.param ?? []) {\n registrationOnly.declare(dependency);\n }\n registrationOnly.actualRoot.registerFunction(token, factory, options as never);\n };\n }\n if (property === 'isRegistered') {\n return (token: unknown): boolean =>\n registrationOnly.target?.isRegistered(token) ?? registrationOnly.owners.has(token);\n }\n if (property === 'isDisposed') {\n return (): boolean => registrationOnly.target?.isDisposed() ?? false;\n }\n\n const live = registrationOnly.target;\n if (live) {\n const value = Reflect.get(live as object, property, live);\n return typeof value === 'function' ? value.bind(live) : value;\n }\n\n return (..._args: unknown[]): never => {\n const method = String(property);\n throw new TestWoodError(\n `${registrationOnly.hookName} may only register dependencies before test overlays; ` +\n `${method}() attempted eager resolution or root mutation. Move resolution to start(), ` +\n 'a page lifecycle, or the built test environment.',\n );\n };\n },\n });\n }\n\n declare(token: unknown): void {\n if (this.owners.has(token)) return;\n this.owners.add(token);\n if (typeof token !== 'function') return;\n const injected = (Reflect as any).getMetadata?.(\n Symbol.for('ioc:inject:tokens'),\n token,\n ) as Map<number, unknown> | undefined;\n const design = (Reflect as any).getMetadata?.('design:paramtypes', token) ?? [];\n const indices = new Set<number>([...design.keys(), ...(injected?.keys() ?? [])]);\n for (const index of indices) {\n this.declare(injected?.has(index) ? injected.get(index) : design[index]);\n }\n }\n\n replay(root: IContainer): void {\n if (this.replayed) throw new TestWoodError(`${this.hookName} registrations were already replayed`);\n this.replayed = true;\n if (root !== this.actualRoot) throw new TestWoodError('testWood requires @noego/testing with build({ root }) support; update the shared testing package.');\n }\n\n bind(root: IContainer): void {\n if (!this.replayed) throw new TestWoodError(`${this.hookName} registrations must be replayed before binding`);\n this.target = root;\n }\n\n private assertRecording(method: string): void {\n if (this.replayed) {\n throw new TestWoodError(\n `${this.hookName} cannot call ${method}() after test overlays have been installed`,\n );\n }\n }\n}\n\n/**\n * Materialize shared @noego/testing overlays on the same production root,\n * disposing the partially built root if materialization fails.\n */\nexport async function buildRecordedEnvironment(\n builder: TestIocBuilder,\n recorded: RegistrationOnlyRoot,\n owner: string,\n): Promise<TestEnvironment> {\n const partial: { root?: IContainer } = { root: recorded.actualRoot };\n try {\n const environment = await builder.build({\n root: recorded.actualRoot,\n prepare: (freshRoot) => {\n partial.root = freshRoot;\n recorded.replay(freshRoot);\n },\n });\n recorded.bind(environment.root);\n return environment;\n } catch (error) {\n const failures: CleanupFailure[] = [];\n if (partial.root) {\n try {\n await partial.root.dispose();\n } catch (cleanupError) {\n failures.push({ owner: `${owner} root rollback`, error: cleanupError });\n }\n }\n if (failures.length) {\n throw new TestWoodCleanupError(`${owner} build failed and rollback failed`, failures, error);\n }\n throw error;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/testing/registration_only_root.ts"],"sourcesContent":["import type { ApplicationModule, BindFunction, BindingRefinement, IContainer, Lifetime } from '@noego/ioc';\nimport { defineModule, LoadAs } from '@noego/ioc';\nimport { createWoodRoot } from '../runtime/get_container.js';\nimport type { TestEnvironment, TestIocBuilder } from '@noego/testing';\nimport { TestWoodError } from './test_wood.js';\n\ntype ContainerOptions = { loadAs?: LoadAs; param?: unknown[] };\n\n/** Shared application-test marker (same symbol `@noego/app` registers). */\nexport const APPLICATION_TEST_MARK = Symbol.for('@noego/testing.application.v1');\n\nfunction refine(binding: BindingRefinement, lifetime: Lifetime | undefined): void {\n if (lifetime === 'singleton') binding.singleton();\n else if (lifetime === 'scoped') binding.scoped();\n else if (lifetime === 'transient') binding.transient();\n}\n\nfunction lifetimeOf(options: Partial<ContainerOptions> | undefined): Lifetime | undefined {\n switch (options?.loadAs) {\n case LoadAs.Singleton: return 'singleton';\n case LoadAs.Scoped: return 'scoped';\n case LoadAs.Transient: return 'transient';\n default: return undefined;\n }\n}\n\n\nexport interface CleanupFailure {\n readonly owner: string;\n readonly error: unknown;\n}\n\nfunction errorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n const nested = (error as { failures?: Array<{ error: unknown }> } | null)?.failures;\n return Array.isArray(nested) ? message + ': ' + nested.map(failure => errorMessage(failure.error)).join('; ') : message;\n}\n\n/**\n * Error raised after every requested owner has been given a chance to clean up.\n * The structured failures are retained for assertions and callers that need to\n * inspect the original errors.\n */\nexport class TestWoodCleanupError extends TestWoodError {\n readonly failures: readonly CleanupFailure[];\n\n constructor(message: string, failures: readonly CleanupFailure[], cause?: unknown) {\n super(\n `${message} (${failures.length} failure(s)):\\n ` +\n failures.map(({ owner, error }) => `${owner}: ${errorMessage(error)}`).join('\\n '),\n );\n this.name = 'TestWoodCleanupError';\n this.failures = failures;\n if (cause !== undefined) (this as Error & { cause?: unknown }).cause = cause;\n }\n}\n\n/** Run every cleanup action in order, collecting rather than short-circuiting. */\nexport async function cleanupAll(\n message: string,\n actions: ReadonlyArray<readonly [owner: string, action: () => void | Promise<void>]>,\n): Promise<void> {\n const failures: CleanupFailure[] = [];\n for (const [owner, action] of actions) {\n try {\n await action();\n } catch (error) {\n failures.push({ owner, error });\n }\n }\n if (failures.length) throw new TestWoodCleanupError(message, failures);\n}\n\n/**\n * A registration-only view of the real root owned by this environment.\n *\n * Registrations land immediately on that root; shared @noego/testing applies\n * scenario overlays to it without replay. Resolution is unavailable until it has been\n * built and the test overlays and method decorator are installed.\n */\nexport class RegistrationOnlyRoot {\n readonly owners = new Set<unknown>();\n readonly root: IContainer;\n\n readonly actualRoot = createWoodRoot();\n private target: IContainer | null = null;\n private replayed = false;\n /** Every production registration as a declarative binding (the shared overlay catalog input). */\n private readonly declarations: Array<(bind: BindFunction) => void> = [];\n\n /**\n * @param hookName the app hook that may register on this root\n * @param applicationTest the config path identifying the application test;\n * registered on the ACTUAL root under the shared\n * `@noego/testing.application.v1` marker before any hook runs, so\n * frameworks reading the IoC async-context ABI (e.g. Proper's migration\n * guard) recognize Wood startup/invocation as an application test.\n * Production roots are never marked.\n */\n constructor(private readonly hookName: string, applicationTest: string) {\n this.actualRoot.registerFunction(APPLICATION_TEST_MARK, () => applicationTest, { owned: false });\n const registrationOnly = this;\n this.root = new Proxy(this.actualRoot, {\n get(_target, property) {\n if (property === 'registerClass') {\n return (classDefinition: new (...args: any[]) => unknown, options?: unknown): void => {\n registrationOnly.assertRecording('registerClass');\n registrationOnly.declare(classDefinition);\n const lifetime = lifetimeOf(options as Partial<ContainerOptions> | undefined);\n registrationOnly.declarations.push((bind) => refine(bind(classDefinition).toSelf(), lifetime));\n registrationOnly.actualRoot.registerClass(classDefinition, options as never);\n };\n }\n if (property === 'registerFunction') {\n return (token: unknown, factory: (...args: any[]) => unknown, options?: unknown): void => {\n registrationOnly.assertRecording('registerFunction');\n registrationOnly.declare(token);\n const dependencies = [...((options as { param?: unknown[] } | undefined)?.param ?? [])];\n for (const dependency of dependencies) registrationOnly.declare(dependency);\n const lifetime = lifetimeOf(options as Partial<ContainerOptions> | undefined);\n registrationOnly.declarations.push((bind) => refine(bind(token).toFactory(factory, dependencies), lifetime));\n registrationOnly.actualRoot.registerFunction(token, factory, options as never);\n };\n }\n if (property === 'isRegistered') {\n return (token: unknown): boolean =>\n registrationOnly.target?.isRegistered(token) ?? registrationOnly.owners.has(token);\n }\n if (property === 'isDisposed') {\n return (): boolean => registrationOnly.target?.isDisposed() ?? false;\n }\n\n const live = registrationOnly.target;\n if (live) {\n const value = Reflect.get(live as object, property, live);\n return typeof value === 'function' ? value.bind(live) : value;\n }\n\n return (..._args: unknown[]): never => {\n const method = String(property);\n throw new TestWoodError(\n `${registrationOnly.hookName} may only register dependencies before test overlays; ` +\n `${method}() attempted eager resolution or root mutation. Move resolution to start(), ` +\n 'a page lifecycle, or the built test environment.',\n );\n };\n },\n });\n }\n\n declare(token: unknown): void {\n if (this.owners.has(token)) return;\n this.owners.add(token);\n if (typeof token !== 'function') return;\n const injected = (Reflect as any).getMetadata?.(\n Symbol.for('ioc:inject:tokens'),\n token,\n ) as Map<number, unknown> | undefined;\n const design = (Reflect as any).getMetadata?.('design:paramtypes', token) ?? [];\n const indices = new Set<number>([...design.keys(), ...(injected?.keys() ?? [])]);\n for (const index of indices) {\n this.declare(injected?.has(index) ? injected.get(index) : design[index]);\n }\n }\n\n /**\n * Declare a token this root binds later (at runtime initialization) as a\n * provider so the shared overlay catalog can resolve replacements for it.\n * The placeholder factory is description only and never resolves.\n */\n declareBinding(token: unknown, lifetime: Lifetime): void {\n this.declare(token);\n const hookName = this.hookName;\n this.declarations.push((bind) => refine(bind(token).toFactory(() => {\n throw new TestWoodError(`${hookName} declared-only binding ${String(token)} has no production factory`);\n }, []), lifetime));\n }\n\n /** The recorded production registrations as a declarative module (description only, never built). */\n module(): ApplicationModule {\n const declarations = [...this.declarations];\n return defineModule(`@noego/wood/testing/${this.hookName}`, (bind) => {\n for (const declaration of declarations) declaration(bind);\n });\n }\n\n replay(root: IContainer): void {\n if (this.replayed) throw new TestWoodError(`${this.hookName} registrations were already replayed`);\n this.replayed = true;\n if (root !== this.actualRoot) throw new TestWoodError('testWood requires @noego/testing with build({ root }) support; update the shared testing package.');\n }\n\n bind(root: IContainer): void {\n if (!this.replayed) throw new TestWoodError(`${this.hookName} registrations must be replayed before binding`);\n this.target = root;\n }\n\n private assertRecording(method: string): void {\n if (this.replayed) {\n throw new TestWoodError(\n `${this.hookName} cannot call ${method}() after test overlays have been installed`,\n );\n }\n }\n}\n\n/**\n * Materialize shared @noego/testing overlays on the same production root,\n * disposing the partially built root if materialization fails.\n */\nexport async function buildRecordedEnvironment(\n builder: TestIocBuilder,\n recorded: RegistrationOnlyRoot,\n owner: string,\n borrowedTokens: readonly unknown[] = [],\n): Promise<TestEnvironment> {\n const partial: { root?: IContainer } = { root: recorded.actualRoot };\n try {\n const environment = await builder.build({\n root: recorded.actualRoot,\n borrowedTokens,\n prepare: (freshRoot) => {\n partial.root = freshRoot;\n recorded.replay(freshRoot);\n },\n });\n recorded.bind(environment.root);\n return environment;\n } catch (error) {\n const failures: CleanupFailure[] = [];\n if (partial.root) {\n try {\n await partial.root.dispose();\n } catch (cleanupError) {\n failures.push({ owner: `${owner} root rollback`, error: cleanupError });\n }\n }\n if (failures.length) {\n throw new TestWoodCleanupError(`${owner} build failed and rollback failed`, failures, error);\n }\n throw error;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var runner_importer_exports = {};
|
|
30
|
+
__export(runner_importer_exports, {
|
|
31
|
+
vitestModuleImporter: () => vitestModuleImporter
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(runner_importer_exports);
|
|
34
|
+
var import_node_path = __toESM(require("node:path"), 1);
|
|
35
|
+
var import_node_module = require("node:module");
|
|
36
|
+
var import_node_fs = require("node:fs");
|
|
37
|
+
var import_node_url = require("node:url");
|
|
38
|
+
var import_test_wood = require("./test_wood.cjs");
|
|
39
|
+
async function vitestModuleImporter(configPath) {
|
|
40
|
+
const roots = [.../* @__PURE__ */ new Set([process.cwd(), import_node_path.default.dirname(import_node_path.default.resolve(configPath))])];
|
|
41
|
+
let entry;
|
|
42
|
+
let version;
|
|
43
|
+
for (const root of roots) {
|
|
44
|
+
const require2 = (0, import_node_module.createRequire)(import_node_path.default.join(root, "package.json"));
|
|
45
|
+
try {
|
|
46
|
+
const manifest = require2.resolve("vitest/package.json");
|
|
47
|
+
const pkg = JSON.parse((0, import_node_fs.readFileSync)(manifest, "utf8"));
|
|
48
|
+
version = pkg.version;
|
|
49
|
+
const exported = pkg.exports?.["."]?.import;
|
|
50
|
+
const imported = typeof exported === "string" ? exported : exported?.default;
|
|
51
|
+
if (typeof imported !== "string") throw new Error("Vitest has no declared ESM entry");
|
|
52
|
+
entry = import_node_path.default.resolve(import_node_path.default.dirname(manifest), imported);
|
|
53
|
+
break;
|
|
54
|
+
} catch {
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (!entry || !version) throw new import_test_wood.TestWoodError("testWood under Vitest requires a project-local Vitest installation; none was found");
|
|
58
|
+
if (![2, 3, 4].includes(Number(version.split(".")[0]))) {
|
|
59
|
+
throw new import_test_wood.TestWoodError(`testWood under Vitest: unsupported Vitest version ${version}; expected a qualified 2.x, 3.x or 4.x project`);
|
|
60
|
+
}
|
|
61
|
+
const runner = await import(
|
|
62
|
+
/* @vite-ignore */
|
|
63
|
+
(0, import_node_url.pathToFileURL)(entry).href
|
|
64
|
+
);
|
|
65
|
+
if (typeof runner.vi?.importActual !== "function") {
|
|
66
|
+
throw new import_test_wood.TestWoodError(`testWood under Vitest: Vitest ${version} has no public importActual module API`);
|
|
67
|
+
}
|
|
68
|
+
const importActual = runner.vi.importActual.bind(runner.vi);
|
|
69
|
+
return (absolutePath) => importActual(absolutePath);
|
|
70
|
+
}
|
|
71
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
72
|
+
0 && (module.exports = {
|
|
73
|
+
vitestModuleImporter
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=runner_importer.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/testing/runner_importer.ts"],"sourcesContent":["/**\n * Project-local Vitest module identity for `testWood(configPath)` builds.\n *\n * Under Vitest, hook/controller/loader modules are imported through the\n * runner's public module API (`vi.importActual`) rather than a raw dynamic\n * import, so the framework's load of a source file is the SAME module the\n * test file imported (one class identity, one token identity). The closure\n * belongs to one build and one project; nothing process-global is touched.\n */\nimport path from 'node:path';\nimport { createRequire } from 'node:module';\nimport { readFileSync } from 'node:fs';\nimport { pathToFileURL } from 'node:url';\nimport type { ModuleImporter } from './wood_config_source.cjs';\nimport { TestWoodError } from './test_wood.cjs';\n\nexport async function vitestModuleImporter(configPath: string): Promise<ModuleImporter> {\n const roots = [...new Set([process.cwd(), path.dirname(path.resolve(configPath))])];\n let entry: string | undefined;\n let version: string | undefined;\n for (const root of roots) {\n const require = createRequire(path.join(root, 'package.json'));\n try {\n const manifest = require.resolve('vitest/package.json');\n const pkg = JSON.parse(readFileSync(manifest, 'utf8')) as { version: string; exports?: Record<string, unknown> };\n version = pkg.version;\n const exported = (pkg.exports?.['.'] as { import?: string | { default?: string } } | undefined)?.import;\n const imported = typeof exported === 'string' ? exported : exported?.default;\n if (typeof imported !== 'string') throw new Error('Vitest has no declared ESM entry');\n entry = path.resolve(path.dirname(manifest), imported);\n break;\n } catch { /* try the source config's project before reporting unavailable */ }\n }\n if (!entry || !version) throw new TestWoodError('testWood under Vitest requires a project-local Vitest installation; none was found');\n if (![2, 3, 4].includes(Number(version.split('.')[0]))) {\n throw new TestWoodError(`testWood under Vitest: unsupported Vitest version ${version}; expected a qualified 2.x, 3.x or 4.x project`);\n }\n const runner = await import(/* @vite-ignore */ pathToFileURL(entry).href) as {\n vi?: { importActual?: (path: string) => Promise<unknown> };\n };\n if (typeof runner.vi?.importActual !== 'function') {\n throw new TestWoodError(`testWood under Vitest: Vitest ${version} has no public importActual module API`);\n }\n const importActual = runner.vi.importActual.bind(runner.vi);\n return (absolutePath) => importActual(absolutePath);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,uBAAiB;AACjB,yBAA8B;AAC9B,qBAA6B;AAC7B,sBAA8B;AAE9B,uBAA8B;AAE9B,eAAsB,qBAAqB,YAA6C;AACtF,QAAM,QAAQ,CAAC,GAAG,oBAAI,IAAI,CAAC,QAAQ,IAAI,GAAG,iBAAAA,QAAK,QAAQ,iBAAAA,QAAK,QAAQ,UAAU,CAAC,CAAC,CAAC,CAAC;AAClF,MAAI;AACJ,MAAI;AACJ,aAAW,QAAQ,OAAO;AACxB,UAAMC,eAAU,kCAAc,iBAAAD,QAAK,KAAK,MAAM,cAAc,CAAC;AAC7D,QAAI;AACF,YAAM,WAAWC,SAAQ,QAAQ,qBAAqB;AACtD,YAAM,MAAM,KAAK,UAAM,6BAAa,UAAU,MAAM,CAAC;AACrD,gBAAU,IAAI;AACd,YAAM,WAAY,IAAI,UAAU,GAAG,GAA8D;AACjG,YAAM,WAAW,OAAO,aAAa,WAAW,WAAW,UAAU;AACrE,UAAI,OAAO,aAAa,SAAU,OAAM,IAAI,MAAM,kCAAkC;AACpF,cAAQ,iBAAAD,QAAK,QAAQ,iBAAAA,QAAK,QAAQ,QAAQ,GAAG,QAAQ;AACrD;AAAA,IACF,QAAQ;AAAA,IAAqE;AAAA,EAC/E;AACA,MAAI,CAAC,SAAS,CAAC,QAAS,OAAM,IAAI,+BAAc,oFAAoF;AACpI,MAAI,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,OAAO,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG;AACtD,UAAM,IAAI,+BAAc,qDAAqD,OAAO,gDAAgD;AAAA,EACtI;AACA,QAAM,SAAS,MAAM;AAAA;AAAA,QAA0B,+BAAc,KAAK,EAAE;AAAA;AAGpE,MAAI,OAAO,OAAO,IAAI,iBAAiB,YAAY;AACjD,UAAM,IAAI,+BAAc,iCAAiC,OAAO,wCAAwC;AAAA,EAC1G;AACA,QAAM,eAAe,OAAO,GAAG,aAAa,KAAK,OAAO,EAAE;AAC1D,SAAO,CAAC,iBAAiB,aAAa,YAAY;AACpD;","names":["path","require"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ModuleImporter } from './wood_config_source.cjs';
|
|
2
|
+
import '../types/config.cjs';
|
|
3
|
+
import '../types/operations.cjs';
|
|
4
|
+
import '../types/views.cjs';
|
|
5
|
+
|
|
6
|
+
declare function vitestModuleImporter(configPath: string): Promise<ModuleImporter>;
|
|
7
|
+
|
|
8
|
+
export { vitestModuleImporter };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ModuleImporter } from './wood_config_source.js';
|
|
2
|
+
import '../types/config.js';
|
|
3
|
+
import '../types/operations.js';
|
|
4
|
+
import '../types/views.js';
|
|
5
|
+
|
|
6
|
+
declare function vitestModuleImporter(configPath: string): Promise<ModuleImporter>;
|
|
7
|
+
|
|
8
|
+
export { vitestModuleImporter };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { TestWoodError } from "./test_wood.js";
|
|
6
|
+
async function vitestModuleImporter(configPath) {
|
|
7
|
+
const roots = [.../* @__PURE__ */ new Set([process.cwd(), path.dirname(path.resolve(configPath))])];
|
|
8
|
+
let entry;
|
|
9
|
+
let version;
|
|
10
|
+
for (const root of roots) {
|
|
11
|
+
const require2 = createRequire(path.join(root, "package.json"));
|
|
12
|
+
try {
|
|
13
|
+
const manifest = require2.resolve("vitest/package.json");
|
|
14
|
+
const pkg = JSON.parse(readFileSync(manifest, "utf8"));
|
|
15
|
+
version = pkg.version;
|
|
16
|
+
const exported = pkg.exports?.["."]?.import;
|
|
17
|
+
const imported = typeof exported === "string" ? exported : exported?.default;
|
|
18
|
+
if (typeof imported !== "string") throw new Error("Vitest has no declared ESM entry");
|
|
19
|
+
entry = path.resolve(path.dirname(manifest), imported);
|
|
20
|
+
break;
|
|
21
|
+
} catch {
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (!entry || !version) throw new TestWoodError("testWood under Vitest requires a project-local Vitest installation; none was found");
|
|
25
|
+
if (![2, 3, 4].includes(Number(version.split(".")[0]))) {
|
|
26
|
+
throw new TestWoodError(`testWood under Vitest: unsupported Vitest version ${version}; expected a qualified 2.x, 3.x or 4.x project`);
|
|
27
|
+
}
|
|
28
|
+
const runner = await import(
|
|
29
|
+
/* @vite-ignore */
|
|
30
|
+
pathToFileURL(entry).href
|
|
31
|
+
);
|
|
32
|
+
if (typeof runner.vi?.importActual !== "function") {
|
|
33
|
+
throw new TestWoodError(`testWood under Vitest: Vitest ${version} has no public importActual module API`);
|
|
34
|
+
}
|
|
35
|
+
const importActual = runner.vi.importActual.bind(runner.vi);
|
|
36
|
+
return (absolutePath) => importActual(absolutePath);
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
vitestModuleImporter
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=runner_importer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/testing/runner_importer.ts"],"sourcesContent":["/**\n * Project-local Vitest module identity for `testWood(configPath)` builds.\n *\n * Under Vitest, hook/controller/loader modules are imported through the\n * runner's public module API (`vi.importActual`) rather than a raw dynamic\n * import, so the framework's load of a source file is the SAME module the\n * test file imported (one class identity, one token identity). The closure\n * belongs to one build and one project; nothing process-global is touched.\n */\nimport path from 'node:path';\nimport { createRequire } from 'node:module';\nimport { readFileSync } from 'node:fs';\nimport { pathToFileURL } from 'node:url';\nimport type { ModuleImporter } from './wood_config_source.js';\nimport { TestWoodError } from './test_wood.js';\n\nexport async function vitestModuleImporter(configPath: string): Promise<ModuleImporter> {\n const roots = [...new Set([process.cwd(), path.dirname(path.resolve(configPath))])];\n let entry: string | undefined;\n let version: string | undefined;\n for (const root of roots) {\n const require = createRequire(path.join(root, 'package.json'));\n try {\n const manifest = require.resolve('vitest/package.json');\n const pkg = JSON.parse(readFileSync(manifest, 'utf8')) as { version: string; exports?: Record<string, unknown> };\n version = pkg.version;\n const exported = (pkg.exports?.['.'] as { import?: string | { default?: string } } | undefined)?.import;\n const imported = typeof exported === 'string' ? exported : exported?.default;\n if (typeof imported !== 'string') throw new Error('Vitest has no declared ESM entry');\n entry = path.resolve(path.dirname(manifest), imported);\n break;\n } catch { /* try the source config's project before reporting unavailable */ }\n }\n if (!entry || !version) throw new TestWoodError('testWood under Vitest requires a project-local Vitest installation; none was found');\n if (![2, 3, 4].includes(Number(version.split('.')[0]))) {\n throw new TestWoodError(`testWood under Vitest: unsupported Vitest version ${version}; expected a qualified 2.x, 3.x or 4.x project`);\n }\n const runner = await import(/* @vite-ignore */ pathToFileURL(entry).href) as {\n vi?: { importActual?: (path: string) => Promise<unknown> };\n };\n if (typeof runner.vi?.importActual !== 'function') {\n throw new TestWoodError(`testWood under Vitest: Vitest ${version} has no public importActual module API`);\n }\n const importActual = runner.vi.importActual.bind(runner.vi);\n return (absolutePath) => importActual(absolutePath);\n}\n"],"mappings":"AASA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAE9B,SAAS,qBAAqB;AAE9B,eAAsB,qBAAqB,YAA6C;AACtF,QAAM,QAAQ,CAAC,GAAG,oBAAI,IAAI,CAAC,QAAQ,IAAI,GAAG,KAAK,QAAQ,KAAK,QAAQ,UAAU,CAAC,CAAC,CAAC,CAAC;AAClF,MAAI;AACJ,MAAI;AACJ,aAAW,QAAQ,OAAO;AACxB,UAAMA,WAAU,cAAc,KAAK,KAAK,MAAM,cAAc,CAAC;AAC7D,QAAI;AACF,YAAM,WAAWA,SAAQ,QAAQ,qBAAqB;AACtD,YAAM,MAAM,KAAK,MAAM,aAAa,UAAU,MAAM,CAAC;AACrD,gBAAU,IAAI;AACd,YAAM,WAAY,IAAI,UAAU,GAAG,GAA8D;AACjG,YAAM,WAAW,OAAO,aAAa,WAAW,WAAW,UAAU;AACrE,UAAI,OAAO,aAAa,SAAU,OAAM,IAAI,MAAM,kCAAkC;AACpF,cAAQ,KAAK,QAAQ,KAAK,QAAQ,QAAQ,GAAG,QAAQ;AACrD;AAAA,IACF,QAAQ;AAAA,IAAqE;AAAA,EAC/E;AACA,MAAI,CAAC,SAAS,CAAC,QAAS,OAAM,IAAI,cAAc,oFAAoF;AACpI,MAAI,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,OAAO,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG;AACtD,UAAM,IAAI,cAAc,qDAAqD,OAAO,gDAAgD;AAAA,EACtI;AACA,QAAM,SAAS,MAAM;AAAA;AAAA,IAA0B,cAAc,KAAK,EAAE;AAAA;AAGpE,MAAI,OAAO,OAAO,IAAI,iBAAiB,YAAY;AACjD,UAAM,IAAI,cAAc,iCAAiC,OAAO,wCAAwC;AAAA,EAC1G;AACA,QAAM,eAAe,OAAO,GAAG,aAAa,KAAK,OAAO,EAAE;AAC1D,SAAO,CAAC,iBAAiB,aAAa,YAAY;AACpD;","names":["require"]}
|