Can't target test directory with jest testMatch glob pattern - node.js

Let's say that I have a project structure like below:
src/index.js
src/test/foo.js
test/integration/src/index.test.js
test/unit/src/index.test.js
jest.config.json
In jest.config.json I have my testMatch
{
"testMatch": [
"test/**"
]
}
When I run jest with --config jest.config.json it matches with 0 file.
testMatch: test/** - 0 matches
testPathIgnorePatterns: /node_modules/ - 5 matches
testRegex: - 0 matches
Pattern: - 0 matches
I thought it might be related with some incorrect rootDir since testMatch is relative to that. I run jest in debug mode to see my root and it seems it's correct. It shows my project directory. (where jest.config.json exists)
When I change my testMatch to **/test/** it can detect my tests in test/ directory but that's not what I want because then it also matches with src/test/ directory.
Why it cannot detect my tests in test/ directory? Is my glob pattern incorrect?

Why it cannot detect my tests in test/ directory? Is my glob pattern incorrect?
Jest's glob implementation has been going through some issues as of late. Under the hood Jest uses micromatch, but why it is getting hung up on relative path globs is unclear.
There are a couple things you can try in your Jest config:
Include the <rootDir> string token directly in your testMatch glob like testMatch: ['<rootDir>/test/**'].
Follow the globstar example more closely from the Jest testMatch documentation, paying attention to the note about glob order:
Note: Each glob pattern is applied in the order they are specified in the config. (For example ["!/fixtures/", "/tests//.js"] will not exclude fixtures because the negation is overwritten with the second pattern. In order to make the negated glob work in this example it has to come after /tests//.js.)
testMatch: [
'**/test/**',
'!**/src/**'
]

Related

`transformIgnorePatterns` not working to include some node_modules

I have the following config for Jest, which I was expecting to transform modules foo and bar inside node_modules, but ignore the rest:
{
"transformIgnorePatterns": [
"node_modules/(?!(foo)/)",
"node_modules/(?!(bar)/)"
]
}
But it seems like neither are being transformed. Why?
The answer lies hidden in the documentation (emphasis mine):
If the file path matches any of the patterns, it will not be transformed.
The regex above creates a combination where any folder under node_modules will either match in the first pattern or the second pattern. Here's a visualization of the regex:
If the goal is to not match against certain libraries in node_modules, this combination of regex patterns make that impossible.
The solution is to combine them into a single statement:
{
"transformIgnorePatterns": [
"node_modules/(?!(foo|bar)/)"
]
}

Jest regex to match certain test files

I have integration tests under dir src/test/integration. All files are named like so: foo.integration.js.
Running Jest:
jest ".*\\.integration\\.js"
produces this error:
No tests found, exiting with code 1
Run with `--passWithNoTests` to exit with code 0
In /Users/dangruszczyk/workspace/cef/lambda-workflow
7 files checked.
testMatch: **/__tests__/**/*.[jt]s?(x), **/?(*.)+(spec|test).[tj]s?(x) - 1 match
testPathIgnorePatterns: /node_modules/ - 7 matches
testRegex: - 0 matches
Pattern: .*\.integration\.js - 0 matches
Surely this regex should match src/test/integration/foo.integration.js (https://regex101.com/r/T3WJwd/1/). Any clue why it does not?
The problem is that Jest is still applying the testMatch, i.e. you're filtering within the files it has already determined to be test files, and src/test/integration/foo.integration.js matches neither **/__tests__/**/*.[jt]s?(x) nor **/?(*.)+(spec|test).[tj]s?(x)*.
To run those files, you're probably best off setting the testMatch instead:
jest --testMatch='**/*.integration.js'
This doesn't seem to be a documented part of the CLI, but works fine (for now!) in practice.
* Interestingly, neither does path/to/my-test.js, the example shown in the docs...
I was doing the same thing, but in the end it felt more natural to restructure.
By using .test.js you can easily run all tests or selectively filter sub-types.
example.integration.test.js
example.unit.test.js
"scripts": {
"test-all": "jest",
"unit-test": "jest \"--testPathPattern='.+\\.unit\\.test\\.js$'\"",
"integration-test": "jest \"--testPathPattern='.+\\.integration\\.test\\.js$'\""
},
As others have said, jest expects test files to end .test.js or .spec.js.

Jest "Cannot find module" with typescript paths in CI

On the Gitlab-CI environment 2 of our Jest tests fail with Cannot find module.
The strange thing is that it works on my local Win10 machine - even when I run the tests in a similar docker-container (node 12.12.0).
Here is the console output:
FAIL apps/server/src/domain/dashboard/permission-group.service.spec.ts
Test suite failed to run
Cannot find module '#cm/utils-server' from 'license.service.ts'
9 | isLicenseFileContent,
10 | LicenseStatus,
> 11 | parseLicenseInfo
| ^
12 | } from '#cm/license-shared';
13 | import { ExitCode } from '../../util/exit-codes';
14 | import { readFile } from '#cm/utils-server';
at Resolver.resolveModule (../../node_modules/jest-resolve/build/index.js:259:17)
at Object.<anonymous> (src/domain/license/license.service.ts:11:24)
I am not sure how to correctly interpret this output:
permission-group.service.spec.ts: this is the test that fails
Cannot find module '#cm/utils-server' from 'license.service.ts':
Ok, the test or some of its dependencies, use license.service.ts and in the license.service.ts file the '#cm/utils-server' module cannot be found.
What is the meaning of error-indicator (> at parseLicenseInfo)?
This is for the import #cm/license-shared - not for #cm/utils-server as indicated by the error message in 2
#cm/utils-server is also imported, but 2 lines below in line 14: So is this maybe just a bug in jest?
I just had this issue and searched for some solutions. Found this site which gave a clue about what could be done: to configure Jest's moduleNameMapper property.
So, reading the documentation I found this solution:
Open the tsconfig.json and jest.config.js files (or equivalent)
In tsconfig.json, find your absolute paths definition. My configuration looks like this:
"paths": {
"#modules/*": ["modules/*"],
"#config/*": ["config/*"],
"#shared/*": ["shared/*"]
}
In the jest.config.json, find and uncomment the moduleNameMapper property and start to translate your TS absolute paths into the Jest mapper syntax. Sounds complicated, but it isn't:
moduleNameMapper: {
"#modules/(.*)": "<rootDir>/src/modules/$1",
"#config/(.*)": "<rootDir>/src/config/$1",
"#shared/(.*)": "<rootDir>/src/shared/$1",
}
The <rootDir> if defined automatically, and points to the package.json directory
"#modules/(.*)" is a Regex for "any string starting with '#module/' followed by anything after it
"<rootDir>/src/modules/$1" is the corresponding directory. $1 is a pointer to the Regex expression between the parenthesis ((.*)). Other expressions will be pointed by $2, $3 and so on
After doing this, I was able to execute my tests without any problem.
Console output before follow the above steps:
$ jest
FAIL src/modules/appointments/services/CreateAppointmentService.spec.ts
● Test suite failed to run
Cannot find module '...'
Console output after:
$ jest
PASS src/modules/appointments/services/CreateAppointmentService.spec.ts
Hope this help someone,
Thanks!
For those who are facing this issue in 2022. Please add this code in your
jest-unit.json (or your jest config json file).
"moduleDirectories": ["<rootDir>/../", "node_modules"]
Result:
{
"moduleFileExtensions": ["js", "json", "ts"],
"rootDir": ".",
"testEnvironment": "node",
"testRegex": ".\\.spec.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"moduleDirectories": ["<rootDir>/../", "node_modules"]
}
For now we use a workaround: we had paths defined in multiple tsconfig.json files of our mono-repo. We moved all paths up to the root-tsconfig and now the tests work again.
But we don't really understand why this works.
And a drawback is that it's now easy to accidentally refer to a path that you shouldn't use in the lib (because the IDE now always uses all paths for code-assistance)
I meet the same problem, I found the reason is the package(which cannot found) doesn't set the main field in package.json, add it then everythings ok.

