@empiricalrun/test-run 0.16.0 → 0.16.1
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/CHANGELOG.md +7 -0
- package/dist/bin/commands/failed-list.js +1 -1
- package/dist/failed-test-list.d.ts +25 -2
- package/dist/failed-test-list.d.ts.map +1 -1
- package/dist/failed-test-list.js +115 -17
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/lib/cmd.js +10 -3
- package/dist/lib/run-specific-test.d.ts.map +1 -1
- package/dist/lib/run-specific-test.js +13 -22
- package/package.json +2 -2
- package/test-data/expand-serial-fixture/playwright.config.ts +6 -0
- package/test-data/expand-serial-fixture/serial.spec.ts +17 -0
- package/vitest.config.ts +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -23,7 +23,7 @@ function registerFailedListCommand(program) {
|
|
|
23
23
|
repoPath: options.repoPath,
|
|
24
24
|
verbose: options.verbose,
|
|
25
25
|
});
|
|
26
|
-
console.log(`Found ${result.
|
|
26
|
+
console.log(`Found ${result.testsToRun.length} failed tests`);
|
|
27
27
|
console.log(`Test list written to: ${result.outputPath}`);
|
|
28
28
|
}
|
|
29
29
|
catch (error) {
|
|
@@ -1,9 +1,28 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a test line for comparison between manifest and ran tests.
|
|
3
|
+
* Strips `:line:col` suffixes from file paths.
|
|
4
|
+
*
|
|
5
|
+
* e.g. `[chromium] › foo/bar.spec.ts:4:5 › has title`
|
|
6
|
+
* → `[chromium] › foo/bar.spec.ts › has title`
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeTestLine(line: string): string;
|
|
9
|
+
export declare function parseTestListLine(line: string): TestList | null;
|
|
10
|
+
/**
|
|
11
|
+
* Runs `npx playwright test --list <file>` and returns all test lines for the file.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getAllTestsForFile(file: string, repoPath: string): Promise<string[]>;
|
|
14
|
+
export interface TestList {
|
|
2
15
|
projectName: string;
|
|
3
16
|
file: string;
|
|
4
17
|
title: string;
|
|
5
18
|
suites: string[];
|
|
6
19
|
}
|
|
20
|
+
export interface SerialBlockInfo {
|
|
21
|
+
file: string;
|
|
22
|
+
serialDescribeName: string | null;
|
|
23
|
+
isFileSerial: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare function getSerialBlockInfo(test: TestList, repoPath: string, verbose: boolean): Promise<SerialBlockInfo | null>;
|
|
7
26
|
export interface BuildTestListOptions {
|
|
8
27
|
outputPath?: string;
|
|
9
28
|
verbose?: boolean;
|
|
@@ -11,9 +30,13 @@ export interface BuildTestListOptions {
|
|
|
11
30
|
repoPath?: string;
|
|
12
31
|
}
|
|
13
32
|
export interface BuildTestListResult {
|
|
14
|
-
|
|
33
|
+
testsToRun: TestList[];
|
|
15
34
|
testListContent: string;
|
|
16
35
|
outputPath: string;
|
|
17
36
|
}
|
|
37
|
+
export declare function buildTestList(testsToRun: TestList[], allTests: TestList[], options: BuildTestListOptions & {
|
|
38
|
+
verbose: boolean;
|
|
39
|
+
}): Promise<BuildTestListResult>;
|
|
18
40
|
export declare function buildTestListFromFailedTestRun(runId: string, options?: BuildTestListOptions): Promise<BuildTestListResult>;
|
|
41
|
+
export declare function expandSerialDependencies(testListContent: string, outputPath: string, repoPath: string): Promise<string>;
|
|
19
42
|
//# sourceMappingURL=failed-test-list.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"failed-test-list.d.ts","sourceRoot":"","sources":["../src/failed-test-list.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"failed-test-list.d.ts","sourceRoot":"","sources":["../src/failed-test-list.ts"],"names":[],"mappings":"AAsBA;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAgB/D;AAID;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CAsBnB;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAmED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,OAAO,CAAC;CACvB;AAoBD,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CA+CjC;AA0FD,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,QAAQ,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AA0DD,wBAAsB,aAAa,CACjC,UAAU,EAAE,QAAQ,EAAE,EACtB,QAAQ,EAAE,QAAQ,EAAE,EACpB,OAAO,EAAE,oBAAoB,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GACnD,OAAO,CAAC,mBAAmB,CAAC,CA0D9B;AAED,wBAAsB,8BAA8B,CAClD,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAa9B;AAED,wBAAsB,wBAAwB,CAC5C,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAmCjB"}
|
package/dist/failed-test-list.js
CHANGED
|
@@ -3,13 +3,65 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.normalizeTestLine = normalizeTestLine;
|
|
7
|
+
exports.parseTestListLine = parseTestListLine;
|
|
8
|
+
exports.getAllTestsForFile = getAllTestsForFile;
|
|
9
|
+
exports.getSerialBlockInfo = getSerialBlockInfo;
|
|
10
|
+
exports.buildTestList = buildTestList;
|
|
6
11
|
exports.buildTestListFromFailedTestRun = buildTestListFromFailedTestRun;
|
|
12
|
+
exports.expandSerialDependencies = expandSerialDependencies;
|
|
13
|
+
const node_child_process_1 = require("node:child_process");
|
|
14
|
+
const node_util_1 = require("node:util");
|
|
7
15
|
const reporter_1 = require("@empiricalrun/reporter");
|
|
8
16
|
const fs_1 = __importDefault(require("fs"));
|
|
9
17
|
const path_1 = __importDefault(require("path"));
|
|
10
18
|
const utils_1 = require("./utils");
|
|
11
19
|
const DOMAIN = process.env.DASHBOARD_DOMAIN || "https://dash.empirical.run";
|
|
12
20
|
const SUITES_DELIMITER = " › ";
|
|
21
|
+
/**
|
|
22
|
+
* Normalize a test line for comparison between manifest and ran tests.
|
|
23
|
+
* Strips `:line:col` suffixes from file paths.
|
|
24
|
+
*
|
|
25
|
+
* e.g. `[chromium] › foo/bar.spec.ts:4:5 › has title`
|
|
26
|
+
* → `[chromium] › foo/bar.spec.ts › has title`
|
|
27
|
+
*/
|
|
28
|
+
function normalizeTestLine(line) {
|
|
29
|
+
return line.replace(/(\.spec\.ts|\.test\.ts|\.ts|\.js):\d+:\d+/g, "$1");
|
|
30
|
+
}
|
|
31
|
+
function parseTestListLine(line) {
|
|
32
|
+
const trimmed = normalizeTestLine(line.trim());
|
|
33
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
34
|
+
return null;
|
|
35
|
+
const match = trimmed.match(/^\[(.*?)\]\s*[›>]\s*(.*)/);
|
|
36
|
+
if (!match?.[1] || !match[2])
|
|
37
|
+
return null;
|
|
38
|
+
const projectName = match[1];
|
|
39
|
+
const parts = match[2].split(/\s*[›>]\s*/);
|
|
40
|
+
if (parts.length < 2)
|
|
41
|
+
return null;
|
|
42
|
+
const file = parts[0].trim();
|
|
43
|
+
const suites = parts.slice(1, -1);
|
|
44
|
+
const title = parts[parts.length - 1].trim();
|
|
45
|
+
return { projectName, file, suites, title };
|
|
46
|
+
}
|
|
47
|
+
const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
48
|
+
/**
|
|
49
|
+
* Runs `npx playwright test --list <file>` and returns all test lines for the file.
|
|
50
|
+
*/
|
|
51
|
+
async function getAllTestsForFile(file, repoPath) {
|
|
52
|
+
try {
|
|
53
|
+
const playwrightCli = path_1.default.join(repoPath, "node_modules", "@playwright", "test", "cli.js");
|
|
54
|
+
const { stdout } = await execFileAsync("node", [playwrightCli, "test", "--list", file], { cwd: repoPath });
|
|
55
|
+
return stdout
|
|
56
|
+
.split("\n")
|
|
57
|
+
.map((line) => line.trim())
|
|
58
|
+
.filter((line) => line.includes(" › "));
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
console.error(`Failed to list tests for file: ${file}`, error);
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
13
65
|
async function fetchTestRun(runId, options) {
|
|
14
66
|
if (!process.env.EMPIRICALRUN_API_KEY) {
|
|
15
67
|
throw new Error("EMPIRICALRUN_API_KEY environment variable is required");
|
|
@@ -45,8 +97,12 @@ function getFailedTests(specs) {
|
|
|
45
97
|
const failedTests = [];
|
|
46
98
|
for (const spec of specs) {
|
|
47
99
|
for (const test of spec.tests) {
|
|
48
|
-
const
|
|
49
|
-
|
|
100
|
+
const retries = test.results.map((r) => ({
|
|
101
|
+
status: r.status ?? "unknown",
|
|
102
|
+
expectedStatus: test.expectedStatus,
|
|
103
|
+
}));
|
|
104
|
+
const status = (0, reporter_1.getTestStatusFromRetries)(retries);
|
|
105
|
+
if (status === "failed") {
|
|
50
106
|
const suites = spec.nesting.slice(1, -1);
|
|
51
107
|
failedTests.push({
|
|
52
108
|
projectName: test.projectName,
|
|
@@ -141,17 +197,12 @@ function isTestInSerialBlock(test, serialBlock) {
|
|
|
141
197
|
}
|
|
142
198
|
return false;
|
|
143
199
|
}
|
|
144
|
-
function generateTestListContent(
|
|
145
|
-
const lines = [
|
|
146
|
-
`# Failed tests from test run`,
|
|
147
|
-
`# Generated: ${new Date().toISOString()}`,
|
|
148
|
-
`# Total failed tests: ${failedTests.length}`,
|
|
149
|
-
"",
|
|
150
|
-
];
|
|
200
|
+
function generateTestListContent(testsToRun, allTests, serialBlocks = []) {
|
|
201
|
+
const lines = [];
|
|
151
202
|
const addedEntries = new Set();
|
|
152
203
|
for (const serialBlock of serialBlocks) {
|
|
153
204
|
const projectNames = [
|
|
154
|
-
...new Set(
|
|
205
|
+
...new Set(testsToRun
|
|
155
206
|
.filter((t) => t.file === serialBlock.file)
|
|
156
207
|
.map((t) => t.projectName)),
|
|
157
208
|
];
|
|
@@ -166,7 +217,7 @@ function generateTestListContent(failedTests, allTests, serialBlocks = []) {
|
|
|
166
217
|
}
|
|
167
218
|
}
|
|
168
219
|
}
|
|
169
|
-
for (const test of
|
|
220
|
+
for (const test of testsToRun) {
|
|
170
221
|
const isInSerialBlock = serialBlocks.some((s) => s.file === test.file);
|
|
171
222
|
if (!isInSerialBlock) {
|
|
172
223
|
const line = formatTestListLine(test);
|
|
@@ -178,8 +229,8 @@ function generateTestListContent(failedTests, allTests, serialBlocks = []) {
|
|
|
178
229
|
}
|
|
179
230
|
return lines.join("\n");
|
|
180
231
|
}
|
|
181
|
-
async function
|
|
182
|
-
const verbose = options
|
|
232
|
+
async function fetchFailedTestList(runId, options) {
|
|
233
|
+
const { verbose } = options;
|
|
183
234
|
const testRunResponse = await fetchTestRun(runId, {
|
|
184
235
|
verbose,
|
|
185
236
|
repoName: options.repoName,
|
|
@@ -214,12 +265,16 @@ async function buildTestListFromFailedTestRun(runId, options = {}) {
|
|
|
214
265
|
if (verbose) {
|
|
215
266
|
console.log(`Found ${failedTests.length} failed tests, ${allTests.length} total tests`);
|
|
216
267
|
}
|
|
268
|
+
return { failedTests, allTests };
|
|
269
|
+
}
|
|
270
|
+
async function buildTestList(testsToRun, allTests, options) {
|
|
271
|
+
const { verbose } = options;
|
|
217
272
|
const serialBlocks = [];
|
|
218
273
|
if (options.repoPath) {
|
|
219
274
|
if (verbose) {
|
|
220
275
|
console.log(`Checking for serial blocks in repo: ${options.repoPath}`);
|
|
221
276
|
}
|
|
222
|
-
for (const test of
|
|
277
|
+
for (const test of testsToRun) {
|
|
223
278
|
try {
|
|
224
279
|
const serialInfo = await getSerialBlockInfo(test, options.repoPath, verbose);
|
|
225
280
|
if (serialInfo) {
|
|
@@ -241,16 +296,59 @@ async function buildTestListFromFailedTestRun(runId, options = {}) {
|
|
|
241
296
|
console.log(`Found ${serialBlocks.length} serial blocks to expand`);
|
|
242
297
|
}
|
|
243
298
|
}
|
|
244
|
-
const testListContent = generateTestListContent(
|
|
245
|
-
const outputPath = options.outputPath || path_1.default.join(process.cwd(),
|
|
299
|
+
const testListContent = generateTestListContent(testsToRun, allTests, serialBlocks);
|
|
300
|
+
const outputPath = options.outputPath || path_1.default.join(process.cwd(), "failed-tests.txt");
|
|
246
301
|
const outputDir = path_1.default.dirname(outputPath);
|
|
247
302
|
if (!fs_1.default.existsSync(outputDir)) {
|
|
248
303
|
fs_1.default.mkdirSync(outputDir, { recursive: true });
|
|
249
304
|
}
|
|
250
305
|
fs_1.default.writeFileSync(outputPath, testListContent, "utf-8");
|
|
251
306
|
return {
|
|
252
|
-
|
|
307
|
+
testsToRun,
|
|
253
308
|
testListContent,
|
|
254
309
|
outputPath,
|
|
255
310
|
};
|
|
256
311
|
}
|
|
312
|
+
async function buildTestListFromFailedTestRun(runId, options = {}) {
|
|
313
|
+
const verbose = options.verbose ?? false;
|
|
314
|
+
const { failedTests, allTests } = await fetchFailedTestList(runId, {
|
|
315
|
+
verbose,
|
|
316
|
+
repoName: options.repoName,
|
|
317
|
+
});
|
|
318
|
+
return buildTestList(failedTests, allTests, {
|
|
319
|
+
...options,
|
|
320
|
+
verbose,
|
|
321
|
+
outputPath: options.outputPath ||
|
|
322
|
+
path_1.default.join(process.cwd(), `failed-tests-${runId}.txt`),
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
async function expandSerialDependencies(testListContent, outputPath, repoPath) {
|
|
326
|
+
const lines = testListContent.split("\n");
|
|
327
|
+
const testsToRun = [];
|
|
328
|
+
for (const line of lines) {
|
|
329
|
+
const parsed = parseTestListLine(line);
|
|
330
|
+
if (parsed)
|
|
331
|
+
testsToRun.push(parsed);
|
|
332
|
+
}
|
|
333
|
+
if (testsToRun.length === 0) {
|
|
334
|
+
console.log("testListContent could not be parsed. Returning original tests");
|
|
335
|
+
fs_1.default.writeFileSync(outputPath, testListContent, "utf-8");
|
|
336
|
+
return testListContent;
|
|
337
|
+
}
|
|
338
|
+
const uniqueFiles = [...new Set(testsToRun.map((t) => t.file))];
|
|
339
|
+
const allTests = [];
|
|
340
|
+
for (const file of uniqueFiles) {
|
|
341
|
+
const allLines = await getAllTestsForFile(file, repoPath);
|
|
342
|
+
for (const line of allLines) {
|
|
343
|
+
const parsed = parseTestListLine(line);
|
|
344
|
+
if (parsed)
|
|
345
|
+
allTests.push(parsed);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const result = await buildTestList(testsToRun, allTests, {
|
|
349
|
+
repoPath,
|
|
350
|
+
outputPath,
|
|
351
|
+
verbose: false,
|
|
352
|
+
});
|
|
353
|
+
return result.testListContent;
|
|
354
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { parseTestListOutput } from "./stdout-parser";
|
|
|
5
5
|
import { TestCase } from "./types";
|
|
6
6
|
import { getProjectsFromPlaywrightConfig } from "./utils/config";
|
|
7
7
|
export { getProjectsFromPlaywrightConfig, parseTestListOutput, runSpecificTestsCmd, spawnCmd, };
|
|
8
|
-
export { type BuildTestListOptions, type BuildTestListResult, buildTestListFromFailedTestRun, type
|
|
8
|
+
export { type BuildTestListOptions, type BuildTestListResult, buildTestList, buildTestListFromFailedTestRun, expandSerialDependencies, getAllTestsForFile, normalizeTestLine, parseTestListLine, type TestList, } from "./failed-test-list";
|
|
9
9
|
export * from "./glob-matcher";
|
|
10
10
|
export { type CancellationWatcher, startCancellationWatcher, } from "./lib/cancellation-watcher";
|
|
11
11
|
export { filterArrayByGlobMatchersSet, generateProjectFilters, generateProjectFiltersV2, } from "./utils";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAI/E,OAAO,EAAkB,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,+BAA+B,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EACL,+BAA+B,EAC/B,mBAAmB,EACnB,mBAAmB,EACnB,QAAQ,GACT,CAAC;AACF,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,8BAA8B,EAC9B,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAI/E,OAAO,EAAkB,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,+BAA+B,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EACL,+BAA+B,EAC/B,mBAAmB,EACnB,mBAAmB,EACnB,QAAQ,GACT,CAAC;AACF,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,aAAa,EACb,8BAA8B,EAC9B,wBAAwB,EACxB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,QAAQ,GACd,MAAM,oBAAoB,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,KAAK,mBAAmB,EACxB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,SAAS,CAAC;AAQjB,wBAAsB,aAAa,CAAC,EAClC,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,MAAM,EACN,MAAM,GACP,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;CAChC,GAAG,OAAO,CAAC;IACV,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,oBAAoB,CAAC;CACnC,CAAC,CAmBD;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IACnE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;CACjD,CAAC,CAeD"}
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.generateProjectFiltersV2 = exports.generateProjectFilters = exports.filterArrayByGlobMatchersSet = exports.startCancellationWatcher = exports.buildTestListFromFailedTestRun = exports.spawnCmd = exports.runSpecificTestsCmd = exports.parseTestListOutput = exports.getProjectsFromPlaywrightConfig = void 0;
|
|
20
|
+
exports.generateProjectFiltersV2 = exports.generateProjectFilters = exports.filterArrayByGlobMatchersSet = exports.startCancellationWatcher = exports.parseTestListLine = exports.normalizeTestLine = exports.getAllTestsForFile = exports.expandSerialDependencies = exports.buildTestListFromFailedTestRun = exports.buildTestList = exports.spawnCmd = exports.runSpecificTestsCmd = exports.parseTestListOutput = exports.getProjectsFromPlaywrightConfig = void 0;
|
|
21
21
|
exports.runSingleTest = runSingleTest;
|
|
22
22
|
exports.listProjectsAndTests = listProjectsAndTests;
|
|
23
23
|
const fs_1 = __importDefault(require("fs"));
|
|
@@ -31,7 +31,12 @@ Object.defineProperty(exports, "parseTestListOutput", { enumerable: true, get: f
|
|
|
31
31
|
const config_1 = require("./utils/config");
|
|
32
32
|
Object.defineProperty(exports, "getProjectsFromPlaywrightConfig", { enumerable: true, get: function () { return config_1.getProjectsFromPlaywrightConfig; } });
|
|
33
33
|
var failed_test_list_1 = require("./failed-test-list");
|
|
34
|
+
Object.defineProperty(exports, "buildTestList", { enumerable: true, get: function () { return failed_test_list_1.buildTestList; } });
|
|
34
35
|
Object.defineProperty(exports, "buildTestListFromFailedTestRun", { enumerable: true, get: function () { return failed_test_list_1.buildTestListFromFailedTestRun; } });
|
|
36
|
+
Object.defineProperty(exports, "expandSerialDependencies", { enumerable: true, get: function () { return failed_test_list_1.expandSerialDependencies; } });
|
|
37
|
+
Object.defineProperty(exports, "getAllTestsForFile", { enumerable: true, get: function () { return failed_test_list_1.getAllTestsForFile; } });
|
|
38
|
+
Object.defineProperty(exports, "normalizeTestLine", { enumerable: true, get: function () { return failed_test_list_1.normalizeTestLine; } });
|
|
39
|
+
Object.defineProperty(exports, "parseTestListLine", { enumerable: true, get: function () { return failed_test_list_1.parseTestListLine; } });
|
|
35
40
|
__exportStar(require("./glob-matcher"), exports);
|
|
36
41
|
var cancellation_watcher_1 = require("./lib/cancellation-watcher");
|
|
37
42
|
Object.defineProperty(exports, "startCancellationWatcher", { enumerable: true, get: function () { return cancellation_watcher_1.startCancellationWatcher; } });
|
package/dist/lib/cmd.js
CHANGED
|
@@ -122,9 +122,16 @@ async function spawnCmd(command, args, options) {
|
|
|
122
122
|
function setupProcessSignalHandlers(proc) {
|
|
123
123
|
const handleSignal = async (signal) => {
|
|
124
124
|
logger_1.logger.debug(`\nReceived ${signal}, gracefully shutting down...`);
|
|
125
|
-
if (proc && !proc.killed) {
|
|
126
|
-
// Forward the signal to the
|
|
127
|
-
|
|
125
|
+
if (proc && !proc.killed && proc.pid) {
|
|
126
|
+
// Forward the signal to the entire process group so all children
|
|
127
|
+
// (including Playwright workers and reporters) receive it
|
|
128
|
+
try {
|
|
129
|
+
process.kill(-proc.pid, signal);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// Process group may have already exited
|
|
133
|
+
proc.kill(signal);
|
|
134
|
+
}
|
|
128
135
|
// Wait for the child process to exit
|
|
129
136
|
await new Promise((resolve) => {
|
|
130
137
|
proc.once("exit", () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-specific-test.d.ts","sourceRoot":"","sources":["../../src/lib/run-specific-test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-specific-test.d.ts","sourceRoot":"","sources":["../../src/lib/run-specific-test.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAIlD,wBAAsB,mBAAmB,CAAC,EACxC,KAAU,EACV,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,OAAO,GACR,EAAE;IACD,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,YAAY,CAAC,CAkFxB"}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.runSpecificTestsCmd = runSpecificTestsCmd;
|
|
7
|
-
const
|
|
4
|
+
const failed_test_list_1 = require("../failed-test-list");
|
|
8
5
|
const utils_1 = require("../utils");
|
|
9
6
|
const run_all_tests_1 = require("./run-all-tests");
|
|
10
7
|
async function runSpecificTestsCmd({ tests = [], projects, passthroughArgs, envOverrides, repoDir, }) {
|
|
@@ -16,6 +13,7 @@ async function runSpecificTestsCmd({ tests = [], projects, passthroughArgs, envO
|
|
|
16
13
|
for (const testCase of tests) {
|
|
17
14
|
// TODO: Why do we have this getAllFilePaths call?
|
|
18
15
|
// TODO: Can we remove `dir` from the test case entity?
|
|
16
|
+
// TODO: After 1.57 is present in all repo, replace grep with --test-list
|
|
19
17
|
const files = await (0, utils_1.getAllFilePaths)(testCase.dir, repoDir, {
|
|
20
18
|
filePath: testCase.filePath,
|
|
21
19
|
});
|
|
@@ -43,24 +41,17 @@ async function runSpecificTestsCmd({ tests = [], projects, passthroughArgs, envO
|
|
|
43
41
|
else {
|
|
44
42
|
filesToRun.push(matchingFilePath);
|
|
45
43
|
}
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
suites: testCase.suites,
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
const parentDescribeName = (0, utils_1.getDescribeBlockName)(parentDescribe);
|
|
60
|
-
if (parentDescribeName) {
|
|
61
|
-
patternsToGrep.push(parentDescribeName);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
44
|
+
const serialInfo = await (0, failed_test_list_1.getSerialBlockInfo)({
|
|
45
|
+
file: matchingFilePath,
|
|
46
|
+
title: testCase.name,
|
|
47
|
+
suites: testCase.suites ?? [],
|
|
48
|
+
projectName: "",
|
|
49
|
+
}, repoDir, false);
|
|
50
|
+
if (!serialInfo) {
|
|
51
|
+
patternsToGrep.push(testCase.name);
|
|
52
|
+
}
|
|
53
|
+
else if (!serialInfo.isFileSerial && serialInfo.serialDescribeName) {
|
|
54
|
+
patternsToGrep.push(serialInfo.serialDescribeName);
|
|
64
55
|
}
|
|
65
56
|
}
|
|
66
57
|
const teardownLabels = await (0, utils_1.labelTeardownProjects)(projects, repoDir);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@empiricalrun/test-run",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "public"
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"minimatch": "^10.0.1",
|
|
38
38
|
"ts-morph": "^23.0.0",
|
|
39
39
|
"@empiricalrun/r2-uploader": "^0.9.1",
|
|
40
|
-
"@empiricalrun/reporter": "^0.28.
|
|
40
|
+
"@empiricalrun/reporter": "^0.28.1"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@playwright/test": "1.57.0",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { expect, test } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
test.describe("Serial Tests", () => {
|
|
4
|
+
test.describe.configure({ mode: "serial" });
|
|
5
|
+
|
|
6
|
+
test("Test 1 should pass", async () => {
|
|
7
|
+
expect(true).toBe(true);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("Test 2 should pass", async () => {
|
|
11
|
+
expect(1 + 1).toBe(2);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("Test 3 should fail", async () => {
|
|
15
|
+
expect(true).toBe(true);
|
|
16
|
+
});
|
|
17
|
+
});
|