Skip to content

Commit

Permalink
feat: add global report per file (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
deblockt committed Dec 15, 2023
1 parent 0194cae commit 61108ed
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 5 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ jobs:
name: "success empty report"
access-token: ${{ secrets.GITHUB_TOKEN }}
path: "**/cucumber-report-empty.json"
- uses: ./
name: "job with summary"
with:
name: "job with summary"
access-token: ${{ secrets.GITHUB_TOKEN }}
path: "**/cucumber-report.json"
show-global-summary-report: 'true'
- id: check-output
name: "check output for cucumber-report-empty.json"
if: steps.success-with-empty-cucumber-report.output.cucumber-report-empty_failed_scenarios != 0
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This action should be used to publish action annotations from cucumber json repo
- **annotation-status-on-undefined** (optional): the annotation status on undefined steps. Can be 'notice', 'warning', 'failure'. if this property is not set, no annotation will be generated for undefined steps
- **annotation-status-on-pending** (optional): the annotation status on pending steps. Can be 'notice', 'warning', 'failure'. if this property is not set, no annotation will be generated for pending steps
- **number-of-test-error-to-fail-job** (optional): indicate the number of test in error to fail the build. If the value is -1 this action will never fail the build. By default, this action will not cause the build to fail.
- **show-global-summary-report** (optional): if it is set to true, a full summary report will be display for each feature file.

## outputs

Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ inputs:
description: "if it is set to true, the number of errors will be indicated on the check title (visible on the pr check)"
require: true
default: 'true'
show-global-summary-report:
description: "if it is set to true, a full summary report will be display for each feature file."
require: true
default: 'false'
number-of-test-error-to-fail-job:
description: "indicate the number of test in error to fail the build. If the value is -1 this action will never fail the build."
require: true
Expand Down
86 changes: 84 additions & 2 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11964,6 +11964,11 @@ const EMPTY_GLOBAL_INFO = {
pendingStepNumber: 0
}

module.exports.listAllScenarioByFile = (report) => {
return report
.map(fileReport => fileAllScenario(fileReport))
}

module.exports.globalInformation = (report) => {
return report
.map(fileReport => globalFileInformation(fileReport))
Expand Down Expand Up @@ -12006,6 +12011,18 @@ function filePendingStepsData(fileReport) {
.map(pendingScenario => buildPendingData(fileReport, pendingScenario));
}

function fileAllScenario(fileReport) {
return {
file: fileReport.uri,
name: fileReport.name,
scenarios: fileReport.elements
.map(scenario => ({
name: scenario.name,
status: getScenarioStatus(scenario)
}))
}
}

function sum(info1, info2) {
return {
scenarioNumber: info1.scenarioNumber + info2.scenarioNumber,
Expand Down Expand Up @@ -12080,6 +12097,21 @@ function getUndefinedSteps(scenario) {
function getPendingSteps(scenario) {
return getStepByStatus(scenario, 'pending');
}
function getScenarioStatus(scenario) {
const steps = [...scenario.before || [], ...scenario.after || [], ...scenario.steps || []];
for (const step of steps) {
if (step.result.status === 'failed') {
return 'failed';
} else if (step.result.status === 'skipped') {
return 'skipped';
} else if (step.result.status === 'undefined') {
return 'undefined';
} else if (step.result.status === 'pending') {
return 'pending';
}
}
return 'success';
}

function getStepByStatus(scenario, status) {
const before = scenario.before || [];
Expand Down Expand Up @@ -12356,6 +12388,23 @@ async function buildStepAnnotation(cucumberError, status, errorType) {
}
}

async function buildReportDetailAnnotation(fileReport) {
const message = fileReport.scenarios
.map(scenario => `${emojiByStatus(scenario.status)} Scenario: ${scenario.name}`)
.join('\n');

return {
path: (await memoizedFindBestFileMatch(fileReport.file)) || fileReport.file,
start_line: 0,
end_line: 0,
start_column: 0,
end_column: 0,
annotation_level: 'notice',
title: `Feature: ${fileReport.name} Report`,
message
};
}

async function buildErrorAnnotations(cucumberError, statusOnError) {
return await buildStepAnnotation(cucumberError, statusOnError, 'Failed');
}
Expand All @@ -12368,6 +12417,19 @@ async function buildPendingAnnotation(cucumberError, statusOnPending) {
return await buildStepAnnotation(cucumberError, statusOnPending, 'Pending');
}

function emojiByStatus(status) {
switch (status) {
case 'success':
return '✅';
case 'failed':
return '❌'
case 'pending':
return '⌛';
default:
return '-';
}
}

function setOutput(core, outputName, summaryScenario, summarySteps) {
for (const type in summaryScenario) {
core.setOutput(`${outputName}_${type}_scenarios`, summaryScenario[type]);
Expand All @@ -12389,7 +12451,7 @@ function setOutput(core, outputName, summaryScenario, summarySteps) {
const annotationStatusOnPending = core.getInput('annotation-status-on-pending');
const showNumberOfErrorOnCheckTitle = core.getInput('show-number-of-error-on-check-title');
const numberOfTestErrorToFailJob = core.getInput('number-of-test-error-to-fail-job');

const showGlobalSummaryReport = core.getInput('show-global-summary-report')
const globber = await glob.create(inputPath, {
followSymbolicLinks: false,
});
Expand Down Expand Up @@ -12480,11 +12542,31 @@ function setOutput(core, outputName, summaryScenario, summarySteps) {

core.info('Sending cucumber annotations');
const octokit = github.getOctokit(accessToken);
await octokit.rest.checks.create(createCheckRequest);
const checksReponse = await octokit.rest.checks.create(createCheckRequest);

if (numberOfTestErrorToFailJob != -1 && errorAnnotations.length >= numberOfTestErrorToFailJob) {
core.setFailed(`${errorAnnotations.length} test(s) in error`);
}

if (showGlobalSummaryReport === 'true') {
core.info('Building all scenario summary')
const allScenarioByFile = reportReader.listAllScenarioByFile(reportResult);
const allAnnoattions = await Promise.all(
allScenarioByFile
.map(buildReportDetailAnnotation)
.reduce((a, b) => a.concat(b), [])
);
core.info('Send core scenario summary')
await octokit.rest.checks.update({
...github.context.repo,
check_run_id: checksReponse.data.id,
output: {
title: checkName + additionnalTitleInfo,
summary,
annotations: allAnnoattions
}
});
}
}
})();

Expand Down
2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

54 changes: 52 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,23 @@ async function buildStepAnnotation(cucumberError, status, errorType) {
}
}

async function buildReportDetailAnnotation(fileReport) {
const message = fileReport.scenarios
.map(scenario => `${emojiByStatus(scenario.status)} Scenario: ${scenario.name}`)
.join('\n');

return {
path: (await memoizedFindBestFileMatch(fileReport.file)) || fileReport.file,
start_line: 0,
end_line: 0,
start_column: 0,
end_column: 0,
annotation_level: 'notice',
title: `Feature: ${fileReport.name} Report`,
message
};
}

async function buildErrorAnnotations(cucumberError, statusOnError) {
return await buildStepAnnotation(cucumberError, statusOnError, 'Failed');
}
Expand All @@ -62,6 +79,19 @@ async function buildPendingAnnotation(cucumberError, statusOnPending) {
return await buildStepAnnotation(cucumberError, statusOnPending, 'Pending');
}

function emojiByStatus(status) {
switch (status) {
case 'success':
return '✅';
case 'failed':
return '❌'
case 'pending':
return '⌛';
default:
return '-';
}
}

function setOutput(core, outputName, summaryScenario, summarySteps) {
for (const type in summaryScenario) {
core.setOutput(`${outputName}_${type}_scenarios`, summaryScenario[type]);
Expand All @@ -83,7 +113,7 @@ function setOutput(core, outputName, summaryScenario, summarySteps) {
const annotationStatusOnPending = core.getInput('annotation-status-on-pending');
const showNumberOfErrorOnCheckTitle = core.getInput('show-number-of-error-on-check-title');
const numberOfTestErrorToFailJob = core.getInput('number-of-test-error-to-fail-job');

const showGlobalSummaryReport = core.getInput('show-global-summary-report')
const globber = await glob.create(inputPath, {
followSymbolicLinks: false,
});
Expand Down Expand Up @@ -174,11 +204,31 @@ function setOutput(core, outputName, summaryScenario, summarySteps) {

core.info('Sending cucumber annotations');
const octokit = github.getOctokit(accessToken);
await octokit.rest.checks.create(createCheckRequest);
const checksReponse = await octokit.rest.checks.create(createCheckRequest);

if (numberOfTestErrorToFailJob != -1 && errorAnnotations.length >= numberOfTestErrorToFailJob) {
core.setFailed(`${errorAnnotations.length} test(s) in error`);
}

if (showGlobalSummaryReport === 'true') {
core.info('Building all scenario summary')
const allScenarioByFile = reportReader.listAllScenarioByFile(reportResult);
const allAnnoattions = await Promise.all(
allScenarioByFile
.map(buildReportDetailAnnotation)
.reduce((a, b) => a.concat(b), [])
);
core.info('Send core scenario summary')
await octokit.rest.checks.update({
...github.context.repo,
check_run_id: checksReponse.data.id,
output: {
title: checkName + additionnalTitleInfo,
summary,
annotations: allAnnoattions
}
});
}
}
})();

Expand Down
32 changes: 32 additions & 0 deletions reportReader.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ const EMPTY_GLOBAL_INFO = {
pendingStepNumber: 0
}

module.exports.listAllScenarioByFile = (report) => {
return report
.map(fileReport => fileAllScenario(fileReport))
}

module.exports.globalInformation = (report) => {
return report
.map(fileReport => globalFileInformation(fileReport))
Expand Down Expand Up @@ -54,6 +59,18 @@ function filePendingStepsData(fileReport) {
.map(pendingScenario => buildPendingData(fileReport, pendingScenario));
}

function fileAllScenario(fileReport) {
return {
file: fileReport.uri,
name: fileReport.name,
scenarios: fileReport.elements
.map(scenario => ({
name: scenario.name,
status: getScenarioStatus(scenario)
}))
}
}

function sum(info1, info2) {
return {
scenarioNumber: info1.scenarioNumber + info2.scenarioNumber,
Expand Down Expand Up @@ -128,6 +145,21 @@ function getUndefinedSteps(scenario) {
function getPendingSteps(scenario) {
return getStepByStatus(scenario, 'pending');
}
function getScenarioStatus(scenario) {
const steps = [...scenario.before || [], ...scenario.after || [], ...scenario.steps || []];
for (const step of steps) {
if (step.result.status === 'failed') {
return 'failed';
} else if (step.result.status === 'skipped') {
return 'skipped';
} else if (step.result.status === 'undefined') {
return 'undefined';
} else if (step.result.status === 'pending') {
return 'pending';
}
}
return 'success';
}

function getStepByStatus(scenario, status) {
const before = scenario.before || [];
Expand Down

0 comments on commit 61108ed

Please sign in to comment.