@kinora/vitest-reporter 0.5.0 → 0.6.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/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { AttachmentKind, CiMeta, GitMeta } from "@kinora/core";
1
+ import { AttachmentKind, CiMeta, GitMeta, PrCommentOption, PrStatusOption } from "@kinora/core";
2
2
  import { Reporter, TestModule, Vitest } from "vitest/node";
3
3
  type IncludeTests = 'browser' | 'all';
4
4
  export interface KinoraVitestReporterOptions {
@@ -28,6 +28,18 @@ export interface KinoraVitestReporterOptions {
28
28
  * tell the legs apart. `false` uploads each shard as its own run.
29
29
  */
30
30
  groupKey?: string | false;
31
+ /**
32
+ * Post/update a summary comment on the GitHub PR (uses the job's GITHUB_TOKEN; needs
33
+ * `permissions: pull-requests: write`) or the GitLab MR (needs a GITLAB_TOKEN CI variable with
34
+ * the `api` scope). `label` distinguishes matrix legs sharing one PR.
35
+ */
36
+ prComment?: PrCommentOption;
37
+ /**
38
+ * Set a `kinora / <project>` commit status on the GitHub PR (needs `permissions: statuses: write`)
39
+ * or the GitLab MR pipeline (GITLAB_TOKEN with the Developer role): red only for tests newly
40
+ * failing vs the base branch. `label` distinguishes matrix legs, defaulting to the `prComment` one.
41
+ */
42
+ prStatus?: PrStatusOption;
31
43
  }
32
44
  export default class KinoraVitestReporter implements Reporter {
33
45
  private readonly options;
@@ -37,5 +49,6 @@ export default class KinoraVitestReporter implements Reporter {
37
49
  onInit(vitest: Vitest): void;
38
50
  onTestRunStart(): void;
39
51
  onTestRunEnd(modules: ReadonlyArray<TestModule>): Promise<void>;
52
+ private maybePostToPr;
40
53
  }
41
54
  export {};
package/dist/index.mjs CHANGED
@@ -1,6 +1,7 @@
1
+ import { readFileSync } from "node:fs";
1
2
  import { readFile } from "node:fs/promises";
2
3
  import process from "node:process";
3
- import { DEFAULT_KINORA_URL, DEFAULT_UPLOAD_ATTACHMENTS, IngestError, MAX_A11Y_NODES, MAX_A11Y_VIOLATIONS, STORY_ANNOTATION, artifactsToUpload, axeViolations, createIngestClient, describeRetry, detectCiEnv, makeTestKey, resolveShardGroup, stripAnsi, uploadArtifacts } from "@kinora/core";
4
+ import { DEFAULT_KINORA_URL, DEFAULT_UPLOAD_ATTACHMENTS, IngestError, MAX_A11Y_NODES, MAX_A11Y_VIOLATIONS, STORY_ANNOTATION, artifactsToUpload, axeViolations, createIngestClient, describeRetry, detectCiEnv, flakyTestsOf, makeTestKey, postToPr, prLegLabel, resolvePrContext, resolvePrReportOptions, resolveShardGroup, stripAnsi, uploadArtifacts } from "@kinora/core";
4
5
  // src/convert.ts
5
6
  function identity(test) {
6
7
  const file = test.module.relativeModuleId;
@@ -203,7 +204,11 @@ var KinoraVitestReporter = class {
203
204
  return;
204
205
  }
205
206
  const { tests, skippedNodeTests } = toNormTests(modules, this.options.include);
206
- const group = this.shard && this.options.groupKey !== false ? resolveShardGroup(process.env, { groupKey: this.options.groupKey }) : void 0;
207
+ const prOptions = resolvePrReportOptions(this.options.prComment, this.options.prStatus);
208
+ const group = this.shard && this.options.groupKey !== false ? resolveShardGroup(process.env, {
209
+ groupKey: this.options.groupKey,
210
+ leg: prLegLabel(prOptions)
211
+ }) : void 0;
207
212
  if (!tests.length) {
208
213
  if (!group) {
209
214
  console.warn(skippedNodeTests ? `[kinora] nothing uploaded: no browser tests in this run (${skippedNodeTests} Node tests left out). Set include: 'all' to upload Node tests too.` : "[kinora] nothing uploaded: no tests ran");
@@ -234,6 +239,7 @@ var KinoraVitestReporter = class {
234
239
  const client = createIngestClient({
235
240
  baseUrl: url,
236
241
  token,
242
+ regression: !!(prOptions.comment || prOptions.status),
237
243
  onRetry: (info) => console.warn(`[kinora] ${describeRetry(info)}`)
238
244
  });
239
245
  const res = await client.uploadRun(payload);
@@ -242,10 +248,42 @@ var KinoraVitestReporter = class {
242
248
  onFailed: (a, err) => console.warn(`[kinora] ${a.name} upload failed for ${a.testKey}:`, err instanceof Error ? err.message : err)
243
249
  });
244
250
  console.log(`[kinora] uploaded ${res.tests} tests + ${artifacts} artifacts (run ${res.runId}${res.shardProgress ? `, ${res.shardProgress.landed} of ${res.shardProgress.total} shards` : ""})`);
251
+ if (res.incident) console.warn(`[kinora] environment incident, not counted: ${res.incident.reason}`);
252
+ await this.maybePostToPr(prOptions, payload, res);
245
253
  } catch (err) {
246
254
  if (err instanceof IngestError && err.status === 402) console.warn(`[kinora] ${err.message}`);
247
255
  else console.error("[kinora] upload failed:", err instanceof Error ? err.message : err);
248
256
  }
249
257
  }
258
+ async maybePostToPr(opts, payload, res) {
259
+ if (!opts.comment && !opts.status) return;
260
+ if (this.shard && !res.shardProgress) return;
261
+ const ctx = resolvePrContext(process.env, (p) => {
262
+ try {
263
+ return readFileSync(p, "utf8");
264
+ } catch {
265
+ return;
266
+ }
267
+ });
268
+ if (!ctx) return;
269
+ await postToPr(ctx, opts, {
270
+ projectSlug: payload.project.slug,
271
+ projectName: payload.project.name,
272
+ runUrl: res.runUrl,
273
+ ciRunUrl: payload.run.ci?.runUrl,
274
+ counts: res.counts ?? payload.run.counts,
275
+ regression: res.regression,
276
+ flaky: res.flaky ?? flakyTestsOf(payload.tests),
277
+ baseBranch: payload.run.git?.baseBranch,
278
+ ...res.shardProgress && { shards: {
279
+ runId: res.runId,
280
+ ...res.shardProgress
281
+ } },
282
+ ...res.incident && { incident: res.incident }
283
+ }, {
284
+ info: (m) => console.warn(`[kinora] ${m}`),
285
+ warn: (m) => console.warn(`[kinora] ${m}`)
286
+ });
287
+ }
250
288
  };
251
289
  export { KinoraVitestReporter as default };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kinora/vitest-reporter",
3
3
  "type": "module",
4
- "version": "0.5.0",
4
+ "version": "0.6.0",
5
5
  "description": "Vitest reporter that uploads browser-mode and Storybook test results to a kinora server",
6
6
  "author": "Joris Gallot",
7
7
  "license": "MIT",
@@ -37,7 +37,7 @@
37
37
  "vitest": ">=4.1.12"
38
38
  },
39
39
  "dependencies": {
40
- "@kinora/core": "0.16.0"
40
+ "@kinora/core": "0.18.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^26.6.6",