@rstest/browser 0.8.1 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/entry.d.ts +1 -0
- package/dist/hostController.d.ts +5 -1
- package/dist/index.js +41 -10
- package/package.json +5 -5
- package/src/client/entry.ts +8 -0
- package/src/hostController.ts +61 -12
package/dist/client/entry.d.ts
CHANGED
package/dist/hostController.d.ts
CHANGED
|
@@ -14,4 +14,8 @@ export type ListBrowserTestsResult = {
|
|
|
14
14
|
* This function creates a headless browser runtime, loads test files,
|
|
15
15
|
* and collects their test structure (describe/test declarations).
|
|
16
16
|
*/
|
|
17
|
-
export declare const listBrowserTests: (context: Rstest
|
|
17
|
+
export declare const listBrowserTests: (context: Rstest, options?: {
|
|
18
|
+
shardedEntries?: Map<string, {
|
|
19
|
+
entries: Record<string, string>;
|
|
20
|
+
}>;
|
|
21
|
+
}) => Promise<ListBrowserTestsResult>;
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { __webpack_require__ } from "./rslib-runtime.js";
|
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import promises from "node:fs/promises";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { TEMP_RSTEST_OUTPUT_DIR, color, getSetupFiles, getTestEntries, isDebug, logger, rsbuild, serializableConfig } from "@rstest/core/browser";
|
|
5
|
+
import { TEMP_RSTEST_OUTPUT_DIR, color, getSetupFiles, getTestEntries, isDebug, loadCoverageProvider, logger, rsbuild, serializableConfig } from "@rstest/core/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";
|
|
@@ -1966,6 +1966,7 @@ const createBrowserRuntime = async ({ context, manifestPath, manifestSource, tem
|
|
|
1966
1966
|
const firstProject = browserProjects[0];
|
|
1967
1967
|
const userPlugins = firstProject?.normalizedConfig.plugins || [];
|
|
1968
1968
|
const userRsbuildConfig = firstProject?.normalizedConfig ?? {};
|
|
1969
|
+
const browserConfig = firstProject?.normalizedConfig.browser ?? context.normalizedConfig.browser;
|
|
1969
1970
|
const browserRuntimePath = fileURLToPath(import.meta.resolve('@rstest/core/browser-runtime'));
|
|
1970
1971
|
const rstestInternalAliases = {
|
|
1971
1972
|
'@rstest/browser-manifest': manifestPath,
|
|
@@ -1981,8 +1982,8 @@ const createBrowserRuntime = async ({ context, manifestPath, manifestSource, tem
|
|
|
1981
1982
|
plugins: userPlugins,
|
|
1982
1983
|
server: {
|
|
1983
1984
|
printUrls: false,
|
|
1984
|
-
port:
|
|
1985
|
-
strictPort:
|
|
1985
|
+
port: browserConfig.port ?? 4000,
|
|
1986
|
+
strictPort: browserConfig.strictPort
|
|
1986
1987
|
},
|
|
1987
1988
|
dev: {
|
|
1988
1989
|
client: {
|
|
@@ -1990,7 +1991,7 @@ const createBrowserRuntime = async ({ context, manifestPath, manifestSource, tem
|
|
|
1990
1991
|
}
|
|
1991
1992
|
},
|
|
1992
1993
|
environments: {
|
|
1993
|
-
web: {}
|
|
1994
|
+
[firstProject?.environmentName || 'web']: {}
|
|
1994
1995
|
}
|
|
1995
1996
|
}
|
|
1996
1997
|
});
|
|
@@ -2067,6 +2068,13 @@ const createBrowserRuntime = async ({ context, manifestPath, manifestSource, tem
|
|
|
2067
2068
|
}
|
|
2068
2069
|
}
|
|
2069
2070
|
]);
|
|
2071
|
+
const coverage = firstProject?.normalizedConfig.coverage;
|
|
2072
|
+
if (coverage?.enabled && 'list' !== context.command) {
|
|
2073
|
+
const { pluginCoverage } = await loadCoverageProvider(coverage, context.rootPath);
|
|
2074
|
+
rsbuildInstance.addPlugins([
|
|
2075
|
+
pluginCoverage(coverage)
|
|
2076
|
+
]);
|
|
2077
|
+
}
|
|
2070
2078
|
const devServer = await rsbuildInstance.createDevServer({
|
|
2071
2079
|
getPortSilently: true
|
|
2072
2080
|
});
|
|
@@ -2177,7 +2185,7 @@ const createBrowserRuntime = async ({ context, manifestPath, manifestSource, tem
|
|
|
2177
2185
|
const wsPort = wss.address().port;
|
|
2178
2186
|
logger.debug(`[Browser UI] WebSocket server started on port ${wsPort}`);
|
|
2179
2187
|
let browserLauncher;
|
|
2180
|
-
const browserName =
|
|
2188
|
+
const browserName = browserConfig.browser;
|
|
2181
2189
|
try {
|
|
2182
2190
|
const playwright = await import("playwright");
|
|
2183
2191
|
browserLauncher = playwright[browserName];
|
|
@@ -2189,7 +2197,7 @@ const createBrowserRuntime = async ({ context, manifestPath, manifestSource, tem
|
|
|
2189
2197
|
let browser;
|
|
2190
2198
|
try {
|
|
2191
2199
|
browser = await browserLauncher.launch({
|
|
2192
|
-
headless: forceHeadless ??
|
|
2200
|
+
headless: forceHeadless ?? browserConfig.headless,
|
|
2193
2201
|
args: 'chromium' === browserName ? [
|
|
2194
2202
|
'--disable-popup-blocking',
|
|
2195
2203
|
'--no-first-run',
|
|
@@ -2214,6 +2222,25 @@ const createBrowserRuntime = async ({ context, manifestPath, manifestSource, tem
|
|
|
2214
2222
|
wss
|
|
2215
2223
|
};
|
|
2216
2224
|
};
|
|
2225
|
+
async function resolveProjectEntries(context, shardedEntries) {
|
|
2226
|
+
if (shardedEntries) {
|
|
2227
|
+
const browserProjects = getBrowserProjects(context);
|
|
2228
|
+
const projectEntries = [];
|
|
2229
|
+
for (const project of browserProjects){
|
|
2230
|
+
const entryInfo = shardedEntries.get(project.environmentName);
|
|
2231
|
+
if (entryInfo && Object.keys(entryInfo.entries).length > 0) {
|
|
2232
|
+
const setup = getSetupFiles(project.normalizedConfig.setupFiles, project.rootPath);
|
|
2233
|
+
projectEntries.push({
|
|
2234
|
+
project,
|
|
2235
|
+
setupFiles: Object.values(setup),
|
|
2236
|
+
testFiles: Object.values(entryInfo.entries)
|
|
2237
|
+
});
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
return projectEntries;
|
|
2241
|
+
}
|
|
2242
|
+
return collectProjectEntries(context);
|
|
2243
|
+
}
|
|
2217
2244
|
const runBrowserController = async (context, options)=>{
|
|
2218
2245
|
const { skipOnTestRunEnd = false } = options ?? {};
|
|
2219
2246
|
const buildStart = Date.now();
|
|
@@ -2235,11 +2262,15 @@ const runBrowserController = async (context, options)=>{
|
|
|
2235
2262
|
ensureProcessExitCode(1);
|
|
2236
2263
|
return;
|
|
2237
2264
|
}
|
|
2238
|
-
const projectEntries = await
|
|
2265
|
+
const projectEntries = await resolveProjectEntries(context, options?.shardedEntries);
|
|
2239
2266
|
const totalTests = projectEntries.reduce((total, item)=>total + item.testFiles.length, 0);
|
|
2240
2267
|
if (0 === totalTests) {
|
|
2241
2268
|
const code = context.normalizedConfig.passWithNoTests ? 0 : 1;
|
|
2242
|
-
if (!skipOnTestRunEnd)
|
|
2269
|
+
if (!skipOnTestRunEnd) {
|
|
2270
|
+
const message = `No test files found, exiting with code ${code}.`;
|
|
2271
|
+
if (0 === code) logger.log(color.yellow(message));
|
|
2272
|
+
else logger.error(color.red(message));
|
|
2273
|
+
}
|
|
2243
2274
|
if (0 !== code) ensureProcessExitCode(code);
|
|
2244
2275
|
return;
|
|
2245
2276
|
}
|
|
@@ -2499,8 +2530,8 @@ const runBrowserController = async (context, options)=>{
|
|
|
2499
2530
|
}
|
|
2500
2531
|
return result;
|
|
2501
2532
|
};
|
|
2502
|
-
const listBrowserTests = async (context)=>{
|
|
2503
|
-
const projectEntries = await
|
|
2533
|
+
const listBrowserTests = async (context, options)=>{
|
|
2534
|
+
const projectEntries = await resolveProjectEntries(context, options?.shardedEntries);
|
|
2504
2535
|
const totalTests = projectEntries.reduce((total, item)=>total + item.testFiles.length, 0);
|
|
2505
2536
|
if (0 === totalTests) return {
|
|
2506
2537
|
list: [],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rstest/browser",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Browser mode support for Rstest testing framework.",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/web-infra-dev/rstest/issues"
|
|
@@ -52,13 +52,13 @@
|
|
|
52
52
|
"picocolors": "^1.1.1",
|
|
53
53
|
"picomatch": "^4.0.3",
|
|
54
54
|
"playwright": "^1.49.1",
|
|
55
|
-
"@rstest/
|
|
56
|
-
"@rstest/
|
|
57
|
-
"@rstest/
|
|
55
|
+
"@rstest/core": "0.8.2",
|
|
56
|
+
"@rstest/tsconfig": "0.0.1",
|
|
57
|
+
"@rstest/browser-ui": "0.0.0"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"playwright": "^1.49.1",
|
|
61
|
-
"@rstest/core": "^0.8.
|
|
61
|
+
"@rstest/core": "^0.8.2"
|
|
62
62
|
},
|
|
63
63
|
"peerDependenciesMeta": {
|
|
64
64
|
"playwright": {
|
package/src/client/entry.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
projectTestContexts,
|
|
8
8
|
} from '@rstest/browser-manifest';
|
|
9
9
|
import type {
|
|
10
|
+
CoverageMapData,
|
|
10
11
|
RunnerHooks,
|
|
11
12
|
RuntimeConfig,
|
|
12
13
|
WorkerState,
|
|
@@ -35,6 +36,8 @@ declare global {
|
|
|
35
36
|
__RSTEST_BROWSER_OPTIONS__?: BrowserHostConfig;
|
|
36
37
|
__rstest_dispatch__?: (message: BrowserClientMessage) => void;
|
|
37
38
|
}
|
|
39
|
+
// eslint-disable-next-line no-var
|
|
40
|
+
var __coverage__: Record<string, unknown> | undefined;
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
/**
|
|
@@ -589,6 +592,11 @@ const run = async () => {
|
|
|
589
592
|
runtime.api,
|
|
590
593
|
);
|
|
591
594
|
|
|
595
|
+
// Collect coverage data from global __coverage__ object
|
|
596
|
+
if (globalThis.__coverage__) {
|
|
597
|
+
result.coverage = globalThis.__coverage__ as CoverageMapData;
|
|
598
|
+
}
|
|
599
|
+
|
|
592
600
|
send({
|
|
593
601
|
type: 'file-complete',
|
|
594
602
|
payload: result,
|
package/src/hostController.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
getTestEntries,
|
|
13
13
|
isDebug,
|
|
14
14
|
type ListCommandResult,
|
|
15
|
+
loadCoverageProvider,
|
|
15
16
|
logger,
|
|
16
17
|
type ProjectContext,
|
|
17
18
|
type Reporter,
|
|
@@ -817,6 +818,8 @@ const createBrowserRuntime = async ({
|
|
|
817
818
|
const firstProject = browserProjects[0];
|
|
818
819
|
const userPlugins = firstProject?.normalizedConfig.plugins || [];
|
|
819
820
|
const userRsbuildConfig = firstProject?.normalizedConfig ?? {};
|
|
821
|
+
const browserConfig =
|
|
822
|
+
firstProject?.normalizedConfig.browser ?? context.normalizedConfig.browser;
|
|
820
823
|
|
|
821
824
|
// Rstest internal aliases that must not be overridden by user config
|
|
822
825
|
const browserRuntimePath = fileURLToPath(
|
|
@@ -841,8 +844,8 @@ const createBrowserRuntime = async ({
|
|
|
841
844
|
plugins: userPlugins,
|
|
842
845
|
server: {
|
|
843
846
|
printUrls: false,
|
|
844
|
-
port:
|
|
845
|
-
strictPort:
|
|
847
|
+
port: browserConfig.port ?? 4000,
|
|
848
|
+
strictPort: browserConfig.strictPort,
|
|
846
849
|
},
|
|
847
850
|
dev: {
|
|
848
851
|
client: {
|
|
@@ -850,7 +853,7 @@ const createBrowserRuntime = async ({
|
|
|
850
853
|
},
|
|
851
854
|
},
|
|
852
855
|
environments: {
|
|
853
|
-
web: {},
|
|
856
|
+
[firstProject?.environmentName || 'web']: {},
|
|
854
857
|
},
|
|
855
858
|
},
|
|
856
859
|
});
|
|
@@ -970,6 +973,16 @@ const createBrowserRuntime = async ({
|
|
|
970
973
|
]);
|
|
971
974
|
}
|
|
972
975
|
|
|
976
|
+
// Register coverage plugin for browser mode
|
|
977
|
+
const coverage = firstProject?.normalizedConfig.coverage;
|
|
978
|
+
if (coverage?.enabled && context.command !== 'list') {
|
|
979
|
+
const { pluginCoverage } = await loadCoverageProvider(
|
|
980
|
+
coverage,
|
|
981
|
+
context.rootPath,
|
|
982
|
+
);
|
|
983
|
+
rsbuildInstance.addPlugins([pluginCoverage(coverage)]);
|
|
984
|
+
}
|
|
985
|
+
|
|
973
986
|
const devServer = await rsbuildInstance.createDevServer({
|
|
974
987
|
getPortSilently: true,
|
|
975
988
|
});
|
|
@@ -1134,7 +1147,7 @@ const createBrowserRuntime = async ({
|
|
|
1134
1147
|
logger.debug(`[Browser UI] WebSocket server started on port ${wsPort}`);
|
|
1135
1148
|
|
|
1136
1149
|
let browserLauncher: BrowserType;
|
|
1137
|
-
const browserName =
|
|
1150
|
+
const browserName = browserConfig.browser;
|
|
1138
1151
|
try {
|
|
1139
1152
|
const playwright = await import('playwright');
|
|
1140
1153
|
browserLauncher = playwright[browserName];
|
|
@@ -1147,7 +1160,7 @@ const createBrowserRuntime = async ({
|
|
|
1147
1160
|
let browser: BrowserInstance;
|
|
1148
1161
|
try {
|
|
1149
1162
|
browser = await browserLauncher.launch({
|
|
1150
|
-
headless: forceHeadless ??
|
|
1163
|
+
headless: forceHeadless ?? browserConfig.headless,
|
|
1151
1164
|
// Chromium-specific args (ignored by other browsers)
|
|
1152
1165
|
args:
|
|
1153
1166
|
browserName === 'chromium'
|
|
@@ -1178,6 +1191,32 @@ const createBrowserRuntime = async ({
|
|
|
1178
1191
|
};
|
|
1179
1192
|
};
|
|
1180
1193
|
|
|
1194
|
+
async function resolveProjectEntries(
|
|
1195
|
+
context: Rstest,
|
|
1196
|
+
shardedEntries?: Map<string, { entries: Record<string, string> }>,
|
|
1197
|
+
): Promise<BrowserProjectEntries[]> {
|
|
1198
|
+
if (shardedEntries) {
|
|
1199
|
+
const browserProjects = getBrowserProjects(context);
|
|
1200
|
+
const projectEntries: BrowserProjectEntries[] = [];
|
|
1201
|
+
for (const project of browserProjects) {
|
|
1202
|
+
const entryInfo = shardedEntries.get(project.environmentName);
|
|
1203
|
+
if (entryInfo && Object.keys(entryInfo.entries).length > 0) {
|
|
1204
|
+
const setup = getSetupFiles(
|
|
1205
|
+
project.normalizedConfig.setupFiles,
|
|
1206
|
+
project.rootPath,
|
|
1207
|
+
);
|
|
1208
|
+
projectEntries.push({
|
|
1209
|
+
project,
|
|
1210
|
+
setupFiles: Object.values(setup),
|
|
1211
|
+
testFiles: Object.values(entryInfo.entries),
|
|
1212
|
+
});
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
return projectEntries;
|
|
1216
|
+
}
|
|
1217
|
+
return collectProjectEntries(context);
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1181
1220
|
// ============================================================================
|
|
1182
1221
|
// Main Entry Point
|
|
1183
1222
|
// ============================================================================
|
|
@@ -1219,7 +1258,10 @@ export const runBrowserController = async (
|
|
|
1219
1258
|
}
|
|
1220
1259
|
}
|
|
1221
1260
|
|
|
1222
|
-
const projectEntries = await
|
|
1261
|
+
const projectEntries = await resolveProjectEntries(
|
|
1262
|
+
context,
|
|
1263
|
+
options?.shardedEntries,
|
|
1264
|
+
);
|
|
1223
1265
|
const totalTests = projectEntries.reduce(
|
|
1224
1266
|
(total, item) => total + item.testFiles.length,
|
|
1225
1267
|
0,
|
|
@@ -1228,11 +1270,12 @@ export const runBrowserController = async (
|
|
|
1228
1270
|
if (totalTests === 0) {
|
|
1229
1271
|
const code = context.normalizedConfig.passWithNoTests ? 0 : 1;
|
|
1230
1272
|
if (!skipOnTestRunEnd) {
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1273
|
+
const message = `No test files found, exiting with code ${code}.`;
|
|
1274
|
+
if (code === 0) {
|
|
1275
|
+
logger.log(color.yellow(message));
|
|
1276
|
+
} else {
|
|
1277
|
+
logger.error(color.red(message));
|
|
1278
|
+
}
|
|
1236
1279
|
}
|
|
1237
1280
|
|
|
1238
1281
|
if (code !== 0) {
|
|
@@ -1700,8 +1743,14 @@ export type ListBrowserTestsResult = {
|
|
|
1700
1743
|
*/
|
|
1701
1744
|
export const listBrowserTests = async (
|
|
1702
1745
|
context: Rstest,
|
|
1746
|
+
options?: {
|
|
1747
|
+
shardedEntries?: Map<string, { entries: Record<string, string> }>;
|
|
1748
|
+
},
|
|
1703
1749
|
): Promise<ListBrowserTestsResult> => {
|
|
1704
|
-
const projectEntries = await
|
|
1750
|
+
const projectEntries = await resolveProjectEntries(
|
|
1751
|
+
context,
|
|
1752
|
+
options?.shardedEntries,
|
|
1753
|
+
);
|
|
1705
1754
|
const totalTests = projectEntries.reduce(
|
|
1706
1755
|
(total, item) => total + item.testFiles.length,
|
|
1707
1756
|
0,
|