From 7719f5db55aef9066a70ab36c3f5f5e427295e0d Mon Sep 17 00:00:00 2001 From: Maciej <100693724+m-kusnierz@users.noreply.github.com> Date: Thu, 11 Jan 2024 10:42:43 +0100 Subject: [PATCH] Support separate Slack channels for successful and failed test results (#82) --- README.md | 4 ++++ src/SlackReporter.ts | 37 ++++++++++++++++++++++++++++--------- tests/SlackReporter.spec.ts | 12 +++++++++--- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 42afbbf..94d8baa 100644 --- a/README.md +++ b/README.md @@ -306,6 +306,10 @@ An example advanced configuration is shown below: ### **channels** An array of Slack channels to post to, at least one channel is required +### **onSuccessChannels** +(Optional) An array of Slack channels to post to when tests have passed. Value from `channels` is used if not defined here +### **onFailureChannels** +(Optional) An array of Slack channels to post to when tests have failed. Value from `channels` is used if not defined here ### **sendResults** Can either be *"always"*, *"on-failure"* or *"off"*, this configuration is required: * **always** - will send the results to Slack at completion of the test run diff --git a/src/SlackReporter.ts b/src/SlackReporter.ts index c7e22b6..c0265bc 100644 --- a/src/SlackReporter.ts +++ b/src/SlackReporter.ts @@ -29,7 +29,9 @@ class SlackReporter implements Reporter { private sendResults: 'always' | 'on-failure' | 'off' = 'on-failure'; - private slackChannels: string[] = []; + private onSuccessSlackChannels: string[] = []; + + private onFailureSlackChannels: string[] = []; private slackLogLevel: LogLevel | undefined; @@ -68,7 +70,10 @@ class SlackReporter implements Reporter { this.sendResults = slackReporterConfig.sendResults || 'always'; this.customLayout = slackReporterConfig.layout; this.customLayoutAsync = slackReporterConfig.layoutAsync; - this.slackChannels = slackReporterConfig.channels; + this.onSuccessSlackChannels + = slackReporterConfig.onSuccessChannels || slackReporterConfig.channels; + this.onFailureSlackChannels + = slackReporterConfig.onFailureChannels || slackReporterConfig.channels; this.maxNumberOfFailuresToShow = slackReporterConfig.maxNumberOfFailuresToShow || 10; this.slackOAuthToken = slackReporterConfig.slackOAuthToken || undefined; @@ -98,12 +103,14 @@ class SlackReporter implements Reporter { ); resultSummary.meta = this.meta; const maxRetry = Math.max(...resultSummary.tests.map((o) => o.retry)); + const testsFailed = resultSummary.tests.some( + (z) => (z.status === 'failed' || z.status === 'timedOut') + && z.retry === maxRetry, + ); + if ( this.sendResults === 'on-failure' - && resultSummary.tests.filter( - (z) => (z.status === 'failed' || z.status === 'timedOut') - && z.retry === maxRetry, - ).length === 0 + && !testsFailed ) { this.log('⏩ Slack reporter - no failures found'); return; @@ -134,9 +141,11 @@ class SlackReporter implements Reporter { ), ); + const slackChannels = testsFailed ? this.onFailureSlackChannels : this.onSuccessSlackChannels; + const result = await slackClient.sendMessage({ options: { - channelIds: this.slackChannels, + channelIds: slackChannels, customLayout: this.customLayout, customLayoutAsync: this.customLayoutAsync, maxNumberOfFailures: this.maxNumberOfFailuresToShow, @@ -208,10 +217,20 @@ class SlackReporter implements Reporter { }; } - if (!this.sendResults || this.slackChannels?.length === 0) { + const noSuccessChannelsProvided = this.sendResults === 'always' && (!this.onSuccessSlackChannels || this.onSuccessSlackChannels.length === 0); + const noFailureChannelsProvided = ['always', 'on-failure'].includes(this.sendResults) && (!this.onFailureSlackChannels || this.onFailureSlackChannels.length === 0); + + if (noSuccessChannelsProvided) { + return { + okToProceed: false, + message: '❌ Slack channel(s) for successful tests notifications was not provided in the config', + }; + } + + if (noFailureChannelsProvided) { return { okToProceed: false, - message: '❌ Slack channel(s) was not provided in the config', + message: '❌ Slack channel(s) for failed tests notifications was not provided in the config', }; } diff --git a/tests/SlackReporter.spec.ts b/tests/SlackReporter.spec.ts index faeb43f..9477803 100644 --- a/tests/SlackReporter.spec.ts +++ b/tests/SlackReporter.spec.ts @@ -257,7 +257,7 @@ test.describe('SlackReporter - preChecks()', () => { const result = fakeSlackReporter.preChecks(); expect(result).toEqual({ okToProceed: false, - message: '❌ Slack channel(s) was not provided in the config', + message: '❌ Slack channel(s) for successful tests notifications was not provided in the config', }); }); @@ -292,7 +292,10 @@ test.describe('SlackReporter - preChecks()', () => { cloneFullConfig.reporter = [ [ '/home/ry/_repo/playwright-slack-report/src/SlackReporter.ts', - { layout: 'not a function' }, + { + layout: 'not a function', + channels: ['zeb', 'pw'], + }, ], ]; fakeSlackReporter.onBegin(cloneFullConfig, suite); @@ -313,7 +316,10 @@ test.describe('SlackReporter - preChecks()', () => { cloneFullConfig.reporter = [ [ '/home/ry/_repo/playwright-slack-report/src/SlackReporter.ts', - { meta: 'not a array' }, + { + meta: 'not a array', + channels: ['zeb', 'pw'], + }, ], ]; fakeSlackReporter.onBegin(cloneFullConfig, suite);