Husky/lint-staged is it possible to exclude/ignore file?

Is it possible to exclude/ignore a file when using Husky/lint-staged hooks?
Looking through the docs atm but not having any luck finding anything on this.
Was hoping there was something like an
/*ignore*/
tag that I could add.
To make lint-staged ignore certain files that were causing formatting issues.
Any thought on this greatly appreciated :)
Ended up adding
.prettierignore
file.
Not ideal but seems to do the job ok.
I finally found out how to do this (at least as of lint-staged v11.1.2)
In package.json:
"lint-staged": {
"!(path/to/excluded/dir/**/*)*.ts": [
"eslint --fix",
"prettier --write"
]
}
Note the globstar pattern is within the negation pattern and not outside it. This ensures that subdirectories are also excluded.
While configuring lint-staged in package.json or If you're using any other IDE, in order to ignore/exclude files by lint-Staged and husky hooks, you can add an "ignore" key in the lint-staged object to make it ignore whatever packages or files you want to ignore. Use the following extensible syntax:
{
"lint-staged": {
"linters": {
"src/**/*.js": ["formatter --write", "git add"],
},
"ignore": ["node_modules", "dist", "package-lock.json"] }
}
Just add the target pattern to 'linters' object and all the ignored files which you might be adding previously to .prettierignore to "ignore" key of lint-Staged object. And there you go!
If anyone still looking, take a look at this https://github.com/okonet/lint-staged#filtering-files It has good examples.
Filtering files
Linter commands work on a subset of all staged files, defined by a glob pattern. `lint-staged´ uses micromatch for matching files with the following rules:
If the glob pattern contains no slashes (/), micromatch's matchBase option will enabled, so globs match a file's basename regardless of directory:
"*.js" will match all JS files, like /test.js and /foo/bar/test.js
"!(*test).js". will match all JS files, except those ending in test.js, so foo.js but not foo.test.js
If the glob pattern does contain a slash (/), it will match for paths as well:
"./*.js" will match all JS files in the git repo root, so /test.js but not /foo/bar/test.js
"foo/**/\*.js" will match all JS files inside the/foodirectory, so/foo/bar/test.jsbut not/test.js
So I've been trying to find an answer for this for an entire day and looking at all the forums suggested that they use minimatch for glob check which might have been correct for older versions but they use micromatch for new version and to solve this issue we can use their pattern to exclude certain directories
So in your .lintstagedrc you can add the following pattern to avoid certain folders
{
"*.{json,md,html,scss}": ["prettier --write", "git add"],
["**/!(folder1|folder2)/*.ts"]: ["tslint --project tsconfig.json -c tslint.commit.json --fix", "prettier --write", "git add"]
}
So the glob here is an actual array and make sure not to pass this array within a string else it won't recognize the patterns also do not include **/*.ts the reason being lint-staged automatically converts this into a matchBase comparision if it finds / in the pattern so including this will also match against your folder1|folder2 files.
can fix in three ways:
.lintstagedrc.js
.prettierignore
lint-staged.config.js
more info : https://github.com/okonet/lint-staged/issues/797

ESLint ignore specific rule for a specific directory

Is it possible with ESLint to ignore one specific rule for an entire directory?
In my case, I would like to ignore import/prefer-default-export for a directory named commonComponents
ESLint configuration (.eslintrc) files are hierarchical:
ESLint will automatically look for them in the directory of the file to be linted, and in successive parent directories all the way up to the root directory of the filesystem. This option is useful when you want different configurations for different parts of a project or when you want others to be able to use ESLint directly without needing to remember to pass in the configuration file.
You can disable the import/prefer-default-export rule for the commonComponents directory by creating a .eslintrc file with the following content in that directory:
{
"rules": {
"import/prefer-default-export": "off"
}
}
You can also use the "overrides" key to declare rules for different glob patterns.
Have a read of Configuration Based on Glob Patterns
Sometimes a more fine-controlled configuration is necessary, for example if the configuration for files within the same directory has to be different. Therefore you can provide configurations under the overrides key that will only apply to files that match specific glob patterns, using the same format you would pass on the command line (e.g., app/**/*.test.js).
I use this to remove the no-unused-expressions rule from my test files like so;
"overrides": [{
"files": [ "*.spec.js" ],
"rules": {
"no-unused-expressions": 0
}
}]
If there are multiple directories that you want to apply your rules to, then you can create different configs for different purposes. For example:
.eslintrc.json for common config
.eslintrc-main.json for main linting and run eslint -c .eslintrc-main src test
.eslintrc-comp.json for components and run eslint -c .eslintrc-comp commonComponents fooBarComponent
YAML version :
rules:
no-unused-expressions: true
overrides:
- files: *-tests.js
rules:
no-unused-expressions: false
cretae .eslintignore file and put inside it your exluded folders. example :
node_modules/
functions/
dist/

Resources