I have a jest command that looks like this:
npx jest index.test --testMatch "**/test/*.cjs"
This looks in the ./test directory for test files matching the extension .cjs.
The above command works as expected.
However, I'm having an issue when trying to alias this command via NPM using package.json variables.
Here's the file:
// package.json
...
"config": {
"testmatch": "--testMatch \"**/test/*.cjs\""
},
"scripts": {
"test1": "npx jest index.test $npm_package_config_testmatch",
"test2": "npx jest index.test --testMatch \"**/test/*.cjs\""
}
...
For npm run test1 I get the following result:
No tests found, exiting with code 1
...
For npm run test2 I get the desired result, i.e. Jest runs all the tests and outputs the result.
The two are essentially the same commands, but test1 doesn't work.
When I used the --debug flag for Jest (for both commands) I noticed that Jest appears to be receiving two different values for testMatch:
// npm run test1
...
"testMatch": [
"\"**/test/*.cjs\""
],
...
// npm run test2
...
"testMatch": [
"**/test/*.cjs"
],
...
This would explain why the npm run test1 fails: the pattern is malformed.
Is there some way to deal with the quote character " when using them inside NPM package variables?
Related
I know there are some threads about a similar topic but tried various suggested solutions and neither worked.
The problem:
When running the jest tests written in TS on docker as part of a Jenkins pipeline, I got: Cannot find module '../../../common/src/SomeType' from 'dist/src/services/foo.services.js', where foo.services.js is what being tested.
This is my project structure; don't know why it was initially structured like this. I joint the party way too late.
MyProject123
client
package.json
tsconfig.json
...
common
tsconfig.json
src
SomeType.ts (NOTE: this is what can't be found by jest!)
Others.ts
server
dist
src
foo.services.ts (NOTE: this is what being tested)
tests
unit
services
foo.services.spec.ts (NOTE: this is the test!)
tsconfig.json
jest.conf.js
Inside foo.services.ts, it references SomeType as:
import { SomeType } from '../../../common/src/SomeType';
Inside server/tsconfig.json, it set the references in order to reference the common folder:
"references": [
{
"path": "../common"
}
],
"include": [
"src/**/*.ts",
"*.ts",
"src/**/*.json",
"tests/**/*.ts"
],
In jest.conf.js under server folder, it has:
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1'
},`
Inside server/package.json, it has:
"jest": {
"testEnvironment": "node",
"rootDir": "./",
"modulePaths": [
"<rootDir>"
]
},
What's odd is all tests work fine locally on my machine. But it doesn't work when running in docker.
Guess I am missing some jest config setting somewhere?
----------------------------EDIT 1 ---------------------------
Here is our dockerfile that is relevant for the part:
FROM company.com/nodejs:16
ARG BUILD_MODE
USER root
ARG http_proxy=******
ARG https_proxy=$http_proxy
ARG no_proxy=******
ARG CI=true
ARG NPM_CONFIG__AUTH
WORKDIR /app
COPY . .
RUN npm cache clean --force
RUN npm install npm -g
WORKDIR /app/server
COPY server/package.json .
COPY server/package-lock.json .
COPY server/.npmrc .
RUN npm ci --loglevel verbose
RUN npm run build-ts
RUN rm -rf tests/coverage
RUN npm run test:unit //NOTE: runs the server unit tests
From the error you have
Cannot find module '../../../common/src/SomeType' from 'dist/src/services/foo.services.js'
looks like you are running Jest on your bundle files. (from dist/...)
As a reminder, Jest runs on source files, not on bundled files.
A quick fix, would be to run your test suite before bundling your App in your dockerfile :
# ...
RUN npm run test:unit
RUN npm run build-ts
I have the following scripts in the package.json:
"scripts": {
"test" : "npm run module1 || npm run posttest",
"createenv": "node cliTest.js && npm run test"
}
cliTest.js has the following:
console.log(process.argv);
I need to run createenv first to create an env file that will be used by the script 'test'. The problem is that the arguments in the CLI are not made available.
So, if I run the following:
npm run createenv foobar
I get the following and I do not see 'foobar'
[
'/Users/xxxxx/.nvm/versions/node/v16.13.2/bin/node',
'/Users/xxxxx/Documents/core/cliTest.js'
]
How can I retrieve the value foobar from the CLI in my cliTest.js file?
If you really need this &&-chain you can try npm_config_, something like this:
"createenv": "node cliTest.js ${npm_config_name} && npm run test"
then run the command:
npm run createenv --name=foobar
the last argument in console.log should be foobar.
I have created below simple Dockerfile:
FROM node:16.7.0
WORKDIR /app
COPY . .
RUN npm install
# ENTRYPOINT [ "npm" ]
CMD ["sh", "-c", "tail -f /dev/null"]
I have added a cmd line with "tail -f /dev/null" to check exactly what's the issue if I issue npm test inside the container.
As soon as I run npm test inside the container --> It throws me below error
# npm test
> docker-jest#1.0.0 test
> jest --verbose
sh: 1: jest: not found
my package.json
{
"name": "docker-jest",
"version": "1.0.0",
"description": "Package for Jest",
"scripts": {
"test": "jest --verbose"
},
"Dependencies": {
"#babel/node": "*",
"#babel/core": "*",
"#babel/preset-env": "*",
"babel-jest": "*",
"jest": "*"
},
"license": "ISC"
}
sum.js
function sum(a, b) {
return a + b;
}
module.exports = sum;
sum.test.js
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
Even if I disable CMD and enable ENTRYPOINT and after the build, if I issue:
docker run -it <imagename> test
It throws me the same error, I see the npm install is installing but can't find the jest # /usr/local/lib/node_modules/ as I see the node modules are deployed in location/usr/local/lib/node_modules/ inside the container, and if I issue jest it says jest not found. If I, run the same without the container it works fine. I mean just in the command line after running npm install and then npm run test.
Can anyone assist me with why I'm getting this error and how to fix it?
-----------UPDATE-------------
Found the fix, it was because of my corrupted package-lock file. When I tested in local without the docker, I somehow corrupted the lock file, and later stage when I build and try to run using docker, the corrupted lock file was causing a whole lot of issues. So I deleted it and again ran thru docker...It's working as expected.
I had the same issue and the fix for me was running npm install -g jest (or yarn global add jest).
To add this to your package.json do the following:
"scripts: {
"test": "npm install -g jest && jest --verbose"
},
Is there a way to pass command line arguments to an npm 'pre' script or to a script which runs multiple commands?
Assuming a simple script mySexyScript.js that just logs out the process.argv :
console.log(process.argv);
This works
With an npm script:
...
"scripts": {
....
"sexyscript": "node mySexyScript.js"
....
}
...
running:
npm run sexyscript -- --foo=bar
the arguments are logged to the console as expected.
'pre' script - This doesn't work
With an npm script:
...
"scripts": {
....
"presexyscript": "node mySexyScript.js"
"sexyscript": "node mySuperSexyScript.js"
....
}
...
running:
npm run sexyscript -- --foo=bar
the arguments are not passed to mySexyScript and they are not logged
Multiple commands - This also doesn't work
With an npm script:
...
"scripts": {
....
"sexyscript": "node mySexyScript.js && node mySuperSexyScript.js"
....
}
...
running:
npm run sexyscript -- --foo=bar
the arguments are not passed to mySexyScript and they are not logged
There is no way to pass args in the way that you are describing.
Assuming a package.json:
...
"scripts": {
....
"somescript": "node one.js && node two.js"
....
}
...
Running:
npm run somescript -- --foo=bar
basically just runs
node one.js && node two.js --foo=bar
on the default system shell (usually bash or cmd.exe).
npm doesn't actually know anything about shell operators (i.e. &&), so it can't pass args to both scripts.
I have a production build with Webpack that uses node's process.env to set environment variables:
webpack.prod.babel.js:
const DefinePlugin = new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production'),
API_URL: JSON.stringify('https://myprodurl.com'),
},
});
packge.json:
"scripts: {
"build:prod": "webpack"
}
It's working fine, but I need something different.
I need to set the production url as variable in the NPM Script.
So, instead of this:
npm run build:prod
I need this:
npm run build:prod --URL https://myprodurl.com
How about defining your environment variable in the command line, like:
URL=https://myprodurl.com npm run build:prod
I tested this with a simple script and was able to print out the URL.
"scripts": {
"test": "./myTest.js"
},
myTest.js:
#!/usr/local/bin/node
'use strict'
console.log(process.env.URL);
console.log('Done!');
then:
$ URL=https://whatever.com npm run test
> my-test#1.0.0 test /Test/my-test
> ./myTest.js
https://whatever.com
Done!
EDIT: As mentioned by #RyanZim, see the following for Windows: https://github.com/kentcdodds/cross-env
(disclaimer: I don't use Windows and have never tried this lib)