playwright-slack-report 1.1.1 → 1.1.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.
@@ -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>;
@@ -1,30 +1,30 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- function generateCustomLayoutSimpleMeta(summaryResults) {
4
- const meta = [];
5
- if (summaryResults.meta) {
6
- for (let i = 0; i < summaryResults.meta.length; i += 1) {
7
- const { key, value } = summaryResults.meta[i];
8
- meta.push({
9
- type: 'section',
10
- text: {
11
- type: 'mrkdwn',
12
- text: `\n*${key}* :\t${value}`,
13
- },
14
- });
15
- }
16
- }
17
- return [
18
- {
19
- type: 'section',
20
- text: {
21
- type: 'mrkdwn',
22
- text: summaryResults.failed === 0
23
- ? ':tada: All tests passed!'
24
- : `😭${summaryResults.failed} failure(s) out of ${summaryResults.tests.length} tests`,
25
- },
26
- },
27
- ...meta,
28
- ];
29
- }
30
- exports.default = generateCustomLayoutSimpleMeta;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function generateCustomLayoutSimpleMeta(summaryResults) {
4
+ const meta = [];
5
+ if (summaryResults.meta) {
6
+ for (let i = 0; i < summaryResults.meta.length; i += 1) {
7
+ const { key, value } = summaryResults.meta[i];
8
+ meta.push({
9
+ type: 'section',
10
+ text: {
11
+ type: 'mrkdwn',
12
+ text: `\n*${key}* :\t${value}`,
13
+ },
14
+ });
15
+ }
16
+ }
17
+ return [
18
+ {
19
+ type: 'section',
20
+ text: {
21
+ type: 'mrkdwn',
22
+ text: summaryResults.failed === 0
23
+ ? ':tada: All tests passed!'
24
+ : `😭${summaryResults.failed} failure(s) out of ${summaryResults.tests.length} tests`,
25
+ },
26
+ },
27
+ ...meta,
28
+ ];
29
+ }
30
+ exports.default = generateCustomLayoutSimpleMeta;
@@ -1,32 +1,32 @@
1
- /// <reference types="node" />
2
- export declare type SummaryResults = {
3
- passed: number;
4
- failed: number;
5
- skipped: number;
6
- failures: Array<failure>;
7
- meta?: Array<{
8
- key: string;
9
- value: string;
10
- }>;
11
- tests: Array<{
12
- suiteName: string;
13
- name: string;
14
- browser?: string;
15
- projectName?: string;
16
- endedAt: string;
17
- reason: string;
18
- retry: number;
19
- startedAt: string;
20
- status: 'passed' | 'failed' | 'timedOut' | 'skipped';
21
- attachments?: {
22
- body: string | undefined | Buffer;
23
- contentType: string;
24
- name: string;
25
- path: string;
26
- }[];
27
- }>;
28
- };
29
- export declare type failure = {
30
- test: string;
31
- failureReason: string;
32
- };
1
+ /// <reference types="node" />
2
+ export declare type SummaryResults = {
3
+ passed: number;
4
+ failed: number;
5
+ skipped: number;
6
+ failures: Array<failure>;
7
+ meta?: Array<{
8
+ key: string;
9
+ value: string;
10
+ }>;
11
+ tests: Array<{
12
+ suiteName: string;
13
+ name: string;
14
+ browser?: string;
15
+ projectName?: string;
16
+ endedAt: string;
17
+ reason: string;
18
+ retry: number;
19
+ startedAt: string;
20
+ status: 'passed' | 'failed' | 'timedOut' | 'skipped';
21
+ attachments?: {
22
+ body: string | undefined | Buffer;
23
+ contentType: string;
24
+ name: string;
25
+ path: string;
26
+ }[];
27
+ }>;
28
+ };
29
+ export declare type failure = {
30
+ test: string;
31
+ failureReason: string;
32
+ };
package/dist/src/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });