@rpcbase/test 0.384.0 → 0.386.0

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 (39) hide show
  1. package/dist/clearDatabase.js +10 -12
  2. package/dist/clearDatabase.js.map +1 -1
  3. package/dist/cli.js +439 -556
  4. package/dist/cli.js.map +1 -1
  5. package/dist/coverage/collect.js +63 -101
  6. package/dist/coverage/collect.js.map +1 -1
  7. package/dist/coverage/config-loader.js +179 -229
  8. package/dist/coverage/config-loader.js.map +1 -1
  9. package/dist/coverage/config.js +76 -100
  10. package/dist/coverage/config.js.map +1 -1
  11. package/dist/coverage/console-text-report.js +175 -220
  12. package/dist/coverage/console-text-report.js.map +1 -1
  13. package/dist/coverage/files.js +44 -57
  14. package/dist/coverage/files.js.map +1 -1
  15. package/dist/coverage/fixtures.js +27 -38
  16. package/dist/coverage/fixtures.js.map +1 -1
  17. package/dist/coverage/global-setup.js +15 -18
  18. package/dist/coverage/global-setup.js.map +1 -1
  19. package/dist/coverage/index.js +38 -55
  20. package/dist/coverage/index.js.map +1 -1
  21. package/dist/coverage/report.js +340 -465
  22. package/dist/coverage/report.js.map +1 -1
  23. package/dist/coverage/reporter.js +47 -60
  24. package/dist/coverage/reporter.js.map +1 -1
  25. package/dist/coverage/v8-tracker.js +114 -146
  26. package/dist/coverage/v8-tracker.js.map +1 -1
  27. package/dist/index.js +46 -75
  28. package/dist/index.js.map +1 -1
  29. package/dist/runners/playwright.js +440 -564
  30. package/dist/runners/playwright.js.map +1 -1
  31. package/dist/runners/process.js +124 -183
  32. package/dist/runners/process.js.map +1 -1
  33. package/dist/runners/vitest.js +123 -170
  34. package/dist/runners/vitest.js.map +1 -1
  35. package/dist/serverCoverage.js +28 -42
  36. package/dist/serverCoverage.js.map +1 -1
  37. package/dist/vitest.config.js +176 -228
  38. package/dist/vitest.config.js.map +1 -1
  39. package/package.json +1 -1
@@ -1,615 +1,491 @@
1
- import fs from "node:fs";
2
- import fs$1 from "node:fs/promises";
1
+ import { spawnAndCaptureStdout, spawnWithLogs, withRegisterShim } from "./process.js";
2
+ import fs from "node:fs/promises";
3
+ import fsSync from "node:fs";
3
4
  import path from "node:path";
4
5
  import { createRequire } from "node:module";
5
6
  import { fileURLToPath } from "node:url";
