Upgrade Ava to v4
This commit is contained in:
parent
9a40cc5274
commit
ce89f1b611
1153 changed files with 27264 additions and 95308 deletions
305
node_modules/ava/lib/globs.js
generated
vendored
305
node_modules/ava/lib/globs.js
generated
vendored
|
|
@ -1,54 +1,36 @@
|
|||
'use strict';
|
||||
const path = require('path');
|
||||
const globby = require('globby');
|
||||
const ignoreByDefault = require('ignore-by-default');
|
||||
const picomatch = require('picomatch');
|
||||
const slash = require('slash');
|
||||
const providerManager = require('./provider-manager');
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
const defaultIgnorePatterns = [...ignoreByDefault.directories(), '**/node_modules'];
|
||||
const defaultPicomatchIgnorePatterns = [
|
||||
...defaultIgnorePatterns,
|
||||
// Unlike globby(), picomatch needs a complete pattern when ignoring directories.
|
||||
...defaultIgnorePatterns.map(pattern => `${pattern}/**/*`)
|
||||
];
|
||||
import {globby, globbySync} from 'globby';
|
||||
|
||||
const defaultMatchNoIgnore = picomatch(defaultPicomatchIgnorePatterns);
|
||||
import {
|
||||
defaultIgnorePatterns,
|
||||
hasExtension,
|
||||
normalizeFileForMatching,
|
||||
normalizePatterns,
|
||||
processMatchingPatterns,
|
||||
} from './glob-helpers.cjs';
|
||||
|
||||
export {
|
||||
classify,
|
||||
isHelperish,
|
||||
matches,
|
||||
normalizePattern,
|
||||
defaultIgnorePatterns,
|
||||
hasExtension,
|
||||
normalizeFileForMatching,
|
||||
normalizePatterns,
|
||||
} from './glob-helpers.cjs';
|
||||
|
||||
const defaultIgnoredByWatcherPatterns = [
|
||||
'**/*.snap.md', // No need to rerun tests when the Markdown files change.
|
||||
'ava.config.js', // Config is not reloaded so avoid rerunning tests when it changes.
|
||||
'ava.config.cjs' // Config is not reloaded so avoid rerunning tests when it changes.
|
||||
'ava.config.cjs', // Config is not reloaded so avoid rerunning tests when it changes.
|
||||
];
|
||||
|
||||
const buildExtensionPattern = extensions => extensions.length === 1 ? extensions[0] : `{${extensions.join(',')}}`;
|
||||
|
||||
function normalizePattern(pattern) {
|
||||
// Always use `/` in patterns, harmonizing matching across platforms
|
||||
if (process.platform === 'win32') {
|
||||
pattern = slash(pattern);
|
||||
}
|
||||
|
||||
if (pattern.startsWith('./')) {
|
||||
return pattern.slice(2);
|
||||
}
|
||||
|
||||
if (pattern.startsWith('!./')) {
|
||||
return `!${pattern.slice(3)}`;
|
||||
}
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
||||
exports.normalizePattern = normalizePattern;
|
||||
|
||||
function normalizePatterns(patterns) {
|
||||
return patterns.map(pattern => normalizePattern(pattern));
|
||||
}
|
||||
|
||||
exports.normalizePatterns = normalizePatterns;
|
||||
|
||||
function normalizeGlobs({extensions, files: filePatterns, ignoredByWatcher: ignoredByWatcherPatterns, providers}) {
|
||||
export function normalizeGlobs({extensions, files: filePatterns, ignoredByWatcher: ignoredByWatcherPatterns, providers}) {
|
||||
if (filePatterns !== undefined && (!Array.isArray(filePatterns) || filePatterns.length === 0)) {
|
||||
throw new Error('The ’files’ configuration must be an array containing glob patterns.');
|
||||
}
|
||||
|
|
@ -68,7 +50,7 @@ function normalizeGlobs({extensions, files: filePatterns, ignoredByWatcher: igno
|
|||
`**/test/**/*.${extensionPattern}`,
|
||||
`**/tests/**/*.${extensionPattern}`,
|
||||
'!**/__tests__/**/__{helper,fixture}?(s)__/**/*',
|
||||
'!**/test?(s)/**/{helper,fixture}?(s)/**/*'
|
||||
'!**/test?(s)/**/{helper,fixture}?(s)/**/*',
|
||||
];
|
||||
|
||||
if (filePatterns) {
|
||||
|
|
@ -84,40 +66,36 @@ function normalizeGlobs({extensions, files: filePatterns, ignoredByWatcher: igno
|
|||
|
||||
ignoredByWatcherPatterns = ignoredByWatcherPatterns ? [...defaultIgnoredByWatcherPatterns, ...normalizePatterns(ignoredByWatcherPatterns)] : [...defaultIgnoredByWatcherPatterns];
|
||||
|
||||
for (const {level, main} of providers) {
|
||||
if (level >= providerManager.levels.pathRewrites) {
|
||||
({filePatterns, ignoredByWatcherPatterns} = main.updateGlobs({filePatterns, ignoredByWatcherPatterns}));
|
||||
}
|
||||
for (const {main} of providers) {
|
||||
({filePatterns, ignoredByWatcherPatterns} = main.updateGlobs({filePatterns, ignoredByWatcherPatterns}));
|
||||
}
|
||||
|
||||
return {extensions, filePatterns, ignoredByWatcherPatterns};
|
||||
}
|
||||
|
||||
exports.normalizeGlobs = normalizeGlobs;
|
||||
|
||||
const hasExtension = (extensions, file) => extensions.includes(path.extname(file).slice(1));
|
||||
|
||||
exports.hasExtension = hasExtension;
|
||||
const globOptions = {
|
||||
// Globs should work relative to the cwd value only (this should be the
|
||||
// project directory that AVA is run in).
|
||||
absolute: false,
|
||||
braceExpansion: true,
|
||||
caseSensitiveMatch: false,
|
||||
dot: false,
|
||||
expandDirectories: false,
|
||||
extglob: true,
|
||||
followSymbolicLinks: true,
|
||||
gitignore: false,
|
||||
globstar: true,
|
||||
ignore: defaultIgnorePatterns,
|
||||
baseNameMatch: false,
|
||||
stats: false,
|
||||
unique: true,
|
||||
};
|
||||
|
||||
const globFiles = async (cwd, patterns) => {
|
||||
const files = await globby(patterns, {
|
||||
// Globs should work relative to the cwd value only (this should be the
|
||||
// project directory that AVA is run in).
|
||||
absolute: false,
|
||||
braceExpansion: true,
|
||||
caseSensitiveMatch: false,
|
||||
...globOptions,
|
||||
cwd,
|
||||
dot: false,
|
||||
expandDirectories: false,
|
||||
extglob: true,
|
||||
followSymbolicLinks: true,
|
||||
gitignore: false,
|
||||
globstar: true,
|
||||
ignore: defaultIgnorePatterns,
|
||||
baseNameMatch: false,
|
||||
onlyFiles: true,
|
||||
stats: false,
|
||||
unique: true
|
||||
});
|
||||
|
||||
// Return absolute file paths. This has the side-effect of normalizing paths
|
||||
|
|
@ -125,119 +103,114 @@ const globFiles = async (cwd, patterns) => {
|
|||
return files.map(file => path.join(cwd, file));
|
||||
};
|
||||
|
||||
async function findFiles({cwd, extensions, filePatterns}) {
|
||||
return (await globFiles(cwd, filePatterns)).filter(file => hasExtension(extensions, file));
|
||||
const globDirectoriesSync = (cwd, patterns) => {
|
||||
const files = globbySync(patterns, {
|
||||
...globOptions,
|
||||
cwd,
|
||||
onlyDirectories: true,
|
||||
});
|
||||
|
||||
// Return absolute file paths. This has the side-effect of normalizing paths
|
||||
// on Windows.
|
||||
return files.map(file => path.join(cwd, file));
|
||||
};
|
||||
|
||||
export async function findFiles({cwd, extensions, filePatterns}) {
|
||||
const files = await globFiles(cwd, filePatterns);
|
||||
return files.filter(file => hasExtension(extensions, file));
|
||||
}
|
||||
|
||||
exports.findFiles = findFiles;
|
||||
|
||||
async function findTests({cwd, extensions, filePatterns}) {
|
||||
return (await findFiles({cwd, extensions, filePatterns})).filter(file => !path.basename(file).startsWith('_'));
|
||||
export async function findTests({cwd, extensions, filePatterns}) {
|
||||
const files = await findFiles({cwd, extensions, filePatterns});
|
||||
return files.filter(file => !path.basename(file).startsWith('_'));
|
||||
}
|
||||
|
||||
exports.findTests = findTests;
|
||||
|
||||
function getChokidarIgnorePatterns({ignoredByWatcherPatterns}) {
|
||||
export function getChokidarIgnorePatterns({ignoredByWatcherPatterns}) {
|
||||
return [
|
||||
...defaultIgnorePatterns.map(pattern => `${pattern}/**/*`),
|
||||
...ignoredByWatcherPatterns.filter(pattern => !pattern.startsWith('!'))
|
||||
...ignoredByWatcherPatterns.filter(pattern => !pattern.startsWith('!')),
|
||||
];
|
||||
}
|
||||
|
||||
exports.getChokidarIgnorePatterns = getChokidarIgnorePatterns;
|
||||
export function applyTestFileFilter({ // eslint-disable-line complexity
|
||||
cwd,
|
||||
expandDirectories = true,
|
||||
filter,
|
||||
providers = [],
|
||||
testFiles,
|
||||
treatFilterPatternsAsFiles = true,
|
||||
}) {
|
||||
const {individualMatchers} = processMatchingPatterns(filter);
|
||||
const normalizedFiles = testFiles.map(file => ({file, matcheable: normalizeFileForMatching(cwd, file)}));
|
||||
|
||||
const matchingCache = new WeakMap();
|
||||
const processMatchingPatterns = input => {
|
||||
let result = matchingCache.get(input);
|
||||
if (!result) {
|
||||
const ignore = [...defaultPicomatchIgnorePatterns];
|
||||
const patterns = input.filter(pattern => {
|
||||
if (pattern.startsWith('!')) {
|
||||
// Unlike globby(), picomatch needs a complete pattern when ignoring directories.
|
||||
ignore.push(pattern.slice(1), `${pattern.slice(1)}/**/*`);
|
||||
return false;
|
||||
const selected = new Set();
|
||||
const unmatchedPatterns = new Set(individualMatchers.map(({pattern}) => pattern));
|
||||
|
||||
for (const {pattern, match} of individualMatchers) {
|
||||
for (const {file, matcheable} of normalizedFiles) {
|
||||
if (match(matcheable)) {
|
||||
unmatchedPatterns.delete(pattern);
|
||||
selected.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (expandDirectories && unmatchedPatterns.size > 0) {
|
||||
const expansion = [];
|
||||
for (const pattern of unmatchedPatterns) {
|
||||
const directories = globDirectoriesSync(cwd, pattern);
|
||||
if (directories.length > 0) {
|
||||
unmatchedPatterns.delete(pattern);
|
||||
expansion.push(directories);
|
||||
}
|
||||
}
|
||||
|
||||
const directories = expansion.flat();
|
||||
if (directories.length > 0) {
|
||||
for (const file of testFiles) {
|
||||
if (selected.has(file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const dir of directories) {
|
||||
if (file.startsWith(dir + path.sep)) { // eslint-disable-line max-depth
|
||||
selected.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ignoredFilterPatternFiles = [];
|
||||
if (treatFilterPatternsAsFiles && unmatchedPatterns.size > 0) {
|
||||
const providerExtensions = new Set(providers.flatMap(({main}) => main.extensions));
|
||||
for (const pattern of unmatchedPatterns) {
|
||||
const file = path.join(cwd, pattern);
|
||||
try {
|
||||
const stats = fs.statSync(file);
|
||||
if (!stats.isFile()) {
|
||||
continue;
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
continue;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
if (
|
||||
path.basename(file).startsWith('_')
|
||||
|| providerExtensions.has(path.extname(file).slice(1))
|
||||
|| file.split(path.sep).includes('node_modules')
|
||||
) {
|
||||
ignoredFilterPatternFiles.push(pattern);
|
||||
continue;
|
||||
}
|
||||
|
||||
result = {
|
||||
match: picomatch(patterns, {ignore}),
|
||||
matchNoIgnore: picomatch(patterns)
|
||||
};
|
||||
matchingCache.set(input, result);
|
||||
selected.add(file);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
function matches(file, patterns) {
|
||||
const {match} = processMatchingPatterns(patterns);
|
||||
return match(file);
|
||||
return Object.assign([...selected], {ignoredFilterPatternFiles});
|
||||
}
|
||||
|
||||
exports.matches = matches;
|
||||
|
||||
const matchesIgnorePatterns = (file, patterns) => {
|
||||
const {matchNoIgnore} = processMatchingPatterns(patterns);
|
||||
return matchNoIgnore(file) || defaultMatchNoIgnore(file);
|
||||
};
|
||||
|
||||
function normalizeFileForMatching(cwd, file) {
|
||||
if (process.platform === 'win32') {
|
||||
cwd = slash(cwd);
|
||||
file = slash(file);
|
||||
}
|
||||
|
||||
if (!cwd) { // TODO: Ensure tests provide an actual value.
|
||||
return file;
|
||||
}
|
||||
|
||||
// TODO: If `file` is outside `cwd` we can't normalize it. Need to figure
|
||||
// out if that's a real-world scenario, but we may have to ensure the file
|
||||
// isn't even selected.
|
||||
if (!file.startsWith(cwd)) {
|
||||
return file;
|
||||
}
|
||||
|
||||
// Assume `cwd` does *not* end in a slash.
|
||||
return file.slice(cwd.length + 1);
|
||||
}
|
||||
|
||||
exports.normalizeFileForMatching = normalizeFileForMatching;
|
||||
|
||||
function isHelperish(file) { // Assume file has been normalized already.
|
||||
// File names starting with an underscore are deemed "helpers".
|
||||
if (path.basename(file).startsWith('_')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// This function assumes the file has been normalized. If it couldn't be,
|
||||
// don't check if it's got a parent directory that starts with an underscore.
|
||||
// Deem it not a "helper".
|
||||
if (path.isAbsolute(file)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the file has a parent directory that starts with only a single
|
||||
// underscore, it's deemed a "helper".
|
||||
return path.dirname(file).split('/').some(dir => /^_(?:$|[^_])/.test(dir));
|
||||
}
|
||||
|
||||
exports.isHelperish = isHelperish;
|
||||
|
||||
function classify(file, {cwd, extensions, filePatterns, ignoredByWatcherPatterns}) {
|
||||
file = normalizeFileForMatching(cwd, file);
|
||||
return {
|
||||
isIgnoredByWatcher: matchesIgnorePatterns(file, ignoredByWatcherPatterns),
|
||||
isTest: hasExtension(extensions, file) && !isHelperish(file) && filePatterns.length > 0 && matches(file, filePatterns)
|
||||
};
|
||||
}
|
||||
|
||||
exports.classify = classify;
|
||||
|
||||
function applyTestFileFilter({cwd, filter, testFiles}) {
|
||||
return testFiles.filter(file => matches(normalizeFileForMatching(cwd, file), filter));
|
||||
}
|
||||
|
||||
exports.applyTestFileFilter = applyTestFileFilter;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue