I'm using mocha on a node project. I'd like to run all js files in a test directory and its subdirectories. I've added this block to my package.json:
"scripts": {
"test": "mocha ./test/**/*.js"
}
This glob pattern ONLY matches files in subdirectories of tests; it does not match top level files. This is confusing to me because the pattern as run through the glob module does indeed match as desired. Am I missing something obvious here or is this a bug?
Note that I can get the desired behavior by modifying my test command thusly:
mocha ./test/*.js ./test/**/*.js
But this does seem incorrect.
Use single quotes:
"test": "mocha './test/**/*.js'"
Thanks, that worked well. Can you explain why this works? Is the shell trying to interpret this before it hits mocha or something?
Yes, if you don't use quotes, shell expands the glob pattern before it reaches Mocha.
Got it, thanks for clarifying.
if you use follow
"test": "cross-env mode=test mocha --require ts-node/register --recursive \"test/{*,!(testdata)/**}.ts\"",
this will exclude testdata folder
But
If you use
"test": "cross-env mode=test mocha --require ts-node/register --recursive 'test/{*,!(testdata)/**}.ts'",
it will throw exception
wish it's will help others
I'm using Windows 10
@iamwwc,
The --recursive argument is _completely_ unnecessary if you use an extended glob ('').
If you single quote your glob, Mocha will handle it using the glob and minimatch npm modules.
If you double quote your glob, your shell _may_ handle it (depending on its support for extended globbing and having the applicable options enabled). Be aware that your shell and the glob npm package _may interpret the same extended glob pattern differently_. The portable solution is to let Mocha handle extended globs itself **without any _help_ from your shell.
Since you're using Windows, its shell doesn't handle extended globs anyway, and the choice of single vs. double quotes _should_ be meaningless.
To easily exclude Typescript files within the "testdata" directory (and its subdirectories), try:
C:\> mocha --require ts-node/register --exclude 'test/testdata/**' 'test/**/*.ts'
If needed, the --exclude argument can be given multiple times.
$ cd /tmp
$ mkdir test
$ touch test/setup.ts
$ mkdir test/subdir1
$ touch test/subdir1/file1.ts
$ mkdir test/subdir2
$ touch test/subdir2/file2a.ts
$ touch test/subdir2/file2b.ts
$ mkdir test/testdata
$ touch test/testdata/tdfile.ts
$ mkdir test/testdata/subdir3
$ touch test/testdata/subdir3/file3.ts
$ find test -type f -print
test/setup.ts
test/subdir1/file1.ts
test/subdir2/file2a.ts
test/subdir2/file2b.ts
test/testdata/subdir3/file3.ts
test/testdata/tdfile.ts
I patched _mocha here to add the following line so you could see what gets loaded.
console.log('files:', files);
I left the Typescript registration out here as these are empty files anyway.
$ mocha --exclude 'test/testdata/**' 'test/**/*.ts'
files: [ 'test/setup.ts',
'test/subdir1/file1.ts',
'test/subdir2/file2a.ts',
'test/subdir2/file2b.ts' ]
If you use
"test": "cross-env mode=test mocha --require ts-node/register --recursive 'test/{*,!(testdata)/**}.ts'",it will throw exception
You don't mention _what_ exception you get (nor your directory structure)...
References:
I'm trying to get --experimental-loader working along with mocha, and having no luck. Until I started trying to compile ES6 modules, I used to be able to run mocha tests this way:
"test": "nyc --reporter=html mocha --require ts-node/register src/**/*.spec.ts"
That doesn't work anymore when generating ES6 modules.
I'd use the TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' solution for testing, but that won't work for me because of another complication: I'm generating ES6 modules as a first step in my build, but also generating ES5/CommonJS modules using webpack and babel. That last step doesn't work unless I add .js to the end of my local TypeScript import statements.
But adding those .js extensions turns out to break the TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' solution, which will work, however, if I go back and delete all of the .js extensions. I obviously don't want a test and build process where I have to keep going back and forth between adding and removing those extensions.
To simplify for now, I've taken out nyc, and I'm trying things like this:
mocha -r ts-node/register --experimental-loader ./ts-loader.mjs src/**/*.spec.ts
I get no errors this way, but nothing happens either. It's like the src/**/*.spec.ts doesn't exist.
My do-nothing (for now) dummy loader looks like this:
console.log('ts-loader loaded');
export async function resolve(specifier, context, defaultResolve) {
console.log('resolve');
return defaultResolve(specifier, context, defaultResolve);
}
export async function getFormat(url, context, defaultGetFormat) {
console.log('getFormat');
return defaultGetFormat(url, context, defaultGetFormat);
}
export async function getSource(url, context, defaultGetSource) {
console.log('getSource');
return defaultGetSource(url, context, defaultGetSource);
}
export async function transformSource(source, context, defaultTransformSource) {
console.log('transformSource');
return defaultTransformSource(source, context, defaultTransformSource);
}
export function getGlobalPreloadCode() {
console.log('getGlobalPreloadCode');
return '';
}
I can tell it gets loaded because the 'ts-loader loaded' message appears, but none of the functions ever get called.
I've tried other permutations, but just get errors like src/**/*.spec.ts being treated as a literal file name instead of a glob, or errors about modules not being found.
I was hoping to see my loader invoked for every import being handled, and then figuring out how to manipulate the file extensions, but I haven't managed to get that far yet. Any suggestions?
Most helpful comment
Use single quotes: