@opice/harness 0.2.0 → 0.2.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/dist/context.d.ts +12 -2
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +47 -12
- package/dist/context.js.map +1 -1
- package/dist/navigation.d.ts +0 -9
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +8 -4
- package/dist/navigation.js.map +1 -1
- package/dist/reporter.d.ts.map +1 -1
- package/dist/reporter.js +14 -1
- package/dist/reporter.js.map +1 -1
- package/dist/scenario.d.ts.map +1 -1
- package/dist/scenario.js +5 -1
- package/dist/scenario.js.map +1 -1
- package/package.json +1 -1
- package/src/context.ts +49 -12
- package/src/navigation.ts +9 -4
- package/src/reporter.ts +15 -1
- package/src/scenario.ts +5 -1
package/dist/context.d.ts
CHANGED
|
@@ -3,8 +3,18 @@ import { type BrowserContext, type Page } from 'playwright';
|
|
|
3
3
|
export declare function getPage(): Page;
|
|
4
4
|
/** The active browser context (for cookies/storage, new tabs, etc.). */
|
|
5
5
|
export declare function getContext(): BrowserContext;
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Open a fresh isolated context + page for a scenario, reusing the shared
|
|
8
|
+
* browser. Called from `beforeAll`. Any context left over from a previous
|
|
9
|
+
* scenario whose teardown didn't complete is closed first so state never
|
|
10
|
+
* bleeds across scenarios.
|
|
11
|
+
*/
|
|
7
12
|
export declare function launchPage(): Promise<Page>;
|
|
8
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Close the scenario's context (and page); keep the shared browser alive for
|
|
15
|
+
* the next scenario. Called from `afterAll`. The browser itself is launched
|
|
16
|
+
* once and reaped by Playwright's own process-exit handler when `bun test`
|
|
17
|
+
* exits — see the `beforeExit` hook below for the graceful path.
|
|
18
|
+
*/
|
|
9
19
|
export declare function closePage(): Promise<void>;
|
|
10
20
|
//# sourceMappingURL=context.d.ts.map
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,cAAc,EAAE,KAAK,IAAI,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,cAAc,EAAE,KAAK,IAAI,EAAE,MAAM,YAAY,CAAA;AA2BnF,4EAA4E;AAC5E,wBAAgB,OAAO,IAAI,IAAI,CAK9B;AAED,wEAAwE;AACxE,wBAAgB,UAAU,IAAI,cAAc,CAK3C;AAUD;;;;;GAKG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAUhD;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAO/C"}
|
package/dist/context.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { chromium } from 'playwright';
|
|
2
2
|
/**
|
|
3
|
-
* The live Playwright page for the running scenario.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
3
|
+
* The live Playwright page for the running scenario.
|
|
4
|
+
*
|
|
5
|
+
* The browser process is launched **once** and reused across every scenario;
|
|
6
|
+
* each `browserTest` only opens a fresh isolated `context` + `page` in
|
|
7
|
+
* `beforeAll` and closes that context in `afterAll`. Launching (and tearing
|
|
8
|
+
* down) a whole chromium per scenario is expensive — on a constrained CI runner
|
|
9
|
+
* that per-scenario launch competes with the app/server for CPU and, when a
|
|
10
|
+
* teardown stalls, leaks a zombie browser that drags the rest of the suite
|
|
11
|
+
* down. A fresh context per scenario keeps the same isolation (separate
|
|
12
|
+
* storage/cookies) at a fraction of the cost.
|
|
13
|
+
*
|
|
14
|
+
* The DSL — `el`, `byRole`, navigation — reads the current page from here. The
|
|
15
|
+
* browser runs in-process under `bun test`; there is no shell-out and no daemon.
|
|
9
16
|
*/
|
|
10
17
|
let browser = null;
|
|
11
18
|
let context = null;
|
|
@@ -28,23 +35,51 @@ export function getContext() {
|
|
|
28
35
|
}
|
|
29
36
|
return context;
|
|
30
37
|
}
|
|
31
|
-
/** Launch
|
|
38
|
+
/** Launch the shared browser once; reuse it on subsequent scenarios. */
|
|
39
|
+
async function getBrowser() {
|
|
40
|
+
if (!browser || !browser.isConnected()) {
|
|
41
|
+
browser = await chromium.launch({ headless: !headed() });
|
|
42
|
+
}
|
|
43
|
+
return browser;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Open a fresh isolated context + page for a scenario, reusing the shared
|
|
47
|
+
* browser. Called from `beforeAll`. Any context left over from a previous
|
|
48
|
+
* scenario whose teardown didn't complete is closed first so state never
|
|
49
|
+
* bleeds across scenarios.
|
|
50
|
+
*/
|
|
32
51
|
export async function launchPage() {
|
|
33
|
-
|
|
34
|
-
|
|
52
|
+
if (context) {
|
|
53
|
+
await context.close().catch(() => { });
|
|
54
|
+
context = null;
|
|
55
|
+
page = null;
|
|
56
|
+
}
|
|
57
|
+
const b = await getBrowser();
|
|
58
|
+
context = await b.newContext();
|
|
35
59
|
page = await context.newPage();
|
|
36
60
|
return page;
|
|
37
61
|
}
|
|
38
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* Close the scenario's context (and page); keep the shared browser alive for
|
|
64
|
+
* the next scenario. Called from `afterAll`. The browser itself is launched
|
|
65
|
+
* once and reaped by Playwright's own process-exit handler when `bun test`
|
|
66
|
+
* exits — see the `beforeExit` hook below for the graceful path.
|
|
67
|
+
*/
|
|
39
68
|
export async function closePage() {
|
|
40
69
|
try {
|
|
41
70
|
await context?.close();
|
|
42
71
|
}
|
|
43
72
|
finally {
|
|
44
|
-
await browser?.close();
|
|
45
73
|
page = null;
|
|
46
74
|
context = null;
|
|
47
|
-
browser = null;
|
|
48
75
|
}
|
|
49
76
|
}
|
|
77
|
+
// Graceful shutdown of the shared browser when the test process winds down. If
|
|
78
|
+
// this doesn't fire (hard exit/signal), Playwright's own exit handler still
|
|
79
|
+
// kills the chromium child, so the process never outlives the run.
|
|
80
|
+
process.once('beforeExit', () => {
|
|
81
|
+
const b = browser;
|
|
82
|
+
browser = null;
|
|
83
|
+
void b?.close().catch(() => { });
|
|
84
|
+
});
|
|
50
85
|
//# sourceMappingURL=context.js.map
|
package/dist/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAgD,MAAM,YAAY,CAAA;AAEnF
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAgD,MAAM,YAAY,CAAA;AAEnF;;;;;;;;;;;;;;GAcG;AAEH,IAAI,OAAO,GAAmB,IAAI,CAAA;AAClC,IAAI,OAAO,GAA0B,IAAI,CAAA;AACzC,IAAI,IAAI,GAAgB,IAAI,CAAA;AAE5B,oFAAoF;AACpF,SAAS,MAAM;IACd,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAA;AACjE,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,OAAO;IACtB,IAAI,CAAC,IAAI,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAA;IAC3F,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,UAAU;IACzB,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAA;IAC1F,CAAC;IACD,OAAO,OAAO,CAAA;AACf,CAAC;AAED,wEAAwE;AACxE,KAAK,UAAU,UAAU;IACxB,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;QACxC,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IACzD,CAAC;IACD,OAAO,OAAO,CAAA;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC/B,IAAI,OAAO,EAAE,CAAC;QACb,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QACrC,OAAO,GAAG,IAAI,CAAA;QACd,IAAI,GAAG,IAAI,CAAA;IACZ,CAAC;IACD,MAAM,CAAC,GAAG,MAAM,UAAU,EAAE,CAAA;IAC5B,OAAO,GAAG,MAAM,CAAC,CAAC,UAAU,EAAE,CAAA;IAC9B,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAA;IAC9B,OAAO,IAAI,CAAA;AACZ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS;IAC9B,IAAI,CAAC;QACJ,MAAM,OAAO,EAAE,KAAK,EAAE,CAAA;IACvB,CAAC;YAAS,CAAC;QACV,IAAI,GAAG,IAAI,CAAA;QACX,OAAO,GAAG,IAAI,CAAA;IACf,CAAC;AACF,CAAC;AAED,+EAA+E;AAC/E,4EAA4E;AAC5E,mEAAmE;AACnE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE;IAC/B,MAAM,CAAC,GAAG,OAAO,CAAA;IACjB,OAAO,GAAG,IAAI,CAAA;IACd,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;AAChC,CAAC,CAAC,CAAA"}
|
package/dist/navigation.d.ts
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Page navigation primitives. `browserTest` opens the scenario URL for you in
|
|
3
|
-
* `beforeAll`; these are for mid-scenario navigation — following a hard link,
|
|
4
|
-
* reloading after mutating storage/cookies, or going back/forward.
|
|
5
|
-
*
|
|
6
|
-
* Each navigating call waits for the `load` event (Playwright's default), so
|
|
7
|
-
* the old agent-browser reload caveat (a reload from inside `eval` getting
|
|
8
|
-
* dropped) no longer applies — `reload()` drives the page directly.
|
|
9
|
-
*/
|
|
10
1
|
/** Navigate to a URL in the current page. */
|
|
11
2
|
export declare function open(url: string): Promise<void>;
|
|
12
3
|
/** Reload the current page. */
|
package/dist/navigation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../src/navigation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../src/navigation.ts"],"names":[],"mappings":"AAiBA,6CAA6C;AAC7C,wBAAsB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAErD;AAED,+BAA+B;AAC/B,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAE5C;AAED,0BAA0B;AAC1B,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAE1C;AAED,6BAA6B;AAC7B,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAE7C;AAED,8CAA8C;AAC9C,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,8CAA8C;AAC9C,wBAAgB,WAAW,IAAI,MAAM,CAEpC"}
|
package/dist/navigation.js
CHANGED
|
@@ -8,21 +8,25 @@ import { getPage } from './context.js';
|
|
|
8
8
|
* the old agent-browser reload caveat (a reload from inside `eval` getting
|
|
9
9
|
* dropped) no longer applies — `reload()` drives the page directly.
|
|
10
10
|
*/
|
|
11
|
+
// SPA pages can hold the `load` event on a slow chunk or a long-lived
|
|
12
|
+
// connection, so every navigation waits for `domcontentloaded` (not the default
|
|
13
|
+
// `load`) and lets the test's retrying assertions handle readiness.
|
|
14
|
+
const WAIT_UNTIL = { waitUntil: 'domcontentloaded' };
|
|
11
15
|
/** Navigate to a URL in the current page. */
|
|
12
16
|
export async function open(url) {
|
|
13
|
-
await getPage().goto(url);
|
|
17
|
+
await getPage().goto(url, WAIT_UNTIL);
|
|
14
18
|
}
|
|
15
19
|
/** Reload the current page. */
|
|
16
20
|
export async function reload() {
|
|
17
|
-
await getPage().reload();
|
|
21
|
+
await getPage().reload(WAIT_UNTIL);
|
|
18
22
|
}
|
|
19
23
|
/** Go back in history. */
|
|
20
24
|
export async function back() {
|
|
21
|
-
await getPage().goBack();
|
|
25
|
+
await getPage().goBack(WAIT_UNTIL);
|
|
22
26
|
}
|
|
23
27
|
/** Go forward in history. */
|
|
24
28
|
export async function forward() {
|
|
25
|
-
await getPage().goForward();
|
|
29
|
+
await getPage().goForward(WAIT_UNTIL);
|
|
26
30
|
}
|
|
27
31
|
/** The current full URL (`location.href`). */
|
|
28
32
|
export function currentUrl() {
|
package/dist/navigation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation.js","sourceRoot":"","sources":["../src/navigation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC;;;;;;;;GAQG;AAEH,6CAA6C;AAC7C,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,GAAW;IACrC,MAAM,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"navigation.js","sourceRoot":"","sources":["../src/navigation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC;;;;;;;;GAQG;AAEH,sEAAsE;AACtE,gFAAgF;AAChF,oEAAoE;AACpE,MAAM,UAAU,GAAG,EAAE,SAAS,EAAE,kBAAkB,EAAW,CAAA;AAE7D,6CAA6C;AAC7C,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,GAAW;IACrC,MAAM,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;AACtC,CAAC;AAED,+BAA+B;AAC/B,MAAM,CAAC,KAAK,UAAU,MAAM;IAC3B,MAAM,OAAO,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;AACnC,CAAC;AAED,0BAA0B;AAC1B,MAAM,CAAC,KAAK,UAAU,IAAI;IACzB,MAAM,OAAO,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;AACnC,CAAC;AAED,6BAA6B;AAC7B,MAAM,CAAC,KAAK,UAAU,OAAO;IAC5B,MAAM,OAAO,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;AACtC,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,UAAU;IACzB,OAAO,OAAO,EAAE,CAAC,GAAG,EAAE,CAAA;AACvB,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,WAAW;IAC1B,OAAO,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAA;AACzC,CAAC"}
|
package/dist/reporter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAaH,MAAM,WAAW,cAAc;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,MAAM,CAAC,EAAE,IAAI,GAAG,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,SAAS;IACzB,UAAU,EAAE,MAAM,CAAA;IAClB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,cAAc;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,QAAQ;IACxB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACpD,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3C,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACtB;AAWD,eAAO,MAAM,WAAW,QAAwC,CAAA;AAMhE,MAAM,WAAW,UAAU;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACb;AA8JD,wBAAgB,WAAW,IAAI,QAAQ,CAEtC;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAEpD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,QAAQ,CA8B/E"}
|
package/dist/reporter.js
CHANGED
|
@@ -18,6 +18,10 @@ import { mkdirSync, writeFileSync } from 'node:fs';
|
|
|
18
18
|
import { tmpdir } from 'node:os';
|
|
19
19
|
import path from 'node:path';
|
|
20
20
|
import { parseOpiceDsn } from './dsn.js';
|
|
21
|
+
/** Per-request cap, so a hung connection can't stall a scenario's afterAll. */
|
|
22
|
+
const REQUEST_TIMEOUT_MS = 10_000;
|
|
23
|
+
/** Total cap on `flush()` waiting for pending step uploads (afterAll-bounded). */
|
|
24
|
+
const FLUSH_BUDGET_MS = 15_000;
|
|
21
25
|
class NoopReporter {
|
|
22
26
|
async startScenario(input) {
|
|
23
27
|
return `noop-${input.name}-${Date.now()}`;
|
|
@@ -105,7 +109,14 @@ class HttpReporter {
|
|
|
105
109
|
});
|
|
106
110
|
}
|
|
107
111
|
async flush() {
|
|
108
|
-
|
|
112
|
+
// Bound the wait: step uploads (a base64 screenshot each) pile up on a
|
|
113
|
+
// slow/contended uplink, and `flush()` is awaited in a scenario's afterAll
|
|
114
|
+
// — an unbounded wait there blows the afterAll budget and fails the
|
|
115
|
+
// scenario over *reporting*, not the test. Best-effort: stop waiting after
|
|
116
|
+
// FLUSH_BUDGET_MS; stragglers settle in the background. Pair with the
|
|
117
|
+
// per-request timeout in `fetch`.
|
|
118
|
+
const budget = new Promise((resolve) => setTimeout(resolve, FLUSH_BUDGET_MS));
|
|
119
|
+
await Promise.race([Promise.allSettled([...this.pending]), budget]);
|
|
109
120
|
// finishRun is the CLI's responsibility — see handoff file.
|
|
110
121
|
}
|
|
111
122
|
track(promise) {
|
|
@@ -131,6 +142,8 @@ class HttpReporter {
|
|
|
131
142
|
'content-type': 'application/json',
|
|
132
143
|
},
|
|
133
144
|
body: body == null ? undefined : JSON.stringify(body),
|
|
145
|
+
// Don't let a stalled connection hang past the afterAll budget.
|
|
146
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
134
147
|
});
|
|
135
148
|
}
|
|
136
149
|
catch (err) {
|
package/dist/reporter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"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"}
|
package/dist/scenario.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scenario.d.ts","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,kBAAkB;IAClC,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACrB;AAuCD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,EAAE,OAAO,GAAE,kBAAkB,GAAG,MAAW,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"scenario.d.ts","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,kBAAkB;IAClC,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACrB;AAuCD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,EAAE,OAAO,GAAE,kBAAkB,GAAG,MAAW,GAAG,IAAI,CA6DzG;AAED;;;;;;GAMG;AACH,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAkCtF"}
|
package/dist/scenario.js
CHANGED
|
@@ -87,7 +87,11 @@ export function browserTest(name, fn, options = {}) {
|
|
|
87
87
|
await setup(getContext());
|
|
88
88
|
const base = opts.url ?? PLAYGROUND_URL;
|
|
89
89
|
const url = opts.hash ? `${base}#${opts.hash}` : base;
|
|
90
|
-
|
|
90
|
+
// `domcontentloaded`, not the default `load`: an SPA paints after its JS
|
|
91
|
+
// runs and may hold `load` on a slow chunk or long-lived connection, so
|
|
92
|
+
// waiting for `load` flakily times out under CI contention. Readiness is
|
|
93
|
+
// handled by the test's retrying assertions.
|
|
94
|
+
await page.goto(url, { waitUntil: 'domcontentloaded' });
|
|
91
95
|
}, 30_000);
|
|
92
96
|
afterAll(async () => {
|
|
93
97
|
try {
|
package/dist/scenario.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scenario.js","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"scenario.js","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/context.ts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import { chromium, type Browser, type BrowserContext, type Page } from 'playwright'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* The live Playwright page for the running scenario.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* The live Playwright page for the running scenario.
|
|
5
|
+
*
|
|
6
|
+
* The browser process is launched **once** and reused across every scenario;
|
|
7
|
+
* each `browserTest` only opens a fresh isolated `context` + `page` in
|
|
8
|
+
* `beforeAll` and closes that context in `afterAll`. Launching (and tearing
|
|
9
|
+
* down) a whole chromium per scenario is expensive — on a constrained CI runner
|
|
10
|
+
* that per-scenario launch competes with the app/server for CPU and, when a
|
|
11
|
+
* teardown stalls, leaks a zombie browser that drags the rest of the suite
|
|
12
|
+
* down. A fresh context per scenario keeps the same isolation (separate
|
|
13
|
+
* storage/cookies) at a fraction of the cost.
|
|
14
|
+
*
|
|
15
|
+
* The DSL — `el`, `byRole`, navigation — reads the current page from here. The
|
|
16
|
+
* browser runs in-process under `bun test`; there is no shell-out and no daemon.
|
|
10
17
|
*/
|
|
11
18
|
|
|
12
19
|
let browser: Browser | null = null
|
|
@@ -34,22 +41,52 @@ export function getContext(): BrowserContext {
|
|
|
34
41
|
return context
|
|
35
42
|
}
|
|
36
43
|
|
|
37
|
-
/** Launch
|
|
44
|
+
/** Launch the shared browser once; reuse it on subsequent scenarios. */
|
|
45
|
+
async function getBrowser(): Promise<Browser> {
|
|
46
|
+
if (!browser || !browser.isConnected()) {
|
|
47
|
+
browser = await chromium.launch({ headless: !headed() })
|
|
48
|
+
}
|
|
49
|
+
return browser
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Open a fresh isolated context + page for a scenario, reusing the shared
|
|
54
|
+
* browser. Called from `beforeAll`. Any context left over from a previous
|
|
55
|
+
* scenario whose teardown didn't complete is closed first so state never
|
|
56
|
+
* bleeds across scenarios.
|
|
57
|
+
*/
|
|
38
58
|
export async function launchPage(): Promise<Page> {
|
|
39
|
-
|
|
40
|
-
|
|
59
|
+
if (context) {
|
|
60
|
+
await context.close().catch(() => {})
|
|
61
|
+
context = null
|
|
62
|
+
page = null
|
|
63
|
+
}
|
|
64
|
+
const b = await getBrowser()
|
|
65
|
+
context = await b.newContext()
|
|
41
66
|
page = await context.newPage()
|
|
42
67
|
return page
|
|
43
68
|
}
|
|
44
69
|
|
|
45
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* Close the scenario's context (and page); keep the shared browser alive for
|
|
72
|
+
* the next scenario. Called from `afterAll`. The browser itself is launched
|
|
73
|
+
* once and reaped by Playwright's own process-exit handler when `bun test`
|
|
74
|
+
* exits — see the `beforeExit` hook below for the graceful path.
|
|
75
|
+
*/
|
|
46
76
|
export async function closePage(): Promise<void> {
|
|
47
77
|
try {
|
|
48
78
|
await context?.close()
|
|
49
79
|
} finally {
|
|
50
|
-
await browser?.close()
|
|
51
80
|
page = null
|
|
52
81
|
context = null
|
|
53
|
-
browser = null
|
|
54
82
|
}
|
|
55
83
|
}
|
|
84
|
+
|
|
85
|
+
// Graceful shutdown of the shared browser when the test process winds down. If
|
|
86
|
+
// this doesn't fire (hard exit/signal), Playwright's own exit handler still
|
|
87
|
+
// kills the chromium child, so the process never outlives the run.
|
|
88
|
+
process.once('beforeExit', () => {
|
|
89
|
+
const b = browser
|
|
90
|
+
browser = null
|
|
91
|
+
void b?.close().catch(() => {})
|
|
92
|
+
})
|
package/src/navigation.ts
CHANGED
|
@@ -10,24 +10,29 @@ import { getPage } from './context.js'
|
|
|
10
10
|
* dropped) no longer applies — `reload()` drives the page directly.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
// SPA pages can hold the `load` event on a slow chunk or a long-lived
|
|
14
|
+
// connection, so every navigation waits for `domcontentloaded` (not the default
|
|
15
|
+
// `load`) and lets the test's retrying assertions handle readiness.
|
|
16
|
+
const WAIT_UNTIL = { waitUntil: 'domcontentloaded' } as const
|
|
17
|
+
|
|
13
18
|
/** Navigate to a URL in the current page. */
|
|
14
19
|
export async function open(url: string): Promise<void> {
|
|
15
|
-
await getPage().goto(url)
|
|
20
|
+
await getPage().goto(url, WAIT_UNTIL)
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
/** Reload the current page. */
|
|
19
24
|
export async function reload(): Promise<void> {
|
|
20
|
-
await getPage().reload()
|
|
25
|
+
await getPage().reload(WAIT_UNTIL)
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
/** Go back in history. */
|
|
24
29
|
export async function back(): Promise<void> {
|
|
25
|
-
await getPage().goBack()
|
|
30
|
+
await getPage().goBack(WAIT_UNTIL)
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
/** Go forward in history. */
|
|
29
34
|
export async function forward(): Promise<void> {
|
|
30
|
-
await getPage().goForward()
|
|
35
|
+
await getPage().goForward(WAIT_UNTIL)
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
/** The current full URL (`location.href`). */
|
package/src/reporter.ts
CHANGED
|
@@ -20,6 +20,11 @@ import { tmpdir } from 'node:os'
|
|
|
20
20
|
import path from 'node:path'
|
|
21
21
|
import { parseOpiceDsn } from './dsn.js'
|
|
22
22
|
|
|
23
|
+
/** Per-request cap, so a hung connection can't stall a scenario's afterAll. */
|
|
24
|
+
const REQUEST_TIMEOUT_MS = 10_000
|
|
25
|
+
/** Total cap on `flush()` waiting for pending step uploads (afterAll-bounded). */
|
|
26
|
+
const FLUSH_BUDGET_MS = 15_000
|
|
27
|
+
|
|
23
28
|
export interface ReporterConfig {
|
|
24
29
|
endpoint: string
|
|
25
30
|
projectId: string
|
|
@@ -161,7 +166,14 @@ class HttpReporter implements Reporter {
|
|
|
161
166
|
}
|
|
162
167
|
|
|
163
168
|
async flush(): Promise<void> {
|
|
164
|
-
|
|
169
|
+
// Bound the wait: step uploads (a base64 screenshot each) pile up on a
|
|
170
|
+
// slow/contended uplink, and `flush()` is awaited in a scenario's afterAll
|
|
171
|
+
// — an unbounded wait there blows the afterAll budget and fails the
|
|
172
|
+
// scenario over *reporting*, not the test. Best-effort: stop waiting after
|
|
173
|
+
// FLUSH_BUDGET_MS; stragglers settle in the background. Pair with the
|
|
174
|
+
// per-request timeout in `fetch`.
|
|
175
|
+
const budget = new Promise<void>((resolve) => setTimeout(resolve, FLUSH_BUDGET_MS))
|
|
176
|
+
await Promise.race([Promise.allSettled([...this.pending]), budget])
|
|
165
177
|
// finishRun is the CLI's responsibility — see handoff file.
|
|
166
178
|
}
|
|
167
179
|
|
|
@@ -189,6 +201,8 @@ class HttpReporter implements Reporter {
|
|
|
189
201
|
'content-type': 'application/json',
|
|
190
202
|
},
|
|
191
203
|
body: body == null ? undefined : JSON.stringify(body),
|
|
204
|
+
// Don't let a stalled connection hang past the afterAll budget.
|
|
205
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
192
206
|
})
|
|
193
207
|
} catch (err) {
|
|
194
208
|
// Network error / blocked request (e.g. a test runner that installs a
|
package/src/scenario.ts
CHANGED
|
@@ -102,7 +102,11 @@ export function browserTest(name: string, fn: () => void, options: BrowserTestOp
|
|
|
102
102
|
if (setup) await setup(getContext())
|
|
103
103
|
const base = opts.url ?? PLAYGROUND_URL
|
|
104
104
|
const url = opts.hash ? `${base}#${opts.hash}` : base
|
|
105
|
-
|
|
105
|
+
// `domcontentloaded`, not the default `load`: an SPA paints after its JS
|
|
106
|
+
// runs and may hold `load` on a slow chunk or long-lived connection, so
|
|
107
|
+
// waiting for `load` flakily times out under CI contention. Readiness is
|
|
108
|
+
// handled by the test's retrying assertions.
|
|
109
|
+
await page.goto(url, { waitUntil: 'domcontentloaded' })
|
|
106
110
|
}, 30_000)
|
|
107
111
|
|
|
108
112
|
afterAll(async () => {
|