@opice/harness 0.2.1 → 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/package.json +1 -1
- package/src/context.ts +49 -12
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/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
|
+
})
|