From dfae176dc50cd05381cb797864470892c725373c Mon Sep 17 00:00:00 2001 From: Anudeep Date: Sat, 18 Jun 2022 17:55:01 +0530 Subject: [PATCH] fix: parsing 0 ms duration --- package-lock.json | 18 ++++++--- package.json | 2 +- src/helpers/helper.js | 6 +++ src/index.d.ts | 2 + src/targets/slack.js | 29 +++----------- src/targets/teams.js | 18 ++++----- test/mocks/slack.mock.js | 26 ++++++------- test/mocks/teams.mock.js | 78 ++++++++++++++++++++++++++++++-------- test/targets.teams.spec.js | 31 +++++++++++++++ 9 files changed, 144 insertions(+), 66 deletions(-) diff --git a/package-lock.json b/package-lock.json index c748701..19df6e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -167,11 +167,6 @@ "wrap-ansi": "^7.0.0" } }, - "colon-notation": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/colon-notation/-/colon-notation-1.2.1.tgz", - "integrity": "sha512-WY0rL64V5GiftuqYylUMcM9q+NdOVdFt6IxnapgALGSVG7Yk82cAqRoK5MeakM0b16ZQY0lkHJzxmwBExlJL7A==" - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -640,6 +635,11 @@ "integrity": "sha512-NjvQHHaiPCxPZrhm/kKnorxOv7r/eA+tE0VW5E8iJMH9wTqFA1V0YK/7nbpxVu3JdXUxyWTKMez9lsHUtAwa0w==", "dev": true }, + "parse-ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", + "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==" + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -684,6 +684,14 @@ "trouter": "^2.0.1" } }, + "pretty-ms": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.0.tgz", + "integrity": "sha512-J3aPWiC5e9ZeZFuSeBraGxSkGMOvulSWsxDByOcbD1Pr75YL3LSNIKIb52WXbCLE1sS5s4inBBbryjF4Y05Ceg==", + "requires": { + "parse-ms": "^2.1.0" + } + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", diff --git a/package.json b/package.json index b5f022f..5a7e257 100644 --- a/package.json +++ b/package.json @@ -39,9 +39,9 @@ }, "homepage": "https://test-results-reporter.github.io", "dependencies": { - "colon-notation": "^1.2.1", "dotenv": "^14.3.0", "phin-retry": "^1.0.3", + "pretty-ms": "^7.0.0", "rosters": "0.0.1", "sade": "^1.7.4", "test-results-parser": "^0.0.11" diff --git a/src/helpers/helper.js b/src/helpers/helper.js index 62a7f74..01635d8 100644 --- a/src/helpers/helper.js +++ b/src/helpers/helper.js @@ -1,4 +1,5 @@ const DATA_REF_PATTERN = /(\{[^\}]+\})/g; +const pretty_ms = require('pretty-ms'); function getPercentage(x, y) { if (y > 0) { @@ -47,8 +48,13 @@ function truncate(text, length) { } } +function getPrettyDuration(ms, format) { + return pretty_ms(parseInt(ms), { [format]: true, secondsDecimalDigits: 0 }) +} + module.exports = { getPercentage, processData, truncate, + getPrettyDuration } \ No newline at end of file diff --git a/src/index.d.ts b/src/index.d.ts index 89aea30..d62922f 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -63,6 +63,7 @@ export interface SlackInputs { only_failures?: boolean; title?: string; title_suffix?: string; + duration?: string; } export interface TeamsInputs { @@ -72,6 +73,7 @@ export interface TeamsInputs { title?: string; title_suffix?: string; width?: string; + duration?: string; } export interface Target { diff --git a/src/targets/slack.js b/src/targets/slack.js index 317f3c8..d689647 100644 --- a/src/targets/slack.js +++ b/src/targets/slack.js @@ -1,6 +1,5 @@ const request = require('phin-retry'); -const { getPercentage, truncate } = require('../helpers/helper'); -const { toColonNotation } = require('colon-notation'); +const { getPercentage, truncate, getPrettyDuration } = require('../helpers/helper'); const extension_manager = require('../extensions'); const { HOOK } = require('../helpers/constants'); @@ -44,7 +43,7 @@ function getMainPayload() { function setMainBlock({ result, target, payload }) { let text = `*${getTitleText(result, target)}*\n`; text += `\n*Results*: ${getResultText(result)}`; - text += `\n*Duration*: ${getDurationText(result)}`; + text += `\n*Duration*: ${getPrettyDuration(result.duration, target.inputs.duration)}`; payload.blocks.push({ "type": "section", "text": { @@ -67,10 +66,6 @@ function getResultText(result) { return `${result.passed} / ${result.total} Passed (${percentage}%)`; } -function getDurationText(result) { - return `${toColonNotation(parseInt(result.duration))}`; -} - function setSuiteBlock({ result, target, payload }) { if (target.inputs.include_suites) { for (let i = 0; i < result.suites.length; i++) { @@ -80,7 +75,7 @@ function setSuiteBlock({ result, target, payload }) { } // if suites length eq to 1 then main block will include suite summary if (result.suites.length > 1) { - payload.blocks.push(getSuiteSummary(suite)); + payload.blocks.push(getSuiteSummary({ target, suite })); } if (target.inputs.include_failure_details) { payload.blocks.push(getFailureDetails(suite)); @@ -89,23 +84,10 @@ function setSuiteBlock({ result, target, payload }) { } } -function getSuiteSummary(suite) { - let text = `*${getSuiteTitle(suite)}*\n`; - text += `\n*Results*: ${getResultText(suite)}`; - text += `\n*Duration*: ${getDurationText(suite)}`; - return { - "type": "section", - "text": { - "type": "mrkdwn", - "text": text - } - }; -} - -function getSuiteSummary(suite) { +function getSuiteSummary({ target, suite }) { let text = `*${getSuiteTitle(suite)}*\n`; text += `\n*Results*: ${getResultText(suite)}`; - text += `\n*Duration*: ${getDurationText(suite)}`; + text += `\n*Duration*: ${getPrettyDuration(suite.duration, target.inputs.duration )}`; return { "type": "section", "text": { @@ -167,6 +149,7 @@ const default_inputs = { include_suites: true, only_failure_suites: false, include_failure_details: false, + duration: 'colonNotation' } module.exports = { diff --git a/src/targets/teams.js b/src/targets/teams.js index 558b2be..41de3ae 100644 --- a/src/targets/teams.js +++ b/src/targets/teams.js @@ -1,6 +1,5 @@ const request = require('phin-retry'); -const { toColonNotation } = require('colon-notation'); -const { getPercentage, truncate } = require('../helpers/helper'); +const { getPercentage, truncate, getPrettyDuration } = require('../helpers/helper'); const extension_manager = require('../extensions'); const { HOOK } = require('../helpers/constants'); @@ -10,7 +9,7 @@ async function run({result, target}) { const payload = getMainPayload(target); await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.START }); setTitleBlock(result, { target, payload }); - setMainBlock(result, { target, payload }); + setMainBlock({ result, target, payload }); await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.POST_MAIN }); setSuiteBlock(result, { target, payload }); await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.END }); @@ -76,7 +75,7 @@ function setTitleBlock(result, { target, payload }) { }); } -function setMainBlock(result, { payload }) { +function setMainBlock({ result, target, payload }) { const facts = []; const percentage = getPercentage(result.passed, result.total); facts.push({ @@ -85,7 +84,7 @@ function setMainBlock(result, { payload }) { }); facts.push({ "title": "Duration:", - "value": `${toColonNotation(parseInt(result.duration))}` + "value": `${getPrettyDuration(result.duration, target.inputs.duration)}` }); payload.body.push({ "type": "FactSet", @@ -102,7 +101,7 @@ function setSuiteBlock(result, { target, payload }) { } // if suites length eq to 1 then main block will include suite summary if (result.suites.length > 1) { - payload.body.push(...getSuiteSummary(suite)); + payload.body.push(...getSuiteSummary({ suite, target })); } if (target.inputs.include_failure_details) { payload.body.push(...getFailureDetailsFactSets(suite)); @@ -111,7 +110,7 @@ function setSuiteBlock(result, { target, payload }) { } } -function getSuiteSummary(suite) { +function getSuiteSummary({ suite, target }) { const percentage = getPercentage(suite.passed, suite.total); const emoji = suite.status === 'PASS' ? '✅' : '❌'; return [ @@ -131,7 +130,7 @@ function getSuiteSummary(suite) { }, { "title": "Duration:", - "value": `${toColonNotation(parseInt(suite.duration))}` + "value": `${getPrettyDuration(suite.duration, target.inputs.duration)}` } ] } @@ -187,7 +186,8 @@ const default_inputs = { include_suites: true, only_failure_suites: false, include_failure_details: false, - width: "" + width: '', + duration: 'colonNotation' } module.exports = { diff --git a/test/mocks/slack.mock.js b/test/mocks/slack.mock.js index cf1b03f..dbe16e3 100644 --- a/test/mocks/slack.mock.js +++ b/test/mocks/slack.mock.js @@ -14,7 +14,7 @@ addInteractionHandler('post test-summary to slack', () => { "type": "section", "text": { "type": "mrkdwn", - "text": "*Default suite*\n\n*Results*: 4 / 4 Passed (100%)\n*Duration*: 00:02" + "text": "*Default suite*\n\n*Results*: 4 / 4 Passed (100%)\n*Duration*: 0:02" } } ] @@ -49,14 +49,14 @@ addInteractionHandler('post test-summary to slack with multiple suites', () => { "type": "section", "text": { "type": "mrkdwn", - "text": "*❌ desktop-chrome*\n\n*Results*: 2 / 5 Passed (40%)\n*Duration*: 03:22" + "text": "*❌ desktop-chrome*\n\n*Results*: 2 / 5 Passed (40%)\n*Duration*: 3:22" } }, { "type": "section", "text": { "type": "mrkdwn", - "text": "*❌ mobile-ios*\n\n*Results*: 2 / 5 Passed (40%)\n*Duration*: 09:05" + "text": "*❌ mobile-ios*\n\n*Results*: 2 / 5 Passed (40%)\n*Duration*: 9:05" } } ] @@ -119,7 +119,7 @@ addInteractionHandler('post failure-details to slack with multiple suites', () = "type": "section", "text": { "type": "mrkdwn", - "text": "*❌ desktop-chrome*\n\n*Results*: 2 / 5 Passed (40%)\n*Duration*: 03:22" + "text": "*❌ desktop-chrome*\n\n*Results*: 2 / 5 Passed (40%)\n*Duration*: 3:22" } }, { @@ -133,7 +133,7 @@ addInteractionHandler('post failure-details to slack with multiple suites', () = "type": "section", "text": { "type": "mrkdwn", - "text": "*❌ mobile-ios*\n\n*Results*: 2 / 5 Passed (40%)\n*Duration*: 09:05" + "text": "*❌ mobile-ios*\n\n*Results*: 2 / 5 Passed (40%)\n*Duration*: 9:05" } }, { @@ -168,7 +168,7 @@ addInteractionHandler('post failure-details to slack with single suite', () => { "type": "section", "text": { "type": "mrkdwn", - "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 00:02" + "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 0:02" } }, { @@ -203,7 +203,7 @@ addInteractionHandler('post test-summary with hyperlinks to slack - pass status' "type": "section", "text": { "type": "mrkdwn", - "text": "*Default suite*\n\n*Results*: 4 / 4 Passed (100%)\n*Duration*: 00:02" + "text": "*Default suite*\n\n*Results*: 4 / 4 Passed (100%)\n*Duration*: 0:02" } }, { @@ -240,7 +240,7 @@ addInteractionHandler('post test-summary with hyperlinks to slack - fail status' "type": "section", "text": { "type": "mrkdwn", - "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 00:02" + "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 0:02" } }, { @@ -277,7 +277,7 @@ addInteractionHandler('post test-summary to slack with report portal analysis', "type": "section", "text": { "type": "mrkdwn", - "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 00:02" + "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 0:02" } }, { @@ -312,7 +312,7 @@ addInteractionHandler('post test-summary to slack with report portal analysis wi "type": "section", "text": { "type": "mrkdwn", - "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 00:02" + "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 0:02" } }, { @@ -350,7 +350,7 @@ addInteractionHandler('post test-summary with mentions to slack', () => { "type": "section", "text": { "type": "mrkdwn", - "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 00:02" + "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 0:02" } }, { @@ -385,7 +385,7 @@ addInteractionHandler('post test-summary to slack with qc-test-summary', (ctx) = "type": "section", "text": { "type": "mrkdwn", - "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 00:02" + "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 0:02" }, "accessory": { "type": "image", @@ -418,7 +418,7 @@ addInteractionHandler('post test-summary to slack with report portal history', ( "type": "section", "text": { "type": "mrkdwn", - "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 00:02" + "text": "*Default suite*\n\n*Results*: 3 / 4 Passed (75%)\n*Duration*: 0:02" } }, { diff --git a/test/mocks/teams.mock.js b/test/mocks/teams.mock.js index d334ec3..a595881 100644 --- a/test/mocks/teams.mock.js +++ b/test/mocks/teams.mock.js @@ -31,7 +31,7 @@ addInteractionHandler('post test-summary to teams', () => { }, { "title": "Duration:", - "value": "00:02" + "value": "0:02" } ] } @@ -99,7 +99,7 @@ addInteractionHandler('post test-summary to teams with multiple suites', () => { }, { "title": "Duration:", - "value": "03:22" + "value": "3:22" } ] }, @@ -119,7 +119,7 @@ addInteractionHandler('post test-summary to teams with multiple suites', () => { }, { "title": "Duration:", - "value": "09:05" + "value": "9:05" } ] } @@ -235,7 +235,7 @@ addInteractionHandler('post failure-details to teams with multiple suites', () = }, { "title": "Duration:", - "value": "03:22" + "value": "3:22" } ] }, @@ -294,7 +294,7 @@ addInteractionHandler('post failure-details to teams with multiple suites', () = }, { "title": "Duration:", - "value": "09:05" + "value": "9:05" } ] }, @@ -381,7 +381,7 @@ addInteractionHandler('post failure-details to teams with single suite', () => { }, { "title": "Duration:", - "value": "00:02" + "value": "0:02" } ] }, @@ -442,7 +442,7 @@ addInteractionHandler('post test-summary with hyperlinks to teams - pass status' }, { "title": "Duration:", - "value": "00:02" + "value": "0:02" } ] }, @@ -496,7 +496,7 @@ addInteractionHandler('post test-summary with hyperlinks to teams - fail status' }, { "title": "Duration:", - "value": "00:02" + "value": "0:02" } ] }, @@ -550,7 +550,7 @@ addInteractionHandler('post test-summary with hyperlinks having a title and with }, { "title": "Duration:", - "value": "00:02" + "value": "0:02" } ] }, @@ -611,7 +611,7 @@ addInteractionHandler('post test-summary to teams with report portal analysis', }, { "title": "Duration:", - "value": "00:02" + "value": "0:02" } ] }, @@ -672,7 +672,7 @@ addInteractionHandler('post test-summary to teams with mentions', () => { }, { "title": "Duration:", - "value": "00:02" + "value": "0:02" } ] }, @@ -752,7 +752,7 @@ addInteractionHandler('post test-summary to teams with qc-test-summary', (ctx) = }, { "title": "Duration:", - "value": "00:02" + "value": "0:02" } ] } @@ -817,7 +817,7 @@ addInteractionHandler('post test-summary to teams with report portal history', ( }, { "title": "Duration:", - "value": "00:02" + "value": "0:02" } ] }, @@ -878,7 +878,7 @@ addInteractionHandler('post test-summary to teams with report portal history wit }, { "title": "Duration:", - "value": "00:02" + "value": "0:02" } ] }, @@ -932,7 +932,7 @@ addInteractionHandler('post test-summary to teams with full width', () => { }, { "title": "Duration:", - "value": "00:02" + "value": "0:02" } ] } @@ -950,4 +950,52 @@ addInteractionHandler('post test-summary to teams with full width', () => { status: 200 } } +}); + +addInteractionHandler('post test-summary-slim with verbose duration', () => { + 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": "❌ Regression Tests", + "size": "medium", + "weight": "bolder", + "wrap": true + }, + { + "type": "FactSet", + "facts": [ + { + "title": "Results:", + "value": "8 / 20 Passed (40%)" + }, + { + "title": "Duration:", + "value": "23 minutes 23 seconds" + } + ] + } + ], + "actions": [] + } + } + ] + } + }, + response: { + status: 200 + } + } }); \ No newline at end of file diff --git a/test/targets.teams.spec.js b/test/targets.teams.spec.js index e55bbef..8c34fbc 100644 --- a/test/targets.teams.spec.js +++ b/test/targets.teams.spec.js @@ -182,6 +182,37 @@ describe('targets - teams', () => { assert.equal(mock.getInteraction(id).exercised, true); }); + it('should send test-summary-slim with verbose duration', async () => { + const id = mock.addInteraction('post test-summary-slim with verbose duration'); + await publish({ + config: { + "reports": [ + { + "targets": [ + { + "name": "teams", + "inputs": { + "url": "http://localhost:9393/message", + "publish": "test-summary-slim", + "duration": "verbose" + } + } + ], + "results": [ + { + "type": "testng", + "files": [ + "test/data/testng/multiple-suites.xml" + ] + } + ] + } + ] + } + }); + assert.equal(mock.getInteraction(id).exercised, true); + }); + afterEach(() => { mock.clearInteractions(); });