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