@noego/wood 0.4.0 → 0.4.2
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 +100 -2
- package/dist/client/global_polyfill.d.cts +1 -2
- package/dist/client/global_polyfill.d.ts +1 -2
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/index.cjs +0 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/dist/main/index.cjs +16 -2
- package/dist/main/index.cjs.map +1 -1
- package/dist/main/index.js +16 -2
- package/dist/main/index.js.map +1 -1
- package/dist/runtime/runtime.cjs +4 -4
- package/dist/runtime/runtime.cjs.map +1 -1
- package/dist/runtime/runtime.d.cts +2 -1
- package/dist/runtime/runtime.d.ts +2 -1
- package/dist/runtime/runtime.js +8 -5
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/testing/browser.cjs +224 -32
- package/dist/testing/browser.cjs.map +1 -1
- package/dist/testing/browser.d.cts +18 -1
- package/dist/testing/browser.d.ts +18 -1
- package/dist/testing/browser.js +226 -32
- package/dist/testing/browser.js.map +1 -1
- package/dist/testing/create_controller_harness.cjs +3 -1
- package/dist/testing/create_controller_harness.cjs.map +1 -1
- package/dist/testing/create_controller_harness.d.cts +4 -2
- package/dist/testing/create_controller_harness.d.ts +4 -2
- package/dist/testing/create_controller_harness.js +3 -1
- package/dist/testing/create_controller_harness.js.map +1 -1
- package/dist/testing/index.cjs +3 -3
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +6 -4
- package/dist/testing/index.d.ts +6 -4
- package/dist/testing/index.js +2 -2
- package/dist/testing/index.js.map +1 -1
- package/dist/trace-testing/index.cjs +39 -0
- package/dist/trace-testing/index.cjs.map +1 -0
- package/dist/trace-testing/index.d.cts +6 -0
- package/dist/trace-testing/index.d.ts +6 -0
- package/dist/trace-testing/index.js +19 -0
- package/dist/trace-testing/index.js.map +1 -0
- package/dist/trace-testing/trace_assertions.cjs +29 -0
- package/dist/trace-testing/trace_assertions.cjs.map +1 -0
- package/dist/trace-testing/trace_assertions.d.cts +1 -0
- package/dist/trace-testing/trace_assertions.d.ts +1 -0
- package/dist/trace-testing/trace_assertions.js +7 -0
- package/dist/trace-testing/trace_assertions.js.map +1 -0
- package/dist/trace-testing/trace_query.cjs +33 -0
- package/dist/trace-testing/trace_query.cjs.map +1 -0
- package/dist/trace-testing/trace_query.d.cts +1 -0
- package/dist/trace-testing/trace_query.d.ts +1 -0
- package/dist/trace-testing/trace_query.js +11 -0
- package/dist/trace-testing/trace_query.js.map +1 -0
- package/dist/trace-testing/trace_recorder.cjs +50 -0
- package/dist/trace-testing/trace_recorder.cjs.map +1 -0
- package/dist/trace-testing/trace_recorder.d.cts +12 -0
- package/dist/trace-testing/trace_recorder.d.ts +12 -0
- package/dist/trace-testing/trace_recorder.js +32 -0
- package/dist/trace-testing/trace_recorder.js.map +1 -0
- package/dist/tracing/index.cjs +0 -4
- package/dist/tracing/index.cjs.map +1 -1
- package/dist/tracing/index.d.cts +1 -1
- package/dist/tracing/index.d.ts +1 -1
- package/dist/tracing/index.js +1 -5
- package/dist/tracing/index.js.map +1 -1
- package/dist/tracing/trace_hub.cjs +19 -86
- package/dist/tracing/trace_hub.cjs.map +1 -1
- package/dist/tracing/trace_hub.d.cts +11 -16
- package/dist/tracing/trace_hub.d.ts +11 -16
- package/dist/tracing/trace_hub.js +19 -74
- package/dist/tracing/trace_hub.js.map +1 -1
- package/dist/tracing/trace_provider.cjs +0 -6
- package/dist/tracing/trace_provider.cjs.map +1 -1
- package/dist/tracing/trace_provider.d.cts +1 -3
- package/dist/tracing/trace_provider.d.ts +1 -3
- package/dist/tracing/trace_provider.js +0 -7
- package/dist/tracing/trace_provider.js.map +1 -1
- package/docs/browser-testing.md +84 -0
- package/package.json +8 -1
package/dist/testing/browser.cjs
CHANGED
|
@@ -36,10 +36,16 @@ var import_node_fs = __toESM(require("node:fs"), 1);
|
|
|
36
36
|
var import_node_module = require("node:module");
|
|
37
37
|
var import_node_path = __toESM(require("node:path"), 1);
|
|
38
38
|
var import_node_url = require("node:url");
|
|
39
|
+
var import_tracing = require("../tracing/index.js");
|
|
40
|
+
var import_trace_testing = require("../trace-testing/index.js");
|
|
39
41
|
const DEFAULT_VIEWPORT = {
|
|
40
42
|
width: 1280,
|
|
41
43
|
height: 800
|
|
42
44
|
};
|
|
45
|
+
const DEFAULT_EXPECT_TIMEOUT_MS = 1e4;
|
|
46
|
+
const DEFAULT_RESOURCE_CLOSE_TIMEOUT_MS = 5e3;
|
|
47
|
+
const WORKER_RUNTIME_IDLE_CLOSE_MS = 5e3;
|
|
48
|
+
const browserWorkerRuntimes = /* @__PURE__ */ new Map();
|
|
43
49
|
function normalizeRoot(rootDir) {
|
|
44
50
|
return import_node_path.default.resolve(rootDir ?? process.cwd());
|
|
45
51
|
}
|
|
@@ -62,6 +68,18 @@ function mergeBridge(base, override) {
|
|
|
62
68
|
record: override?.record ?? base?.record
|
|
63
69
|
};
|
|
64
70
|
}
|
|
71
|
+
async function waitForBoundedClose(promise, timeoutMs = DEFAULT_RESOURCE_CLOSE_TIMEOUT_MS) {
|
|
72
|
+
let timeout;
|
|
73
|
+
await Promise.race([
|
|
74
|
+
promise.catch(() => void 0),
|
|
75
|
+
new Promise((resolve) => {
|
|
76
|
+
timeout = setTimeout(resolve, timeoutMs);
|
|
77
|
+
})
|
|
78
|
+
]);
|
|
79
|
+
if (timeout) {
|
|
80
|
+
clearTimeout(timeout);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
65
83
|
function channelToManifestEntry(channel, handler) {
|
|
66
84
|
const pathSegments = channel.split(".").filter(Boolean);
|
|
67
85
|
const action = pathSegments.length > 0 ? pathSegments[pathSegments.length - 1] : channel;
|
|
@@ -92,24 +110,32 @@ function createBridgeState(input) {
|
|
|
92
110
|
};
|
|
93
111
|
}
|
|
94
112
|
function createBrowserBridgeFixture(input) {
|
|
113
|
+
return createBrowserBridgeFixtureWithTrace(input, void 0);
|
|
114
|
+
}
|
|
115
|
+
function createBrowserBridgeFixtureWithTrace(input, traceConfig) {
|
|
95
116
|
const state = createBridgeState(input);
|
|
96
117
|
const manifest = Array.from(state.operations.entries()).map(([channel, handler]) => channelToManifestEntry(channel, handler));
|
|
97
118
|
return {
|
|
98
119
|
state,
|
|
99
120
|
manifest,
|
|
100
|
-
bridgeInit: buildBridgeInitScript(manifest)
|
|
121
|
+
bridgeInit: buildBridgeInitScript(manifest, traceConfig)
|
|
101
122
|
};
|
|
102
123
|
}
|
|
103
|
-
function buildBridgeInitScript(manifest) {
|
|
124
|
+
function buildBridgeInitScript(manifest, traceConfig) {
|
|
125
|
+
const traceEnabled = traceConfig?.enabled === true;
|
|
126
|
+
const traceMinLevel = traceConfig?.minLevel ?? "debug";
|
|
104
127
|
return `
|
|
105
128
|
(() => {
|
|
106
129
|
const manifest = ${JSON.stringify(manifest)};
|
|
107
130
|
const listeners = new Map();
|
|
108
131
|
const bridge = {
|
|
109
132
|
__rpcManifest: manifest,
|
|
110
|
-
__woodConfig: async () => ({
|
|
133
|
+
__woodConfig: async () => ({
|
|
134
|
+
rendererTraceEnabled: ${JSON.stringify(traceEnabled)},
|
|
135
|
+
rendererTraceMinLevel: ${JSON.stringify(traceMinLevel)}
|
|
136
|
+
}),
|
|
111
137
|
__log: () => {},
|
|
112
|
-
__trace: () =>
|
|
138
|
+
__trace: (payload) => window.__woodBrowserTrace?.(payload),
|
|
113
139
|
__window: {
|
|
114
140
|
current: async () => ({ ok: true, windowId: 'wood-browser-harness', defaultRoute: window.__WOOD_BROWSER_DEFAULT_ROUTE__ }),
|
|
115
141
|
open: async () => ({}),
|
|
@@ -185,12 +211,13 @@ async function loadViews(viewsPath) {
|
|
|
185
211
|
const parser = await import("../parser/views_parser.cjs");
|
|
186
212
|
return parser.parseViewsFile(viewsPath);
|
|
187
213
|
}
|
|
188
|
-
async function createViteServer(rootDir) {
|
|
214
|
+
async function createViteServer(rootDir, cacheDir) {
|
|
189
215
|
const vite = await loadVite();
|
|
190
216
|
const svelte = await loadSveltePlugin(rootDir);
|
|
191
217
|
const plugins = svelte ? [svelte()] : [];
|
|
192
218
|
const server = await vite.createServer({
|
|
193
219
|
root: rootDir,
|
|
220
|
+
cacheDir,
|
|
194
221
|
logLevel: process.env.WOOD_BROWSER_TEST_DEBUG ? "info" : "silent",
|
|
195
222
|
plugins,
|
|
196
223
|
resolve: {
|
|
@@ -201,6 +228,92 @@ async function createViteServer(rootDir) {
|
|
|
201
228
|
await server.listen();
|
|
202
229
|
return server;
|
|
203
230
|
}
|
|
231
|
+
function workerRuntimeKey(input) {
|
|
232
|
+
return [
|
|
233
|
+
input.rootDir,
|
|
234
|
+
input.browserName,
|
|
235
|
+
input.headless ? "headless" : "headed"
|
|
236
|
+
].join("::");
|
|
237
|
+
}
|
|
238
|
+
async function createBrowserWorkerRuntime(input) {
|
|
239
|
+
const cacheRoot = import_node_fs.default.mkdtempSync(import_node_path.default.join(input.rootDir, ".wood-browser-vite-"));
|
|
240
|
+
let browser2 = null;
|
|
241
|
+
try {
|
|
242
|
+
const playwrightBrowser = await loadPlaywright(input.browserName);
|
|
243
|
+
browser2 = await playwrightBrowser.launch({ headless: input.headless });
|
|
244
|
+
const server = await createViteServer(input.rootDir, import_node_path.default.join(cacheRoot, ".vite"));
|
|
245
|
+
return {
|
|
246
|
+
browser: browser2,
|
|
247
|
+
server,
|
|
248
|
+
cacheDir: cacheRoot,
|
|
249
|
+
rootDir: input.rootDir,
|
|
250
|
+
key: input.key,
|
|
251
|
+
activeHarnesses: 0,
|
|
252
|
+
closing: false,
|
|
253
|
+
idleCloseTimer: null
|
|
254
|
+
};
|
|
255
|
+
} catch (error) {
|
|
256
|
+
await browser2?.close().catch(() => void 0);
|
|
257
|
+
import_node_fs.default.rmSync(cacheRoot, { recursive: true, force: true });
|
|
258
|
+
throw error;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
async function acquireBrowserWorkerRuntime(input) {
|
|
262
|
+
const key = workerRuntimeKey(input);
|
|
263
|
+
let entry = browserWorkerRuntimes.get(key);
|
|
264
|
+
if (!entry) {
|
|
265
|
+
entry = {
|
|
266
|
+
promise: createBrowserWorkerRuntime({ ...input, key })
|
|
267
|
+
};
|
|
268
|
+
browserWorkerRuntimes.set(key, entry);
|
|
269
|
+
}
|
|
270
|
+
const runtime = await entry.promise;
|
|
271
|
+
if (runtime.closing) {
|
|
272
|
+
browserWorkerRuntimes.delete(key);
|
|
273
|
+
return await acquireBrowserWorkerRuntime(input);
|
|
274
|
+
}
|
|
275
|
+
if (runtime.idleCloseTimer) {
|
|
276
|
+
clearTimeout(runtime.idleCloseTimer);
|
|
277
|
+
runtime.idleCloseTimer = null;
|
|
278
|
+
}
|
|
279
|
+
runtime.activeHarnesses += 1;
|
|
280
|
+
return runtime;
|
|
281
|
+
}
|
|
282
|
+
async function closeBrowserWorkerRuntime(runtime) {
|
|
283
|
+
if (runtime.closing) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
runtime.closing = true;
|
|
287
|
+
try {
|
|
288
|
+
await Promise.all([
|
|
289
|
+
waitForBoundedClose(runtime.server.close()),
|
|
290
|
+
waitForBoundedClose(runtime.browser.close())
|
|
291
|
+
]);
|
|
292
|
+
} finally {
|
|
293
|
+
import_node_fs.default.rmSync(runtime.cacheDir, { recursive: true, force: true });
|
|
294
|
+
const entry = browserWorkerRuntimes.get(runtime.key);
|
|
295
|
+
const current = entry ? await entry.promise.catch(() => null) : null;
|
|
296
|
+
if (current === runtime) {
|
|
297
|
+
browserWorkerRuntimes.delete(runtime.key);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function scheduleBrowserWorkerRuntimeClose(runtime) {
|
|
302
|
+
if (runtime.closing || runtime.activeHarnesses > 0 || runtime.idleCloseTimer) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
runtime.idleCloseTimer = setTimeout(() => {
|
|
306
|
+
runtime.idleCloseTimer = null;
|
|
307
|
+
if (runtime.activeHarnesses === 0) {
|
|
308
|
+
void closeBrowserWorkerRuntime(runtime);
|
|
309
|
+
}
|
|
310
|
+
}, WORKER_RUNTIME_IDLE_CLOSE_MS);
|
|
311
|
+
runtime.idleCloseTimer.unref?.();
|
|
312
|
+
}
|
|
313
|
+
function releaseBrowserWorkerRuntime(runtime) {
|
|
314
|
+
runtime.activeHarnesses = Math.max(0, runtime.activeHarnesses - 1);
|
|
315
|
+
scheduleBrowserWorkerRuntimeClose(runtime);
|
|
316
|
+
}
|
|
204
317
|
function serverBaseUrl(server) {
|
|
205
318
|
return server.resolvedUrls?.local?.[0] ?? "http://127.0.0.1:5173";
|
|
206
319
|
}
|
|
@@ -407,6 +520,14 @@ async function installBridge(page, bridgeState, manifest, bridgeInit) {
|
|
|
407
520
|
window.__WOOD_BROWSER_BRIDGE_MANIFEST__ = entries;
|
|
408
521
|
}, manifest);
|
|
409
522
|
}
|
|
523
|
+
async function installTraceBinding(page, traceRecorder, context) {
|
|
524
|
+
if (!traceRecorder) {
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
await page.exposeBinding("__woodBrowserTrace", async (_source, payload) => {
|
|
528
|
+
(0, import_tracing.dispatchRendererTracePayload)(payload, context);
|
|
529
|
+
});
|
|
530
|
+
}
|
|
410
531
|
function createMountedBridge(page, state) {
|
|
411
532
|
return {
|
|
412
533
|
async emit(channel, payload) {
|
|
@@ -483,20 +604,35 @@ async function elementRect(page, selector) {
|
|
|
483
604
|
}).catch(() => null);
|
|
484
605
|
}
|
|
485
606
|
function createExpect(page, outputDir) {
|
|
607
|
+
async function waitForVisible(selector) {
|
|
608
|
+
const locator = page.locator(selector).first();
|
|
609
|
+
try {
|
|
610
|
+
await locator.waitFor({ state: "attached", timeout: DEFAULT_EXPECT_TIMEOUT_MS });
|
|
611
|
+
} catch {
|
|
612
|
+
throw new Error(`Expected "${selector}" to exist.`);
|
|
613
|
+
}
|
|
614
|
+
try {
|
|
615
|
+
await locator.waitFor({ state: "visible", timeout: DEFAULT_EXPECT_TIMEOUT_MS });
|
|
616
|
+
} catch {
|
|
617
|
+
throw new Error(`Expected "${selector}" to be visible.`);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
486
620
|
return {
|
|
487
621
|
async visible(selector) {
|
|
488
|
-
|
|
489
|
-
if (count < 1) throw new Error(`Expected "${selector}" to exist.`);
|
|
490
|
-
const visible = await page.locator(selector).first().isVisible();
|
|
491
|
-
if (!visible) throw new Error(`Expected "${selector}" to be visible.`);
|
|
622
|
+
await waitForVisible(selector);
|
|
492
623
|
},
|
|
493
624
|
async hidden(selector) {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
625
|
+
try {
|
|
626
|
+
await page.locator(selector).first().waitFor({
|
|
627
|
+
state: "hidden",
|
|
628
|
+
timeout: DEFAULT_EXPECT_TIMEOUT_MS
|
|
629
|
+
});
|
|
630
|
+
} catch {
|
|
631
|
+
throw new Error(`Expected "${selector}" to be hidden.`);
|
|
632
|
+
}
|
|
498
633
|
},
|
|
499
634
|
async insideViewport(selector, options = {}) {
|
|
635
|
+
await waitForVisible(selector);
|
|
500
636
|
const margin = options.margin ?? 0;
|
|
501
637
|
const rect = await elementRect(page, selector);
|
|
502
638
|
if (!rect) throw new Error(`Expected "${selector}" to exist.`);
|
|
@@ -507,6 +643,7 @@ function createExpect(page, outputDir) {
|
|
|
507
643
|
}
|
|
508
644
|
},
|
|
509
645
|
async notClipped(selector) {
|
|
646
|
+
await waitForVisible(selector);
|
|
510
647
|
const result = await page.locator(selector).first().evaluate((element) => {
|
|
511
648
|
const rect = element.getBoundingClientRect();
|
|
512
649
|
let parent = element.parentElement;
|
|
@@ -528,6 +665,8 @@ function createExpect(page, outputDir) {
|
|
|
528
665
|
}
|
|
529
666
|
},
|
|
530
667
|
async notOverlapping(firstSelector, secondSelector) {
|
|
668
|
+
await waitForVisible(firstSelector);
|
|
669
|
+
await waitForVisible(secondSelector);
|
|
531
670
|
const first = await elementRect(page, firstSelector);
|
|
532
671
|
const second = await elementRect(page, secondSelector);
|
|
533
672
|
if (!first || !second) throw new Error(`Expected both "${firstSelector}" and "${secondSelector}" to exist.`);
|
|
@@ -537,6 +676,8 @@ function createExpect(page, outputDir) {
|
|
|
537
676
|
}
|
|
538
677
|
},
|
|
539
678
|
async zIndexAbove(topSelector, lowerSelector) {
|
|
679
|
+
await waitForVisible(topSelector);
|
|
680
|
+
await waitForVisible(lowerSelector);
|
|
540
681
|
const values = await page.evaluate((payload) => {
|
|
541
682
|
const { topSelector: top, lowerSelector: lower } = payload;
|
|
542
683
|
const topElement = document.querySelector(top);
|
|
@@ -610,6 +751,7 @@ async function openMountPage(input) {
|
|
|
610
751
|
await page.setViewportSize({ width: viewport.width, height: viewport.height });
|
|
611
752
|
const entryPath = writeEntry(input.runtime.tempDir, input.name, input.entrySource);
|
|
612
753
|
const htmlPath = writeHtml(input.runtime.tempDir, input.name, entryPath, input.css);
|
|
754
|
+
await installTraceBinding(input.runtime.page, input.traceRecorder, input.traceContext ?? {});
|
|
613
755
|
await installBridge(page, input.bridge.state, input.bridge.manifest, input.bridge.bridgeInit);
|
|
614
756
|
const mountedBridge = createMountedBridge(page, input.bridge.state);
|
|
615
757
|
const context = {
|
|
@@ -642,22 +784,47 @@ async function openMountPage(input) {
|
|
|
642
784
|
async function createHarness(config = {}) {
|
|
643
785
|
const rootDir = normalizeRoot(config.rootDir);
|
|
644
786
|
const browserName = config.browser?.browserName ?? "chromium";
|
|
645
|
-
const
|
|
646
|
-
const
|
|
647
|
-
|
|
787
|
+
const headless = config.browser?.headless ?? true;
|
|
788
|
+
const workerRuntime = await acquireBrowserWorkerRuntime({
|
|
789
|
+
rootDir,
|
|
790
|
+
browserName,
|
|
791
|
+
headless
|
|
648
792
|
});
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
793
|
+
let released = false;
|
|
794
|
+
let destroyed = false;
|
|
795
|
+
let tempDir = null;
|
|
796
|
+
let context = null;
|
|
797
|
+
let page = null;
|
|
798
|
+
let traceRecorder;
|
|
799
|
+
function releaseRuntimeOnce() {
|
|
800
|
+
if (released) {
|
|
801
|
+
return;
|
|
655
802
|
}
|
|
656
|
-
|
|
657
|
-
|
|
803
|
+
released = true;
|
|
804
|
+
releaseBrowserWorkerRuntime(workerRuntime);
|
|
805
|
+
}
|
|
806
|
+
try {
|
|
807
|
+
tempDir = import_node_fs.default.mkdtempSync(import_node_path.default.join(rootDir, ".wood-browser-harness-"));
|
|
808
|
+
context = await workerRuntime.browser.newContext({
|
|
809
|
+
viewport: {
|
|
810
|
+
width: config.viewport?.width ?? DEFAULT_VIEWPORT.width,
|
|
811
|
+
height: config.viewport?.height ?? DEFAULT_VIEWPORT.height,
|
|
812
|
+
deviceScaleFactor: config.viewport?.deviceScaleFactor
|
|
813
|
+
}
|
|
814
|
+
});
|
|
815
|
+
page = await context.newPage();
|
|
816
|
+
traceRecorder = config.trace?.enabled === true ? new import_trace_testing.TraceRecorder() : void 0;
|
|
817
|
+
traceRecorder?.enable({ maxEvents: config.trace?.maxEvents });
|
|
818
|
+
} catch (error) {
|
|
819
|
+
if (page) await waitForBoundedClose(page.close());
|
|
820
|
+
if (context) await waitForBoundedClose(context.close());
|
|
821
|
+
if (tempDir) import_node_fs.default.rmSync(tempDir, { recursive: true, force: true });
|
|
822
|
+
releaseRuntimeOnce();
|
|
823
|
+
throw error;
|
|
824
|
+
}
|
|
658
825
|
const runtime = {
|
|
659
|
-
|
|
660
|
-
server,
|
|
826
|
+
context,
|
|
827
|
+
server: workerRuntime.server,
|
|
661
828
|
page,
|
|
662
829
|
tempDir,
|
|
663
830
|
rootDir
|
|
@@ -669,8 +836,9 @@ async function createHarness(config = {}) {
|
|
|
669
836
|
});
|
|
670
837
|
return {
|
|
671
838
|
page,
|
|
839
|
+
...traceRecorder ? { traceRecorder } : {},
|
|
672
840
|
async mountRoute(routeKey, options = {}) {
|
|
673
|
-
const bridge =
|
|
841
|
+
const bridge = createBrowserBridgeFixtureWithTrace(mergeBridge(config.bridge, options.bridge), config.trace);
|
|
674
842
|
const route = {
|
|
675
843
|
params: options.route?.params ?? {},
|
|
676
844
|
query: options.route?.query ?? {}
|
|
@@ -701,6 +869,12 @@ async function createHarness(config = {}) {
|
|
|
701
869
|
css,
|
|
702
870
|
viewport: options.viewport ?? config.viewport,
|
|
703
871
|
bridge,
|
|
872
|
+
traceRecorder,
|
|
873
|
+
traceContext: {
|
|
874
|
+
windowId: config.trace?.windowId ?? routeKey.split(".")[0],
|
|
875
|
+
routeKey,
|
|
876
|
+
harnessId: config.trace?.harnessId
|
|
877
|
+
},
|
|
704
878
|
context: {
|
|
705
879
|
route: {
|
|
706
880
|
key: routeKey,
|
|
@@ -721,7 +895,7 @@ async function createHarness(config = {}) {
|
|
|
721
895
|
async mountComponent(component, options = {}) {
|
|
722
896
|
const componentPath = resolveFromRoot(rootDir, component);
|
|
723
897
|
assertFileExists(componentPath, "Component");
|
|
724
|
-
const bridge =
|
|
898
|
+
const bridge = createBrowserBridgeFixtureWithTrace(mergeBridge(config.bridge, options.bridge), config.trace);
|
|
725
899
|
return await openMountPage({
|
|
726
900
|
runtime,
|
|
727
901
|
entrySource: buildComponentEntrySource({
|
|
@@ -732,6 +906,11 @@ async function createHarness(config = {}) {
|
|
|
732
906
|
css,
|
|
733
907
|
viewport: options.viewport ?? config.viewport,
|
|
734
908
|
bridge,
|
|
909
|
+
traceRecorder,
|
|
910
|
+
traceContext: {
|
|
911
|
+
windowId: config.trace?.windowId ?? "wood-browser-harness",
|
|
912
|
+
harnessId: config.trace?.harnessId
|
|
913
|
+
},
|
|
735
914
|
context: {},
|
|
736
915
|
hooks: {
|
|
737
916
|
beforeMount: options.page?.beforeMount ?? config.page?.beforeMount,
|
|
@@ -740,7 +919,7 @@ async function createHarness(config = {}) {
|
|
|
740
919
|
});
|
|
741
920
|
},
|
|
742
921
|
async mountTree(tree) {
|
|
743
|
-
const bridge =
|
|
922
|
+
const bridge = createBrowserBridgeFixtureWithTrace(mergeBridge(config.bridge, tree.bridge), config.trace);
|
|
744
923
|
const layouts = (tree.layouts ?? []).map((layout) => ({
|
|
745
924
|
component: resolveFromRoot(rootDir, layout.component),
|
|
746
925
|
props: layout.props
|
|
@@ -760,6 +939,12 @@ async function createHarness(config = {}) {
|
|
|
760
939
|
css,
|
|
761
940
|
viewport: tree.viewport ?? config.viewport,
|
|
762
941
|
bridge,
|
|
942
|
+
traceRecorder,
|
|
943
|
+
traceContext: {
|
|
944
|
+
windowId: config.trace?.windowId ?? tree.page?.key?.split(".")[0] ?? "wood-browser-harness",
|
|
945
|
+
routeKey: tree.page?.key,
|
|
946
|
+
harnessId: config.trace?.harnessId
|
|
947
|
+
},
|
|
763
948
|
context: tree.page?.key ? {
|
|
764
949
|
route: {
|
|
765
950
|
key: tree.page.key,
|
|
@@ -771,10 +956,17 @@ async function createHarness(config = {}) {
|
|
|
771
956
|
});
|
|
772
957
|
},
|
|
773
958
|
async destroy() {
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
959
|
+
if (destroyed) {
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
destroyed = true;
|
|
963
|
+
await Promise.all([
|
|
964
|
+
waitForBoundedClose(page.close()),
|
|
965
|
+
waitForBoundedClose(context.close())
|
|
966
|
+
]);
|
|
967
|
+
traceRecorder?.disable();
|
|
777
968
|
import_node_fs.default.rmSync(tempDir, { recursive: true, force: true });
|
|
969
|
+
releaseRuntimeOnce();
|
|
778
970
|
}
|
|
779
971
|
};
|
|
780
972
|
}
|