UNPKG

testbeats

Version:

Publish test results to Microsoft Teams, Google Chat, Slack and InfluxDB

274 lines (250 loc) 8.34 kB
const request = require('phin-retry'); const { getTitleText, getResultText, truncate, getPrettyDuration } = require('../helpers/helper'); const extension_manager = require('../extensions'); const { HOOK, STATUS } = require('../helpers/constants'); const PerformanceTestResult = require('performance-results-parser/src/models/PerformanceTestResult'); const { getValidMetrics, getMetricValuesText } = require('../helpers/performance'); const logger = require('../utils/logger'); const { BaseTarget } = require('./base.target'); async function run({ result, target }) { setTargetInputs(target); const root_payload = getRootPayload(); const payload = root_payload.cards[0]; if (result instanceof PerformanceTestResult) { await setPerformancePayload({ result, target, payload, root_payload }); } else { await setFunctionalPayload({ result, target, payload, root_payload }); } logger.info(`🔔 Publishing results to Chat...`); return request.post({ url: target.inputs.url, body: root_payload }); } async function setFunctionalPayload({ result, target, payload, root_payload }) { await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.START }); setMainBlock({ result, target, payload }); await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.AFTER_SUMMARY }); setSuiteBlock({ result, target, payload }); await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.END }); } function setTargetInputs(target) { target.inputs = Object.assign({}, default_inputs, target.inputs); if (target.inputs.publish === 'test-summary-slim') { target.inputs.include_suites = false; } if (target.inputs.publish === 'failure-details') { target.inputs.include_failure_details = true; } } function getRootPayload() { return { "cards": [ { "sections": [] } ] }; } function setMainBlock({ result, target, payload }) { const title_text_with_emoji = getTitleTextWithEmoji({ result, target }); const result_text = getResultText({ result }); const duration_text = getPrettyDuration(result.duration, target.inputs.duration); const text = `<b>${title_text_with_emoji}</b><br><br><b>Results</b>: ${result_text}<br><b>Duration</b>: ${duration_text}`; payload.sections.push({ "widgets": [ { "textParagraph": { text } } ] }); } function setSuiteBlock({ result, target, payload }) { let suite_attachments_length = 0; if (target.inputs.include_suites) { let texts = []; for (let i = 0; i < result.suites.length && suite_attachments_length < target.inputs.max_suites; i++) { const suite = result.suites[i]; if (target.inputs.only_failures && suite.status !== 'FAIL') { continue; } // if suites length eq to 1 then main block will include suite summary if (result.suites.length > 1) { texts.push(getSuiteSummary({ target, suite })); suite_attachments_length += 1; } if (target.inputs.include_failure_details) { texts.push(getFailureDetails(suite)); } } if (texts.length > 0) { payload.sections.push({ "widgets": [ { "textParagraph": { "text": texts.join("<br><br>") } } ] }); } } } function getSuiteSummary({ target, suite }) { const tg = new ChatTarget({ target }); // const platform = getPlatform(TARGET.CHAT); const text = tg.getSuiteSummaryText(target, suite); return text; } function getFailureDetails(suite) { let text = ''; const cases = suite.cases; for (let i = 0; i < cases.length; i++) { const test_case = cases[i]; if (test_case.status === 'FAIL') { text += `<b>Test</b>: ${test_case.name}<br><b>Error</b>: ${truncate(test_case.failure ?? 'N/A', 150)}<br><br>`; } } return text; } function getTitleTextWithEmoji({ result, target }) { const emoji = result.status === 'PASS' ? '✅' : '❌'; const title_text = getTitleText({ result, target }); let title_text_with_emoji = ''; if (target.inputs.include_suites === false) { title_text_with_emoji = `${emoji} ${title_text}`; } else if (result.suites && result.suites.length > 1 || result.transactions && result.transactions.length > 1) { title_text_with_emoji = title_text; } else { title_text_with_emoji = `${emoji} ${title_text}`; } if (target.inputs.title_link) { title_text_with_emoji = `<a href="${target.inputs.title_link}">${title_text_with_emoji}</a>`; } return title_text_with_emoji; } async function setPerformancePayload({ result, target, payload, root_payload }) { await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.START }); await setPerformanceMainBlock({ result, target, payload }); await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.AFTER_SUMMARY }); await setTransactionBlock({ result, target, payload }); await extension_manager.run({ result, target, payload, root_payload, hook: HOOK.END }); } /** * * @param {object} param0 * @param {PerformanceTestResult} param0.result */ async function setPerformanceMainBlock({ result, target, payload }) { const title_text_with_emoji = getTitleTextWithEmoji({ result, target }); const result_text = getResultText({ result }); let text = `<b>${title_text_with_emoji}</b><br><br><b>Results</b>: ${result_text}<br>`; const valid_metrics = await getValidMetrics({ metrics: result.metrics, target, result }); for (let i = 0; i < valid_metrics.length; i++) { const metric = valid_metrics[i]; text += `<br><b>${metric.name}</b>: ${getMetricValuesText({ metric, target, result })}`; } payload.sections.push({ "widgets": [ { "textParagraph": { text } } ] }); } /** * * @param {object} param0 * @param {PerformanceTestResult} param0.result */ async function setTransactionBlock({ result, target, payload }) { if (target.inputs.include_suites) { let texts = []; for (let i = 0; i < result.transactions.length; i++) { const transaction = result.transactions[i]; if (target.inputs.only_failures && transaction.status !== 'FAIL') { continue; } // if transactions length eq to 1 then main block will include suite summary if (result.transactions.length > 1) { texts.push(await getTransactionSummary({ target, transaction, })); } } if (texts.length > 0) { payload.sections.push({ "widgets": [ { "textParagraph": { "text": texts.join("<br><br>") } } ] }); } } } async function getTransactionSummary({ target, transaction }) { const emoji = transaction.status === 'PASS' ? '✅' : '❌'; const suite_title = `${emoji} ${transaction.name}`; let text = `<b>${suite_title}</b><br>`; const valid_metrics = await getValidMetrics({ metrics: transaction.metrics, target, result: transaction }); for (let i = 0; i < valid_metrics.length; i++) { const metric = valid_metrics[i]; text += `<br><b>${metric.name}</b>: ${getMetricValuesText({ metric, target })}`; } return text; } const default_options = { condition: STATUS.PASS_OR_FAIL }; const default_inputs = { publish: 'test-summary', include_suites: true, max_suites: 10, only_failures: true, include_failure_details: false, duration: '', metrics: [ { "name": "Samples", }, { "name": "Duration", "condition": "always", "fields": ["avg", "p95"] } ] }; async function handleErrors({ target, errors }) { let title = 'Error: Reporting Test Results'; title = target.inputs.title ? title + ' - ' + target.inputs.title : title; const root_payload = getRootPayload(); const payload = root_payload.cards[0]; payload.sections.push({ "widgets": [ { "textParagraph": { text: `<b>${title}</b><br><br><b>Errors</b>: <br>${errors.join('<br>')}` } } ] }); return request.post({ url: target.inputs.url, body: root_payload }); } class ChatTarget extends BaseTarget { constructor({ target }) { super({ target }); } } module.exports = { run, handleErrors, default_options }