@rstest/browser 0.10.2 → 0.10.3

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.
@@ -12,7 +12,7 @@
12
12
  <script>
13
13
  window.__RSTEST_BROWSER_OPTIONS__ = __RSTEST_OPTIONS_PLACEHOLDER__;
14
14
  </script>
15
- <script defer src="/container-static/js/lib-react.5ae9b90ee5.js"></script><script defer src="/container-static/js/188.480c3c49b5.js"></script><script defer src="/container-static/js/index.29fc60be33.js"></script><link href="/container-static/css/index.5c72297783.css" rel="stylesheet"></head>
15
+ <script defer src="/container-static/js/lib-react.5ae9b90ee5.js"></script><script defer src="/container-static/js/27.099feaf1da.js"></script><script defer src="/container-static/js/index.be8c8d2626.js"></script><link href="/container-static/css/index.5c72297783.css" rel="stylesheet"></head>
16
16
  <body>
17
17
  <div id="root"></div>
18
18
  </body>
package/dist/browser.js CHANGED
@@ -1,4 +1,4 @@
1
- import { DISPATCH_RESPONSE_TYPE, DISPATCH_METHOD_RPC, DISPATCH_RPC_REQUEST_TYPE, DISPATCH_MESSAGE_TYPE, DISPATCH_NAMESPACE_BROWSER } from "./323.js";
1
+ import { DISPATCH_RESPONSE_TYPE, DISPATCH_RPC_REQUEST_TYPE, DISPATCH_MESSAGE_TYPE, DISPATCH_NAMESPACE_BROWSER } from "./626.js";
2
2
  const DEFAULT_RPC_TIMEOUT_MS = 30000;
3
3
  const getRpcTimeout = ()=>window.__RSTEST_BROWSER_OPTIONS__?.rpcTimeout ?? DEFAULT_RPC_TIMEOUT_MS;
4
4
  const pendingRequests = new Map();
