@checkly/playwright-reporter 1.0.0 → 1.0.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 ADDED
@@ -0,0 +1,49 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@checkly/playwright-reporter` will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+
7
+ ## 1.0.1 (2026-01-19)
8
+
9
+ ### Fixed
10
+
11
+ - Sharded test execution now works correctly when using `playwright merge-reports` command. Due to a Playwright limitation, `config.projects` is empty after merging blob reports - the reporter now reconstructs project information from the test suite structure.
12
+ - Default projects (when no explicit projects are defined in playwright.config.ts) now preserve their empty name correctly instead of being renamed to "default".
13
+
14
+ ## 1.0.0 (2025-01-19)
15
+
16
+ First stable release of the rewritten Playwright reporter with extension-based architecture.
17
+
18
+ ### Added
19
+
20
+ - **Extension-based architecture** - Modular design allows for composable functionality
21
+ - **Broad Playwright support** - Compatible with Playwright versions 1.40 through 1.57+
22
+ - **Drop-in JSON replacement** - Fully compatible with Playwright's native JSON reporter output format
23
+ - **Trace extraction** - Automatically extracts console messages and network requests from Playwright trace files
24
+ - **Checkly integration** - Automatic upload to Checkly Test Sessions when credentials are configured
25
+ - **New `createChecklyReporter()` function** - Better intellisense support in `playwright.config.ts`
26
+ - **Unified `outputDir` option** - Single option for all output files (JSON report, ZIP assets)
27
+ - **Verbose logging** - Debug mode for troubleshooting report generation
28
+
29
+ ### Changed
30
+
31
+ - `outputFile` option is deprecated - use `outputDir` instead (JSON written to `{outputDir}/checkly-report.json`)
32
+ - `testResultsDir` option is deprecated - use `outputDir` instead
33
+ - `outputPath` option is deprecated - ZIP written to `{outputDir}/checkly-report.zip`
34
+
35
+ ### Migration from 0.x
36
+
37
+ ```diff
38
+ // playwright.config.ts
39
+ +import { createChecklyReporter } from '@checkly/playwright-reporter'
40
+
41
+ export default defineConfig({
42
+ reporter: [
43
+ - ['@checkly/playwright-reporter', { outputFile: 'results/report.json' }],
44
+ + createChecklyReporter({ outputDir: 'results' }),
45
+ ],
46
+ })
47
+ ```
48
+
49
+ The legacy 0.x reporter remains available via `npm install @checkly/playwright-reporter@legacy`.
package/dist/index.d.ts CHANGED
@@ -247,6 +247,7 @@ declare class BaseReporter implements Reporter {
247
247
  private _report;
248
248
  private extensions;
249
249
  private summaryLines;
250
+ private reconstructedProjects;
250
251
  constructor(options?: BaseReporterOptions);
251
252
  protected use(extension: Extension$1): this;
252
253
  private log;
@@ -264,6 +265,17 @@ declare class BaseReporter implements Reporter {
264
265
  printsToStdio(): boolean;
265
266
  getReport(): JSONReport;
266
267
  private buildReport;
268
+ /**
269
+ * Reconstructs projects from the suite structure when config.projects is empty.
270
+ * This handles the merge-reports scenario where Playwright doesn't populate
271
+ * config.projects but still provides project information via suite.project().
272
+ */
273
+ private reconstructProjectsIfNeeded;
274
+ /**
275
+ * Recursively collects project information from test cases in the suite.
276
+ * Fallback for when suite.project() doesn't provide project info.
277
+ */
278
+ private collectProjectsFromTests;
267
279
  private serializeConfig;
268
280
  private serializeProject;
269
281
  /**
@@ -289,6 +301,11 @@ declare class BaseReporter implements Reporter {
289
301
  */
290
302
  private extractTags;
291
303
  private serializeTest;
304
+ /**
305
+ * Get the project name for a test case, handling merge-reports scenarios
306
+ * where project() may not be available in the expected way.
307
+ */
308
+ private getProjectName;
292
309
  private serializeTestResult;
293
310
  private serializeStep;
294
311
  private serializeError;
package/dist/index.js CHANGED
@@ -1855,6 +1855,8 @@ var BaseReporter = class {
1855
1855
  _report = null;
1856
1856
  extensions = [];
1857
1857
  summaryLines = [];
1858
+ // Reconstructed projects for merge-reports scenarios
1859
+ reconstructedProjects = /* @__PURE__ */ new Map();
1858
1860
  constructor(options = {}) {
1859
1861
  this.options = options;
1860
1862
  this.verbose = options.verbose ?? process.env.CHECKLY_REPORTER_VERBOSE === "true";
@@ -1889,8 +1891,10 @@ var BaseReporter = class {
1889
1891
  this.flakyCount = 0;
1890
1892
  this.skippedCount = 0;
1891
1893
  this._report = null;
1894
+ this.reconstructedProjects.clear();
1895
+ this.reconstructProjectsIfNeeded();
1892
1896
  const testCount = this.countTests(suite);
1893
- const projectNames = config.projects.map((p) => p.name).join(", ");
1897
+ const projectNames = config.projects.length > 0 ? config.projects.map((p) => p.name).join(", ") : Array.from(this.reconstructedProjects.keys()).join(", ") || "default";
1894
1898
  this.log(`\u{1F3AC} Starting test run`, { tests: testCount, projects: projectNames, workers: config.workers });
1895
1899
  for (const ext of this.extensions) {
1896
1900
  ext.onBegin?.({ config, suite, log: this.createExtensionLogger(ext.name) });
@@ -2022,8 +2026,86 @@ var BaseReporter = class {
2022
2026
  }
2023
2027
  };
2024
2028
  }
2029
+ /**
2030
+ * Reconstructs projects from the suite structure when config.projects is empty.
2031
+ * This handles the merge-reports scenario where Playwright doesn't populate
2032
+ * config.projects but still provides project information via suite.project().
2033
+ */
2034
+ reconstructProjectsIfNeeded() {
2035
+ if (this.config.projects.length > 0) {
2036
+ return;
2037
+ }
2038
+ this.log("\u{1F504} Detected merge-reports scenario (empty config.projects), reconstructing projects");
2039
+ for (const projectSuite of this.suite.suites) {
2040
+ const project = projectSuite.project();
2041
+ if (project) {
2042
+ const name = project.name || "default";
2043
+ if (!this.reconstructedProjects.has(name)) {
2044
+ this.reconstructedProjects.set(name, {
2045
+ id: name,
2046
+ name,
2047
+ testDir: project.testDir,
2048
+ outputDir: project.outputDir,
2049
+ timeout: project.timeout,
2050
+ retries: project.retries,
2051
+ repeatEach: project.repeatEach,
2052
+ metadata: project.metadata ?? {},
2053
+ testMatch: Array.isArray(project.testMatch) ? project.testMatch.map(String) : [String(project.testMatch)],
2054
+ testIgnore: Array.isArray(project.testIgnore) ? project.testIgnore.map(String) : [String(project.testIgnore)]
2055
+ });
2056
+ }
2057
+ }
2058
+ }
2059
+ if (this.reconstructedProjects.size === 0) {
2060
+ this.collectProjectsFromTests(this.suite);
2061
+ }
2062
+ this.log("\u{1F504} Reconstructed projects", {
2063
+ count: this.reconstructedProjects.size,
2064
+ names: Array.from(this.reconstructedProjects.keys())
2065
+ });
2066
+ }
2067
+ /**
2068
+ * Recursively collects project information from test cases in the suite.
2069
+ * Fallback for when suite.project() doesn't provide project info.
2070
+ */
2071
+ collectProjectsFromTests(suite) {
2072
+ for (const test of suite.allTests()) {
2073
+ const project = test.parent.project();
2074
+ const projectName = project?.name || "default";
2075
+ if (!this.reconstructedProjects.has(projectName)) {
2076
+ if (project) {
2077
+ this.reconstructedProjects.set(projectName, {
2078
+ id: projectName,
2079
+ name: projectName,
2080
+ testDir: project.testDir,
2081
+ outputDir: project.outputDir,
2082
+ timeout: project.timeout,
2083
+ retries: project.retries,
2084
+ repeatEach: project.repeatEach,
2085
+ metadata: project.metadata ?? {},
2086
+ testMatch: Array.isArray(project.testMatch) ? project.testMatch.map(String) : [String(project.testMatch)],
2087
+ testIgnore: Array.isArray(project.testIgnore) ? project.testIgnore.map(String) : [String(project.testIgnore)]
2088
+ });
2089
+ } else {
2090
+ this.reconstructedProjects.set(projectName, {
2091
+ id: projectName,
2092
+ name: projectName,
2093
+ testDir: "",
2094
+ outputDir: "",
2095
+ timeout: 0,
2096
+ retries: 0,
2097
+ repeatEach: 1,
2098
+ metadata: {},
2099
+ testMatch: [],
2100
+ testIgnore: []
2101
+ });
2102
+ }
2103
+ }
2104
+ }
2105
+ }
2025
2106
  serializeConfig() {
2026
2107
  const c = this.config;
2108
+ const projects = c.projects.length > 0 ? c.projects.map((p) => this.serializeProject(p)) : Array.from(this.reconstructedProjects.values());
2027
2109
  return {
2028
2110
  rootDir: c.rootDir,
2029
2111
  configFile: c.configFile ?? void 0,
@@ -2034,7 +2116,7 @@ var BaseReporter = class {
2034
2116
  globalTimeout: c.globalTimeout,
2035
2117
  maxFailures: c.maxFailures,
2036
2118
  metadata: c.metadata ?? {},
2037
- projects: c.projects.map((p) => this.serializeProject(p)),
2119
+ projects,
2038
2120
  shard: c.shard ?? null,
2039
2121
  tags: c.tags ?? [],
2040
2122
  updateSourceMethod: c.updateSourceMethod,
@@ -2162,9 +2244,10 @@ var BaseReporter = class {
2162
2244
  }
2163
2245
  serializeTest(data) {
2164
2246
  const { testCase, results } = data;
2247
+ const projectName = this.getProjectName(testCase);
2165
2248
  return {
2166
- projectId: testCase.parent.project()?.name ?? "default",
2167
- projectName: testCase.parent.project()?.name ?? "default",
2249
+ projectId: projectName,
2250
+ projectName,
2168
2251
  timeout: testCase.timeout,
2169
2252
  expectedStatus: testCase.expectedStatus,
2170
2253
  annotations: this.serializeAnnotations(testCase.annotations),
@@ -2172,6 +2255,25 @@ var BaseReporter = class {
2172
2255
  status: this.mapOutcome(testCase.outcome())
2173
2256
  };
2174
2257
  }
2258
+ /**
2259
+ * Get the project name for a test case, handling merge-reports scenarios
2260
+ * where project() may not be available in the expected way.
2261
+ */
2262
+ getProjectName(testCase) {
2263
+ const project = testCase.parent.project();
2264
+ if (project && typeof project.name === "string") {
2265
+ return project.name;
2266
+ }
2267
+ let current = testCase.parent;
2268
+ while (current) {
2269
+ const suiteProject = current.project();
2270
+ if (suiteProject && typeof suiteProject.name === "string") {
2271
+ return suiteProject.name;
2272
+ }
2273
+ current = current.parent;
2274
+ }
2275
+ return "default";
2276
+ }
2175
2277
  serializeTestResult(r) {
2176
2278
  return {
2177
2279
  workerIndex: r.workerIndex,
@@ -2255,9 +2357,9 @@ var BaseReporter = class {
2255
2357
  printSummary() {
2256
2358
  const pkgVersion = getPackageVersion();
2257
2359
  const playwrightVersion = this.config.version;
2258
- const projects = this.config.projects;
2259
- const projectNames = projects.map((p) => p.name).join(", ");
2260
- const rule = pluralRules.select(projects.length);
2360
+ const projectNames = this.config.projects.length > 0 ? this.config.projects.map((p) => p.name).join(", ") : Array.from(this.reconstructedProjects.keys()).join(", ") || "default";
2361
+ const projectCount = this.config.projects.length > 0 ? this.config.projects.length : this.reconstructedProjects.size || 1;
2362
+ const rule = pluralRules.select(projectCount);
2261
2363
  console.log("\n======================================================\n");
2262
2364
  console.log(`\u{1F99D} Checkly reporter: ${pkgVersion}`);
2263
2365
  console.log(`\u{1F3AD} Playwright: ${playwrightVersion}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkly/playwright-reporter",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Standalone Playwright reporter for Checkly - compatible with Playwright 1.40-1.57+",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -8,6 +8,7 @@
8
8
  "files": [
9
9
  "dist",
10
10
  "README.md",
11
+ "CHANGELOG.md",
11
12
  "LICENSE"
12
13
  ],
13
14
  "keywords": [
@@ -35,7 +36,7 @@
35
36
  "tsup": "8.5.1",
36
37
  "tsx": "4.19.0",
37
38
  "typescript": "5.9.3",
38
- "@checkly/reporter-utils": "1.0.0"
39
+ "@checkly/reporter-utils": "1.0.1"
39
40
  },
40
41
  "scripts": {
41
42
  "build": "tsup",