Skip to content

Commit c8033a0

Browse files
mjesuntabrindle
authored andcommitted
Add extra parameter: runTestsByPath. Fixes jestjs#4396 (jestjs#4411)
1 parent 953dd8e commit c8033a0

14 files changed

Lines changed: 133 additions & 21 deletions

File tree

ā€Žintegration_tests/__tests__/__snapshots__/show_config.test.js.snapā€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ exports[`--showConfig outputs config info and exits 1`] = `
7373
\\"nonFlagArgs\\": [],
7474
\\"notify\\": false,
7575
\\"rootDir\\": \\"<<REPLACED_ROOT_DIR>>\\",
76+
\\"runTestsByPath\\": false,
7677
\\"testFailureExitCode\\": 1,
7778
\\"testPathPattern\\": \\"\\",
7879
\\"testResultsProcessor\\": null,
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
3+
*
4+
* This source code is licensed under the BSD-style license found in the
5+
* LICENSE file in the root directory of this source tree. An additional grant
6+
* of patent rights can be found in the PATENTS file in the same directory.
7+
*
8+
* @flow
9+
*/
10+
11+
'use strict';
12+
13+
import runJest from '../runJest';
14+
import {cleanup, writeFiles} from '../utils';
15+
import os from 'os';
16+
import path from 'path';
17+
18+
const skipOnWindows = require('../../scripts/skip_on_windows');
19+
const DIR = path.resolve(os.tmpdir(), 'run_tests_by_path_test');
20+
21+
skipOnWindows.suite();
22+
23+
beforeEach(() => cleanup(DIR));
24+
afterEach(() => cleanup(DIR));
25+
26+
test('runs tests by exact path', () => {
27+
writeFiles(DIR, {
28+
'.watchmanconfig': '',
29+
'__tests__/t1.test.js': 'it("foo", () => {})',
30+
'__tests__/t2.test.js': 'it("bar", () => {})',
31+
'package.json': JSON.stringify({jest: {testEnvironment: 'node'}}),
32+
});
33+
34+
// Passing an exact path executes only the given test.
35+
const run1 = runJest(DIR, ['--runTestsByPath', '__tests__/t1.test.js']);
36+
expect(run1.stderr).toMatch('PASS __tests__/t1.test.js');
37+
expect(run1.stderr).not.toMatch('PASS __tests__/t2.test.js');
38+
39+
// When running with thte flag and a pattern, no test is found.
40+
const run2 = runJest(DIR, ['--runTestsByPath', '__tests__/t']);
41+
expect(run2.stdout).toMatch(/no tests found/i);
42+
43+
// When ran without the flag and a pattern, both tests are found.
44+
const run3 = runJest(DIR, ['__tests__/t']);
45+
expect(run3.stderr).toMatch('PASS __tests__/t1.test.js');
46+
expect(run3.stderr).toMatch('PASS __tests__/t2.test.js');
47+
});

ā€Žpackages/jest-cli/src/cli/args.jsā€Ž

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,14 @@ const options = {
393393
'rare.',
394394
type: 'boolean',
395395
},
396+
runTestsByPath: {
397+
default: false,
398+
description:
399+
'Used when provided patterns are exact file paths. This avoids ' +
400+
'converting them into a regular expression and matching it against ' +
401+
'every single file.',
402+
type: 'boolean',
403+
},
396404
setupFiles: {
397405
description:
398406
'The paths to modules that run some code to configure or ' +

ā€Žpackages/jest-cli/src/get_no_test_found.jsā€Ž

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ const getNoTestFound = (testRunData, globalConfig): string => {
66
(current, testRun) => (current += testRun.matches.total),
77
0,
88
);
9+
let dataMessage;
10+
11+
if (globalConfig.runTestsByPath) {
12+
dataMessage = `Files: ${globalConfig.nonFlagArgs
13+
.map(p => `"${p}"`)
14+
.join(', ')}`;
15+
} else {
16+
dataMessage = `Pattern: ${chalk.yellow(
17+
globalConfig.testPathPattern,
18+
)} - 0 matches`;
19+
}
20+
921
return (
1022
chalk.bold('No tests found') +
1123
'\n' +
@@ -17,7 +29,7 @@ const getNoTestFound = (testRunData, globalConfig): string => {
1729
's',
1830
)}. for more details run with \`--verbose\`` +
1931
'\n' +
20-
`Pattern: ${chalk.yellow(globalConfig.testPathPattern)} - 0 matches`
32+
dataMessage
2133
);
2234
};
2335

ā€Žpackages/jest-cli/src/get_no_test_found_verbose.jsā€Ž

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,24 @@ const getNoTestFoundVerbose = (testRunData, globalConfig): string => {
3030
`Jest Documentation: ` +
3131
`facebook.github.io/jest/docs/configuration.html`;
3232
});
33+
let dataMessage;
34+
35+
if (globalConfig.runTestsByPath) {
36+
dataMessage = `Files: ${globalConfig.nonFlagArgs
37+
.map(p => `"${p}"`)
38+
.join(', ')}`;
39+
} else {
40+
dataMessage = `Pattern: ${chalk.yellow(
41+
globalConfig.testPathPattern,
42+
)} - 0 matches`;
43+
}
44+
3345
return (
3446
chalk.bold('No tests found') +
3547
'\n' +
3648
individualResults.join('\n') +
3749
'\n' +
38-
`Pattern: ${chalk.yellow(globalConfig.testPathPattern)} - 0 matches`
50+
dataMessage
3951
);
4052
};
4153

