Skip to content

Commit

Permalink
Add forceCoverageMatch configuration option (#5081)
Browse files Browse the repository at this point in the history
Add forceCoverageMatch config option to allow collecting coverage even
if the file is ignored. This way you can collect coverage from the
source files with tests or specific files you ignored manually.
  • Loading branch information
efegurkan authored and cpojer committed Dec 18, 2017
1 parent cb98442 commit 9afeb9c
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 1 deletion.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## master

None
* `[jest-config]` Add `forceCoverageMatch` to allow collecting coverage from
ignored files. ([#5081](https://github.com/facebook/jest/pull/5081))

## jest 22.0.0

Expand Down
35 changes: 35 additions & 0 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,41 @@ Jest will fail if:
* The `./src/api/very-important-module.js` file has less than 100% coverage.
* Every remaining file combined has less than 50% coverage (`global`).

### `forceCoverageMatch` [array<string>]

Default: `['']`

Test files are normally ignored from collecting code coverage. With this option,
you can overwrite this behavior and include otherwise ignored files in code coverage.

For example, if you have tests in source files named with `.t.js` extension as
following:

```javascript
// sum.t.js

export function sum(a,b) {
return a + b;
}

if (process.env.NODE_ENV === 'test') {
test('sum', () => {
expect(sum(1, 2)).toBe(3);
});
}
```

You can collect coverage from those files with setting `forceCoverageMatch`.
```json
{
...
"jest": {
"forceCoverageMatch": ["**/*.t.js"]
}
}
```


### `globals` [object]

Default: `{}`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ exports[`--showConfig outputs config info and exits 1`] = `
\\"/node_modules/\\"
],
\\"detectLeaks\\": false,
\\"forceCoverageMatch\\": [],
\\"globals\\": {},
\\"haste\\": {
\\"providesModuleNodeModules\\": []
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default ({
coverageReporters: ['json', 'text', 'lcov', 'clover'],
detectLeaks: false,
expand: false,
forceCoverageMatch: [],
globalSetup: null,
globalTeardown: null,
globals: {},
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ const getConfigs = (
cwd: options.cwd,
detectLeaks: options.detectLeaks,
displayName: options.displayName,
forceCoverageMatch: options.forceCoverageMatch,
globals: options.globals,
haste: options.haste,
moduleDirectories: options.moduleDirectories,
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/normalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ export default function normalize(options: InitialOptions, argv: Argv) {
case 'expand':
case 'globals':
case 'findRelatedTests':
case 'forceCoverageMatch':
case 'forceExit':
case 'listTests':
case 'logHeapUsage':
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/valid_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export default ({
},
displayName: 'project-name',
expand: false,
forceCoverageMatch: ['**/*.t.js'],
forceExit: false,
globalSetup: 'setup.js',
globalTeardown: 'teardown.js',
Expand Down
151 changes: 151 additions & 0 deletions packages/jest-runtime/src/__tests__/should_instrument.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

import shouldInstrument from '../should_instrument';

describe('should_instrument', () => {
const defaultFilename = 'source_file.test.js';
const defaultOptions = {
collectCoverage: true,
};
const defaultConfig = {
rootDir: '/',
};

describe('should return true', () => {
const testShouldInstrument = (
filename = defaultFilename,
options = defaultOptions,
config = defaultConfig,
) => {
const result = shouldInstrument(filename, options, config);
expect(result).toBe(true);
};

it('when testRegex provided and file is not a test file', () => {
testShouldInstrument('source_file.js', defaultOptions, {
testRegex: '.*\\.(test)\\.(js)$',
});
});

it('when testMatch is provided and file is not a test file', () => {
testShouldInstrument('source_file.js', defaultOptions, {
testMatch: ['**/?(*.)(test).js'],
});
});

it('should return true when file is in collectCoverageOnlyFrom when provided', () => {
testShouldInstrument(
'collect/only/from/here.js',

{
collectCoverage: true,
collectCoverageOnlyFrom: {'collect/only/from/here.js': true},
},
defaultConfig,
);
});

it('should return true when filename matches collectCoverageFrom', () => {
testShouldInstrument(
'do/collect/coverage.js',
{
collectCoverage: true,
collectCoverageFrom: ['!**/dont/**/*.js', '**/do/**/*.js'],
},
defaultConfig,
);
});

it('should return true if the file is not in coveragePathIgnorePatterns', () => {
testShouldInstrument('do/collect/coverage.js', defaultOptions, {
coveragePathIgnorePatterns: ['dont'],
rootDir: '/',
});
});

it('should return true if file is a testfile but forceCoverageMatch is set', () => {
testShouldInstrument('do/collect/sum.coverage.test.js', defaultOptions, {
forceCoverageMatch: ['**/*.(coverage).(test).js'],
rootDir: '/',
testRegex: '.*\\.(test)\\.(js)$',
});
});
});

describe('should return false', () => {
const testShouldInstrument = (
filename = defaultFilename,
options = defaultOptions,
config = defaultConfig,
) => {
const result = shouldInstrument(filename, options, config);
expect(result).toBe(false);
};

it('if collectCoverage is falsy', () => {
testShouldInstrument(
'source_file.js',
{
collectCoverage: false,
},
defaultConfig,
);
});

it('when testRegex provided and filename is a test file', () => {
testShouldInstrument(defaultFilename, defaultOptions, {
testRegex: '.*\\.(test)\\.(js)$',
});
});

it('when testMatch is provided and file is a test file', () => {
testShouldInstrument(defaultFilename, defaultOptions, {
testMatch: ['**/?(*.)(test).js'],
});
});

it('when file is not in collectCoverageOnlyFrom when provided', () => {
testShouldInstrument(
'source_file.js',
{
collectCoverage: true,
collectCoverageOnlyFrom: {'collect/only/from/here.js': true},
},
defaultConfig,
);
});

it('when filename does not match collectCoverageFrom', () => {
testShouldInstrument(
'dont/collect/coverage.js',
{
collectCoverage: true,
collectCoverageFrom: ['!**/dont/**/*.js', '**/do/**/*.js'],
},
defaultConfig,
);
});

it('if the file is in coveragePathIgnorePatterns', () => {
testShouldInstrument('dont/collect/coverage.js', defaultOptions, {
coveragePathIgnorePatterns: ['dont'],
rootDir: '/',
});
});

it('if file is in mock patterns', () => {
const filename =
process.platform === 'win32'
? 'dont\\__mocks__\\collect\\coverage.js'
: 'dont/__mocks__/collect/coverage.js';

testShouldInstrument(filename, defaultOptions, defaultConfig);
});
});
});
8 changes: 8 additions & 0 deletions packages/jest-runtime/src/should_instrument.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ export default function shouldInstrument(
return false;
}

if (
config.forceCoverageMatch &&
config.forceCoverageMatch.length &&
micromatch.any(filename, config.forceCoverageMatch)
) {
return true;
}

if (config.testRegex && filename.match(config.testRegex)) {
return false;
}
Expand Down
1 change: 1 addition & 0 deletions test_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const DEFAULT_PROJECT_CONFIG: ProjectConfig = {
cwd: '/test_root_dir/',
detectLeaks: false,
displayName: undefined,
forceCoverageMatch: [],
globals: {},
haste: {
providesModuleNodeModules: [],
Expand Down
3 changes: 3 additions & 0 deletions types/Config.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type DefaultOptions = {|
coveragePathIgnorePatterns: Array<string>,
coverageReporters: Array<string>,
expand: boolean,
forceCoverageMatch: Array<Glob>,
globals: ConfigGlobals,
globalSetup: ?string,
globalTeardown: ?string,
Expand Down Expand Up @@ -86,6 +87,7 @@ export type InitialOptions = {
displayName?: string,
expand?: boolean,
findRelatedTests?: boolean,
forceCoverageMatch?: Array<Glob>,
forceExit?: boolean,
json?: boolean,
globals?: ConfigGlobals,
Expand Down Expand Up @@ -212,6 +214,7 @@ export type ProjectConfig = {|
cwd: Path,
detectLeaks: boolean,
displayName: ?string,
forceCoverageMatch: Array<Glob>,
globals: ConfigGlobals,
haste: HasteConfig,
moduleDirectories: Array<string>,
Expand Down

0 comments on commit 9afeb9c

Please sign in to comment.