Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace <rootDir> prior to path.join() #154

Merged
merged 24 commits into from Oct 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5a96643
Replace <rootDir> prior to path.join().
Dec 10, 2020
79682c6
Bump y18n from 4.0.0 to 4.0.1
dependabot[bot] Mar 31, 2021
12da1a2
Merge pull request #161 from jest-community/dependabot/npm_and_yarn/y…
palmerj3 Mar 31, 2021
3c68d50
Add outputFile config and tests
May 25, 2021
69e802c
Merge pull request #168 from daivinhtran/add-outputfile-config
palmerj3 May 25, 2021
712907b
v12.1.0
palmerj3 May 25, 2021
e02ac65
Merge pull request #169 from palmerj3/bumpVersion
palmerj3 May 25, 2021
c6bc051
fix: Upgrade uuid package
scttcper Jun 9, 2021
181e14e
Merge pull request #171 from scttcper/uuid-upgrade
palmerj3 Jun 9, 2021
ce8dde5
v12.2.0
palmerj3 Jun 9, 2021
6751a86
Merge pull request #172 from palmerj3/v12.2.0
palmerj3 Jun 9, 2021
e189f2d
Fix displayName usage in templates
D4N14L Sep 9, 2021
8e5f72b
Merge pull request #179 from D4N14L/fixDisplayName
palmerj3 Sep 10, 2021
7568d08
v12.3.0
palmerj3 Sep 21, 2021
46ab4a4
Merge pull request #182 from palmerj3/twelveThreeZero
palmerj3 Sep 21, 2021
77e5b64
chore: migrate to GH Actions (#185)
SimenB Sep 29, 2021
475c84f
chore: refresh lockfile (#184)
SimenB Sep 29, 2021
c054549
chore: run tests on Windows (#187)
SimenB Sep 29, 2021
506df22
chore: use Jest 27 (#186)
SimenB Sep 29, 2021
8f43cd0
Fix CG by updating strip-ansi from 5.2.0 to 6.0.1
Sep 30, 2021
2b6c131
Update package.json
SimenB Sep 30, 2021
46bc2c9
Merge pull request #188 from KeYu-dev/fixcg-ansi-regex
palmerj3 Sep 30, 2021
c5ca7c8
Replace <rootDir> prior to path.join().
Dec 10, 2020
1b5af37
Merge branch 'rootDir' of https://github.com/arabull/jest-junit into …
Sep 30, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/nodejs.yml
@@ -0,0 +1,57 @@
name: Unit tests

on:
push:
branches:
- master
- next
pull_request:
branches:
- master
- next

jobs:
test-node:
name: Test on Node.js v${{ matrix.node-version }} and Jest v${{ matrix.jest-version }}
strategy:
fail-fast: false
matrix:
node-version: [10.x, 12.x, 13.x, 14.x, 16.x]
jest-version: [24, 25, 26, 27]
exclude:
# jest@27 doesn't support node@13
- node-version: 13.x
jest-version: 27
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: yarn
- name: install with jest v${{ matrix.jest-version }}
run: |
yarn add --dev jest@${{ matrix.jest-version }} babel-jest@${{ matrix.jest-version }}
yarn
- name: run tests
run: yarn test
test-os:
name: Test on ${{ matrix.os }} using Node.js LTS
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 14.x
cache: yarn
- name: install
run: yarn
- name: run tests
run: yarn test
12 changes: 0 additions & 12 deletions .travis.yml

This file was deleted.

3 changes: 2 additions & 1 deletion README.md
@@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/jest-community/jest-junit.svg?branch=master)](https://travis-ci.org/jest-community/jest-junit)
[![Actions Status](https://github.com/jest-community/jest-junit/actions/workflows/nodejs.yml/badge.svg?branch=master)](https://github.com/jest-community/jest-junit/actions)

# jest-junit
A Jest reporter that creates compatible junit xml files
Expand Down Expand Up @@ -59,6 +59,7 @@ Reporter options should also be strings exception for suiteNameTemplate, classNa
| `JEST_SUITE_NAME` | `suiteName` | `name` attribute of `<testsuites>` | `"jest tests"` | N/A
| `JEST_JUNIT_OUTPUT_DIR` | `outputDirectory` | Directory to save the output. | `process.cwd()` | N/A
| `JEST_JUNIT_OUTPUT_NAME` | `outputName` | File name for the output. | `"junit.xml"` | N/A
| `JEST_JUNIT_OUTPUT_FILE` | `outputFile` | Fullpath for the output. If defined, `outputDirectory` and `outputName` will be overridden | `undefined` | N/A
| `JEST_JUNIT_UNIQUE_OUTPUT_NAME` | `uniqueOutputName` | Create unique file name for the output `junit-${uuid}.xml`, overrides `outputName` | `false` | N/A
| `JEST_JUNIT_SUITE_NAME` | `suiteNameTemplate` | Template string for `name` attribute of the `<testsuite>`. | `"{title}"` | `{title}`, `{filepath}`, `{filename}`, `{displayName}`
| `JEST_JUNIT_CLASSNAME` | `classNameTemplate` | Template string for the `classname` attribute of `<testcase>`. | `"{classname} {title}"` | `{classname}`, `{title}`, `{suitename}`, `{filepath}`, `{filename}`, `{displayName}`
Expand Down
23 changes: 12 additions & 11 deletions __tests__/buildJsonResults.test.js
@@ -1,5 +1,6 @@
'use strict';

const slash = require('slash');
const buildJsonResults = require('../utils/buildJsonResults');
const constants = require('../constants/index');

Expand Down Expand Up @@ -88,7 +89,7 @@ describe('buildJsonResults', () => {
classNameTemplate: "{filepath}"
}));

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

it('should return the proper filename when classNameTemplate is "{filename}"', () => {
Expand Down Expand Up @@ -148,7 +149,7 @@ describe('buildJsonResults', () => {
expect(totals.failures).toEqual(0);

const suiteResult = jsonResults.testsuites[1].testsuite[0]._attr;
expect(suiteResult.name).toEqual('../spec/test.spec.ts')
expect(slash(suiteResult.name)).toEqual('../spec/test.spec.ts')
expect(suiteResult.errors).toEqual(1);
expect(suiteResult.tests).toEqual(0);

Expand All @@ -168,7 +169,7 @@ describe('buildJsonResults', () => {
}));

const errorSuite = jsonResults.testsuites[1].testsuite[2];
expect(errorSuite.testcase[0]._attr.name).toEqual('../spec/test.spec.ts');
expect(slash(errorSuite.testcase[0]._attr.name)).toEqual('../spec/test.spec.ts');
expect(errorSuite.testcase[0]._attr.classname).toEqual('Test suite failed to run');
expect(errorSuite.testcase[1].error).toContain("Cannot find module './mult'");
});
Expand All @@ -182,7 +183,7 @@ describe('buildJsonResults', () => {
}));

const errorSuite = jsonResults.testsuites[1].testsuite[2];
expect(errorSuite.testcase[0]._attr.name).toEqual('../spec/test.spec.ts');
expect(slash(errorSuite.testcase[0]._attr.name)).toEqual('../spec/test.spec.ts');
expect(errorSuite.testcase[0]._attr.classname).toEqual('Test suite failed to run');
expect(errorSuite.testcase[1].error).toContain("Your test suite must contain at least one test");
});
Expand All @@ -206,7 +207,7 @@ describe('buildJsonResults', () => {
Object.assign({}, constants.DEFAULT_OPTIONS, {
titleTemplate: "{filepath}"
}));
expect(jsonResults.testsuites[1].testsuite[2].testcase[0]._attr.name).toBe('path/to/test/__tests__/foo.test.js');
expect(slash(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"', () => {
Expand All @@ -215,7 +216,7 @@ describe('buildJsonResults', () => {
Object.assign({}, constants.DEFAULT_OPTIONS, {
suiteNameTemplate: "{filepath}"
}));
expect(jsonResults.testsuites[1].testsuite[0]._attr.name).toBe('path/to/test/__tests__/foo.test.js');
expect(slash(jsonResults.testsuites[1].testsuite[0]._attr.name)).toBe('path/to/test/__tests__/foo.test.js');
});

it('should return the proper name from ancestorTitles when suiteNameTemplate is set to "{title}" and usePathForSuiteName is "true"', () => {
Expand All @@ -224,7 +225,7 @@ describe('buildJsonResults', () => {
Object.assign({}, constants.DEFAULT_OPTIONS, {
usePathForSuiteName: "true"
}));
expect(jsonResults.testsuites[1].testsuite[0]._attr.name).toBe('path/to/test/__tests__/foo.test.js');
expect(slash(jsonResults.testsuites[1].testsuite[0]._attr.name)).toBe('path/to/test/__tests__/foo.test.js');
});

it('should return the proper name from testFilePath when usePathForSuiteName is "true"; no appDirectory set', () => {
Expand All @@ -233,7 +234,7 @@ describe('buildJsonResults', () => {
Object.assign({}, constants.DEFAULT_OPTIONS, {
usePathForSuiteName: "true"
}));
expect(jsonResults.testsuites[1].testsuite[0]._attr.name).toBe('path/to/test/__tests__/foo.test.js');
expect(slash(jsonResults.testsuites[1].testsuite[0]._attr.name)).toBe('path/to/test/__tests__/foo.test.js');
});

it('should return the proper name from testFilePath when usePathForSuiteName is "true"; with appDirectory set', () => {
Expand All @@ -242,7 +243,7 @@ describe('buildJsonResults', () => {
Object.assign({}, constants.DEFAULT_OPTIONS, {
usePathForSuiteName: "true"
}));
expect(jsonResults.testsuites[1].testsuite[0]._attr.name).toBe('__tests__/foo.test.js');
expect(slash(jsonResults.testsuites[1].testsuite[0]._attr.name)).toBe('__tests__/foo.test.js');
});

it('should return the proper classname when ancestorSeparator is default', () => {
Expand Down Expand Up @@ -277,7 +278,7 @@ describe('buildJsonResults', () => {

// Mock Date.now() to return a fixed later value
const startDate = new Date(multiProjectNoFailingTestsReport.startTime);
spyOn(Date, 'now').and.returnValue(startDate.getTime() + 1234);
jest.spyOn(Date, 'now').mockImplementation(() => startDate.getTime() + 1234);

jsonResults = buildJsonResults(multiProjectNoFailingTestsReport, '/',
Object.assign({}, constants.DEFAULT_OPTIONS, {
Expand Down Expand Up @@ -305,7 +306,7 @@ describe('buildJsonResults', () => {
Object.assign({}, constants.DEFAULT_OPTIONS, {
addFileAttribute: "true"
}));
expect(jsonResults.testsuites[1].testsuite[2].testcase[0]._attr.file).toBe('path/to/test/__tests__/foo.test.js');
expect(slash(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', () => {
Expand Down
28 changes: 28 additions & 0 deletions __tests__/testResultProcessor.test.js
Expand Up @@ -60,4 +60,32 @@ describe('jest-junit', () => {
const xmlDoc = libxmljs.parseXml(fs.writeFileSync.mock.calls[0][1]);
expect(xmlDoc).toBeTruthy();
});


it('should generate xml at the output filepath defined by JEST_JUNIT_OUTPUT_FILE', () => {
process.env.JEST_JUNIT_OUTPUT_FILE = 'path_to_output/output_name.xml'
const noFailingTestsReport = require('../__mocks__/no-failing-tests.json');
testResultProcessor(noFailingTestsReport);

// Ensure fs.writeFileSync is called
expect(fs.writeFileSync).toHaveBeenCalledTimes(1);

// Ensure file would have been generated
expect(fs.writeFileSync).toHaveBeenLastCalledWith(
expect.stringMatching(/path_to_output\S+\output_name.xml/), expect.any(String)
);
});

it('should generate xml at the output filepath defined by outputFile config', () => {
const noFailingTestsReport = require('../__mocks__/no-failing-tests.json');
testResultProcessor(noFailingTestsReport, {outputFile: 'path_to_output/output_name.xml' });

// Ensure fs.writeFileSync is called
expect(fs.writeFileSync).toHaveBeenCalledTimes(1);

// Ensure file would have been generated
expect(fs.writeFileSync).toHaveBeenLastCalledWith(
expect.stringMatching(/path_to_output\S+\output_name.xml/), expect.any(String)
);
});
});
1 change: 1 addition & 0 deletions constants/index.js
Expand Up @@ -5,6 +5,7 @@ module.exports = {
JEST_SUITE_NAME: 'suiteName',
JEST_JUNIT_OUTPUT_DIR: 'outputDirectory',
JEST_JUNIT_OUTPUT_NAME: 'outputName',
JEST_JUNIT_OUTPUT_FILE: 'outputFile',
JEST_JUNIT_UNIQUE_OUTPUT_NAME: 'uniqueOutputName',
JEST_JUNIT_CLASSNAME: 'classNameTemplate',
JEST_JUNIT_SUITE_NAME: 'suiteNameTemplate',
Expand Down
11 changes: 4 additions & 7 deletions index.js
Expand Up @@ -7,6 +7,7 @@ const path = require('path');

const buildJsonResults = require('./utils/buildJsonResults');
const getOptions = require('./utils/getOptions');
const getOutputPath = require('./utils/getOutputPath');

// Store console results from onTestResult to later
// append to result
Expand All @@ -23,17 +24,13 @@ const processor = (report, reporterOptions = {}, jestRootDir = null) => {

const jsonResults = buildJsonResults(report, fs.realpathSync(process.cwd()), options);

// Set output to use new outputDirectory and fallback on original output
const outputName = (options.uniqueOutputName === 'true') ? getOptions.getUniqueOutputName() : options.outputName
const output = path.join(options.outputDirectory, outputName);

const finalOutput = getOptions.replaceRootDirInOutput(jestRootDir, output);
let outputPath = getOutputPath(options, jestRootDir);

// Ensure output path exists
mkdirp.sync(path.dirname(finalOutput));
mkdirp.sync(path.dirname(outputPath));

// Write data to file
fs.writeFileSync(finalOutput, xml(jsonResults, { indent: ' ', declaration: true }));
fs.writeFileSync(outputPath, xml(jsonResults, { indent: ' ', declaration: true }));

// Jest 18 compatibility
return report;
Expand Down
15 changes: 7 additions & 8 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "jest-junit",
"version": "12.0.0",
"version": "12.3.0",
"description": "A jest reporter that generates junit xml files",
"main": "index.js",
"repository": "https://github.com/jest-community/jest-junit",
Expand All @@ -15,18 +15,17 @@
"constants"
],
"scripts": {
"test": "jest",
"pretest:ci": "npm uninstall jest babel-jest && npm install jest@$JEST_VERSION babel-jest@$JEST_VERSION --no-save",
"test:ci": "jest --ci"
"test": "jest"
},
"dependencies": {
"mkdirp": "^1.0.4",
"strip-ansi": "^5.2.0",
"uuid": "^3.3.3",
"strip-ansi": "^6.0.1",
"uuid": "^8.3.2",
"xml": "^1.0.1"
},
"devDependencies": {
"jest": "26.0.1",
"libxmljs": "^0.19.7"
"jest": "^27.2.3",
"libxmljs": "^0.19.7",
"slash": "^3.0.0"
}
}
4 changes: 3 additions & 1 deletion utils/buildJsonResults.js
Expand Up @@ -98,7 +98,9 @@ module.exports = function (report, appDirectory, options) {
const filepath = path.relative(appDirectory, suite.testFilePath);
const filename = path.basename(filepath);
const suiteTitle = suite.testResults[0].ancestorTitles[0];
const displayName = suite.displayName;
const displayName = typeof suite.displayName === 'object'
? suite.displayName.name
: suite.displayName;

// Build replacement map
let suiteNameVariables = {};
Expand Down
2 changes: 1 addition & 1 deletion utils/getOptions.js
Expand Up @@ -2,7 +2,7 @@

const path = require('path');
const fs = require('fs');
const uuid = require('uuid/v1');
const { v1: uuid } = require('uuid');

const constants = require('../constants/index');

Expand Down
17 changes: 17 additions & 0 deletions utils/getOutputPath.js
@@ -0,0 +1,17 @@
const path = require('path');
const getOptions = require('./getOptions');

module.exports = (options, jestRootDir) => {
// Override outputName and outputDirectory with outputFile if outputFile is defined
let output = options.outputFile;
if (!output) {
// Set output to use new outputDirectory and fallback on original output
const outputName = (options.uniqueOutputName === 'true') ? getOptions.getUniqueOutputName() : options.outputName
output = getOptions.replaceRootDirInOutput(jestRootDir, options.outputDirectory);
const finalOutput = path.join(output, outputName);
return finalOutput;
}

const finalOutput = getOptions.replaceRootDirInOutput(jestRootDir, output);
return finalOutput;
};