ā€Žpackages/jest-cli/src/reporters/summary_reporter.jsā€Ž

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,25 @@ class SummaryReporter extends BaseReporter {
190190
);
191191
};
192192

193-
const testInfo = globalConfig.onlyChanged
194-
? chalk.dim(' related to changed files')
195-
: globalConfig.testPathPattern ? getMatchingTestsInfo() : '';
193+
let testInfo = '';
194+
195+
if (globalConfig.runTestsByPath) {
196+
testInfo = chalk.dim(' within paths');
197+
} else if (globalConfig.onlyChanged) {
198+
testInfo = chalk.dim(' related to changed files');
199+
} else if (globalConfig.testPathPattern) {
200+
testInfo = getMatchingTestsInfo();
201+
}
202+
203+
let nameInfo = '';
196204

197-
const nameInfo = globalConfig.testNamePattern
198-
? chalk.dim(' with tests matching ') + `"${globalConfig.testNamePattern}"`
199-
: '';
205+
if (globalConfig.runTestsByPath) {
206+
nameInfo = ' ' + globalConfig.nonFlagArgs.map(p => `"${p}"`).join(', ');
207+
} else if (globalConfig.testNamePattern) {
208+
nameInfo =
209+
chalk.dim(' with tests matching ') +
210+
`"${globalConfig.testNamePattern}"`;
211+
}
200212

201213
const contextInfo =
202214
contexts.size > 1

ā€Žpackages/jest-cli/src/run_jest.jsā€Ž

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,18 @@ const getTestPaths = async (
3939
) => {
4040
const source = new SearchSource(context);
4141
let data = await source.getTestPaths(globalConfig, changedFilesPromise);
42-
if (!data.tests.length) {
43-
if (globalConfig.onlyChanged && data.noSCM) {
44-
if (globalConfig.watch) {
45-
data = await source.getTestPaths(globalConfig);
46-
} else {
47-
new Console(outputStream, outputStream).log(
48-
'Jest can only find uncommitted changed files in a git or hg ' +
49-
'repository. If you make your project a git or hg ' +
50-
'repository (`git init` or `hg init`), Jest will be able ' +
51-
'to only run tests related to files changed since the last ' +
52-
'commit.',
53-
);
54-
}
42+
43+
if (!data.tests.length && globalConfig.onlyChanged && data.noSCM) {
44+
if (globalConfig.watch) {
45+
data = await source.getTestPaths(globalConfig);
46+
} else {
47+
new Console(outputStream, outputStream).log(
48+
'Jest can only find uncommitted changed files in a git or hg ' +
49+
'repository. If you make your project a git or hg ' +
50+
'repository (`git init` or `hg init`), Jest will be able ' +
51+
'to only run tests related to files changed since the last ' +
52+
'commit.',
53+
);
5554
}
5655
}
5756
return data;

ā€Žpackages/jest-cli/src/search_source.jsā€Ž

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,17 @@ class SearchSource {
162162
};
163163
}
164164

165+
findTestsByPaths(paths: Array<Path>): SearchResult {
166+
return {
167+
tests: toTests(
168+
this._context,
169+
paths
170+
.map(p => path.resolve(process.cwd(), p))
171+
.filter(this.isTestFilePath.bind(this)),
172+
),
173+
};
174+
}
175+
165176
findRelatedTestsFromPattern(paths: Array<Path>): SearchResult {
166177
if (Array.isArray(paths) && paths.length) {
167178
const resolvedPaths = paths.map(p => path.resolve(process.cwd(), p));
@@ -193,6 +204,8 @@ class SearchSource {
193204
}
194205

195206
return this.findTestRelatedToChangedFiles(changedFilesPromise);
207+
} else if (globalConfig.runTestsByPath && paths && paths.length) {
208+
return Promise.resolve(this.findTestsByPaths(paths));
196209
} else if (globalConfig.findRelatedTests && paths && paths.length) {
197210
return Promise.resolve(this.findRelatedTestsFromPattern(paths));
198211
} else if (globalConfig.testPathPattern != null) {

ā€Žpackages/jest-config/src/defaults.jsā€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ module.exports = ({
5252
preset: null,
5353
resetMocks: false,
5454
resetModules: false,
55+
runTestsByPath: false,
5556
runner: 'jest-runner',
5657
snapshotSerializers: [],
5758
testEnvironment: 'jest-environment-jsdom',

ā€Žpackages/jest-config/src/index.jsā€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ const getConfigs = (
101101
replname: options.replname,
102102
reporters: options.reporters,
103103
rootDir: options.rootDir,
104+
runTestsByPath: options.runTestsByPath,
104105
silent: options.silent,
105106
testFailureExitCode: options.testFailureExitCode,
106107
testNamePattern: options.testNamePattern,

0 commit comments

Comments
Ā (0)
⚔