@rstest/browser 0.10.3 → 0.10.5

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.
Files changed (64) hide show
  1. package/dist/626.js +2 -1
  2. package/dist/browser-container/container-static/css/index.0521ff95b1.css +1 -0
  3. package/dist/browser-container/container-static/js/{27.099feaf1da.js → 854.c59f71483d.js} +5728 -5756
  4. package/dist/browser-container/container-static/js/854.c59f71483d.js.LICENSE.txt +1 -0
  5. package/dist/browser-container/container-static/js/{index.be8c8d2626.js → index.fedc31dff3.js} +109 -136
  6. package/dist/browser-container/container-static/js/{lib-react.5ae9b90ee5.js → lib-react.62b27a21db.js} +21 -21
  7. package/dist/browser-container/container-static/js/lib-react.62b27a21db.js.LICENSE.txt +1 -0
  8. package/dist/browser-container/index.html +1 -1
  9. package/dist/browser.js +4 -4
  10. package/dist/browserRpcRegistry.d.ts +1 -2
  11. package/dist/client/api.d.ts +1 -1
  12. package/dist/client/dispatchTransport.d.ts +18 -1
  13. package/dist/client/locator.d.ts +2 -3
  14. package/dist/concurrency.d.ts +5 -3
  15. package/dist/configValidation.d.ts +2 -2
  16. package/dist/dispatchCapabilities.d.ts +3 -3
  17. package/dist/dispatchRouter.d.ts +2 -3
  18. package/dist/headedSerialTaskQueue.d.ts +5 -5
  19. package/dist/headlessLatestRerunScheduler.d.ts +2 -3
  20. package/dist/headlessTransport.d.ts +2 -3
  21. package/dist/hostController.d.ts +12 -9
  22. package/dist/index.d.ts +6 -6
  23. package/dist/index.js +169 -216
  24. package/dist/protocol.d.ts +78 -55
  25. package/dist/providers/index.d.ts +18 -20
  26. package/dist/providers/playwright/dispatchBrowserRpc.d.ts +5 -3
  27. package/dist/providers/playwright/expectUtils.d.ts +2 -3
  28. package/dist/providers/playwright/implementation.d.ts +1 -1
  29. package/dist/providers/playwright/runtime.d.ts +1 -1
  30. package/dist/rpcProtocol.d.ts +36 -29
  31. package/dist/runSession.d.ts +3 -5
  32. package/dist/sessionRegistry.d.ts +2 -3
  33. package/dist/sourceMap/sourceMapLoader.d.ts +2 -2
  34. package/dist/viewportPresets.d.ts +7 -3
  35. package/dist/watchCliShortcuts.d.ts +1 -1
  36. package/dist/watchRerunPlanner.d.ts +2 -2
  37. package/package.json +7 -9
  38. package/src/AGENTS.md +7 -1
  39. package/src/browserRpcRegistry.ts +2 -2
  40. package/src/client/dispatchTransport.ts +63 -1
  41. package/src/client/entry.ts +25 -58
  42. package/src/client/public.ts +3 -3
  43. package/src/client/snapshot.ts +24 -22
  44. package/src/client/sourceMapSupport.ts +1 -1
  45. package/src/concurrency.ts +7 -21
  46. package/src/configValidation.ts +2 -2
  47. package/src/dispatchCapabilities.ts +102 -83
  48. package/src/env.d.ts +6 -2
  49. package/src/headedSerialTaskQueue.ts +5 -1
  50. package/src/hostController.ts +85 -43
  51. package/src/index.ts +22 -11
  52. package/src/protocol.ts +66 -22
  53. package/src/providers/index.ts +8 -1
  54. package/src/rpcProtocol.ts +34 -21
  55. package/src/viewportPresets.ts +5 -0
  56. package/src/watchCliShortcuts.ts +2 -4
  57. package/dist/browser-container/container-static/css/index.5c72297783.css +0 -1
  58. package/dist/browser-container/container-static/js/27.099feaf1da.js.LICENSE.txt +0 -1
  59. package/dist/browser-container/container-static/js/lib-react.5ae9b90ee5.js.LICENSE.txt +0 -1
  60. package/dist/client/entry.d.ts +0 -4
  61. package/dist/client/fakeTimersStub.d.ts +0 -25
  62. package/dist/client/public.d.ts +0 -9
  63. package/dist/client/snapshot.d.ts +0 -29
  64. package/dist/client/sourceMapSupport.d.ts +0 -42
