Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80606 views
1
/**
2
* Copyright (c) 2014, 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
'use strict';
9
10
var childProcess = require('child_process');
11
var fs = require('fs');
12
var path = require('path');
13
var q = require('q');
14
var TestRunner = require('./TestRunner');
15
var utils = require('./lib/utils');
16
17
var _jestVersion = null;
18
function getVersion() {
19
if (_jestVersion === null) {
20
var pkgJsonPath = path.resolve(__dirname, '..', 'package.json');
21
_jestVersion = require(pkgJsonPath).version;
22
}
23
return _jestVersion;
24
}
25
26
function _findChangedFiles(dirPath) {
27
var deferred = q.defer();
28
29
var args =
30
['diff', '--name-only', '--diff-filter=ACMR'];
31
var child = childProcess.spawn('git', args, {cwd: dirPath});
32
33
var stdout = '';
34
child.stdout.on('data', function(data) {
35
stdout += data;
36
});
37
38
var stderr = '';
39
child.stderr.on('data', function(data) {
40
stderr += data;
41
});
42
43
child.on('close', function(code) {
44
if (code === 0) {
45
stdout = stdout.trim();
46
if (stdout === '') {
47
deferred.resolve([]);
48
} else {
49
deferred.resolve(stdout.split('\n').map(function(changedPath) {
50
return path.resolve(dirPath, changedPath);
51
}));
52
}
53
} else {
54
deferred.reject(code + ': ' + stderr);
55
}
56
});
57
58
return deferred.promise;
59
}
60
61
function _verifyIsGitRepository(dirPath) {
62
var deferred = q.defer();
63
64
childProcess.spawn('git', ['rev-parse', '--git-dir'], {cwd: dirPath})
65
.on('close', function(code) {
66
var isGitRepo = code === 0;
67
deferred.resolve(isGitRepo);
68
});
69
70
return deferred.promise;
71
}
72
73
function _testRunnerOptions(argv) {
74
var options = {};
75
if (argv.runInBand) {
76
options.runInBand = argv.runInBand;
77
}
78
if (argv.maxWorkers) {
79
options.maxWorkers = argv.maxWorkers;
80
}
81
return options;
82
}
83
84
function _promiseConfig(argv, packageRoot) {
85
return _promiseRawConfig(argv, packageRoot).then(function (config) {
86
if (argv.coverage) {
87
config.collectCoverage = true;
88
}
89
90
if (argv.testEnvData) {
91
config.testEnvData = argv.testEnvData;
92
}
93
94
config.noHighlight = argv.noHighlight || !process.stdout.isTTY;
95
96
return config;
97
});
98
}
99
100
function _promiseRawConfig(argv, packageRoot) {
101
if (typeof argv.config === 'string') {
102
return utils.loadConfigFromFile(argv.config);
103
}
104
105
if (typeof argv.config === 'object') {
106
return q(utils.normalizeConfig(argv.config));
107
}
108
109
var pkgJsonPath = path.join(packageRoot, 'package.json');
110
var pkgJson = fs.existsSync(pkgJsonPath) ? require(pkgJsonPath) : {};
111
112
// Look to see if there is a package.json file with a jest config in it
113
if (pkgJson.jest) {
114
if (!pkgJson.jest.hasOwnProperty('rootDir')) {
115
pkgJson.jest.rootDir = packageRoot;
116
} else {
117
pkgJson.jest.rootDir = path.resolve(packageRoot, pkgJson.jest.rootDir);
118
}
119
var config = utils.normalizeConfig(pkgJson.jest);
120
config.name = pkgJson.name;
121
return q(config);
122
}
123
124
// Sane default config
125
return q(utils.normalizeConfig({
126
name: packageRoot.replace(/[/\\]/g, '_'),
127
rootDir: packageRoot,
128
testPathDirs: [packageRoot],
129
testPathIgnorePatterns: ['/node_modules/.+']
130
}));
131
}
132
133
function _promiseOnlyChangedTestPaths(testRunner, config) {
134
var testPathDirsAreGit = config.testPathDirs.map(_verifyIsGitRepository);
135
return q.all(testPathDirsAreGit)
136
.then(function(results) {
137
if (!results.every(function(result) { return result; })) {
138
throw (
139
'It appears that one of your testPathDirs does not exist ' +
140
'with in a git repository. Currently --onlyChanged only works ' +
141
'with git projects.\n'
142
);
143
}
144
return q.all(config.testPathDirs.map(_findChangedFiles));
145
})
146
.then(function(changedPathSets) {
147
// Collapse changed files from each of the testPathDirs into a single list
148
// of changed file paths
149
var changedPaths = [];
150
changedPathSets.forEach(function(pathSet) {
151
changedPaths = changedPaths.concat(pathSet);
152
});
153
return testRunner.promiseTestPathsRelatedTo(changedPaths);
154
});
155
}
156
157
function _promisePatternMatchingTestPaths(argv, testRunner) {
158
var pattern = argv.testPathPattern ||
159
( (argv._ && argv._.length) ? argv._.join('|') : '.*' );
160
161
return testRunner.promiseTestPathsMatching(new RegExp(pattern));
162
}
163
164
function runCLI(argv, packageRoot, onComplete) {
165
argv = argv || {};
166
167
if (argv.version) {
168
console.log('v' + getVersion());
169
onComplete && onComplete(true);
170
return;
171
}
172
173
_promiseConfig(argv, packageRoot).then(function(config) {
174
var testRunner = new TestRunner(config, _testRunnerOptions(argv));
175
var testPaths = argv.onlyChanged ?
176
_promiseOnlyChangedTestPaths(testRunner, config) :
177
_promisePatternMatchingTestPaths(argv, testRunner);
178
return testPaths.then(function (testPaths) {
179
return testRunner.runTests(testPaths);
180
});
181
}).then(function (runResults) {
182
onComplete && onComplete(runResults.success);
183
}).catch(function (error) {
184
console.error('Failed with unexpected error.');
185
process.nextTick(function () {
186
throw error;
187
});
188
});
189
}
190
191
exports.TestRunner = TestRunner;
192
exports.getVersion = getVersion;
193
exports.runCLI = runCLI;
194
195