playwright-slack-report 1.1.1 → 1.1.3

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.
@@ -1,62 +1,62 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const LayoutGenerator_1 = require("./LayoutGenerator");
4
- class SlackClient {
5
- slackWebClient;
6
- constructor(slackClient) {
7
- this.slackWebClient = slackClient;
8
- }
9
- async sendMessage({ options, }) {
10
- let blocks;
11
- if (options.customLayout) {
12
- blocks = options.customLayout(options.summaryResults);
13
- }
14
- else if (options.customLayoutAsync) {
15
- blocks = await options.customLayoutAsync(options.summaryResults);
16
- }
17
- else {
18
- blocks = await (0, LayoutGenerator_1.default)(options.summaryResults, options.maxNumberOfFailures);
19
- }
20
- if (!options.channelIds) {
21
- throw new Error(`Channel ids [${options.channelIds}] is not valid`);
22
- }
23
- const result = [];
24
- for (const channel of options.channelIds) {
25
- let chatResponse;
26
- try {
27
- // under test
28
- if (options.fakeRequest) {
29
- chatResponse = await options.fakeRequest();
30
- }
31
- else {
32
- // send request for reals
33
- chatResponse = await this.doPostRequest(channel, blocks);
34
- }
35
- if (chatResponse.ok) {
36
- result.push({ channel, outcome: `✅ Message sent to ${channel}` });
37
- // eslint-disable-next-line no-console
38
- console.log(`✅ Message sent to ${channel}`);
39
- }
40
- else {
41
- result.push({ channel, outcome: `❌ Message not sent to ${channel} \r\n ${JSON.stringify(chatResponse, null, 2)}` });
42
- }
43
- }
44
- catch (error) {
45
- result.push({
46
- channel,
47
- outcome: `❌ Message not sent to ${channel} \r\n ${error.message}`,
48
- });
49
- }
50
- }
51
- return result;
52
- }
53
- async doPostRequest(channel, blocks) {
54
- const chatResponse = await this.slackWebClient.chat.postMessage({
55
- channel,
56
- text: ' ',
57
- blocks,
58
- });
59
- return chatResponse;
60
- }
61
- }
62
- exports.default = SlackClient;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const LayoutGenerator_1 = require("./LayoutGenerator");
4
+ class SlackClient {
5
+ slackWebClient;
6
+ constructor(slackClient) {
7
+ this.slackWebClient = slackClient;
8
+ }
9
+ async sendMessage({ options, }) {
10
+ let blocks;
11
+ if (options.customLayout) {
12
+ blocks = options.customLayout(options.summaryResults);
13
+ }
14
+ else if (options.customLayoutAsync) {
15
+ blocks = await options.customLayoutAsync(options.summaryResults);
16
+ }
17
+ else {
18
+ blocks = await (0, LayoutGenerator_1.default)(options.summaryResults, options.maxNumberOfFailures);
19
+ }
20
+ if (!options.channelIds) {
21
+ throw new Error(`Channel ids [${options.channelIds}] is not valid`);
22
+ }
23
+ const result = [];
24
+ for (const channel of options.channelIds) {
25
+ let chatResponse;
26
+ try {
27
+ // under test
28
+ if (options.fakeRequest) {
29
+ chatResponse = await options.fakeRequest();
30
+ }
31
+ else {
32
+ // send request for reals
33
+ chatResponse = await this.doPostRequest(channel, blocks);
34
+ }
35
+ if (chatResponse.ok) {
36
+ result.push({ channel, outcome: `✅ Message sent to ${channel}` });
37
+ // eslint-disable-next-line no-console
38
+ console.log(`✅ Message sent to ${channel}`);
39
+ }
40
+ else {
41
+ result.push({ channel, outcome: `❌ Message not sent to ${channel} \r\n ${JSON.stringify(chatResponse, null, 2)}` });
42
+ }
43
+ }
44
+ catch (error) {
45
+ result.push({
46
+ channel,
47
+ outcome: `❌ Message not sent to ${channel} \r\n ${error.message}`,
48
+ });
49
+ }
50
+ }
51
+ return result;
52
+ }
53
+ async doPostRequest(channel, blocks) {
54
+ const chatResponse = await this.slackWebClient.chat.postMessage({
55
+ channel,
56
+ text: ' ',
57
+ blocks,
58
+ });
59
+ return chatResponse;
60
+ }
61
+ }
62
+ exports.default = SlackClient;
@@ -1,23 +1,23 @@
1
- import { FullConfig, Reporter, Suite, TestCase, TestResult } from '@playwright/test/reporter';
2
- declare class SlackReporter implements Reporter {
3
- private customLayout;
4
- private customLayoutAsync;
5
- private maxNumberOfFailuresToShow;
6
- private meta;
7
- private resultsParser;
8
- private sendResults;
9
- private slackChannels;
10
- private slackLogLevel;
11
- private slackOAuthToken;
12
- private suite;
13
- logs: string[];
14
- onBegin(fullConfig: FullConfig, suite: Suite): void;
15
- onTestEnd(test: TestCase, result: TestResult): void;
16
- onEnd(): Promise<void>;
17
- preChecks(): {
18
- okToProceed: boolean;
19
- message?: string;
20
- };
21
- log(message: string | undefined): void;
22
- }
23
- export default SlackReporter;
1
+ import { FullConfig, Reporter, Suite, TestCase, TestResult } from '@playwright/test/reporter';
2
+ declare class SlackReporter implements Reporter {
3
+ private customLayout;
4
+ private customLayoutAsync;
5
+ private maxNumberOfFailuresToShow;
6
+ private meta;
7
+ private resultsParser;
8
+ private sendResults;
9
+ private slackChannels;
10
+ private slackLogLevel;
11
+ private slackOAuthToken;
12
+ private suite;
13
+ logs: string[];
14
+ onBegin(fullConfig: FullConfig, suite: Suite): void;
15
+ onTestEnd(test: TestCase, result: TestResult): void;
16
+ onEnd(): Promise<void>;
17
+ preChecks(): {
18
+ okToProceed: boolean;
19
+ message?: string;
20
+ };
21
+ log(message: string | undefined): void;
22
+ }
23
+ export default SlackReporter;
@@ -1,114 +1,115 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const web_api_1 = require("@slack/web-api");
4
- const ResultsParser_1 = require("./ResultsParser");
5
- const SlackClient_1 = require("./SlackClient");
6
- class SlackReporter {
7
- customLayout;
8
- customLayoutAsync;
9
- maxNumberOfFailuresToShow;
10
- meta = [];
11
- resultsParser;
12
- sendResults = 'on-failure';
13
- slackChannels = [];
14
- slackLogLevel;
15
- slackOAuthToken;
16
- suite;
17
- logs = [];
18
- onBegin(fullConfig, suite) {
19
- this.suite = suite;
20
- this.logs = [];
21
- const slackReporterConfig = fullConfig.reporter.filter((f) => f[0].toLowerCase().includes('slackreporter'))[0][1];
22
- if (slackReporterConfig) {
23
- this.meta = slackReporterConfig.meta || [];
24
- this.sendResults = slackReporterConfig.sendResults || 'always';
25
- this.customLayout = slackReporterConfig.layout;
26
- this.customLayoutAsync = slackReporterConfig.layoutAsync;
27
- this.slackChannels = slackReporterConfig.channels;
28
- this.maxNumberOfFailuresToShow = slackReporterConfig.maxNumberOfFailuresToShow || 10;
29
- }
30
- this.resultsParser = new ResultsParser_1.default();
31
- }
32
- // eslint-disable-next-line class-methods-use-this, no-unused-vars
33
- onTestEnd(test, result) {
34
- this.resultsParser.addTestResult(test.parent.title, test);
35
- }
36
- async onEnd() {
37
- const { okToProceed, message } = this.preChecks();
38
- if (!okToProceed) {
39
- this.log(message);
40
- return;
41
- }
42
- const resultSummary = await this.resultsParser.getParsedResults();
43
- resultSummary.meta = this.meta;
44
- const maxRetry = Math.max(...resultSummary.tests.map((o) => o.retry));
45
- if (this.sendResults === 'on-failure'
46
- && resultSummary.tests.filter((z) => (z.status === 'failed' || z.status === 'timedOut') && z.retry === maxRetry).length === 0) {
47
- this.log('⏩ Slack reporter - no failures found');
48
- return;
49
- }
50
- const slackClient = new SlackClient_1.default(new web_api_1.WebClient(this.slackOAuthToken || process.env.SLACK_BOT_USER_OAUTH_TOKEN, {
51
- logLevel: this.slackLogLevel || web_api_1.LogLevel.DEBUG,
52
- }));
53
- const result = await slackClient.sendMessage({
54
- options: {
55
- channelIds: this.slackChannels,
56
- customLayout: this.customLayout,
57
- customLayoutAsync: this.customLayoutAsync,
58
- maxNumberOfFailures: this.maxNumberOfFailuresToShow,
59
- summaryResults: resultSummary,
60
- },
61
- });
62
- // eslint-disable-next-line no-console
63
- console.log(JSON.stringify(result, null, 2));
64
- }
65
- preChecks() {
66
- if (this.sendResults === 'off') {
67
- return { okToProceed: false, message: '❌ Slack reporter is disabled' };
68
- }
69
- if (!this.slackOAuthToken && !process.env.SLACK_BOT_USER_OAUTH_TOKEN) {
70
- return {
71
- okToProceed: false,
72
- message: '❌ Neither slackOAuthToken nor process.env.SLACK_BOT_USER_OAUTH_TOKEN were found',
73
- };
74
- }
75
- if (!this.sendResults
76
- || !['always', 'on-failure', 'off'].includes(this.sendResults)) {
77
- return {
78
- okToProceed: false,
79
- message: "❌ \"sendResults\" is not valid. Expecting one of ['always', 'on-failure', 'off'].",
80
- };
81
- }
82
- if (!this.sendResults || this.slackChannels?.length === 0) {
83
- return {
84
- okToProceed: false,
85
- message: '❌ Slack channel(s) was not provided in the config',
86
- };
87
- }
88
- if (this.customLayout && typeof this.customLayout !== 'function') {
89
- return {
90
- okToProceed: false,
91
- message: '❌ Custom layout is not a function',
92
- };
93
- }
94
- if (this.customLayoutAsync
95
- && typeof this.customLayoutAsync !== 'function') {
96
- return {
97
- okToProceed: false,
98
- message: '❌ customLayoutAsync is not a function',
99
- };
100
- }
101
- if (this.meta && !Array.isArray(this.meta)) {
102
- return { okToProceed: false, message: '❌ Meta is not an array' };
103
- }
104
- return { okToProceed: true };
105
- }
106
- log(message) {
107
- // eslint-disable-next-line no-console
108
- console.log(message);
109
- if (message) {
110
- this.logs.push(message);
111
- }
112
- }
113
- }
114
- exports.default = SlackReporter;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const web_api_1 = require("@slack/web-api");
4
+ const ResultsParser_1 = require("./ResultsParser");
5
+ const SlackClient_1 = require("./SlackClient");
6
+ class SlackReporter {
7
+ customLayout;
8
+ customLayoutAsync;
9
+ maxNumberOfFailuresToShow;
10
+ meta = [];
11
+ resultsParser;
12
+ sendResults = 'on-failure';
13
+ slackChannels = [];
14
+ slackLogLevel;
15
+ slackOAuthToken;
16
+ suite;
17
+ logs = [];
18
+ onBegin(fullConfig, suite) {
19
+ this.suite = suite;
20
+ this.logs = [];
21
+ const slackReporterConfig = fullConfig.reporter.filter((f) => f[0].toLowerCase().includes('slackreporter'))[0][1];
22
+ if (slackReporterConfig) {
23
+ this.meta = slackReporterConfig.meta || [];
24
+ this.sendResults = slackReporterConfig.sendResults || 'always';
25
+ this.customLayout = slackReporterConfig.layout;
26
+ this.customLayoutAsync = slackReporterConfig.layoutAsync;
27
+ this.slackChannels = slackReporterConfig.channels;
28
+ this.maxNumberOfFailuresToShow = slackReporterConfig.maxNumberOfFailuresToShow || 10;
29
+ this.slackOAuthToken = slackReporterConfig.slackOAuthToken || undefined;
30
+ }
31
+ this.resultsParser = new ResultsParser_1.default();
32
+ }
33
+ // eslint-disable-next-line class-methods-use-this, no-unused-vars
34
+ onTestEnd(test, result) {
35
+ this.resultsParser.addTestResult(test.parent.title, test);
36
+ }
37
+ async onEnd() {
38
+ const { okToProceed, message } = this.preChecks();
39
+ if (!okToProceed) {
40
+ this.log(message);
41
+ return;
42
+ }
43
+ const resultSummary = await this.resultsParser.getParsedResults();
44
+ resultSummary.meta = this.meta;
45
+ const maxRetry = Math.max(...resultSummary.tests.map((o) => o.retry));
46
+ if (this.sendResults === 'on-failure'
47
+ && resultSummary.tests.filter((z) => (z.status === 'failed' || z.status === 'timedOut') && z.retry === maxRetry).length === 0) {
48
+ this.log('⏩ Slack reporter - no failures found');
49
+ return;
50
+ }
51
+ const slackClient = new SlackClient_1.default(new web_api_1.WebClient(this.slackOAuthToken || process.env.SLACK_BOT_USER_OAUTH_TOKEN, {
52
+ logLevel: this.slackLogLevel || web_api_1.LogLevel.DEBUG,
53
+ }));
54
+ const result = await slackClient.sendMessage({
55
+ options: {
56
+ channelIds: this.slackChannels,
57
+ customLayout: this.customLayout,
58
+ customLayoutAsync: this.customLayoutAsync,
59
+ maxNumberOfFailures: this.maxNumberOfFailuresToShow,
60
+ summaryResults: resultSummary,
61
+ },
62
+ });
63
+ // eslint-disable-next-line no-console
64
+ console.log(JSON.stringify(result, null, 2));
65
+ }
66
+ preChecks() {
67
+ if (this.sendResults === 'off') {
68
+ return { okToProceed: false, message: '❌ Slack reporter is disabled' };
69
+ }
70
+ if (!this.slackOAuthToken && !process.env.SLACK_BOT_USER_OAUTH_TOKEN) {
71
+ return {
72
+ okToProceed: false,
73
+ message: '❌ Neither slackOAuthToken nor process.env.SLACK_BOT_USER_OAUTH_TOKEN were found',
74
+ };
75
+ }
76
+ if (!this.sendResults
77
+ || !['always', 'on-failure', 'off'].includes(this.sendResults)) {
78
+ return {
79
+ okToProceed: false,
80
+ message: "❌ \"sendResults\" is not valid. Expecting one of ['always', 'on-failure', 'off'].",
81
+ };
82
+ }
83
+ if (!this.sendResults || this.slackChannels?.length === 0) {
84
+ return {
85
+ okToProceed: false,
86
+ message: '❌ Slack channel(s) was not provided in the config',
87
+ };
88
+ }
89
+ if (this.customLayout && typeof this.customLayout !== 'function') {
90
+ return {
91
+ okToProceed: false,
92
+ message: '❌ Custom layout is not a function',
93
+ };
94
+ }
95
+ if (this.customLayoutAsync
96
+ && typeof this.customLayoutAsync !== 'function') {
97
+ return {
98
+ okToProceed: false,
99
+ message: '❌ customLayoutAsync is not a function',
100
+ };
101
+ }
102
+ if (this.meta && !Array.isArray(this.meta)) {
103
+ return { okToProceed: false, message: '❌ Meta is not an array' };
104
+ }
105
+ return { okToProceed: true };
106
+ }
107
+ log(message) {
108
+ // eslint-disable-next-line no-console
109
+ console.log(message);
110
+ if (message) {
111
+ this.logs.push(message);
112
+ }
113
+ }
114
+ }
115
+ exports.default = SlackReporter;
@@ -1,4 +1,4 @@
1
- import { Block, KnownBlock } from '@slack/types';
2
- import { SummaryResults } from '..';
3
- declare const generateCustomLayout: (summaryResults: SummaryResults) => Array<KnownBlock | Block>;
4
- export default generateCustomLayout;
1
+ import { Block, KnownBlock } from '@slack/types';
2
+ import { SummaryResults } from '..';
3
+ declare const generateCustomLayout: (summaryResults: SummaryResults) => Array<KnownBlock | Block>;
4
+ export default generateCustomLayout;
@@ -1,87 +1,87 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const generateCustomLayout = (summaryResults) => {
4
- const maxNumberOfFailures = 10;
5
- const maxNumberOfFailureLength = 650;
6
- const fails = [];
7
- const meta = [];
8
- for (let i = 0; i < summaryResults.failures.length; i += 1) {
9
- const { failureReason, test } = summaryResults.failures[i];
10
- const formattedFailure = failureReason
11
- .substring(0, maxNumberOfFailureLength)
12
- .split('\n')
13
- .map((l) => `>${l}`)
14
- .join('\n');
15
- fails.push({
16
- type: 'section',
17
- text: {
18
- type: 'mrkdwn',
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const generateCustomLayout = (summaryResults) => {
4
+ const maxNumberOfFailures = 10;
5
+ const maxNumberOfFailureLength = 650;
6
+ const fails = [];
7
+ const meta = [];
8
+ for (let i = 0; i < summaryResults.failures.length; i += 1) {
9
+ const { failureReason, test } = summaryResults.failures[i];
10
+ const formattedFailure = failureReason
11
+ .substring(0, maxNumberOfFailureLength)
12
+ .split('\n')
13
+ .map((l) => `>${l}`)
14
+ .join('\n');
15
+ fails.push({
16
+ type: 'section',
17
+ text: {
18
+ type: 'mrkdwn',
19
19
  text: `*${test}*
20
- \n\n${formattedFailure}`,
21
- },
22
- });
23
- if (i > maxNumberOfFailures) {
24
- fails.push({
25
- type: 'section',
26
- text: {
27
- type: 'mrkdwn',
28
- text: '*There are too many failures to display, view the full results in BuildKite*',
29
- },
30
- });
31
- break;
32
- }
33
- }
34
- if (summaryResults.meta) {
35
- for (let i = 0; i < summaryResults.meta.length; i += 1) {
36
- const { key, value } = summaryResults.meta[i];
37
- meta.push({
38
- type: 'section',
39
- text: {
40
- type: 'mrkdwn',
41
- text: `\n*${key}* :\t${value}`,
42
- },
43
- });
44
- }
45
- }
46
- const testWithStringAttachment = summaryResults.tests.filter((t) => t.attachments)[0];
47
- return [
48
- {
49
- type: 'section',
50
- text: {
51
- type: 'mrkdwn',
52
- text: '**Thisi is cusomter block**',
53
- },
54
- },
55
- {
56
- type: 'section',
57
- text: {
58
- type: 'mrkdwn',
59
- text: `**The first test is:**\n${summaryResults.tests[0].name}`,
60
- },
61
- },
62
- {
63
- type: 'section',
64
- text: {
65
- type: 'mrkdwn',
66
- text: `**Test with attachment:**\n${testWithStringAttachment?.attachments
67
- ?.filter((a) => a.contentType === 'text/plain')
68
- .map((a) => a.body?.toString())}`,
69
- },
70
- },
71
- ...meta,
72
- {
73
- type: 'section',
74
- text: {
75
- type: 'mrkdwn',
76
- text: `:white_check_mark: *${summaryResults.passed}* Tests ran successfully \n\n :red_circle: *${summaryResults.failed}* Tests failed \n\n ${summaryResults.skipped > 0
77
- ? `:fast_forward: *${summaryResults.skipped}* skipped`
78
- : ''} \n\n `,
79
- },
80
- },
81
- {
82
- type: 'divider',
83
- },
84
- ...fails,
85
- ];
86
- };
87
- exports.default = generateCustomLayout;
20
+ \n\n${formattedFailure}`,
21
+ },
22
+ });
23
+ if (i > maxNumberOfFailures) {
24
+ fails.push({
25
+ type: 'section',
26
+ text: {
27
+ type: 'mrkdwn',
28
+ text: '*There are too many failures to display, view the full results in BuildKite*',
29
+ },
30
+ });
31
+ break;
32
+ }
33
+ }
34
+ if (summaryResults.meta) {
35
+ for (let i = 0; i < summaryResults.meta.length; i += 1) {
36
+ const { key, value } = summaryResults.meta[i];
37
+ meta.push({
38
+ type: 'section',
39
+ text: {
40
+ type: 'mrkdwn',
41
+ text: `\n*${key}* :\t${value}`,
42
+ },
43
+ });
44
+ }
45
+ }
46
+ const testWithStringAttachment = summaryResults.tests.filter((t) => t.attachments)[0];
47
+ return [
48
+ {
49
+ type: 'section',
50
+ text: {
51
+ type: 'mrkdwn',
52
+ text: '**Thisi is cusomter block**',
53
+ },
54
+ },
55
+ {
56
+ type: 'section',
57
+ text: {
58
+ type: 'mrkdwn',
59
+ text: `**The first test is:**\n${summaryResults.tests[0].name}`,
60
+ },
61
+ },
62
+ {
63
+ type: 'section',
64
+ text: {
65
+ type: 'mrkdwn',
66
+ text: `**Test with attachment:**\n${testWithStringAttachment?.attachments
67
+ ?.filter((a) => a.contentType === 'text/plain')
68
+ .map((a) => a.body?.toString())}`,
69
+ },
70
+ },
71
+ ...meta,
72
+ {
73
+ type: 'section',
74
+ text: {
75
+ type: 'mrkdwn',
76
+ text: `:white_check_mark: *${summaryResults.passed}* Tests ran successfully \n\n :red_circle: *${summaryResults.failed}* Tests failed \n\n ${summaryResults.skipped > 0
77
+ ? `:fast_forward: *${summaryResults.skipped}* skipped`
78
+ : ''} \n\n `,
79
+ },
80
+ },
81
+ {
82
+ type: 'divider',
83
+ },
84
+ ...fails,
85
+ ];
86
+ };
87
+ exports.default = generateCustomLayout;
@@ -1,3 +1,3 @@
1
- import { Block, KnownBlock } from '@slack/types';
2
- import { SummaryResults } from '..';
3
- export default function generateCustomLayoutSimpleExample(summaryResults: SummaryResults): Array<Block | KnownBlock>;
1
+ import { Block, KnownBlock } from '@slack/types';
2
+ import { SummaryResults } from '..';
3
+ export default function generateCustomLayoutSimpleExample(summaryResults: SummaryResults): Array<Block | KnownBlock>;
@@ -1,16 +1,16 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- function generateCustomLayoutSimpleExample(summaryResults) {
4
- return [
5
- {
6
- type: 'section',
7
- text: {
8
- type: 'mrkdwn',
9
- text: summaryResults.failed === 0
10
- ? ':tada: All tests passed!'
11
- : `😭${summaryResults.failed} failure(s) out of ${summaryResults.tests.length} tests`,
12
- },
13
- },
14
- ];
15
- }
16
- exports.default = generateCustomLayoutSimpleExample;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function generateCustomLayoutSimpleExample(summaryResults) {
4
+ return [
5
+ {
6
+ type: 'section',
7
+ text: {
8
+ type: 'mrkdwn',
9
+ text: summaryResults.failed === 0
10
+ ? ':tada: All tests passed!'
11
+ : `😭${summaryResults.failed} failure(s) out of ${summaryResults.tests.length} tests`,
12
+ },
13
+ },
14
+ ];
15
+ }
16
+ exports.default = generateCustomLayoutSimpleExample;
@@ -1,3 +1,3 @@
1
- import { Block, KnownBlock } from '@slack/types';
2
- import { SummaryResults } from '..';
3
- export default function generateCustomLayoutSimpleMeta(summaryResults: SummaryResults): Array<Block | KnownBlock>;
1
+ import { Block, KnownBlock } from '@slack/types';
2
+ import { SummaryResults } from '..';
3
+ export default function generateCustomLayoutSimpleMeta(summaryResults: SummaryResults): Array<Block | KnownBlock>;