Skip to content

Commit 9c28990

Browse files
committed
support leading dots in --extension
- update documentation for the feature and multipart extensions - rename integration test `file-utils.spec.js` to `lookup-files.spec.js` and "modernize" it Signed-off-by: Christopher Hiller <[email protected]>
1 parent 2852505 commit 9c28990

File tree

4 files changed

+290
-137
lines changed

4 files changed

+290
-137
lines changed

docs/index.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,11 @@ Files having this extension will be considered test files. Defaults to `js`.
984984

985985
Specifying `--extension` will _remove_ `.js` as a test file extension; use `--extension js` to re-add it. For example, to load `.mjs` and `.js` test files, you must supply `--extension mjs --extension js`.
986986

987-
The option can be given multiple times. The option accepts a comma-delimited list: `--extension a,b` is equivalent to `--extension a --extension b`
987+
The option can be given multiple times. The option accepts a comma-delimited list: `--extension a,b` is equivalent to `--extension a --extension b`.
988+
989+
> _New in v8.2.0._
990+
991+
`--extension` now supports multipart extensions (e.g., `spec.js`), leading dots (`.js`) and combinations thereof (`.spec.js`);
988992

989993
### `--file <file|directory|glob>`
990994

lib/cli/lookup-files.js

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
'use strict';
2-
32
/**
43
* Contains `lookupFiles`, which takes some globs/dirs/options and returns a list of files.
54
* @module
@@ -14,6 +13,7 @@ var errors = require('../errors');
1413
var createNoFilesMatchPatternError = errors.createNoFilesMatchPatternError;
1514
var createMissingArgumentError = errors.createMissingArgumentError;
1615
var {sQuote, dQuote} = require('../utils');
16+
const debug = require('debug')('mocha:cli:lookup-files');
1717

1818
/**
1919
* Determines if pathname would be a "hidden" file (or directory) on UN*X.
@@ -30,25 +30,26 @@ var {sQuote, dQuote} = require('../utils');
3030
* @example
3131
* isHiddenOnUnix('.profile'); // => true
3232
*/
33-
function isHiddenOnUnix(pathname) {
34-
return path.basename(pathname)[0] === '.';
35-
}
33+
const isHiddenOnUnix = pathname => path.basename(pathname).startsWith('.');
3634

3735
/**
3836
* Determines if pathname has a matching file extension.
3937
*
38+
* Supports multi-part extensions.
39+
*
4040
* @private
4141
* @param {string} pathname - Pathname to check for match.
42-
* @param {string[]} exts - List of file extensions (sans period).
43-
* @return {boolean} whether file extension matches.
42+
* @param {string[]} exts - List of file extensions, w/-or-w/o leading period
43+
* @return {boolean} `true` if file extension matches.
4444
* @example
45-
* hasMatchingExtname('foo.html', ['js', 'css']); // => false
45+
* hasMatchingExtname('foo.html', ['js', 'css']); // false
46+
* hasMatchingExtname('foo.js', ['.js']); // true
47+
* hasMatchingExtname('foo.js', ['js']); // ture
4648
*/
47-
function hasMatchingExtname(pathname, exts) {
48-
return exts.some(function(element) {
49-
return pathname.endsWith('.' + element);
50-
});
51-
}
49+
const hasMatchingExtname = (pathname, exts = []) =>
50+
exts
51+
.map(ext => (ext.startsWith('.') ? ext : `.${ext}`))
52+
.some(ext => pathname.endsWith(ext));
5253

5354
/**
5455
* Lookup file names at the given `path`.
@@ -66,27 +67,28 @@ function hasMatchingExtname(pathname, exts) {
6667
* @throws {Error} if no files match pattern.
6768
* @throws {TypeError} if `filepath` is directory and `extensions` not provided.
6869
*/
69-
module.exports = function lookupFiles(filepath, extensions, recursive) {
70-
extensions = extensions || [];
71-
recursive = recursive || false;
72-
var files = [];
73-
var stat;
70+
module.exports = function lookupFiles(
71+
filepath,
72+
extensions = [],
73+
recursive = false
74+
) {
75+
const files = [];
76+
let stat;
7477

7578
if (!fs.existsSync(filepath)) {
76-
var pattern;
79+
let pattern;
7780
if (glob.hasMagic(filepath)) {
7881
// Handle glob as is without extensions
7982
pattern = filepath;
8083
} else {
8184
// glob pattern e.g. 'filepath+(.js|.ts)'
82-
var strExtensions = extensions
83-
.map(function(v) {
84-
return '.' + v;
85-
})
85+
const strExtensions = extensions
86+
.map(ext => (ext.startsWith('.') ? ext : `.${ext}`))
8687
.join('|');
87-
pattern = filepath + '+(' + strExtensions + ')';
88+
pattern = `${filepath}+(${strExtensions})`;
89+
debug('looking for files using glob pattern: %s', pattern);
8890
}
89-
files = glob.sync(pattern, {nodir: true});
91+
files.push(...glob.sync(pattern, {nodir: true}));
9092
if (!files.length) {
9193
throw createNoFilesMatchPatternError(
9294
'Cannot find any files matching pattern ' + dQuote(filepath),
@@ -108,20 +110,19 @@ module.exports = function lookupFiles(filepath, extensions, recursive) {
108110
}
109111

110112
// Handle directory
111-
fs.readdirSync(filepath).forEach(function(dirent) {
112-
var pathname = path.join(filepath, dirent);
113-
var stat;
113+
fs.readdirSync(filepath).forEach(dirent => {
114+
const pathname = path.join(filepath, dirent);
115+
let stat;
114116

115117
try {
116118
stat = fs.statSync(pathname);
117119
if (stat.isDirectory()) {
118120
if (recursive) {
119-
files = files.concat(lookupFiles(pathname, extensions, recursive));
121+
files.push(...lookupFiles(pathname, extensions, recursive));
120122
}
121123
return;
122124
}
123-
} catch (err) {
124-
// ignore error
125+
} catch (ignored) {
125126
return;
126127
}
127128
if (!extensions.length) {

0 commit comments

Comments
 (0)