package/dist/index.js CHANGED
@@ -2,15 +2,14 @@ import { existsSync } from "node:fs";
2
2
  import promises from "node:fs/promises";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { isDeepStrictEqual } from "node:util";
5
- import { PhaseTracker, color, createCoverageProvider, getNoTestFilesMessage, getSetupFiles, getTestEntries, isDebug, loadCoverageProvider, logger, resolveProjectBuildCache, rsbuild, serializableConfig } from "@rstest/core/browser";
5
+ import { DEFAULT_TEST_TIMEOUT, PhaseTracker, RSTEST_ENV_SYMBOL_KEY, color, createCoverageProvider, getNoTestFilesMessage, getNumCpus, getSetupFiles, getTestEntries, isDebug, isTTY, loadCoverageProvider, logger, parseWorkers, resolveProjectBuildCache, rsbuild, serializableConfig } from "@rstest/core/internal/browser";
6
6
  import open_editor from "open-editor";
7
7
  import { basename, dirname, join, normalize, relative, resolve as external_pathe_resolve } from "pathe";
8
8
  import sirv from "sirv";
9
9
  import { WebSocketServer } from "ws";
10
- import node_os from "node:os";
11
10
  import convert_source_map from "convert-source-map";
12
11
  import { __webpack_require__ } from "./rslib-runtime.js";