@@ -97,7 +97,7 @@ const getCurrentRunId = ()=>{
97
97
  const createBrowserDispatchRequest = (requestId, request)=>({
98
98
  requestId,
99
99
  namespace: DISPATCH_NAMESPACE_BROWSER,
100
- method: DISPATCH_METHOD_RPC,
100
+ method: "rpc",
101
101
  args: request,
102
102
  target: {
103
103
  testFile: request.testPath
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import { WebSocketServer } from "ws";
10
10
  import node_os from "node:os";
11
11
  import convert_source_map from "convert-source-map";
12
12
  import { __webpack_require__ } from "./rslib-runtime.js";
13
- import { DISPATCH_RPC_BRIDGE_NAME, DISPATCH_MESSAGE_TYPE, DISPATCH_NAMESPACE_RUNNER } from "./323.js";
13
+ import { DISPATCH_RPC_BRIDGE_NAME, DISPATCH_MESSAGE_TYPE } from "./626.js";
14
14
  __webpack_require__.add({
15
15
  "../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/index.js" (module, __unused_rspack_exports, __webpack_require__) {
16
16
  const pico = __webpack_require__("../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/picomatch.js");
@@ -2428,6 +2428,41 @@ async function dispatchPlaywrightBrowserRpc({ containerPage, runnerPage, request
2428
2428
  }
2429
2429
  throw new Error(`Unknown browser rpc kind: ${request.kind}`);
2430
2430
  }
2431
+ const patchedPages = new WeakSet();
2432
+ const patchedContexts = new WeakSet();
2433
+ const withAsyncDispose = (resource)=>{
2434
+ if ('symbol' == typeof Symbol.asyncDispose) {
2435
+ const existing = Object.getOwnPropertyDescriptor(resource, Symbol.asyncDispose);
2436
+ if (!existing) Object.defineProperty(resource, Symbol.asyncDispose, {
2437
+ configurable: true,
2438
+ value: ()=>resource.close()
2439
+ });
2440
+ }
2441
+ return resource;
2442
+ };
2443
+ const wrapPage = (page)=>{
2444
+ if (patchedPages.has(page)) return withAsyncDispose(page);
2445
+ patchedPages.add(page);
2446
+ const originalOn = page.on.bind(page);
2447
+ page.on = (event, listener)=>{
2448
+ if ('popup' === event) return void originalOn(event, (popup)=>{
2449
+ listener(wrapPage(popup));
2450
+ });
2451
+ originalOn(event, listener);
2452
+ };
2453
+ return withAsyncDispose(page);
2454
+ };
2455
+ const wrapContext = (context)=>{
2456
+ if (patchedContexts.has(context)) return withAsyncDispose(context);
2457
+ patchedContexts.add(context);
2458
+ const originalNewPage = context.newPage.bind(context);
2459
+ context.newPage = async ()=>wrapPage(await originalNewPage());
2460
+ const originalOn = context.on.bind(context);
2461
+ context.on = (event, listener)=>{
2462
+ originalOn(event, (page)=>listener(wrapPage(page)));
2463
+ };
2464
+ return withAsyncDispose(context);
2465
+ };
2431
2466
  async function launchPlaywrightBrowser({ browserName, headless, providerOptions }) {
2432
2467
  const playwright = await import("playwright");
2433
2468
  const browserType = playwright[browserName];
@@ -2442,7 +2477,7 @@ async function launchPlaywrightBrowser({ browserName, headless, providerOptions
2442
2477
  headless,
2443
2478
  args: launchArgs
2444
2479
  });
2445
- const wrappedBrowser = {
2480
+ const wrappedBrowser = withAsyncDispose({
2446
2481
  close: async ()=>browser.close(),
2447
2482
  newContext: async ({ providerOptions: contextProviderOptions, viewport })=>{
2448
2483
  const contextOptions = contextProviderOptions?.context;
@@ -2450,9 +2485,9 @@ async function launchPlaywrightBrowser({ browserName, headless, providerOptions
2450
2485
  ...contextOptions,
2451
2486
  viewport
2452
2487
  });
2453
- return context;
2488
+ return wrapContext(context);
2454
2489
  }
2455
- };
2490
+ });
2456
2491
  return {
2457
2492
  browser: wrappedBrowser
2458
2493
  };
@@ -4072,14 +4107,14 @@ const runBrowserController = async (context, options)=>{
4072
4107
  const dispatchRouter = createDispatchRouter({
4073
4108
  isRunTokenStale: (runToken)=>runLifecycle.isTokenStale(runToken),
4074
4109
  onStale: (request)=>{
4075
- if (request.namespace === DISPATCH_NAMESPACE_RUNNER) logger.debug(`[Headless] Dropped stale message "${request.method}" for ${request.target?.testFile ?? 'unknown'}`);
4110
+ if ("runner" === request.namespace) logger.debug(`[Headless] Dropped stale message "${request.method}" for ${request.target?.testFile ?? 'unknown'}`);
4076
4111
  }
4077
4112
  });
4078
4113
  const dispatchRunnerMessage = async (run, file, sessionId, message)=>{
4079
4114
  const response = await dispatchRouter.dispatch({
4080
4115
  requestId: nextDispatchRequestId('runner'),
4081
4116
  runToken: run.token,
4082
- namespace: DISPATCH_NAMESPACE_RUNNER,
4117
+ namespace: "runner",
4083
4118
  method: message.type,
4084
4119
  args: 'payload' in message ? message.payload : void 0,
4085
4120
  target: {
@@ -39,16 +39,19 @@ export type BrowserProviderPage = {
39
39
  (event: 'console', listener: (message: BrowserConsoleMessage) => void): void;
40
40
  };
41
41
  close: () => Promise<void>;
42
+ [Symbol.asyncDispose]: () => Promise<void>;
42
43
  };
43
44
  /** Minimal browser context API surface required by hostController. */
44
45
  export type BrowserProviderContext = {
45
46
  newPage: () => Promise<BrowserProviderPage>;
46
47
  on: (event: 'page', listener: (page: BrowserProviderPage) => void) => void;
47
48
  close: () => Promise<void>;
49
+ [Symbol.asyncDispose]: () => Promise<void>;
48
50
  };
49
51
  /** Minimal browser API surface required by hostController. */
50
52
  export type BrowserProviderBrowser = {
51
53
  close: () => Promise<void>;
54
+ [Symbol.asyncDispose]: () => Promise<void>;
52
55
  newContext: (options: {
53
56
  viewport: {
54
57
  width: number;
@@ -20,11 +20,15 @@ __webpack_require__.m = __webpack_modules__;
20
20
  };
21
21
  })();
22
22
  (()=>{
23
- __webpack_require__.d = (exports, definition)=>{
24
- for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) Object.defineProperty(exports, key, {
25
- enumerable: true,
26
- get: definition[key]
27
- });
23
+ __webpack_require__.d = (exports, getters, values)=>{
24
+ var define = (defs, kind)=>{
25
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports, key)) Object.defineProperty(exports, key, {
26
+ enumerable: true,
27
+ [kind]: defs[key]
28
+ });
29
+ };
30
+ define(getters, "get");
31
+ define(values, "value");
28
32
  };
29
33
  })();
30
34
  (()=>{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rstest/browser",
3
- "version": "0.10.2",
3
+ "version": "0.10.3",
4
4
  "description": "Browser mode support for Rstest testing framework.",
5
5
  "keywords": [
6
6
  "rstest",
@@ -45,25 +45,25 @@
45
45
  "open-editor": "^6.0.0",
46
46
  "pathe": "^2.0.3",
47
47
  "sirv": "^3.0.2",
48
- "ws": "^8.20.1"
48
+ "ws": "^8.21.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@rslib/core": "0.21.5",
52
52
  "@types/convert-source-map": "^2.0.3",
53
53
  "@types/picomatch": "^4.0.3",
54
54
  "@types/ws": "^8.18.1",
55
- "@typescript/native-preview": "7.0.0-dev.20260516.1",
55
+ "@typescript/native-preview": "7.0.0-dev.20260527.1",
56
56
  "@vitest/snapshot": "^3.2.4",
57
57
  "birpc": "^4.0.0",
58
58
  "picomatch": "^4.0.4",
59
59
  "playwright": "^1.60.0",
60
60
  "@rstest/browser-ui": "0.0.0",
61
- "@rstest/tsconfig": "0.0.1",
62
- "@rstest/core": "0.10.2"
61
+ "@rstest/core": "0.10.3",
62
+ "@rstest/tsconfig": "0.0.1"
63
63
  },
64
64
  "peerDependencies": {
65
65
  "playwright": "^1.49.1",
66
- "@rstest/core": "^0.10.2"
66
+ "@rstest/core": "^0.10.3"
67
67
  },
68
68
  "peerDependenciesMeta": {
69
69
  "playwright": {
@@ -44,6 +44,7 @@ export type BrowserProviderPage = {
44
44
  ): void;
45
45
  };
46
46
  close: () => Promise<void>;
47
+ [Symbol.asyncDispose]: () => Promise<void>;
47
48
  };
48
49
 
49
50
  /** Minimal browser context API surface required by hostController. */
@@ -51,11 +52,13 @@ export type BrowserProviderContext = {
51
52
  newPage: () => Promise<BrowserProviderPage>;
52
53
  on: (event: 'page', listener: (page: BrowserProviderPage) => void) => void;
53
54
  close: () => Promise<void>;
55
+ [Symbol.asyncDispose]: () => Promise<void>;
54
56
  };
55
57
 
56
58
  /** Minimal browser API surface required by hostController. */
57
59
  export type BrowserProviderBrowser = {
58
60
  close: () => Promise<void>;
61
+ [Symbol.asyncDispose]: () => Promise<void>;
59
62
  newContext: (options: {
60
63
  viewport: { width: number; height: number } | null;
61
64
  providerOptions?: Record<string, unknown>;
@@ -1,4 +1,104 @@
1
- import type { BrowserProviderContext, BrowserProviderRuntime } from '../index';
1
+ import type {
2
+ BrowserConsoleMessage,
3
+ BrowserProviderContext,
4
+ BrowserProviderPage,
5
+ BrowserProviderRuntime,
6
+ } from '../index';
7
+
8
+ type PlaywrightPageLike = Omit<
9
+ BrowserProviderPage,
10
+ 'on' | typeof Symbol.asyncDispose
11
+ > & {
12
+ on: {
13
+ (event: 'popup', listener: (page: PlaywrightPageLike) => void): void;
14
+ (
15
+ event: 'console',
16
+ listener: (message: BrowserConsoleMessage) => void,
17
+ ): void;
18
+ };
19
+ };
20
+ type PlaywrightContextLike = Omit<
21
+ BrowserProviderContext,
22
+ 'newPage' | typeof Symbol.asyncDispose
23
+ > & {
24
+ newPage: () => Promise<PlaywrightPageLike>;
25
+ };
26
+
27
+ type AsyncDisposableResource<T> = T & {
28
+ [Symbol.asyncDispose]: () => Promise<void>;
29
+ };
30
+
31
+ type PlaywrightBrowserLike = Omit<
32
+ BrowserProviderRuntime['browser'],
33
+ typeof Symbol.asyncDispose
34
+ >;
35
+
36
+ const patchedPages = new WeakSet<PlaywrightPageLike>();
37
+ const patchedContexts = new WeakSet<PlaywrightContextLike>();
38
+
39
+ const withAsyncDispose = <T extends { close: () => Promise<void> }>(
40
+ resource: T,
41
+ ): AsyncDisposableResource<T> => {
42
+ if (typeof Symbol.asyncDispose === 'symbol') {
43
+ const existing = Object.getOwnPropertyDescriptor(
44
+ resource,
45
+ Symbol.asyncDispose,
46
+ );
47
+ if (!existing) {
48
+ Object.defineProperty(resource, Symbol.asyncDispose, {
49
+ configurable: true,
50
+ value: () => resource.close(),
51
+ });
52
+ }
53
+ }
54
+
55
+ return resource as AsyncDisposableResource<T>;
56
+ };
57
+
58
+ const wrapPage = (page: PlaywrightPageLike): BrowserProviderPage => {
59
+ if (patchedPages.has(page)) {
60
+ return withAsyncDispose(page) as BrowserProviderPage;
61
+ }
62
+
63
+ patchedPages.add(page);
64
+ const originalOn = page.on.bind(page);
65
+ page.on = ((
66
+ event: 'popup' | 'console',
67
+ listener:
68
+ | ((page: BrowserProviderPage) => void)
69
+ | ((message: BrowserConsoleMessage) => void),
70
+ ) => {
71
+ if (event === 'popup') {
72
+ originalOn(event, (popup) => {
73
+ (listener as (page: BrowserProviderPage) => void)(wrapPage(popup));
74
+ });
75
+ return;
76
+ }
77
+
78
+ originalOn(event, listener as (message: BrowserConsoleMessage) => void);
79
+ }) as PlaywrightPageLike['on'];
80
+
81
+ return withAsyncDispose(page) as BrowserProviderPage;
82
+ };
83
+
84
+ const wrapContext = (
85
+ context: PlaywrightContextLike,
86
+ ): BrowserProviderContext => {
87
+ if (patchedContexts.has(context)) {
88
+ return withAsyncDispose(context) as BrowserProviderContext;
89
+ }
90
+
91
+ patchedContexts.add(context);
92
+ const originalNewPage = context.newPage.bind(context);
93
+ context.newPage = async () => wrapPage(await originalNewPage());
94
+
95
+ const originalOn = context.on.bind(context);
96
+ context.on = (event, listener) => {
97
+ originalOn(event, (page) => listener(wrapPage(page)));
98
+ };
99
+
100
+ return withAsyncDispose(context) as BrowserProviderContext;
101
+ };
2
102
 
3
103
  export async function launchPlaywrightBrowser({
4
104
  browserName,
@@ -30,7 +130,7 @@ export async function launchPlaywrightBrowser({
30
130
  args: launchArgs,
31
131
  });
32
132
 
33
- const wrappedBrowser: BrowserProviderRuntime['browser'] = {
133
+ const wrappedBrowser = withAsyncDispose({
34
134
  close: async () => browser.close(),
35
135
  newContext: async ({
36
136
  providerOptions: contextProviderOptions,
@@ -44,9 +144,9 @@ export async function launchPlaywrightBrowser({
44
144
  viewport,
45
145
  });
46
146
 
47
- return context as unknown as BrowserProviderContext;
147
+ return wrapContext(context as unknown as PlaywrightContextLike);
48
148
  },
49
- };
149
+ } satisfies PlaywrightBrowserLike) as BrowserProviderRuntime['browser'];
50
150
 
51
151
  return {
52
152
  browser: wrappedBrowser,
@@ -1 +0,0 @@
1
- /*! LICENSE: 188.480c3c49b5.js.LICENSE.txt */