@empiricalrun/playwright-utils 0.52.0 → 0.52.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 +6 -0
- package/dist/reporter/harness.d.ts +9 -0
- package/dist/reporter/harness.d.ts.map +1 -1
- package/dist/reporter/harness.js +58 -5
- package/dist/reporter/test-case-sync-reporter.d.ts +12 -0
- package/dist/reporter/test-case-sync-reporter.d.ts.map +1 -0
- package/dist/reporter/test-case-sync-reporter.js +28 -0
- package/dist/reporter/test-case-sync.d.ts +28 -0
- package/dist/reporter/test-case-sync.d.ts.map +1 -0
- package/dist/reporter/test-case-sync.js +134 -0
- package/package.json +10 -2
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,10 @@ export interface IBRTestContext {
|
|
|
3
3
|
blobDir: string;
|
|
4
4
|
zipPath: string;
|
|
5
5
|
}
|
|
6
|
+
export interface TestCaseSyncTestContext {
|
|
7
|
+
tempDir: string;
|
|
8
|
+
outputPath: string;
|
|
9
|
+
}
|
|
6
10
|
export declare function sleep(ms: number): Promise<void>;
|
|
7
11
|
/**
|
|
8
12
|
* Sets up a temp directory with the IBR fixture files.
|
|
@@ -12,6 +16,10 @@ export declare function setupFixture(suite: string): Promise<{
|
|
|
12
16
|
ctx: IBRTestContext;
|
|
13
17
|
cleanup: () => Promise<void>;
|
|
14
18
|
}>;
|
|
19
|
+
export declare function setupTestCaseSyncFixture(suite: string): Promise<{
|
|
20
|
+
ctx: TestCaseSyncTestContext;
|
|
21
|
+
cleanup: () => Promise<void>;
|
|
22
|
+
}>;
|
|
15
23
|
/**
|
|
16
24
|
* Cleans blob artifacts from a previous run inside the same temp dir.
|
|
17
25
|
*/
|
|
@@ -31,6 +39,7 @@ export declare function runPlaywrightWithSigint(ctx: IBRTestContext, opts: {
|
|
|
31
39
|
workers: number;
|
|
32
40
|
waitFor: WaitFor;
|
|
33
41
|
}): Promise<RunResult>;
|
|
42
|
+
export declare function runPlaywrightList(ctx: TestCaseSyncTestContext): Promise<RunResult>;
|
|
34
43
|
export interface BlobEvent {
|
|
35
44
|
method: string;
|
|
36
45
|
params?: Record<string, unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/reporter/harness.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/reporter/harness.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAErD;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACzD,GAAG,EAAE,cAAc,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CAaD;AAqCD,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACrE,GAAG,EAAE,uBAAuB,CAAC;IAC7B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CAaD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAI3E;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,OAAO,GAAG,cAAc,GAAG,cAAc,CAAC;AAOtD;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC1C,OAAO,CAAC,SAAS,CAAC,CAiDpB;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,uBAAuB,GAC3B,OAAO,CAAC,SAAS,CAAC,CA6BpB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,SAAS,EAAE,CAAC,CAUtB"}
|
package/dist/reporter/harness.js
CHANGED
|
@@ -5,8 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.sleep = sleep;
|
|
7
7
|
exports.setupFixture = setupFixture;
|
|
8
|
+
exports.setupTestCaseSyncFixture = setupTestCaseSyncFixture;
|
|
8
9
|
exports.cleanBlobArtifacts = cleanBlobArtifacts;
|
|
9
10
|
exports.runPlaywrightWithSigint = runPlaywrightWithSigint;
|
|
11
|
+
exports.runPlaywrightList = runPlaywrightList;
|
|
10
12
|
exports.readBlobEvents = readBlobEvents;
|
|
11
13
|
const zip_1 = require("@empiricalrun/r2-uploader/zip");
|
|
12
14
|
const child_process_1 = require("child_process");
|
|
@@ -15,6 +17,7 @@ const os_1 = __importDefault(require("os"));
|
|
|
15
17
|
const path_1 = __importDefault(require("path"));
|
|
16
18
|
const TEST_DATA_DIR = path_1.default.resolve(__dirname, "../../test-data");
|
|
17
19
|
const REPORTER_PATH = path_1.default.resolve(__dirname, "../../dist/reporter/incremental-blob-reporter.js");
|
|
20
|
+
const TEST_CASE_SYNC_REPORTER_PATH = path_1.default.resolve(__dirname, "../../dist/reporter/test-case-sync-reporter.js");
|
|
18
21
|
const PLAYWRIGHT_BIN = path_1.default.resolve(__dirname, "../../node_modules/.bin/playwright");
|
|
19
22
|
async function sleep(ms) {
|
|
20
23
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -24,27 +27,52 @@ async function sleep(ms) {
|
|
|
24
27
|
* Returns a context object and a cleanup function.
|
|
25
28
|
*/
|
|
26
29
|
async function setupFixture(suite) {
|
|
30
|
+
const { tempDir, cleanup } = await setupReporterFixture({
|
|
31
|
+
suite,
|
|
32
|
+
reporterPath: REPORTER_PATH,
|
|
33
|
+
tempPrefix: "incr-blob-test-",
|
|
34
|
+
});
|
|
35
|
+
const blobDir = path_1.default.join(tempDir, "blob-report-incremental");
|
|
36
|
+
const zipPath = path_1.default.join(blobDir, "incremental-report-1.zip");
|
|
37
|
+
return {
|
|
38
|
+
ctx: { tempDir, blobDir, zipPath },
|
|
39
|
+
cleanup,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async function setupReporterFixture({ suite, reporterPath, tempPrefix, }) {
|
|
27
43
|
const fixtureDir = path_1.default.join(TEST_DATA_DIR, suite);
|
|
28
|
-
const tempDir = await fs_1.default.promises.mkdtemp(path_1.default.join(os_1.default.tmpdir(),
|
|
44
|
+
const tempDir = await fs_1.default.promises.mkdtemp(path_1.default.join(os_1.default.tmpdir(), tempPrefix));
|
|
29
45
|
const files = await fs_1.default.promises.readdir(fixtureDir);
|
|
30
46
|
for (const file of files) {
|
|
31
47
|
const src = path_1.default.join(fixtureDir, file);
|
|
32
48
|
const dest = path_1.default.join(tempDir, file);
|
|
33
49
|
if (file === "playwright.config.ts") {
|
|
34
50
|
const content = await fs_1.default.promises.readFile(src, "utf8");
|
|
35
|
-
await fs_1.default.promises.writeFile(dest, content.replace("__REPORTER_PATH__",
|
|
51
|
+
await fs_1.default.promises.writeFile(dest, content.replace("__REPORTER_PATH__", reporterPath));
|
|
36
52
|
}
|
|
37
53
|
else {
|
|
38
54
|
await fs_1.default.promises.copyFile(src, dest);
|
|
39
55
|
}
|
|
40
56
|
}
|
|
41
|
-
const blobDir = path_1.default.join(tempDir, "blob-report-incremental");
|
|
42
|
-
const zipPath = path_1.default.join(blobDir, "incremental-report-1.zip");
|
|
43
57
|
return {
|
|
44
|
-
|
|
58
|
+
tempDir,
|
|
45
59
|
cleanup: () => fs_1.default.promises.rm(tempDir, { recursive: true, force: true }),
|
|
46
60
|
};
|
|
47
61
|
}
|
|
62
|
+
async function setupTestCaseSyncFixture(suite) {
|
|
63
|
+
const { tempDir, cleanup } = await setupReporterFixture({
|
|
64
|
+
suite,
|
|
65
|
+
reporterPath: TEST_CASE_SYNC_REPORTER_PATH,
|
|
66
|
+
tempPrefix: "test-case-sync-",
|
|
67
|
+
});
|
|
68
|
+
return {
|
|
69
|
+
ctx: {
|
|
70
|
+
tempDir,
|
|
71
|
+
outputPath: path_1.default.join(tempDir, "test-case-sync.json"),
|
|
72
|
+
},
|
|
73
|
+
cleanup,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
48
76
|
/**
|
|
49
77
|
* Cleans blob artifacts from a previous run inside the same temp dir.
|
|
50
78
|
*/
|
|
@@ -108,6 +136,31 @@ async function runPlaywrightWithSigint(ctx, opts) {
|
|
|
108
136
|
});
|
|
109
137
|
return { stdout, stderr };
|
|
110
138
|
}
|
|
139
|
+
async function runPlaywrightList(ctx) {
|
|
140
|
+
const child = (0, child_process_1.spawn)(PLAYWRIGHT_BIN, ["test", "--list"], {
|
|
141
|
+
cwd: ctx.tempDir,
|
|
142
|
+
env: {
|
|
143
|
+
...process.env,
|
|
144
|
+
EMPIRICAL_TEST_CASE_SYNC_OUTPUT: ctx.outputPath,
|
|
145
|
+
},
|
|
146
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
147
|
+
});
|
|
148
|
+
let stdout = "";
|
|
149
|
+
let stderr = "";
|
|
150
|
+
child.stdout?.on("data", (data) => {
|
|
151
|
+
stdout += data.toString();
|
|
152
|
+
});
|
|
153
|
+
child.stderr?.on("data", (data) => {
|
|
154
|
+
stderr += data.toString();
|
|
155
|
+
});
|
|
156
|
+
const exitCode = await new Promise((resolve) => {
|
|
157
|
+
child.on("close", (code) => resolve(code));
|
|
158
|
+
});
|
|
159
|
+
if (exitCode !== 0) {
|
|
160
|
+
throw new Error(`playwright test --list failed with exit code ${exitCode}\n${stderr}`);
|
|
161
|
+
}
|
|
162
|
+
return { stdout, stderr };
|
|
163
|
+
}
|
|
111
164
|
/**
|
|
112
165
|
* Reads `report.jsonl` from the blob zip and returns parsed events.
|
|
113
166
|
*/
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FullConfig, Reporter, Suite } from "@playwright/test/reporter";
|
|
2
|
+
interface TestCaseSyncReporterOptions {
|
|
3
|
+
outputFile?: string;
|
|
4
|
+
}
|
|
5
|
+
declare class TestCaseSyncReporter implements Reporter {
|
|
6
|
+
private readonly outputFile;
|
|
7
|
+
constructor(options?: TestCaseSyncReporterOptions);
|
|
8
|
+
printsToStdio(): boolean;
|
|
9
|
+
onBegin(config: FullConfig, suite: Suite): void;
|
|
10
|
+
}
|
|
11
|
+
export default TestCaseSyncReporter;
|
|
12
|
+
//# sourceMappingURL=test-case-sync-reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-case-sync-reporter.d.ts","sourceRoot":"","sources":["../../src/reporter/test-case-sync-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAK7E,UAAU,2BAA2B;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,cAAM,oBAAqB,YAAW,QAAQ;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,OAAO,GAAE,2BAAgC;IAOrD,aAAa,IAAI,OAAO;IAIxB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;CAOhD;AAED,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const test_case_sync_1 = require("./test-case-sync");
|
|
9
|
+
class TestCaseSyncReporter {
|
|
10
|
+
outputFile;
|
|
11
|
+
constructor(options = {}) {
|
|
12
|
+
this.outputFile =
|
|
13
|
+
options.outputFile ||
|
|
14
|
+
process.env.EMPIRICAL_TEST_CASE_SYNC_OUTPUT ||
|
|
15
|
+
"test-case-sync.json";
|
|
16
|
+
}
|
|
17
|
+
printsToStdio() {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
onBegin(config, suite) {
|
|
21
|
+
const manifest = (0, test_case_sync_1.collectTestCaseSyncManifest)(config, suite);
|
|
22
|
+
fs_1.default.mkdirSync(path_1.default.dirname(path_1.default.resolve(this.outputFile)), {
|
|
23
|
+
recursive: true,
|
|
24
|
+
});
|
|
25
|
+
fs_1.default.writeFileSync(this.outputFile, JSON.stringify(manifest, null, 2));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.default = TestCaseSyncReporter;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { FullConfig, Suite } from "@playwright/test/reporter";
|
|
2
|
+
export interface TestCaseSyncTestCase {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
file_path: string;
|
|
6
|
+
suites: string[];
|
|
7
|
+
playwright_project: string;
|
|
8
|
+
tags: string[];
|
|
9
|
+
}
|
|
10
|
+
export interface TestCaseDependencyGroupMember {
|
|
11
|
+
test_case_id: string;
|
|
12
|
+
dependency_order: number;
|
|
13
|
+
}
|
|
14
|
+
export interface TestCaseDependencyGroup {
|
|
15
|
+
id: string;
|
|
16
|
+
kind: "playwright_serial";
|
|
17
|
+
file_path: string;
|
|
18
|
+
title_path: string[];
|
|
19
|
+
playwright_project: string;
|
|
20
|
+
members: TestCaseDependencyGroupMember[];
|
|
21
|
+
}
|
|
22
|
+
export interface TestCaseSyncManifest {
|
|
23
|
+
version: 1;
|
|
24
|
+
test_cases: TestCaseSyncTestCase[];
|
|
25
|
+
dependency_groups: TestCaseDependencyGroup[];
|
|
26
|
+
}
|
|
27
|
+
export declare function collectTestCaseSyncManifest(config: FullConfig, rootSuite: Suite): TestCaseSyncManifest;
|
|
28
|
+
//# sourceMappingURL=test-case-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-case-sync.d.ts","sourceRoot":"","sources":["../../src/reporter/test-case-sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EAEV,KAAK,EAEN,MAAM,2BAA2B,CAAC;AAMnC,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,6BAA6B;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,mBAAmB,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,6BAA6B,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,CAAC,CAAC;IACX,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,iBAAiB,EAAE,uBAAuB,EAAE,CAAC;CAC9C;AA+JD,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,KAAK,GACf,oBAAoB,CAuBtB"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.collectTestCaseSyncManifest = collectTestCaseSyncManifest;
|
|
7
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
function getSuiteParallelMode(suite) {
|
|
10
|
+
const mode = suite._parallelMode;
|
|
11
|
+
return mode === "none" ||
|
|
12
|
+
mode === "default" ||
|
|
13
|
+
mode === "serial" ||
|
|
14
|
+
mode === "parallel"
|
|
15
|
+
? mode
|
|
16
|
+
: "none";
|
|
17
|
+
}
|
|
18
|
+
function toPosixPath(value) {
|
|
19
|
+
return value.split(path_1.default.sep).join("/");
|
|
20
|
+
}
|
|
21
|
+
function relativePath(rootDir, file) {
|
|
22
|
+
return toPosixPath(path_1.default.relative(rootDir, file));
|
|
23
|
+
}
|
|
24
|
+
function normalizeTags(tags) {
|
|
25
|
+
return tags.map((tag) => (tag.startsWith("@") ? tag.slice(1) : tag));
|
|
26
|
+
}
|
|
27
|
+
function projectNameFor(test) {
|
|
28
|
+
return test.parent.project()?.name ?? "";
|
|
29
|
+
}
|
|
30
|
+
function filePathForTest(rootDir, test) {
|
|
31
|
+
return relativePath(rootDir, test.location.file);
|
|
32
|
+
}
|
|
33
|
+
function stableGroupId(input) {
|
|
34
|
+
const hash = crypto_1.default
|
|
35
|
+
.createHash("sha1")
|
|
36
|
+
.update(JSON.stringify([
|
|
37
|
+
input.projectName,
|
|
38
|
+
input.filePath,
|
|
39
|
+
input.titlePath,
|
|
40
|
+
input.line,
|
|
41
|
+
input.column,
|
|
42
|
+
]))
|
|
43
|
+
.digest("hex");
|
|
44
|
+
return `playwright_serial:${hash}`;
|
|
45
|
+
}
|
|
46
|
+
function collectDirectTestCases(rootDir, suite, state) {
|
|
47
|
+
return suite.tests.map((test) => ({
|
|
48
|
+
id: test.id,
|
|
49
|
+
name: test.title,
|
|
50
|
+
file_path: filePathForTest(rootDir, test),
|
|
51
|
+
suites: state.suites,
|
|
52
|
+
playwright_project: projectNameFor(test),
|
|
53
|
+
tags: normalizeTags(test.tags),
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
function collectOutermostSerialGroup(rootDir, suite, state) {
|
|
57
|
+
if (state.serialAncestor || getSuiteParallelMode(suite) !== "serial") {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
const tests = suite.allTests();
|
|
61
|
+
if (tests.length < 2) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const firstTest = tests[0];
|
|
65
|
+
if (!firstTest) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const filePath = filePathForTest(rootDir, firstTest);
|
|
69
|
+
const projectName = projectNameFor(firstTest);
|
|
70
|
+
const titlePath = state.suites;
|
|
71
|
+
const location = suite.location ?? firstTest.location;
|
|
72
|
+
return {
|
|
73
|
+
id: stableGroupId({
|
|
74
|
+
projectName,
|
|
75
|
+
filePath,
|
|
76
|
+
titlePath,
|
|
77
|
+
line: location.line,
|
|
78
|
+
column: location.column,
|
|
79
|
+
}),
|
|
80
|
+
kind: "playwright_serial",
|
|
81
|
+
file_path: filePath,
|
|
82
|
+
title_path: titlePath,
|
|
83
|
+
playwright_project: projectName,
|
|
84
|
+
members: tests.map((test, index) => ({
|
|
85
|
+
test_case_id: test.id,
|
|
86
|
+
dependency_order: index,
|
|
87
|
+
})),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function walkSuite(rootDir, suite, state, testCases, dependencyGroups) {
|
|
91
|
+
const isDescribe = suite.type === "describe";
|
|
92
|
+
const suites = isDescribe ? [...state.suites, suite.title] : state.suites;
|
|
93
|
+
const nextState = { ...state, suites };
|
|
94
|
+
const serialGroup = collectOutermostSerialGroup(rootDir, suite, nextState);
|
|
95
|
+
if (serialGroup) {
|
|
96
|
+
dependencyGroups.push(serialGroup);
|
|
97
|
+
nextState.serialAncestor = suite;
|
|
98
|
+
}
|
|
99
|
+
testCases.push(...collectDirectTestCases(rootDir, suite, nextState));
|
|
100
|
+
for (const child of suite.suites) {
|
|
101
|
+
const childState = { ...nextState };
|
|
102
|
+
if (child.type === "project") {
|
|
103
|
+
const project = child.project();
|
|
104
|
+
childState.projectName = project?.name ?? child.title;
|
|
105
|
+
}
|
|
106
|
+
else if (child.type === "file") {
|
|
107
|
+
const firstTest = child.allTests()[0];
|
|
108
|
+
childState.filePath = firstTest
|
|
109
|
+
? filePathForTest(rootDir, firstTest)
|
|
110
|
+
: child.location
|
|
111
|
+
? relativePath(rootDir, child.location.file)
|
|
112
|
+
: "";
|
|
113
|
+
childState.suites = [];
|
|
114
|
+
childState.serialAncestor = null;
|
|
115
|
+
}
|
|
116
|
+
walkSuite(rootDir, child, childState, testCases, dependencyGroups);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function collectTestCaseSyncManifest(config, rootSuite) {
|
|
120
|
+
const testCases = [];
|
|
121
|
+
const dependencyGroups = [];
|
|
122
|
+
const rootProject = rootSuite.project();
|
|
123
|
+
walkSuite(config.rootDir, rootSuite, {
|
|
124
|
+
projectName: rootProject?.name ?? "",
|
|
125
|
+
filePath: "",
|
|
126
|
+
suites: [],
|
|
127
|
+
serialAncestor: null,
|
|
128
|
+
}, testCases, dependencyGroups);
|
|
129
|
+
return {
|
|
130
|
+
version: 1,
|
|
131
|
+
test_cases: testCases,
|
|
132
|
+
dependency_groups: dependencyGroups,
|
|
133
|
+
};
|
|
134
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@empiricalrun/playwright-utils",
|
|
3
|
-
"version": "0.52.
|
|
3
|
+
"version": "0.52.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "public"
|
|
@@ -14,6 +14,14 @@
|
|
|
14
14
|
"./test": {
|
|
15
15
|
"types": "./dist/test/index.d.ts",
|
|
16
16
|
"default": "./dist/test/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./test-case-sync": {
|
|
19
|
+
"types": "./dist/reporter/test-case-sync.d.ts",
|
|
20
|
+
"default": "./dist/reporter/test-case-sync.js"
|
|
21
|
+
},
|
|
22
|
+
"./test-case-sync-reporter": {
|
|
23
|
+
"types": "./dist/reporter/test-case-sync-reporter.d.ts",
|
|
24
|
+
"default": "./dist/reporter/test-case-sync-reporter.js"
|
|
17
25
|
}
|
|
18
26
|
},
|
|
19
27
|
"repository": {
|
|
@@ -47,9 +55,9 @@
|
|
|
47
55
|
"rimraf": "^6.0.1",
|
|
48
56
|
"ts-morph": "^23.0.0",
|
|
49
57
|
"@empiricalrun/cua": "^0.4.1",
|
|
50
|
-
"@empiricalrun/llm": "^0.27.0",
|
|
51
58
|
"@empiricalrun/dashboard-client": "^0.3.0",
|
|
52
59
|
"@empiricalrun/r2-uploader": "^0.9.1",
|
|
60
|
+
"@empiricalrun/llm": "^0.27.0",
|
|
53
61
|
"@empiricalrun/reporter": "^0.29.1"
|
|
54
62
|
},
|
|
55
63
|
"scripts": {
|
package/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/email.ts","./src/inbox-client.ts","./src/index.ts","./src/kv.ts","./src/logger.ts","./src/mailosaur-client.ts","./src/playwright-extensions.ts","./src/postgres.ts","./src/telemetry.ts","./src/types.ts","./src/webhook.ts","./src/auth/google.ts","./src/auth/index.ts","./src/auth/types.ts","./src/captcha/index.ts","./src/config/index.ts","./src/config/proxy.ts","./src/config/devices/types.ts","./src/overlay-tests/cache.spec.ts","./src/overlay-tests/click.spec.ts","./src/overlay-tests/fixtures.ts","./src/overlay-tests/patch.spec.ts","./src/overlay-tests/visual.spec.ts","./src/reporter/attachment-cleanup-test-reporter.ts","./src/reporter/attachment-cleanup.ts","./src/reporter/blob-utils.ts","./src/reporter/empirical-reporter.ts","./src/reporter/failing-line.ts","./src/reporter/harness.ts","./src/reporter/ibr-utils.ts","./src/reporter/incremental-blob-reporter.ts","./src/reporter/lifecycle-events.ts","./src/reporter/local-test.ts","./src/reporter/reporter-state.ts","./src/reporter/uploader.ts","./src/reporter/util.ts","./src/test/constants.ts","./src/test/coverage.ts","./src/test/index.ts","./src/test/types.ts","./src/test/video-labels.ts","./src/test/expect/index.ts","./src/test/expect/types.ts","./src/test/expect/visual.ts","./src/test/expect/webhook.ts","./src/test/scripts/agent-capabilities.ts","./src/test/scripts/index.ts","./src/test/scripts/locator-highlights.ts","./src/test/scripts/locator-vision.ts","./src/test/scripts/mouse-pointer.ts","./src/test/scripts/types.ts","./src/test/scripts/pw-locator-patch/dismiss-overlays/cache.ts","./src/test/scripts/pw-locator-patch/dismiss-overlays/index.ts","./src/test/scripts/pw-locator-patch/dismiss-overlays/prompt.ts","./src/test/scripts/pw-locator-patch/dismiss-overlays/types.ts","./src/test/scripts/pw-locator-patch/dismiss-overlays/utils.ts","./src/test/scripts/pw-locator-patch/highlight/click.ts","./src/test/scripts/pw-locator-patch/highlight/expect.ts","./src/test/scripts/pw-locator-patch/highlight/hover.ts","./src/test/scripts/pw-locator-patch/highlight/inner-text.ts","./src/test/scripts/pw-locator-patch/highlight/input-value.ts","./src/test/scripts/pw-locator-patch/highlight/is-checked.ts","./src/test/scripts/pw-locator-patch/highlight/is-disabled.ts","./src/test/scripts/pw-locator-patch/highlight/is-editable.ts","./src/test/scripts/pw-locator-patch/highlight/text-content.ts","./src/test/scripts/pw-locator-patch/utils/index.ts","./src/test/scripts/pw-locator-patch/vision/query.ts"],"version":"5.8.3"}
|
|
1
|
+
{"root":["./src/email.ts","./src/inbox-client.ts","./src/index.ts","./src/kv.ts","./src/logger.ts","./src/mailosaur-client.ts","./src/playwright-extensions.ts","./src/postgres.ts","./src/telemetry.ts","./src/types.ts","./src/webhook.ts","./src/auth/google.ts","./src/auth/index.ts","./src/auth/types.ts","./src/captcha/index.ts","./src/config/index.ts","./src/config/proxy.ts","./src/config/devices/types.ts","./src/overlay-tests/cache.spec.ts","./src/overlay-tests/click.spec.ts","./src/overlay-tests/fixtures.ts","./src/overlay-tests/patch.spec.ts","./src/overlay-tests/visual.spec.ts","./src/reporter/attachment-cleanup-test-reporter.ts","./src/reporter/attachment-cleanup.ts","./src/reporter/blob-utils.ts","./src/reporter/empirical-reporter.ts","./src/reporter/failing-line.ts","./src/reporter/harness.ts","./src/reporter/ibr-utils.ts","./src/reporter/incremental-blob-reporter.ts","./src/reporter/lifecycle-events.ts","./src/reporter/local-test.ts","./src/reporter/reporter-state.ts","./src/reporter/test-case-sync-reporter.ts","./src/reporter/test-case-sync.ts","./src/reporter/uploader.ts","./src/reporter/util.ts","./src/test/constants.ts","./src/test/coverage.ts","./src/test/index.ts","./src/test/types.ts","./src/test/video-labels.ts","./src/test/expect/index.ts","./src/test/expect/types.ts","./src/test/expect/visual.ts","./src/test/expect/webhook.ts","./src/test/scripts/agent-capabilities.ts","./src/test/scripts/index.ts","./src/test/scripts/locator-highlights.ts","./src/test/scripts/locator-vision.ts","./src/test/scripts/mouse-pointer.ts","./src/test/scripts/types.ts","./src/test/scripts/pw-locator-patch/dismiss-overlays/cache.ts","./src/test/scripts/pw-locator-patch/dismiss-overlays/index.ts","./src/test/scripts/pw-locator-patch/dismiss-overlays/prompt.ts","./src/test/scripts/pw-locator-patch/dismiss-overlays/types.ts","./src/test/scripts/pw-locator-patch/dismiss-overlays/utils.ts","./src/test/scripts/pw-locator-patch/highlight/click.ts","./src/test/scripts/pw-locator-patch/highlight/expect.ts","./src/test/scripts/pw-locator-patch/highlight/hover.ts","./src/test/scripts/pw-locator-patch/highlight/inner-text.ts","./src/test/scripts/pw-locator-patch/highlight/input-value.ts","./src/test/scripts/pw-locator-patch/highlight/is-checked.ts","./src/test/scripts/pw-locator-patch/highlight/is-disabled.ts","./src/test/scripts/pw-locator-patch/highlight/is-editable.ts","./src/test/scripts/pw-locator-patch/highlight/text-content.ts","./src/test/scripts/pw-locator-patch/utils/index.ts","./src/test/scripts/pw-locator-patch/vision/query.ts"],"version":"5.8.3"}
|