@lokalise/playwright-reporters 1.0.2
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/LICENSE.md +13 -0
- package/README.md +66 -0
- package/dist/playwright.config.d.ts +2 -0
- package/dist/playwright.config.js +15 -0
- package/dist/playwright.config.js.map +1 -0
- package/dist/src/analytics/elastic.d.ts +30 -0
- package/dist/src/analytics/elastic.js +72 -0
- package/dist/src/analytics/elastic.js.map +1 -0
- package/dist/src/analytics/logger.d.ts +1 -0
- package/dist/src/analytics/logger.js +7 -0
- package/dist/src/analytics/logger.js.map +1 -0
- package/dist/src/analytics/reporter.d.ts +39 -0
- package/dist/src/analytics/reporter.js +118 -0
- package/dist/src/analytics/reporter.js.map +1 -0
- package/dist/src/analytics/tests/transform.test.d.ts +1 -0
- package/dist/src/analytics/tests/transform.test.js +159 -0
- package/dist/src/analytics/tests/transform.test.js.map +1 -0
- package/dist/src/analytics/transform.d.ts +89 -0
- package/dist/src/analytics/transform.js +124 -0
- package/dist/src/analytics/transform.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +33 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/retry/reporter.d.ts +24 -0
- package/dist/src/retry/reporter.js +117 -0
- package/dist/src/retry/reporter.js.map +1 -0
- package/package.json +61 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright 2023 Lokalise, Inc.
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Lokalise Playwright Reporters
|
|
2
|
+
|
|
3
|
+
## Project Purpose
|
|
4
|
+
|
|
5
|
+
This is a collection of reporters to use with our Playwright test frameworks.
|
|
6
|
+
|
|
7
|
+
## Key Features
|
|
8
|
+
|
|
9
|
+
- Retry reporter: Provides an easy way to retry failed tests on Jenkins or locally.
|
|
10
|
+
- Analytics reporter: Uploads test results to ElasticSearch for further analysis.
|
|
11
|
+
|
|
12
|
+
## Getting Started
|
|
13
|
+
|
|
14
|
+
- Add the package to your project:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @lokalise/playwright-reporters
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- Add the reporters to your Playwright configuration:
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { defineAnalyticsReporterConfig, defineRetryReporterConfig } from '@lokalise/playwright-reporters';
|
|
24
|
+
|
|
25
|
+
export default defineConfig({
|
|
26
|
+
...
|
|
27
|
+
reporters: [
|
|
28
|
+
['retry', defineRetryReporterConfig({ maxRetryCount: 2, isPREnv: false })],
|
|
29
|
+
['analytics', defineAnalyticsReporterConfig({
|
|
30
|
+
flakyTestIndex: 'flaky_tests_0001',
|
|
31
|
+
failedTestIndex: 'non_passing_tests_0001',
|
|
32
|
+
testRunIndex: 'test_run_0001',
|
|
33
|
+
elasticUrl: 'elasticUrl',
|
|
34
|
+
elasticToken: 'elasticToken',
|
|
35
|
+
currentBuildId: 'buildId',
|
|
36
|
+
debug: false,
|
|
37
|
+
})],
|
|
38
|
+
],
|
|
39
|
+
...
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Husky
|
|
44
|
+
|
|
45
|
+
By default, pre-commit hook will run `npm run lint:fix`. Feel free to remove that if it's undesirable or add your own
|
|
46
|
+
pre-commit commands.
|
|
47
|
+
|
|
48
|
+
Check out [husky](https://typicode.github.io/husky) docs for more info.
|
|
49
|
+
|
|
50
|
+
## commitlint
|
|
51
|
+
|
|
52
|
+
You can use `npm run commit` to interactively construct correct commit messsage.
|
|
53
|
+
|
|
54
|
+
Check out [commitlint](https://commitlint.js.org) docs for examples of how to customise.
|
|
55
|
+
|
|
56
|
+
## Release actions
|
|
57
|
+
|
|
58
|
+
The following token needs to be set in the Github repo for the `prerelease` and `release` Github Actions to work:
|
|
59
|
+
|
|
60
|
+
- `secrets.NPM_TOKEN` (need this to publish on NPM)
|
|
61
|
+
|
|
62
|
+
When performing a release, make sure to follow our conventional commit approach, as described in [contribution documentation](https://github.com/lokalise/npm-package-template/blob/main/CONTRIBUTING.md).
|
|
63
|
+
|
|
64
|
+
## License
|
|
65
|
+
|
|
66
|
+
This project is APACHE, VERSION 2.0 licensed, see LICENSE.md for details.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const test_1 = require("@playwright/test");
|
|
4
|
+
// eslint-disable-next-line import/no-default-export
|
|
5
|
+
exports.default = (0, test_1.defineConfig)({
|
|
6
|
+
retries: 0,
|
|
7
|
+
reporter: [["list"], ["html", { open: "never" }]],
|
|
8
|
+
projects: [
|
|
9
|
+
{
|
|
10
|
+
name: "analytics",
|
|
11
|
+
testMatch: "src/analytics/tests/transform.test.ts",
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
});
|
|
15
|
+
//# sourceMappingURL=playwright.config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright.config.js","sourceRoot":"","sources":["../playwright.config.ts"],"names":[],"mappings":";;AAAA,2CAAgD;AAEhD,oDAAoD;AACpD,kBAAe,IAAA,mBAAY,EAAC;IAC3B,OAAO,EAAE,CAAC;IACV,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACjD,QAAQ,EAAE;QACT;YACC,IAAI,EAAE,WAAW;YACjB,SAAS,EAAE,uCAAuC;SAClD;KACD;CACD,CAAC,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type formBuildData, type formFailedTestData, type formFlakyTestData } from "./transform";
|
|
2
|
+
export type ElasticConfig = {
|
|
3
|
+
flakyTestIndex: string;
|
|
4
|
+
failedTestIndex: string;
|
|
5
|
+
testRunIndex: string;
|
|
6
|
+
elasticUrl: string;
|
|
7
|
+
elasticToken: string;
|
|
8
|
+
};
|
|
9
|
+
export declare class Elastic {
|
|
10
|
+
private request;
|
|
11
|
+
private readonly flakyTestIndex;
|
|
12
|
+
private readonly failedTestIndex;
|
|
13
|
+
private readonly testRunIndex;
|
|
14
|
+
private readonly elasticUrl;
|
|
15
|
+
private readonly elasticToken;
|
|
16
|
+
constructor(analyticsConfig: ElasticConfig);
|
|
17
|
+
setNativeRequestContext(): Promise<void>;
|
|
18
|
+
saveFlakyData(flake: ReturnType<typeof formFlakyTestData>): Promise<void>;
|
|
19
|
+
saveFailedData(failure: ReturnType<typeof formFailedTestData>): Promise<void>;
|
|
20
|
+
saveBuildData(build: ReturnType<typeof formBuildData>): Promise<void>;
|
|
21
|
+
getLastRunData(): Promise<{
|
|
22
|
+
hits: {
|
|
23
|
+
hits: {
|
|
24
|
+
_source: {
|
|
25
|
+
buildId: string;
|
|
26
|
+
};
|
|
27
|
+
}[];
|
|
28
|
+
};
|
|
29
|
+
} | null>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Elastic = void 0;
|
|
4
|
+
const test_1 = require("@playwright/test");
|
|
5
|
+
const logger_1 = require("./logger");
|
|
6
|
+
class Elastic {
|
|
7
|
+
constructor(analyticsConfig) {
|
|
8
|
+
this.flakyTestIndex = analyticsConfig.flakyTestIndex;
|
|
9
|
+
this.failedTestIndex = analyticsConfig.failedTestIndex;
|
|
10
|
+
this.testRunIndex = analyticsConfig.testRunIndex;
|
|
11
|
+
this.elasticUrl = analyticsConfig.elasticUrl;
|
|
12
|
+
this.elasticToken = analyticsConfig.elasticToken;
|
|
13
|
+
}
|
|
14
|
+
async setNativeRequestContext() {
|
|
15
|
+
this.request = await test_1.request.newContext({
|
|
16
|
+
baseURL: this.elasticUrl,
|
|
17
|
+
ignoreHTTPSErrors: true,
|
|
18
|
+
...(this.elasticToken && {
|
|
19
|
+
extraHTTPHeaders: { Authorization: `ApiKey ${this.elasticToken}` },
|
|
20
|
+
}),
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
async saveFlakyData(flake) {
|
|
24
|
+
try {
|
|
25
|
+
await this.request.post(`/${this.flakyTestIndex}/_doc`, { data: flake });
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
(0, logger_1.logger)(error);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async saveFailedData(failure) {
|
|
32
|
+
try {
|
|
33
|
+
await this.request.post(`/${this.failedTestIndex}/_doc`, {
|
|
34
|
+
data: failure,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
(0, logger_1.logger)(error);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async saveBuildData(build) {
|
|
42
|
+
try {
|
|
43
|
+
await this.request.post(`/${this.testRunIndex}/_doc`, { data: build });
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
(0, logger_1.logger)(error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async getLastRunData() {
|
|
50
|
+
try {
|
|
51
|
+
const response = await this.request.post(`/${this.testRunIndex}/_search`, {
|
|
52
|
+
data: {
|
|
53
|
+
sort: [
|
|
54
|
+
{
|
|
55
|
+
startTime: {
|
|
56
|
+
order: "desc",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
size: 1,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
return (await response.json());
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
(0, logger_1.logger)(error);
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.Elastic = Elastic;
|
|
72
|
+
//# sourceMappingURL=elastic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elastic.js","sourceRoot":"","sources":["../../../src/analytics/elastic.ts"],"names":[],"mappings":";;;AAAA,2CAAmE;AAEnE,qCAAkC;AAelC,MAAa,OAAO;IAQnB,YAAY,eAA8B;QACzC,IAAI,CAAC,cAAc,GAAG,eAAe,CAAC,cAAc,CAAC;QACrD,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC,eAAe,CAAC;QACvD,IAAI,CAAC,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC;QACjD,IAAI,CAAC,UAAU,GAAG,eAAe,CAAC,UAAU,CAAC;QAC7C,IAAI,CAAC,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,uBAAuB;QAC5B,IAAI,CAAC,OAAO,GAAG,MAAM,cAAO,CAAC,UAAU,CAAC;YACvC,OAAO,EAAE,IAAI,CAAC,UAAU;YACxB,iBAAiB,EAAE,IAAI;YACvB,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI;gBACxB,gBAAgB,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,YAAY,EAAE,EAAE;aAClE,CAAC;SACF,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAA2C;QAC9D,IAAI;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,cAAc,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;SACzE;QAAC,OAAO,KAAK,EAAE;YACf,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC;SACd;IACF,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAA8C;QAClE,IAAI;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,eAAe,OAAO,EAAE;gBACxD,IAAI,EAAE,OAAO;aACb,CAAC,CAAC;SACH;QAAC,OAAO,KAAK,EAAE;YACf,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC;SACd;IACF,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAAuC;QAC1D,IAAI;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,YAAY,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;SACvE;QAAC,OAAO,KAAK,EAAE;YACf,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC;SACd;IACF,CAAC;IAED,KAAK,CAAC,cAAc;QACnB,IAAI;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CACvC,IAAI,IAAI,CAAC,YAAY,UAAU,EAC/B;gBACC,IAAI,EAAE;oBACL,IAAI,EAAE;wBACL;4BACC,SAAS,EAAE;gCACV,KAAK,EAAE,MAAM;6BACb;yBACD;qBACD;oBACD,IAAI,EAAE,CAAC;iBACP;aACD,CACD,CAAC;YAEF,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAE5B,CAAC;SACF;QAAC,OAAO,KAAK,EAAE;YACf,IAAA,eAAM,EAAC,KAAK,CAAC,CAAC;YACd,OAAO,IAAI,CAAC;SACZ;IACF,CAAC;CACD;AA9ED,0BA8EC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const logger: (...messages: unknown[]) => void;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = void 0;
|
|
4
|
+
// eslint-disable-next-line no-console
|
|
5
|
+
const logger = (...messages) => console.log(...messages);
|
|
6
|
+
exports.logger = logger;
|
|
7
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/analytics/logger.ts"],"names":[],"mappings":";;;AAAA,sCAAsC;AAC/B,MAAM,MAAM,GAAG,CAAC,GAAG,QAAmB,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;AAA9D,QAAA,MAAM,UAAwD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type FullConfig, type FullResult, type Reporter, type Suite, type TestCase, type TestResult, type TestStatus, type TestStep } from "@playwright/test/reporter";
|
|
2
|
+
import { type ElasticConfig } from "./elastic";
|
|
3
|
+
export default class AnalyticsReporter implements Reporter {
|
|
4
|
+
readonly listOfNonPassingTests: TestAnalyticsData[];
|
|
5
|
+
readonly listOfFlakyTests: TestAnalyticsData[];
|
|
6
|
+
readonly browserCreationTimes: number[];
|
|
7
|
+
readonly browserClosingTimes: number[];
|
|
8
|
+
private elastic;
|
|
9
|
+
private runStartTime;
|
|
10
|
+
private runEndTime;
|
|
11
|
+
private numberOfTests;
|
|
12
|
+
private readonly testRunId;
|
|
13
|
+
private projectNames;
|
|
14
|
+
private testOwnerCount;
|
|
15
|
+
private readonly options;
|
|
16
|
+
constructor(options: ReporterOptions);
|
|
17
|
+
onBegin(config: FullConfig, suite: Suite): Promise<void>;
|
|
18
|
+
onStepEnd(test: TestCase, result: TestResult, step: TestStep): void;
|
|
19
|
+
onTestEnd(test: TestCase, result: TestResult): Promise<void>;
|
|
20
|
+
private onEndDebug;
|
|
21
|
+
onEnd(result: FullResult): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export declare const defineAnalyticsReporterConfig: (options: ConstructorParameters<typeof AnalyticsReporter>[0]) => ReporterOptions;
|
|
24
|
+
type ReporterOptions = {
|
|
25
|
+
debug?: boolean;
|
|
26
|
+
currentBuildId: string;
|
|
27
|
+
} & ElasticConfig;
|
|
28
|
+
export type TestAnalyticsData = {
|
|
29
|
+
timestamp: number;
|
|
30
|
+
name: string;
|
|
31
|
+
status: TestStatus;
|
|
32
|
+
beforeHookDuration?: number;
|
|
33
|
+
afterHookDuration?: number;
|
|
34
|
+
hooksDuration?: number;
|
|
35
|
+
testDuration: number;
|
|
36
|
+
totalDuration: number;
|
|
37
|
+
retry?: number;
|
|
38
|
+
};
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defineAnalyticsReporterConfig = void 0;
|
|
4
|
+
/* eslint-disable no-console */
|
|
5
|
+
const faker_1 = require("@faker-js/faker");
|
|
6
|
+
const elastic_1 = require("./elastic");
|
|
7
|
+
const transform_1 = require("./transform");
|
|
8
|
+
// eslint-disable-next-line import/no-default-export
|
|
9
|
+
class AnalyticsReporter {
|
|
10
|
+
constructor(options) {
|
|
11
|
+
this.options = options;
|
|
12
|
+
this.listOfNonPassingTests = [];
|
|
13
|
+
this.listOfFlakyTests = [];
|
|
14
|
+
this.browserCreationTimes = [];
|
|
15
|
+
this.browserClosingTimes = [];
|
|
16
|
+
this.projectNames = [];
|
|
17
|
+
this.testOwnerCount = {};
|
|
18
|
+
this.testRunId = faker_1.faker.string.uuid();
|
|
19
|
+
this.runStartTime = Date.now();
|
|
20
|
+
this.runEndTime = Date.now();
|
|
21
|
+
this.numberOfTests = 0;
|
|
22
|
+
this.elastic = new elastic_1.Elastic(options);
|
|
23
|
+
}
|
|
24
|
+
async onBegin(config, suite) {
|
|
25
|
+
try {
|
|
26
|
+
this.runStartTime = Date.now();
|
|
27
|
+
this.numberOfTests = suite.allTests().length;
|
|
28
|
+
this.projectNames = suite.suites.map((testSuite) => testSuite.title);
|
|
29
|
+
await this.elastic.setNativeRequestContext();
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
console.error("Could not perform 'onBegin' analytics step", error);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
onStepEnd(test, result, step) {
|
|
36
|
+
try {
|
|
37
|
+
if (step.title.toLowerCase().includes("create browser")) {
|
|
38
|
+
this.browserCreationTimes.push(step.duration);
|
|
39
|
+
}
|
|
40
|
+
if (step.title.toLowerCase().includes("close browser")) {
|
|
41
|
+
this.browserClosingTimes.push(step.duration);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
console.error("Could not perform 'onStepEnd' analytics step", error);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async onTestEnd(test, result) {
|
|
49
|
+
try {
|
|
50
|
+
const { status, retry: currentRetryCount } = result;
|
|
51
|
+
const { retries: maxRetriesCount } = test;
|
|
52
|
+
if (["failed", "timedOut", "interrupted"].includes(status) &&
|
|
53
|
+
currentRetryCount === maxRetriesCount) {
|
|
54
|
+
const failedTest = (0, transform_1.formFailedTestData)(test, result, this.testRunId);
|
|
55
|
+
this.listOfNonPassingTests.push(failedTest);
|
|
56
|
+
await this.elastic.saveFailedData(failedTest);
|
|
57
|
+
}
|
|
58
|
+
else if (["passed"].includes(status) && currentRetryCount) {
|
|
59
|
+
const flakyTest = (0, transform_1.formFlakyTestData)(test, result, this.testRunId);
|
|
60
|
+
this.listOfFlakyTests.push(flakyTest);
|
|
61
|
+
await this.elastic.saveFlakyData(flakyTest);
|
|
62
|
+
}
|
|
63
|
+
else if (!currentRetryCount) {
|
|
64
|
+
const ownerTeamNames = (0, transform_1.getTeamNames)(test);
|
|
65
|
+
this.testOwnerCount = (0, transform_1.addTeamCount)(this.testOwnerCount, ownerTeamNames);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error("Could not perform 'onTestEnd' analytics step", error);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
onEndDebug(buildData) {
|
|
73
|
+
(0, transform_1.calculateRuntime)(this.runStartTime);
|
|
74
|
+
(0, transform_1.calculateRetriedTests)(this.listOfFlakyTests);
|
|
75
|
+
console.log("NON PASSING TESTS");
|
|
76
|
+
console.table(this.listOfNonPassingTests);
|
|
77
|
+
console.log("FLAKY TESTS");
|
|
78
|
+
console.table(this.listOfFlakyTests);
|
|
79
|
+
console.log("RUN DATA");
|
|
80
|
+
console.table([buildData]);
|
|
81
|
+
}
|
|
82
|
+
async onEnd(result) {
|
|
83
|
+
try {
|
|
84
|
+
this.runEndTime = Date.now();
|
|
85
|
+
const lastBuildData = await this.elastic.getLastRunData();
|
|
86
|
+
const buildIDWithPrefix = transform_1.getBuildIdWithPrefix.bind(this)(lastBuildData, this.options.currentBuildId);
|
|
87
|
+
const buildData = (0, transform_1.formBuildData)({
|
|
88
|
+
result,
|
|
89
|
+
testRunId: this.testRunId,
|
|
90
|
+
startTime: this.runStartTime,
|
|
91
|
+
endTime: this.runEndTime,
|
|
92
|
+
numberOfTests: this.numberOfTests,
|
|
93
|
+
failedTests: this.listOfNonPassingTests,
|
|
94
|
+
flakyTests: this.listOfFlakyTests,
|
|
95
|
+
browserCreation: this.browserCreationTimes.reduce((acc, current) => acc + current, 0),
|
|
96
|
+
browserClose: this.browserClosingTimes.reduce((acc, current) => acc + current, 0),
|
|
97
|
+
project: {
|
|
98
|
+
e2e: this.projectNames.includes("e2e"),
|
|
99
|
+
api: this.projectNames.includes("api"),
|
|
100
|
+
regression: this.projectNames.includes("regression"),
|
|
101
|
+
},
|
|
102
|
+
teamStats: this.testOwnerCount,
|
|
103
|
+
buildId: buildIDWithPrefix,
|
|
104
|
+
});
|
|
105
|
+
await this.elastic.saveBuildData(buildData);
|
|
106
|
+
if (this.options.debug) {
|
|
107
|
+
this.onEndDebug(buildData);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error("Could not perform 'onEnd' analytics step", error);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
exports.default = AnalyticsReporter;
|
|
116
|
+
const defineAnalyticsReporterConfig = (options) => options;
|
|
117
|
+
exports.defineAnalyticsReporterConfig = defineAnalyticsReporterConfig;
|
|
118
|
+
//# sourceMappingURL=reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../../../src/analytics/reporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const test_1 = require("@playwright/test");
|
|
4
|
+
const transform_1 = require("../transform");
|
|
5
|
+
test_1.test.describe("Analytics: data transform", () => {
|
|
6
|
+
(0, test_1.test)("should form failed test data", () => {
|
|
7
|
+
const formedTestData = (0, transform_1.formFailedTestData)({ title: "hello" }, {
|
|
8
|
+
startTime: new Date(),
|
|
9
|
+
steps: [
|
|
10
|
+
{ title: "before hooks", duration: 123 },
|
|
11
|
+
{ title: "after hooks", duration: 234 },
|
|
12
|
+
],
|
|
13
|
+
status: "passed",
|
|
14
|
+
duration: 1234,
|
|
15
|
+
retry: 2,
|
|
16
|
+
}, "testRunId");
|
|
17
|
+
(0, test_1.expect)(formedTestData).toMatchObject({
|
|
18
|
+
timestamp: test_1.expect.any(Number),
|
|
19
|
+
name: "hello",
|
|
20
|
+
testRunId: "testRunId",
|
|
21
|
+
status: "passed",
|
|
22
|
+
hooksDuration: 357,
|
|
23
|
+
beforeHookDuration: 123,
|
|
24
|
+
afterHookDuration: 234,
|
|
25
|
+
testDuration: 1234,
|
|
26
|
+
totalDuration: 1591,
|
|
27
|
+
project: { e2e: false, api: false },
|
|
28
|
+
retry: 2,
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
(0, test_1.test)("should form flaky test data", () => {
|
|
32
|
+
const formedTestData = (0, transform_1.formFlakyTestData)({ title: "hello" }, {
|
|
33
|
+
startTime: new Date(),
|
|
34
|
+
steps: [
|
|
35
|
+
{ title: "before hooks", duration: 123 },
|
|
36
|
+
{ title: "after hooks", duration: 234 },
|
|
37
|
+
],
|
|
38
|
+
status: "passed",
|
|
39
|
+
duration: 1234,
|
|
40
|
+
retry: 2,
|
|
41
|
+
}, "testRunId");
|
|
42
|
+
(0, test_1.expect)(formedTestData).toMatchObject({
|
|
43
|
+
timestamp: test_1.expect.any(Number),
|
|
44
|
+
name: "hello",
|
|
45
|
+
testRunId: "testRunId",
|
|
46
|
+
status: "passed",
|
|
47
|
+
hooksDuration: 357,
|
|
48
|
+
beforeHookDuration: 123,
|
|
49
|
+
afterHookDuration: 234,
|
|
50
|
+
testDuration: 1234,
|
|
51
|
+
totalDuration: 1591,
|
|
52
|
+
project: { e2e: false, api: false },
|
|
53
|
+
retry: 2,
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
(0, test_1.test)("should form build data", () => {
|
|
57
|
+
process.env.BUILD_ID = "983";
|
|
58
|
+
const buildData = (0, transform_1.formBuildData)({
|
|
59
|
+
result: { status: "passed" },
|
|
60
|
+
startTime: 10,
|
|
61
|
+
endTime: 1234,
|
|
62
|
+
numberOfTests: 666,
|
|
63
|
+
browserCreation: 945,
|
|
64
|
+
browserClose: 23,
|
|
65
|
+
testRunId: "testRunId",
|
|
66
|
+
project: { e2e: false, api: true, regression: false },
|
|
67
|
+
failedTests: [{ name: "some failed test" }],
|
|
68
|
+
flakyTests: [
|
|
69
|
+
{ name: "some flaky test", totalDuration: 123 },
|
|
70
|
+
{ name: "another flaky test", totalDuration: 234 },
|
|
71
|
+
],
|
|
72
|
+
teamStats: { MAX: 999 },
|
|
73
|
+
buildId: "0001-02983",
|
|
74
|
+
});
|
|
75
|
+
(0, test_1.expect)(buildData).toEqual({
|
|
76
|
+
result: "passed",
|
|
77
|
+
startTime: 10,
|
|
78
|
+
endTime: 1234,
|
|
79
|
+
numberOfTests: 666,
|
|
80
|
+
browserCreation: 945,
|
|
81
|
+
browserClose: 23,
|
|
82
|
+
testRunId: "testRunId",
|
|
83
|
+
project: { e2e: false, api: true, regression: false },
|
|
84
|
+
duration: 1224,
|
|
85
|
+
failedTestCount: 1,
|
|
86
|
+
flakyTestCount: 2,
|
|
87
|
+
timeSpentOnRetry: 357,
|
|
88
|
+
teamStats: { MAX: 999 },
|
|
89
|
+
buildId: "0001-02983",
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
(0, test_1.test)("should include first team's name in failed test", () => {
|
|
93
|
+
const formedTestData = (0, transform_1.formFailedTestData)({
|
|
94
|
+
title: "hello",
|
|
95
|
+
annotations: [
|
|
96
|
+
{ type: "somethingElse", description: "notATeam" },
|
|
97
|
+
{ type: "owner", description: "firstTeam" },
|
|
98
|
+
{ type: "owner", description: "secondTeam" },
|
|
99
|
+
],
|
|
100
|
+
}, {
|
|
101
|
+
startTime: new Date(),
|
|
102
|
+
steps: [
|
|
103
|
+
{ title: "before hooks", duration: 123 },
|
|
104
|
+
{ title: "after hooks", duration: 234 },
|
|
105
|
+
],
|
|
106
|
+
status: "passed",
|
|
107
|
+
duration: 1234,
|
|
108
|
+
retry: 2,
|
|
109
|
+
}, "testRunId");
|
|
110
|
+
(0, test_1.expect)(formedTestData).toMatchObject({
|
|
111
|
+
timestamp: test_1.expect.any(Number),
|
|
112
|
+
name: "hello",
|
|
113
|
+
testRunId: "testRunId",
|
|
114
|
+
status: "passed",
|
|
115
|
+
hooksDuration: 357,
|
|
116
|
+
beforeHookDuration: 123,
|
|
117
|
+
afterHookDuration: 234,
|
|
118
|
+
team: "firstTeam",
|
|
119
|
+
testDuration: 1234,
|
|
120
|
+
totalDuration: 1591,
|
|
121
|
+
project: { e2e: false, api: false },
|
|
122
|
+
retry: 2,
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
(0, test_1.test)("should include first team's name in flaky test", () => {
|
|
126
|
+
const formedTestData = (0, transform_1.formFlakyTestData)({
|
|
127
|
+
title: "hello",
|
|
128
|
+
annotations: [
|
|
129
|
+
{ type: "somethingElse", description: "notATeam" },
|
|
130
|
+
{ type: "owner", description: "firstTeam" },
|
|
131
|
+
{ type: "owner", description: "secondTeam" },
|
|
132
|
+
],
|
|
133
|
+
}, {
|
|
134
|
+
startTime: new Date(),
|
|
135
|
+
steps: [
|
|
136
|
+
{ title: "before hooks", duration: 123 },
|
|
137
|
+
{ title: "after hooks", duration: 234 },
|
|
138
|
+
],
|
|
139
|
+
status: "passed",
|
|
140
|
+
duration: 1234,
|
|
141
|
+
retry: 2,
|
|
142
|
+
}, "testRunId");
|
|
143
|
+
(0, test_1.expect)(formedTestData).toMatchObject({
|
|
144
|
+
timestamp: test_1.expect.any(Number),
|
|
145
|
+
name: "hello",
|
|
146
|
+
testRunId: "testRunId",
|
|
147
|
+
status: "passed",
|
|
148
|
+
hooksDuration: 357,
|
|
149
|
+
beforeHookDuration: 123,
|
|
150
|
+
afterHookDuration: 234,
|
|
151
|
+
team: "firstTeam",
|
|
152
|
+
testDuration: 1234,
|
|
153
|
+
totalDuration: 1591,
|
|
154
|
+
project: { e2e: false, api: false },
|
|
155
|
+
retry: 2,
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
//# sourceMappingURL=transform.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.test.js","sourceRoot":"","sources":["../../../../src/analytics/tests/transform.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { type FullResult, type TestCase, type TestResult, type TestStep } from "@playwright/test/reporter";
|
|
2
|
+
import { type Elastic } from "./elastic";
|
|
3
|
+
import type AnalyticsReporter from ".";
|
|
4
|
+
import { type TestAnalyticsData } from ".";
|
|
5
|
+
export declare const calculateRuntime: (startTime: number) => void;
|
|
6
|
+
export declare const calculateRetriedTests: (listOfNonPassingTests: AnalyticsReporter["listOfNonPassingTests"]) => void;
|
|
7
|
+
export declare const calculateHooksDuration: (steps: TestStep[], hook: "before" | "after") => number;
|
|
8
|
+
export declare const getTeamNames: (test: TestCase) => {
|
|
9
|
+
type: string;
|
|
10
|
+
description?: string | undefined;
|
|
11
|
+
}[];
|
|
12
|
+
export declare const formFailedTestData: (test: TestCase, result: TestResult, testRunId: string) => {
|
|
13
|
+
retry?: number | undefined;
|
|
14
|
+
timestamp: number;
|
|
15
|
+
name: string;
|
|
16
|
+
team: string;
|
|
17
|
+
testRunId: string;
|
|
18
|
+
status: import("@playwright/test/reporter").TestStatus;
|
|
19
|
+
hooksDuration: number;
|
|
20
|
+
beforeHookDuration: number;
|
|
21
|
+
afterHookDuration: number;
|
|
22
|
+
testDuration: number;
|
|
23
|
+
totalDuration: number;
|
|
24
|
+
project: {
|
|
25
|
+
e2e: boolean;
|
|
26
|
+
api: boolean;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export declare const formFlakyTestData: (test: TestCase, result: TestResult, testRunId: string) => {
|
|
30
|
+
retry?: number | undefined;
|
|
31
|
+
timestamp: number;
|
|
32
|
+
name: string;
|
|
33
|
+
team: string;
|
|
34
|
+
testRunId: string;
|
|
35
|
+
status: import("@playwright/test/reporter").TestStatus;
|
|
36
|
+
hooksDuration: number;
|
|
37
|
+
beforeHookDuration: number;
|
|
38
|
+
afterHookDuration: number;
|
|
39
|
+
testDuration: number;
|
|
40
|
+
totalDuration: number;
|
|
41
|
+
project: {
|
|
42
|
+
e2e: boolean;
|
|
43
|
+
api: boolean;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
export declare const formBuildData: (args: {
|
|
47
|
+
result: FullResult;
|
|
48
|
+
startTime: number;
|
|
49
|
+
endTime: number;
|
|
50
|
+
numberOfTests: number;
|
|
51
|
+
browserCreation: number;
|
|
52
|
+
browserClose: number;
|
|
53
|
+
testRunId: string;
|
|
54
|
+
project: {
|
|
55
|
+
e2e: boolean;
|
|
56
|
+
api: boolean;
|
|
57
|
+
regression: boolean;
|
|
58
|
+
};
|
|
59
|
+
failedTests: TestAnalyticsData[];
|
|
60
|
+
flakyTests: TestAnalyticsData[];
|
|
61
|
+
teamStats: TeamStats;
|
|
62
|
+
buildId: string;
|
|
63
|
+
}) => {
|
|
64
|
+
result: "failed" | "interrupted" | "passed" | "timedout";
|
|
65
|
+
startTime: number;
|
|
66
|
+
endTime: number;
|
|
67
|
+
numberOfTests: number;
|
|
68
|
+
browserCreation: number;
|
|
69
|
+
browserClose: number;
|
|
70
|
+
testRunId: string;
|
|
71
|
+
project: {
|
|
72
|
+
e2e: boolean;
|
|
73
|
+
api: boolean;
|
|
74
|
+
regression: boolean;
|
|
75
|
+
};
|
|
76
|
+
duration: number;
|
|
77
|
+
failedTestCount: number;
|
|
78
|
+
flakyTestCount: number;
|
|
79
|
+
timeSpentOnRetry: number;
|
|
80
|
+
teamStats: TeamStats;
|
|
81
|
+
buildId: string;
|
|
82
|
+
};
|
|
83
|
+
export declare const addTeamCount: (teamStats: TeamStats, ownerTestAnnotations: TestCase["annotations"]) => {
|
|
84
|
+
[x: string]: number;
|
|
85
|
+
};
|
|
86
|
+
export declare const getBuildIdWithPrefix: (lastRunData: Awaited<ReturnType<Elastic["getLastRunData"]>>, currentBuildId: string) => string;
|
|
87
|
+
type TeamName = string;
|
|
88
|
+
export type TeamStats = Record<TeamName, number>;
|
|
89
|
+
export {};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getBuildIdWithPrefix = exports.addTeamCount = exports.formBuildData = exports.formFlakyTestData = exports.formFailedTestData = exports.getTeamNames = exports.calculateHooksDuration = exports.calculateRetriedTests = exports.calculateRuntime = void 0;
|
|
4
|
+
const logger_1 = require("./logger");
|
|
5
|
+
const calculateRuntime = (startTime) => {
|
|
6
|
+
const currentTime = Date.now();
|
|
7
|
+
const totalRunTime = currentTime - startTime;
|
|
8
|
+
(0, logger_1.logger)(`Finished the run: in ${totalRunTime / 1000} seconds`);
|
|
9
|
+
};
|
|
10
|
+
exports.calculateRuntime = calculateRuntime;
|
|
11
|
+
const calculateRetriedTests = (listOfNonPassingTests) => {
|
|
12
|
+
const totalRetriedTests = listOfNonPassingTests.filter((test) => test.retry);
|
|
13
|
+
const retriedTestNumber = totalRetriedTests.length;
|
|
14
|
+
const retriedTestDuration = totalRetriedTests.reduce((acc, current) => {
|
|
15
|
+
return acc + current.testDuration;
|
|
16
|
+
}, totalRetriedTests[0]?.testDuration ?? 0);
|
|
17
|
+
(0, logger_1.logger)(`Tests spent ${retriedTestDuration / 1000} seconds on ${retriedTestNumber} retries`);
|
|
18
|
+
};
|
|
19
|
+
exports.calculateRetriedTests = calculateRetriedTests;
|
|
20
|
+
const calculateHooksDuration = (steps, hook) => {
|
|
21
|
+
return steps
|
|
22
|
+
.filter((step) => step.title.toLowerCase().includes(`${hook} hooks`))
|
|
23
|
+
.map((step) => step.duration)
|
|
24
|
+
.reduce((acc, current) => acc + current);
|
|
25
|
+
};
|
|
26
|
+
exports.calculateHooksDuration = calculateHooksDuration;
|
|
27
|
+
const getTeamNames = (test) => {
|
|
28
|
+
return (test.annotations?.filter((annotation) => annotation.type === "owner") ?? []);
|
|
29
|
+
};
|
|
30
|
+
exports.getTeamNames = getTeamNames;
|
|
31
|
+
const baseTestData = (test, result, testRunId) => {
|
|
32
|
+
const { startTime, steps, status, duration, retry } = result;
|
|
33
|
+
const beforeHookDuration = (0, exports.calculateHooksDuration)(steps, "before");
|
|
34
|
+
const afterHookDuration = (0, exports.calculateHooksDuration)(steps, "after");
|
|
35
|
+
const totalHooksDuration = beforeHookDuration + afterHookDuration;
|
|
36
|
+
const parentTestProjectName = test?.parent?.project()?.name ?? "";
|
|
37
|
+
return {
|
|
38
|
+
timestamp: startTime.getTime(),
|
|
39
|
+
name: test.title,
|
|
40
|
+
team: (0, exports.getTeamNames)(test)?.at(0)?.description,
|
|
41
|
+
testRunId,
|
|
42
|
+
status,
|
|
43
|
+
hooksDuration: totalHooksDuration,
|
|
44
|
+
beforeHookDuration,
|
|
45
|
+
afterHookDuration,
|
|
46
|
+
testDuration: duration,
|
|
47
|
+
totalDuration: duration + totalHooksDuration,
|
|
48
|
+
project: {
|
|
49
|
+
e2e: ["regression", "e2e"].includes(parentTestProjectName),
|
|
50
|
+
api: test?.parent?.project()?.name === "api",
|
|
51
|
+
},
|
|
52
|
+
...(retry && { retry }),
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
const formFailedTestData = (test, result, testRunId) => {
|
|
56
|
+
return baseTestData(test, result, testRunId);
|
|
57
|
+
};
|
|
58
|
+
exports.formFailedTestData = formFailedTestData;
|
|
59
|
+
const formFlakyTestData = (test, result, testRunId) => {
|
|
60
|
+
return baseTestData(test, result, testRunId);
|
|
61
|
+
};
|
|
62
|
+
exports.formFlakyTestData = formFlakyTestData;
|
|
63
|
+
const formBuildData = (args) => {
|
|
64
|
+
const timeSpentOnRetry = args.flakyTests.reduce((acc, current) => {
|
|
65
|
+
return acc + current.totalDuration;
|
|
66
|
+
}, 0);
|
|
67
|
+
return {
|
|
68
|
+
result: args.result.status,
|
|
69
|
+
startTime: args.startTime,
|
|
70
|
+
endTime: args.endTime,
|
|
71
|
+
numberOfTests: args.numberOfTests,
|
|
72
|
+
browserCreation: args.browserCreation,
|
|
73
|
+
browserClose: args.browserClose,
|
|
74
|
+
testRunId: args.testRunId,
|
|
75
|
+
project: args.project,
|
|
76
|
+
duration: args.endTime - args.startTime,
|
|
77
|
+
failedTestCount: args.failedTests.length,
|
|
78
|
+
flakyTestCount: args.flakyTests.length,
|
|
79
|
+
timeSpentOnRetry,
|
|
80
|
+
teamStats: args.teamStats,
|
|
81
|
+
buildId: args.buildId,
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
exports.formBuildData = formBuildData;
|
|
85
|
+
const addTeamCount = (teamStats, ownerTestAnnotations) => {
|
|
86
|
+
const newTeamStats = { ...teamStats };
|
|
87
|
+
const testOwnerCount = ownerTestAnnotations.reduce((previous, current) => {
|
|
88
|
+
const parsedTeamNameAnnotation = current?.description?.split(",");
|
|
89
|
+
if (!parsedTeamNameAnnotation)
|
|
90
|
+
return {};
|
|
91
|
+
const newData = { ...previous };
|
|
92
|
+
parsedTeamNameAnnotation.forEach((teamName) => {
|
|
93
|
+
const previousValue = previous[teamName] ?? 0;
|
|
94
|
+
newData[teamName] = previousValue + 1;
|
|
95
|
+
});
|
|
96
|
+
return newData;
|
|
97
|
+
}, newTeamStats);
|
|
98
|
+
return testOwnerCount;
|
|
99
|
+
};
|
|
100
|
+
exports.addTeamCount = addTeamCount;
|
|
101
|
+
const getBuildIdWithPrefix = (lastRunData, currentBuildId) => {
|
|
102
|
+
const lastBuildIdWithPrefix = lastRunData?.hits?.hits?.at(0)?._source
|
|
103
|
+
?.buildId;
|
|
104
|
+
const previousPrefix = (() => {
|
|
105
|
+
const defaultPrefix = "0001";
|
|
106
|
+
if (lastBuildIdWithPrefix?.includes("-")) {
|
|
107
|
+
return lastBuildIdWithPrefix?.split("-")?.at(0) ?? defaultPrefix;
|
|
108
|
+
}
|
|
109
|
+
return defaultPrefix;
|
|
110
|
+
})();
|
|
111
|
+
const lastBuildId = (() => {
|
|
112
|
+
if (lastBuildIdWithPrefix?.includes("-")) {
|
|
113
|
+
return lastBuildIdWithPrefix.split("-").at(1);
|
|
114
|
+
}
|
|
115
|
+
return lastBuildIdWithPrefix;
|
|
116
|
+
})();
|
|
117
|
+
if (Number(currentBuildId) < Number(lastBuildId)) {
|
|
118
|
+
const newPrefix = String(Number(previousPrefix) + 1).padStart(4, "0");
|
|
119
|
+
return `${newPrefix}-${currentBuildId.padStart(5, "0")}`;
|
|
120
|
+
}
|
|
121
|
+
return `${previousPrefix}-${currentBuildId.padStart(5, "0")}`;
|
|
122
|
+
};
|
|
123
|
+
exports.getBuildIdWithPrefix = getBuildIdWithPrefix;
|
|
124
|
+
//# sourceMappingURL=transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.js","sourceRoot":"","sources":["../../../src/analytics/transform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.defineRetryReporterConfig = exports.RetryReporter = exports.defineAnalyticsReporterConfig = exports.AnalyticsReporter = void 0;
|
|
27
|
+
const reporter_1 = __importStar(require("./analytics/reporter"));
|
|
28
|
+
exports.AnalyticsReporter = reporter_1.default;
|
|
29
|
+
Object.defineProperty(exports, "defineAnalyticsReporterConfig", { enumerable: true, get: function () { return reporter_1.defineAnalyticsReporterConfig; } });
|
|
30
|
+
const reporter_2 = __importStar(require("./retry/reporter"));
|
|
31
|
+
exports.RetryReporter = reporter_2.default;
|
|
32
|
+
Object.defineProperty(exports, "defineRetryReporterConfig", { enumerable: true, get: function () { return reporter_2.defineRetryReporterConfig; } });
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iEAE8B;AAI7B,4BANM,kBAAiB,CAMN;AACjB,8GANA,wCAA6B,OAMA;AAJ9B,6DAA4E;AAK3E,wBALM,kBAAa,CAKN;AACb,0GANuB,oCAAyB,OAMvB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type FullResult, type Reporter, type TestCase, type TestResult, type TestError } from "@playwright/test/reporter";
|
|
2
|
+
export default class RetryReporter implements Reporter {
|
|
3
|
+
private readonly failedTestNames;
|
|
4
|
+
private readonly flakyTestNames;
|
|
5
|
+
private readonly timeoutMessages;
|
|
6
|
+
private readonly failedProjectName;
|
|
7
|
+
private readonly flakyProjectName;
|
|
8
|
+
private readonly maxRetryCount;
|
|
9
|
+
private readonly isPREnv;
|
|
10
|
+
constructor(options: {
|
|
11
|
+
maxRetryCount: number;
|
|
12
|
+
isPREnv: boolean;
|
|
13
|
+
});
|
|
14
|
+
onTestEnd(test: TestCase, result: TestResult): void;
|
|
15
|
+
onError(error: TestError): void;
|
|
16
|
+
private logFlakyTests;
|
|
17
|
+
private logFailedTests;
|
|
18
|
+
private logTimeout;
|
|
19
|
+
onEnd(result: FullResult): void;
|
|
20
|
+
}
|
|
21
|
+
export declare const defineRetryReporterConfig: (options: ConstructorParameters<typeof RetryReporter>[0]) => {
|
|
22
|
+
maxRetryCount: number;
|
|
23
|
+
isPREnv: boolean;
|
|
24
|
+
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defineRetryReporterConfig = void 0;
|
|
4
|
+
const lodash_1 = require("lodash");
|
|
5
|
+
const escapeBash = (command) => {
|
|
6
|
+
const shouldEscapeRegExp = /[^a-zA-Z0-9_/:=-]/;
|
|
7
|
+
if (shouldEscapeRegExp.test(command)) {
|
|
8
|
+
const removeDuplicateQuotes = command.replace(/^(?:'')+/g, "");
|
|
9
|
+
const removeUnescapedQuotes = removeDuplicateQuotes.replace(/\\'''/g, "\\'");
|
|
10
|
+
return removeUnescapedQuotes;
|
|
11
|
+
}
|
|
12
|
+
return command;
|
|
13
|
+
};
|
|
14
|
+
const formLocalRerunCommand = (projectList) => {
|
|
15
|
+
const baseCommand = "npx playwright test";
|
|
16
|
+
const projectArguments = projectList
|
|
17
|
+
.map((projectName) => `--project=${projectName}`)
|
|
18
|
+
.join(" ");
|
|
19
|
+
return `${baseCommand} ${projectArguments}`;
|
|
20
|
+
};
|
|
21
|
+
// eslint-disable-next-line import/no-default-export
|
|
22
|
+
class RetryReporter {
|
|
23
|
+
constructor(options) {
|
|
24
|
+
this.maxRetryCount = options.maxRetryCount;
|
|
25
|
+
this.isPREnv = options.isPREnv;
|
|
26
|
+
this.failedTestNames = [];
|
|
27
|
+
this.timeoutMessages = [];
|
|
28
|
+
this.failedProjectName = [];
|
|
29
|
+
this.flakyProjectName = [];
|
|
30
|
+
this.flakyTestNames = [];
|
|
31
|
+
}
|
|
32
|
+
onTestEnd(test, result) {
|
|
33
|
+
const projectName = test?.parent?.project()?.name;
|
|
34
|
+
const testPathSegments = test.titlePath();
|
|
35
|
+
const nonEmptyPaths = testPathSegments.filter((pathSegment) => pathSegment);
|
|
36
|
+
const testName = test.title;
|
|
37
|
+
const suiteName = nonEmptyPaths[nonEmptyPaths.length - 2];
|
|
38
|
+
const testNameWithSuite = `${suiteName} ${testName}`;
|
|
39
|
+
if (["failed", "timedOut", "interrupted"].includes(result.status) &&
|
|
40
|
+
result.retry === this.maxRetryCount) {
|
|
41
|
+
const escapedTitle = (0, lodash_1.escapeRegExp)(testNameWithSuite);
|
|
42
|
+
this.failedTestNames.push(escapedTitle);
|
|
43
|
+
if (projectName && !this.failedProjectName.includes(projectName)) {
|
|
44
|
+
this.failedProjectName.push(projectName);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if (result.status === "passed" && result.retry) {
|
|
48
|
+
const escapedTitle = (0, lodash_1.escapeRegExp)(testNameWithSuite);
|
|
49
|
+
this.flakyTestNames.push(escapedTitle);
|
|
50
|
+
if (projectName && !this.flakyProjectName.includes(projectName)) {
|
|
51
|
+
this.flakyProjectName.push(projectName);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
onError(error) {
|
|
56
|
+
if (error?.message?.toLowerCase()?.includes("timed out")) {
|
|
57
|
+
this.timeoutMessages.push(error.message);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
logFlakyTests() {
|
|
61
|
+
if (this.flakyTestNames.length) {
|
|
62
|
+
console.log("-------------------------- FLAKY TESTS --------------------------", "\n");
|
|
63
|
+
const flakyTestsRegex = this.flakyTestNames.join("|");
|
|
64
|
+
const flakyEscapedString = escapeBash(flakyTestsRegex);
|
|
65
|
+
const flakyBufferData = Buffer.from(flakyTestsRegex);
|
|
66
|
+
const flakyBase64String = flakyBufferData.toString("base64");
|
|
67
|
+
console.log("Use the following command to rerun the flaky tests locally:", "\n");
|
|
68
|
+
const npxCommandWithProject = formLocalRerunCommand(this.flakyProjectName);
|
|
69
|
+
console.log(`${npxCommandWithProject} -g '${flakyEscapedString}'`, "\n");
|
|
70
|
+
console.log("---------------------------------------------------------------------------------");
|
|
71
|
+
console.log('Paste the following base64 string in the "Build with parameters" section of Jenkins to rerun the FLAKY tests', "\n");
|
|
72
|
+
console.log(flakyBase64String, "\n");
|
|
73
|
+
console.log("---------------------------------------------------------------------------------");
|
|
74
|
+
console.log("\n");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
logFailedTests() {
|
|
78
|
+
if (this.failedTestNames.length) {
|
|
79
|
+
const failedTestsRegex = this.failedTestNames.join("|");
|
|
80
|
+
const escapedString = escapeBash(failedTestsRegex);
|
|
81
|
+
const bufferData = Buffer.from(failedTestsRegex);
|
|
82
|
+
const base64String = bufferData.toString("base64");
|
|
83
|
+
console.log("-------------------------- FAILED TESTS --------------------------", "\n");
|
|
84
|
+
if (this.failedProjectName.length) {
|
|
85
|
+
console.log("Use the following command to rerun the failed tests locally:", "\n");
|
|
86
|
+
const npxCommandWithProject = formLocalRerunCommand(this.failedProjectName);
|
|
87
|
+
console.log(`${npxCommandWithProject} -g '${escapedString}'`, "\n");
|
|
88
|
+
}
|
|
89
|
+
console.log("---------------------------------------------------------------------------------");
|
|
90
|
+
console.log('Paste the following base64 string in the "Build with parameters" section of Jenkins to rerun the FAILED tests', "\n");
|
|
91
|
+
console.log(base64String, "\n");
|
|
92
|
+
console.log("---------------------------------------------------------------------------------");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
logTimeout() {
|
|
96
|
+
console.log("-------------------------- TOTAL DURATION IS LONGER THAN GLOBAL TIMEOUT --------------------------", "\n");
|
|
97
|
+
this.timeoutMessages.forEach((message) => {
|
|
98
|
+
console.log("*", message);
|
|
99
|
+
});
|
|
100
|
+
console.log("---------------------------------------------------------------------------------");
|
|
101
|
+
}
|
|
102
|
+
onEnd(result) {
|
|
103
|
+
if (this.isPREnv) {
|
|
104
|
+
this.logFlakyTests();
|
|
105
|
+
}
|
|
106
|
+
if (result.status === "failed") {
|
|
107
|
+
this.logFailedTests();
|
|
108
|
+
}
|
|
109
|
+
if (result.status === "timedout") {
|
|
110
|
+
this.logTimeout();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.default = RetryReporter;
|
|
115
|
+
const defineRetryReporterConfig = (options) => options;
|
|
116
|
+
exports.defineRetryReporterConfig = defineRetryReporterConfig;
|
|
117
|
+
//# sourceMappingURL=reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../../../src/retry/reporter.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lokalise/playwright-reporters",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"lint:eslint": "eslint --cache . --ext .js,.cjs,.ts",
|
|
6
|
+
"lint:ts": "tsc --noEmit",
|
|
7
|
+
"lint": "npm run lint:eslint && npm run lint:ts",
|
|
8
|
+
"lint:fix": "npm run lint:eslint -- --fix",
|
|
9
|
+
"test": "playwright test",
|
|
10
|
+
"prepare": "husky install",
|
|
11
|
+
"commit": "commit",
|
|
12
|
+
"build": "tsc -p tsconfig.json"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"./dist/**/*"
|
|
16
|
+
],
|
|
17
|
+
"main": "./dist/src/index",
|
|
18
|
+
"module": "./dist/src/index",
|
|
19
|
+
"types": "./dist/src/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"import": "./dist/src/index.js",
|
|
23
|
+
"require": "./dist/src/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./retry": {
|
|
26
|
+
"import": "./dist/src/retry/reporter.js",
|
|
27
|
+
"require": "./dist/src/retry/reporter.js"
|
|
28
|
+
},
|
|
29
|
+
"./analytics": {
|
|
30
|
+
"import": "./dist/src/analytics/reporter.js",
|
|
31
|
+
"require": "./dist/src/analytics/reporter.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@commitlint/cli": "17.6.7",
|
|
39
|
+
"@commitlint/config-conventional": "17.6.7",
|
|
40
|
+
"@commitlint/prompt-cli": "17.6.7",
|
|
41
|
+
"@lokalise/eslint-config-frontend": "2.0.1",
|
|
42
|
+
"@playwright/test": "^1.36.2",
|
|
43
|
+
"@semantic-release/changelog": "6.0.3",
|
|
44
|
+
"@semantic-release/commit-analyzer": "10.0.1",
|
|
45
|
+
"@semantic-release/git": "10.0.1",
|
|
46
|
+
"@semantic-release/github": "9.0.4",
|
|
47
|
+
"@semantic-release/npm": "10.0.4",
|
|
48
|
+
"@semantic-release/release-notes-generator": "11.0.4",
|
|
49
|
+
"@types/lodash": "^4.14.196",
|
|
50
|
+
"eslint-config-prettier": "8.10.0",
|
|
51
|
+
"eslint-plugin-prettier": "4.2.1",
|
|
52
|
+
"husky": "8.0.3",
|
|
53
|
+
"prettier": "2.8.8",
|
|
54
|
+
"semantic-release": "21.0.7",
|
|
55
|
+
"typescript": "5.1.6"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"@faker-js/faker": "^8.0.2",
|
|
59
|
+
"lodash": "^4.17.21"
|
|
60
|
+
}
|
|
61
|
+
}
|