@qualflare/playwright 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -105,6 +105,12 @@ Every option has an environment-variable override, and everything has a sensible
105
105
  [`docs/CONFIGURATION.md`](./docs/CONFIGURATION.md). There is no `token` option: this reporter makes
106
106
  no requests, so it has no credential.
107
107
 
108
+ One option is worth calling out because it fails late: `environment` is matched against the
109
+ environment's **uid (slug)**, not its display name, so **Staging** in the UI is `staging` here. A
110
+ wrong value cannot fail at test time — the reporter makes no requests — so the run succeeds and
111
+ `collect` 404s afterwards. See
112
+ [the note in the configuration docs](./docs/CONFIGURATION.md#environment-is-matched-by-uid-not-display-name).
113
+
108
114
  ## Known limitations
109
115
 
110
116
  - **Traces are not uploaded.** Playwright traces are `application/zip`, which Qualflare's attachment
@@ -113,9 +119,9 @@ no requests, so it has no credential.
113
119
  - **`pw:api` and `fixture` steps are filtered out by default** (`includeApiSteps`) — a single
114
120
  browser test emits hundreds, which buries the steps you actually wrote. A *failed* one is always
115
121
  kept.
116
- - **`outputDir` is merged blindly** — `qf collect` uploads every report file it finds, with no
117
- run-identity check, so a directory left over from a previous run is silently merged into the
118
- current one. Clear it at the start of each run.
122
+ - **A stale `outputDir` is refused, not merged** — each report carries a `runId`, and `qf collect`
123
+ errors rather than merging files from two different runs. Needs `@qualflare/cli` v0.1.19+; older
124
+ CLIs merge as before.
119
125
  - **`merge-reports` mode is not supported** in v0.1.0 — use the `outputDir` flow above rather than
120
126
  Playwright's `blob` reporter.
121
127
 
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ReporterDescription } from '@playwright/test';
2
- import { L as LinkType, C as CasePriority, Q as QualflarePlaywrightOptions } from './resolve-config-CSjXFl7v.cjs';
3
- export { A as Attachment, a as Case, b as CaseStatus, c as Collect, F as FrameworkCategory, d as Label, e as Link, M as Metadata, N as NanosecondDuration, P as Parameter, f as Platform, R as ResolvedReporterConfig, S as Step, g as Suite } from './resolve-config-CSjXFl7v.cjs';
2
+ import { L as LinkType, C as CasePriority, Q as QualflarePlaywrightOptions } from './resolve-config-CQe-oDpg.cjs';
3
+ export { A as Attachment, a as Case, b as CaseStatus, c as Collect, F as FrameworkCategory, d as Label, e as Link, M as Metadata, N as NanosecondDuration, P as Parameter, f as Platform, R as ResolvedReporterConfig, S as Step, g as Suite } from './resolve-config-CQe-oDpg.cjs';
4
4
 
