playwright-slack-report 1.1.4 → 1.1.15
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 +6 -0
- package/dist/src/LayoutGenerator.d.ts +2 -1
- package/dist/src/LayoutGenerator.js +39 -1
- package/dist/src/SlackClient.d.ts +11 -1
- package/dist/src/SlackClient.js +43 -6
- package/dist/src/SlackReporter.d.ts +1 -0
- package/dist/src/SlackReporter.js +13 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -130,6 +130,7 @@ An example advanced configuration is shown below:
|
|
|
130
130
|
slackOAuthToken: 'YOUR_SLACK_OAUTH_TOKEN',
|
|
131
131
|
slackLogLevel: LogLevel.DEBUG,
|
|
132
132
|
enableUnfurl: false,
|
|
133
|
+
showInThread: true,
|
|
133
134
|
},
|
|
134
135
|
|
|
135
136
|
],
|
|
@@ -156,8 +157,13 @@ Instead of providing an environment variable `SLACK_BOT_USER_OAUTH_TOKEN` you ca
|
|
|
156
157
|
This option allows you to control slack client severity levels for log entries. It accepts a value from @slack/web-api `LogLevel` enum
|
|
157
158
|
### **enableUnfurl** (default: true)
|
|
158
159
|
Enable or disable unfurling of links in Slack messages.
|
|
160
|
+
### **showInThread** (default: false)
|
|
161
|
+
Instructs the reporter to show the failure details in a thread instead of the main channel.
|
|
159
162
|
|
|
163
|
+

