@owlmeans/test-ui 0.1.18-rc.48 → 0.1.18-rc.49
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 +8 -6
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/testing-ui/SKILL.md +29 -29
- package/build/browser/types.d.ts +22 -0
- package/build/browser/types.d.ts.map +1 -0
- package/build/browser/types.js +2 -0
- package/build/browser/types.js.map +1 -0
- package/build/browser.d.ts +8 -16
- package/build/browser.d.ts.map +1 -1
- package/build/browser.js +38 -41
- package/build/browser.js.map +1 -1
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/marketing-consent.d.ts +2 -22
- package/build/marketing-consent.d.ts.map +1 -1
- package/build/marketing-consent.js +3 -106
- package/build/marketing-consent.js.map +1 -1
- package/build/mount.d.ts +1 -1
- package/build/mount.js +3 -3
- package/build/mount.js.map +1 -1
- package/build/page/types.d.ts +134 -0
- package/build/page/types.d.ts.map +1 -0
- package/build/page/types.js +2 -0
- package/build/page/types.js.map +1 -0
- package/build/page.d.ts +4 -0
- package/build/page.d.ts.map +1 -0
- package/build/page.js +160 -0
- package/build/page.js.map +1 -0
- package/build/supervisor/types.d.ts +56 -0
- package/build/supervisor/types.d.ts.map +1 -0
- package/build/supervisor/types.js +2 -0
- package/build/supervisor/types.js.map +1 -0
- package/build/supervisor.d.ts +9 -67
- package/build/supervisor.d.ts.map +1 -1
- package/build/supervisor.js +65 -177
- package/build/supervisor.js.map +1 -1
- package/build/types.d.ts +0 -86
- package/build/types.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/browser/types.ts +22 -0
- package/src/browser.ts +43 -40
- package/src/index.ts +4 -0
- package/src/marketing-consent.ts +4 -115
- package/src/mount.ts +3 -3
- package/src/page/types.ts +137 -0
- package/src/page.ts +184 -0
- package/src/supervisor/types.ts +55 -0
- package/src/supervisor.ts +82 -207
- package/src/types.ts +0 -86
package/README.md
CHANGED
|
@@ -6,19 +6,21 @@ These are **not** end-to-end UI tests — they exercise individual components in
|
|
|
6
6
|
|
|
7
7
|
## Exports
|
|
8
8
|
|
|
9
|
-
- `launchBrowser(opts?)` — return the shared chromium instance for this `bun test` process. Idempotent.
|
|
10
|
-
- `closeBrowser()` — tear it down. Call from `afterAll`.
|
|
11
|
-
- `withPage(fn)` — convenience: lease a fresh context+page for the duration of `fn`, then dispose the context.
|
|
9
|
+
- `browserHelper.launchBrowser(opts?)` — return the shared chromium instance for this `bun test` process. Idempotent.
|
|
10
|
+
- `browserHelper.closeBrowser()` — tear it down. Call from `afterAll`.
|
|
11
|
+
- `browserHelper.withPage(fn)` — convenience: lease a fresh context+page for the duration of `fn`, then dispose the context.
|
|
12
12
|
- `mountComponent({ url, component?, props? })` — opens a fresh context, navigates to a harness URL with the component / props encoded, returns `{ page, close }` so the spec can assert against `page.locator(...)` and dispose the context when done.
|
|
13
|
+
- `makePageHelper(page)` — drives one page of an OwlMeans app: `.acceptConsent(opts?)`, `.answerMarketingConsent(opts?)`, `.loginViaDispatcher(baseUrl, token, opts?)`, `.loginViaSupervisorForm(opts)`, `.saveScreenshot(dir, name)`.
|
|
14
|
+
- `supervisorAuthHelper` — bearers without a browser: `.pregenerateAuthToken(opts)` (signed offline) and `.authenticateViaSupervisorApi(opts)` (the live supervisor flow over the API).
|
|
13
15
|
- `Browser`, `BrowserContext`, `Page`, `Locator` — re-exports of the Playwright types so consumers don't need a direct `playwright` import.
|
|
14
16
|
|
|
15
17
|
## Spec shape
|
|
16
18
|
|
|
17
19
|
```ts
|
|
18
20
|
import { afterAll, describe, expect, test } from 'bun:test'
|
|
19
|
-
import {
|
|
21
|
+
import { browserHelper, mountComponent } from '@owlmeans/test-ui'
|
|
20
22
|
|
|
21
|
-
afterAll(async () => { await closeBrowser() })
|
|
23
|
+
afterAll(async () => { await browserHelper.closeBrowser() })
|
|
22
24
|
|
|
23
25
|
describe('LoginForm — acceptance', () => {
|
|
24
26
|
test('renders the heading from the SKILL example', async () => {
|
|
@@ -58,7 +60,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
58
60
|
your project's skill store (`.agents/skills/`):
|
|
59
61
|
|
|
60
62
|
```sh
|
|
61
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.
|
|
63
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.49
|
|
62
64
|
```
|
|
63
65
|
|
|
64
66
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/test-ui",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-10-
|
|
4
|
+
"version": "0.1.18-rc.49",
|
|
5
|
+
"generatedAt": "2026-10-05T21:03:06.365Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -6,7 +6,7 @@ description: Category-D component-level acceptance tests for OwlMeans Common UI
|
|
|
6
6
|
|
|
7
7
|
# UI Acceptance Tests — Category D (bun test + Playwright as a library)
|
|
8
8
|
|
|
9
|
-
**Install:** `"@owlmeans/test-ui": "^0.1.18-rc.
|
|
9
|
+
**Install:** `"@owlmeans/test-ui": "^0.1.18-rc.49"` in `devDependencies`
|
|
10
10
|
|
|
11
11
|
`@owlmeans/test-ui` depends on `playwright`, so the browser library arrives with it; add
|
|
12
12
|
`playwright` to `devDependencies` as well when a spec imports a launcher itself. The Vite harness
|
|
@@ -52,13 +52,13 @@ Downloads the chromium binary the `playwright` library drives. CI installs it in
|
|
|
52
52
|
|
|
53
53
|
| Helper | Purpose |
|
|
54
54
|
|---|---|
|
|
55
|
-
| `launchBrowser(opts?)` | Return the shared chromium for this `bun test` process. Idempotent. |
|
|
56
|
-
| `closeBrowser()` | Tear it down. Call from `afterAll`. |
|
|
57
|
-
| `withPage(fn)` | Lease a fresh context+page for the duration of `fn`, dispose context on completion. |
|
|
55
|
+
| `browserHelper.launchBrowser(opts?)` | Return the shared chromium for this `bun test` process. Idempotent. |
|
|
56
|
+
| `browserHelper.closeBrowser()` | Tear it down. Call from `afterAll`. |
|
|
57
|
+
| `browserHelper.withPage(fn)` | Lease a fresh context+page for the duration of `fn`, dispose context on completion. |
|
|
58
58
|
| `mountComponent(opts)` | Open a fresh context, navigate to `opts.url`, return `Mounted` = `{ page, close }`. `component` and `props`, when given, are appended as `?component=` and `?props=`; omit them when the harness mounts a fixed root, which is what every harness here does. |
|
|
59
59
|
| `MountOptions` | `{ url, component?, props?, waitUntil?, timeout? }` — `waitUntil` defaults to `domcontentloaded`, see below. |
|
|
60
|
-
| `acceptConsent(
|
|
61
|
-
| `saveScreenshot(
|
|
60
|
+
| `makePageHelper(page).acceptConsent({ timeout? })` | Wait up to `timeout` (default 5s) for `[data-consent-dialog]`, accept all, wait for it to detach. Returns whether it answered one — and costs that whole wait when it does not. |
|
|
61
|
+
| `makePageHelper(page).saveScreenshot(dir, name)` | Full-page PNG to `<dir>/<name>.png`, creating `dir`. Returns the absolute path. |
|
|
62
62
|
| Re-exports: `Browser`, `BrowserContext`, `Page`, `Locator` | Playwright types — no direct `playwright` import needed. |
|
|
63
63
|
|
|
64
64
|
### Authenticated specs
|
|
@@ -68,11 +68,11 @@ sits behind auth without hand-rolling a token:
|
|
|
68
68
|
|
|
69
69
|
| Helper | Purpose |
|
|
70
70
|
|---|---|
|
|
71
|
-
| `pregenerateAuthToken(opts)` | Mint an `ED25519-BASIC-TOKEN …` bearer offline from a trusted private key — no browser, no round trip. Options: `{ userId, pk, scopes?, role?, entityId?, profileId?, source? }`. |
|
|
72
|
-
| `authenticateViaSupervisorApi(opts)` | Drive the live PK supervisor flow over the backend API (init → sign → authenticate → dispatch), registering the user on first use. Options: `{ apiBaseUrl, userId, pk, paths?, fetchImpl? }`. |
|
|
73
|
-
| `loginViaDispatcher(
|
|
74
|
-
| `loginViaSupervisorForm(
|
|
75
|
-
| `answerMarketingConsent(
|
|
71
|
+
| `supervisorAuthHelper.pregenerateAuthToken(opts)` | Mint an `ED25519-BASIC-TOKEN …` bearer offline from a trusted private key — no browser, no round trip. Options: `{ userId, pk, scopes?, role?, entityId?, profileId?, source? }`. |
|
|
72
|
+
| `supervisorAuthHelper.authenticateViaSupervisorApi(opts)` | Drive the live PK supervisor flow over the backend API (init → sign → authenticate → dispatch), registering the user on first use. Options: `{ apiBaseUrl, userId, pk, paths?, fetchImpl? }`. |
|
|
73
|
+
| `makePageHelper(page).loginViaDispatcher(baseUrl, token, opts?)` | Inject a bearer through the standard `/dispatcher?token=…` route, wait for the app to navigate away, then answer marketing consent (see below). Options: `{ dispatcherPath?, waitUntil?, marketingConsent? }`. |
|
|
74
|
+
| `makePageHelper(page).loginViaSupervisorForm(opts)` | Drive the real login form end-to-end — navigate, answer consent, fill user id + key, submit, wait for the landing, then answer marketing consent (see below). Options: `{ baseUrl, userId, pk, path?, expectPath?, timeout?, waitUntil?, consent?, screenshotDir?, marketingConsent? }`. |
|
|
75
|
+
| `makePageHelper(page).answerMarketingConsent(opts?)` | Answer the `@owlmeans/web-marketing-consent` full-page step if it is shown right after login. Options: `{ accept?: 'all' \| 'none' \| 'skip', terms?: 'accept' \| 'leave', timeout? }`, default `accept: 'all'`, `terms: 'accept'`, `timeout: 30_000`. Returns whether the step was actually shown and answered — `false` means it never appeared. Throws if a Terms box could not be confirmed. |
|
|
76
76
|
|
|
77
77
|
These need a project whose backend trusts the private key they sign with, so they belong to specs
|
|
78
78
|
that run against a real app rather than a mounted component. See `[[supervisor-auth]]` for the
|
|
@@ -82,14 +82,14 @@ server and web wiring they assume.
|
|
|
82
82
|
|
|
83
83
|
```ts
|
|
84
84
|
import { afterAll, describe, expect, test } from 'bun:test'
|
|
85
|
-
import {
|
|
85
|
+
import { browserHelper, mountComponent } from '@owlmeans/test-ui'
|
|
86
86
|
import { HARNESS_URL } from './context.js'
|
|
87
87
|
|
|
88
88
|
// Browser work does not fit bun's 5s default: a cold harness compiles the app on first request,
|
|
89
89
|
// and the first test to run pays for the Vite boot happening in the same process.
|
|
90
90
|
const TIMEOUT = 30_000
|
|
91
91
|
|
|
92
|
-
afterAll(async () => { await closeBrowser() })
|
|
92
|
+
afterAll(async () => { await browserHelper.closeBrowser() })
|
|
93
93
|
|
|
94
94
|
// The harness is a real app, so a spec picks its case by opening a path on it.
|
|
95
95
|
const open = async (path: string) =>
|
|
@@ -173,11 +173,11 @@ For a package that only needs to prove the bun-test + chromium pipeline works, s
|
|
|
173
173
|
|
|
174
174
|
```ts
|
|
175
175
|
import { afterAll, describe, expect, test } from 'bun:test'
|
|
176
|
-
import {
|
|
176
|
+
import { browserHelper, mountComponent } from '@owlmeans/test-ui'
|
|
177
177
|
|
|
178
178
|
const harness = `data:text/html,${encodeURIComponent('<h1 id="t">hello</h1>')}`
|
|
179
179
|
|
|
180
|
-
afterAll(async () => { await closeBrowser() })
|
|
180
|
+
afterAll(async () => { await browserHelper.closeBrowser() })
|
|
181
181
|
|
|
182
182
|
describe('chromium smoke', () => {
|
|
183
183
|
test('reads a heading from a data: URL', async () => {
|
|
@@ -262,7 +262,7 @@ See `[[shadcn-web]]` for the full `@` alias contract and `tests/context.ts` patt
|
|
|
262
262
|
- **Always pass a timeout as `test`'s third argument.** 30s for a mounted component, 60s for a
|
|
263
263
|
suite that drives a login or a consent gate. Bun's 5s default is for in-process work, and
|
|
264
264
|
`bunfig.toml`'s `[test] timeout` is not a way to change it.
|
|
265
|
-
- **Always `close()` the page and `closeBrowser()` in `afterAll`.** A leaked context blocks the bun process from exiting.
|
|
265
|
+
- **Always `close()` the page and `browserHelper.closeBrowser()` in `afterAll`.** A leaked context blocks the bun process from exiting.
|
|
266
266
|
- **Chromium only by default.** Add `firefox` or `webkit` per package only when the feature has documented cross-browser concerns — call `chromium.launch` / `firefox.launch` explicitly in that case.
|
|
267
267
|
|
|
268
268
|
## `mountComponent` waits for `domcontentloaded`, not `load`
|
|
@@ -278,13 +278,13 @@ selector it actually needs. That wait IS the assertion; the load event never was
|
|
|
278
278
|
`waitUntil` explicitly for the rare case that wants otherwise.
|
|
279
279
|
|
|
280
280
|
The rule is not `mountComponent`'s alone — **every** navigation helper here follows it, including
|
|
281
|
-
`loginViaSupervisorForm` and
|
|
281
|
+
`makePageHelper(page).loginViaSupervisorForm` and `.loginViaDispatcher`. A helper that navigates on playwright's default
|
|
282
282
|
turns "someone added a tag manager" into "the whole login-driven suite times out", with the browser
|
|
283
283
|
showing a working login form the entire time. Any new helper that calls `page.goto` passes
|
|
284
284
|
`domcontentloaded` and takes a `waitUntil` override.
|
|
285
285
|
|
|
286
|
-
`saveScreenshot(
|
|
287
|
-
screen when an assertion timed out;
|
|
286
|
+
`makePageHelper(page).saveScreenshot(dir, name)` is the fastest way to see what the browser actually had on
|
|
287
|
+
screen when an assertion timed out; `.loginViaSupervisorForm` takes a `screenshotDir` that captures
|
|
288
288
|
the filled form just before submit.
|
|
289
289
|
|
|
290
290
|
## The consent dialog blocks the login form, and the failure blames the button
|
|
@@ -297,27 +297,27 @@ and then reports `click: Timeout … waiting for getByTestId('supervisor-submit'
|
|
|
297
297
|
button. Nothing is wrong with the button; read the `subtree intercepts pointer events` line, which
|
|
298
298
|
names `[data-consent-dialog]`.
|
|
299
299
|
|
|
300
|
-
`loginViaSupervisorForm` therefore calls
|
|
301
|
-
|
|
300
|
+
`makePageHelper(page).loginViaSupervisorForm` therefore calls `.acceptConsent()` after navigating. `.acceptConsent` is
|
|
301
|
+
public for specs that drive their own login: it waits for `[data-consent-dialog]` to become
|
|
302
302
|
visible, clicks `[data-consent-accept-all]`, waits for the dialog to detach, and reports whether it
|
|
303
303
|
answered one. It accepts **all** categories deliberately — a spec asserting a narrower decision must
|
|
304
304
|
make that decision itself rather than inherit a silent minimum.
|
|
305
305
|
|
|
306
306
|
**The `false` return costs the full wait.** It is what the visibility wait rejects into, not a cheap
|
|
307
|
-
probe, so a page with no dialog pays the timeout — 5s by `acceptConsent`'s own default, but
|
|
308
|
-
|
|
307
|
+
probe, so a page with no dialog pays the timeout — 5s by `makePageHelper(page).acceptConsent`'s own default, but
|
|
308
|
+
`.loginViaSupervisorForm` passes its `timeout` straight through and that defaults to `60_000`. On an
|
|
309
309
|
app that ships no consent widget the login helper therefore sits for a full minute before it fills
|
|
310
310
|
the first field, with nothing on screen to explain it. Drive such an app with `consent: 'ignore'`,
|
|
311
311
|
which skips the call entirely; that is also the switch a spec flips when it wants to answer the
|
|
312
312
|
dialog itself.
|
|
313
313
|
|
|
314
|
-
## `answerMarketingConsent` — cheap absence detection, unlike the cookie dialog
|
|
314
|
+
## `makePageHelper(page).answerMarketingConsent` — cheap absence detection, unlike the cookie dialog
|
|
315
315
|
|
|
316
|
-
`loginViaSupervisorForm` and
|
|
316
|
+
`makePageHelper(page).loginViaSupervisorForm` and `.loginViaDispatcher` both call `.answerMarketingConsent({ accept:
|
|
317
317
|
'all', timeout })` right after they confirm the app has navigated away from login/dispatch, passing
|
|
318
318
|
their **own** `timeout` through explicitly rather than relying on this helper's internal default —
|
|
319
319
|
both of them already budget more than one round trip (login + terms + items) into the value they
|
|
320
|
-
pick. Both also default `marketingConsent` (their own option, not
|
|
320
|
+
pick. Both also default `marketingConsent` (their own option, not `.answerMarketingConsent`'s) to
|
|
321
321
|
`'save'` — pass `'ignore'` to skip the call in a spec that drives the step itself.
|
|
322
322
|
`@owlmeans/web-marketing-consent` renders a full-page step, when shown, with `[data-marketing-consent]`
|
|
323
323
|
(root, carrying `data-state="loading"` while its status read is outstanding and `"ready"` once it can
|
|
@@ -329,15 +329,15 @@ step is optional-only — i.e. `!loading && !terms.needed` — not only after a
|
|
|
329
329
|
`[data-marketing-consent-skip-note]`, `[data-marketing-consent-signout]` (shown while a Terms box or
|
|
330
330
|
the loading state is up) and `[data-marketing-consent-error]`.
|
|
331
331
|
|
|
332
|
-
Unlike `acceptConsent`, whose `false` return deliberately costs the full wait (see above),
|
|
333
|
-
|
|
332
|
+
Unlike `makePageHelper(page).acceptConsent`, whose `false` return deliberately costs the full wait (see above),
|
|
333
|
+
`.answerMarketingConsent` does NOT pay the full `timeout` (default `30_000`) when the step is absent.
|
|
334
334
|
The screen is opt-in per app and most applications and environments don't have it wired in yet, and this helper
|
|
335
335
|
is called unconditionally by both login helpers — a full-timeout tax on every login, on every app,
|
|
336
336
|
whether or not the screen exists, would be an unacceptable regression to every existing suite. It
|
|
337
337
|
instead races `[data-marketing-consent]` against the generic "the app has already landed" /
|
|
338
338
|
"still on the login screen" markers the login helpers themselves already rely on (`#app-prompt`,
|
|
339
339
|
`[data-login-method]`) via the same `locator('a, b, c').first().waitFor({ state: 'visible' })` idiom
|
|
340
|
-
|
|
340
|
+
`.loginViaSupervisorForm` uses for its own dialog-vs-form race. By the time a login helper calls this,
|
|
341
341
|
one of those markers has typically already rendered, so on an app without the screen the race
|
|
342
342
|
resolves as soon as it does — no fixed sleep, and no meaningful added latency over what the login
|
|
343
343
|
helper already paid to get there.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Browser, LaunchOptions, Page } from 'playwright';
|
|
2
|
+
/** The one chromium a `bun test` process shares, and the pages specs drive off it. */
|
|
3
|
+
export interface BrowserHelper {
|
|
4
|
+
/**
|
|
5
|
+
* Launch (or return) a single shared chromium instance for the current
|
|
6
|
+
* `bun test` process. UI specs hold a fixture page off this browser; the
|
|
7
|
+
* suite calls {@link BrowserHelper.closeBrowser} from `afterAll` to tear it down once.
|
|
8
|
+
*/
|
|
9
|
+
launchBrowser: (opts?: LaunchOptions) => Promise<Browser>;
|
|
10
|
+
/**
|
|
11
|
+
* Tear down the shared browser. Idempotent — safe to call from multiple
|
|
12
|
+
* `afterAll` hooks.
|
|
13
|
+
*/
|
|
14
|
+
closeBrowser: () => Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Convenience that launches the browser, runs a callback with a fresh
|
|
17
|
+
* context + page, and closes the context on completion. The browser
|
|
18
|
+
* itself stays alive across calls so multiple specs share it cheaply.
|
|
19
|
+
*/
|
|
20
|
+
withPage: <T>(fn: (page: Page) => Promise<T>) => Promise<T>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/browser/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAE9D,sFAAsF;AACtF,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,aAAa,EAAE,CAAC,IAAI,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACzD;;;OAGG;IACH,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC;;;;OAIG;IACH,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;CAC5D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/browser/types.ts"],"names":[],"mappings":""}
|
package/build/browser.d.ts
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import type { Browser, LaunchOptions } from 'playwright';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*/
|
|
1
|
+
import type { Browser, LaunchOptions, Page } from 'playwright';
|
|
2
|
+
import type { BrowserHelper } from './browser/types.js';
|
|
3
|
+
export declare const createBrowserHelper: () => BrowserHelper;
|
|
4
|
+
export declare const browserHelper: BrowserHelper;
|
|
5
|
+
/** @deprecated compat:factory-refactor — use `browserHelper.launchBrowser(…)` */
|
|
7
6
|
export declare const launchBrowser: (opts?: LaunchOptions) => Promise<Browser>;
|
|
8
|
-
/**
|
|
9
|
-
* Tear down the shared browser. Idempotent — safe to call from multiple
|
|
10
|
-
* `afterAll` hooks.
|
|
11
|
-
*/
|
|
7
|
+
/** @deprecated compat:factory-refactor — use `browserHelper.closeBrowser()` */
|
|
12
8
|
export declare const closeBrowser: () => Promise<void>;
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
* context + page, and closes the context on completion. The browser
|
|
16
|
-
* itself stays alive across calls so multiple specs share it cheaply.
|
|
17
|
-
*/
|
|
18
|
-
export declare const withPage: <T>(fn: (page: import('playwright').Page) => Promise<T>) => Promise<T>;
|
|
9
|
+
/** @deprecated compat:factory-refactor — use `browserHelper.withPage(…)` */
|
|
10
|
+
export declare const withPage: <T>(fn: (page: Page) => Promise<T>) => Promise<T>;
|
|
19
11
|
//# sourceMappingURL=browser.d.ts.map
|
package/build/browser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAMvD,eAAO,MAAM,mBAAmB,QAAO,aA+BtC,CAAA;AAED,eAAO,MAAM,aAAa,eAAwB,CAAA;AAElD,iFAAiF;AACjF,eAAO,MAAM,aAAa,UAAgB,aAAa,KAAQ,OAAO,CAAC,OAAO,CACrC,CAAA;AAEzC,+EAA+E;AAC/E,eAAO,MAAM,YAAY,QAAa,OAAO,CAAC,IAAI,CAAuC,CAAA;AAEzF,4EAA4E;AAC5E,eAAO,MAAM,QAAQ,GAAU,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAC1C,CAAA"}
|
package/build/browser.js
CHANGED
|
@@ -1,47 +1,44 @@
|
|
|
1
1
|
import { chromium } from 'playwright';
|
|
2
|
+
// Process-wide on purpose: every spec of a `bun test` run shares one browser.
|
|
2
3
|
let shared;
|
|
3
4
|
let inflight;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
export const createBrowserHelper = () => {
|
|
6
|
+
const launchBrowser = async (opts = {}) => {
|
|
7
|
+
if (shared != null)
|
|
8
|
+
return shared;
|
|
9
|
+
if (inflight != null)
|
|
10
|
+
return inflight;
|
|
11
|
+
inflight = chromium.launch({ headless: true, ...opts });
|
|
12
|
+
shared = await inflight;
|
|
13
|
+
inflight = undefined;
|
|
11
14
|
return shared;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* context + page, and closes the context on completion. The browser
|
|
34
|
-
* itself stays alive across calls so multiple specs share it cheaply.
|
|
35
|
-
*/
|
|
36
|
-
export const withPage = async (fn) => {
|
|
37
|
-
const browser = await launchBrowser();
|
|
38
|
-
const context = await browser.newContext();
|
|
39
|
-
const page = await context.newPage();
|
|
40
|
-
try {
|
|
41
|
-
return await fn(page);
|
|
42
|
-
}
|
|
43
|
-
finally {
|
|
44
|
-
await context.close();
|
|
45
|
-
}
|
|
15
|
+
};
|
|
16
|
+
const closeBrowser = async () => {
|
|
17
|
+
const b = shared;
|
|
18
|
+
shared = undefined;
|
|
19
|
+
inflight = undefined;
|
|
20
|
+
if (b != null) {
|
|
21
|
+
await b.close();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const withPage = async (fn) => {
|
|
25
|
+
const browser = await launchBrowser();
|
|
26
|
+
const context = await browser.newContext();
|
|
27
|
+
const page = await context.newPage();
|
|
28
|
+
try {
|
|
29
|
+
return await fn(page);
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
await context.close();
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
return { launchBrowser, closeBrowser, withPage };
|
|
46
36
|
};
|
|
37
|
+
export const browserHelper = createBrowserHelper();
|
|
38
|
+
/** @deprecated compat:factory-refactor — use `browserHelper.launchBrowser(…)` */
|
|
39
|
+
export const launchBrowser = async (opts = {}) => await browserHelper.launchBrowser(opts);
|
|
40
|
+
/** @deprecated compat:factory-refactor — use `browserHelper.closeBrowser()` */
|
|
41
|
+
export const closeBrowser = async () => await browserHelper.closeBrowser();
|
|
42
|
+
/** @deprecated compat:factory-refactor — use `browserHelper.withPage(…)` */
|
|
43
|
+
export const withPage = async (fn) => await browserHelper.withPage(fn);
|
|
47
44
|
//# sourceMappingURL=browser.js.map
|
package/build/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAIrC,8EAA8E;AAC9E,IAAI,MAA2B,CAAA;AAC/B,IAAI,QAAsC,CAAA;AAE1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAkB,EAAE;IACrD,MAAM,aAAa,GAAG,KAAK,EAAE,IAAI,GAAkB,EAAE,EAAoB,EAAE;QACzE,IAAI,MAAM,IAAI,IAAI;YAAE,OAAO,MAAM,CAAA;QACjC,IAAI,QAAQ,IAAI,IAAI;YAAE,OAAO,QAAQ,CAAA;QACrC,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,CAAA;QACvD,MAAM,GAAG,MAAM,QAAQ,CAAA;QACvB,QAAQ,GAAG,SAAS,CAAA;QACpB,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;IAED,MAAM,YAAY,GAAG,KAAK,IAAmB,EAAE;QAC7C,MAAM,CAAC,GAAG,MAAM,CAAA;QAChB,MAAM,GAAG,SAAS,CAAA;QAClB,QAAQ,GAAG,SAAS,CAAA;QACpB,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YACd,MAAM,CAAC,CAAC,KAAK,EAAE,CAAA;QACjB,CAAC;IACH,CAAC,CAAA;IAED,MAAM,QAAQ,GAAG,KAAK,EAAK,EAA8B,EAAc,EAAE;QACvE,MAAM,OAAO,GAAG,MAAM,aAAa,EAAE,CAAA;QACrC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAA;QAC1C,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAA;QACpC,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,CAAC,IAAI,CAAC,CAAA;QACvB,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAA;QACvB,CAAC;IACH,CAAC,CAAA;IAED,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAA;AAClD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,mBAAmB,EAAE,CAAA;AAElD,iFAAiF;AACjF,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,IAAI,GAAkB,EAAE,EAAoB,EAAE,CAChF,MAAM,aAAa,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;AAEzC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,IAAmB,EAAE,CAAC,MAAM,aAAa,CAAC,YAAY,EAAE,CAAA;AAEzF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,EAAK,EAA8B,EAAc,EAAE,CAC9E,MAAM,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA"}
|
package/build/index.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export * from './browser.js';
|
|
2
|
+
export type * from './browser/types.js';
|
|
2
3
|
export * from './marketing-consent.js';
|
|
3
4
|
export type * from './types.js';
|
|
4
5
|
export * from './mount.js';
|
|
6
|
+
export * from './page.js';
|
|
7
|
+
export type * from './page/types.js';
|
|
5
8
|
export * from './supervisor.js';
|
|
9
|
+
export type * from './supervisor/types.js';
|
|
6
10
|
export type { Browser, BrowserContext, Locator, Page } from 'playwright';
|
|
7
11
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,wBAAwB,CAAA;AACtC,mBAAmB,YAAY,CAAA;AAC/B,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,mBAAmB,oBAAoB,CAAA;AACvC,cAAc,wBAAwB,CAAA;AACtC,mBAAmB,YAAY,CAAA;AAC/B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,mBAAmB,iBAAiB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,mBAAmB,uBAAuB,CAAA;AAC1C,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA"}
|
package/build/index.js
CHANGED
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAE5B,cAAc,wBAAwB,CAAA;AAEtC,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AAEzB,cAAc,iBAAiB,CAAA"}
|
|
@@ -1,25 +1,5 @@
|
|
|
1
1
|
import type { Page } from 'playwright';
|
|
2
|
-
import type { AnswerMarketingConsentOptions } from './types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Answer the marketing-consent full-page step (`@owlmeans/web-marketing-consent`) if it is shown
|
|
5
|
-
* right after login, so a spec driving {@link loginViaSupervisorForm} or {@link loginViaDispatcher}
|
|
6
|
-
* is never blocked behind it.
|
|
7
|
-
*
|
|
8
|
-
* The screen is opt-in per app, and most apps/environments will not have it wired in — that makes
|
|
9
|
-
* detecting its ABSENCE cheaply the whole point. A plain `waitFor` on `[data-marketing-consent]`
|
|
10
|
-
* alone would cost the full `timeout` on every login of every app that never renders it (the same
|
|
11
|
-
* caveat `acceptConsent` documents for the cookie dialog). Instead this races the step's own root
|
|
12
|
-
* against the generic OwlMeans "the app has already landed" / "still on the login screen" markers
|
|
13
|
-
* this file's own login helpers already wait on (`#app-prompt`, `[data-login-method]`) — by the
|
|
14
|
-
* time a login helper calls this, one of those has typically already rendered, so the race resolves
|
|
15
|
-
* as soon as it does: no fixed sleep, and in the common "step absent" case, no material added
|
|
16
|
-
* latency over what the login helper already paid to get here.
|
|
17
|
-
*
|
|
18
|
-
* @returns whether the step was actually shown and answered (including the error/skip fallback
|
|
19
|
-
* below); `false` when it never appeared within `timeout`, which is the expected result everywhere
|
|
20
|
-
* the screen is not yet configured or the visitor already has saved consents.
|
|
21
|
-
* @throws if a Terms box could not be confirmed (a `[data-marketing-consent-terms-error]`, or the
|
|
22
|
-
* box is still up with nowhere left to go — Skip is never offered there on purpose).
|
|
23
|
-
*/
|
|
2
|
+
import type { AnswerMarketingConsentOptions } from './page/types.js';
|
|
3
|
+
/** @deprecated compat:factory-refactor — use `makePageHelper(page).answerMarketingConsent(…)` */
|
|
24
4
|
export declare const answerMarketingConsent: (page: Page, opts?: AnswerMarketingConsentOptions) => Promise<boolean>;
|
|
25
5
|
//# sourceMappingURL=marketing-consent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketing-consent.d.ts","sourceRoot":"","sources":["../src/marketing-consent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEtC,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"marketing-consent.d.ts","sourceRoot":"","sources":["../src/marketing-consent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEtC,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,iBAAiB,CAAA;AAEpE,iGAAiG;AACjG,eAAO,MAAM,sBAAsB,SAC3B,IAAI,SAAS,6BAA6B,KAC/C,OAAO,CAAC,OAAO,CAA4D,CAAA"}
|
|
@@ -1,107 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
* right after login, so a spec driving {@link loginViaSupervisorForm} or {@link loginViaDispatcher}
|
|
5
|
-
* is never blocked behind it.
|
|
6
|
-
*
|
|
7
|
-
* The screen is opt-in per app, and most apps/environments will not have it wired in — that makes
|
|
8
|
-
* detecting its ABSENCE cheaply the whole point. A plain `waitFor` on `[data-marketing-consent]`
|
|
9
|
-
* alone would cost the full `timeout` on every login of every app that never renders it (the same
|
|
10
|
-
* caveat `acceptConsent` documents for the cookie dialog). Instead this races the step's own root
|
|
11
|
-
* against the generic OwlMeans "the app has already landed" / "still on the login screen" markers
|
|
12
|
-
* this file's own login helpers already wait on (`#app-prompt`, `[data-login-method]`) — by the
|
|
13
|
-
* time a login helper calls this, one of those has typically already rendered, so the race resolves
|
|
14
|
-
* as soon as it does: no fixed sleep, and in the common "step absent" case, no material added
|
|
15
|
-
* latency over what the login helper already paid to get here.
|
|
16
|
-
*
|
|
17
|
-
* @returns whether the step was actually shown and answered (including the error/skip fallback
|
|
18
|
-
* below); `false` when it never appeared within `timeout`, which is the expected result everywhere
|
|
19
|
-
* the screen is not yet configured or the visitor already has saved consents.
|
|
20
|
-
* @throws if a Terms box could not be confirmed (a `[data-marketing-consent-terms-error]`, or the
|
|
21
|
-
* box is still up with nowhere left to go — Skip is never offered there on purpose).
|
|
22
|
-
*/
|
|
23
|
-
export const answerMarketingConsent = async (page, opts) => {
|
|
24
|
-
const timeout = opts?.timeout ?? DEFAULT_MARKETING_CONSENT_TIMEOUT;
|
|
25
|
-
const step = page.locator('[data-marketing-consent]');
|
|
26
|
-
try {
|
|
27
|
-
await page.locator('[data-marketing-consent], #app-prompt, [data-login-method]')
|
|
28
|
-
.first().waitFor({ state: 'visible', timeout });
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
if (await step.count() === 0)
|
|
34
|
-
return false;
|
|
35
|
-
// The step's own status read may still be outstanding (`data-state="loading"`) — wait past it,
|
|
36
|
-
// OR notice it already auto-continued (nothing was pending) and detached on its own. An older
|
|
37
|
-
// `web-marketing-consent` that predates `data-state` entirely satisfies the first selector
|
|
38
|
-
// immediately (a missing attribute is never `"loading"`), so this costs nothing there.
|
|
39
|
-
await Promise.race([
|
|
40
|
-
page.waitForSelector('[data-marketing-consent]:not([data-state="loading"])', { timeout }),
|
|
41
|
-
page.waitForSelector('[data-marketing-consent]', { state: 'detached', timeout }),
|
|
42
|
-
]).catch(() => undefined);
|
|
43
|
-
// Nothing was pending — it already auto-continued while this waited.
|
|
44
|
-
if (await step.count() === 0)
|
|
45
|
-
return true;
|
|
46
|
-
const terms = page.locator('[data-marketing-consent-terms]');
|
|
47
|
-
const hasTerms = await terms.count() > 0;
|
|
48
|
-
if (!hasTerms && opts?.accept === 'skip') {
|
|
49
|
-
await page.locator('[data-marketing-consent-skip]').click();
|
|
50
|
-
await step.waitFor({ state: 'detached', timeout });
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
if ((opts?.accept ?? 'all') === 'all') {
|
|
54
|
-
// The step draws "Select all" only when there is more than one row to select; a lone consent
|
|
55
|
-
// is ticked itself. Select all speaks for the Terms row too while it is up, which the choice
|
|
56
|
-
// below then settles either way.
|
|
57
|
-
const all = page.locator('[data-marketing-consent-all]');
|
|
58
|
-
if (await all.count() > 0) {
|
|
59
|
-
await all.click();
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
for (const item of await page.locator('[data-marketing-consent-item]').all()) {
|
|
63
|
-
await item.check();
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
// 'none' leaves every item unchecked and clicks nothing else before saving.
|
|
68
|
-
if (hasTerms) {
|
|
69
|
-
const wanted = (opts?.terms ?? 'accept') === 'accept';
|
|
70
|
-
if (wanted && !(await terms.isChecked())) {
|
|
71
|
-
await terms.check();
|
|
72
|
-
}
|
|
73
|
-
else if (!wanted && await terms.isChecked()) {
|
|
74
|
-
await terms.uncheck();
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
// `{ force: true }`: the confirm is never the native `disabled` — only `aria-disabled` while a
|
|
78
|
-
// Terms box is unticked, or merely styled muted with nothing changed yet — and Playwright's own
|
|
79
|
-
// actionability check honours `aria-disabled`, which this helper deliberately does not.
|
|
80
|
-
await page.locator('[data-marketing-consent-save]').click({ force: true });
|
|
81
|
-
const outcome = await Promise.race([
|
|
82
|
-
step.waitFor({ state: 'detached', timeout }).then(() => 'saved'),
|
|
83
|
-
page.locator('[data-marketing-consent-error]').waitFor({ state: 'visible', timeout })
|
|
84
|
-
.then(() => 'error'),
|
|
85
|
-
page.locator('[data-marketing-consent-terms-error]').waitFor({ state: 'visible', timeout })
|
|
86
|
-
.then(() => 'terms-error'),
|
|
87
|
-
]).catch(() => 'error');
|
|
88
|
-
if (outcome === 'terms-error') {
|
|
89
|
-
throw new Error('[@owlmeans/test-ui] the marketing-consent step could not confirm the Terms');
|
|
90
|
-
}
|
|
91
|
-
if (outcome !== 'saved') {
|
|
92
|
-
const skip = page.locator('[data-marketing-consent-skip]');
|
|
93
|
-
if (await skip.count() > 0) {
|
|
94
|
-
console.warn('[@owlmeans/test-ui] marketing consent save did not complete; using the skip link instead');
|
|
95
|
-
await skip.click();
|
|
96
|
-
await step.waitFor({ state: 'detached', timeout }).catch(() => undefined);
|
|
97
|
-
}
|
|
98
|
-
else if (await terms.count() > 0) {
|
|
99
|
-
// No Skip is ever offered while the Terms box is up — a failed/blocked confirm here has no
|
|
100
|
-
// fallback, and silently returning would hide a caller stuck behind a real requirement.
|
|
101
|
-
throw new Error('[@owlmeans/test-ui] the marketing-consent step is still showing its Terms box');
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
// Answered either way: saved, or skipped past a flaky save. Never leaves the caller blocked.
|
|
105
|
-
return true;
|
|
106
|
-
};
|
|
1
|
+
import { makePageHelper } from './page.js';
|
|
2
|
+
/** @deprecated compat:factory-refactor — use `makePageHelper(page).answerMarketingConsent(…)` */
|
|
3
|
+
export const answerMarketingConsent = async (page, opts) => await makePageHelper(page).answerMarketingConsent(opts);
|
|
107
4
|
//# sourceMappingURL=marketing-consent.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketing-consent.js","sourceRoot":"","sources":["../src/marketing-consent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"marketing-consent.js","sourceRoot":"","sources":["../src/marketing-consent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAG1C,iGAAiG;AACjG,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EACzC,IAAU,EAAE,IAAoC,EAC9B,EAAE,CAAC,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAA"}
|
package/build/mount.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type { Mounted, MountOptions } from './types.js';
|
|
|
9
9
|
* try { expect(await page.locator('h1').textContent()).toBe('Sign in') }
|
|
10
10
|
* finally { await close() }
|
|
11
11
|
*
|
|
12
|
-
* `closeBrowser()` from `afterAll` tears down the shared browser at the end of the suite.
|
|
12
|
+
* `browserHelper.closeBrowser()` from `afterAll` tears down the shared browser at the end of the suite.
|
|
13
13
|
*/
|
|
14
14
|
export declare const mountComponent: (opts: MountOptions) => Promise<Mounted>;
|
|
15
15
|
//# sourceMappingURL=mount.d.ts.map
|
package/build/mount.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { browserHelper } from './browser.js';
|
|
2
2
|
const buildUrl = (opts) => {
|
|
3
3
|
const params = new URLSearchParams();
|
|
4
4
|
if (opts.component != null)
|
|
@@ -21,10 +21,10 @@ const buildUrl = (opts) => {
|
|
|
21
21
|
* try { expect(await page.locator('h1').textContent()).toBe('Sign in') }
|
|
22
22
|
* finally { await close() }
|
|
23
23
|
*
|
|
24
|
-
* `closeBrowser()` from `afterAll` tears down the shared browser at the end of the suite.
|
|
24
|
+
* `browserHelper.closeBrowser()` from `afterAll` tears down the shared browser at the end of the suite.
|
|
25
25
|
*/
|
|
26
26
|
export const mountComponent = async (opts) => {
|
|
27
|
-
const browser = await launchBrowser();
|
|
27
|
+
const browser = await browserHelper.launchBrowser();
|
|
28
28
|
const context = await browser.newContext();
|
|
29
29
|
const page = await context.newPage();
|
|
30
30
|
await page.goto(buildUrl(opts), {
|
package/build/mount.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAG5C,MAAM,QAAQ,GAAG,CAAC,IAAkB,EAAU,EAAE;IAC9C,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAA;IACpC,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI;QAAE,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;IACnE,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;IACvE,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAA;IAC5B,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC,GAAG,CAAA;IAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA;IAC9C,OAAO,GAAG,IAAI,CAAC,GAAG,GAAG,GAAG,GAAG,EAAE,EAAE,CAAA;AACjC,CAAC,CAAA;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,IAAkB,EAAoB,EAAE;IAC3E,MAAM,OAAO,GAAG,MAAM,aAAa,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAG5C,MAAM,QAAQ,GAAG,CAAC,IAAkB,EAAU,EAAE;IAC9C,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAA;IACpC,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI;QAAE,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;IACnE,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;IACvE,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAA;IAC5B,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC,GAAG,CAAA;IAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA;IAC9C,OAAO,GAAG,IAAI,CAAC,GAAG,GAAG,GAAG,GAAG,EAAE,EAAE,CAAA;AACjC,CAAC,CAAA;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,IAAkB,EAAoB,EAAE;IAC3E,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,aAAa,EAAE,CAAA;IACnD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAA;IAC1C,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAA;IACpC,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;QAC9B,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,kBAAkB;QAC/C,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3D,CAAC,CAAA;IACF,OAAO;QACL,IAAI;QACJ,KAAK,EAAE,KAAK,IAAI,EAAE,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,CAAA,CAAC,CAAC;KAC7C,CAAA;AACH,CAAC,CAAA"}
|