5
5
  /**
6
6
  * Author-facing metadata API. Import it in a spec and annotate tests with
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ReporterDescription } from '@playwright/test';
2
- import { L as LinkType, C as CasePriority, Q as QualflarePlaywrightOptions } from './resolve-config-CSjXFl7v.js';
3
- export { A as Attachment, a as Case, b as CaseStatus, c as Collect, F as FrameworkCategory, d as Label, e as Link, M as Metadata, N as NanosecondDuration, P as Parameter, f as Platform, R as ResolvedReporterConfig, S as Step, g as Suite } from './resolve-config-CSjXFl7v.js';
2
+ import { L as LinkType, C as CasePriority, Q as QualflarePlaywrightOptions } from './resolve-config-CQe-oDpg.js';
3
+ export { A as Attachment, a as Case, b as CaseStatus, c as Collect, F as FrameworkCategory, d as Label, e as Link, M as Metadata, N as NanosecondDuration, P as Parameter, f as Platform, R as ResolvedReporterConfig, S as Step, g as Suite } from './resolve-config-CQe-oDpg.js';
4
4
 
5
5
  /**
6
6
  * Author-facing metadata API. Import it in a spec and annotate tests with
@@ -35,10 +35,13 @@ __export(reporter_exports, {
35
35
  module.exports = __toCommonJS(reporter_exports);
36
36
 
37
37
  // src/reporter/reporter.ts
38
- var import_node_crypto2 = require("crypto");
38
+ var import_node_crypto3 = require("crypto");
39
39
  var fs3 = __toESM(require("fs"), 1);
40
40
  var path3 = __toESM(require("path"), 1);
41
41
 
42
+ // src/config/resolve-config.ts
43
+ var import_node_crypto = require("crypto");
44
+
42
45
  // src/shared/constants.ts
43
46
  var RESERVED_MESSAGE_MEDIA_TYPE = "application/vnd.qualflare.message+json";
44
47
  var MAX_SUITES_PER_LAUNCH = 2e3;
@@ -68,6 +71,7 @@ var PROVIDERS = [
68
71
  detect: (env) => env.GITHUB_ACTIONS === "true",
69
72
  providerName: "GitHub Actions",
70
73
  buildNumber: (env) => nonEmpty(env.GITHUB_RUN_NUMBER),
74
+ runId: (env) => nonEmpty(env.GITHUB_RUN_ID),
71
75
  runUrl: (env) => env.GITHUB_SERVER_URL && env.GITHUB_REPOSITORY && env.GITHUB_RUN_ID ? `${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}/actions/runs/${env.GITHUB_RUN_ID}` : void 0,
72
76
  prNumber: (env) => {
73
77
  const match = /^refs\/pull\/(\d+)\/merge$/.exec(env.GITHUB_REF ?? "");
@@ -78,6 +82,7 @@ var PROVIDERS = [
78
82
  detect: (env) => env.GITLAB_CI === "true",
79
83
  providerName: "GitLab CI",
80
84
  buildNumber: (env) => nonEmpty(env.CI_PIPELINE_IID),
85
+ runId: (env) => nonEmpty(env.CI_PIPELINE_ID),
81
86
  runUrl: (env) => nonEmpty(env.CI_PIPELINE_URL),
82
87
  prNumber: (env) => parsePositiveInt(env.CI_MERGE_REQUEST_IID)
83
88
  },
@@ -85,6 +90,7 @@ var PROVIDERS = [
85
90
  detect: (env) => env.CIRCLECI === "true",
86
91
  providerName: "CircleCI",
87
92
  buildNumber: (env) => nonEmpty(env.CIRCLE_BUILD_NUM),
93
+ runId: (env) => nonEmpty(env.CIRCLE_WORKFLOW_ID ?? env.CIRCLE_BUILD_NUM),
88
94
  runUrl: (env) => nonEmpty(env.CIRCLE_BUILD_URL),
89
95
  prNumber: (env) => parsePositiveInt(env.CIRCLE_PR_NUMBER)
90
96
  },
@@ -92,6 +98,7 @@ var PROVIDERS = [
92
98
  detect: (env) => env.BUILDKITE === "true",
93
99
  providerName: "Buildkite",
94
100
  buildNumber: (env) => nonEmpty(env.BUILDKITE_BUILD_NUMBER),
101
+ runId: (env) => nonEmpty(env.BUILDKITE_BUILD_ID),
95
102
  runUrl: (env) => nonEmpty(env.BUILDKITE_BUILD_URL),
96
103
  prNumber: (env) => {
97
104
  const raw = env.BUILDKITE_PULL_REQUEST;
@@ -107,6 +114,7 @@ var PROVIDERS = [
107
114
  detect: (env) => Boolean(env.JENKINS_URL),
108
115
  providerName: "Jenkins",
109
116
  buildNumber: (env) => nonEmpty(env.BUILD_NUMBER),
117
+ runId: (env) => nonEmpty(env.BUILD_TAG ?? env.BUILD_NUMBER),
110
118
  runUrl: (env) => nonEmpty(env.BUILD_URL)
111
119
  // Jenkins has no standardized PR-number env var across its many PR
112
120
  // plugins (Multibranch, GitHub Branch Source, etc.) — deliberately
@@ -116,6 +124,7 @@ var PROVIDERS = [
116
124
  detect: (env) => env.TF_BUILD === "True" || env.TF_BUILD === "true",
117
125
  providerName: "Azure Pipelines",
118
126
  buildNumber: (env) => nonEmpty(env.BUILD_BUILDID),
127
+ runId: (env) => nonEmpty(env.BUILD_BUILDID),
119
128
  runUrl: (env) => {
120
129
  const collectionUri = env.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI;
121
130
  const project = env.SYSTEM_TEAMPROJECT;
@@ -131,6 +140,7 @@ var PROVIDERS = [
131
140
  detect: (env) => Boolean(env.BITBUCKET_BUILD_NUMBER),
132
141
  providerName: "Bitbucket Pipelines",
133
142
  buildNumber: (env) => nonEmpty(env.BITBUCKET_BUILD_NUMBER),
143
+ runId: (env) => nonEmpty(env.BITBUCKET_BUILD_NUMBER),
134
144
  runUrl: (env) => {
135
145
  const origin = env.BITBUCKET_GIT_HTTP_ORIGIN;
136
146
  if (!origin) {
@@ -152,6 +162,8 @@ function detectCi(env = process.env) {
152
162
  if (runUrl !== void 0) result.ciRunUrl = runUrl;
153
163
  const prNumber = provider.prNumber?.(env);
154
164
  if (prNumber !== void 0) result.ciPrNumber = prNumber;
165
+ const runId = provider.runId?.(env);
166
+ if (runId !== void 0) result.ciRunId = runId;
155
167
  return result;
156
168
  }
157
169
  if (ciInfo.name) {
@@ -241,6 +253,7 @@ function resolveConfig(options, deps = {}) {
241
253
  const ciBuildNumber = options.ciBuildNumber ?? detectedCi.ciBuildNumber;
242
254
  const ciRunUrl = options.ciRunUrl ?? detectedCi.ciRunUrl;
243
255
  const ciPrNumber = options.ciPrNumber ?? detectedCi.ciPrNumber;
256
+ const runId = options.runId ?? firstEnv2("QUALFLARE_RUN_ID") ?? detectedCi.ciRunId ?? (0, import_node_crypto.randomUUID)();
244
257
  return {
245
258
  // `||` (truthy check), not `??`, for these three REQUIRED-non-empty wire
246
259
  // fields — an explicit `''` option must not silently win over the
@@ -260,6 +273,7 @@ function resolveConfig(options, deps = {}) {
260
273
  ciBuildNumber,
261
274
  ciRunUrl,
262
275
  ciPrNumber,
276
+ runId,
263
277
  attachScreenshots: options.attachScreenshots ?? envBool("QUALFLARE_ATTACH_SCREENSHOTS") ?? true,
264
278
  includeApiSteps: options.includeApiSteps ?? envBool("QUALFLARE_INCLUDE_API_STEPS") ?? false,
265
279
  maxAttachmentBytes: options.maxAttachmentBytes ?? envInt("QUALFLARE_MAX_ATTACHMENT_BYTES") ?? 15e5,
@@ -295,7 +309,7 @@ var fs2 = __toESM(require("fs"), 1);
295
309
  // src/reporter/video-writer.ts
296
310
  var fs = __toESM(require("fs"), 1);
297
311
  var path = __toESM(require("path"), 1);
298
- var import_node_crypto = require("crypto");
312
+ var import_node_crypto2 = require("crypto");
299
313
  var VIDEO_MIME_TYPES_BY_EXTENSION = {
300
314
  ".mp4": "video/mp4",
301
315
  ".webm": "video/webm",
@@ -321,7 +335,7 @@ function copyVideoAttachment(filePath, outputDir, maxVideoBytes) {
321
335
  );
322
336
  return void 0;
323
337
  }
324
- const localVideoPath = `${(0, import_node_crypto.randomUUID)()}${ext}`;
338
+ const localVideoPath = `${(0, import_node_crypto2.randomUUID)()}${ext}`;
325
339
  try {
326
340
  fs.mkdirSync(outputDir, { recursive: true });
327
341
  fs.copyFileSync(filePath, path.join(outputDir, localVideoPath));
@@ -722,7 +736,7 @@ function buildCase(test, config, attachmentsByResult, budget) {
722
736
  var os = __toESM(require("os"), 1);
723
737
 
724
738
  // src/config/version.ts
725
- var PACKAGE_VERSION = "0.1.0";
739
+ var PACKAGE_VERSION = "0.2.0";
726
740
 
727
741
  // src/reporter/collect-builder.ts
728
742
  function resolveOs(config) {
@@ -751,7 +765,8 @@ function buildCollectPayload(suites, config, browsers = []) {
751
765
  metadata: {
752
766
  version: PACKAGE_VERSION,
753
767
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
754
- cliName: "qualflare-playwright"
768
+ cliName: "qualflare-playwright",
769
+ runId: config.runId
755
770
  },
756
771
  properties: config.properties,
757
772
  suites,
@@ -901,7 +916,7 @@ var QualflareReporter = class {
901
916
  }
902
917
  const outputDir = this.resolveOutputDir(config.outputDir);
903
918
  fs3.mkdirSync(outputDir, { recursive: true });
904
- const outputPath = path3.join(outputDir, `${(0, import_node_crypto2.randomUUID)()}.json`);
919
+ const outputPath = path3.join(outputDir, `${(0, import_node_crypto3.randomUUID)()}.json`);
905
920
  fs3.writeFileSync(outputPath, JSON.stringify(collect));
906
921
  logger.info(`wrote Collect payload to ${outputPath} \u2014 run \`qualflare-cli collect ${outputDir}\` to upload it.`);
907
922
  }