Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Glob pattern not working as expected #1828

Closed
cappslock opened this issue Aug 11, 2015 · 9 comments
Closed

Glob pattern not working as expected #1828

cappslock opened this issue Aug 11, 2015 · 9 comments

Comments

@cappslock
Copy link

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?

@cappslock
Copy link
Author

Note that I can get the desired behavior by modifying my test command thusly:

mocha ./test/*.js ./test/**/*.js

But this does seem incorrect.

@gergoerdosi
Copy link

Use single quotes:

"test": "mocha './test/**/*.js'"

@cappslock
Copy link
Author

Thanks, that worked well. Can you explain why this works? Is the shell trying to interpret this before it hits mocha or something?

@gergoerdosi
Copy link

Yes, if you don't use quotes, shell expands the glob pattern before it reaches Mocha.

@cappslock
Copy link
Author

Got it, thanks for clarifying.

ifrost pushed a commit to ifrost/sinon that referenced this issue Jun 13, 2018
mroderick pushed a commit to sinonjs/sinon that referenced this issue Jun 16, 2018
allouis added a commit to allouis/slimer that referenced this issue Oct 4, 2018
no-issue

This is because the shell will try to expand the glob if it's not
wrapped in strings, which can give different outcomes depending on the
globbing supporting by the shell. Passing a string will allow mocha to
sort out globbing which is more predictable.

Related issue is here: mochajs/mocha#1828
ErisDS pushed a commit to TryGhost/slimer that referenced this issue Oct 4, 2018
no-issue

This is because the shell will try to expand the glob if it's not
wrapped in strings, which can give different outcomes depending on the
globbing supporting by the shell. Passing a string will allow mocha to
sort out globbing which is more predictable.

Related issue is here: mochajs/mocha#1828
@taikulawo
Copy link

taikulawo commented Nov 25, 2018

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

@plroebuck
Copy link
Contributor

plroebuck commented Nov 26, 2018

@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.

Directory Structure

$ 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

Test

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:

@kshetline
Copy link

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?

undergroundwires added a commit to undergroundwires/privacy.sexy that referenced this issue May 3, 2021
Integration tests are executed using vue-cli-service with double quotes as following: `vue-cli-service test:unit "tests/integration/**/*.spec.ts"`. Using single quotes (mochajs/mocha#1828) works on macOS and Ubuntu but does not on Windows (tests are not found). Double quotes is the only portable way that works on all three platforms (mochajs/mocha#3136).
@yuyaryshev
Copy link

yuyaryshev commented Nov 5, 2022

Note for ones who still have this problem in 2022 or later.
Add doublequotes to your npm script's glob!

Incorrect, won't work:

  "scripts": {
    "test": "mocha ./test/**/*.js"
  }

Correct:

  "scripts": {
    "test": "mocha \"./test/**/*.js\""
  }

LarrMarburger pushed a commit to LarrMarburger/privacy.sexy that referenced this issue Nov 16, 2023
Integration tests are executed using vue-cli-service with double quotes as following: `vue-cli-service test:unit "tests/integration/**/*.spec.ts"`. Using single quotes (mochajs/mocha#1828) works on macOS and Ubuntu but does not on Windows (tests are not found). Double quotes is the only portable way that works on all three platforms (mochajs/mocha#3136).
github-merge-queue bot pushed a commit to proofcarryingdata/zupass that referenced this issue Apr 3, 2024
`passport-server` tests are only matching a single test file, instead of
all files in `test` and its subdirectories. This means that the majority
(227 of 231) tests for `passport-server` are not being run in CI.

Fix is the same as described here:
mochajs/mocha#1828 - because the pattern is
unquoted, it gets expanded by the shell rather than passed through, and
the shell pattern expansion algorithm is different/inferior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants