@noego/wood 0.4.1 → 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/testing/browser.cjs +188 -34
- package/dist/testing/browser.cjs.map +1 -1
- package/dist/testing/browser.d.cts +6 -2
- package/dist/testing/browser.d.ts +6 -2
- package/dist/testing/browser.js +188 -35
- 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 +5 -3
- package/dist/testing/index.d.ts +5 -3
- package/dist/testing/index.js +2 -2
- package/dist/testing/index.js.map +1 -1
- package/dist/trace-testing/index.cjs +3 -3
- package/dist/trace-testing/index.cjs.map +1 -1
- package/dist/trace-testing/index.d.cts +2 -3
- package/dist/trace-testing/index.d.ts +2 -3
- package/dist/trace-testing/index.js +3 -3
- package/dist/trace-testing/index.js.map +1 -1
- package/dist/trace-testing/trace_assertions.cjs +2 -46
- package/dist/trace-testing/trace_assertions.cjs.map +1 -1
- package/dist/trace-testing/trace_assertions.d.cts +1 -15
- package/dist/trace-testing/trace_assertions.d.ts +1 -15
- package/dist/trace-testing/trace_assertions.js +3 -45
- package/dist/trace-testing/trace_assertions.js.map +1 -1
- package/dist/trace-testing/trace_query.cjs +4 -115
- package/dist/trace-testing/trace_query.cjs.map +1 -1
- package/dist/trace-testing/trace_query.d.cts +1 -24
- package/dist/trace-testing/trace_query.d.ts +1 -24
- package/dist/trace-testing/trace_query.js +5 -112
- package/dist/trace-testing/trace_query.js.map +1 -1
- 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 +0 -84
- package/dist/tracing/trace_hub.cjs.map +1 -1
- package/dist/tracing/trace_hub.d.cts +1 -16
- package/dist/tracing/trace_hub.d.ts +1 -16
- package/dist/tracing/trace_hub.js +0 -72
- 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 +2 -1
- package/dist/trace-testing/trace_scenario.cjs +0 -61
- package/dist/trace-testing/trace_scenario.cjs.map +0 -1
- package/dist/trace-testing/trace_scenario.d.cts +0 -27
- package/dist/trace-testing/trace_scenario.d.ts +0 -27
- package/dist/trace-testing/trace_scenario.js +0 -37
- package/dist/trace-testing/trace_scenario.js.map +0 -1
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TraceLevel } from '../tracing/trace_hub.cjs';
|
|
2
|
+
import { TraceRecorder } from '../trace-testing/trace_recorder.cjs';
|
|
2
3
|
import 'rxjs';
|
|
4
|
+
import '@noego/trace/testing';
|
|
5
|
+
import '../tracing/trace_provider.cjs';
|
|
6
|
+
import '@noego/ioc';
|
|
3
7
|
|
|
4
8
|
type MaybePromise<T> = T | Promise<T>;
|
|
5
9
|
type BrowserName = 'chromium' | 'firefox' | 'webkit';
|
|
@@ -153,7 +157,7 @@ type MountedWoodComponent = MountedWoodSurface;
|
|
|
153
157
|
type MountedWoodTree = MountedWoodSurface;
|
|
154
158
|
interface WoodBrowserHarness {
|
|
155
159
|
page: any;
|
|
156
|
-
|
|
160
|
+
traceRecorder?: TraceRecorder;
|
|
157
161
|
mountRoute(routeKey: string, options?: MountRouteOptions): Promise<MountedWoodRoute>;
|
|
158
162
|
mountComponent(component: string, options?: MountComponentOptions): Promise<MountedWoodComponent>;
|
|
159
163
|
mountTree(tree: MountTreeOptions): Promise<MountedWoodTree>;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TraceLevel } from '../tracing/trace_hub.js';
|
|
2
|
+
import { TraceRecorder } from '../trace-testing/trace_recorder.js';
|
|
2
3
|
import 'rxjs';
|
|
4
|
+
import '@noego/trace/testing';
|
|
5
|
+
import '../tracing/trace_provider.js';
|
|
6
|
+
import '@noego/ioc';
|
|
3
7
|
|
|
4
8
|
type MaybePromise<T> = T | Promise<T>;
|
|
5
9
|
type BrowserName = 'chromium' | 'firefox' | 'webkit';
|
|
@@ -153,7 +157,7 @@ type MountedWoodComponent = MountedWoodSurface;
|
|
|
153
157
|
type MountedWoodTree = MountedWoodSurface;
|
|
154
158
|
interface WoodBrowserHarness {
|
|
155
159
|
page: any;
|
|
156
|
-
|
|
160
|
+
traceRecorder?: TraceRecorder;
|
|
157
161
|
mountRoute(routeKey: string, options?: MountRouteOptions): Promise<MountedWoodRoute>;
|
|
158
162
|
mountComponent(component: string, options?: MountComponentOptions): Promise<MountedWoodComponent>;
|
|
159
163
|
mountTree(tree: MountTreeOptions): Promise<MountedWoodTree>;
|
package/dist/testing/browser.js
CHANGED
|
@@ -3,13 +3,17 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
import {
|
|
6
|
-
createTraceCapture,
|
|
7
6
|
dispatchRendererTracePayload
|
|
8
7
|
} from "../tracing/index.js";
|
|
8
|
+
import { TraceRecorder } from "../trace-testing/index.js";
|
|
9
9
|
const DEFAULT_VIEWPORT = {
|
|
10
10
|
width: 1280,
|
|
11
11
|
height: 800
|
|
12
12
|
};
|
|
13
|
+
const DEFAULT_EXPECT_TIMEOUT_MS = 1e4;
|
|
14
|
+
const DEFAULT_RESOURCE_CLOSE_TIMEOUT_MS = 5e3;
|
|
15
|
+
const WORKER_RUNTIME_IDLE_CLOSE_MS = 5e3;
|
|
16
|
+
const browserWorkerRuntimes = /* @__PURE__ */ new Map();
|
|
13
17
|
function normalizeRoot(rootDir) {
|
|
14
18
|
return path.resolve(rootDir ?? process.cwd());
|
|
15
19
|
}
|
|
@@ -32,6 +36,18 @@ function mergeBridge(base, override) {
|
|
|
32
36
|
record: override?.record ?? base?.record
|
|
33
37
|
};
|
|
34
38
|
}
|
|
39
|
+
async function waitForBoundedClose(promise, timeoutMs = DEFAULT_RESOURCE_CLOSE_TIMEOUT_MS) {
|
|
40
|
+
let timeout;
|
|
41
|
+
await Promise.race([
|
|
42
|
+
promise.catch(() => void 0),
|
|
43
|
+
new Promise((resolve) => {
|
|
44
|
+
timeout = setTimeout(resolve, timeoutMs);
|
|
45
|
+
})
|
|
46
|
+
]);
|
|
47
|
+
if (timeout) {
|
|
48
|
+
clearTimeout(timeout);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
35
51
|
function channelToManifestEntry(channel, handler) {
|
|
36
52
|
const pathSegments = channel.split(".").filter(Boolean);
|
|
37
53
|
const action = pathSegments.length > 0 ? pathSegments[pathSegments.length - 1] : channel;
|
|
@@ -163,12 +179,13 @@ async function loadViews(viewsPath) {
|
|
|
163
179
|
const parser = await import("../parser/views_parser.js");
|
|
164
180
|
return parser.parseViewsFile(viewsPath);
|
|
165
181
|
}
|
|
166
|
-
async function createViteServer(rootDir) {
|
|
182
|
+
async function createViteServer(rootDir, cacheDir) {
|
|
167
183
|
const vite = await loadVite();
|
|
168
184
|
const svelte = await loadSveltePlugin(rootDir);
|
|
169
185
|
const plugins = svelte ? [svelte()] : [];
|
|
170
186
|
const server = await vite.createServer({
|
|
171
187
|
root: rootDir,
|
|
188
|
+
cacheDir,
|
|
172
189
|
logLevel: process.env.WOOD_BROWSER_TEST_DEBUG ? "info" : "silent",
|
|
173
190
|
plugins,
|
|
174
191
|
resolve: {
|
|
@@ -179,6 +196,92 @@ async function createViteServer(rootDir) {
|
|
|
179
196
|
await server.listen();
|
|
180
197
|
return server;
|
|
181
198
|
}
|
|
199
|
+
function workerRuntimeKey(input) {
|
|
200
|
+
return [
|
|
201
|
+
input.rootDir,
|
|
202
|
+
input.browserName,
|
|
203
|
+
input.headless ? "headless" : "headed"
|
|
204
|
+
].join("::");
|
|
205
|
+
}
|
|
206
|
+
async function createBrowserWorkerRuntime(input) {
|
|
207
|
+
const cacheRoot = fs.mkdtempSync(path.join(input.rootDir, ".wood-browser-vite-"));
|
|
208
|
+
let browser2 = null;
|
|
209
|
+
try {
|
|
210
|
+
const playwrightBrowser = await loadPlaywright(input.browserName);
|
|
211
|
+
browser2 = await playwrightBrowser.launch({ headless: input.headless });
|
|
212
|
+
const server = await createViteServer(input.rootDir, path.join(cacheRoot, ".vite"));
|
|
213
|
+
return {
|
|
214
|
+
browser: browser2,
|
|
215
|
+
server,
|
|
216
|
+
cacheDir: cacheRoot,
|
|
217
|
+
rootDir: input.rootDir,
|
|
218
|
+
key: input.key,
|
|
219
|
+
activeHarnesses: 0,
|
|
220
|
+
closing: false,
|
|
221
|
+
idleCloseTimer: null
|
|
222
|
+
};
|
|
223
|
+
} catch (error) {
|
|
224
|
+
await browser2?.close().catch(() => void 0);
|
|
225
|
+
fs.rmSync(cacheRoot, { recursive: true, force: true });
|
|
226
|
+
throw error;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async function acquireBrowserWorkerRuntime(input) {
|
|
230
|
+
const key = workerRuntimeKey(input);
|
|
231
|
+
let entry = browserWorkerRuntimes.get(key);
|
|
232
|
+
if (!entry) {
|
|
233
|
+
entry = {
|
|
234
|
+
promise: createBrowserWorkerRuntime({ ...input, key })
|
|
235
|
+
};
|
|
236
|
+
browserWorkerRuntimes.set(key, entry);
|
|
237
|
+
}
|
|
238
|
+
const runtime = await entry.promise;
|
|
239
|
+
if (runtime.closing) {
|
|
240
|
+
browserWorkerRuntimes.delete(key);
|
|
241
|
+
return await acquireBrowserWorkerRuntime(input);
|
|
242
|
+
}
|
|
243
|
+
if (runtime.idleCloseTimer) {
|
|
244
|
+
clearTimeout(runtime.idleCloseTimer);
|
|
245
|
+
runtime.idleCloseTimer = null;
|
|
246
|
+
}
|
|
247
|
+
runtime.activeHarnesses += 1;
|
|
248
|
+
return runtime;
|
|
249
|
+
}
|
|
250
|
+
async function closeBrowserWorkerRuntime(runtime) {
|
|
251
|
+
if (runtime.closing) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
runtime.closing = true;
|
|
255
|
+
try {
|
|
256
|
+
await Promise.all([
|
|
257
|
+
waitForBoundedClose(runtime.server.close()),
|
|
258
|
+
waitForBoundedClose(runtime.browser.close())
|
|
259
|
+
]);
|
|
260
|
+
} finally {
|
|
261
|
+
fs.rmSync(runtime.cacheDir, { recursive: true, force: true });
|
|
262
|
+
const entry = browserWorkerRuntimes.get(runtime.key);
|
|
263
|
+
const current = entry ? await entry.promise.catch(() => null) : null;
|
|
264
|
+
if (current === runtime) {
|
|
265
|
+
browserWorkerRuntimes.delete(runtime.key);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function scheduleBrowserWorkerRuntimeClose(runtime) {
|
|
270
|
+
if (runtime.closing || runtime.activeHarnesses > 0 || runtime.idleCloseTimer) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
runtime.idleCloseTimer = setTimeout(() => {
|
|
274
|
+
runtime.idleCloseTimer = null;
|
|
275
|
+
if (runtime.activeHarnesses === 0) {
|
|
276
|
+
void closeBrowserWorkerRuntime(runtime);
|
|
277
|
+
}
|
|
278
|
+
}, WORKER_RUNTIME_IDLE_CLOSE_MS);
|
|
279
|
+
runtime.idleCloseTimer.unref?.();
|
|
280
|
+
}
|
|
281
|
+
function releaseBrowserWorkerRuntime(runtime) {
|
|
282
|
+
runtime.activeHarnesses = Math.max(0, runtime.activeHarnesses - 1);
|
|
283
|
+
scheduleBrowserWorkerRuntimeClose(runtime);
|
|
284
|
+
}
|
|
182
285
|
function serverBaseUrl(server) {
|
|
183
286
|
return server.resolvedUrls?.local?.[0] ?? "http://127.0.0.1:5173";
|
|
184
287
|
}
|
|
@@ -385,8 +488,8 @@ async function installBridge(page, bridgeState, manifest, bridgeInit) {
|
|
|
385
488
|
window.__WOOD_BROWSER_BRIDGE_MANIFEST__ = entries;
|
|
386
489
|
}, manifest);
|
|
387
490
|
}
|
|
388
|
-
async function installTraceBinding(page,
|
|
389
|
-
if (!
|
|
491
|
+
async function installTraceBinding(page, traceRecorder, context) {
|
|
492
|
+
if (!traceRecorder) {
|
|
390
493
|
return;
|
|
391
494
|
}
|
|
392
495
|
await page.exposeBinding("__woodBrowserTrace", async (_source, payload) => {
|
|
@@ -469,20 +572,35 @@ async function elementRect(page, selector) {
|
|
|
469
572
|
}).catch(() => null);
|
|
470
573
|
}
|
|
471
574
|
function createExpect(page, outputDir) {
|
|
575
|
+
async function waitForVisible(selector) {
|
|
576
|
+
const locator = page.locator(selector).first();
|
|
577
|
+
try {
|
|
578
|
+
await locator.waitFor({ state: "attached", timeout: DEFAULT_EXPECT_TIMEOUT_MS });
|
|
579
|
+
} catch {
|
|
580
|
+
throw new Error(`Expected "${selector}" to exist.`);
|
|
581
|
+
}
|
|
582
|
+
try {
|
|
583
|
+
await locator.waitFor({ state: "visible", timeout: DEFAULT_EXPECT_TIMEOUT_MS });
|
|
584
|
+
} catch {
|
|
585
|
+
throw new Error(`Expected "${selector}" to be visible.`);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
472
588
|
return {
|
|
473
589
|
async visible(selector) {
|
|
474
|
-
|
|
475
|
-
if (count < 1) throw new Error(`Expected "${selector}" to exist.`);
|
|
476
|
-
const visible = await page.locator(selector).first().isVisible();
|
|
477
|
-
if (!visible) throw new Error(`Expected "${selector}" to be visible.`);
|
|
590
|
+
await waitForVisible(selector);
|
|
478
591
|
},
|
|
479
592
|
async hidden(selector) {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
593
|
+
try {
|
|
594
|
+
await page.locator(selector).first().waitFor({
|
|
595
|
+
state: "hidden",
|
|
596
|
+
timeout: DEFAULT_EXPECT_TIMEOUT_MS
|
|
597
|
+
});
|
|
598
|
+
} catch {
|
|
599
|
+
throw new Error(`Expected "${selector}" to be hidden.`);
|
|
600
|
+
}
|
|
484
601
|
},
|
|
485
602
|
async insideViewport(selector, options = {}) {
|
|
603
|
+
await waitForVisible(selector);
|
|
486
604
|
const margin = options.margin ?? 0;
|
|
487
605
|
const rect = await elementRect(page, selector);
|
|
488
606
|
if (!rect) throw new Error(`Expected "${selector}" to exist.`);
|
|
@@ -493,6 +611,7 @@ function createExpect(page, outputDir) {
|
|
|
493
611
|
}
|
|
494
612
|
},
|
|
495
613
|
async notClipped(selector) {
|
|
614
|
+
await waitForVisible(selector);
|
|
496
615
|
const result = await page.locator(selector).first().evaluate((element) => {
|
|
497
616
|
const rect = element.getBoundingClientRect();
|
|
498
617
|
let parent = element.parentElement;
|
|
@@ -514,6 +633,8 @@ function createExpect(page, outputDir) {
|
|
|
514
633
|
}
|
|
515
634
|
},
|
|
516
635
|
async notOverlapping(firstSelector, secondSelector) {
|
|
636
|
+
await waitForVisible(firstSelector);
|
|
637
|
+
await waitForVisible(secondSelector);
|
|
517
638
|
const first = await elementRect(page, firstSelector);
|
|
518
639
|
const second = await elementRect(page, secondSelector);
|
|
519
640
|
if (!first || !second) throw new Error(`Expected both "${firstSelector}" and "${secondSelector}" to exist.`);
|
|
@@ -523,6 +644,8 @@ function createExpect(page, outputDir) {
|
|
|
523
644
|
}
|
|
524
645
|
},
|
|
525
646
|
async zIndexAbove(topSelector, lowerSelector) {
|
|
647
|
+
await waitForVisible(topSelector);
|
|
648
|
+
await waitForVisible(lowerSelector);
|
|
526
649
|
const values = await page.evaluate((payload) => {
|
|
527
650
|
const { topSelector: top, lowerSelector: lower } = payload;
|
|
528
651
|
const topElement = document.querySelector(top);
|
|
@@ -596,7 +719,7 @@ async function openMountPage(input) {
|
|
|
596
719
|
await page.setViewportSize({ width: viewport.width, height: viewport.height });
|
|
597
720
|
const entryPath = writeEntry(input.runtime.tempDir, input.name, input.entrySource);
|
|
598
721
|
const htmlPath = writeHtml(input.runtime.tempDir, input.name, entryPath, input.css);
|
|
599
|
-
await installTraceBinding(input.runtime.page, input.
|
|
722
|
+
await installTraceBinding(input.runtime.page, input.traceRecorder, input.traceContext ?? {});
|
|
600
723
|
await installBridge(page, input.bridge.state, input.bridge.manifest, input.bridge.bridgeInit);
|
|
601
724
|
const mountedBridge = createMountedBridge(page, input.bridge.state);
|
|
602
725
|
const context = {
|
|
@@ -629,23 +752,47 @@ async function openMountPage(input) {
|
|
|
629
752
|
async function createHarness(config = {}) {
|
|
630
753
|
const rootDir = normalizeRoot(config.rootDir);
|
|
631
754
|
const browserName = config.browser?.browserName ?? "chromium";
|
|
632
|
-
const
|
|
633
|
-
const
|
|
634
|
-
|
|
755
|
+
const headless = config.browser?.headless ?? true;
|
|
756
|
+
const workerRuntime = await acquireBrowserWorkerRuntime({
|
|
757
|
+
rootDir,
|
|
758
|
+
browserName,
|
|
759
|
+
headless
|
|
635
760
|
});
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
761
|
+
let released = false;
|
|
762
|
+
let destroyed = false;
|
|
763
|
+
let tempDir = null;
|
|
764
|
+
let context = null;
|
|
765
|
+
let page = null;
|
|
766
|
+
let traceRecorder;
|
|
767
|
+
function releaseRuntimeOnce() {
|
|
768
|
+
if (released) {
|
|
769
|
+
return;
|
|
642
770
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
771
|
+
released = true;
|
|
772
|
+
releaseBrowserWorkerRuntime(workerRuntime);
|
|
773
|
+
}
|
|
774
|
+
try {
|
|
775
|
+
tempDir = fs.mkdtempSync(path.join(rootDir, ".wood-browser-harness-"));
|
|
776
|
+
context = await workerRuntime.browser.newContext({
|
|
777
|
+
viewport: {
|
|
778
|
+
width: config.viewport?.width ?? DEFAULT_VIEWPORT.width,
|
|
779
|
+
height: config.viewport?.height ?? DEFAULT_VIEWPORT.height,
|
|
780
|
+
deviceScaleFactor: config.viewport?.deviceScaleFactor
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
page = await context.newPage();
|
|
784
|
+
traceRecorder = config.trace?.enabled === true ? new TraceRecorder() : void 0;
|
|
785
|
+
traceRecorder?.enable({ maxEvents: config.trace?.maxEvents });
|
|
786
|
+
} catch (error) {
|
|
787
|
+
if (page) await waitForBoundedClose(page.close());
|
|
788
|
+
if (context) await waitForBoundedClose(context.close());
|
|
789
|
+
if (tempDir) fs.rmSync(tempDir, { recursive: true, force: true });
|
|
790
|
+
releaseRuntimeOnce();
|
|
791
|
+
throw error;
|
|
792
|
+
}
|
|
646
793
|
const runtime = {
|
|
647
|
-
|
|
648
|
-
server,
|
|
794
|
+
context,
|
|
795
|
+
server: workerRuntime.server,
|
|
649
796
|
page,
|
|
650
797
|
tempDir,
|
|
651
798
|
rootDir
|
|
@@ -657,7 +804,7 @@ async function createHarness(config = {}) {
|
|
|
657
804
|
});
|
|
658
805
|
return {
|
|
659
806
|
page,
|
|
660
|
-
...
|
|
807
|
+
...traceRecorder ? { traceRecorder } : {},
|
|
661
808
|
async mountRoute(routeKey, options = {}) {
|
|
662
809
|
const bridge = createBrowserBridgeFixtureWithTrace(mergeBridge(config.bridge, options.bridge), config.trace);
|
|
663
810
|
const route = {
|
|
@@ -690,7 +837,7 @@ async function createHarness(config = {}) {
|
|
|
690
837
|
css,
|
|
691
838
|
viewport: options.viewport ?? config.viewport,
|
|
692
839
|
bridge,
|
|
693
|
-
|
|
840
|
+
traceRecorder,
|
|
694
841
|
traceContext: {
|
|
695
842
|
windowId: config.trace?.windowId ?? routeKey.split(".")[0],
|
|
696
843
|
routeKey,
|
|
@@ -727,7 +874,7 @@ async function createHarness(config = {}) {
|
|
|
727
874
|
css,
|
|
728
875
|
viewport: options.viewport ?? config.viewport,
|
|
729
876
|
bridge,
|
|
730
|
-
|
|
877
|
+
traceRecorder,
|
|
731
878
|
traceContext: {
|
|
732
879
|
windowId: config.trace?.windowId ?? "wood-browser-harness",
|
|
733
880
|
harnessId: config.trace?.harnessId
|
|
@@ -760,7 +907,7 @@ async function createHarness(config = {}) {
|
|
|
760
907
|
css,
|
|
761
908
|
viewport: tree.viewport ?? config.viewport,
|
|
762
909
|
bridge,
|
|
763
|
-
|
|
910
|
+
traceRecorder,
|
|
764
911
|
traceContext: {
|
|
765
912
|
windowId: config.trace?.windowId ?? tree.page?.key?.split(".")[0] ?? "wood-browser-harness",
|
|
766
913
|
routeKey: tree.page?.key,
|
|
@@ -777,11 +924,17 @@ async function createHarness(config = {}) {
|
|
|
777
924
|
});
|
|
778
925
|
},
|
|
779
926
|
async destroy() {
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
927
|
+
if (destroyed) {
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
destroyed = true;
|
|
931
|
+
await Promise.all([
|
|
932
|
+
waitForBoundedClose(page.close()),
|
|
933
|
+
waitForBoundedClose(context.close())
|
|
934
|
+
]);
|
|
935
|
+
traceRecorder?.disable();
|
|
784
936
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
937
|
+
releaseRuntimeOnce();
|
|
785
938
|
}
|
|
786
939
|
};
|
|
787
940
|
}
|