ava 4.0.0-alpha.1 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/entrypoints/cli.mjs +4 -0
- package/{eslint-plugin-helper.js → entrypoints/eslint-plugin-helper.cjs} +20 -7
- package/entrypoints/main.cjs +2 -0
- package/entrypoints/main.mjs +1 -0
- package/entrypoints/plugin.cjs +2 -0
- package/entrypoints/plugin.mjs +4 -0
- package/index.d.ts +6 -709
- package/lib/api.js +95 -46
- package/lib/assert.js +122 -173
- package/lib/chalk.js +9 -14
- package/lib/cli.js +105 -97
- package/lib/code-excerpt.js +12 -17
- package/lib/concordance-options.js +30 -31
- package/lib/context-ref.js +3 -6
- package/lib/create-chain.js +32 -4
- package/lib/environment-variables.js +1 -4
- package/lib/eslint-plugin-helper-worker.js +16 -26
- package/lib/extensions.js +2 -2
- package/lib/fork.js +42 -83
- package/lib/glob-helpers.cjs +140 -0
- package/lib/globs.js +136 -163
- package/lib/{ipc-flow-control.js → ipc-flow-control.cjs} +1 -0
- package/lib/is-ci.js +4 -2
- package/lib/like-selector.js +7 -13
- package/lib/line-numbers.js +10 -17
- package/lib/load-config.js +62 -56
- package/lib/module-types.js +3 -3
- package/lib/node-arguments.js +4 -5
- package/lib/{now-and-timers.js → now-and-timers.cjs} +0 -0
- package/lib/parse-test-args.js +22 -11
- package/lib/pkg.cjs +2 -0
- package/lib/plugin-support/shared-worker-loader.js +45 -48
- package/lib/plugin-support/shared-workers.js +24 -43
- package/lib/provider-manager.js +20 -14
- package/lib/reporters/beautify-stack.js +6 -11
- package/lib/reporters/colors.js +40 -15
- package/lib/reporters/default.js +115 -350
- package/lib/reporters/format-serialized-error.js +7 -18
- package/lib/reporters/improper-usage-messages.js +8 -9
- package/lib/reporters/prefix-title.js +17 -15
- package/lib/reporters/tap.js +15 -16
- package/lib/run-status.js +25 -23
- package/lib/runner.js +138 -127
- package/lib/scheduler.js +42 -36
- package/lib/serialize-error.js +34 -34
- package/lib/snapshot-manager.js +83 -76
- package/lib/test.js +114 -195
- package/lib/watcher.js +65 -40
- package/lib/worker/base.js +48 -99
- package/lib/worker/channel.cjs +290 -0
- package/lib/worker/dependency-tracker.js +22 -22
- package/lib/worker/guard-environment.cjs +19 -0
- package/lib/worker/line-numbers.js +57 -19
- package/lib/worker/main.cjs +12 -0
- package/lib/worker/{options.js → options.cjs} +0 -0
- package/lib/worker/{plugin.js → plugin.cjs} +31 -16
- package/lib/worker/state.cjs +5 -0
- package/lib/worker/{utils.js → utils.cjs} +1 -1
- package/package.json +60 -68
- package/plugin.d.ts +51 -53
- package/readme.md +5 -12
- package/types/assertions.d.ts +327 -0
- package/types/subscribable.ts +6 -0
- package/types/test-fn.d.ts +231 -0
- package/types/try-fn.d.ts +58 -0
- package/cli.js +0 -11
- package/index.js +0 -8
- package/lib/worker/channel.js +0 -218
- package/lib/worker/main.js +0 -20
- package/plugin.js +0 -9
package/lib/globs.js
CHANGED
|
@@ -1,54 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
import {globby, globbySync} from 'globby';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
defaultIgnorePatterns,
|
|
8
|
+
hasExtension,
|
|
9
|
+
normalizeFileForMatching,
|
|
10
|
+
normalizePatterns,
|
|
11
|
+
processMatchingPatterns,
|
|
12
|
+
} from './glob-helpers.cjs';
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
classify,
|
|
16
|
+
isHelperish,
|
|
17
|
+
matches,
|
|
18
|
+
normalizePattern,
|
|
19
|
+
defaultIgnorePatterns,
|
|
20
|
+
hasExtension,
|
|
21
|
+
normalizeFileForMatching,
|
|
22
|
+
normalizePatterns,
|
|
23
|
+
} from './glob-helpers.cjs';
|
|
17
24
|
|
|
18
25
|
const defaultIgnoredByWatcherPatterns = [
|
|
19
26
|
'**/*.snap.md', // No need to rerun tests when the Markdown files change.
|
|
20
27
|
'ava.config.js', // Config is not reloaded so avoid rerunning tests when it changes.
|
|
21
|
-
'ava.config.cjs' // Config is not reloaded so avoid rerunning tests when it changes.
|
|
28
|
+
'ava.config.cjs', // Config is not reloaded so avoid rerunning tests when it changes.
|
|
22
29
|
];
|
|
23
30
|
|
|
24
31
|
const buildExtensionPattern = extensions => extensions.length === 1 ? extensions[0] : `{${extensions.join(',')}}`;
|
|
25
32
|
|
|
26
|
-
function
|
|
27
|
-
// Always use `/` in patterns, harmonizing matching across platforms
|
|
28
|
-
if (process.platform === 'win32') {
|
|
29
|
-
pattern = slash(pattern);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (pattern.startsWith('./')) {
|
|
33
|
-
return pattern.slice(2);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (pattern.startsWith('!./')) {
|
|
37
|
-
return `!${pattern.slice(3)}`;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return pattern;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
exports.normalizePattern = normalizePattern;
|
|
44
|
-
|
|
45
|
-
function normalizePatterns(patterns) {
|
|
46
|
-
return patterns.map(pattern => normalizePattern(pattern));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
exports.normalizePatterns = normalizePatterns;
|
|
50
|
-
|
|
51
|
-
function normalizeGlobs({extensions, files: filePatterns, ignoredByWatcher: ignoredByWatcherPatterns, providers}) {
|
|
33
|
+
export function normalizeGlobs({extensions, files: filePatterns, ignoredByWatcher: ignoredByWatcherPatterns, providers}) {
|
|
52
34
|
if (filePatterns !== undefined && (!Array.isArray(filePatterns) || filePatterns.length === 0)) {
|
|
53
35
|
throw new Error('The ’files’ configuration must be an array containing glob patterns.');
|
|
54
36
|
}
|
|
@@ -68,7 +50,7 @@ function normalizeGlobs({extensions, files: filePatterns, ignoredByWatcher: igno
|
|
|
68
50
|
`**/test/**/*.${extensionPattern}`,
|
|
69
51
|
`**/tests/**/*.${extensionPattern}`,
|
|
70
52
|
'!**/__tests__/**/__{helper,fixture}?(s)__/**/*',
|
|
71
|
-
'!**/test?(s)/**/{helper,fixture}?(s)/**/*'
|
|
53
|
+
'!**/test?(s)/**/{helper,fixture}?(s)/**/*',
|
|
72
54
|
];
|
|
73
55
|
|
|
74
56
|
if (filePatterns) {
|
|
@@ -84,40 +66,36 @@ function normalizeGlobs({extensions, files: filePatterns, ignoredByWatcher: igno
|
|
|
84
66
|
|
|
85
67
|
ignoredByWatcherPatterns = ignoredByWatcherPatterns ? [...defaultIgnoredByWatcherPatterns, ...normalizePatterns(ignoredByWatcherPatterns)] : [...defaultIgnoredByWatcherPatterns];
|
|
86
68
|
|
|
87
|
-
for (const {
|
|
88
|
-
|
|
89
|
-
({filePatterns, ignoredByWatcherPatterns} = main.updateGlobs({filePatterns, ignoredByWatcherPatterns}));
|
|
90
|
-
}
|
|
69
|
+
for (const {main} of providers) {
|
|
70
|
+
({filePatterns, ignoredByWatcherPatterns} = main.updateGlobs({filePatterns, ignoredByWatcherPatterns}));
|
|
91
71
|
}
|
|
92
72
|
|
|
93
73
|
return {extensions, filePatterns, ignoredByWatcherPatterns};
|
|
94
74
|
}
|
|
95
75
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
76
|
+
const globOptions = {
|
|
77
|
+
// Globs should work relative to the cwd value only (this should be the
|
|
78
|
+
// project directory that AVA is run in).
|
|
79
|
+
absolute: false,
|
|
80
|
+
braceExpansion: true,
|
|
81
|
+
caseSensitiveMatch: false,
|
|
82
|
+
dot: false,
|
|
83
|
+
expandDirectories: false,
|
|
84
|
+
extglob: true,
|
|
85
|
+
followSymbolicLinks: true,
|
|
86
|
+
gitignore: false,
|
|
87
|
+
globstar: true,
|
|
88
|
+
ignore: defaultIgnorePatterns,
|
|
89
|
+
baseNameMatch: false,
|
|
90
|
+
stats: false,
|
|
91
|
+
unique: true,
|
|
92
|
+
};
|
|
101
93
|
|
|
102
94
|
const globFiles = async (cwd, patterns) => {
|
|
103
95
|
const files = await globby(patterns, {
|
|
104
|
-
|
|
105
|
-
// project directory that AVA is run in).
|
|
106
|
-
absolute: false,
|
|
107
|
-
braceExpansion: true,
|
|
108
|
-
caseSensitiveMatch: false,
|
|
96
|
+
...globOptions,
|
|
109
97
|
cwd,
|
|
110
|
-
dot: false,
|
|
111
|
-
expandDirectories: false,
|
|
112
|
-
extglob: true,
|
|
113
|
-
followSymbolicLinks: true,
|
|
114
|
-
gitignore: false,
|
|
115
|
-
globstar: true,
|
|
116
|
-
ignore: defaultIgnorePatterns,
|
|
117
|
-
baseNameMatch: false,
|
|
118
98
|
onlyFiles: true,
|
|
119
|
-
stats: false,
|
|
120
|
-
unique: true
|
|
121
99
|
});
|
|
122
100
|
|
|
123
101
|
// Return absolute file paths. This has the side-effect of normalizing paths
|
|
@@ -125,119 +103,114 @@ const globFiles = async (cwd, patterns) => {
|
|
|
125
103
|
return files.map(file => path.join(cwd, file));
|
|
126
104
|
};
|
|
127
105
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
106
|
+
const globDirectoriesSync = (cwd, patterns) => {
|
|
107
|
+
const files = globbySync(patterns, {
|
|
108
|
+
...globOptions,
|
|
109
|
+
cwd,
|
|
110
|
+
onlyDirectories: true,
|
|
111
|
+
});
|
|
131
112
|
|
|
132
|
-
|
|
113
|
+
// Return absolute file paths. This has the side-effect of normalizing paths
|
|
114
|
+
// on Windows.
|
|
115
|
+
return files.map(file => path.join(cwd, file));
|
|
116
|
+
};
|
|
133
117
|
|
|
134
|
-
async function
|
|
135
|
-
|
|
118
|
+
export async function findFiles({cwd, extensions, filePatterns}) {
|
|
119
|
+
const files = await globFiles(cwd, filePatterns);
|
|
120
|
+
return files.filter(file => hasExtension(extensions, file));
|
|
136
121
|
}
|
|
137
122
|
|
|
138
|
-
|
|
123
|
+
export async function findTests({cwd, extensions, filePatterns}) {
|
|
124
|
+
const files = await findFiles({cwd, extensions, filePatterns});
|
|
125
|
+
return files.filter(file => !path.basename(file).startsWith('_'));
|
|
126
|
+
}
|
|
139
127
|
|
|
140
|
-
function getChokidarIgnorePatterns({ignoredByWatcherPatterns}) {
|
|
128
|
+
export function getChokidarIgnorePatterns({ignoredByWatcherPatterns}) {
|
|
141
129
|
return [
|
|
142
130
|
...defaultIgnorePatterns.map(pattern => `${pattern}/**/*`),
|
|
143
|
-
...ignoredByWatcherPatterns.filter(pattern => !pattern.startsWith('!'))
|
|
131
|
+
...ignoredByWatcherPatterns.filter(pattern => !pattern.startsWith('!')),
|
|
144
132
|
];
|
|
145
133
|
}
|
|
146
134
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
135
|
+
export function applyTestFileFilter({ // eslint-disable-line complexity
|
|
136
|
+
cwd,
|
|
137
|
+
expandDirectories = true,
|
|
138
|
+
filter,
|
|
139
|
+
providers = [],
|
|
140
|
+
testFiles,
|
|
141
|
+
treatFilterPatternsAsFiles = true,
|
|
142
|
+
}) {
|
|
143
|
+
const {individualMatchers} = processMatchingPatterns(filter);
|
|
144
|
+
const normalizedFiles = testFiles.map(file => ({file, matcheable: normalizeFileForMatching(cwd, file)}));
|
|
145
|
+
|
|
146
|
+
const selected = new Set();
|
|
147
|
+
const unmatchedPatterns = new Set(individualMatchers.map(({pattern}) => pattern));
|
|
148
|
+
|
|
149
|
+
for (const {pattern, match} of individualMatchers) {
|
|
150
|
+
for (const {file, matcheable} of normalizedFiles) {
|
|
151
|
+
if (match(matcheable)) {
|
|
152
|
+
unmatchedPatterns.delete(pattern);
|
|
153
|
+
selected.add(file);
|
|
159
154
|
}
|
|
160
|
-
|
|
161
|
-
return true;
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
result = {
|
|
165
|
-
match: picomatch(patterns, {ignore}),
|
|
166
|
-
matchNoIgnore: picomatch(patterns)
|
|
167
|
-
};
|
|
168
|
-
matchingCache.set(input, result);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return result;
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
function matches(file, patterns) {
|
|
175
|
-
const {match} = processMatchingPatterns(patterns);
|
|
176
|
-
return match(file);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
exports.matches = matches;
|
|
180
|
-
|
|
181
|
-
const matchesIgnorePatterns = (file, patterns) => {
|
|
182
|
-
const {matchNoIgnore} = processMatchingPatterns(patterns);
|
|
183
|
-
return matchNoIgnore(file) || defaultMatchNoIgnore(file);
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
function normalizeFileForMatching(cwd, file) {
|
|
187
|
-
if (process.platform === 'win32') {
|
|
188
|
-
cwd = slash(cwd);
|
|
189
|
-
file = slash(file);
|
|
155
|
+
}
|
|
190
156
|
}
|
|
191
157
|
|
|
192
|
-
if (
|
|
193
|
-
|
|
194
|
-
|
|
158
|
+
if (expandDirectories && unmatchedPatterns.size > 0) {
|
|
159
|
+
const expansion = [];
|
|
160
|
+
for (const pattern of unmatchedPatterns) {
|
|
161
|
+
const directories = globDirectoriesSync(cwd, pattern);
|
|
162
|
+
if (directories.length > 0) {
|
|
163
|
+
unmatchedPatterns.delete(pattern);
|
|
164
|
+
expansion.push(directories);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
195
167
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
168
|
+
const directories = expansion.flat();
|
|
169
|
+
if (directories.length > 0) {
|
|
170
|
+
for (const file of testFiles) {
|
|
171
|
+
if (selected.has(file)) {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
for (const dir of directories) {
|
|
176
|
+
if (file.startsWith(dir + path.sep)) { // eslint-disable-line max-depth
|
|
177
|
+
selected.add(file);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
201
182
|
}
|
|
202
183
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
184
|
+
const ignoredFilterPatternFiles = [];
|
|
185
|
+
if (treatFilterPatternsAsFiles && unmatchedPatterns.size > 0) {
|
|
186
|
+
const providerExtensions = new Set(providers.flatMap(({main}) => main.extensions));
|
|
187
|
+
for (const pattern of unmatchedPatterns) {
|
|
188
|
+
const file = path.join(cwd, pattern);
|
|
189
|
+
try {
|
|
190
|
+
const stats = fs.statSync(file);
|
|
191
|
+
if (!stats.isFile()) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
} catch (error) {
|
|
195
|
+
if (error.code === 'ENOENT') {
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
throw error;
|
|
200
|
+
}
|
|
208
201
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
202
|
+
if (
|
|
203
|
+
path.basename(file).startsWith('_')
|
|
204
|
+
|| providerExtensions.has(path.extname(file).slice(1))
|
|
205
|
+
|| file.split(path.sep).includes('node_modules')
|
|
206
|
+
) {
|
|
207
|
+
ignoredFilterPatternFiles.push(pattern);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
214
210
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
// Deem it not a "helper".
|
|
218
|
-
if (path.isAbsolute(file)) {
|
|
219
|
-
return false;
|
|
211
|
+
selected.add(file);
|
|
212
|
+
}
|
|
220
213
|
}
|
|
221
214
|
|
|
222
|
-
|
|
223
|
-
// underscore, it's deemed a "helper".
|
|
224
|
-
return path.dirname(file).split('/').some(dir => /^_(?:$|[^_])/.test(dir));
|
|
215
|
+
return Object.assign([...selected], {ignoredFilterPatternFiles});
|
|
225
216
|
}
|
|
226
|
-
|
|
227
|
-
exports.isHelperish = isHelperish;
|
|
228
|
-
|
|
229
|
-
function classify(file, {cwd, extensions, filePatterns, ignoredByWatcherPatterns}) {
|
|
230
|
-
file = normalizeFileForMatching(cwd, file);
|
|
231
|
-
return {
|
|
232
|
-
isIgnoredByWatcher: matchesIgnorePatterns(file, ignoredByWatcherPatterns),
|
|
233
|
-
isTest: hasExtension(extensions, file) && !isHelperish(file) && filePatterns.length > 0 && matches(file, filePatterns)
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
exports.classify = classify;
|
|
238
|
-
|
|
239
|
-
function applyTestFileFilter({cwd, filter, testFiles}) {
|
|
240
|
-
return testFiles.filter(file => matches(normalizeFileForMatching(cwd, file), filter));
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
exports.applyTestFileFilter = applyTestFileFilter;
|
package/lib/is-ci.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import process from 'node:process';
|
|
2
|
+
|
|
3
|
+
import info from 'ci-info';
|
|
2
4
|
|
|
3
5
|
const {AVA_FORCE_CI} = process.env;
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
export default AVA_FORCE_CI === 'not-ci' ? false : AVA_FORCE_CI === 'ci' || info.isCI;
|
package/lib/like-selector.js
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Reflect.
|
|
6
|
-
Reflect.ownKeys(selector).length > 0;
|
|
1
|
+
export function isLikeSelector(selector) {
|
|
2
|
+
return selector !== null
|
|
3
|
+
&& typeof selector === 'object'
|
|
4
|
+
&& Reflect.getPrototypeOf(selector) === Object.prototype
|
|
5
|
+
&& Reflect.ownKeys(selector).length > 0;
|
|
7
6
|
}
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
export const CIRCULAR_SELECTOR = new Error('Encountered a circular selector');
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
exports.CIRCULAR_SELECTOR = CIRCULAR_SELECTOR;
|
|
13
|
-
|
|
14
|
-
function selectComparable(lhs, selector, circular = new Set()) {
|
|
10
|
+
export function selectComparable(lhs, selector, circular = new Set()) {
|
|
15
11
|
if (circular.has(selector)) {
|
|
16
12
|
throw CIRCULAR_SELECTOR;
|
|
17
13
|
}
|
|
@@ -33,5 +29,3 @@ function selectComparable(lhs, selector, circular = new Set()) {
|
|
|
33
29
|
|
|
34
30
|
return comparable;
|
|
35
31
|
}
|
|
36
|
-
|
|
37
|
-
exports.selectComparable = selectComparable;
|
package/lib/line-numbers.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const picomatch = require('picomatch');
|
|
4
|
-
const flatten = require('lodash/flatten');
|
|
1
|
+
import picomatch from 'picomatch';
|
|
5
2
|
|
|
6
3
|
const NUMBER_REGEX = /^\d+$/;
|
|
7
4
|
const RANGE_REGEX = /^(?<startGroup>\d+)-(?<endGroup>\d+)$/;
|
|
@@ -19,8 +16,8 @@ const parseNumber = string => Number.parseInt(string, 10);
|
|
|
19
16
|
const removeAllWhitespace = string => string.replace(/\s/g, '');
|
|
20
17
|
const range = (start, end) => Array.from({length: end - start + 1}).fill(start).map((element, index) => element + index);
|
|
21
18
|
|
|
22
|
-
const parseLineNumbers = suffix => sortNumbersAscending(distinctArray(
|
|
23
|
-
suffix.split(',').
|
|
19
|
+
const parseLineNumbers = suffix => sortNumbersAscending(distinctArray(
|
|
20
|
+
suffix.split(',').flatMap(part => {
|
|
24
21
|
if (NUMBER_REGEX.test(part)) {
|
|
25
22
|
return parseNumber(part);
|
|
26
23
|
}
|
|
@@ -34,10 +31,10 @@ const parseLineNumbers = suffix => sortNumbersAscending(distinctArray(flatten(
|
|
|
34
31
|
}
|
|
35
32
|
|
|
36
33
|
return range(start, end);
|
|
37
|
-
})
|
|
38
|
-
))
|
|
34
|
+
}),
|
|
35
|
+
));
|
|
39
36
|
|
|
40
|
-
function splitPatternAndLineNumbers(pattern) {
|
|
37
|
+
export function splitPatternAndLineNumbers(pattern) {
|
|
41
38
|
const parts = pattern.split(DELIMITER);
|
|
42
39
|
if (parts.length === 1) {
|
|
43
40
|
return {pattern, lineNumbers: null};
|
|
@@ -51,14 +48,10 @@ function splitPatternAndLineNumbers(pattern) {
|
|
|
51
48
|
return {pattern: parts.join(DELIMITER), lineNumbers: parseLineNumbers(suffix)};
|
|
52
49
|
}
|
|
53
50
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
function getApplicableLineNumbers(normalizedFilePath, filter) {
|
|
57
|
-
return sortNumbersAscending(distinctArray(flatten(
|
|
51
|
+
export function getApplicableLineNumbers(normalizedFilePath, filter) {
|
|
52
|
+
return sortNumbersAscending(distinctArray(
|
|
58
53
|
filter
|
|
59
54
|
.filter(({pattern, lineNumbers}) => lineNumbers && picomatch.isMatch(normalizedFilePath, pattern))
|
|
60
|
-
.
|
|
61
|
-
))
|
|
55
|
+
.flatMap(({lineNumbers}) => lineNumbers),
|
|
56
|
+
));
|
|
62
57
|
}
|
|
63
|
-
|
|
64
|
-
exports.getApplicableLineNumbers = getApplicableLineNumbers;
|
package/lib/load-config.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
import url from 'node:url';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import {isPlainObject} from 'is-plain-object';
|
|
7
|
+
import {packageConfig, packageJsonPath} from 'pkg-conf';
|
|
8
8
|
|
|
9
9
|
const NO_SUCH_FILE = Symbol('no ava.config.js file');
|
|
10
10
|
const MISSING_DEFAULT_EXPORT = Symbol('missing default export');
|
|
11
|
-
const EXPERIMENTS = new Set(
|
|
12
|
-
'sharedWorkers'
|
|
13
|
-
]);
|
|
11
|
+
const EXPERIMENTS = new Set();
|
|
14
12
|
|
|
15
13
|
const importConfig = async ({configFile, fileForErrorMessage}) => {
|
|
16
14
|
const {default: config = MISSING_DEFAULT_EXPORT} = await import(url.pathToFileURL(configFile)); // eslint-disable-line node/no-unsupported-features/es-syntax
|
|
@@ -21,51 +19,22 @@ const importConfig = async ({configFile, fileForErrorMessage}) => {
|
|
|
21
19
|
return config;
|
|
22
20
|
};
|
|
23
21
|
|
|
24
|
-
const
|
|
25
|
-
if (!
|
|
22
|
+
const loadConfigFile = async ({projectDir, configFile}) => {
|
|
23
|
+
if (!fs.existsSync(configFile)) {
|
|
26
24
|
return null;
|
|
27
25
|
}
|
|
28
26
|
|
|
29
27
|
const fileForErrorMessage = path.relative(projectDir, configFile);
|
|
30
28
|
try {
|
|
31
|
-
return {config: await importConfig({configFile, fileForErrorMessage}), fileForErrorMessage};
|
|
29
|
+
return {config: await importConfig({configFile, fileForErrorMessage}), configFile, fileForErrorMessage};
|
|
32
30
|
} catch (error) {
|
|
33
31
|
throw Object.assign(new Error(`Error loading ${fileForErrorMessage}: ${error.message}`), {parent: error});
|
|
34
32
|
}
|
|
35
33
|
};
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
if (!configFile.endsWith('.cjs') || !fs.existsSync(configFile)) {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const fileForErrorMessage = path.relative(projectDir, configFile);
|
|
43
|
-
try {
|
|
44
|
-
return {config: await require(configFile), fileForErrorMessage};
|
|
45
|
-
} catch (error) {
|
|
46
|
-
throw Object.assign(new Error(`Error loading ${fileForErrorMessage}`), {parent: error});
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const loadMjsConfig = async ({projectDir, configFile = path.join(projectDir, 'ava.config.mjs')}) => {
|
|
51
|
-
if (!configFile.endsWith('.mjs') || !fs.existsSync(configFile)) {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const fileForErrorMessage = path.relative(projectDir, configFile);
|
|
56
|
-
try {
|
|
57
|
-
return {config: await importConfig({configFile, fileForErrorMessage}), fileForErrorMessage};
|
|
58
|
-
} catch (error) {
|
|
59
|
-
throw Object.assign(new Error(`Error loading ${fileForErrorMessage}`), {parent: error});
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
function resolveConfigFile(projectDir, configFile) {
|
|
35
|
+
function resolveConfigFile(configFile) {
|
|
64
36
|
if (configFile) {
|
|
65
37
|
configFile = path.resolve(configFile); // Relative to CWD
|
|
66
|
-
if (path.basename(configFile) !== path.relative(projectDir, configFile)) {
|
|
67
|
-
throw new Error('Config files must be located next to the package.json file');
|
|
68
|
-
}
|
|
69
38
|
|
|
70
39
|
if (!configFile.endsWith('.js') && !configFile.endsWith('.cjs') && !configFile.endsWith('.mjs')) {
|
|
71
40
|
throw new Error('Config files must have .js, .cjs or .mjs extensions');
|
|
@@ -75,20 +44,59 @@ function resolveConfigFile(projectDir, configFile) {
|
|
|
75
44
|
return configFile;
|
|
76
45
|
}
|
|
77
46
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const
|
|
47
|
+
const gitScmFile = process.env.AVA_FAKE_SCM_ROOT || '.git';
|
|
48
|
+
|
|
49
|
+
async function findRepoRoot(fromDir) {
|
|
50
|
+
const {root} = path.parse(fromDir);
|
|
51
|
+
let dir = fromDir;
|
|
52
|
+
while (root !== dir) {
|
|
53
|
+
try {
|
|
54
|
+
const stat = await fs.promises.stat(path.join(dir, gitScmFile)); // eslint-disable-line no-await-in-loop
|
|
55
|
+
if (stat.isFile() || stat.isDirectory()) {
|
|
56
|
+
return dir;
|
|
57
|
+
}
|
|
58
|
+
} catch {}
|
|
59
|
+
|
|
60
|
+
dir = path.dirname(dir);
|
|
61
|
+
}
|
|
82
62
|
|
|
83
|
-
|
|
63
|
+
return root;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) {
|
|
67
|
+
let packageConf = await packageConfig('ava', {cwd: resolveFrom});
|
|
68
|
+
const filepath = packageJsonPath(packageConf);
|
|
69
|
+
const projectDir = filepath === undefined ? resolveFrom : path.dirname(filepath);
|
|
70
|
+
|
|
71
|
+
const repoRoot = await findRepoRoot(projectDir);
|
|
72
|
+
|
|
73
|
+
// Conflicts are only allowed when an explicit config file is provided.
|
|
84
74
|
const allowConflictWithPackageJson = Boolean(configFile);
|
|
75
|
+
configFile = resolveConfigFile(configFile);
|
|
85
76
|
|
|
86
|
-
|
|
87
|
-
let
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
77
|
+
let fileConf = NO_SUCH_FILE;
|
|
78
|
+
let fileForErrorMessage;
|
|
79
|
+
let conflicting = [];
|
|
80
|
+
if (configFile) {
|
|
81
|
+
const loaded = await loadConfigFile({projectDir, configFile});
|
|
82
|
+
if (loaded !== null) {
|
|
83
|
+
({config: fileConf, fileForErrorMessage} = loaded);
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
let searchDir = projectDir;
|
|
87
|
+
const stopAt = path.dirname(repoRoot);
|
|
88
|
+
do {
|
|
89
|
+
const results = await Promise.all([ // eslint-disable-line no-await-in-loop
|
|
90
|
+
loadConfigFile({projectDir, configFile: path.join(searchDir, 'ava.config.js')}),
|
|
91
|
+
loadConfigFile({projectDir, configFile: path.join(searchDir, 'ava.config.cjs')}),
|
|
92
|
+
loadConfigFile({projectDir, configFile: path.join(searchDir, 'ava.config.mjs')}),
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
[{config: fileConf, fileForErrorMessage, configFile} = {config: NO_SUCH_FILE, fileForErrorMessage: undefined}, ...conflicting] = results.filter(result => result !== null);
|
|
96
|
+
|
|
97
|
+
searchDir = path.dirname(searchDir);
|
|
98
|
+
} while (fileConf === NO_SUCH_FILE && searchDir !== stopAt);
|
|
99
|
+
}
|
|
92
100
|
|
|
93
101
|
if (conflicting.length > 0) {
|
|
94
102
|
throw new Error(`Conflicting configuration in ${fileForErrorMessage} and ${conflicting.map(({fileForErrorMessage}) => fileForErrorMessage).join(' & ')}`);
|
|
@@ -118,7 +126,7 @@ async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {
|
|
|
118
126
|
}
|
|
119
127
|
}
|
|
120
128
|
|
|
121
|
-
const config = {...defaults, nonSemVerExperiments: {}, ...fileConf, ...packageConf, projectDir};
|
|
129
|
+
const config = {...defaults, nonSemVerExperiments: {}, ...fileConf, ...packageConf, projectDir, configFile};
|
|
122
130
|
|
|
123
131
|
const {nonSemVerExperiments: experiments} = config;
|
|
124
132
|
if (!isPlainObject(experiments)) {
|
|
@@ -133,5 +141,3 @@ async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {
|
|
|
133
141
|
|
|
134
142
|
return config;
|
|
135
143
|
}
|
|
136
|
-
|
|
137
|
-
exports.loadConfig = loadConfig;
|
package/lib/module-types.js
CHANGED
|
@@ -54,12 +54,12 @@ const deriveFromArray = (extensions, defaultModuleType) => {
|
|
|
54
54
|
return moduleTypes;
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
export default function moduleTypes(configuredExtensions, defaultModuleType) {
|
|
58
58
|
if (configuredExtensions === undefined) {
|
|
59
59
|
return {
|
|
60
60
|
cjs: 'commonjs',
|
|
61
61
|
mjs: 'module',
|
|
62
|
-
js: defaultModuleType
|
|
62
|
+
js: defaultModuleType,
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -68,4 +68,4 @@ module.exports = (configuredExtensions, defaultModuleType) => {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
return deriveFromObject(configuredExtensions, defaultModuleType);
|
|
71
|
-
}
|
|
71
|
+
}
|
package/lib/node-arguments.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
const arrgv = require('arrgv');
|
|
1
|
+
import process from 'node:process';
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
import arrgv from 'arrgv';
|
|
4
|
+
|
|
5
|
+
export default function normalizeNodeArguments(fromConf = [], fromArgv = '') {
|
|
5
6
|
let parsedArgv = [];
|
|
6
7
|
if (fromArgv !== '') {
|
|
7
8
|
try {
|
|
@@ -13,5 +14,3 @@ function normalizeNodeArguments(fromConf = [], fromArgv = '') {
|
|
|
13
14
|
|
|
14
15
|
return [...process.execArgv, ...fromConf, ...parsedArgv];
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
module.exports = normalizeNodeArguments;
|
|
File without changes
|