diff --git a/src/extensions/hyperlinks.js b/src/extensions/hyperlinks.js index c0d685c..d1c499e 100644 --- a/src/extensions/hyperlinks.js +++ b/src/extensions/hyperlinks.js @@ -1,42 +1,54 @@ -async function run({ target, extension, payload }) { +const { STATUS } = require("../helpers/constants"); + +async function run({ target, extension, payload, result }) { if (target.name === 'teams') { - attachTeamLinks({ extension, payload }); + attachTeamLinks({ extension, payload, result }); } else if (target.name === 'slack') { - attachSlackLinks({ extension, payload }); + attachSlackLinks({ extension, payload, result }); } } -function attachTeamLinks({ extension, payload }) { +function attachTeamLinks({ extension, payload, result }) { const links = []; for (const link of extension.inputs.links) { - links.push(`[${link.text}](${link.url})`); + link["condition"] = link.condition || default_options.condition; + if (link.condition.toLowerCase().includes(result.status.toLowerCase())) { + links.push(`[${link.text}](${link.url})`); + } + } + if (links.length) { + payload.body.push({ + "type": "TextBlock", + "text": links.join(' | '), + "separator": true + }); } - payload.body.push({ - "type": "TextBlock", - "text": links.join(' | '), - "separator": true - }); } -function attachSlackLinks({ extension, payload }) { +function attachSlackLinks({ extension, payload, result }) { const links = []; for (const link of extension.inputs.links) { - links.push(`<${link.url}|${link.text}>`); + link["condition"] = link.condition || default_options.condition; + if (link.condition.toLowerCase().includes(result.status.toLowerCase())) { + links.push(`<${link.url}|${link.text}>`); + } + } + if (links.length) { + payload.blocks.push({ + "type": "context", + "elements": [ + { + "type": "mrkdwn", + "text": links.join(' | ') + } + ] + }); } - payload.blocks.push({ - "type": "context", - "elements": [ - { - "type": "mrkdwn", - "text": links.join(' | ') - } - ] - }); } const default_options = { hook: 'end', - condition: 'passOrFail' + condition: STATUS.PASS_OR_FAIL } module.exports = { diff --git a/src/helpers/constants.js b/src/helpers/constants.js new file mode 100644 index 0000000..2fa2a3a --- /dev/null +++ b/src/helpers/constants.js @@ -0,0 +1,11 @@ +// Constants + +const status = Object.freeze({ + PASS: "pass", + FAIL: "fail", + PASS_OR_FAIL: "passOrfail" +}) + +module.exports = Object.freeze({ + STATUS: status +}) \ No newline at end of file diff --git a/test/ext.hyperlink.spec.js b/test/ext.hyperlink.spec.js index ae8e186..d77b6d5 100644 --- a/test/ext.hyperlink.spec.js +++ b/test/ext.hyperlink.spec.js @@ -4,8 +4,8 @@ const { publish } = require('../src'); describe('extensions - hyperlinks', () => { - it('should send test-summary with links to teams', async () => { - const id = mock.addInteraction('post test-summary with hyperlinks to teams'); + it('should send test-summary with links to teams - default condition', async () => { + const id = mock.addInteraction('post test-summary with hyperlinks to teams - pass status'); await publish({ config: { "reports": [ @@ -50,8 +50,107 @@ describe('extensions - hyperlinks', () => { assert.equal(mock.getInteraction(id).exercised, true); }); - it('should send test-summary with links to slack', async () => { - const id = mock.addInteraction('post test-summary with hyperlinks to slack'); + it('should send test-summary with links to teams - conditional hyperlinks - pass', async () => { + const id = mock.addInteraction('post test-summary with hyperlinks to teams - pass status'); + await publish({ + config: { + "reports": [ + { + "targets": [ + { + "name": "teams", + "inputs": { + "url": "http://localhost:9393/message" + }, + "extensions": [ + { + "name": "hyperlinks", + "inputs": { + "links": [ + { + "text": "Pipeline", + "url": "some-url" + }, + { + "text": "Video", + "url": "some-url", + "condition": "pass" + } + ] + } + } + ] + } + ], + "results": [ + { + "type": "testng", + "files": [ + "test/data/testng/single-suite.xml" + ] + } + ] + } + ] + } + }); + assert.equal(mock.getInteraction(id).exercised, true); + }); + + it('should send test-summary with links to teams - conditional hyperlinks - multiconditions', async () => { + const id = mock.addInteraction('post test-summary with hyperlinks to teams - fail status'); + await publish({ + config: { + "reports": [ + { + "targets": [ + { + "name": "teams", + "inputs": { + "url": "http://localhost:9393/message" + }, + "extensions": [ + { + "name": "hyperlinks", + "inputs": { + "links": [ + { + "text": "Pipeline", + "url": "some-url", + }, + { + "text": "S3 link", + "url": "some-url", + "condition": "pass" + }, + { + "text": "Video", + "url": "some-url", + "condition": "fail" + } + ] + } + } + ] + } + ], + "results": [ + { + "type": "testng", + "files": [ + "test/data/testng/single-suite-failures.xml" + ] + } + ] + } + ] + } + }); + assert.equal(mock.getInteraction(id).exercised, true); + }); + + it('should send test-summary with links to slack - default condition', async () => { + const id = mock.addInteraction('post test-summary with hyperlinks to slack - pass status'); await publish({ config: { "reports": [ @@ -96,6 +195,110 @@ describe('extensions - hyperlinks', () => { assert.equal(mock.getInteraction(id).exercised, true); }); + it('should send test-summary with links to slack - conditional hyperlinks - pass', async () => { + const id = mock.addInteraction('post test-summary with hyperlinks to slack - pass status'); + await publish({ + config: { + "reports": [ + { + "targets": [ + { + "name": "slack", + "inputs": { + "url": "http://localhost:9393/message" + }, + "extensions": [ + { + "name": "hyperlinks", + "inputs": { + "links": [ + { + "text": "Pipeline", + "url": "some-url" + }, + { + "text": "S3 link", + "url": "some-url", + "condition": "fail" + }, + { + "text": "Video", + "url": "some-url", + "condition": "pass" + } + ] + } + } + ] + } + ], + "results": [ + { + "type": "testng", + "files": [ + "test/data/testng/single-suite.xml" + ] + } + ] + } + ] + } + }); + assert.equal(mock.getInteraction(id).exercised, true); + }); + + it('should send test-summary with links to slack - conditional hyperlinks - multiconditions', async () => { + const id = mock.addInteraction('post test-summary with hyperlinks to slack - fail status'); + await publish({ + config: { + "reports": [ + { + "targets": [ + { + "name": "slack", + "inputs": { + "url": "http://localhost:9393/message" + }, + "extensions": [ + { + "name": "hyperlinks", + "inputs": { + "links": [ + { + "text": "Pipeline", + "url": "some-url", + }, + { + "text": "S3 link", + "url": "some-url", + "condition": "pass" + }, + { + "text": "Video", + "url": "some-url", + "condition": "fail" + } + ] + } + } + ] + } + ], + "results": [ + { + "type": "testng", + "files": [ + "test/data/testng/single-suite-failures.xml" + ] + } + ] + } + ] + } + }); + assert.equal(mock.getInteraction(id).exercised, true); + }); + afterEach(() => { mock.clearInteractions(); }); diff --git a/test/mocks/slack.mock.js b/test/mocks/slack.mock.js index e7513b9..16c7264 100644 --- a/test/mocks/slack.mock.js +++ b/test/mocks/slack.mock.js @@ -189,7 +189,7 @@ addInteractionHandler('post failure-details to slack with single suite', () => { } }); -addInteractionHandler('post test-summary with hyperlinks to slack', () => { +addInteractionHandler('post test-summary with hyperlinks to slack - pass status', () => { return { request: { method: 'POST', @@ -226,6 +226,43 @@ addInteractionHandler('post test-summary with hyperlinks to slack', () => { } }); +addInteractionHandler('post test-summary with hyperlinks to slack - fail status', () => { + return { + request: { + method: 'POST', + path: '/message', + body: { + "attachments": [ + { + "color": "#DC143C", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 00:02" + } + }, + { + "type": "context", + "elements": [ + { + "type": "mrkdwn", + "text": "" + } + ] + } + ] + } + ] + } + }, + response: { + status: 200 + } + } +}); + addInteractionHandler('post test-summary to slack with report portal analysis', () => { return { request: { diff --git a/test/mocks/teams.mock.js b/test/mocks/teams.mock.js index 0ab91a4..cfd79ab 100644 --- a/test/mocks/teams.mock.js +++ b/test/mocks/teams.mock.js @@ -402,7 +402,7 @@ addInteractionHandler('post failure-details to teams with single suite', () => { } }); -addInteractionHandler('post test-summary with hyperlinks to teams', () => { +addInteractionHandler('post test-summary with hyperlinks to teams - pass status', () => { return { request: { method: 'POST', @@ -454,6 +454,58 @@ addInteractionHandler('post test-summary with hyperlinks to teams', () => { } }); +addInteractionHandler('post test-summary with hyperlinks to teams - fail status', () => { + return { + request: { + method: 'POST', + path: '/message', + body: { + "type": "message", + "attachments": [ + { + "contentType": "application/vnd.microsoft.card.adaptive", + "content": { + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "version": "1.0", + "body": [ + { + "type": "TextBlock", + "text": "❌ Default suite", + "size": "medium", + "weight": "bolder" + }, + { + "type": "FactSet", + "facts": [ + { + "title": "Results:", + "value": "3 / 4 Passed (75%)" + }, + { + "title": "Duration:", + "value": "00:02" + } + ] + }, + { + "type": "TextBlock", + "text": "[Pipeline](some-url) | [Video](some-url)", + "separator": true + } + ], + "actions": [] + } + } + ] + } + }, + response: { + status: 200 + } + } +}); + addInteractionHandler('post test-summary to teams with report portal analysis', () => { return { request: {