Skip to content

Commit

Permalink
feat(commitlint-config): add junit formatter
Browse files Browse the repository at this point in the history
Old package was deprecated so we are adding a new one forked into the repo
  • Loading branch information
SimeonC committed Jul 28, 2023
1 parent 0cfaf66 commit 37863a8
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 0 deletions.
8 changes: 8 additions & 0 deletions packages/commitlint-config/README.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@ import { Meta } from '@storybook/addon-docs/blocks';
## Introduction

This package is a rules preset package for [https://commitlint.js.org/](https://commitlint.js.org/).

## Formatters

We provide some custom formatters under the `formatters` folder. Run these by providing the `--formatter` argument to commitlint like as follows;

```sh
npx commitlint --format @tablecheck/commitlint-config/formatters/junit
```
159 changes: 159 additions & 0 deletions packages/commitlint-config/formatters/junit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// @ts-check
/**
* Forked from archived repo - https://github.com/byCedric/Commitlint-Formats/blob/develop/packages/junit/src/junit.js
*/

/**
* Indent the message with an indentation level.
* This will add tabs based on this level.
*
* @param {number} level
* @param {string} line
* @return {string}
*/
function indent(level, line) {
return `${' '.repeat(level)}${line}`;
}

/**
* Escape a string to make it xml safe.
*
* @param {string | number} text
* @return {string}
*/
function escape(text) {
const characters = {
'<': '&lt;',
'>': '&gt;',
'&': '&amp;',
"'": '&apos;',
'"': '&quot;',
};

return String(text).replace(/[<>&'"]/g, (char) => characters[char]);
}

/**
* @typedef {Object} CreateElementOptions
* @property {number} [indent]
* @property {boolean} [selfClosing]
* @property {boolean} [noNewline]
*/

/**
* Create a new XML element containing various properties.
* It can be configured to automatically add a newline, indentation and make it self closing.
*
* @param {string} tag
* @param {CreateElementOptions} options
* @param {Object} attributes
* @return {string}
*/
function createElement(tag, options, attributes) {
const element = `<${tag}`;
const closing = options.selfClosing ? ' />' : '>';
const ending = options.noNewline ? '' : '\n';
const properties = Object.keys(attributes)
.map((key) => `${key}="${escape(attributes[key])}"`)
.join(' ');

return indent(
options.indent || 0,
`${element} ${properties}${closing}${ending}`,
);
}

/**
* Format the commitlint report as a valid JUnit XML report.
*
* @param {import('@commitlint/types').FormattableReport} report
* @return {string}
*/
function formatJunit(report = {}) {
let output = '';

output += indent(0, '<?xml version="1.0" encoding="utf-8"?>\n');
output += indent(0, '<testsuites>\n');

const { results = [] } = report;

const { errorCount, warningCount, testsCount } = results.reduce(
(carry, result) =>
result.input
? carry
: {
errorCount: carry.errorCount + (result.errors?.length || 0),
warningCount: carry.warningCount + (result.warnings?.length || 0),
testsCount:
carry.testsCount +
(result.errors?.length || 0) +
(result.warnings?.length || 0),
},
{ errorCount: 0, warningCount: 0, testsCount: 0 },
);

output += createElement(
'testsuite',
{ indent: 1 },
{
name: 'commitlint',
errors: 0,
failures: errorCount + warningCount,
tests: testsCount,
},
);

results.forEach((result) => {
if (!result.input) return;
const issues = [].concat(result.errors || [], result.warnings || []);

output += createElement(
'testsuite',
{ indent: 2 },
{
name: result.input.split('\n')[0],
errors: 0,
failures: issues.length,
tests: issues.length || 1,
},
);

if (issues.length > 0) {
issues.forEach((issue) => {
const type = issue.level === 2 ? 'error' : 'warning';

output += createElement(
'testcase',
{ indent: 3 },
{ name: issue.name },
);
output += createElement(
'failure',
{ indent: 4, noNewline: true },
{ type },
);
output += '<![CDATA[';
output += `${issue.message} (${issue.name})\n`;
output += ']]>';
output += '</failure>\n';
output += indent(3, '</testcase>\n');
});

output += indent(2, '</testsuite>\n');
} else {
output += createElement(
'testcase',
{ indent: 3, selfClosing: true },
{ name: 'valid' },
);
output += indent(2, '</testsuite>\n');
}
});

output += indent(1, '</testsuite>\n');
output += indent(0, '</testsuites>\n');

return output;
}

module.exports = formatJunit;
8 changes: 8 additions & 0 deletions packages/commitlint-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@
"type": "git",
"url": "[email protected]:tablecheck/frontend.git"
},
"files": [
"index.js",
"formatters"
],
"version": "1.2.0",
"main": "index.js",
"exports": {
".": "./index.js",
"./formatters/junit": "./formatters/junit.js"
},
"dependencies": {
"@commitlint/config-conventional": "^17"
},
Expand Down

0 comments on commit 37863a8

Please sign in to comment.