UNPKG

11.4 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', {
4 value: true
5});
6exports.default = void 0;
7
8function os() {
9 const data = _interopRequireWildcard(require('os'));
10
11 os = function () {
12 return data;
13 };
14
15 return data;
16}
17
18function path() {
19 const data = _interopRequireWildcard(require('path'));
20
21 path = function () {
22 return data;
23 };
24
25 return data;
26}
27
28function _micromatch() {
29 const data = _interopRequireDefault(require('micromatch'));
30
31 _micromatch = function () {
32 return data;
33 };
34
35 return data;
36}
37
38function _jestResolveDependencies() {
39 const data = _interopRequireDefault(require('jest-resolve-dependencies'));
40
41 _jestResolveDependencies = function () {
42 return data;
43 };
44
45 return data;
46}
47
48function _jestRegexUtil() {
49 const data = require('jest-regex-util');
50
51 _jestRegexUtil = function () {
52 return data;
53 };
54
55 return data;
56}
57
58function _jestConfig() {
59 const data = require('jest-config');
60
61 _jestConfig = function () {
62 return data;
63 };
64
65 return data;
66}
67
68function _jestSnapshot() {
69 const data = require('jest-snapshot');
70
71 _jestSnapshot = function () {
72 return data;
73 };
74
75 return data;
76}
77
78function _jestUtil() {
79 const data = require('jest-util');
80
81 _jestUtil = function () {
82 return data;
83 };
84
85 return data;
86}
87
88function _interopRequireDefault(obj) {
89 return obj && obj.__esModule ? obj : {default: obj};
90}
91
92function _getRequireWildcardCache() {
93 if (typeof WeakMap !== 'function') return null;
94 var cache = new WeakMap();
95 _getRequireWildcardCache = function () {
96 return cache;
97 };
98 return cache;
99}
100
101function _interopRequireWildcard(obj) {
102 if (obj && obj.__esModule) {
103 return obj;
104 }
105 if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
106 return {default: obj};
107 }
108 var cache = _getRequireWildcardCache();
109 if (cache && cache.has(obj)) {
110 return cache.get(obj);
111 }
112 var newObj = {};
113 var hasPropertyDescriptor =
114 Object.defineProperty && Object.getOwnPropertyDescriptor;
115 for (var key in obj) {
116 if (Object.prototype.hasOwnProperty.call(obj, key)) {
117 var desc = hasPropertyDescriptor
118 ? Object.getOwnPropertyDescriptor(obj, key)
119 : null;
120 if (desc && (desc.get || desc.set)) {
121 Object.defineProperty(newObj, key, desc);
122 } else {
123 newObj[key] = obj[key];
124 }
125 }
126 }
127 newObj.default = obj;
128 if (cache) {
129 cache.set(obj, newObj);
130 }
131 return newObj;
132}
133
134function _defineProperty(obj, key, value) {
135 if (key in obj) {
136 Object.defineProperty(obj, key, {
137 value: value,
138 enumerable: true,
139 configurable: true,
140 writable: true
141 });
142 } else {
143 obj[key] = value;
144 }
145 return obj;
146}
147
148const regexToMatcher = testRegex => {
149 const regexes = testRegex.map(testRegex => new RegExp(testRegex));
150 return path =>
151 regexes.some(regex => {
152 const result = regex.test(path); // prevent stateful regexes from breaking, just in case
153
154 regex.lastIndex = 0;
155 return result;
156 });
157};
158
159const toTests = (context, tests) =>
160 tests.map(path => ({
161 context,
162 duration: undefined,
163 path
164 }));
165
166const hasSCM = changedFilesInfo => {
167 const {repos} = changedFilesInfo; // no SCM (git/hg/...) is found in any of the roots.
168
169 const noSCM = Object.values(repos).every(scm => scm.size === 0);
170 return !noSCM;
171};
172
173class SearchSource {
174 constructor(context) {
175 _defineProperty(this, '_context', void 0);
176
177 _defineProperty(this, '_dependencyResolver', void 0);
178
179 _defineProperty(this, '_testPathCases', []);
180
181 const {config} = context;
182 this._context = context;
183 this._dependencyResolver = null;
184 const rootPattern = new RegExp(
185 config.roots
186 .map(dir => (0, _jestRegexUtil().escapePathForRegex)(dir + path().sep))
187 .join('|')
188 );
189
190 this._testPathCases.push({
191 isMatch: path => rootPattern.test(path),
192 stat: 'roots'
193 });
194
195 if (config.testMatch.length) {
196 this._testPathCases.push({
197 isMatch: (0, _jestUtil().globsToMatcher)(config.testMatch),
198 stat: 'testMatch'
199 });
200 }
201
202 if (config.testPathIgnorePatterns.length) {
203 const testIgnorePatternsRegex = new RegExp(
204 config.testPathIgnorePatterns.join('|')
205 );
206
207 this._testPathCases.push({
208 isMatch: path => !testIgnorePatternsRegex.test(path),
209 stat: 'testPathIgnorePatterns'
210 });
211 }
212
213 if (config.testRegex.length) {
214 this._testPathCases.push({
215 isMatch: regexToMatcher(config.testRegex),
216 stat: 'testRegex'
217 });
218 }
219 }
220
221 _getOrBuildDependencyResolver() {
222 if (!this._dependencyResolver) {
223 this._dependencyResolver = new (_jestResolveDependencies().default)(
224 this._context.resolver,
225 this._context.hasteFS,
226 (0, _jestSnapshot().buildSnapshotResolver)(this._context.config)
227 );
228 }
229
230 return this._dependencyResolver;
231 }
232
233 _filterTestPathsWithStats(allPaths, testPathPattern) {
234 const data = {
235 stats: {
236 roots: 0,
237 testMatch: 0,
238 testPathIgnorePatterns: 0,
239 testRegex: 0
240 },
241 tests: [],
242 total: allPaths.length
243 };
244 const testCases = Array.from(this._testPathCases); // clone
245
246 if (testPathPattern) {
247 const regex = (0, _jestUtil().testPathPatternToRegExp)(testPathPattern);
248 testCases.push({
249 isMatch: path => regex.test(path),
250 stat: 'testPathPattern'
251 });
252 data.stats.testPathPattern = 0;
253 }
254
255 data.tests = allPaths.filter(test => {
256 let filterResult = true;
257
258 for (const {isMatch, stat} of testCases) {
259 if (isMatch(test.path)) {
260 data.stats[stat]++;
261 } else {
262 filterResult = false;
263 }
264 }
265
266 return filterResult;
267 });
268 return data;
269 }
270
271 _getAllTestPaths(testPathPattern) {
272 return this._filterTestPathsWithStats(
273 toTests(this._context, this._context.hasteFS.getAllFiles()),
274 testPathPattern
275 );
276 }
277
278 isTestFilePath(path) {
279 return this._testPathCases.every(testCase => testCase.isMatch(path));
280 }
281
282 findMatchingTests(testPathPattern) {
283 return this._getAllTestPaths(testPathPattern);
284 }
285
286 findRelatedTests(allPaths, collectCoverage) {
287 const dependencyResolver = this._getOrBuildDependencyResolver();
288
289 if (!collectCoverage) {
290 return {
291 tests: toTests(
292 this._context,
293 dependencyResolver.resolveInverse(
294 allPaths,
295 this.isTestFilePath.bind(this),
296 {
297 skipNodeResolution: this._context.config.skipNodeResolution
298 }
299 )
300 )
301 };
302 }
303
304 const testModulesMap = dependencyResolver.resolveInverseModuleMap(
305 allPaths,
306 this.isTestFilePath.bind(this),
307 {
308 skipNodeResolution: this._context.config.skipNodeResolution
309 }
310 );
311 const allPathsAbsolute = Array.from(allPaths).map(p => path().resolve(p));
312 const collectCoverageFrom = new Set();
313 testModulesMap.forEach(testModule => {
314 if (!testModule.dependencies) {
315 return;
316 }
317
318 testModule.dependencies.forEach(p => {
319 if (!allPathsAbsolute.includes(p)) {
320 return;
321 }
322
323 const filename = (0, _jestConfig().replaceRootDirInPath)(
324 this._context.config.rootDir,
325 p
326 );
327 collectCoverageFrom.add(
328 path().isAbsolute(filename)
329 ? path().relative(this._context.config.rootDir, filename)
330 : filename
331 );
332 });
333 });
334 return {
335 collectCoverageFrom,
336 tests: toTests(
337 this._context,
338 testModulesMap.map(testModule => testModule.file)
339 )
340 };
341 }
342
343 findTestsByPaths(paths) {
344 return {
345 tests: toTests(
346 this._context,
347 paths
348 .map(p => path().resolve(this._context.config.cwd, p))
349 .filter(this.isTestFilePath.bind(this))
350 )
351 };
352 }
353
354 findRelatedTestsFromPattern(paths, collectCoverage) {
355 if (Array.isArray(paths) && paths.length) {
356 const resolvedPaths = paths.map(p =>
357 path().resolve(this._context.config.cwd, p)
358 );
359 return this.findRelatedTests(new Set(resolvedPaths), collectCoverage);
360 }
361
362 return {
363 tests: []
364 };
365 }
366
367 findTestRelatedToChangedFiles(changedFilesInfo, collectCoverage) {
368 if (!hasSCM(changedFilesInfo)) {
369 return {
370 noSCM: true,
371 tests: []
372 };
373 }
374
375 const {changedFiles} = changedFilesInfo;
376 return this.findRelatedTests(changedFiles, collectCoverage);
377 }
378
379 _getTestPaths(globalConfig, changedFiles) {
380 if (globalConfig.onlyChanged) {
381 if (!changedFiles) {
382 throw new Error('Changed files must be set when running with -o.');
383 }
384
385 return this.findTestRelatedToChangedFiles(
386 changedFiles,
387 globalConfig.collectCoverage
388 );
389 }
390
391 let paths = globalConfig.nonFlagArgs;
392
393 if (globalConfig.findRelatedTests && 'win32' === os().platform()) {
394 const allFiles = this._context.hasteFS.getAllFiles();
395
396 const options = {
397 nocase: true,
398 windows: false
399 };
400 paths = paths
401 .map(p => {
402 const relativePath = path()
403 .resolve(this._context.config.cwd, p)
404 .replace(/\\/g, '\\\\');
405 const match = (0, _micromatch().default)(
406 allFiles,
407 relativePath,
408 options
409 );
410 return match[0];
411 })
412 .filter(Boolean);
413 }
414
415 if (globalConfig.runTestsByPath && paths && paths.length) {
416 return this.findTestsByPaths(paths);
417 } else if (globalConfig.findRelatedTests && paths && paths.length) {
418 return this.findRelatedTestsFromPattern(
419 paths,
420 globalConfig.collectCoverage
421 );
422 } else if (globalConfig.testPathPattern != null) {
423 return this.findMatchingTests(globalConfig.testPathPattern);
424 } else {
425 return {
426 tests: []
427 };
428 }
429 }
430
431 async getTestPaths(globalConfig, changedFiles, filter) {
432 const searchResult = this._getTestPaths(globalConfig, changedFiles);
433
434 const filterPath = globalConfig.filter;
435
436 if (filter) {
437 const tests = searchResult.tests;
438 const filterResult = await filter(tests.map(test => test.path));
439
440 if (!Array.isArray(filterResult.filtered)) {
441 throw new Error(
442 `Filter ${filterPath} did not return a valid test list`
443 );
444 }
445
446 const filteredSet = new Set(
447 filterResult.filtered.map(result => result.test)
448 );
449 return {
450 ...searchResult,
451 tests: tests.filter(test => filteredSet.has(test.path))
452 };
453 }
454
455 return searchResult;
456 }
457
458 findRelatedSourcesFromTestsInChangedFiles(changedFilesInfo) {
459 if (!hasSCM(changedFilesInfo)) {
460 return [];
461 }
462
463 const {changedFiles} = changedFilesInfo;
464
465 const dependencyResolver = this._getOrBuildDependencyResolver();
466
467 const relatedSourcesSet = new Set();
468 changedFiles.forEach(filePath => {
469 if (this.isTestFilePath(filePath)) {
470 const sourcePaths = dependencyResolver.resolve(filePath, {
471 skipNodeResolution: this._context.config.skipNodeResolution
472 });
473 sourcePaths.forEach(sourcePath => relatedSourcesSet.add(sourcePath));
474 }
475 });
476 return Array.from(relatedSourcesSet);
477 }
478}
479
480exports.default = SearchSource;