-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
/
Copy pathTestPathPatterns.ts
128 lines (110 loc) · 2.86 KB
/
TestPathPatterns.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import * as path from 'path';
import {replacePathSepForRegex} from 'jest-regex-util';
export class TestPathPatterns {
constructor(readonly patterns: Array<string>) {}
/**
* Return true if there are any patterns.
*/
isSet(): boolean {
return this.patterns.length > 0;
}
/**
* Return true if the patterns are valid.
*/
isValid(): boolean {
return this.toExecutor({
// isValid() doesn't require rootDir to be accurate, so just
// specify a dummy rootDir here
rootDir: '/',
}).isValid();
}
/**
* Return a human-friendly version of the pattern regex.
*/
toPretty(): string {
return this.patterns.join('|');
}
/**
* Return a TestPathPatternsExecutor that can execute the patterns.
*/
toExecutor(
options: TestPathPatternsExecutorOptions,
): TestPathPatternsExecutor {
return new TestPathPatternsExecutor(this, options);
}
/** For jest serializers */
toJSON(): any {
return {
patterns: this.patterns,
type: 'TestPathPatterns',
};
}
}
export type TestPathPatternsExecutorOptions = {
rootDir: string;
};
export class TestPathPatternsExecutor {
constructor(
readonly patterns: TestPathPatterns,
private readonly options: TestPathPatternsExecutorOptions,
) {}
private toRegex(s: string): RegExp {
return new RegExp(s, 'i');
}
/**
* Return true if there are any patterns.
*/
isSet(): boolean {
return this.patterns.isSet();
}
/**
* Return true if the patterns are valid.
*/
isValid(): boolean {
try {
for (const p of this.patterns.patterns) {
this.toRegex(p);
}
return true;
} catch {
return false;
}
}
/**
* Return true if the given ABSOLUTE path matches the patterns.
*
* Throws an error if the patterns form an invalid regex (see `validate`).
*/
isMatch(absPath: string): boolean {
const relPath = path.relative(this.options.rootDir || '/', absPath);
if (this.patterns.patterns.length === 0) {
return true;
}
for (const p of this.patterns.patterns) {
const pathToTest = path.isAbsolute(p) ? absPath : relPath;
// special case: ./foo.spec.js (and .\foo.spec.js on Windows) should
// match /^foo.spec.js/ after stripping root dir
let regexStr = p.replace(/^\.\//, '^');
if (path.sep === '\\') {
regexStr = regexStr.replace(/^\.\\/, '^');
}
regexStr = replacePathSepForRegex(regexStr);
if (this.toRegex(regexStr).test(pathToTest)) {
return true;
}
}
return false;
}
/**
* Return a human-friendly version of the pattern regex.
*/
toPretty(): string {
return this.patterns.toPretty();
}
}