@vera-ci/playwright-reporter 0.1.0-beta.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/dist/detector.d.ts +7 -0
- package/dist/detector.d.ts.map +1 -0
- package/dist/detector.js +56 -0
- package/dist/detector.js.map +1 -0
- package/dist/git.d.ts +4 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +19 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +5 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +26 -0
- package/dist/logger.js.map +1 -0
- package/dist/reporter.d.ts +15 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +176 -0
- package/dist/reporter.js.map +1 -0
- package/dist/types.d.ts +52 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/uploader.d.ts +19 -0
- package/dist/uploader.d.ts.map +1 -0
- package/dist/uploader.js +123 -0
- package/dist/uploader.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type CiProvider = "github_actions" | "circleci" | "gitlab" | "local";
|
|
2
|
+
export declare function detectCiProvider(): CiProvider | undefined;
|
|
3
|
+
export declare function detectBranch(): string | undefined;
|
|
4
|
+
export declare function detectCommitSha(): string | undefined;
|
|
5
|
+
export declare function detectPullRequestNumber(): number | undefined;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../src/detector.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,GAAG,gBAAgB,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAC;AAErE,wBAAgB,gBAAgB,IAAI,UAAU,GAAG,SAAS,CAKzD;AAED,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAQjD;AAED,wBAAgB,eAAe,IAAI,MAAM,GAAG,SAAS,CAQpD;AAED,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,SAAS,CAqB5D"}
|
package/dist/detector.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export function detectCiProvider() {
|
|
2
|
+
if (process.env.GITHUB_ACTIONS)
|
|
3
|
+
return "github_actions";
|
|
4
|
+
if (process.env.CIRCLECI)
|
|
5
|
+
return "circleci";
|
|
6
|
+
if (process.env.GITLAB_CI)
|
|
7
|
+
return "gitlab";
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
export function detectBranch() {
|
|
11
|
+
// GitHub Actions
|
|
12
|
+
if (process.env.GITHUB_REF_NAME)
|
|
13
|
+
return process.env.GITHUB_REF_NAME;
|
|
14
|
+
// CircleCI
|
|
15
|
+
if (process.env.CIRCLE_BRANCH)
|
|
16
|
+
return process.env.CIRCLE_BRANCH;
|
|
17
|
+
// GitLab
|
|
18
|
+
if (process.env.CI_COMMIT_REF_NAME)
|
|
19
|
+
return process.env.CI_COMMIT_REF_NAME;
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
export function detectCommitSha() {
|
|
23
|
+
// GitHub Actions
|
|
24
|
+
if (process.env.GITHUB_SHA)
|
|
25
|
+
return process.env.GITHUB_SHA;
|
|
26
|
+
// CircleCI
|
|
27
|
+
if (process.env.CIRCLE_SHA1)
|
|
28
|
+
return process.env.CIRCLE_SHA1;
|
|
29
|
+
// GitLab
|
|
30
|
+
if (process.env.CI_COMMIT_SHA)
|
|
31
|
+
return process.env.CI_COMMIT_SHA;
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
export function detectPullRequestNumber() {
|
|
35
|
+
// GitHub Actions
|
|
36
|
+
const ghPr = process.env.GITHUB_PR_NUMBER;
|
|
37
|
+
if (ghPr)
|
|
38
|
+
return parseInt(ghPr, 10) || undefined;
|
|
39
|
+
// GitHub Actions — parse from GITHUB_REF (refs/pull/123/merge)
|
|
40
|
+
const ghRef = process.env.GITHUB_REF;
|
|
41
|
+
if (ghRef) {
|
|
42
|
+
const match = ghRef.match(/^refs\/pull\/(\d+)\//);
|
|
43
|
+
if (match)
|
|
44
|
+
return parseInt(match[1], 10);
|
|
45
|
+
}
|
|
46
|
+
// CircleCI
|
|
47
|
+
const circlePr = process.env.CIRCLE_PR_NUMBER;
|
|
48
|
+
if (circlePr)
|
|
49
|
+
return parseInt(circlePr, 10) || undefined;
|
|
50
|
+
// GitLab
|
|
51
|
+
const gitlabMr = process.env.CI_MERGE_REQUEST_IID;
|
|
52
|
+
if (gitlabMr)
|
|
53
|
+
return parseInt(gitlabMr, 10) || undefined;
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detector.js","sourceRoot":"","sources":["../src/detector.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB;IAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,gBAAgB,CAAC;IACxD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ;QAAE,OAAO,UAAU,CAAC;IAC5C,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC3C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,iBAAiB;IACjB,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IACpE,WAAW;IACX,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAChE,SAAS;IACT,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAC1E,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,iBAAiB;IACjB,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;IAC1D,WAAW;IACX,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IAC5D,SAAS;IACT,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAChE,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,iBAAiB;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC1C,IAAI,IAAI;QAAE,OAAO,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC;IAEjD,+DAA+D;IAC/D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;IACrC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAClD,IAAI,KAAK;YAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,WAAW;IACX,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC9C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC;IAEzD,SAAS;IACT,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAClD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC;IAEzD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
package/dist/git.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAUA,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAEjD;AAED,wBAAgB,eAAe,IAAI,MAAM,GAAG,SAAS,CAEpD;AAED,wBAAgB,mBAAmB,IAAI,MAAM,GAAG,SAAS,CAExD"}
|
package/dist/git.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
function exec(cmd) {
|
|
3
|
+
try {
|
|
4
|
+
return execSync(cmd, { encoding: "utf-8", timeout: 5000 }).trim() || undefined;
|
|
5
|
+
}
|
|
6
|
+
catch {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function getGitBranch() {
|
|
11
|
+
return exec("git rev-parse --abbrev-ref HEAD");
|
|
12
|
+
}
|
|
13
|
+
export function getGitCommitSha() {
|
|
14
|
+
return exec("git rev-parse HEAD");
|
|
15
|
+
}
|
|
16
|
+
export function getGitCommitMessage() {
|
|
17
|
+
return exec("git log -1 --pretty=%s");
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,SAAS,IAAI,CAAC,GAAW;IACvB,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;IACjF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC,iCAAiC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,oBAAoB,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,CAAC,wBAAwB,CAAC,CAAC;AACxC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,QAAQ,GACT,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAU/B,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { UploadResult, RunStats } from "./types.js";
|
|
2
|
+
export declare function printUploading(): void;
|
|
3
|
+
export declare function printSuccess(result: UploadResult, stats: RunStats): void;
|
|
4
|
+
export declare function printWarning(message: string, hint?: string): void;
|
|
5
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEzD,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI,CAiBxE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAMjE"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function printUploading() {
|
|
2
|
+
console.log("\n [Vera] Uploading results...");
|
|
3
|
+
}
|
|
4
|
+
export function printSuccess(result, stats) {
|
|
5
|
+
const parts = [
|
|
6
|
+
`${stats.total} tests`,
|
|
7
|
+
`${stats.passed} passed`,
|
|
8
|
+
`${stats.failed} failed`,
|
|
9
|
+
`${stats.snapshots} snapshots`,
|
|
10
|
+
];
|
|
11
|
+
console.log(`\n \u2713 [Vera] Run uploaded successfully`);
|
|
12
|
+
console.log(` \u2192 ${parts.join(" \u00b7 ")}`);
|
|
13
|
+
if (stats.flaky > 0) {
|
|
14
|
+
console.log(` \u2192 ${stats.flaky} flaky`);
|
|
15
|
+
}
|
|
16
|
+
console.log(` \u2192 ${result.url}`);
|
|
17
|
+
console.log();
|
|
18
|
+
}
|
|
19
|
+
export function printWarning(message, hint) {
|
|
20
|
+
console.warn(`\n \u26a0 [Vera] ${message}`);
|
|
21
|
+
if (hint) {
|
|
22
|
+
console.warn(` ${hint}`);
|
|
23
|
+
}
|
|
24
|
+
console.warn();
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAoB,EAAE,KAAe;IAChE,MAAM,KAAK,GAAG;QACZ,GAAG,KAAK,CAAC,KAAK,QAAQ;QACtB,GAAG,KAAK,CAAC,MAAM,SAAS;QACxB,GAAG,KAAK,CAAC,MAAM,SAAS;QACxB,GAAG,KAAK,CAAC,SAAS,YAAY;KAC/B,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAEpD,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,CAAC,KAAK,QAAQ,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,IAAa;IACzD,OAAO,CAAC,IAAI,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;IAC7C,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,CAAC,IAAI,EAAE,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Reporter, TestCase, TestResult, FullConfig, Suite, FullResult } from "@playwright/test/reporter";
|
|
2
|
+
import type { VeraReporterOptions } from "./types.js";
|
|
3
|
+
declare class VeraReporter implements Reporter {
|
|
4
|
+
private options;
|
|
5
|
+
private tests;
|
|
6
|
+
private startTime;
|
|
7
|
+
constructor(options: VeraReporterOptions);
|
|
8
|
+
onBegin(_config: FullConfig, _suite: Suite): void;
|
|
9
|
+
onTestEnd(test: TestCase, result: TestResult): void;
|
|
10
|
+
onEnd(_result: FullResult): Promise<void>;
|
|
11
|
+
private buildReportJson;
|
|
12
|
+
private computeStats;
|
|
13
|
+
}
|
|
14
|
+
export default VeraReporter;
|
|
15
|
+
//# sourceMappingURL=reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,UAAU,EACV,KAAK,EACL,UAAU,EACX,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EACV,mBAAmB,EAGpB,MAAM,YAAY,CAAC;AAWpB,cAAM,YAAa,YAAW,QAAQ;IACpC,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,SAAS,CAAK;gBAEV,OAAO,EAAE,mBAAmB;IAUxC,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,GAAG,IAAI;IAyBjD,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IA2B7C,KAAK,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAgD/C,OAAO,CAAC,eAAe;IAgDvB,OAAO,CAAC,YAAY;CAsCrB;AAED,eAAe,YAAY,CAAC"}
|
package/dist/reporter.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { detectCiProvider, detectBranch, detectCommitSha, detectPullRequestNumber, } from "./detector.js";
|
|
2
|
+
import { getGitBranch, getGitCommitSha, getGitCommitMessage } from "./git.js";
|
|
3
|
+
import { printUploading, printSuccess, printWarning } from "./logger.js";
|
|
4
|
+
import { uploadRun } from "./uploader.js";
|
|
5
|
+
class VeraReporter {
|
|
6
|
+
options;
|
|
7
|
+
tests = [];
|
|
8
|
+
startTime = 0;
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.options = {
|
|
11
|
+
uploadTraces: true,
|
|
12
|
+
uploadVideos: true,
|
|
13
|
+
failOnUploadError: false,
|
|
14
|
+
printSummary: true,
|
|
15
|
+
...options,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
onBegin(_config, _suite) {
|
|
19
|
+
this.startTime = Date.now();
|
|
20
|
+
const apiKey = this.options.apiKey || process.env.VERA_API_KEY;
|
|
21
|
+
const projectId = this.options.projectId || process.env.VERA_PROJECT_ID;
|
|
22
|
+
if (!apiKey) {
|
|
23
|
+
printWarning("Missing API key", "Set apiKey in reporter options or VERA_API_KEY env var");
|
|
24
|
+
}
|
|
25
|
+
if (!projectId) {
|
|
26
|
+
printWarning("Missing project ID", "Set projectId in reporter options or VERA_PROJECT_ID env var");
|
|
27
|
+
}
|
|
28
|
+
// Allow env vars to fill in options
|
|
29
|
+
if (!this.options.apiKey && apiKey)
|
|
30
|
+
this.options.apiKey = apiKey;
|
|
31
|
+
if (!this.options.projectId && projectId)
|
|
32
|
+
this.options.projectId = projectId;
|
|
33
|
+
}
|
|
34
|
+
onTestEnd(test, result) {
|
|
35
|
+
const suite = test.titlePath().slice(0, -1).join(" > ");
|
|
36
|
+
this.tests.push({
|
|
37
|
+
title: test.title,
|
|
38
|
+
suite,
|
|
39
|
+
status: result.status,
|
|
40
|
+
duration: result.duration,
|
|
41
|
+
ok: test.ok(),
|
|
42
|
+
retries: result.retry,
|
|
43
|
+
errors: result.errors.map((e) => ({
|
|
44
|
+
message: e.message,
|
|
45
|
+
stack: e.stack,
|
|
46
|
+
})),
|
|
47
|
+
annotations: result.annotations.map((a) => ({
|
|
48
|
+
type: a.type,
|
|
49
|
+
description: a.description,
|
|
50
|
+
})),
|
|
51
|
+
attachments: result.attachments.map((a) => ({
|
|
52
|
+
name: a.name,
|
|
53
|
+
contentType: a.contentType,
|
|
54
|
+
path: a.path,
|
|
55
|
+
body: a.body ? Buffer.from(a.body) : undefined,
|
|
56
|
+
})),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async onEnd(_result) {
|
|
60
|
+
if (!this.options.apiKey || !this.options.projectId) {
|
|
61
|
+
printWarning("Skipping upload — missing API key or project ID");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// Build report JSON (Playwright-compatible structure)
|
|
65
|
+
const reportJson = this.buildReportJson();
|
|
66
|
+
const stats = this.computeStats();
|
|
67
|
+
// Resolve CI/git info
|
|
68
|
+
const ciProvider = detectCiProvider();
|
|
69
|
+
const branch = this.options.branch || detectBranch() || getGitBranch();
|
|
70
|
+
const commitSha = this.options.commitSha || detectCommitSha() || getGitCommitSha();
|
|
71
|
+
const commitMessage = this.options.commitMessage || getGitCommitMessage();
|
|
72
|
+
const pullRequestNumber = this.options.pullRequestNumber ?? detectPullRequestNumber();
|
|
73
|
+
const pullRequestUrl = this.options.pullRequestUrl;
|
|
74
|
+
if (this.options.printSummary !== false) {
|
|
75
|
+
printUploading();
|
|
76
|
+
}
|
|
77
|
+
const result = await uploadRun({
|
|
78
|
+
options: this.options,
|
|
79
|
+
reportJson,
|
|
80
|
+
tests: this.tests,
|
|
81
|
+
ciProvider,
|
|
82
|
+
branch,
|
|
83
|
+
commitSha,
|
|
84
|
+
commitMessage,
|
|
85
|
+
pullRequestNumber,
|
|
86
|
+
pullRequestUrl,
|
|
87
|
+
});
|
|
88
|
+
if (result && this.options.printSummary !== false) {
|
|
89
|
+
printSuccess(result, stats);
|
|
90
|
+
}
|
|
91
|
+
if (!result && this.options.failOnUploadError) {
|
|
92
|
+
printWarning("Upload failed and failOnUploadError is enabled");
|
|
93
|
+
// Don't throw — Playwright handles this via the return value
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
buildReportJson() {
|
|
97
|
+
// Build a Playwright-compatible JSON report structure
|
|
98
|
+
const suiteMap = new Map();
|
|
99
|
+
for (const test of this.tests) {
|
|
100
|
+
const key = test.suite || "(root)";
|
|
101
|
+
const list = suiteMap.get(key) || [];
|
|
102
|
+
list.push(test);
|
|
103
|
+
suiteMap.set(key, list);
|
|
104
|
+
}
|
|
105
|
+
const suites = Array.from(suiteMap.entries()).map(([suiteName, tests]) => ({
|
|
106
|
+
title: suiteName,
|
|
107
|
+
specs: tests.map((test) => ({
|
|
108
|
+
title: test.title,
|
|
109
|
+
ok: test.ok,
|
|
110
|
+
tests: [
|
|
111
|
+
{
|
|
112
|
+
status: test.status,
|
|
113
|
+
duration: test.duration,
|
|
114
|
+
retries: test.retries,
|
|
115
|
+
errors: test.errors,
|
|
116
|
+
annotations: test.annotations,
|
|
117
|
+
attachments: test.attachments.map((a) => ({
|
|
118
|
+
name: a.name,
|
|
119
|
+
contentType: a.contentType,
|
|
120
|
+
path: a.path,
|
|
121
|
+
})),
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
})),
|
|
125
|
+
}));
|
|
126
|
+
const stats = this.computeStats();
|
|
127
|
+
const duration = Date.now() - this.startTime;
|
|
128
|
+
return {
|
|
129
|
+
suites,
|
|
130
|
+
stats: {
|
|
131
|
+
duration,
|
|
132
|
+
expected: stats.passed,
|
|
133
|
+
unexpected: stats.failed,
|
|
134
|
+
skipped: stats.skipped,
|
|
135
|
+
flaky: stats.flaky,
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
computeStats() {
|
|
140
|
+
let passed = 0;
|
|
141
|
+
let failed = 0;
|
|
142
|
+
let skipped = 0;
|
|
143
|
+
let flaky = 0;
|
|
144
|
+
let snapshots = 0;
|
|
145
|
+
for (const test of this.tests) {
|
|
146
|
+
switch (test.status) {
|
|
147
|
+
case "passed":
|
|
148
|
+
if (test.retries > 0)
|
|
149
|
+
flaky++;
|
|
150
|
+
else
|
|
151
|
+
passed++;
|
|
152
|
+
break;
|
|
153
|
+
case "failed":
|
|
154
|
+
failed++;
|
|
155
|
+
break;
|
|
156
|
+
case "skipped":
|
|
157
|
+
skipped++;
|
|
158
|
+
break;
|
|
159
|
+
case "timedOut":
|
|
160
|
+
failed++;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
snapshots += test.attachments.filter((a) => a.contentType.startsWith("image/")).length;
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
total: this.tests.length,
|
|
167
|
+
passed,
|
|
168
|
+
failed,
|
|
169
|
+
skipped,
|
|
170
|
+
flaky,
|
|
171
|
+
snapshots,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
export default VeraReporter;
|
|
176
|
+
//# sourceMappingURL=reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export interface VeraReporterOptions {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
projectId: string;
|
|
4
|
+
baseUrl?: string;
|
|
5
|
+
branch?: string;
|
|
6
|
+
commitSha?: string;
|
|
7
|
+
commitMessage?: string;
|
|
8
|
+
pullRequestNumber?: number;
|
|
9
|
+
pullRequestUrl?: string;
|
|
10
|
+
uploadTraces?: boolean;
|
|
11
|
+
uploadVideos?: boolean;
|
|
12
|
+
failOnUploadError?: boolean;
|
|
13
|
+
printSummary?: boolean;
|
|
14
|
+
tags?: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface UploadResult {
|
|
17
|
+
runId: string;
|
|
18
|
+
status: string;
|
|
19
|
+
url: string;
|
|
20
|
+
}
|
|
21
|
+
export interface CollectedAttachment {
|
|
22
|
+
name: string;
|
|
23
|
+
contentType: string;
|
|
24
|
+
path?: string;
|
|
25
|
+
body?: Buffer;
|
|
26
|
+
}
|
|
27
|
+
export interface CollectedTest {
|
|
28
|
+
title: string;
|
|
29
|
+
suite: string;
|
|
30
|
+
status: string;
|
|
31
|
+
duration: number;
|
|
32
|
+
ok: boolean;
|
|
33
|
+
retries: number;
|
|
34
|
+
errors: Array<{
|
|
35
|
+
message?: string;
|
|
36
|
+
stack?: string;
|
|
37
|
+
}>;
|
|
38
|
+
annotations: Array<{
|
|
39
|
+
type: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
}>;
|
|
42
|
+
attachments: CollectedAttachment[];
|
|
43
|
+
}
|
|
44
|
+
export interface RunStats {
|
|
45
|
+
total: number;
|
|
46
|
+
passed: number;
|
|
47
|
+
failed: number;
|
|
48
|
+
skipped: number;
|
|
49
|
+
flaky: number;
|
|
50
|
+
snapshots: number;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,CAAC;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,WAAW,EAAE,mBAAmB,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { VeraReporterOptions, UploadResult, CollectedTest } from "./types.js";
|
|
2
|
+
interface UploadPayload {
|
|
3
|
+
options: VeraReporterOptions;
|
|
4
|
+
reportJson: unknown;
|
|
5
|
+
tests: CollectedTest[];
|
|
6
|
+
ciProvider?: string;
|
|
7
|
+
branch?: string;
|
|
8
|
+
commitSha?: string;
|
|
9
|
+
commitMessage?: string;
|
|
10
|
+
pullRequestNumber?: number;
|
|
11
|
+
pullRequestUrl?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Upload a Playwright run to the Vera CI API.
|
|
15
|
+
* Returns null on failure, never throws.
|
|
16
|
+
*/
|
|
17
|
+
export declare function uploadRun(payload: UploadPayload): Promise<UploadResult | null>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=uploader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploader.d.ts","sourceRoot":"","sources":["../src/uploader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAOnF,UAAU,aAAa;IACrB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAqIpF"}
|
package/dist/uploader.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { readFile } from "fs/promises";
|
|
2
|
+
import { printWarning } from "./logger.js";
|
|
3
|
+
const UPLOAD_TIMEOUT = 5 * 60 * 1000; // 5 minutes
|
|
4
|
+
const MAX_RETRIES = 3;
|
|
5
|
+
const BACKOFF_MS = [1000, 2000, 4000];
|
|
6
|
+
/**
|
|
7
|
+
* Upload a Playwright run to the Vera CI API.
|
|
8
|
+
* Returns null on failure, never throws.
|
|
9
|
+
*/
|
|
10
|
+
export async function uploadRun(payload) {
|
|
11
|
+
const { options, reportJson, tests, ciProvider, branch, commitSha, commitMessage, pullRequestNumber, pullRequestUrl, } = payload;
|
|
12
|
+
const baseUrl = options.baseUrl || "https://api.vera-ci.com";
|
|
13
|
+
const url = `${baseUrl}/v1/runs`;
|
|
14
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
15
|
+
try {
|
|
16
|
+
const formData = new FormData();
|
|
17
|
+
// Add report JSON
|
|
18
|
+
const reportBlob = new Blob([JSON.stringify(reportJson)], {
|
|
19
|
+
type: "application/json",
|
|
20
|
+
});
|
|
21
|
+
formData.append("report", reportBlob, "report.json");
|
|
22
|
+
// Add metadata fields
|
|
23
|
+
if (branch)
|
|
24
|
+
formData.append("branch", branch);
|
|
25
|
+
if (commitSha)
|
|
26
|
+
formData.append("commit_sha", commitSha);
|
|
27
|
+
if (commitMessage)
|
|
28
|
+
formData.append("commit_message", commitMessage);
|
|
29
|
+
if (pullRequestNumber != null) {
|
|
30
|
+
formData.append("pull_request_number", String(pullRequestNumber));
|
|
31
|
+
}
|
|
32
|
+
if (pullRequestUrl)
|
|
33
|
+
formData.append("pull_request_url", pullRequestUrl);
|
|
34
|
+
if (ciProvider)
|
|
35
|
+
formData.append("ci_provider", ciProvider);
|
|
36
|
+
if (options.tags && options.tags.length > 0) {
|
|
37
|
+
formData.append("metadata", JSON.stringify({ tags: options.tags }));
|
|
38
|
+
}
|
|
39
|
+
// Collect and add attachments
|
|
40
|
+
for (const test of tests) {
|
|
41
|
+
for (const attachment of test.attachments) {
|
|
42
|
+
const isScreenshot = attachment.contentType.startsWith("image/");
|
|
43
|
+
const isTrace = attachment.contentType === "application/zip" ||
|
|
44
|
+
attachment.name.endsWith(".zip") ||
|
|
45
|
+
attachment.name === "trace";
|
|
46
|
+
const isVideo = attachment.contentType.startsWith("video/");
|
|
47
|
+
// Skip unknown attachment types (e.g., error-context markdown files)
|
|
48
|
+
if (!isScreenshot && !isTrace && !isVideo)
|
|
49
|
+
continue;
|
|
50
|
+
// Skip traces if not uploading
|
|
51
|
+
if (isTrace && options.uploadTraces === false)
|
|
52
|
+
continue;
|
|
53
|
+
// Skip videos if not uploading
|
|
54
|
+
if (isVideo && options.uploadVideos === false)
|
|
55
|
+
continue;
|
|
56
|
+
let fileBuffer;
|
|
57
|
+
if (attachment.body) {
|
|
58
|
+
fileBuffer = attachment.body;
|
|
59
|
+
}
|
|
60
|
+
else if (attachment.path) {
|
|
61
|
+
try {
|
|
62
|
+
fileBuffer = await readFile(attachment.path);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// File may not exist (e.g., transient test artifact)
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (!fileBuffer)
|
|
70
|
+
continue;
|
|
71
|
+
const blob = new Blob([new Uint8Array(fileBuffer)], { type: attachment.contentType });
|
|
72
|
+
const fieldName = isScreenshot
|
|
73
|
+
? "screenshots[]"
|
|
74
|
+
: isTrace
|
|
75
|
+
? "traces[]"
|
|
76
|
+
: "videos[]";
|
|
77
|
+
formData.append(fieldName, blob, attachment.name);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const controller = new AbortController();
|
|
81
|
+
const timeout = setTimeout(() => controller.abort(), UPLOAD_TIMEOUT);
|
|
82
|
+
const response = await fetch(url, {
|
|
83
|
+
method: "POST",
|
|
84
|
+
headers: {
|
|
85
|
+
Authorization: `Bearer ${options.apiKey}`,
|
|
86
|
+
},
|
|
87
|
+
body: formData,
|
|
88
|
+
signal: controller.signal,
|
|
89
|
+
});
|
|
90
|
+
clearTimeout(timeout);
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
const body = await response.text().catch(() => "");
|
|
93
|
+
let errorMessage;
|
|
94
|
+
try {
|
|
95
|
+
const parsed = JSON.parse(body);
|
|
96
|
+
errorMessage = parsed.error?.message || `HTTP ${response.status}`;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
errorMessage = `HTTP ${response.status}`;
|
|
100
|
+
}
|
|
101
|
+
printWarning(`Upload failed: ${errorMessage}`);
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
const data = (await response.json());
|
|
105
|
+
return data.data;
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
const isNetworkError = err instanceof TypeError ||
|
|
109
|
+
(err instanceof DOMException && err.name === "AbortError");
|
|
110
|
+
if (isNetworkError && attempt < MAX_RETRIES) {
|
|
111
|
+
const delay = BACKOFF_MS[attempt] || 4000;
|
|
112
|
+
printWarning(`Upload attempt ${attempt + 1} failed, retrying in ${delay / 1000}s...`);
|
|
113
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
117
|
+
printWarning(`Upload failed: ${message}`);
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=uploader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploader.js","sourceRoot":"","sources":["../src/uploader.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vera-ci/playwright-reporter",
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
|
+
"description": "Playwright reporter for Vera CI — upload test results, screenshots, traces, and videos.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.js",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"dev": "tsc --watch",
|
|
23
|
+
"type-check": "tsc --noEmit",
|
|
24
|
+
"lint": "eslint src/"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"@playwright/test": ">=1.30.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@playwright/test": "^1.52.0",
|
|
31
|
+
"@types/node": "^22.19.11",
|
|
32
|
+
"typescript": "^5.9.3"
|
|
33
|
+
},
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "https://github.com/vera-ci/vera-ci"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"playwright",
|
|
41
|
+
"reporter",
|
|
42
|
+
"testing",
|
|
43
|
+
"visual-regression",
|
|
44
|
+
"ci",
|
|
45
|
+
"vera-ci"
|
|
46
|
+
]
|
|
47
|
+
}
|