13
- import { DISPATCH_RPC_BRIDGE_NAME, DISPATCH_MESSAGE_TYPE } from "./626.js";
12
+ import { DISPATCH_RPC_BRIDGE_NAME, DISPATCH_NAMESPACE_SNAPSHOT, DISPATCH_MESSAGE_TYPE, DISPATCH_NAMESPACE_BROWSER } from "./626.js";
14
13
  __webpack_require__.add({
15
14
  "../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/index.js" (module, __unused_rspack_exports, __webpack_require__) {
16
15
  const pico = __webpack_require__("../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/picomatch.js");
@@ -1632,6 +1631,113 @@ __webpack_require__.add({
1632
1631
  };
1633
1632
  }
1634
1633
  });
1634
+ const BROWSER_VIEWPORT_PRESET_DIMENSIONS = {
1635
+ iPhoneSE: {
1636
+ width: 375,
1637
+ height: 667
1638
+ },
1639
+ iPhoneXR: {
1640
+ width: 414,
1641
+ height: 896
1642
+ },
1643
+ iPhone12Pro: {
1644
+ width: 390,
1645
+ height: 844
1646
+ },
1647
+ iPhone14ProMax: {
1648
+ width: 430,
1649
+ height: 932
1650
+ },
1651
+ Pixel7: {
1652
+ width: 412,
1653
+ height: 915
1654
+ },
1655
+ SamsungGalaxyS8Plus: {
1656
+ width: 360,
1657
+ height: 740
1658
+ },
1659
+ SamsungGalaxyS20Ultra: {
1660
+ width: 412,
1661
+ height: 915
1662
+ },
1663
+ iPadMini: {
1664
+ width: 768,
1665
+ height: 1024
1666
+ },
1667
+ iPadAir: {
1668
+ width: 820,
1669
+ height: 1180
1670
+ },
1671
+ iPadPro: {
1672
+ width: 1024,
1673
+ height: 1366
1674
+ },
1675
+ SurfacePro7: {
1676
+ width: 912,
1677
+ height: 1368
1678
+ },
1679
+ SurfaceDuo: {
1680
+ width: 540,
1681
+ height: 720
1682
+ },
1683
+ GalaxyZFold5: {
1684
+ width: 344,
1685
+ height: 882
1686
+ },
1687
+ AsusZenbookFold: {
1688
+ width: 853,
1689
+ height: 1280
1690
+ },
1691
+ SamsungGalaxyA51A71: {
1692
+ width: 412,
1693
+ height: 914
1694
+ },
1695
+ NestHub: {
1696
+ width: 1024,
1697
+ height: 600
1698
+ },
1699
+ NestHubMax: {
1700
+ width: 1280,
1701
+ height: 800
1702
+ }
1703
+ };
1704
+ const resolveBrowserViewportPreset = (presetId)=>{
1705
+ const size = BROWSER_VIEWPORT_PRESET_DIMENSIONS[presetId];
1706
+ return size ?? null;
1707
+ };
1708
+ const SUPPORTED_PROVIDERS = [
1709
+ 'playwright'
1710
+ ];
1711
+ const isPlainObject = (value)=>'[object Object]' === Object.prototype.toString.call(value);
1712
+ const validateViewport = (viewport)=>{
1713
+ if (null == viewport) return;
1714
+ if ('string' == typeof viewport) {
1715
+ const presetId = viewport.trim();
1716
+ if (!presetId) throw new Error('browser.viewport must be a non-empty preset id.');
1717
+ if (!resolveBrowserViewportPreset(presetId)) throw new Error(`browser.viewport must be a valid preset id. Received: ${viewport}`);
1718
+ return;
1719
+ }
1720
+ if (isPlainObject(viewport)) {
1721
+ const width = viewport.width;
1722
+ const height = viewport.height;
1723
+ if (!Number.isFinite(width) || width <= 0) throw new Error('browser.viewport.width must be a positive number.');
1724
+ if (!Number.isFinite(height) || height <= 0) throw new Error('browser.viewport.height must be a positive number.');
1725
+ return;
1726
+ }
1727
+ throw new Error('browser.viewport must be either a preset id or { width, height }.');
1728
+ };
1729
+ const validateBrowserConfig = (context)=>{
1730
+ for (const project of context.projects){
1731
+ const { browser, output } = project.normalizedConfig;
1732
+ if (browser.enabled) {
1733
+ if (!browser.provider) throw new Error('browser.provider is required when browser.enabled is true.');
1734
+ if (!SUPPORTED_PROVIDERS.includes(browser.provider)) throw new Error(`browser.provider must be one of: ${SUPPORTED_PROVIDERS.join(', ')}.`);
1735
+ validateViewport(browser.viewport);
1736
+ if (!isPlainObject(browser.providerOptions)) throw new Error('browser.providerOptions must be a plain object.');
1737
+ if (output?.bundleDependencies === false) throw new Error('output.bundleDependencies false is not supported in browser mode.');
1738
+ }
1739
+ }
1740
+ };
1635
1741
  const TYPE_REQUEST = "q";
1636
1742
  const TYPE_RESPONSE = "s";
1637
1743
  function createPromiseWithResolvers() {
@@ -1828,15 +1934,6 @@ function createBirpc($functions, options) {
1828
1934
  return rpc;
1829
1935
  }
1830
1936
  const DEFAULT_MAX_HEADLESS_WORKERS = 12;
1831
- const getNumCpus = ()=>node_os.availableParallelism?.() ?? node_os.cpus().length;
1832
- const parseWorkers = (maxWorkers, numCpus = getNumCpus())=>{
1833
- const parsed = Number.parseInt(maxWorkers.toString(), 10);
1834
- if ('string' == typeof maxWorkers && maxWorkers.trim().endsWith('%')) {
1835
- const workers = Math.floor(parsed / 100 * numCpus);
1836
- return Math.max(workers, 1);
1837
- }
1838
- return parsed > 0 ? parsed : 1;
1839
- };
1840
1937
  const resolveDefaultHeadlessWorkers = (command, numCpus = getNumCpus())=>{
1841
1938
  const baseWorkers = Math.max(Math.min(DEFAULT_MAX_HEADLESS_WORKERS, numCpus - 1), 1);
1842
1939
  return 'watch' === command ? Math.max(Math.floor(baseWorkers / 2), 1) : baseWorkers;
@@ -1895,72 +1992,49 @@ class HostDispatchRouter {
1895
1992
  }
1896
1993
  }
1897
1994
  }
1995
+ const snapshotRequestBuilders = {
1996
+ resolveSnapshotPath: (id, args)=>({
1997
+ id,
1998
+ method: 'resolveSnapshotPath',
1999
+ args: args
2000
+ }),
2001
+ readSnapshotFile: (id, args)=>({
2002
+ id,
2003
+ method: 'readSnapshotFile',
2004
+ args: args
2005
+ }),
2006
+ saveSnapshotFile: (id, args)=>({
2007
+ id,
2008
+ method: 'saveSnapshotFile',
2009
+ args: args
2010
+ }),
2011
+ removeSnapshotFile: (id, args)=>({
2012
+ id,
2013
+ method: 'removeSnapshotFile',
2014
+ args: args
2015
+ })
2016
+ };
1898
2017
  const toSnapshotRpcRequest = (request)=>{
1899
- switch(request.method){
1900
- case 'resolveSnapshotPath':
1901
- return {
1902
- id: request.requestId,
1903
- method: 'resolveSnapshotPath',
1904
- args: request.args
1905
- };
1906
- case 'readSnapshotFile':
1907
- return {
1908
- id: request.requestId,
1909
- method: 'readSnapshotFile',
1910
- args: request.args
1911
- };
1912
- case 'saveSnapshotFile':
1913
- return {
1914
- id: request.requestId,
1915
- method: 'saveSnapshotFile',
1916
- args: request.args
1917
- };
1918
- case 'removeSnapshotFile':
1919
- return {
1920
- id: request.requestId,
1921
- method: 'removeSnapshotFile',
1922
- args: request.args
1923
- };
1924
- default:
1925
- return null;
1926
- }
2018
+ const builder = snapshotRequestBuilders[request.method];
2019
+ return builder ? builder(request.requestId, request.args) : null;
1927
2020
  };
1928
2021
  const createHostDispatchRouter = ({ routerOptions, runnerCallbacks, runSnapshotRpc, extensionHandlers, onDuplicateNamespace })=>{
1929
2022
  const router = new HostDispatchRouter(routerOptions);
1930
- router.register('runner', async (request)=>{
1931
- switch(request.method){
1932
- case 'file-start':
1933
- await runnerCallbacks.onTestFileStart(request.args);
1934
- break;
1935
- case 'file-ready':
1936
- await runnerCallbacks.onTestFileReady(request.args);
1937
- break;
1938
- case 'suite-start':
1939
- await runnerCallbacks.onTestSuiteStart(request.args);
1940
- break;
1941
- case 'suite-result':
1942
- await runnerCallbacks.onTestSuiteResult(request.args);
1943
- break;
1944
- case 'case-start':
1945
- await runnerCallbacks.onTestCaseStart(request.args);
1946
- break;
1947
- case 'case-result':
1948
- await runnerCallbacks.onTestCaseResult(request.args);
1949
- break;
1950
- case 'file-complete':
1951
- await runnerCallbacks.onTestFileComplete(request.args);
1952
- break;
1953
- case 'log':
1954
- await runnerCallbacks.onLog(request.args);
1955
- break;
1956
- case 'fatal':
1957
- await runnerCallbacks.onFatal(request.args);
1958
- break;
1959
- default:
1960
- break;
1961
- }
2023
+ const runnerMethodHandlers = {
2024
+ 'file-start': (args)=>runnerCallbacks.onTestFileStart(args),
2025
+ 'file-ready': (args)=>runnerCallbacks.onTestFileReady(args),
2026
+ 'suite-start': (args)=>runnerCallbacks.onTestSuiteStart(args),
2027
+ 'suite-result': (args)=>runnerCallbacks.onTestSuiteResult(args),
2028
+ 'case-start': (args)=>runnerCallbacks.onTestCaseStart(args),
2029
+ 'case-result': (args)=>runnerCallbacks.onTestCaseResult(args),
2030
+ 'file-complete': (args)=>runnerCallbacks.onTestFileComplete(args),
2031
+ log: (args)=>runnerCallbacks.onLog(args),
2032
+ fatal: (args)=>runnerCallbacks.onFatal(args)
2033
+ };
2034
+ router.register("runner", async (request)=>{
2035
+ await runnerMethodHandlers[request.method]?.(request.args);
1962
2036
  });
1963
- router.register('snapshot', async (request)=>{
2037
+ router.register(DISPATCH_NAMESPACE_SNAPSHOT, async (request)=>{
1964
2038
  const snapshotRequest = toSnapshotRpcRequest(request);
1965
2039
  if (!snapshotRequest) return;
1966
2040
  return runSnapshotRpc(snapshotRequest);
@@ -2672,101 +2746,7 @@ const loadSourceMapWithCache = async ({ jsUrl, cache, force = false, origin, fet
2672
2746
  return null;
2673
2747
  }
2674
2748
  };
2675
- const BROWSER_VIEWPORT_PRESET_IDS = [
2676
- 'iPhoneSE',
2677
- 'iPhoneXR',
2678
- 'iPhone12Pro',
2679
- 'iPhone14ProMax',
2680
- 'Pixel7',
2681
- 'SamsungGalaxyS8Plus',
2682
- 'SamsungGalaxyS20Ultra',
2683
- 'iPadMini',
2684
- 'iPadAir',
2685
- 'iPadPro',
2686
- 'SurfacePro7',
2687
- 'SurfaceDuo',
2688
- 'GalaxyZFold5',
2689
- 'AsusZenbookFold',
2690
- 'SamsungGalaxyA51A71',
2691
- 'NestHub',
2692
- 'NestHubMax'
2693
- ];
2694
- const BROWSER_VIEWPORT_PRESET_DIMENSIONS = {
2695
- iPhoneSE: {
2696
- width: 375,
2697
- height: 667
2698
- },
2699
- iPhoneXR: {
2700
- width: 414,
2701
- height: 896
2702
- },
2703
- iPhone12Pro: {
2704
- width: 390,
2705
- height: 844
2706
- },
2707
- iPhone14ProMax: {
2708
- width: 430,
2709
- height: 932
2710
- },
2711
- Pixel7: {
2712
- width: 412,
2713
- height: 915
2714
- },
2715
- SamsungGalaxyS8Plus: {
2716
- width: 360,
2717
- height: 740
2718
- },
2719
- SamsungGalaxyS20Ultra: {
2720
- width: 412,
2721
- height: 915
2722
- },
2723
- iPadMini: {
2724
- width: 768,
2725
- height: 1024
2726
- },
2727
- iPadAir: {
2728
- width: 820,
2729
- height: 1180
2730
- },
2731
- iPadPro: {
2732
- width: 1024,
2733
- height: 1366
2734
- },
2735
- SurfacePro7: {
2736
- width: 912,
2737
- height: 1368
2738
- },
2739
- SurfaceDuo: {
2740
- width: 540,
2741
- height: 720
2742
- },
2743
- GalaxyZFold5: {
2744
- width: 344,
2745
- height: 882
2746
- },
2747
- AsusZenbookFold: {
2748
- width: 853,
2749
- height: 1280
2750
- },
2751
- SamsungGalaxyA51A71: {
2752
- width: 412,
2753
- height: 914
2754
- },
2755
- NestHub: {
2756
- width: 1024,
2757
- height: 600
2758
- },
2759
- NestHubMax: {
2760
- width: 1280,
2761
- height: 800
2762
- }
2763
- };
2764
- const resolveBrowserViewportPreset = (presetId)=>{
2765
- const size = BROWSER_VIEWPORT_PRESET_DIMENSIONS[presetId];
2766
- return size ?? null;
2767
- };
2768
- const isTTY = ()=>Boolean(process.stdin.isTTY && !process.env.CI);
2769
- const isBrowserWatchCliShortcutsEnabled = ()=>isTTY();
2749
+ const isBrowserWatchCliShortcutsEnabled = ()=>isTTY('stdin');
2770
2750
  const getBrowserWatchCliShortcutsHintMessage = ()=>` ${color.dim('press')} ${color.bold('q')} ${color.dim('to quit')}\n`;
2771
2751
  const logBrowserWatchReadyMessage = (enableCliShortcuts)=>{
2772
2752
  logger.log(color.green(' Waiting for file changes...'));
@@ -2835,6 +2815,7 @@ var picomatch_default = /*#__PURE__*/ __webpack_require__.n(picomatch);
2835
2815
  const { createRsbuild: createRsbuild, rspack: rspack } = rsbuild;
2836
2816
  const hostController_dirname = dirname(fileURLToPath(import.meta.url));
2837
2817
  const OPTIONS_PLACEHOLDER = '__RSTEST_OPTIONS_PLACEHOLDER__';
2818
+ const PER_FILE_TIMEOUT_BUFFER_MS = 30000;
2838
2819
  let nextBrowserFilePid = 1000000000;
2839
2820
  const serializeForInlineScript = (value)=>JSON.stringify(value).replace(/</g, '\\u003c').replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029');
2840
2821
  const getBrowserProviderOptions = (project)=>{
@@ -3101,6 +3082,7 @@ const getRuntimeConfigFromProject = (project)=>{
3101
3082
  return {
3102
3083
  env: {
3103
3084
  NODE_ENV: process.env.NODE_ENV,
3085
+ RSTEST: 'true',
3104
3086
  ...env
3105
3087
  },
3106
3088
  testNamePattern,
@@ -3328,12 +3310,12 @@ const createBrowserRuntime = async ({ context, manifestPath, manifestSource, tem
3328
3310
  ]));
3329
3311
  const userPlugins = browserProjects.flatMap((project)=>project.normalizedConfig.plugins || []);
3330
3312
  const browserLaunchOptions = ensureConsistentBrowserLaunchOptions(browserProjects);
3331
- const browserRuntimePath = fileURLToPath(import.meta.resolve('@rstest/core/browser-runtime'));
3313
+ const browserRuntimePath = fileURLToPath(import.meta.resolve('@rstest/core/internal/browser-runtime'));
3332
3314
  const rstestInternalAliases = {
3333
3315
  '@rstest/browser-manifest': manifestPath,
3334
3316
  '@rstest/core': resolveBrowserFile('client/public.ts'),
3335
3317
  '@rstest/browser': resolveBrowserFile('browser.ts'),
3336
- '@rstest/core/browser-runtime': browserRuntimePath,
3318
+ '@rstest/core/internal/browser-runtime': browserRuntimePath,
3337
3319
  '@sinonjs/fake-timers': resolveBrowserFile('client/fakeTimersStub.ts')
3338
3320
  };
3339
3321
  const rsbuildInstance = await createRsbuild({
@@ -3375,6 +3357,7 @@ const createBrowserRuntime = async ({ context, manifestPath, manifestSource, tem
3375
3357
  project
3376
3358
  });
3377
3359
  const setupFiles = Object.values(getSetupFiles(project.normalizedConfig.setupFiles, project.rootPath));
3360
+ const rstestEnvDefine = `globalThis[Symbol.for(${JSON.stringify(RSTEST_ENV_SYMBOL_KEY)})]`;
3378
3361
  const merged = mergeEnvironmentConfig(config, {
3379
3362
  ...userRsbuildConfig,
3380
3363
  performance: buildCache ? {
@@ -3387,8 +3370,8 @@ const createBrowserRuntime = async ({ context, manifestPath, manifestSource, tem
3387
3370
  },
3388
3371
  source: {
3389
3372
  define: {
3390
- 'process.env': 'globalThis[Symbol.for("rstest.env")]',
3391
- 'import.meta.env': 'globalThis[Symbol.for("rstest.env")]'
3373
+ 'process.env': rstestEnvDefine,
3374
+ 'import.meta.env': rstestEnvDefine
3392
3375
  }
3393
3376
  },
3394
3377
  output: {
@@ -3824,7 +3807,7 @@ const runBrowserController = async (context, options)=>{
3824
3807
  runtimeConfig: serializableConfig(getRuntimeConfigFromProject(project)),
3825
3808
  viewport: project.normalizedConfig.browser.viewport
3826
3809
  }));
3827
- const maxTestTimeoutForRpc = Math.max(...browserProjects.map((p)=>p.normalizedConfig.testTimeout ?? 5000));
3810
+ const maxTestTimeoutForRpc = Math.max(...browserProjects.map((p)=>p.normalizedConfig.testTimeout ?? DEFAULT_TEST_TIMEOUT));
3828
3811
  const hostOptions = {
3829
3812
  rootPath: normalize(context.rootPath),
3830
3813
  projects: projectRuntimeConfigs,
@@ -3867,7 +3850,7 @@ const runBrowserController = async (context, options)=>{
3867
3850
  throw String(error);
3868
3851
  }
3869
3852
  };
3870
- runtime.dispatchHandlers.set('browser', async (dispatchRequest)=>{
3853
+ runtime.dispatchHandlers.set(DISPATCH_NAMESPACE_BROWSER, async (dispatchRequest)=>{
3871
3854
  const request = validateBrowserRpcRequest(dispatchRequest.args);
3872
3855
  return dispatchBrowserRpcRequest({
3873
3856
  request,
@@ -4011,7 +3994,7 @@ const runBrowserController = async (context, options)=>{
4011
3994
  const pushTaskId = (taskIds, taskId)=>{
4012
3995
  if (!taskIds.includes(taskId)) taskIds.push(taskId);
4013
3996
  };
4014
- const shouldEmitUserConsoleLog = (log)=>context.normalizedConfig.onConsoleLog?.(log.content) !== false;
3997
+ const shouldEmitUserConsoleLog = (log)=>context.normalizedConfig.onConsoleLog?.(log.content, log.type) !== false;
4015
3998
  const emitUserConsoleLog = async (log)=>{
4016
3999
  if (!shouldEmitUserConsoleLog(log)) return;
4017
4000
  await Promise.all(context.reporters.map((reporter)=>reporter.onUserConsoleLog?.(log)));
@@ -4062,7 +4045,10 @@ const runBrowserController = async (context, options)=>{
4062
4045
  case 'removeSnapshotFile':
4063
4046
  return snapshotRpcMethods.removeSnapshotFile(request.args.filepath);
4064
4047
  default:
4065
- return;
4048
+ {
4049
+ const _exhaustive = request;
4050
+ return _exhaustive;
4051
+ }
4066
4052
  }
4067
4053
  };
4068
4054
  const createDispatchRouter = (options)=>createHostDispatchRouter({
@@ -4112,7 +4098,7 @@ const runBrowserController = async (context, options)=>{
4112
4098
  });
4113
4099
  const dispatchRunnerMessage = async (run, file, sessionId, message)=>{
4114
4100
  const response = await dispatchRouter.dispatch({
4115
- requestId: nextDispatchRequestId('runner'),
4101
+ requestId: nextDispatchRequestId("runner"),
4116
4102
  runToken: run.token,
4117
4103
  namespace: "runner",
4118
4104
  method: message.type,
@@ -4148,7 +4134,7 @@ const runBrowserController = async (context, options)=>{
4148
4134
  resolveDone = resolve;
4149
4135
  });
4150
4136
  const projectRuntime = projectRuntimeConfigs.find((project)=>project.name === file.projectName);
4151
- const perFileTimeoutMs = (projectRuntime?.runtimeConfig.testTimeout ?? maxTestTimeoutForRpc) + 30000;
4137
+ const perFileTimeoutMs = (projectRuntime?.runtimeConfig.testTimeout ?? maxTestTimeoutForRpc) + PER_FILE_TIMEOUT_BUFFER_MS;
4152
4138
  let timeoutId;
4153
4139
  try {
4154
4140
  page = await browserContext.newPage();
@@ -4471,7 +4457,7 @@ const runBrowserController = async (context, options)=>{
4471
4457
  };
4472
4458
  const getHeadedPerFileTimeoutMs = (file)=>{
4473
4459
  const projectRuntime = projectRuntimeConfigs.find((project)=>project.name === file.projectName);
4474
- return (projectRuntime?.runtimeConfig.testTimeout ?? maxTestTimeoutForRpc) + 30000;
4460
+ return (projectRuntime?.runtimeConfig.testTimeout ?? maxTestTimeoutForRpc) + PER_FILE_TIMEOUT_BUFFER_MS;
4475
4461
  };
4476
4462
  let containerContext;
4477
4463
  let containerPage;
@@ -4779,7 +4765,7 @@ const listBrowserTests = async (context, options)=>{
4779
4765
  runtimeConfig: serializableConfig(getRuntimeConfigFromProject(project)),
4780
4766
  viewport: project.normalizedConfig.browser.viewport
4781
4767
  }));
4782
- const maxTestTimeoutForRpc = Math.max(...browserProjects.map((p)=>p.normalizedConfig.testTimeout ?? 5000));
4768
+ const maxTestTimeoutForRpc = Math.max(...browserProjects.map((p)=>p.normalizedConfig.testTimeout ?? DEFAULT_TEST_TIMEOUT));
4783
4769
  const hostOptions = {
4784
4770
  rootPath: normalize(context.rootPath),
4785
4771
  projects: projectRuntimeConfigs,
@@ -4885,43 +4871,10 @@ const listBrowserTests = async (context, options)=>{
4885
4871
  close: cleanup
4886
4872
  };
4887
4873
  };
4888
- const SUPPORTED_PROVIDERS = [
4889
- 'playwright'
4890
- ];
4891
- const isPlainObject = (value)=>'[object Object]' === Object.prototype.toString.call(value);
4892
- const validateViewport = (viewport)=>{
4893
- if (null == viewport) return;
4894
- if ('string' == typeof viewport) {
4895
- const presetId = viewport.trim();
4896
- if (!presetId) throw new Error('browser.viewport must be a non-empty preset id.');
4897
- if (!resolveBrowserViewportPreset(presetId)) throw new Error(`browser.viewport must be a valid preset id. Received: ${viewport}`);
4898
- return;
4899
- }
4900
- if (isPlainObject(viewport)) {
4901
- const width = viewport.width;
4902
- const height = viewport.height;
4903
- if (!Number.isFinite(width) || width <= 0) throw new Error('browser.viewport.width must be a positive number.');
4904
- if (!Number.isFinite(height) || height <= 0) throw new Error('browser.viewport.height must be a positive number.');
4905
- return;
4906
- }
4907
- throw new Error('browser.viewport must be either a preset id or { width, height }.');
4908
- };
4909
- const validateBrowserConfig = (context)=>{
4910
- for (const project of context.projects){
4911
- const { browser, output } = project.normalizedConfig;
4912
- if (browser.enabled) {
4913
- if (!browser.provider) throw new Error('browser.provider is required when browser.enabled is true.');
4914
- if (!SUPPORTED_PROVIDERS.includes(browser.provider)) throw new Error(`browser.provider must be one of: ${SUPPORTED_PROVIDERS.join(', ')}.`);
4915
- validateViewport(browser.viewport);
4916
- if (!isPlainObject(browser.providerOptions)) throw new Error('browser.providerOptions must be a plain object.');
4917
- if (output?.bundleDependencies === false) throw new Error('output.bundleDependencies false is not supported in browser mode.');
4918
- }
4919
- }
4920
- };
4921
4874
  async function runBrowserTests(context, options) {
4922
4875
  return runBrowserController(context, options);
4923
4876
  }
4924
- async function src_listBrowserTests(context) {
4925
- return listBrowserTests(context);
4877
+ async function src_listBrowserTests(context, options) {
4878
+ return listBrowserTests(context, options);
4926
4879
  }
4927
- export { BROWSER_VIEWPORT_PRESET_DIMENSIONS, BROWSER_VIEWPORT_PRESET_IDS, resolveBrowserViewportPreset, runBrowserTests, src_listBrowserTests as listBrowserTests, validateBrowserConfig };
4880
+ export { runBrowserTests, src_listBrowserTests as listBrowserTests, validateBrowserConfig };