playwright-slack-report 1.1.24 → 1.1.25
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 +0 -2
- package/dist/src/LayoutGenerator.d.ts +2 -1
- package/dist/src/LayoutGenerator.js +3 -1
- package/dist/src/ResultsParser.d.ts +4 -11
- package/dist/src/ResultsParser.js +14 -57
- package/dist/src/SlackClient.d.ts +1 -1
- package/dist/src/SlackClient.js +6 -4
- package/dist/src/SlackReporter.d.ts +0 -1
- package/dist/src/SlackReporter.js +2 -6
- package/dist/src/index.d.ts +0 -7
- package/package.json +13 -4
package/README.md
CHANGED
|
@@ -179,8 +179,6 @@ A function that returns a layout object, this configuration is optional. See se
|
|
|
179
179
|
Same as **layout** above, but asynchronous in that it returns a promise.
|
|
180
180
|
### **maxNumberOfFailuresToShow**
|
|
181
181
|
Limits the number of failures shown in the Slack message, defaults to 10.
|
|
182
|
-
### **separateFlaky**
|
|
183
|
-
Don't consider flaky tests as passed, instead output them separately. Flaky tests are tests that passed but not on the first try. This defaults to `false` but it is highly recommended that you switch this on.
|
|
184
182
|
### **slackOAuthToken**
|
|
185
183
|
Instead of providing an environment variable `SLACK_BOT_USER_OAUTH_TOKEN` you can specify the token in the config in the `slackOAuthToken` field.
|
|
186
184
|
### **slackLogLevel** (default LogLevel.DEBUG)
|
|
@@ -2,4 +2,5 @@ import { KnownBlock, Block } from '@slack/types';
|
|
|
2
2
|
import { SummaryResults } from '.';
|
|
3
3
|
declare const generateBlocks: (summaryResults: SummaryResults, maxNumberOfFailures: number) => Promise<Array<KnownBlock | Block>>;
|
|
4
4
|
declare const generateFailures: (summaryResults: SummaryResults, maxNumberOfFailures: number) => Promise<Array<KnownBlock | Block>>;
|
|
5
|
-
|
|
5
|
+
declare const generateFallbackText: (summaryResults: SummaryResults) => string;
|
|
6
|
+
export { generateBlocks, generateFailures, generateFallbackText };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateFailures = exports.generateBlocks = void 0;
|
|
3
|
+
exports.generateFallbackText = exports.generateFailures = exports.generateBlocks = void 0;
|
|
4
4
|
const generateBlocks = async (summaryResults, maxNumberOfFailures) => {
|
|
5
5
|
const meta = [];
|
|
6
6
|
const header = {
|
|
@@ -72,3 +72,5 @@ const generateFailures = async (summaryResults, maxNumberOfFailures) => {
|
|
|
72
72
|
];
|
|
73
73
|
};
|
|
74
74
|
exports.generateFailures = generateFailures;
|
|
75
|
+
const generateFallbackText = (summaryResults) => `✅ ${summaryResults.passed} ❌ ${summaryResults.failed} ${summaryResults.flaky !== undefined ? ` 🟡 ${summaryResults.flaky} ` : ' '}⏩ ${summaryResults.skipped}`;
|
|
76
|
+
exports.generateFallbackText = generateFallbackText;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import {
|
|
2
|
+
import { TestCase } from '@playwright/test/reporter';
|
|
3
|
+
import { failure, SummaryResults } from '.';
|
|
3
4
|
export declare type testResult = {
|
|
4
5
|
suiteName: string;
|
|
5
6
|
name: string;
|
|
@@ -27,14 +28,9 @@ export declare type testSuite = {
|
|
|
27
28
|
};
|
|
28
29
|
export default class ResultsParser {
|
|
29
30
|
private result;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
separateFlakyTests: boolean;
|
|
33
|
-
});
|
|
34
|
-
getParsedResults(): Promise<SummaryResults>;
|
|
31
|
+
constructor();
|
|
32
|
+
getParsedResults(allTests: Array<TestCase>): Promise<SummaryResults>;
|
|
35
33
|
getFailures(): Promise<Array<failure>>;
|
|
36
|
-
getFlakes(): Promise<Array<flaky>>;
|
|
37
|
-
getPasses(): Promise<Array<pass>>;
|
|
38
34
|
static getTestName(failedTest: any): any;
|
|
39
35
|
updateResults(data: {
|
|
40
36
|
testSuite: any;
|
|
@@ -55,7 +51,4 @@ export default class ResultsParser {
|
|
|
55
51
|
projectName: string;
|
|
56
52
|
browser: string;
|
|
57
53
|
};
|
|
58
|
-
/** removes tests from the passed array that only passed on a retry (flaky).
|
|
59
|
-
* Does not modify param passed, returns a new passed array. */
|
|
60
|
-
doSeparateFlakyTests(passes: Array<pass>, flakes: Array<flaky>): pass[];
|
|
61
54
|
}
|
|
@@ -8,33 +8,29 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
class ResultsParser {
|
|
10
10
|
result;
|
|
11
|
-
|
|
12
|
-
constructor(options = { separateFlakyTests: false }) {
|
|
11
|
+
constructor() {
|
|
13
12
|
this.result = [];
|
|
14
|
-
this.separateFlakyTests = options.separateFlakyTests;
|
|
15
13
|
}
|
|
16
|
-
async getParsedResults() {
|
|
14
|
+
async getParsedResults(allTests) {
|
|
17
15
|
const failures = await this.getFailures();
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
16
|
+
// use Playwright recommended way of extracting test stats:
|
|
17
|
+
// https://github.com/microsoft/playwright/issues/27498#issuecomment-1766766335
|
|
18
|
+
const stats = {
|
|
19
|
+
expected: 0, skipped: 0, unexpected: 0, flaky: 0,
|
|
20
|
+
};
|
|
21
|
+
// eslint-disable-next-line no-plusplus
|
|
22
|
+
for (const test of allTests)
|
|
23
|
+
++stats[test.outcome()];
|
|
23
24
|
const summary = {
|
|
24
|
-
passed:
|
|
25
|
-
failed:
|
|
26
|
-
flaky:
|
|
27
|
-
skipped:
|
|
25
|
+
passed: stats.expected,
|
|
26
|
+
failed: stats.unexpected,
|
|
27
|
+
flaky: stats.flaky,
|
|
28
|
+
skipped: stats.skipped,
|
|
28
29
|
failures,
|
|
29
30
|
tests: [],
|
|
30
31
|
};
|
|
31
32
|
for (const suite of this.result) {
|
|
32
33
|
summary.tests = summary.tests.concat(suite.testSuite.tests);
|
|
33
|
-
for (const test of suite.testSuite.tests) {
|
|
34
|
-
if (test.status === 'skipped') {
|
|
35
|
-
summary.skipped += 1;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
34
|
}
|
|
39
35
|
return summary;
|
|
40
36
|
}
|
|
@@ -55,33 +51,6 @@ class ResultsParser {
|
|
|
55
51
|
}
|
|
56
52
|
return failures;
|
|
57
53
|
}
|
|
58
|
-
async getFlakes() {
|
|
59
|
-
const flaky = [];
|
|
60
|
-
for (const suite of this.result) {
|
|
61
|
-
for (const test of suite.testSuite.tests) {
|
|
62
|
-
if (test.status === 'passed' && test.retry > 0) {
|
|
63
|
-
flaky.push({
|
|
64
|
-
test: ResultsParser.getTestName(test),
|
|
65
|
-
retry: test.retry,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return flaky;
|
|
71
|
-
}
|
|
72
|
-
async getPasses() {
|
|
73
|
-
const passes = [];
|
|
74
|
-
for (const suite of this.result) {
|
|
75
|
-
for (const test of suite.testSuite.tests) {
|
|
76
|
-
if (test.status === 'passed') {
|
|
77
|
-
passes.push({
|
|
78
|
-
test: ResultsParser.getTestName(test),
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return passes;
|
|
84
|
-
}
|
|
85
54
|
static getTestName(failedTest) {
|
|
86
55
|
const testName = failedTest.name;
|
|
87
56
|
if (failedTest.browser && failedTest.projectName) {
|
|
@@ -154,17 +123,5 @@ class ResultsParser {
|
|
|
154
123
|
browser: '',
|
|
155
124
|
};
|
|
156
125
|
}
|
|
157
|
-
/** removes tests from the passed array that only passed on a retry (flaky).
|
|
158
|
-
* Does not modify param passed, returns a new passed array. */
|
|
159
|
-
doSeparateFlakyTests(passes, flakes) {
|
|
160
|
-
const _passes = new Map();
|
|
161
|
-
for (const pass of passes) {
|
|
162
|
-
_passes.set(pass.test, pass);
|
|
163
|
-
}
|
|
164
|
-
for (const flake of flakes) {
|
|
165
|
-
_passes.delete(flake.test);
|
|
166
|
-
}
|
|
167
|
-
return [..._passes.values()];
|
|
168
|
-
}
|
|
169
126
|
}
|
|
170
127
|
exports.default = ResultsParser;
|
|
@@ -33,5 +33,5 @@ export default class SlackClient {
|
|
|
33
33
|
disableUnfurl?: boolean;
|
|
34
34
|
fakeRequest?: Function;
|
|
35
35
|
}): Promise<any[]>;
|
|
36
|
-
static doPostRequest(slackWebClient: WebClient, channel: string, blocks: Array<KnownBlock | Block>, unfurl: boolean, threadTimestamp?: string): Promise<ChatPostMessageResponse>;
|
|
36
|
+
static doPostRequest(slackWebClient: WebClient, channel: string, fallbackText: string, blocks: Array<KnownBlock | Block>, unfurl: boolean, threadTimestamp?: string): Promise<ChatPostMessageResponse>;
|
|
37
37
|
}
|
package/dist/src/SlackClient.js
CHANGED
|
@@ -25,6 +25,7 @@ class SlackClient {
|
|
|
25
25
|
if (!options.channelIds) {
|
|
26
26
|
throw new Error(`Channel ids [${options.channelIds}] is not valid`);
|
|
27
27
|
}
|
|
28
|
+
const fallbackText = (0, LayoutGenerator_1.generateFallbackText)(options.summaryResults);
|
|
28
29
|
const result = [];
|
|
29
30
|
const unfurl = !options.disableUnfurl;
|
|
30
31
|
for (const channel of options.channelIds) {
|
|
@@ -36,7 +37,7 @@ class SlackClient {
|
|
|
36
37
|
}
|
|
37
38
|
else {
|
|
38
39
|
// send request for reals
|
|
39
|
-
chatResponse = await SlackClient.doPostRequest(this.slackWebClient, channel, blocks, unfurl);
|
|
40
|
+
chatResponse = await SlackClient.doPostRequest(this.slackWebClient, channel, fallbackText, blocks, unfurl);
|
|
40
41
|
}
|
|
41
42
|
if (chatResponse.ok) {
|
|
42
43
|
result.push({
|
|
@@ -66,6 +67,7 @@ class SlackClient {
|
|
|
66
67
|
async attachDetailsToThread({ channelIds, ts, summaryResults, maxNumberOfFailures, disableUnfurl, fakeRequest, }) {
|
|
67
68
|
const result = [];
|
|
68
69
|
const blocks = await (0, LayoutGenerator_1.generateFailures)(summaryResults, maxNumberOfFailures);
|
|
70
|
+
const fallbackText = (0, LayoutGenerator_1.generateFallbackText)(summaryResults);
|
|
69
71
|
for (const channel of channelIds) {
|
|
70
72
|
// under test
|
|
71
73
|
let chatResponse;
|
|
@@ -73,7 +75,7 @@ class SlackClient {
|
|
|
73
75
|
chatResponse = await fakeRequest();
|
|
74
76
|
}
|
|
75
77
|
else {
|
|
76
|
-
chatResponse = await SlackClient.doPostRequest(this.slackWebClient, channel, blocks, disableUnfurl, ts);
|
|
78
|
+
chatResponse = await SlackClient.doPostRequest(this.slackWebClient, channel, fallbackText, blocks, disableUnfurl, ts);
|
|
77
79
|
}
|
|
78
80
|
if (chatResponse.ok) {
|
|
79
81
|
// eslint-disable-next-line no-console
|
|
@@ -87,10 +89,10 @@ class SlackClient {
|
|
|
87
89
|
}
|
|
88
90
|
return result;
|
|
89
91
|
}
|
|
90
|
-
static async doPostRequest(slackWebClient, channel, blocks, unfurl, threadTimestamp) {
|
|
92
|
+
static async doPostRequest(slackWebClient, channel, fallbackText, blocks, unfurl, threadTimestamp) {
|
|
91
93
|
const chatResponse = await slackWebClient.chat.postMessage({
|
|
92
94
|
channel,
|
|
93
|
-
text:
|
|
95
|
+
text: fallbackText,
|
|
94
96
|
unfurl_link: unfurl,
|
|
95
97
|
blocks,
|
|
96
98
|
thread_ts: threadTimestamp,
|
|
@@ -15,7 +15,6 @@ declare class SlackReporter implements Reporter {
|
|
|
15
15
|
private proxy;
|
|
16
16
|
private browsers;
|
|
17
17
|
private suite;
|
|
18
|
-
private separateFlaky;
|
|
19
18
|
logs: string[];
|
|
20
19
|
onBegin(fullConfig: FullConfig, suite: Suite): void;
|
|
21
20
|
onTestEnd(test: TestCase, result: TestResult): void;
|
|
@@ -22,7 +22,6 @@ class SlackReporter {
|
|
|
22
22
|
proxy;
|
|
23
23
|
browsers = [];
|
|
24
24
|
suite;
|
|
25
|
-
separateFlaky = false;
|
|
26
25
|
logs = [];
|
|
27
26
|
onBegin(fullConfig, suite) {
|
|
28
27
|
this.suite = suite;
|
|
@@ -54,11 +53,8 @@ class SlackReporter {
|
|
|
54
53
|
this.showInThread = slackReporterConfig.showInThread || false;
|
|
55
54
|
this.slackLogLevel = slackReporterConfig.slackLogLevel || web_api_1.LogLevel.DEBUG;
|
|
56
55
|
this.proxy = slackReporterConfig.proxy || undefined;
|
|
57
|
-
this.separateFlaky = slackReporterConfig.separateFlaky || false;
|
|
58
56
|
}
|
|
59
|
-
this.resultsParser = new ResultsParser_1.default(
|
|
60
|
-
separateFlakyTests: this.separateFlaky,
|
|
61
|
-
});
|
|
57
|
+
this.resultsParser = new ResultsParser_1.default();
|
|
62
58
|
}
|
|
63
59
|
// eslint-disable-next-line class-methods-use-this, no-unused-vars
|
|
64
60
|
onTestEnd(test, result) {
|
|
@@ -70,7 +66,7 @@ class SlackReporter {
|
|
|
70
66
|
this.log(message);
|
|
71
67
|
return;
|
|
72
68
|
}
|
|
73
|
-
const resultSummary = await this.resultsParser.getParsedResults();
|
|
69
|
+
const resultSummary = await this.resultsParser.getParsedResults(this.suite.allTests());
|
|
74
70
|
resultSummary.meta = this.meta;
|
|
75
71
|
const maxRetry = Math.max(...resultSummary.tests.map((o) => o.retry));
|
|
76
72
|
if (this.sendResults === 'on-failure'
|
package/dist/src/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"dependencies": {
|
|
3
|
-
"@slack/web-api": "^6.
|
|
4
|
-
"@slack/webhook": "^
|
|
3
|
+
"@slack/web-api": "^6.9.1",
|
|
4
|
+
"@slack/webhook": "^7.0.1",
|
|
5
5
|
"https-proxy-agent": "^7.0.1"
|
|
6
6
|
},
|
|
7
7
|
"devDependencies": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"lint-fix": "npx eslint . --ext .ts --fix"
|
|
31
31
|
},
|
|
32
32
|
"name": "playwright-slack-report",
|
|
33
|
-
"version": "1.1.
|
|
33
|
+
"version": "1.1.25",
|
|
34
34
|
"main": "index.js",
|
|
35
35
|
"types": "dist/index.d.ts",
|
|
36
36
|
"repository": "git@github.com:ryanrosello-og/playwright-slack-report.git",
|
|
@@ -44,5 +44,14 @@
|
|
|
44
44
|
"report",
|
|
45
45
|
"playwright",
|
|
46
46
|
"typescript"
|
|
47
|
-
]
|
|
47
|
+
],
|
|
48
|
+
"nyc": {
|
|
49
|
+
"all": true,
|
|
50
|
+
"include": [
|
|
51
|
+
"src/**/*.ts"
|
|
52
|
+
],
|
|
53
|
+
"exclude": [
|
|
54
|
+
"./src/custom_block/my_block.ts"
|
|
55
|
+
]
|
|
56
|
+
}
|
|
48
57
|
}
|