6
- import { withRegisterShim, spawnWithLogs, spawnAndCaptureStdout } from "./process.js";
7
- const require$1 = createRequire(import.meta.url);
8
- const moduleDir = path.dirname(fileURLToPath(import.meta.url));
9
- const COMBINED_COVERAGE_ENV_VAR = "RB_TEST_COMBINED_COVERAGE";
10
- const PLAYWRIGHT_RESULTS_FILE = path.join(process.cwd(), "build", "playwright", "results.json");
11
- const PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE = /* @__PURE__ */ new Set(["--browser", "--config", "-c", "--grep", "-g", "--grep-invert", "--global-timeout", "--max-failures", "--output", "--project", "--repeat-each", "--reporter", "--retries", "--shard", "--timeout", "--trace", "--tsconfig", "--workers", "-j"]);
12
- const PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE = /* @__PURE__ */ new Set(["--only-changed", "--update-snapshots", "-u"]);
13
- const PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_WORKER_RETRY = /* @__PURE__ */ new Set(["--last-failed", "--only-changed", "--output", "--retries", "--pass-with-no-tests", "--reporter", "--workers", "-j"]);
14
- const PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_INITIAL_FRESH_RUN = /* @__PURE__ */ new Set(["--retries"]);
15
- const PLAYWRIGHT_RETRY_LOG_LABEL_MAX_LENGTH = 20;
16
- async function runPlaywright(userArgs, {
17
- disableCoverage = false
18
- } = {}) {
19
- const configPath = fs.existsSync(path.join(process.cwd(), "playwright.config.ts")) ? path.join(process.cwd(), "playwright.config.ts") : path.join(moduleDir, "..", "playwright.config.ts");
20
- const hasCustomConfig = userArgs.some((arg) => {
21
- if (arg === "--config" || arg === "-c") {
22
- return true;
23
- }
24
- return arg.startsWith("--config=");
25
- });
26
- ensureJsxRuntimeShim(process.cwd());
27
- const launcher = resolvePlaywrightLauncher();
28
- const env = withRegisterShim(process.env);
29
- env[COMBINED_COVERAGE_ENV_VAR] = "1";
30
- if (disableCoverage) {
31
- env.RB_DISABLE_COVERAGE = "1";
32
- }
33
- const runtimeSettings = await resolveFreshWorkerRetrySettings({
34
- launcher,
35
- configPath,
36
- hasCustomConfig,
37
- userArgs,
38
- env
39
- });
40
- const configuredRetries = runtimeSettings.retries;
41
- const retryConcurrency = Math.max(1, runtimeSettings.workers ?? 1);
42
- const resultsMtimeBeforeRun = getFileMtimeMs(PLAYWRIGHT_RESULTS_FILE);
43
- const initialRunArgs = buildPlaywrightInitialFreshWorkerArgs(userArgs);
44
- const initialPlaywrightArgs = ["test"];
45
- if (!hasCustomConfig) {
46
- initialPlaywrightArgs.push("--config", configPath);
47
- }
48
- initialPlaywrightArgs.push(...initialRunArgs);
49
- try {
50
- await runPlaywrightOnce({
51
- launcher,
52
- args: initialPlaywrightArgs,
53
- env
54
- });
55
- return;
56
- } catch (error) {
57
- const summary = await readPlaywrightReportSummary(PLAYWRIGHT_RESULTS_FILE, resultsMtimeBeforeRun);
58
- if (!summary || configuredRetries <= 0 || summary.failedFiles.length === 0) {
59
- throw error;
60
- }
61
- let lastError = error;
62
- let failedFiles = summary.failedFiles;
63
- const maxAttempts = configuredRetries;
64
- for (let attempt = 1; attempt <= maxAttempts && failedFiles.length > 0; attempt += 1) {
65
- const activeRetryWorkers = Math.max(1, Math.min(retryConcurrency, failedFiles.length));
66
- console.warn(`[rb-test] Retrying ${failedFiles.length} failed Playwright file(s) with fresh workers (${attempt}/${maxAttempts}, up to ${activeRetryWorkers} in parallel)`);
67
- const retryResults = await runPlaywrightRetryAttempt({
68
- launcher,
69
- userArgs,
70
- failedFiles,
71
- retryConcurrency: activeRetryWorkers,
72
- configPath,
73
- hasCustomConfig,
74
- env,
75
- attempt
76
- });
77
- if (retryResults.lastError) {
78
- lastError = retryResults.lastError;
79
- }
80
- failedFiles = retryResults.failedFiles;
81
- }
82
- if (failedFiles.length === 0) {
83
- return;
84
- }
85
- throw lastError;
86
- }
87
- }
88
- function runPlaywrightOnce({
89
- launcher,
90
- args,
91
- env,
92
- outputMode = "chunk",
93
- bufferOutput = false,
94
- successMessage,
95
- failureMessage,
96
- stdoutLinePrefix,
97
- stderrLinePrefix
98
- }) {
99
- return spawnWithLogs({
100
- name: "Playwright",
101
- launcher,
102
- args,
103
- env,
104
- outputMode,
105
- bufferOutput,
106
- successMessage: successMessage === void 0 ? "Playwright suite passed!" : successMessage ?? void 0,
107
- failureMessage: failureMessage === void 0 ? "Playwright failed" : failureMessage ?? void 0,
108
- stdoutLinePrefix,
109
- stderrLinePrefix
110
- });
7
+ //#region src/runners/playwright.ts
8
+ var require = createRequire(import.meta.url);
9
+ var moduleDir = path.dirname(fileURLToPath(import.meta.url));
10
+ var COMBINED_COVERAGE_ENV_VAR = "RB_TEST_COMBINED_COVERAGE";
11
+ var PLAYWRIGHT_RESULTS_FILE = path.join(process.cwd(), "build", "playwright", "results.json");
12
+ var PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE = /* @__PURE__ */ new Set([
13
+ "--browser",
14
+ "--config",
15
+ "-c",
16
+ "--grep",
17
+ "-g",
18
+ "--grep-invert",
19
+ "--global-timeout",
20
+ "--max-failures",
21
+ "--output",
22
+ "--project",
23
+ "--repeat-each",
24
+ "--reporter",
25
+ "--retries",
26
+ "--shard",
27
+ "--timeout",
28
+ "--trace",
29
+ "--tsconfig",
30
+ "--workers",
31
+ "-j"
32
+ ]);
33
+ var PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE = /* @__PURE__ */ new Set([
34
+ "--only-changed",
35
+ "--update-snapshots",
36
+ "-u"
37
+ ]);
38
+ var PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_WORKER_RETRY = /* @__PURE__ */ new Set([
39
+ "--last-failed",
40
+ "--only-changed",
41
+ "--output",
42
+ "--retries",
43
+ "--pass-with-no-tests",
44
+ "--reporter",
45
+ "--workers",
46
+ "-j"
47
+ ]);
48
+ var PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_INITIAL_FRESH_RUN = /* @__PURE__ */ new Set(["--retries"]);
49
+ var PLAYWRIGHT_RETRY_LOG_LABEL_MAX_LENGTH = 20;
50
+ async function runPlaywright(userArgs, { disableCoverage = false } = {}) {
51
+ const configPath = fsSync.existsSync(path.join(process.cwd(), "playwright.config.ts")) ? path.join(process.cwd(), "playwright.config.ts") : path.join(moduleDir, "..", "playwright.config.ts");
52
+ const hasCustomConfig = userArgs.some((arg) => {
53
+ if (arg === "--config" || arg === "-c") return true;
54
+ return arg.startsWith("--config=");
55
+ });
56
+ ensureJsxRuntimeShim(process.cwd());
57
+ const launcher = resolvePlaywrightLauncher();
58
+ const env = withRegisterShim(process.env);
59
+ env[COMBINED_COVERAGE_ENV_VAR] = "1";
60
+ if (disableCoverage) env.RB_DISABLE_COVERAGE = "1";
61
+ const runtimeSettings = await resolveFreshWorkerRetrySettings({
62
+ launcher,
63
+ configPath,
64
+ hasCustomConfig,
65
+ userArgs,
66
+ env
67
+ });
68
+ const configuredRetries = runtimeSettings.retries;
69
+ const retryConcurrency = Math.max(1, runtimeSettings.workers ?? 1);
70
+ const resultsMtimeBeforeRun = getFileMtimeMs(PLAYWRIGHT_RESULTS_FILE);
71
+ const initialRunArgs = buildPlaywrightInitialFreshWorkerArgs(userArgs);
72
+ const initialPlaywrightArgs = ["test"];
73
+ if (!hasCustomConfig) initialPlaywrightArgs.push("--config", configPath);
74
+ initialPlaywrightArgs.push(...initialRunArgs);
75
+ try {
76
+ await runPlaywrightOnce({
77
+ launcher,
78
+ args: initialPlaywrightArgs,
79
+ env
80
+ });
81
+ return;
82
+ } catch (error) {
83
+ const summary = await readPlaywrightReportSummary(PLAYWRIGHT_RESULTS_FILE, resultsMtimeBeforeRun);
84
+ if (!summary || configuredRetries <= 0 || summary.failedFiles.length === 0) throw error;
85
+ let lastError = error;
86
+ let failedFiles = summary.failedFiles;
87
+ const maxAttempts = configuredRetries;
88
+ for (let attempt = 1; attempt <= maxAttempts && failedFiles.length > 0; attempt += 1) {
89
+ const activeRetryWorkers = Math.max(1, Math.min(retryConcurrency, failedFiles.length));
90
+ console.warn(`[rb-test] Retrying ${failedFiles.length} failed Playwright file(s) with fresh workers (${attempt}/${maxAttempts}, up to ${activeRetryWorkers} in parallel)`);
91
+ const retryResults = await runPlaywrightRetryAttempt({
92
+ launcher,
93
+ userArgs,
94
+ failedFiles,
95
+ retryConcurrency: activeRetryWorkers,
96
+ configPath,
97
+ hasCustomConfig,
98
+ env,
99
+ attempt
100
+ });
101
+ if (retryResults.lastError) lastError = retryResults.lastError;
102
+ failedFiles = retryResults.failedFiles;
103
+ }
104
+ if (failedFiles.length === 0) return;
105
+ throw lastError;
106
+ }
107
+ }
108
+ function runPlaywrightOnce({ launcher, args, env, outputMode = "chunk", bufferOutput = false, successMessage, failureMessage, stdoutLinePrefix, stderrLinePrefix }) {
109
+ return spawnWithLogs({
110
+ name: "Playwright",
111
+ launcher,
112
+ args,
113
+ env,
114
+ outputMode,
115
+ bufferOutput,
116
+ successMessage: successMessage === void 0 ? "Playwright suite passed!" : successMessage ?? void 0,
117
+ failureMessage: failureMessage === void 0 ? "Playwright failed" : failureMessage ?? void 0,
118
+ stdoutLinePrefix,
119
+ stderrLinePrefix
120
+ });
111
121
  }
112
122
  function resolvePlaywrightLauncher() {
113
- const cliPath = resolveCliPath();
114
- if (cliPath) {
115
- return {
116
- command: process.execPath,
117
- args: [cliPath]
118
- };
119
- }
120
- const localBin = path.resolve(process.cwd(), "node_modules/.bin/playwright");
121
- if (fs.existsSync(localBin)) {
122
- return {
123
- command: localBin,
124
- args: []
125
- };
126
- }
127
- return {
128
- command: "playwright",
129
- args: []
130
- };
123
+ const cliPath = resolveCliPath();
124
+ if (cliPath) return {
125
+ command: process.execPath,
126
+ args: [cliPath]
127
+ };
128
+ const localBin = path.resolve(process.cwd(), "node_modules/.bin/playwright");
129
+ if (fsSync.existsSync(localBin)) return {
130
+ command: localBin,
131
+ args: []
132
+ };
133
+ return {
134
+ command: "playwright",
135
+ args: []
136
+ };
131
137
  }
132
138
  function resolveCliPath() {
133
- const searchRoots = [process.cwd(), moduleDir];
134
- for (const base of searchRoots) {
135
- try {
136
- const pkgPath = require$1.resolve("@playwright/test/package.json", {
137
- paths: [base]
138
- });
139
- const cliPath = path.join(path.dirname(pkgPath), "cli.js");
140
- if (fs.existsSync(cliPath)) {
141
- return cliPath;
142
- }
143
- } catch (_error) {
144
- }
145
- }
146
- return null;
139
+ const searchRoots = [process.cwd(), moduleDir];
140
+ for (const base of searchRoots) try {
141
+ const pkgPath = require.resolve("@playwright/test/package.json", { paths: [base] });
142
+ const cliPath = path.join(path.dirname(pkgPath), "cli.js");
143
+ if (fsSync.existsSync(cliPath)) return cliPath;
144
+ } catch (_error) {}
145
+ return null;
147
146
  }
148
147
  function buildPlaywrightWorkerRetryArgs(userArgs, failedFiles, attempt) {
149
- const optionArgs = extractPlaywrightOptionArgs(userArgs);
150
- const sanitizedOptions = removePlaywrightOptions(optionArgs, PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_WORKER_RETRY);
151
- return [...sanitizedOptions, "--retries=0", "--workers=1", "--reporter=list", "--output", buildPlaywrightRetryOutputDir(attempt, failedFiles), ...failedFiles];
148
+ return [
149
+ ...removePlaywrightOptions(extractPlaywrightOptionArgs(userArgs), PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_WORKER_RETRY),
150
+ "--retries=0",
151
+ "--workers=1",
152
+ "--reporter=list",
153
+ "--output",
154
+ buildPlaywrightRetryOutputDir(attempt, failedFiles),
155
+ ...failedFiles
156
+ ];
152
157
  }
153
158
  function buildPlaywrightInitialFreshWorkerArgs(userArgs) {
154
- const optionArgs = extractPlaywrightOptionArgs(userArgs);
155
- const sanitizedOptions = removePlaywrightOptions(optionArgs, PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_INITIAL_FRESH_RUN);
156
- const positionalArgs = extractPlaywrightPositionalArgs(userArgs);
157
- return [...sanitizedOptions, "--retries=0", ...positionalArgs];
158
- }
159
- async function resolveFreshWorkerRetrySettings({
160
- launcher,
161
- configPath,
162
- hasCustomConfig,
163
- userArgs,
164
- env
165
- }) {
166
- const configuredSettings = await probeConfiguredPlaywrightSettings({
167
- launcher,
168
- configPath,
169
- hasCustomConfig,
170
- userArgs,
171
- env
172
- });
173
- return {
174
- retries: configuredSettings.retries ?? 0,
175
- workers: configuredSettings.workers
176
- };
177
- }
178
- async function probeConfiguredPlaywrightSettings({
179
- launcher,
180
- configPath,
181
- hasCustomConfig,
182
- userArgs,
183
- env
184
- }) {
185
- const probeArgs = ["test"];
186
- if (!hasCustomConfig) {
187
- probeArgs.push("--config", configPath);
188
- }
189
- probeArgs.push("--list", "--reporter=json", ...extractPlaywrightProjectArgs(userArgs));
190
- try {
191
- const stdout = await spawnAndCaptureStdout({
192
- name: "Playwright retries probe",
193
- launcher,
194
- args: probeArgs,
195
- env
196
- });
197
- const json = parseJsonObjectFromText(stdout);
198
- if (!json) {
199
- return {
200
- retries: null,
201
- workers: null
202
- };
203
- }
204
- return {
205
- retries: resolvePlaywrightRetriesFromReport(json),
206
- workers: resolvePlaywrightWorkersFromReport(json)
207
- };
208
- } catch (_error) {
209
- return {
210
- retries: null,
211
- workers: null
212
- };
213
- }
159
+ const sanitizedOptions = removePlaywrightOptions(extractPlaywrightOptionArgs(userArgs), PLAYWRIGHT_OPTIONS_TO_REMOVE_FOR_INITIAL_FRESH_RUN);
160
+ const positionalArgs = extractPlaywrightPositionalArgs(userArgs);
161
+ return [
162
+ ...sanitizedOptions,
163
+ "--retries=0",
164
+ ...positionalArgs
165
+ ];
166
+ }
167
+ async function resolveFreshWorkerRetrySettings({ launcher, configPath, hasCustomConfig, userArgs, env }) {
168
+ const configuredSettings = await probeConfiguredPlaywrightSettings({
169
+ launcher,
170
+ configPath,
171
+ hasCustomConfig,
172
+ userArgs,
173
+ env
174
+ });
175
+ return {
176
+ retries: configuredSettings.retries ?? 0,
177
+ workers: configuredSettings.workers
178
+ };
179
+ }
180
+ async function probeConfiguredPlaywrightSettings({ launcher, configPath, hasCustomConfig, userArgs, env }) {
181
+ const probeArgs = ["test"];
182
+ if (!hasCustomConfig) probeArgs.push("--config", configPath);
183
+ probeArgs.push("--list", "--reporter=json", ...extractPlaywrightProjectArgs(userArgs));
184
+ try {
185
+ const json = parseJsonObjectFromText(await spawnAndCaptureStdout({
186
+ name: "Playwright retries probe",
187
+ launcher,
188
+ args: probeArgs,
189
+ env
190
+ }));
191
+ if (!json) return {
192
+ retries: null,
193
+ workers: null
194
+ };
195
+ return {
196
+ retries: resolvePlaywrightRetriesFromReport(json),
197
+ workers: resolvePlaywrightWorkersFromReport(json)
198
+ };
199
+ } catch (_error) {
200
+ return {
201
+ retries: null,
202
+ workers: null
203
+ };
204
+ }
214
205
  }
215
206
  function extractPlaywrightProjectArgs(userArgs) {
216
- const output = [];
217
- for (let i = 0; i < userArgs.length; i += 1) {
218
- const arg = userArgs[i];
219
- if (arg === "--") {
220
- break;
221
- }
222
- if (arg === "--project") {
223
- const next = userArgs[i + 1];
224
- if (next != null) {
225
- output.push(arg, next);
226
- i += 1;
227
- }
228
- continue;
229
- }
230
- if (arg.startsWith("--project=")) {
231
- output.push(arg);
232
- }
233
- }
234
- return output;
207
+ const output = [];
208
+ for (let i = 0; i < userArgs.length; i += 1) {
209
+ const arg = userArgs[i];
210
+ if (arg === "--") break;
211
+ if (arg === "--project") {
212
+ const next = userArgs[i + 1];
213
+ if (next != null) {
214
+ output.push(arg, next);
215
+ i += 1;
216
+ }
217
+ continue;
218
+ }
219
+ if (arg.startsWith("--project=")) output.push(arg);
220
+ }
221
+ return output;
235
222
  }
236
223
  function parseJsonObjectFromText(input) {
237
- try {
238
- return JSON.parse(input);
239
- } catch {
240
- const start = input.indexOf("{");
241
- const end = input.lastIndexOf("}");
242
- if (start === -1 || end === -1 || end <= start) {
243
- return null;
244
- }
245
- try {
246
- return JSON.parse(input.slice(start, end + 1));
247
- } catch {
248
- return null;
249
- }
250
- }
224
+ try {
225
+ return JSON.parse(input);
226
+ } catch {
227
+ const start = input.indexOf("{");
228
+ const end = input.lastIndexOf("}");
229
+ if (start === -1 || end === -1 || end <= start) return null;
230
+ try {
231
+ return JSON.parse(input.slice(start, end + 1));
232
+ } catch {
233
+ return null;
234
+ }
235
+ }
251
236
  }
252
237
  function extractPlaywrightPositionalArgs(userArgs) {
253
- const output = [];
254
- for (let i = 0; i < userArgs.length; i += 1) {
255
- const arg = userArgs[i];
256
- if (arg === "--") {
257
- break;
258
- }
259
- if (!arg.startsWith("-")) {
260
- output.push(arg);
261
- continue;
262
- }
263
- if (arg.includes("=")) {
264
- continue;
265
- }
266
- if (PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE.has(arg)) {
267
- const next = userArgs[i + 1];
268
- if (next !== void 0) {
269
- i += 1;
270
- }
271
- continue;
272
- }
273
- if (PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE.has(arg)) {
274
- const next = userArgs[i + 1];
275
- if (next !== void 0 && !next.startsWith("-")) {
276
- i += 1;
277
- }
278
- }
279
- }
280
- return output;
238
+ const output = [];
239
+ for (let i = 0; i < userArgs.length; i += 1) {
240
+ const arg = userArgs[i];
241
+ if (arg === "--") break;
242
+ if (!arg.startsWith("-")) {
243
+ output.push(arg);
244
+ continue;
245
+ }
246
+ if (arg.includes("=")) continue;
247
+ if (PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE.has(arg)) {
248
+ if (userArgs[i + 1] !== void 0) i += 1;
249
+ continue;
250
+ }
251
+ if (PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE.has(arg)) {
252
+ const next = userArgs[i + 1];
253
+ if (next !== void 0 && !next.startsWith("-")) i += 1;
254
+ }
255
+ }
256
+ return output;
281
257
  }
282
258
  function removePlaywrightOptions(optionArgs, optionsToRemove) {
283
- const output = [];
284
- for (let i = 0; i < optionArgs.length; i += 1) {
285
- const arg = optionArgs[i];
286
- const normalized = arg.split("=")[0];
287
- if (!arg.startsWith("-") || !optionsToRemove.has(normalized)) {
288
- output.push(arg);
289
- continue;
290
- }
291
- if (arg.includes("=")) {
292
- continue;
293
- }
294
- if (PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE.has(normalized)) {
295
- const next = optionArgs[i + 1];
296
- if (next !== void 0) {
297
- i += 1;
298
- }
299
- continue;
300
- }
301
- if (PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE.has(normalized)) {
302
- const next = optionArgs[i + 1];
303
- if (next !== void 0 && !next.startsWith("-")) {
304
- i += 1;
305
- }
306
- }
307
- }
308
- return output;
259
+ const output = [];
260
+ for (let i = 0; i < optionArgs.length; i += 1) {
261
+ const arg = optionArgs[i];
262
+ const normalized = arg.split("=")[0];
263
+ if (!arg.startsWith("-") || !optionsToRemove.has(normalized)) {
264
+ output.push(arg);
265
+ continue;
266
+ }
267
+ if (arg.includes("=")) continue;
268
+ if (PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE.has(normalized)) {
269
+ if (optionArgs[i + 1] !== void 0) i += 1;
270
+ continue;
271
+ }
272
+ if (PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE.has(normalized)) {
273
+ const next = optionArgs[i + 1];
274
+ if (next !== void 0 && !next.startsWith("-")) i += 1;
275
+ }
276
+ }
277
+ return output;
309
278
  }
310
279
  function extractPlaywrightOptionArgs(userArgs) {
311
- const output = [];
312
- for (let i = 0; i < userArgs.length; i += 1) {
313
- const arg = userArgs[i];
314
- if (arg === "--") {
315
- break;
316
- }
317
- if (!arg.startsWith("-")) {
318
- continue;
319
- }
320
- output.push(arg);
321
- if (arg.includes("=")) {
322
- continue;
323
- }
324
- if (PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE.has(arg)) {
325
- const next = userArgs[i + 1];
326
- if (next !== void 0) {
327
- output.push(next);
328
- i += 1;
329
- }
330
- continue;
331
- }
332
- if (PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE.has(arg)) {
333
- const next = userArgs[i + 1];
334
- if (next !== void 0 && !next.startsWith("-")) {
335
- output.push(next);
336
- i += 1;
337
- }
338
- }
339
- }
340
- return output;
280
+ const output = [];
281
+ for (let i = 0; i < userArgs.length; i += 1) {
282
+ const arg = userArgs[i];
283
+ if (arg === "--") break;
284
+ if (!arg.startsWith("-")) continue;
285
+ output.push(arg);
286
+ if (arg.includes("=")) continue;
287
+ if (PLAYWRIGHT_OPTIONS_WITH_REQUIRED_VALUE.has(arg)) {
288
+ const next = userArgs[i + 1];
289
+ if (next !== void 0) {
290
+ output.push(next);
291
+ i += 1;
292
+ }
293
+ continue;
294
+ }
295
+ if (PLAYWRIGHT_OPTIONS_WITH_OPTIONAL_VALUE.has(arg)) {
296
+ const next = userArgs[i + 1];
297
+ if (next !== void 0 && !next.startsWith("-")) {
298
+ output.push(next);
299
+ i += 1;
300
+ }
301
+ }
302
+ }
303
+ return output;
341
304
  }
342
305
  async function readPlaywrightReportSummary(resultsFilePath, newerThanMtimeMs) {
343
- const stats = await fs$1.stat(resultsFilePath).catch(() => null);
344
- if (!stats) {
345
- return null;
346
- }
347
- if (newerThanMtimeMs != null && stats.mtimeMs <= newerThanMtimeMs) {
348
- return null;
349
- }
350
- const data = await readJson(resultsFilePath);
351
- if (!data || typeof data !== "object") {
352
- return null;
353
- }
354
- return {
355
- failedFiles: resolveFailedPlaywrightFiles(data)
356
- };
306
+ const stats = await fs.stat(resultsFilePath).catch(() => null);
307
+ if (!stats) return null;
308
+ if (newerThanMtimeMs != null && stats.mtimeMs <= newerThanMtimeMs) return null;
309
+ const data = await readJson(resultsFilePath);
310
+ if (!data || typeof data !== "object") return null;
311
+ return { failedFiles: resolveFailedPlaywrightFiles(data) };
357
312
  }
358
313
  function getFileMtimeMs(filePath) {
359
- try {
360
- return fs.statSync(filePath).mtimeMs;
361
- } catch {
362
- return null;
363
- }
314
+ try {
315
+ return fsSync.statSync(filePath).mtimeMs;
316
+ } catch {
317
+ return null;
318
+ }
364
319
  }
365
320
  function resolvePlaywrightRetriesFromReport(data) {
366
- const projects = Array.isArray(data?.config?.projects) ? data.config.projects : [];
367
- const retriesFromProjects = projects.map((project) => Number(project?.retries)).filter((value) => Number.isFinite(value)).map((value) => Math.max(0, Math.floor(value)));
368
- if (retriesFromProjects.length > 0) {
369
- return Math.max(...retriesFromProjects);
370
- }
371
- const fallback = Number(data?.config?.retries);
372
- if (Number.isFinite(fallback)) {
373
- return Math.max(0, Math.floor(fallback));
374
- }
375
- return 0;
321
+ const retriesFromProjects = (Array.isArray(data?.config?.projects) ? data.config.projects : []).map((project) => Number(project?.retries)).filter((value) => Number.isFinite(value)).map((value) => Math.max(0, Math.floor(value)));
322
+ if (retriesFromProjects.length > 0) return Math.max(...retriesFromProjects);
323
+ const fallback = Number(data?.config?.retries);
324
+ if (Number.isFinite(fallback)) return Math.max(0, Math.floor(fallback));
325
+ return 0;
376
326
  }
377
327
  function resolvePlaywrightWorkersFromReport(data) {
378
- const configWorkers = Number(data?.config?.workers);
379
- if (Number.isFinite(configWorkers)) {
380
- return Math.max(1, Math.floor(configWorkers));
381
- }
382
- const projects = Array.isArray(data?.config?.projects) ? data.config.projects : [];
383
- const workersFromProjects = projects.map((project) => Number(project?.metadata?.actualWorkers ?? project?.workers)).filter((value) => Number.isFinite(value)).map((value) => Math.max(1, Math.floor(value)));
384
- if (workersFromProjects.length > 0) {
385
- return Math.max(...workersFromProjects);
386
- }
387
- return null;
328
+ const configWorkers = Number(data?.config?.workers);
329
+ if (Number.isFinite(configWorkers)) return Math.max(1, Math.floor(configWorkers));
330
+ const workersFromProjects = (Array.isArray(data?.config?.projects) ? data.config.projects : []).map((project) => Number(project?.metadata?.actualWorkers ?? project?.workers)).filter((value) => Number.isFinite(value)).map((value) => Math.max(1, Math.floor(value)));
331
+ if (workersFromProjects.length > 0) return Math.max(...workersFromProjects);
332
+ return null;
388
333
  }
389
334
  function resolveFailedPlaywrightFiles(data) {
390
- const suites = Array.isArray(data?.suites) ? data.suites : [];
391
- const rootDir = typeof data?.config?.rootDir === "string" ? data.config.rootDir : null;
392
- const failedFiles = /* @__PURE__ */ new Set();
393
- for (const suite of suites) {
394
- collectFailedPlaywrightFiles(suite, failedFiles, rootDir);
395
- }
396
- return Array.from(failedFiles).sort();
335
+ const suites = Array.isArray(data?.suites) ? data.suites : [];
336
+ const rootDir = typeof data?.config?.rootDir === "string" ? data.config.rootDir : null;
337
+ const failedFiles = /* @__PURE__ */ new Set();
338
+ for (const suite of suites) collectFailedPlaywrightFiles(suite, failedFiles, rootDir);
339
+ return Array.from(failedFiles).sort();
397
340
  }
398
341
  function collectFailedPlaywrightFiles(suite, output, rootDir) {
399
- const specs = Array.isArray(suite?.specs) ? suite.specs : [];
400
- for (const spec of specs) {
401
- if (isPlaywrightSpecSuccessful(spec)) {
402
- continue;
403
- }
404
- const file = normalizePlaywrightReportFile(spec?.file ?? suite?.file, rootDir);
405
- if (file) {
406
- output.add(file);
407
- }
408
- }
409
- const innerSuites = Array.isArray(suite?.suites) ? suite.suites : [];
410
- for (const innerSuite of innerSuites) {
411
- collectFailedPlaywrightFiles(innerSuite, output, rootDir);
412
- }
342
+ const specs = Array.isArray(suite?.specs) ? suite.specs : [];
343
+ for (const spec of specs) {
344
+ if (isPlaywrightSpecSuccessful(spec)) continue;
345
+ const file = normalizePlaywrightReportFile(spec?.file ?? suite?.file, rootDir);
346
+ if (file) output.add(file);
347
+ }
348
+ const innerSuites = Array.isArray(suite?.suites) ? suite.suites : [];
349
+ for (const innerSuite of innerSuites) collectFailedPlaywrightFiles(innerSuite, output, rootDir);
413
350
  }
414
351
  function isPlaywrightSpecSuccessful(spec) {
415
- if (typeof spec?.ok === "boolean") {
416
- return spec.ok;
417
- }
418
- const tests = Array.isArray(spec?.tests) ? spec.tests : [];
419
- if (tests.length === 0) {
420
- return false;
421
- }
422
- return tests.every((test) => {
423
- const testStatus = String(test?.status ?? "");
424
- if (testStatus === "expected" || testStatus === "skipped" || testStatus === "flaky") {
425
- return true;
426
- }
427
- const results = Array.isArray(test?.results) ? test.results : [];
428
- if (results.length === 0) {
429
- return false;
430
- }
431
- return results.every((result) => result?.status === "passed" || result?.status === "skipped");
432
- });
352
+ if (typeof spec?.ok === "boolean") return spec.ok;
353
+ const tests = Array.isArray(spec?.tests) ? spec.tests : [];
354
+ if (tests.length === 0) return false;
355
+ return tests.every((test) => {
356
+ const testStatus = String(test?.status ?? "");
357
+ if (testStatus === "expected" || testStatus === "skipped" || testStatus === "flaky") return true;
358
+ const results = Array.isArray(test?.results) ? test.results : [];
359
+ if (results.length === 0) return false;
360
+ return results.every((result) => result?.status === "passed" || result?.status === "skipped");
361
+ });
433
362
  }
434
363
  function normalizePlaywrightReportFile(filePath, rootDir) {
435
- const raw = String(filePath ?? "").trim();
436
- if (!raw) {
437
- return null;
438
- }
439
- let absolutePath;
440
- if (path.isAbsolute(raw)) {
441
- absolutePath = path.normalize(raw);
442
- } else {
443
- const cwdCandidate = path.resolve(process.cwd(), raw);
444
- const rootCandidate = rootDir ? path.resolve(rootDir, raw) : null;
445
- if (rootCandidate && fs.existsSync(rootCandidate)) {
446
- absolutePath = rootCandidate;
447
- } else if (fs.existsSync(cwdCandidate)) {
448
- absolutePath = cwdCandidate;
449
- } else {
450
- absolutePath = rootCandidate ?? cwdCandidate;
451
- }
452
- }
453
- const relative = path.relative(process.cwd(), absolutePath);
454
- if (relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative)) {
455
- return toPosixPath(relative || raw);
456
- }
457
- return toPosixPath(raw);
364
+ const raw = String(filePath ?? "").trim();
365
+ if (!raw) return null;
366
+ let absolutePath;
367
+ if (path.isAbsolute(raw)) absolutePath = path.normalize(raw);
368
+ else {
369
+ const cwdCandidate = path.resolve(process.cwd(), raw);
370
+ const rootCandidate = rootDir ? path.resolve(rootDir, raw) : null;
371
+ if (rootCandidate && fsSync.existsSync(rootCandidate)) absolutePath = rootCandidate;
372
+ else if (fsSync.existsSync(cwdCandidate)) absolutePath = cwdCandidate;
373
+ else absolutePath = rootCandidate ?? cwdCandidate;
374
+ }
375
+ const relative = path.relative(process.cwd(), absolutePath);
376
+ if (relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative)) return toPosixPath(relative || raw);
377
+ return toPosixPath(raw);
458
378
  }
