Skip to content

Commit

Permalink
Implement testGlob option
Browse files Browse the repository at this point in the history
  • Loading branch information
pugnascotia committed Jan 16, 2017
1 parent e5d5a55 commit f02cc5b
Show file tree
Hide file tree
Showing 20 changed files with 246 additions and 35 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ lerna-debug.log
npm-debug.log*
coverage
.eslintcache

.idea
*.iml
21 changes: 12 additions & 9 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ These options let you control Jest's behavior in your `package.json` file. The J
- [`setupTestFrameworkScriptFile` [string]](#setuptestframeworkscriptfile-string)
- [`snapshotSerializers` [array<string>]](#snapshotserializers-array-string)
- [`testEnvironment` [string]](#testenvironment-string)
- [`testGlob` [string]](#testglob-string-or-array)
- [`testPathDirs` [array<string>]](#testpathdirs-array-string)
- [`testPathIgnorePatterns` [array<string>]](#testpathignorepatterns-array-string)
- [`testRegex` [string]](#testregex-string)
- [`testResultsProcessor` [string]](#testresultsprocessor-string)
- [`testRunner` [string]](#testrunner-string)
- [`testURL` [string]](#testurl-string)
Expand Down Expand Up @@ -347,6 +347,17 @@ Pretty foo: Object {

The test environment that will be used for testing. The default environment in Jest is a browser-like environment through [jsdom](https://github.com/tmpvar/jsdom). If you are building a node service, you can use the `node` option to use a node-like environment instead.

### `testGlob` [array<string>]
(default: `[ '**/__tests__/**/*.js?(x)', '**/?(*.)(spec|test).js?(x)' ]`)

The glob patterns Jest uses to detect test files. By default it looks for `.js` and `.jsx` files
inside of `__tests__` folders, as well as any files with a suffix of `.test` or `.spec`
(e.g. `Component.test.js` or `Component.spec.js`). It will also find files called `test.js`
or `spec.js`.

See the [micromatch](https://github.com/jonschlinkert/micromatch) package
for details of the patterns you can specify.

### `testPathDirs` [array<string>]
(default: `["<rootDir>"]`)

Expand All @@ -361,14 +372,6 @@ An array of regexp pattern strings that are matched against all test paths befor

These pattern strings match against the full path. Use the `<rootDir>` string token to include the path to your project's root directory to prevent it from accidentally ignoring all of your files in different environments that may have different root directories. Example: `["<rootDir>/build/", "<rootDir>/node_modules/"]`.

### `testRegex` [string]
(default: `(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$`)

The pattern Jest uses to detect test files. By default it looks for `.js` and `.jsx` files
inside of `__tests__` folders, as well as any files with a suffix of `.test` or `.spec`
(e.g. `Component.test.js` or `Component.spec.js`). It will also find files called `test.js`
or `spec.js`.

### `testResultsProcessor` [string]
(default: `undefined`)

Expand Down
2 changes: 1 addition & 1 deletion examples/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
"transform": {
"^.+\\.(ts|tsx)$": "<rootDir>/preprocessor.js"
},
"testRegex": "/__tests__/.*\\.(ts|tsx|js)$"
"testGlob": ["**/__tests__/*.(ts|tsx|js)"]
}
}
2 changes: 1 addition & 1 deletion integration_tests/typescript-coverage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"transform": {
"^.+\\.(ts|js)$": "<rootDir>/typescript-preprocessor.js"
},
"testRegex": "/__tests__/.*\\.(ts|tsx|js)$",
"testGlob": ["**/__tests__/*.(ts|tsx|js)"],
"testEnvironment": "node",
"moduleFileExtensions": [
"ts",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,6 @@
"\\.snap$",
"/packages/.*/build"
],
"testRegex": ".*-test\\.js"
"testGlob": ["**/*-test.js"]
}
}
1 change: 1 addition & 0 deletions packages/jest-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"jest-snapshot": "^18.1.0",
"jest-util": "^18.1.0",
"json-stable-stringify": "^1.0.0",
"micromatch": "^2.3.11",
"node-notifier": "^4.6.1",
"sane": "~1.4.1",
"strip-ansi": "^3.0.1",
Expand Down
30 changes: 26 additions & 4 deletions packages/jest-cli/src/SearchSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
'use strict';

import type {HasteContext} from 'types/HasteMap';
import type {Path} from 'types/Config';
import type {Glob, Path} from 'types/Config';
import type {ResolveModuleConfig} from 'jest-resolve';

const mm = require('micromatch');

const DependencyResolver = require('jest-resolve-dependencies');

const chalk = require('chalk');
Expand All @@ -26,6 +28,7 @@ const {
} = require('jest-util');

type SearchSourceConfig = {|
testGlob: Array<Glob>,
testPathDirs: Array<Path>,
testRegex: string,
testPathIgnorePatterns: Array<RegExp>,
Expand Down Expand Up @@ -69,14 +72,33 @@ const pluralize = (
ending: string,
) => `${count} ${word}${count === 1 ? '' : ending}`;

const globsToMatcher = (globs: ?Array<Glob>) => {
if (globs == null || globs.length === 0) {
return () => true;
}

const matchers = globs.map(each => mm.matcher(each));

return (path: Path) => matchers.some(each => each(path));
};

const regexToMatcher = (testRegex: string) => {
if (!testRegex.length) {
return () => true;
}

const regex = new RegExp(pathToRegex(testRegex));
return (path: Path) => regex.test(path);
};

class SearchSource {
_hasteContext: HasteContext;
_config: SearchSourceConfig;
_options: ResolveModuleConfig;
_testPathDirPattern: RegExp;
_testRegex: RegExp;
_testIgnorePattern: ?RegExp;
_testPathCases: {
testGlob: (path: Path) => boolean,
testPathDirs: (path: Path) => boolean,
testRegex: (path: Path) => boolean,
testPathIgnorePatterns: (path: Path) => boolean,
Expand All @@ -98,18 +120,18 @@ class SearchSource {
dir => escapePathForRegex(dir),
).join('|'));

this._testRegex = new RegExp(pathToRegex(config.testRegex));
const ignorePattern = config.testPathIgnorePatterns;
this._testIgnorePattern =
ignorePattern.length ? new RegExp(ignorePattern.join('|')) : null;

this._testPathCases = {
testGlob: globsToMatcher(config.testGlob),
testPathDirs: path => this._testPathDirPattern.test(path),
testPathIgnorePatterns: path => (
!this._testIgnorePattern ||
!this._testIgnorePattern.test(path)
),
testRegex: path => this._testRegex.test(path),
testRegex: regexToMatcher(config.testRegex),
};
}

Expand Down
128 changes: 119 additions & 9 deletions packages/jest-cli/src/__tests__/SearchSource-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const skipOnWindows = require('skipOnWindows');

const rootDir = path.resolve(__dirname, 'test_root');
const testRegex = path.sep + '__testtests__' + path.sep;
const testGlob = ['**/__testtests__/**/*'];
const maxWorkers = 1;

let findMatchingTests;
Expand Down Expand Up @@ -50,10 +51,24 @@ describe('SearchSource', () => {
});
});

it('supports ../ paths and unix separators', () => {
// micromatch doesn't support '..' through the globstar ('**') to avoid
// infinite recursion.

it('supports ../ paths and unix separators via textRegex', () => {
if (process.platform !== 'win32') {
const path = '/path/to/__tests__/foo/bar/baz/../../../test.js';
expect(searchSource.isTestFilePath(path)).toEqual(true);
config = normalizeConfig({
name,
rootDir: '.',
testGlob: '',
testPathDirs: [],
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.jsx?$',
});
Runtime.createHasteContext(config, {maxWorkers}).then(hasteMap => {
searchSource = new SearchSource(hasteMap, config);

const path = '/path/to/__tests__/foo/bar/baz/../../../test.js';
expect(searchSource.isTestFilePath(path)).toEqual(true);
});
}
});

Expand All @@ -80,11 +95,12 @@ describe('SearchSource', () => {
);
});

it('finds tests matching a pattern', () => {
it('finds tests matching a pattern via testRegex', () => {
const config = normalizeConfig({
moduleFileExtensions: ['js', 'jsx', 'txt'],
name,
rootDir,
testGlob: [],
testRegex: 'not-really-a-test',
});
return findMatchingTests(config).then(data => {
Expand All @@ -97,11 +113,30 @@ describe('SearchSource', () => {
});
});

it('finds tests matching a JS pattern', () => {
it('finds tests matching a pattern via testGlob', () => {
const config = normalizeConfig({
moduleFileExtensions: ['js', 'jsx', 'txt'],
name,
rootDir,
testGlob: ['**/not-really-a-test.txt'],
testRegex: '',
});
return findMatchingTests(config).then(data => {
const relPaths = data.paths.map(absPath => (
path.relative(rootDir, absPath)
));
expect(relPaths).toEqual([
path.normalize('__testtests__/not-really-a-test.txt'),
]);
});
});

it('finds tests matching a JS regex pattern', () => {
const config = normalizeConfig({
moduleFileExtensions: ['js', 'jsx'],
name,
rootDir,
testGlob: [],
testRegex: 'test\.jsx?',
});
return findMatchingTests(config).then(data => {
Expand All @@ -115,10 +150,30 @@ describe('SearchSource', () => {
});
});

it('finds tests with default file extensions', () => {
it('finds tests matching a JS glob pattern', () => {
const config = normalizeConfig({
moduleFileExtensions: ['js', 'jsx'],
name,
rootDir,
testGlob: ['**/test.js?(x)'],
testRegex: '',
});
return findMatchingTests(config).then(data => {
const relPaths = data.paths.map(absPath => (
path.relative(rootDir, absPath)
));
expect(relPaths.sort()).toEqual([
path.normalize('__testtests__/test.js'),
path.normalize('__testtests__/test.jsx'),
]);
});
});

it('finds tests with default file extensions using testRegex', () => {
const config = normalizeConfig({
name,
rootDir,
testGlob: '',
testRegex,
});
return findMatchingTests(config).then(data => {
Expand All @@ -132,12 +187,30 @@ describe('SearchSource', () => {
});
});

it('finds tests with default file extensions using testGlob', () => {
const config = normalizeConfig({
name,
rootDir,
testGlob,
testRegex: '',
});
return findMatchingTests(config).then(data => {
const relPaths = data.paths.map(absPath => (
path.relative(rootDir, absPath)
));
expect(relPaths.sort()).toEqual([
path.normalize('__testtests__/test.js'),
path.normalize('__testtests__/test.jsx'),
]);
});
});

it('finds tests with similar but custom file extensions', () => {
const config = normalizeConfig({
moduleFileExtensions: ['jsx'],
name,
rootDir,
testRegex,
testGlob,
});
return findMatchingTests(config).then(data => {
const relPaths = data.paths.map(absPath => (
Expand All @@ -154,7 +227,7 @@ describe('SearchSource', () => {
moduleFileExtensions: ['foobar'],
name,
rootDir,
testRegex,
testGlob,
});
return findMatchingTests(config).then(data => {
const relPaths = data.paths.map(absPath => (
Expand All @@ -165,11 +238,30 @@ describe('SearchSource', () => {
]);
});
});

it('finds tests with many kinds of file extensions', () => {
const config = normalizeConfig({
moduleFileExtensions: ['js', 'jsx'],
name,
rootDir,
testGlob,
});
return findMatchingTests(config).then(data => {
const relPaths = data.paths.map(absPath => (
path.relative(rootDir, absPath)
));
expect(relPaths.sort()).toEqual([
path.normalize('__testtests__/test.js'),
path.normalize('__testtests__/test.jsx'),
]);
});
});

it('finds tests using a regex only', () => {
const config = normalizeConfig({
name,
rootDir,
testGlob: [],
testRegex,
});
return findMatchingTests(config).then(data => {
Expand All @@ -182,6 +274,24 @@ describe('SearchSource', () => {
]);
});
});

it('finds tests using a glob only', () => {
const config = normalizeConfig({
name,
rootDir,
testGlob,
testRegex: '',
});
return findMatchingTests(config).then(data => {
const relPaths = data.paths.map(absPath => (
path.relative(rootDir, absPath)
));
expect(relPaths.sort()).toEqual([
path.normalize('__testtests__/test.js'),
path.normalize('__testtests__/test.jsx'),
]);
});
});
});

describe('findRelatedTests', () => {
Expand Down Expand Up @@ -233,7 +343,7 @@ describe('SearchSource', () => {
moduleFileExtensions: ['js', 'jsx', 'foobar'],
name,
rootDir,
testRegex,
testGlob,
});
Runtime.createHasteContext(config, {maxWorkers}).then(hasteMap => {
searchSource = new SearchSource(hasteMap, config);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,13 @@ exports[`transform throws for invalid value 2`] = `
Jest Issue Tracker: https://github.com/facebook/jest/issues
"
`;
exports[`Upgrade help logs a warning when \`testRegex\` is used 1`] = `
"● testRegex is deprecated: use testGlob instead
Jest changed the default configuration for tests.
Configuration Documentation: https://facebook.github.io/jest/docs/configuration.html
Jest Issue Tracker: https://github.com/facebook/jest/issues
"
`;
Loading

0 comments on commit f02cc5b

Please sign in to comment.