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
Related
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?
I'm currently trying to create a two stage build for an application that runs with Next.js (version 12.0.6) and has a custom server for an API. I do not want to rebuild the app each single time docker runs so I copy the compiled files into the /app directory. I'd assume that the pages directory would work automatically from .next folder but unfortunately it doesn't.
While the app builds all fine, I am plagued by this issue:
Error: > Couldn't find a `pages` directory. Please create one under the project root
at Object.findPagesDir (/app/node_modules/next/dist/lib/find-pages-dir.js:33:11)
at /app/node_modules/next/dist/build/index.js:113:45
at async Span.traceAsyncFn (/app/node_modules/next/dist/trace/trace.js:74:20)
at async Object.build [as default] (/app/node_modules/next/dist/build/index.js:82:25)
My Docker file looks like this:
FROM node:lts-slim AS base
WORKDIR /base
COPY package*.json ./
RUN npm install
COPY . .
FROM base AS build
ENV NODE_ENV=production
WORKDIR /build
COPY --from=base /base ./
CMD mkdir ./pages
RUN npm run build
FROM node:lts-slim AS production
ENV NODE_ENV=production
WORKDIR /app
COPY --from=build /build/next.config.js ./
COPY --from=build /build/package*.json ./
COPY --from=build /build/.next ./.next
COPY --from=build /build/public ./public
COPY --from=build /build/dist ./dist
# RUN mkdir pages; < uncommenting this will silence the error but it's an empty fake directory
RUN npm install
EXPOSE 3000
CMD npm run start
I start the Next.js sever like this (also tried with hardcoded false for the dev property with no success):
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
And the npm commands in the project are as follows:
"scripts": {
"prestart": "next build",
"dev": "NODE_ENV=development ts-node --project tsconfig.server.json server/index.ts",
"next-dev": "next dev",
"build:server": "tsc --project tsconfig.server.json",
"build:next": "next build",
"build": "npm run build:next && npm run build:server",
"next-start": "next start",
"start": "NODE_ENV=production node ./dist/server/index.js",
"test": "jest"
},
Things I have tried so far:
Fiddling with the dir directory when creating the server. Unfortunately it seems to be correct by default pointing to the /app directly and changing it doesn't help
Fiddling with the distDir in next.config. Unfortunately the same result as above
Creating an empty pages folder in /app. This doesn't seem to work - pages are loaded from that folder and since there is nothing inside everything yields 404.
Copying the entire build into app. While this creates pages folder and works, it completely defeats the purpose of a multi-stage build.
Copying only pages folder. This fails miserably as it has dependencies on all of the other folders.
Could anyone please direct me on how to tackle this? I simply ran out of ideas and hopefully I'm missing something silly here.
Thanks!
Answering this myself as I got it to "work" and it might help someone else.
For a reason which seems to be beyond my understanding, creating a separate run script in package.json stopped Next.js to recompile itself whenever the app starts.
To reiterate on the steps taken:
Using npm start caused the entire solution to recompile.
Creating a new run line in package.json (I called it npm run go) prevents this from happens. Server spins up perfectly from the compiled js files and runs immediatelly.
It works but I have no idea why. If anyone has any insight I'm more than happy to hear it!
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"
},
I want to store all new and previous reports in my directory.
Current behavior
Right now after running tests by 'npm run test' previous reports are deleted or appended (when i delete line clean reports in package.json).
Desired behavior
I want to give my directory path a dynamic name e.g with current date or number so previous ones stays where they are but i don't know if it is possible to do it inside cypres.json. Is there any solution workaround?
Code
package.json
"scripts": {
"clean:reports": rmdir /S /Q cypress\reports && mkdir cypress\reports && mkdircypress\reports\mochareports",
"pretest": "npm run archive-report && npm run clean:reports",
"scripts": "cypress run --browser chrome",
"combine-reports": "mochawesome-merge ./cypress/reports/chrome/mocha/*.json > cypress/reports/chrome/mochareports/report.json",
"generate-report": "marge cypress/reports/chrome/mochareports/report.json -f report -o cypress/reports/chrome/mochareports",
"posttest-chrome": "npm run combine-reports && npm run generate-report",
"test-chrome": "npm run scripts || npm run posttest-chrome"
cypress.json
"reporter": "cypress-multi-reporters",
"reporterOptions": {
"reporterEnabled": "mochawesome",
"mochaFile": "raports/my-test-output-.xml",
"mochawesomeReporterOptions": {
"reportDir": "cypress/reports/mocha",
"quite": true,
"overwrite": false,
"html": false,
"json": true
}
}
simillar: ReportDir of a mochawesome reporter option in cypress.json to point to folder created at run time named after timestamp
A workaround:
If you start the tests in some CI, then once npm run test command is finished you can add additional steps to do this for you, for bash it would be something like:
dirName="$(date +"%d-%m-%Y-%H:%M:%S")"
mkdir $dirName
mv cypress/screenshots/*.json $dirName
More details regarding the dirName here.
I have a ReactJS application and I'm deploying it using Kubernetes.
I'm trying to wrap my head around how to inject environment variables into my config.js file from within the Kubernetes deployment file.
I currently have these:
config.js file:
export const CLIENT_API_ENDPOINT = {
default:process.env.URL_TO_SERVICE,
};
and here's my Kubernetes deployment variables:
"spec": {
"containers": [
{
"name": "container_name",
"image": "image_name",
"env": [
{
"name": "URL_TO_SERVICE",
"value": "https://www.myurl.com"
}
]
Kinda clueless of why I can't see the environment variable in my config.js file. Any help would be highly appreciated.
Here's my dockerfile:
# Dockerfile (tag: v3)
FROM node:9.3.0
RUN npm install webpack -g
WORKDIR /tmp
COPY package.json /tmp/
RUN npm config set registry http://registry.npmjs.org/ && npm install
WORKDIR /usr/src/app
COPY . /usr/src/app/
RUN cp -a /tmp/node_modules /usr/src/app/
#RUN webpack
ENV NODE_ENV=production
ENV PORT=4000
#CMD [ "/usr/local/bin/node", "./index.js" ]
ENTRYPOINT npm start
EXPOSE 4000
The kubernetes environment variables are available in your container. So you would think the task here is a version of getting server side configuration variables shipped to your client side code.
But, If your react application is running in a container, you are most likely running your javascript build pipeline when you build the docker image. Something like this:
RUN npm run build
# Run app using nodemon
CMD [ "npm", "start" ]
When docker is building your container, the environment variables injected by kubernetes aren't yet yet available. They won't exist until you run the built container on a cluster.
One solution, and this is maybe your shortest path, is to stop building your client side code in the docker file and combine the build and run steps in npm start command . Something like this if you are using webpack:
"start": "webpack -p --progress --config webpack.production.config.js && node index.js"
If you go this route, then you can use any of the well documented techniques for shipping server side environment variables to your client during the build step : Passing environment-dependent variables in webpack. There are similar techniques and tools for all other javascript build tools.
Two: If you are running node, you can continue building your client app in the container, but have the node app write a config.js to the file system on the startup of the node application.
You could do even more complicated things like exposing your config via an api (a variation on the second approach), but this seems like throwing good money after bad.
I wonder if there isn't an easier way. If you have a purely client side app, why not just deploy it as a static site to, say, an amazon or gcloud bucket, firebase, or netlify? This way you just run the build process and deploy to the correct environment. no container needed.