Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jest-community/jest-junit
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v10.0.0
Choose a base ref
...
head repository: jest-community/jest-junit
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4e21bc35354ec60f7588f9b765b5cfbec9d81870
Choose a head ref
  • 5 commits
  • 12 files changed
  • 1 contributor

Commits on Dec 18, 2019

  1. Update README.md

    palmerj3 authored Dec 18, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    7f53d6e View commit details

Commits on Jun 20, 2020

  1. Copy the full SHA
    2822fa1 View commit details
  2. Copy the full SHA
    2b4ad87 View commit details
  3. Copy the full SHA
    d3a2b21 View commit details
  4. Merge pull request #129 from palmerj3/addPropertiesSupport

    Add support for test suite properties. Upgrade mkdirp. Drop node < 10 support
    palmerj3 authored Jun 20, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4e21bc3 View commit details
8 changes: 3 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
language: node_js
node_js:
- "8"
- "10"
- "12"
- "13"
- "14"
env:
- JEST_VERSION=^22.0.0
- JEST_VERSION=^23.0.0
- JEST_VERSION=^24.0.0
- JEST_VERSION=^24.9.0
- JEST_VERSION=^26.0.0
script:
- npm run test:ci
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -3,14 +3,13 @@
# jest-junit
A Jest reporter that creates compatible junit xml files

Note: as of jest-junit 11.0.0 NodeJS >= 10.12.0 is required.

## Installation
```shell
yarn add --dev jest-junit
```

## Important Notice
Soon jest-junit will no longer function as a testResultProcessor. It will only work as a jest reporter. See the docs just below this for how to transition your project.

## Usage
In your jest config add the following entry:
```JSON
@@ -220,3 +219,28 @@ renders
</testsuite>
</testsuites>
```

#### Adding custom testsuite properties
New feature as of jest-junit 11.0.0!

Create a file in your project root directory named junitProperties.js:
```js
module.exports = () => {
return {
key: "value"
}
});
```