459
379
  function toPosixPath(input) {
460
- return String(input ?? "").replaceAll("\\", "/").split(path.sep).join("/");
380
+ return String(input ?? "").replaceAll("\\", "/").split(path.sep).join("/");
461
381
  }
462
382
  function buildPlaywrightRetryOutputDir(attempt, failedFiles) {
463
- const slug = failedFiles.map((file) => toPosixPath(file).replace(/[^a-zA-Z0-9._/-]+/g, "-").replace(/\//g, "__")).join("--");
464
- return toPosixPath(path.join("build", "playwright", "test-results", "rb-retries", `attempt-${attempt}`, slug));
383
+ const slug = failedFiles.map((file) => toPosixPath(file).replace(/[^a-zA-Z0-9._/-]+/g, "-").replace(/\//g, "__")).join("--");
384
+ return toPosixPath(path.join("build", "playwright", "test-results", "rb-retries", `attempt-${attempt}`, slug));
465
385
  }
466
386
  function createPlaywrightRetryEnv(baseEnv) {
467
- return {
468
- ...baseEnv,
469
- PLAYWRIGHT_FORCE_TTY: "false"
470
- };
387
+ return {
388
+ ...baseEnv,
389
+ PLAYWRIGHT_FORCE_TTY: "false"
390
+ };
471
391
  }
472
392
  function truncatePlaywrightRetryLogLabel(label, maxLength = PLAYWRIGHT_RETRY_LOG_LABEL_MAX_LENGTH) {
473
- if (label.length <= maxLength) {
474
- return label;
475
- }
476
- if (maxLength <= 3) {
477
- return ".".repeat(Math.max(0, maxLength));
478
- }
479
- const visibleChars = maxLength - 3;
480
- const startLength = Math.ceil(visibleChars / 2);
481
- const endLength = Math.floor(visibleChars / 2);
482
- return `${label.slice(0, startLength)}...${label.slice(-endLength)}`;
393
+ if (label.length <= maxLength) return label;
394
+ if (maxLength <= 3) return ".".repeat(Math.max(0, maxLength));
395
+ const visibleChars = maxLength - 3;
396
+ const startLength = Math.ceil(visibleChars / 2);
397
+ const endLength = Math.floor(visibleChars / 2);
398
+ return `${label.slice(0, startLength)}...${label.slice(-endLength)}`;
483
399
  }
484
400
  function getPlaywrightRetryLogName(failedFile) {
485
- const normalizedFile = toPosixPath(failedFile);
486
- const relativeFile = normalizedFile.startsWith("build/spec/") ? normalizedFile.slice("build/spec/".length) : normalizedFile;
487
- const strippedBaseName = relativeFile.replace(/\.(spec|test)\.[^.]+$/i, "").replace(/\.[^.]+$/i, "").trim();
488
- return strippedBaseName || relativeFile || normalizedFile;
489
- }
490
- function formatPlaywrightRetryBracketLabel({
491
- failedFile,
492
- suffix = ""
493
- }) {
494
- const label = truncatePlaywrightRetryLogLabel(getPlaywrightRetryLogName(failedFile), Math.max(1, PLAYWRIGHT_RETRY_LOG_LABEL_MAX_LENGTH - suffix.length));
495
- return `[${label}${suffix}]`;
496
- }
497
- function formatPlaywrightRetryLogLabel({
498
- failedFile
499
- }) {
500
- return formatPlaywrightRetryBracketLabel({
501
- failedFile
502
- });
503
- }
504
- function formatPlaywrightRetryLinePrefix({
505
- failedFile,
506
- stream
507
- }) {
508
- return stream === "stderr" ? `${formatPlaywrightRetryBracketLabel({
509
- failedFile,
510
- suffix: " stderr"
511
- })} ` : `${formatPlaywrightRetryLogLabel({
512
- failedFile
513
- })} `;
514
- }
515
- async function runPlaywrightRetryAttempt({
516
- launcher,
517
- userArgs,
518
- failedFiles,
519
- retryConcurrency,
520
- configPath,
521
- hasCustomConfig,
522
- env,
523
- attempt
524
- }) {
525
- const failedAgain = /* @__PURE__ */ new Set();
526
- let lastError = null;
527
- let nextIndex = 0;
528
- const retryEnv = createPlaywrightRetryEnv(env);
529
- async function runNext() {
530
- while (nextIndex < failedFiles.length) {
531
- const fileIndex = nextIndex;
532
- nextIndex += 1;
533
- const failedFile = failedFiles[fileIndex];
534
- const retryLogLabel = formatPlaywrightRetryLogLabel({
535
- failedFile
536
- });
537
- const retryArgs = buildPlaywrightWorkerRetryArgs(userArgs, [failedFile], attempt);
538
- const retryPlaywrightArgs = ["test"];
539
- if (!hasCustomConfig) {
540
- retryPlaywrightArgs.push("--config", configPath);
541
- }
542
- retryPlaywrightArgs.push(...retryArgs);
543
- try {
544
- console.warn(`${retryLogLabel} Starting fresh-worker retry`);
545
- await runPlaywrightOnce({
546
- launcher,
547
- args: retryPlaywrightArgs,
548
- env: retryEnv,
549
- outputMode: "line",
550
- bufferOutput: true,
551
- successMessage: null,
552
- failureMessage: `${retryLogLabel} Playwright failed`,
553
- stdoutLinePrefix: formatPlaywrightRetryLinePrefix({
554
- failedFile,
555
- stream: "stdout"
556
- }),
557
- stderrLinePrefix: formatPlaywrightRetryLinePrefix({
558
- failedFile,
559
- stream: "stderr"
560
- })
561
- });
562
- } catch (retryError) {
563
- lastError = retryError;
564
- failedAgain.add(failedFile);
565
- }
566
- }
567
- }
568
- await Promise.all(Array.from({
569
- length: Math.max(1, Math.min(retryConcurrency, failedFiles.length))
570
- }, () => runNext()));
571
- return {
572
- failedFiles: failedFiles.filter((failedFile) => failedAgain.has(failedFile)),
573
- lastError
574
- };
401
+ const normalizedFile = toPosixPath(failedFile);
402
+ const relativeFile = normalizedFile.startsWith("build/spec/") ? normalizedFile.slice(11) : normalizedFile;
403
+ return relativeFile.replace(/\.(spec|test)\.[^.]+$/i, "").replace(/\.[^.]+$/i, "").trim() || relativeFile || normalizedFile;
404
+ }
405
+ function formatPlaywrightRetryBracketLabel({ failedFile, suffix = "" }) {
406
+ return `[${truncatePlaywrightRetryLogLabel(getPlaywrightRetryLogName(failedFile), Math.max(1, PLAYWRIGHT_RETRY_LOG_LABEL_MAX_LENGTH - suffix.length))}${suffix}]`;
407
+ }
408
+ function formatPlaywrightRetryLogLabel({ failedFile }) {
409
+ return formatPlaywrightRetryBracketLabel({ failedFile });
410
+ }
411
+ function formatPlaywrightRetryLinePrefix({ failedFile, stream }) {
412
+ return stream === "stderr" ? `${formatPlaywrightRetryBracketLabel({
413
+ failedFile,
414
+ suffix: " stderr"
415
+ })} ` : `${formatPlaywrightRetryLogLabel({ failedFile })} `;
416
+ }
417
+ async function runPlaywrightRetryAttempt({ launcher, userArgs, failedFiles, retryConcurrency, configPath, hasCustomConfig, env, attempt }) {
418
+ const failedAgain = /* @__PURE__ */ new Set();
419
+ let lastError = null;
420
+ let nextIndex = 0;
421
+ const retryEnv = createPlaywrightRetryEnv(env);
422
+ async function runNext() {
423
+ while (nextIndex < failedFiles.length) {
424
+ const fileIndex = nextIndex;
425
+ nextIndex += 1;
426
+ const failedFile = failedFiles[fileIndex];
427
+ const retryLogLabel = formatPlaywrightRetryLogLabel({ failedFile });
428
+ const retryArgs = buildPlaywrightWorkerRetryArgs(userArgs, [failedFile], attempt);
429
+ const retryPlaywrightArgs = ["test"];
430
+ if (!hasCustomConfig) retryPlaywrightArgs.push("--config", configPath);
431
+ retryPlaywrightArgs.push(...retryArgs);
432
+ try {
433
+ console.warn(`${retryLogLabel} Starting fresh-worker retry`);
434
+ await runPlaywrightOnce({
435
+ launcher,
436
+ args: retryPlaywrightArgs,
437
+ env: retryEnv,
438
+ outputMode: "line",
439
+ bufferOutput: true,
440
+ successMessage: null,
441
+ failureMessage: `${retryLogLabel} Playwright failed`,
442
+ stdoutLinePrefix: formatPlaywrightRetryLinePrefix({
443
+ failedFile,
444
+ stream: "stdout"
445
+ }),
446
+ stderrLinePrefix: formatPlaywrightRetryLinePrefix({
447
+ failedFile,
448
+ stream: "stderr"
449
+ })
450
+ });
451
+ } catch (retryError) {
452
+ lastError = retryError;
453
+ failedAgain.add(failedFile);
454
+ }
455
+ }
456
+ }
457
+ await Promise.all(Array.from({ length: Math.max(1, Math.min(retryConcurrency, failedFiles.length)) }, () => runNext()));
458
+ return {
459
+ failedFiles: failedFiles.filter((failedFile) => failedAgain.has(failedFile)),
460
+ lastError
461
+ };
575
462
  }
576
463
  async function readJson(filePath) {
577
- try {
578
- const raw = await fs$1.readFile(filePath, "utf8");
579
- return JSON.parse(raw);
580
- } catch {
581
- return null;
582
- }
464
+ try {
465
+ const raw = await fs.readFile(filePath, "utf8");
466
+ return JSON.parse(raw);
467
+ } catch {
468
+ return null;
469
+ }
583
470
  }
584
471
  function ensureJsxRuntimeShim(projectRoot) {
585
- const shimDir = path.join(projectRoot, "node_modules", "playwright");
586
- fs.mkdirSync(shimDir, {
587
- recursive: true
588
- });
589
- const shims = [{
590
- file: "jsx-runtime.js",
591
- target: "react/jsx-runtime"
592
- }, {
593
- file: "jsx-dev-runtime.js",
594
- target: "react/jsx-dev-runtime"
595
- }];
596
- for (const {
597
- file,
598
- target
599
- } of shims) {
600
- const filePath = path.join(shimDir, file);
601
- if (!fs.existsSync(filePath)) {
602
- const content = `export * from "${target}";
603
- export { default } from "${target}";
604
- `;
605
- fs.writeFileSync(filePath, content, "utf8");
606
- }
607
- }
608
- }
609
- export {
610
- createPlaywrightRetryEnv,
611
- formatPlaywrightRetryLinePrefix,
612
- formatPlaywrightRetryLogLabel,
613
- runPlaywright
614
- };
615
- //# sourceMappingURL=playwright.js.map
472
+ const shimDir = path.join(projectRoot, "node_modules", "playwright");
473
+ fsSync.mkdirSync(shimDir, { recursive: true });
474
+ for (const { file, target } of [{
475
+ file: "jsx-runtime.js",
476
+ target: "react/jsx-runtime"
477
+ }, {
478
+ file: "jsx-dev-runtime.js",
479
+ target: "react/jsx-dev-runtime"
480
+ }]) {
481
+ const filePath = path.join(shimDir, file);
482
+ if (!fsSync.existsSync(filePath)) {
483
+ const content = `export * from "${target}";\nexport { default } from "${target}";\n`;
484
+ fsSync.writeFileSync(filePath, content, "utf8");
485
+ }
486
+ }
487
+ }
488
+ //#endregion
489
+ export { createPlaywrightRetryEnv, formatPlaywrightRetryLinePrefix, formatPlaywrightRetryLogLabel, runPlaywright };
490
+
491
+ //# sourceMappingURL=playwright.js.map