|
|
160
164
|
|
|
165
|
+
### **meta** (default: empty array)
|
|
166
|
+
The meta data to be sent to Slack. This is useful for providing additional context to your test run.
|
|
161
167
|
|
|
162
168
|
**Examples:**
|
|
163
169
|
```typescript
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
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
|
+
export { generateBlocks, generateFailures };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateFailures = exports.generateBlocks = void 0;
|
|
3
4
|
const generateBlocks = async (summaryResults, maxNumberOfFailures) => {
|
|
4
5
|
const maxNumberOfFailureLength = 650;
|
|
5
6
|
const fails = [];
|
|
@@ -66,4 +67,41 @@ const generateBlocks = async (summaryResults, maxNumberOfFailures) => {
|
|
|
66
67
|
...fails,
|
|
67
68
|
];
|
|
68
69
|
};
|
|
69
|
-
exports.
|
|
70
|
+
exports.generateBlocks = generateBlocks;
|
|
71
|
+
const generateFailures = async (summaryResults, maxNumberOfFailures) => {
|
|
72
|
+
const maxNumberOfFailureLength = 650;
|
|
73
|
+
const fails = [];
|
|
74
|
+
for (let i = 0; i < summaryResults.failures.length; i += 1) {
|
|
75
|
+
const { failureReason, test } = summaryResults.failures[i];
|
|
76
|
+
const formattedFailure = failureReason
|
|
77
|
+
.substring(0, maxNumberOfFailureLength)
|
|
78
|
+
.split('\n')
|
|
79
|
+
.map((l) => `>${l}`)
|
|
80
|
+
.join('\n');
|
|
81
|
+
fails.push({
|
|
82
|
+
type: 'section',
|
|
83
|
+
text: {
|
|
84
|
+
type: 'mrkdwn',
|
|
85
|
+
text: `*${test}*
|
|
86
|
+
\n${formattedFailure}`,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
if (i > maxNumberOfFailures) {
|
|
90
|
+
fails.push({
|
|
91
|
+
type: 'section',
|
|
92
|
+
text: {
|
|
93
|
+
type: 'mrkdwn',
|
|
94
|
+
text: `*There are too many failures to display - ${fails.length} out of ${summaryResults.failures.length} failures shown*`,
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return [
|
|
101
|
+
{
|
|
102
|
+
type: 'divider',
|
|
103
|
+
},
|
|
104
|
+
...fails,
|
|
105
|
+
];
|
|
106
|
+
};
|
|
107
|
+
exports.generateFailures = generateFailures;
|
|
@@ -18,10 +18,20 @@ export default class SlackClient {
|
|
|
18
18
|
slackLogLevel?: LogLevel;
|
|
19
19
|
unfurlEnable?: boolean;
|
|
20
20
|
summaryResults: SummaryResults;
|
|
21
|
+
showInThread: boolean;
|
|
21
22
|
};
|
|
22
23
|
}): Promise<Array<{
|
|
23
24
|
channel: string;
|
|
24
25
|
outcome: string;
|
|
26
|
+
ts: string;
|
|
25
27
|
}>>;
|
|
26
|
-
|
|
28
|
+
attachDetailsToThread({ channelIds, ts, summaryResults, maxNumberOfFailures, unfurlEnable, fakeRequest, }: {
|
|
29
|
+
channelIds: Array<string>;
|
|
30
|
+
ts: string;
|
|
31
|
+
summaryResults: SummaryResults;
|
|
32
|
+
maxNumberOfFailures: number;
|
|
33
|
+
unfurlEnable?: boolean;
|
|
34
|
+
fakeRequest?: Function;
|
|
35
|
+
}): Promise<any[]>;
|
|
36
|
+
static doPostRequest(slackWebClient: WebClient, channel: string, blocks: Array<KnownBlock | Block>, unfurl: boolean, threadTimestamp?: string): Promise<ChatPostMessageResponse>;
|
|
27
37
|
}
|
package/dist/src/SlackClient.js
CHANGED
|
@@ -14,8 +14,13 @@ class SlackClient {
|
|
|
14
14
|
else if (options.customLayoutAsync) {
|
|
15
15
|
blocks = await options.customLayoutAsync(options.summaryResults);
|
|
16
16
|
}
|
|
17
|
+
else if (options.showInThread) {
|
|
18
|
+
const modifiedOptions = JSON.parse(JSON.stringify(options));
|
|
19
|
+
modifiedOptions.summaryResults.failures = [];
|
|
20
|
+
blocks = await (0, LayoutGenerator_1.generateBlocks)(modifiedOptions.summaryResults, options.maxNumberOfFailures);
|
|
21
|
+
}
|
|
17
22
|
else {
|
|
18
|
-
blocks = await (0, LayoutGenerator_1.
|
|
23
|
+
blocks = await (0, LayoutGenerator_1.generateBlocks)(options.summaryResults, options.maxNumberOfFailures);
|
|
19
24
|
}
|
|
20
25
|
if (!options.channelIds) {
|
|
21
26
|
throw new Error(`Channel ids [${options.channelIds}] is not valid`);
|
|
@@ -31,15 +36,22 @@ class SlackClient {
|
|
|
31
36
|
}
|
|
32
37
|
else {
|
|
33
38
|
// send request for reals
|
|
34
|
-
chatResponse = await
|
|
39
|
+
chatResponse = await SlackClient.doPostRequest(this.slackWebClient, channel, blocks, unfurl);
|
|
35
40
|
}
|
|
36
41
|
if (chatResponse.ok) {
|
|
37
|
-
result.push({
|
|
42
|
+
result.push({
|
|
43
|
+
channel,
|
|
44
|
+
outcome: `✅ Message sent to ${channel}`,
|
|
45
|
+
ts: chatResponse.ts,
|
|
46
|
+
});
|
|
38
47
|
// eslint-disable-next-line no-console
|
|
39
48
|
console.log(`✅ Message sent to ${channel}`);
|
|
40
49
|
}
|
|
41
50
|
else {
|
|
42
|
-
result.push({
|
|
51
|
+
result.push({
|
|
52
|
+
channel,
|
|
53
|
+
outcome: `❌ Message not sent to ${channel} \r\n ${JSON.stringify(chatResponse, null, 2)}`,
|
|
54
|
+
});
|
|
43
55
|
}
|
|
44
56
|
}
|
|
45
57
|
catch (error) {
|
|
@@ -51,12 +63,37 @@ class SlackClient {
|
|
|
51
63
|
}
|
|
52
64
|
return result;
|
|
53
65
|
}
|
|
54
|
-
async
|
|
55
|
-
const
|
|
66
|
+
async attachDetailsToThread({ channelIds, ts, summaryResults, maxNumberOfFailures, unfurlEnable, fakeRequest, }) {
|
|
67
|
+
const result = [];
|
|
68
|
+
const blocks = await (0, LayoutGenerator_1.generateFailures)(summaryResults, maxNumberOfFailures);
|
|
69
|
+
for (const channel of channelIds) {
|
|
70
|
+
// under test
|
|
71
|
+
let chatResponse;
|
|
72
|
+
if (fakeRequest) {
|
|
73
|
+
chatResponse = await fakeRequest();
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
chatResponse = await SlackClient.doPostRequest(this.slackWebClient, channel, blocks, unfurlEnable, ts);
|
|
77
|
+
}
|
|
78
|
+
if (chatResponse.ok) {
|
|
79
|
+
// eslint-disable-next-line no-console
|
|
80
|
+
console.log(`✅ Message sent to ${channel} within thread ${ts}`);
|
|
81
|
+
result.push({
|
|
82
|
+
channel,
|
|
83
|
+
outcome: `✅ Message sent to ${channel} within thread ${ts}`,
|
|
84
|
+
ts: chatResponse.ts,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
static async doPostRequest(slackWebClient, channel, blocks, unfurl, threadTimestamp) {
|
|
91
|
+
const chatResponse = await slackWebClient.chat.postMessage({
|
|
56
92
|
channel,
|
|
57
93
|
text: ' ',
|
|
58
94
|
unfurl_link: unfurl,
|
|
59
95
|
blocks,
|
|
96
|
+
thread_ts: threadTimestamp,
|
|
60
97
|
});
|
|
61
98
|
return chatResponse;
|
|
62
99
|
}
|
|
@@ -7,6 +7,7 @@ class SlackReporter {
|
|
|
7
7
|
customLayout;
|
|
8
8
|
customLayoutAsync;
|
|
9
9
|
maxNumberOfFailuresToShow;
|
|
10
|
+
showInThread;
|
|
10
11
|
meta = [];
|
|
11
12
|
resultsParser;
|
|
12
13
|
sendResults = 'on-failure';
|
|
@@ -29,6 +30,7 @@ class SlackReporter {
|
|
|
29
30
|
this.maxNumberOfFailuresToShow = slackReporterConfig.maxNumberOfFailuresToShow || 10;
|
|
30
31
|
this.slackOAuthToken = slackReporterConfig.slackOAuthToken || undefined;
|
|
31
32
|
this.enableUnfurl = slackReporterConfig.enableUnfurl || true;
|
|
33
|
+
this.showInThread = slackReporterConfig.showInThread || false;
|
|
32
34
|
}
|
|
33
35
|
this.resultsParser = new ResultsParser_1.default();
|
|
34
36
|
}
|
|
@@ -46,7 +48,8 @@ class SlackReporter {
|
|
|
46
48
|
resultSummary.meta = this.meta;
|
|
47
49
|
const maxRetry = Math.max(...resultSummary.tests.map((o) => o.retry));
|
|
48
50
|
if (this.sendResults === 'on-failure'
|
|
49
|
-
&& resultSummary.tests.filter((z) => (z.status === 'failed' || z.status === 'timedOut')
|
|
51
|
+
&& resultSummary.tests.filter((z) => (z.status === 'failed' || z.status === 'timedOut')
|
|
52
|
+
&& z.retry === maxRetry).length === 0) {
|
|
50
53
|
this.log('⏩ Slack reporter - no failures found');
|
|
51
54
|
return;
|
|
52
55
|
}
|
|
@@ -61,10 +64,19 @@ class SlackReporter {
|
|
|
61
64
|
maxNumberOfFailures: this.maxNumberOfFailuresToShow,
|
|
62
65
|
unfurlEnable: this.enableUnfurl,
|
|
63
66
|
summaryResults: resultSummary,
|
|
67
|
+
showInThread: this.showInThread,
|
|
64
68
|
},
|
|
65
69
|
});
|
|
66
70
|
// eslint-disable-next-line no-console
|
|
67
71
|
console.log(JSON.stringify(result, null, 2));
|
|
72
|
+
if (this.showInThread && resultSummary.failures.length > 0) {
|
|
73
|
+
await slackClient.attachDetailsToThread({
|
|
74
|
+
channelIds: this.slackChannels,
|
|
75
|
+
ts: result[0].ts,
|
|
76
|
+
summaryResults: resultSummary,
|
|
77
|
+
maxNumberOfFailures: this.maxNumberOfFailuresToShow,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
68
80
|
}
|
|
69
81
|
preChecks() {
|
|
70
82
|
if (this.sendResults === 'off') {
|
package/package.json
CHANGED