@rstest/browser 0.10.2 → 0.10.4
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/{323.js → 626.js} +2 -3
- package/dist/browser-container/container-static/js/{188.480c3c49b5.js → 3.d3d6c6e4cf.js} +2908 -2915
- package/dist/browser-container/container-static/js/3.d3d6c6e4cf.js.LICENSE.txt +1 -0
- package/dist/browser-container/container-static/js/{index.29fc60be33.js → index.8fb1588e4a.js} +431 -455
- package/dist/browser-container/container-static/js/{lib-react.5ae9b90ee5.js → lib-react.62b27a21db.js} +21 -21
- package/dist/browser-container/container-static/js/lib-react.62b27a21db.js.LICENSE.txt +1 -0
- package/dist/browser-container/index.html +1 -1
- package/dist/browser.js +5 -5
- package/dist/client/dispatchTransport.d.ts +19 -0
- package/dist/client/public.d.ts +3 -3
- package/dist/client/sourceMapSupport.d.ts +1 -1
- package/dist/concurrency.d.ts +3 -3
- package/dist/configValidation.d.ts +2 -2
- package/dist/dispatchCapabilities.d.ts +1 -1
- package/dist/hostController.d.ts +3 -3
- package/dist/index.d.ts +5 -5
- package/dist/index.js +209 -221
- package/dist/protocol.d.ts +45 -18
- package/dist/providers/index.d.ts +11 -1
- package/dist/rpcProtocol.d.ts +32 -18
- package/dist/rslib-runtime.js +9 -5
- package/dist/viewportPresets.d.ts +5 -0
- package/package.json +8 -8
- package/src/AGENTS.md +7 -1
- package/src/client/dispatchTransport.ts +63 -1
- package/src/client/entry.ts +25 -58
- package/src/client/public.ts +3 -3
- package/src/client/snapshot.ts +24 -22
- package/src/client/sourceMapSupport.ts +1 -1
- package/src/concurrency.ts +6 -20
- package/src/configValidation.ts +2 -2
- package/src/dispatchCapabilities.ts +102 -83
- package/src/env.d.ts +6 -2
- package/src/hostController.ts +76 -42
- package/src/index.ts +22 -11
- package/src/protocol.ts +66 -22
- package/src/providers/index.ts +11 -1
- package/src/providers/playwright/runtime.ts +104 -4
- package/src/rpcProtocol.ts +34 -21
- package/src/viewportPresets.ts +5 -0
- package/src/watchCliShortcuts.ts +2 -4
- package/dist/browser-container/container-static/js/188.480c3c49b5.js.LICENSE.txt +0 -1
- package/dist/browser-container/container-static/js/lib-react.5ae9b90ee5.js.LICENSE.txt +0 -1
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,
|
|
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
|
-
|
|
1900
|
-
|
|
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
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
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(
|
|
2037
|
+
router.register(DISPATCH_NAMESPACE_SNAPSHOT, async (request)=>{
|
|
1964
2038
|
const snapshotRequest = toSnapshotRpcRequest(request);
|
|
1965
2039
|
if (!snapshotRequest) return;
|
|
1966
2040
|
return runSnapshotRpc(snapshotRequest);
|
|
@@ -2428,6 +2502,41 @@ async function dispatchPlaywrightBrowserRpc({ containerPage, runnerPage, request
|
|
|
2428
2502
|
}
|
|
2429
2503
|
throw new Error(`Unknown browser rpc kind: ${request.kind}`);
|
|
2430
2504
|
}
|
|
2505
|
+
const patchedPages = new WeakSet();
|
|
2506
|
+
const patchedContexts = new WeakSet();
|
|
2507
|
+
const withAsyncDispose = (resource)=>{
|
|
2508
|
+
if ('symbol' == typeof Symbol.asyncDispose) {
|
|
2509
|
+
const existing = Object.getOwnPropertyDescriptor(resource, Symbol.asyncDispose);
|
|
2510
|
+
if (!existing) Object.defineProperty(resource, Symbol.asyncDispose, {
|
|
2511
|
+
configurable: true,
|
|
2512
|
+
value: ()=>resource.close()
|
|
2513
|
+
});
|
|
2514
|
+
}
|
|
2515
|
+
return resource;
|
|
2516
|
+
};
|
|
2517
|
+
const wrapPage = (page)=>{
|
|
2518
|
+
if (patchedPages.has(page)) return withAsyncDispose(page);
|
|
2519
|
+
patchedPages.add(page);
|
|
2520
|
+
const originalOn = page.on.bind(page);
|
|
2521
|
+
page.on = (event, listener)=>{
|
|
2522
|
+
if ('popup' === event) return void originalOn(event, (popup)=>{
|
|
2523
|
+
listener(wrapPage(popup));
|
|
2524
|
+
});
|
|
2525
|
+
originalOn(event, listener);
|
|
2526
|
+
};
|
|
2527
|
+
return withAsyncDispose(page);
|
|
2528
|
+
};
|
|
2529
|
+
const wrapContext = (context)=>{
|
|
2530
|
+
if (patchedContexts.has(context)) return withAsyncDispose(context);
|
|
2531
|
+
patchedContexts.add(context);
|
|
2532
|
+
const originalNewPage = context.newPage.bind(context);
|
|
2533
|
+
context.newPage = async ()=>wrapPage(await originalNewPage());
|
|
2534
|
+
const originalOn = context.on.bind(context);
|
|
2535
|
+
context.on = (event, listener)=>{
|
|
2536
|
+
originalOn(event, (page)=>listener(wrapPage(page)));
|
|
2537
|
+
};
|
|
2538
|
+
return withAsyncDispose(context);
|
|
2539
|
+
};
|
|
2431
2540
|
async function launchPlaywrightBrowser({ browserName, headless, providerOptions }) {
|
|
2432
2541
|
const playwright = await import("playwright");
|
|
2433
2542
|
const browserType = playwright[browserName];
|
|
@@ -2442,7 +2551,7 @@ async function launchPlaywrightBrowser({ browserName, headless, providerOptions
|
|
|
2442
2551
|
headless,
|
|
2443
2552
|
args: launchArgs
|
|
2444
2553
|
});
|
|
2445
|
-
const wrappedBrowser = {
|
|
2554
|
+
const wrappedBrowser = withAsyncDispose({
|
|
2446
2555
|
close: async ()=>browser.close(),
|
|
2447
2556
|
newContext: async ({ providerOptions: contextProviderOptions, viewport })=>{
|
|
2448
2557
|
const contextOptions = contextProviderOptions?.context;
|
|
@@ -2450,9 +2559,9 @@ async function launchPlaywrightBrowser({ browserName, headless, providerOptions
|
|
|
2450
2559
|
...contextOptions,
|
|
2451
2560
|
viewport
|
|
2452
2561
|
});
|
|
2453
|
-
return context;
|
|
2562
|
+
return wrapContext(context);
|
|
2454
2563
|
}
|
|
2455
|
-
};
|
|
2564
|
+
});
|
|
2456
2565
|
return {
|
|
2457
2566
|
browser: wrappedBrowser
|
|
2458
2567
|
};
|
|
@@ -2637,101 +2746,7 @@ const loadSourceMapWithCache = async ({ jsUrl, cache, force = false, origin, fet
|
|
|
2637
2746
|
return null;
|
|
2638
2747
|
}
|
|
2639
2748
|
};
|
|
2640
|
-
const
|
|
2641
|
-
'iPhoneSE',
|
|
2642
|
-
'iPhoneXR',
|
|
2643
|
-
'iPhone12Pro',
|
|
2644
|
-
'iPhone14ProMax',
|
|
2645
|
-
'Pixel7',
|
|
2646
|
-
'SamsungGalaxyS8Plus',
|
|
2647
|
-
'SamsungGalaxyS20Ultra',
|
|
2648
|
-
'iPadMini',
|
|
2649
|
-
'iPadAir',
|
|
2650
|
-
'iPadPro',
|
|
2651
|
-
'SurfacePro7',
|
|
2652
|
-
'SurfaceDuo',
|
|
2653
|
-
'GalaxyZFold5',
|
|
2654
|
-
'AsusZenbookFold',
|
|
2655
|
-
'SamsungGalaxyA51A71',
|
|
2656
|
-
'NestHub',
|
|
2657
|
-
'NestHubMax'
|
|
2658
|
-
];
|
|
2659
|
-
const BROWSER_VIEWPORT_PRESET_DIMENSIONS = {
|
|
2660
|
-
iPhoneSE: {
|
|
2661
|
-
width: 375,
|
|
2662
|
-
height: 667
|
|
2663
|
-
},
|
|
2664
|
-
iPhoneXR: {
|
|
2665
|
-
width: 414,
|
|
2666
|
-
height: 896
|
|
2667
|
-
},
|
|
2668
|
-
iPhone12Pro: {
|
|
2669
|
-
width: 390,
|
|
2670
|
-
height: 844
|
|
2671
|
-
},
|
|
2672
|
-
iPhone14ProMax: {
|
|
2673
|
-
width: 430,
|
|
2674
|
-
height: 932
|
|
2675
|
-
},
|
|
2676
|
-
Pixel7: {
|
|
2677
|
-
width: 412,
|
|
2678
|
-
height: 915
|
|
2679
|
-
},
|
|
2680
|
-
SamsungGalaxyS8Plus: {
|
|
2681
|
-
width: 360,
|
|
2682
|
-
height: 740
|
|
2683
|
-
},
|
|
2684
|
-
SamsungGalaxyS20Ultra: {
|
|
2685
|
-
width: 412,
|
|
2686
|
-
height: 915
|
|
2687
|
-
},
|
|
2688
|
-
iPadMini: {
|
|
2689
|
-
width: 768,
|
|
2690
|
-
height: 1024
|
|
2691
|
-
},
|
|
2692
|
-
iPadAir: {
|
|
2693
|
-
width: 820,
|
|
2694
|
-
height: 1180
|
|
2695
|
-
},
|
|
2696
|
-
iPadPro: {
|
|
2697
|
-
width: 1024,
|
|
2698
|
-
height: 1366
|
|
2699
|
-
},
|
|
2700
|
-
SurfacePro7: {
|
|
2701
|
-
width: 912,
|
|
2702
|
-
height: 1368
|
|
2703
|
-
},
|
|
2704
|
-
SurfaceDuo: {
|
|
2705
|
-
width: 540,
|
|
2706
|
-
height: 720
|
|
2707
|
-
},
|
|
2708
|
-
GalaxyZFold5: {
|
|
2709
|
-
width: 344,
|
|
2710
|
-
height: 882
|
|
2711
|
-
},
|
|
2712
|
-
AsusZenbookFold: {
|
|
2713
|
-
width: 853,
|
|
2714
|
-
height: 1280
|
|
2715
|
-
},
|
|
2716
|
-
SamsungGalaxyA51A71: {
|
|
2717
|
-
width: 412,
|
|
2718
|
-
height: 914
|
|
2719
|
-
},
|
|
2720
|
-
NestHub: {
|
|
2721
|
-
width: 1024,
|
|
2722
|
-
height: 600
|
|
2723
|
-
},
|
|
2724
|
-
NestHubMax: {
|
|
2725
|
-
width: 1280,
|
|
2726
|
-
height: 800
|
|
2727
|
-
}
|
|
2728
|
-
};
|
|
2729
|
-
const resolveBrowserViewportPreset = (presetId)=>{
|
|
2730
|
-
const size = BROWSER_VIEWPORT_PRESET_DIMENSIONS[presetId];
|
|
2731
|
-
return size ?? null;
|
|
2732
|
-
};
|
|
2733
|
-
const isTTY = ()=>Boolean(process.stdin.isTTY && !process.env.CI);
|
|
2734
|
-
const isBrowserWatchCliShortcutsEnabled = ()=>isTTY();
|
|
2749
|
+
const isBrowserWatchCliShortcutsEnabled = ()=>isTTY('stdin');
|
|
2735
2750
|
const getBrowserWatchCliShortcutsHintMessage = ()=>` ${color.dim('press')} ${color.bold('q')} ${color.dim('to quit')}\n`;
|
|
2736
2751
|
const logBrowserWatchReadyMessage = (enableCliShortcuts)=>{
|
|
2737
2752
|
logger.log(color.green(' Waiting for file changes...'));
|
|
@@ -2800,6 +2815,7 @@ var picomatch_default = /*#__PURE__*/ __webpack_require__.n(picomatch);
|
|
|
2800
2815
|
const { createRsbuild: createRsbuild, rspack: rspack } = rsbuild;
|
|
2801
2816
|
const hostController_dirname = dirname(fileURLToPath(import.meta.url));
|
|
2802
2817
|
const OPTIONS_PLACEHOLDER = '__RSTEST_OPTIONS_PLACEHOLDER__';
|
|
2818
|
+
const PER_FILE_TIMEOUT_BUFFER_MS = 30000;
|
|
2803
2819
|
let nextBrowserFilePid = 1000000000;
|
|
2804
2820
|
const serializeForInlineScript = (value)=>JSON.stringify(value).replace(/</g, '\\u003c').replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029');
|
|
2805
2821
|
const getBrowserProviderOptions = (project)=>{
|
|
@@ -3066,6 +3082,7 @@ const getRuntimeConfigFromProject = (project)=>{
|
|
|
3066
3082
|
return {
|
|
3067
3083
|
env: {
|
|
3068
3084
|
NODE_ENV: process.env.NODE_ENV,
|
|
3085
|
+
RSTEST: 'true',
|
|
3069
3086
|
...env
|
|
3070
3087
|
},
|
|
3071
3088
|
testNamePattern,
|
|
@@ -3293,12 +3310,12 @@ const createBrowserRuntime = async ({ context, manifestPath, manifestSource, tem
|
|
|
3293
3310
|
]));
|
|
3294
3311
|
const userPlugins = browserProjects.flatMap((project)=>project.normalizedConfig.plugins || []);
|
|
3295
3312
|
const browserLaunchOptions = ensureConsistentBrowserLaunchOptions(browserProjects);
|
|
3296
|
-
const browserRuntimePath = fileURLToPath(import.meta.resolve('@rstest/core/browser-runtime'));
|
|
3313
|
+
const browserRuntimePath = fileURLToPath(import.meta.resolve('@rstest/core/internal/browser-runtime'));
|
|
3297
3314
|
const rstestInternalAliases = {
|
|
3298
3315
|
'@rstest/browser-manifest': manifestPath,
|
|
3299
3316
|
'@rstest/core': resolveBrowserFile('client/public.ts'),
|
|
3300
3317
|
'@rstest/browser': resolveBrowserFile('browser.ts'),
|
|
3301
|
-
'@rstest/core/browser-runtime': browserRuntimePath,
|
|
3318
|
+
'@rstest/core/internal/browser-runtime': browserRuntimePath,
|
|
3302
3319
|
'@sinonjs/fake-timers': resolveBrowserFile('client/fakeTimersStub.ts')
|
|
3303
3320
|
};
|
|
3304
3321
|
const rsbuildInstance = await createRsbuild({
|
|
@@ -3340,6 +3357,7 @@ const createBrowserRuntime = async ({ context, manifestPath, manifestSource, tem
|
|
|
3340
3357
|
project
|
|
3341
3358
|
});
|
|
3342
3359
|
const setupFiles = Object.values(getSetupFiles(project.normalizedConfig.setupFiles, project.rootPath));
|
|
3360
|
+
const rstestEnvDefine = `globalThis[Symbol.for(${JSON.stringify(RSTEST_ENV_SYMBOL_KEY)})]`;
|
|
3343
3361
|
const merged = mergeEnvironmentConfig(config, {
|
|
3344
3362
|
...userRsbuildConfig,
|
|
3345
3363
|
performance: buildCache ? {
|
|
@@ -3352,8 +3370,8 @@ const createBrowserRuntime = async ({ context, manifestPath, manifestSource, tem
|
|
|
3352
3370
|
},
|
|
3353
3371
|
source: {
|
|
3354
3372
|
define: {
|
|
3355
|
-
'process.env':
|
|
3356
|
-
'import.meta.env':
|
|
3373
|
+
'process.env': rstestEnvDefine,
|
|
3374
|
+
'import.meta.env': rstestEnvDefine
|
|
3357
3375
|
}
|
|
3358
3376
|
},
|
|
3359
3377
|
output: {
|
|
@@ -3789,7 +3807,7 @@ const runBrowserController = async (context, options)=>{
|
|
|
3789
3807
|
runtimeConfig: serializableConfig(getRuntimeConfigFromProject(project)),
|
|
3790
3808
|
viewport: project.normalizedConfig.browser.viewport
|
|
3791
3809
|
}));
|
|
3792
|
-
const maxTestTimeoutForRpc = Math.max(...browserProjects.map((p)=>p.normalizedConfig.testTimeout ??
|
|
3810
|
+
const maxTestTimeoutForRpc = Math.max(...browserProjects.map((p)=>p.normalizedConfig.testTimeout ?? DEFAULT_TEST_TIMEOUT));
|
|
3793
3811
|
const hostOptions = {
|
|
3794
3812
|
rootPath: normalize(context.rootPath),
|
|
3795
3813
|
projects: projectRuntimeConfigs,
|
|
@@ -3832,7 +3850,7 @@ const runBrowserController = async (context, options)=>{
|
|
|
3832
3850
|
throw String(error);
|
|
3833
3851
|
}
|
|
3834
3852
|
};
|
|
3835
|
-
runtime.dispatchHandlers.set(
|
|
3853
|
+
runtime.dispatchHandlers.set(DISPATCH_NAMESPACE_BROWSER, async (dispatchRequest)=>{
|
|
3836
3854
|
const request = validateBrowserRpcRequest(dispatchRequest.args);
|
|
3837
3855
|
return dispatchBrowserRpcRequest({
|
|
3838
3856
|
request,
|
|
@@ -3976,7 +3994,7 @@ const runBrowserController = async (context, options)=>{
|
|
|
3976
3994
|
const pushTaskId = (taskIds, taskId)=>{
|
|
3977
3995
|
if (!taskIds.includes(taskId)) taskIds.push(taskId);
|
|
3978
3996
|
};
|
|
3979
|
-
const shouldEmitUserConsoleLog = (log)=>context.normalizedConfig.onConsoleLog?.(log.content) !== false;
|
|
3997
|
+
const shouldEmitUserConsoleLog = (log)=>context.normalizedConfig.onConsoleLog?.(log.content, log.type) !== false;
|
|
3980
3998
|
const emitUserConsoleLog = async (log)=>{
|
|
3981
3999
|
if (!shouldEmitUserConsoleLog(log)) return;
|
|
3982
4000
|
await Promise.all(context.reporters.map((reporter)=>reporter.onUserConsoleLog?.(log)));
|
|
@@ -4027,7 +4045,10 @@ const runBrowserController = async (context, options)=>{
|
|
|
4027
4045
|
case 'removeSnapshotFile':
|
|
4028
4046
|
return snapshotRpcMethods.removeSnapshotFile(request.args.filepath);
|
|
4029
4047
|
default:
|
|
4030
|
-
|
|
4048
|
+
{
|
|
4049
|
+
const _exhaustive = request;
|
|
4050
|
+
return _exhaustive;
|
|
4051
|
+
}
|
|
4031
4052
|
}
|
|
4032
4053
|
};
|
|
4033
4054
|
const createDispatchRouter = (options)=>createHostDispatchRouter({
|
|
@@ -4072,14 +4093,14 @@ const runBrowserController = async (context, options)=>{
|
|
|
4072
4093
|
const dispatchRouter = createDispatchRouter({
|
|
4073
4094
|
isRunTokenStale: (runToken)=>runLifecycle.isTokenStale(runToken),
|
|
4074
4095
|
onStale: (request)=>{
|
|
4075
|
-
if (request.namespace
|
|
4096
|
+
if ("runner" === request.namespace) logger.debug(`[Headless] Dropped stale message "${request.method}" for ${request.target?.testFile ?? 'unknown'}`);
|
|
4076
4097
|
}
|
|
4077
4098
|
});
|
|
4078
4099
|
const dispatchRunnerMessage = async (run, file, sessionId, message)=>{
|
|
4079
4100
|
const response = await dispatchRouter.dispatch({
|
|
4080
|
-
requestId: nextDispatchRequestId(
|
|
4101
|
+
requestId: nextDispatchRequestId("runner"),
|
|
4081
4102
|
runToken: run.token,
|
|
4082
|
-
namespace:
|
|
4103
|
+
namespace: "runner",
|
|
4083
4104
|
method: message.type,
|
|
4084
4105
|
args: 'payload' in message ? message.payload : void 0,
|
|
4085
4106
|
target: {
|
|
@@ -4113,7 +4134,7 @@ const runBrowserController = async (context, options)=>{
|
|
|
4113
4134
|
resolveDone = resolve;
|
|
4114
4135
|
});
|
|
4115
4136
|
const projectRuntime = projectRuntimeConfigs.find((project)=>project.name === file.projectName);
|
|
4116
|
-
const perFileTimeoutMs = (projectRuntime?.runtimeConfig.testTimeout ?? maxTestTimeoutForRpc) +
|
|
4137
|
+
const perFileTimeoutMs = (projectRuntime?.runtimeConfig.testTimeout ?? maxTestTimeoutForRpc) + PER_FILE_TIMEOUT_BUFFER_MS;
|
|
4117
4138
|
let timeoutId;
|
|
4118
4139
|
try {
|
|
4119
4140
|
page = await browserContext.newPage();
|
|
@@ -4436,7 +4457,7 @@ const runBrowserController = async (context, options)=>{
|
|
|
4436
4457
|
};
|
|
4437
4458
|
const getHeadedPerFileTimeoutMs = (file)=>{
|
|
4438
4459
|
const projectRuntime = projectRuntimeConfigs.find((project)=>project.name === file.projectName);
|
|
4439
|
-
return (projectRuntime?.runtimeConfig.testTimeout ?? maxTestTimeoutForRpc) +
|
|
4460
|
+
return (projectRuntime?.runtimeConfig.testTimeout ?? maxTestTimeoutForRpc) + PER_FILE_TIMEOUT_BUFFER_MS;
|
|
4440
4461
|
};
|
|
4441
4462
|
let containerContext;
|
|
4442
4463
|
let containerPage;
|
|
@@ -4744,7 +4765,7 @@ const listBrowserTests = async (context, options)=>{
|
|
|
4744
4765
|
runtimeConfig: serializableConfig(getRuntimeConfigFromProject(project)),
|
|
4745
4766
|
viewport: project.normalizedConfig.browser.viewport
|
|
4746
4767
|
}));
|
|
4747
|
-
const maxTestTimeoutForRpc = Math.max(...browserProjects.map((p)=>p.normalizedConfig.testTimeout ??
|
|
4768
|
+
const maxTestTimeoutForRpc = Math.max(...browserProjects.map((p)=>p.normalizedConfig.testTimeout ?? DEFAULT_TEST_TIMEOUT));
|
|
4748
4769
|
const hostOptions = {
|
|
4749
4770
|
rootPath: normalize(context.rootPath),
|
|
4750
4771
|
projects: projectRuntimeConfigs,
|
|
@@ -4850,43 +4871,10 @@ const listBrowserTests = async (context, options)=>{
|
|
|
4850
4871
|
close: cleanup
|
|
4851
4872
|
};
|
|
4852
4873
|
};
|
|
4853
|
-
const SUPPORTED_PROVIDERS = [
|
|
4854
|
-
'playwright'
|
|
4855
|
-
];
|
|
4856
|
-
const isPlainObject = (value)=>'[object Object]' === Object.prototype.toString.call(value);
|
|
4857
|
-
const validateViewport = (viewport)=>{
|
|
4858
|
-
if (null == viewport) return;
|
|
4859
|
-
if ('string' == typeof viewport) {
|
|
4860
|
-
const presetId = viewport.trim();
|
|
4861
|
-
if (!presetId) throw new Error('browser.viewport must be a non-empty preset id.');
|
|
4862
|
-
if (!resolveBrowserViewportPreset(presetId)) throw new Error(`browser.viewport must be a valid preset id. Received: ${viewport}`);
|
|
4863
|
-
return;
|
|
4864
|
-
}
|
|
4865
|
-
if (isPlainObject(viewport)) {
|
|
4866
|
-
const width = viewport.width;
|
|
4867
|
-
const height = viewport.height;
|
|
4868
|
-
if (!Number.isFinite(width) || width <= 0) throw new Error('browser.viewport.width must be a positive number.');
|
|
4869
|
-
if (!Number.isFinite(height) || height <= 0) throw new Error('browser.viewport.height must be a positive number.');
|
|
4870
|
-
return;
|
|
4871
|
-
}
|
|
4872
|
-
throw new Error('browser.viewport must be either a preset id or { width, height }.');
|
|
4873
|
-
};
|
|
4874
|
-
const validateBrowserConfig = (context)=>{
|
|
4875
|
-
for (const project of context.projects){
|
|
4876
|
-
const { browser, output } = project.normalizedConfig;
|
|
4877
|
-
if (browser.enabled) {
|
|
4878
|
-
if (!browser.provider) throw new Error('browser.provider is required when browser.enabled is true.');
|
|
4879
|
-
if (!SUPPORTED_PROVIDERS.includes(browser.provider)) throw new Error(`browser.provider must be one of: ${SUPPORTED_PROVIDERS.join(', ')}.`);
|
|
4880
|
-
validateViewport(browser.viewport);
|
|
4881
|
-
if (!isPlainObject(browser.providerOptions)) throw new Error('browser.providerOptions must be a plain object.');
|
|
4882
|
-
if (output?.bundleDependencies === false) throw new Error('output.bundleDependencies false is not supported in browser mode.');
|
|
4883
|
-
}
|
|
4884
|
-
}
|
|
4885
|
-
};
|
|
4886
4874
|
async function runBrowserTests(context, options) {
|
|
4887
4875
|
return runBrowserController(context, options);
|
|
4888
4876
|
}
|
|
4889
|
-
async function src_listBrowserTests(context) {
|
|
4890
|
-
return listBrowserTests(context);
|
|
4877
|
+
async function src_listBrowserTests(context, options) {
|
|
4878
|
+
return listBrowserTests(context, options);
|
|
4891
4879
|
}
|
|
4892
|
-
export {
|
|
4880
|
+
export { runBrowserTests, src_listBrowserTests as listBrowserTests, validateBrowserConfig };
|