Will render
```xml
<testsuites name="jest tests">
<testsuite name="addition" tests="1" errors="0" failures="0" skipped="0" timestamp="2017-07-13T09:42:28" time="0.161">
<properties>
<property name="key" value="value" />
</properties>
<testcase classname="addition positive numbers should add up" name="addition positive numbers should add up" time="0.004">
</testcase>
</testsuite>
</testsuites>
```
24 changes: 24 additions & 0 deletions __tests__/__snapshots__/buildJsonResults.test.js.snap
Original file line number Diff line number Diff line change
@@ -24,6 +24,18 @@ Object {
"timestamp": "2018-02-10T14:52:31",
},
},
Object {
"properties": Array [
Object {
"property": Object {
"_attr": Object {
"name": "best-tester",
"value": "Jason Palmer",
},
},
},
],
},
Object {
"testcase": Array [
Object {
@@ -50,6 +62,18 @@ Object {
"timestamp": "2018-02-10T14:52:31",
},
},
Object {
"properties": Array [
Object {
"property": Object {
"_attr": Object {
"name": "best-tester",
"value": "Jason Palmer",
},
},
},
],
},
Object {
"testcase": Array [
Object {
23 changes: 12 additions & 11 deletions __tests__/buildJsonResults.test.js
Original file line number Diff line number Diff line change
@@ -52,7 +52,8 @@ describe('buildJsonResults', () => {
Object.assign({}, constants.DEFAULT_OPTIONS, {
classNameTemplate: "{filename}"
}));
expect(jsonResults.testsuites[1].testsuite[1].testcase[0]._attr.classname).toBe('foo.test.js');

expect(jsonResults.testsuites[1].testsuite[2].testcase[0]._attr.classname).toBe('foo.test.js');
});

it('should support return the function result when classNameTemplate is a function', () => {
@@ -63,7 +64,7 @@ describe('buildJsonResults', () => {
return 'function called with vars: ' + Object.keys(vars).join(', ');
}
}));
expect(jsonResults.testsuites[1].testsuite[1].testcase[0]._attr.classname)
expect(jsonResults.testsuites[1].testsuite[2].testcase[0]._attr.classname)
.toBe('function called with vars: filepath, filename, classname, title, displayName');
});

@@ -73,7 +74,7 @@ describe('buildJsonResults', () => {
Object.assign({}, constants.DEFAULT_OPTIONS, {
titleTemplate: "{filepath}"
}));
expect(jsonResults.testsuites[1].testsuite[1].testcase[0]._attr.name).toBe('path/to/test/__tests__/foo.test.js');
expect(jsonResults.testsuites[1].testsuite[2].testcase[0]._attr.name).toBe('path/to/test/__tests__/foo.test.js');
});

it('should return the proper filepath when suiteNameTemplate is "{filepath}" and usePathForSuiteName is "false"', () => {
@@ -116,7 +117,7 @@ describe('buildJsonResults', () => {
const noFailingTestsReport = require('../__mocks__/no-failing-tests.json');
const jsonResults = buildJsonResults(noFailingTestsReport, '/',
Object.assign({}, constants.DEFAULT_OPTIONS));
expect(jsonResults.testsuites[1].testsuite[1].testcase[0]._attr.classname).toBe('foo baz should bar');
expect(jsonResults.testsuites[1].testsuite[2].testcase[0]._attr.classname).toBe('foo baz should bar');
});

it('should return the proper classname when ancestorSeparator is customized', () => {
@@ -125,14 +126,14 @@ describe('buildJsonResults', () => {
Object.assign({}, constants.DEFAULT_OPTIONS, {
ancestorSeparator: " › "
}));
expect(jsonResults.testsuites[1].testsuite[1].testcase[0]._attr.classname).toBe('foo › baz should bar');
expect(jsonResults.testsuites[1].testsuite[2].testcase[0]._attr.classname).toBe('foo › baz should bar');
});

it('should parse failure messages for failing tests', () => {
const failingTestsReport = require('../__mocks__/failing-tests.json');
const jsonResults = buildJsonResults(failingTestsReport, '/path/to/test', constants.DEFAULT_OPTIONS);

const failureMsg = jsonResults.testsuites[1].testsuite[1].testcase[1].failure;
const failureMsg = jsonResults.testsuites[1].testsuite[2].testcase[1].failure;

// Make sure no escape codes are there that exist in the mock
expect(failureMsg.includes('\u001b')).toBe(false);
@@ -158,7 +159,7 @@ describe('buildJsonResults', () => {
it('should not return the file name by default', () => {
const noFailingTestsReport = require('../__mocks__/no-failing-tests.json');
const jsonResults = buildJsonResults(noFailingTestsReport, '/', constants.DEFAULT_OPTIONS);
expect(jsonResults.testsuites[1].testsuite[1].testcase[0]._attr.file).toBe(undefined);
expect(jsonResults.testsuites[1].testsuite[2].testcase[0]._attr.file).toBe(undefined);
});

it('should return the file name when addFileAttribute is "true"', () => {
@@ -167,7 +168,7 @@ describe('buildJsonResults', () => {
Object.assign({}, constants.DEFAULT_OPTIONS, {
addFileAttribute: "true"
}));
expect(jsonResults.testsuites[1].testsuite[1].testcase[0]._attr.file).toBe('path/to/test/__tests__/foo.test.js');
expect(jsonResults.testsuites[1].testsuite[2].testcase[0]._attr.file).toBe('path/to/test/__tests__/foo.test.js');
});

it('should show output of console if includeConsoleOutput is true', () => {
@@ -189,7 +190,7 @@ describe('buildJsonResults', () => {

expect(jsonResults.testsuites[1].testsuite[1]['system-out']).not.toBeDefined();
});

it('should show short console output if includeShortConsoleOutput is true', () => {
const reportWithShortConsoleOutput = require('../__mocks__/test-with-console-output.json');
const jsonResults = buildJsonResults(reportWithShortConsoleOutput, '/',
@@ -206,7 +207,7 @@ describe('buildJsonResults', () => {
Object.assign({}, constants.DEFAULT_OPTIONS, {
includeShortConsoleOutput: "false"
}));
expect(jsonResults.testsuites[1].testsuite[1]['system-out']).not.toBeDefined();

expect(jsonResults.testsuites[1].testsuite[2]['system-out']).not.toBeDefined();
});
});
2 changes: 1 addition & 1 deletion __tests__/getOptions.test.js
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ const getOptions = require('../utils/getOptions.js');
jest.mock('fs', () => {
return Object.assign(
{},
require.requireActual('fs'),
jest.requireActual('fs'),
{
existsSync: jest.fn().mockReturnValue(true)
}
4 changes: 2 additions & 2 deletions __tests__/testResultProcessor.test.js
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
jest.mock('mkdirp', () => {
return Object.assign(
{},
require.requireActual('mkdirp'),
jest.requireActual('mkdirp'),
{
sync: jest.fn()
}
@@ -13,7 +13,7 @@ jest.mock('mkdirp', () => {
jest.mock('fs', () => {
return Object.assign(
{},
require.requireActual('fs'),
jest.requireActual('fs'),
{
writeFileSync: jest.fn()
}
4 changes: 3 additions & 1 deletion constants/index.js
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ module.exports = {
JEST_JUNIT_INCLUDE_CONSOLE_OUTPUT: 'includeConsoleOutput',
JEST_JUNIT_INCLUDE_SHORT_CONSOLE_OUTPUT: 'includeShortConsoleOutput',
JEST_USE_PATH_FOR_SUITE_NAME: 'usePathForSuiteName',
JEST_JUNIT_TEST_SUITE_PROPERTIES_JSON_FILE: 'testSuitePropertiesFile'
},
DEFAULT_OPTIONS: {
suiteName: 'jest tests',
@@ -27,7 +28,8 @@ module.exports = {
usePathForSuiteName: 'false',
addFileAttribute: 'false',
includeConsoleOutput: 'false',
includeShortConsoleOutput: 'false'
includeShortConsoleOutput: 'false',
testSuitePropertiesFile: 'junitProperties.js'
},
CLASSNAME_VAR: 'classname',
FILENAME_VAR: 'filename',
3 changes: 2 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -12,5 +12,6 @@ module.exports = {
"<rootDir>/integration-tests/testResultsProcessor/",
"<rootDir>/integration-tests/reporter/"
],
setupFilesAfterEnv: ["<rootDir>/__tests__/lib/setupTests.js"]
setupFilesAfterEnv: ["<rootDir>/__tests__/lib/setupTests.js"],
reporters: ['default', '.']
};
5 changes: 5 additions & 0 deletions junitProperties.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = (suite) => {
return {
'best-tester': 'Jason Palmer'
}
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "jest-junit",
"version": "10.0.0",
"version": "11.0.0",
"description": "A jest reporter that generates junit xml files",
"main": "index.js",
"repository": "https://github.com/jest-community/jest-junit",
"author": "Jason Palmer",
"license": "Apache-2.0",
"engines": {
"node": ">=8.0.0"
"node": ">=10.12.0"
},
"files": [
"index.js",
@@ -21,7 +21,7 @@
},
"dependencies": {
"jest-validate": "^24.9.0",
"mkdirp": "^0.5.1",
"mkdirp": "^1.0.4",
"strip-ansi": "^5.2.0",
"uuid": "^3.3.3",
"xml": "^1.0.1"
32 changes: 30 additions & 2 deletions utils/buildJsonResults.js
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
const stripAnsi = require('strip-ansi');
const constants = require('../constants/index');
const path = require('path');

const fs = require('fs');

// Wrap the varName with template tags
const toTemplateTag = function (varName) {
@@ -35,6 +35,10 @@ const executionTime = function (startTime, endTime) {
}

module.exports = function (report, appDirectory, options) {
// Check if there is a junitProperties.js (or whatever they called it)
const junitSuitePropertiesFilePath = path.join(process.cwd(), options.testSuitePropertiesFile);
let ignoreSuitePropertiesCheck = !fs.existsSync(junitSuitePropertiesFilePath);

// Generate a single XML file for all jest tests
let jsonResults = {
'testsuites': [{
@@ -114,7 +118,7 @@ module.exports = function (report, appDirectory, options) {

testSuite.testsuite.push(testSuiteConsole);
}

// Write short stdout console output if available
if (options.includeShortConsoleOutput === 'true' && suite.console && suite.console.length) {
// Extract and then Stringify the console message value
@@ -129,6 +133,30 @@ module.exports = function (report, appDirectory, options) {
testSuite.testsuite.push(testSuiteConsole);
}

if (!ignoreSuitePropertiesCheck) {
let junitSuiteProperties = require(junitSuitePropertiesFilePath)(suite);

// Add any test suite properties
let testSuitePropertyMain = {
'properties': []
};

Object.keys(junitSuiteProperties).forEach((p) => {
let testSuiteProperty = {
'property': {
_attr: {
name: p,
value: replaceVars(junitSuiteProperties[p], suiteNameVariables)
}
}
};

testSuitePropertyMain.properties.push(testSuiteProperty);
});

testSuite.testsuite.push(testSuitePropertyMain);
}

// Iterate through test cases
suite.testResults.forEach((tc) => {
const classname = tc.ancestorTitles.join(options.ancestorSeparator);
19 changes: 18 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
@@ -2237,6 +2237,11 @@ minimist@^1.1.1, minimist@^1.2.0:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=

minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==

minimist@~0.0.1:
version "0.0.10"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
@@ -2265,13 +2270,25 @@ mixin-deep@^1.2.0:
for-in "^1.0.2"
is-extendable "^1.0.1"

mkdirp@^0.5.0, mkdirp@^0.5.1:
mkdirp@^0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
dependencies:
minimist "0.0.8"

mkdirp@^0.5.1:
version "0.5.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
dependencies:
minimist "^1.2.5"

mkdirp@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==

ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"