@empiricalrun/playwright-utils 0.51.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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @empiricalrun/playwright-utils
2
2
 
3
+ ## 0.52.1
4
+
5
+ ### Patch Changes
6
+
7
+ - b17c77d: feat: new custom reporter for dependency groups
8
+
9
+ ## 0.52.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 73b88a2: fix: relative attachment for pw-utils
14
+
3
15
  ## 0.51.0
4
16
 
5
17
  ### Minor Changes
@@ -89,7 +89,7 @@ class AttachmentCleanup {
89
89
  _onEvict = null;
90
90
  constructor(limitBytes = getDefaultDiskLimitBytes()) {
91
91
  this._limitBytes = limitBytes;
92
- logger_1.logger.info(`[AttachmentCleanup] Initialized with limit: ${formatBytes(limitBytes)}`);
92
+ logger_1.logger.debug(`[AttachmentCleanup] Initialized with limit: ${formatBytes(limitBytes)}`);
93
93
  this._diskLogTimer = setInterval(() => {
94
94
  this._logDiskStatus();
95
95
  }, DISK_LOG_INTERVAL_MS);
@@ -139,7 +139,7 @@ class AttachmentCleanup {
139
139
  this._evictedCount++;
140
140
  this._evictedBytes += oldest.size;
141
141
  this._totalSize -= oldest.size;
142
- logger_1.logger.info(`[AttachmentCleanup] Evicted ${oldest.path} (${formatBytes(oldest.size)}), totalSize=${formatBytes(this._totalSize)}, pending=${this._pending.size}, uploaded=${this._uploaded.length}`);
142
+ logger_1.logger.debug(`[AttachmentCleanup] Evicted ${oldest.path} (${formatBytes(oldest.size)}), totalSize=${formatBytes(this._totalSize)}, pending=${this._pending.size}, uploaded=${this._uploaded.length}`);
143
143
  this._onEvict?.(oldest.path);
144
144
  }
145
145
  catch (err) {
@@ -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":"AAgBA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;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,CA2BD;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,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"}
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"}
@@ -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(), "incr-blob-test-"));
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__", 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
- ctx: { tempDir, blobDir, zipPath },
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
  */
@@ -43,6 +43,7 @@ export declare function filterSuiteByCompletedTests(suite: JsonSuite, completedT
43
43
  export declare function hasValidReport(reportLines: string[]): boolean;
44
44
  export declare function buildUrlsJson(attachmentUrlMap: Map<string, string>): Record<string, string>;
45
45
  export declare function isLocalTesting(): boolean;
46
+ export declare function toResourcePath(absolutePath: string): string;
46
47
  export declare function embedAttachment(attachmentPath: string | undefined, resultId: string, stagingDir: string): string | null;
47
48
  export {};
48
49
  //# sourceMappingURL=ibr-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ibr-utils.d.ts","sourceRoot":"","sources":["../../src/reporter/ibr-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAO3E,MAAM,MAAM,WAAW,GAAG;IACxB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC,CAAC;AAIF,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAChD,WAAW,EAAE,CAOf;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAO3E;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,EAC1B,IAAI,EAAE,QAAQ,GACb,MAAM,CAOR;AAID,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAIF,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvD,CAAC;AAIF,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,CAAC,YAAY,GAAG,SAAS,CAAC,EAAE,CAAC;CACvC,CAAC;AAIF,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,CAc3E;AAID,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAsBvE;AAMD;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,SAAS,EAChB,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,GAC5B,SAAS,GAAG,IAAI,CAmBlB;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAK7D;AAED,wBAAgB,aAAa,CAC3B,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMxB;AAED,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED,wBAAgB,eAAe,CAC7B,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,MAAM,GAAG,IAAI,CAkBf"}
1
+ {"version":3,"file":"ibr-utils.d.ts","sourceRoot":"","sources":["../../src/reporter/ibr-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAO3E,MAAM,MAAM,WAAW,GAAG;IACxB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC,CAAC;AAIF,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAChD,WAAW,EAAE,CAOf;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAO3E;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,EAC1B,IAAI,EAAE,QAAQ,GACb,MAAM,CAOR;AAID,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAIF,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvD,CAAC;AAIF,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,CAAC,YAAY,GAAG,SAAS,CAAC,EAAE,CAAC;CACvC,CAAC;AAIF,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,CAc3E;AAID,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAsBvE;AAMD;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,SAAS,EAChB,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,GAC5B,SAAS,GAAG,IAAI,CAmBlB;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAK7D;AAED,wBAAgB,aAAa,CAC3B,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMxB;AAED,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAI3D;AAED,wBAAgB,eAAe,CAC7B,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,MAAM,GAAG,IAAI,CAkBf"}
@@ -13,6 +13,7 @@ exports.filterSuiteByCompletedTests = filterSuiteByCompletedTests;
13
13
  exports.hasValidReport = hasValidReport;
14
14
  exports.buildUrlsJson = buildUrlsJson;
15
15
  exports.isLocalTesting = isLocalTesting;
16
+ exports.toResourcePath = toResourcePath;
16
17
  exports.embedAttachment = embedAttachment;
17
18
  const crypto_1 = __importDefault(require("crypto"));
18
19
  const fs_1 = __importDefault(require("fs"));
@@ -126,6 +127,11 @@ function buildUrlsJson(attachmentUrlMap) {
126
127
  function isLocalTesting() {
127
128
  return process.env.LOCAL_TEST === "true";
128
129
  }
130
+ function toResourcePath(absolutePath) {
131
+ const ext = path_1.default.extname(absolutePath);
132
+ const hash = crypto_1.default.createHash("sha1").update(absolutePath).digest("hex");
133
+ return `resources/${hash}${ext}`;
134
+ }
129
135
  function embedAttachment(attachmentPath, resultId, stagingDir) {
130
136
  if (!attachmentPath || !fs_1.default.existsSync(attachmentPath))
131
137
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"incremental-blob-reporter.d.ts","sourceRoot":"","sources":["../../src/reporter/incremental-blob-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACT,MAAM,2BAA2B,CAAC;AAuBnC;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEnD,cAAM,uBAAwB,YAAW,QAAQ;IAC/C,OAAO,CAAC,kBAAkB,CAAyB;IACnD,OAAO,CAAC,WAAW,CAIjB;IACF,OAAO,CAAC,UAAU,CAGhB;IACF,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,mBAAmB,CAA0B;IACrD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,YAAY,CAGN;IACd,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,gBAAgB,CAA8B;;IAetD,OAAO,CAAC,cAAc,CAA6B;IAEnD,OAAO,CAAC,mBAAmB;IA+B3B,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,qBAAqB;YASf,uBAAuB;IAqErC,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,8BAA8B;IAStC,OAAO,CAAC,mBAAmB;IAkB3B,OAAO,KAAK,QAAQ,GAKnB;IAED,OAAO,KAAK,UAAU,GAErB;IAED,OAAO,KAAK,aAAa,GAExB;IAED,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,aAAa;YAUP,SAAS;IAwBvB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAgB/C,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAIrD,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAyBnD,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAYrE,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAY7D,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB9C;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAI5D,aAAa,IAAI,OAAO;CAGzB;AAID,wBAAgB,0BAA0B,IAAI,uBAAuB,GAAG,IAAI,CAE3E;AAED,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,uBAAuB,GAChC,IAAI,CAEN;AAED,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"incremental-blob-reporter.d.ts","sourceRoot":"","sources":["../../src/reporter/incremental-blob-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACT,MAAM,2BAA2B,CAAC;AAwBnC;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEnD,cAAM,uBAAwB,YAAW,QAAQ;IAC/C,OAAO,CAAC,kBAAkB,CAAyB;IACnD,OAAO,CAAC,WAAW,CAIjB;IACF,OAAO,CAAC,UAAU,CAGhB;IACF,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,mBAAmB,CAA0B;IACrD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,YAAY,CAGN;IACd,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,gBAAgB,CAA8B;;IAetD,OAAO,CAAC,cAAc,CAA6B;IAEnD,OAAO,CAAC,mBAAmB;IA+B3B,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,qBAAqB;YASf,uBAAuB;IAqErC,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,8BAA8B;IAStC,OAAO,CAAC,mBAAmB;IAkB3B,OAAO,KAAK,QAAQ,GAKnB;IAED,OAAO,KAAK,UAAU,GAErB;IAED,OAAO,KAAK,aAAa,GAExB;IAED,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,aAAa;YAUP,SAAS;IAwBvB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAgB/C,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAIrD,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAyBnD,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAYrE,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAY7D,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB9C;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAI5D,aAAa,IAAI,OAAO;CAGzB;AAID,wBAAgB,0BAA0B,IAAI,uBAAuB,GAAG,IAAI,CAE3E;AAED,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,uBAAuB,GAChC,IAAI,CAEN;AAED,eAAe,uBAAuB,CAAC"}
@@ -265,7 +265,7 @@ class IncrementalBlobReporter {
265
265
  * Add a single attachment URL mapping
266
266
  */
267
267
  addAttachmentUrl(localPath, remoteUrl) {
268
- this._attachmentUrlMap.set(localPath, remoteUrl);
268
+ this._attachmentUrlMap.set((0, ibr_utils_1.toResourcePath)(localPath), remoteUrl);
269
269
  }
270
270
  printsToStdio() {
271
271
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle-events.d.ts","sourceRoot":"","sources":["../../src/reporter/lifecycle-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,UAAU,EACV,KAAK,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACT,MAAM,2BAA2B,CAAC;AAenC,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,KAAK,EACZ,iBAAiB,EAAE,MAAM,EACzB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,SAAS,EAAE,CAmDb;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,WAAW,EACpB,YAAY,EAAE,KAAK,EACnB,iBAAiB,EAAE,MAAM,GACxB,SAAS,CA+BX;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,SAAS,CAeX;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,UAAU,EAAE,MAAM,GACjB,SAAS,EAAE,CA+Cb;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,QAAQ,EACd,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,SAAS,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,GAC/B,SAAS,CAsBX;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,QAAQ,EACd,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,SAAS,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,GAC/B,SAAS,CAuBX;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAW7D"}
1
+ {"version":3,"file":"lifecycle-events.d.ts","sourceRoot":"","sources":["../../src/reporter/lifecycle-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,UAAU,EACV,KAAK,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACT,MAAM,2BAA2B,CAAC;AAgBnC,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,KAAK,EACZ,iBAAiB,EAAE,MAAM,EACzB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,SAAS,EAAE,CAmDb;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,WAAW,EACpB,YAAY,EAAE,KAAK,EACnB,iBAAiB,EAAE,MAAM,GACxB,SAAS,CA+BX;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,SAAS,CAeX;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,UAAU,EAAE,MAAM,GACjB,SAAS,EAAE,CAqDb;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,QAAQ,EACd,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,SAAS,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,GAC/B,SAAS,CAsBX;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,QAAQ,EACd,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,SAAS,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,GAC/B,SAAS,CAuBX;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAW7D"}
@@ -113,6 +113,13 @@ function buildOnTestEndEvents(test, result, resultIdMap, stagingDir) {
113
113
  // onAttach for each attachment (matching Playwright's blob format)
114
114
  for (const attachment of result.attachments) {
115
115
  const embeddedPath = (0, ibr_utils_1.embedAttachment)(attachment.path, resultId, stagingDir);
116
+ let attachmentPath;
117
+ if (embeddedPath) {
118
+ attachmentPath = embeddedPath;
119
+ }
120
+ else if (attachment.path) {
121
+ attachmentPath = (0, ibr_utils_1.toResourcePath)(attachment.path);
122
+ }
116
123
  events.push({
117
124
  method: "onAttach",
118
125
  params: {
@@ -122,7 +129,7 @@ function buildOnTestEndEvents(test, result, resultIdMap, stagingDir) {
122
129
  {
123
130
  name: attachment.name,
124
131
  contentType: attachment.contentType,
125
- path: embeddedPath ?? attachment.path,
132
+ path: attachmentPath,
126
133
  },
127
134
  ],
128
135
  },
@@ -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.51.0",
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": {
@@ -48,8 +56,8 @@
48
56
  "ts-morph": "^23.0.0",
49
57
  "@empiricalrun/cua": "^0.4.1",
50
58
  "@empiricalrun/dashboard-client": "^0.3.0",
51
- "@empiricalrun/llm": "^0.27.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": {
@@ -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"}