Jest can't find .env.local for MONGO_URI - reactjs

I have a NextJS app using a MongoDB. I just added Jest for testing. When I run the first test I get the following error:
Please define the MONGODB_URI environment variable inside .env.local
4 |
5 | if (!MONGODB_URI) {
> 6 | throw new Error('Please define the MONGODB_URI environment variable inside .env.local');
| ^
7 | }
I do have a file .env.local that has a MONGODB_URI and it works when I run my app locally and and on prod.
This is the test:
import React from 'react';
import ReactDom from 'react-dom';
import Home from '../../pages/index';
import { configure, shallow } from 'enzyme';
import Adapter from '#wojtekmaj/enzyme-adapter-react-17';
configure({ adapter: new Adapter() });
describe('<Home />', () => {
it('should render Home', () => {
const wrapper = shallow(<Home />);
console.log('wrapper :', wrapper.debug());
});
});
My jest.config.js:
module.exports = {
clearMocks: true,
coverageDirectory: 'coverage',
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/__mocks__/fileMock.js',
'\\.(css|less)$': 'identity-obj-proxy'
},
preset: '#shelf/jest-mongodb'
};
What am I missing here?

The .env.local is not loaded in the test environment, as you expect tests to produce the same results for everyone.
But you can still use environment variables for tests.
1. Option
You can use a env.test file and add the following to a globalSetup.js file
...
import { loadEnvConfig } from '#next/env'
export default async () => {
const projectDir = process.cwd()
loadEnvConfig(projectDir)
}
...
Make sure to setup the globalSetup.js file in the jest.config.js file:
...
globalSetup: ['<rootDir>/test/globalSetup.js'] // path to file
...
When you run your tests there should be a log in the console:
Loaded env from C:\Users\XXX\XXX\XXX\nextjs\.env.test
More information here: Next.js Environment Variables Documentation
2. Option
You can use the dotenv package for the test env with the env.local file.
Add this in your jest-setup.js file:
import dotenv from 'dotenv'
dotenv.config({ path: '.env.local' })

in nextJS, I use .env.test for test environment.

you will have to pass setupFiles option in the jest.config.js
module.exports = {
setupFiles: ['env.local.config file'],
}
to use MONGODB_URI in the tests

Related

Why do i get this error, Cannot use import statement outside a module

so im trying to make a test for my component a simple test that shows if the component was rendered
test('Should render the movie info', () => {
renderWithContext(<MovieInfo movie={mockMovies[0]} />);
expect(screen.getByText('Terrifier 2')).toBeInTheDocument();
});
but i get this error:
SyntaxError: Cannot use import statement outside a module
the problem seems to have be about axios some how because it happens when trying to import axios.
> 2 | import axios from 'axios';
| ^
i have a jest.config.js file like this.
const { compilerOptions } = require('./tsconfig.json');
const { pathsToModuleNameMapper } = require('ts-jest');
const { default: tsjPreset } = require('ts-jest');
module.exports = {
transform: {
...tsjPreset.transform,
'+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2|pdf)$':
'jest-transform-stub',
'^.+\\.ts?$': 'ts-jest',
},
moduleDirectories: ['src', 'node_modules'],
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths),
setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts'],
transformIgnorePatterns: ['node_modules/(?!(axios)/)'],
};
and i have installed ts-jest, #types/jest and jest-transform-stub as dependencies
i have looked on the internet and this seems to be about some jest config that im doing wrong but nothing i do works
I solved this by adding this to my package.json i think its a hacky way of doing it but is the only way it worked for me.
"test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!axios)/\"",

How to fix ReferenceError: TextEncoder is not defined in jest test of Next.js project?

I have a unit test that is checking to see if a particular item is rendered on the page. This unit test fails and I get the following error:
Test suite failed to run
ReferenceError: TextEncoder is not defined
6 | import { unformatPhoneNumber } from '../../../utils/formatter';
7 | import ReactHtmlParser from 'react-html-parser';
> 8 | import DOMPurify from 'isomorphic-dompurify';
Based on the other stackoverflow questions on this subject, I added a jest.config.js file and a jest.setup.js file in the root of my project.
This is what I have in my jest.config.js, which I copied from the Next.js example repo here,
https://github.com/vercel/next.js/tree/canary/examples/with-jest-babel
// You can learn more about each option below in the Jest docs: https://jestjs.io/docs/configuration.
module.exports = {
collectCoverageFrom: ['**/*.{js,jsx,ts,tsx}', '!**/*.d.ts', '!**/node_modules/**'],
moduleNameMapper: {
// Handle CSS imports (with CSS modules)
// https://jestjs.io/docs/webpack#mocking-css-modules
'^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
// Handle CSS imports (without CSS modules)
'^.+\\.(css|sass|scss)$': '<rootDir>/__mocks__/styleMock.js',
// Handle image imports
// https://jestjs.io/docs/webpack#handling-static-assets
'^.+\\.(png|jpg|jpeg|gif|webp|avif|ico|bmp|svg)$': `<rootDir>/__mocks__/fileMock.js`,
// Handle module aliases
'^#/components/(.*)$': '<rootDir>/components/$1',
'^#/pages/(.*)$': '<rootDir>/pages/$1',
},
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/.next/'],
transform: {
// Use babel-jest to transpile tests with the next/babel preset
// https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object
'^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['next/babel'] }],
},
transformIgnorePatterns: ['/node_modules/', '^.+\\.module\\.(css|sass|scss)$'],
testEnvironment: 'jest-environment-jsdom',
};
This is what I have in the jest.setup.js,
// Optional: configure or set up a testing framework before each test.
// If you delete this file, remove `setupFilesAfterEnv` from `jest.config.js`
// Used for __tests__/testing-library.js
// Learn more: https://github.com/testing-library/jest-dom
import '#testing-library/jest-dom/extend-expect';
import { TextEncoder, TextDecoder } from 'util';
global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;
After adding this, I am still getting the same error. I am using node v16.18.0.
This is a Nextjs, Typescript, React app. I also have a jest-config.d.ts file with the following in it:
declare const root: any;
export { root as rootDir };
export declare const setupFilesAfterEnv: string['<rootDir>/jest.setup.js'];
export declare const testMatch: string[];
export declare const testPathIgnorePatterns: string[];
export declare const coveragePathIgnorePatterns: string[];
export declare const coverageDirectory: string;
//# sourceMappingURL=jest-config.d.ts.map
I don't know if I need to add anything into this file.

Configuring Jest and Enzyme for React app using create-react-app

I have built a sample React application using create-react-app (CRA), I am trying to write the unit testing for the application.
Using Jest and Enzyme, I have installed the required packages as the dev dependencies
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.15.1",
"jest": "^24.9.0"
jest.config.js - located outside of src folder
module.exports = {
verbose: true,
setupFilesAfterEnv: ["./src/setupTest.js"],
};
setupTest.js - located inside of src folder root
import { configure } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
configure({ adapter: new Adapter() });
App.test.js
import React from "react";
import { shallow } from "enzyme";
import App from "./App";
describe("<App />", () => {
it("Renders the app component", () => {
const wrapper = shallow(<App />);
expect(wrapper).toMatchSnapshot();
});
});
When I try to do npm run test, it's giving the below error:
Enzyme Internal Error: Enzyme expects an adapter to be configured, but found none.
To configure an adapter, you should call `Enzyme.configure({ adapter: new Adapter() })`
before using any of Enzyme's top level APIs, where `Adapter` is the adapter
corresponding to the library currently being tested. For example:
import Adapter from 'enzyme-adapter-react-15';
To find out more about this, see http://airbnb.io/enzyme/docs/installation/index.html
6 | describe("<App />", () => {
7 | it("Renders the app component", () => {
> 8 | const wrapper = shallow(<App />);
| ^
9 | expect(wrapper).toMatchSnapshot();
10 | });
11 | });
You must name your setupFilesAfterEnv file as src/setupTests.js or src/setupTests.ts. This cannot be configured using without ejecting from create-react-app.
Here is a functional setup file for CRA:
src/setupTests.js
(note that it's setupTests and not setupTest in the file name)
import { configure } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
configure({ adapter: new Adapter() });
More information
I think there is typo in your file name you forgot to add s at the end of file name (setupTests), the expected path for your setup file is src/setupTests.js.
You can go with this filename also but then you have to include it in the jest config like below.
// package.json
{
...,
"jest": {
"setupFilesAfterEnv": "<rootDir>/test-setup.js"
}
}
Hope this helps

jest test cannot import cesium using create react app and craco

I am using create react app with craco, and craco-cesium to load cesium into my project. I am trying to setup jest to start creating tests but the issue is Cesium is using requireJS.
I added the following to my package.json
// package.json
...
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}', '!src/**/*.d.ts"
],
"globalSetup": "<rootDir>/setupTests.js"
}
...
based on the ticket opened up here: https://github.com/facebook/jest/issues/1914
I setup the setupTests.js with the following code:
// setupTests.js
module.exports = async () => {
var cesium = require('cesium');
process.$Cesium = cesium
};
and I have the first basic test for valid rendering:
// App.test.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
however I get the error in one of my view inside <App /> component with the following code:
import Cesium from "cesium";
...
TypeError: Cannot read property 'Ion' of undefined
...
Cesium.Ion.defaultAccessToken = '...';
reporting Cesium as undefined when calling it's functions. I tried to use jest.config.js for jest to pick up the configuration from there with the following code:
// jest.config.js
const { createJestConfig } = require("#craco/craco");
const cracoConfig = require("../craco.config.js");
const jestConfig = createJestConfig(cracoConfig);
module.exports = jestConfig;
but create react app doesn't pick up this file so I cannot try this to verify if this would work.
encoutered the same problem.
Upgrading react-scripts to version 4.0.1 and #craco/craco# to version 6.0.0, seemed to solve these problems, and jest now recognizes all imports from cesium. No other configuration files were needed.

Enzyme expects an adapter to be configured

I created a new React application by create-react-app and I wanted to write a unit test to a component named "MessageBox" that I created in the application. This is the unit test that I wrote:
import MessageBox from "../MessageBox";
import { shallow } from 'enzyme';
import React from 'react';
test('message box', () => {
const app = {setState: jest.fn()};
const wrapper = shallow(<MessageBox app={app}/>);
wrapper.find('button').at(0).simulate('click');
expect(app.setState).toHaveBeenLastCalledWith({modalIsOpen: false});
});
I also added a file under 'src' folder named 'setupTests.js' with the content:
import * as enzyme from 'enzyme';
import * as Adapter from 'enzyme-adapter-react-16';
enzyme.configure({ adapter: new Adapter() });
I ran it by:
npm test
and I got the error:
Enzyme Internal Error: Enzyme expects an adapter to be configured, but
found none. To configure an adapter, you should call Enzyme.configure({ > adapter: new Adapter() })
Do you know what can solve this problem?
Add it to your test case file.
import React from 'react';
import Adapter from 'enzyme-adapter-react-16';
import { shallow, configure } from 'enzyme';
configure({adapter: new Adapter()});
test('message box', ()=> {
...
})
Also, if you don't want to import your setupTests.js file into every test file, you can place it in your package.json folder:
"jest": {
"setupTestFrameworkScriptFile": "./test/setupTests.js" }
Update:
Note: setupTestFrameworkScriptFile is deprecated in favor of setupFilesAfterEnv.
https://jestjs.io/docs/en/configuration
The file 'setupTests' has to be imported to the test file:
import MessageBox from "../MessageBox";
import { shallow } from 'enzyme';
import React from 'react';
import "../setupTests"
test('message box', ()=> {
...
})
As Priyank said, if you are using Create React App, it will pick up the configuration from src/setupTests.js.
Add:
import { configure } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
configure({ adapter: new Adapter() })
A lot of answers are saying import setupTests.js into your test file. Or
configure enzyme adapter in each test file. Which does solve the immediate problem.
But long term, if you add a jest.config.js file to the project root. You can configure it to run a setup file on launch.
jest.config.js
module.exports = {
setupTestFrameworkScriptFile: "<rootDir>/src/setupTests.ts"
}
This tells Jest to run setupTest.ts every time it's launched.
This way if you need to add polyfills or add global mock like localstorage, you can add it to your setupTests file and its configured everywhere.
The Enzyme docs don't cover integration with Jest, so it is confusing to fuse these two together.
For me when using React with create-react-app I had to make sure the file name was correct. The file has to be src/setupTests.js with an s at the end of Tests.
Inside setupTests.js is the following:
import { configure } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
configure({ adapter: new Adapter() });
When running npm run test it auto finds the setupTests.js file. There is no need to import it into each test file.
You need to use the import like this:
import Adapter from 'enzyme-adapter-react-16';
This way: (import * as Adapter from ...) returns a message "TypeError: Adapter is not a constructor."
Add import React from 'react'; to the top of your file.
You are using JSX syntax <MessageBox app={app}/>, which transpiles into React.createComponent(...). In order for this to work React variable must be defined in the scope of the file.
Try sth like this;
import React from 'react';
import App from './containers/App';
import enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
enzyme.configure({ adapter: new Adapter() });
describe('App Screen', () => {
let mountedAppScreen;
let props;
const appScreen = () => {
if (!mountedAppScreen) {
mountedAppScreen = enzyme.mount(
<App {...props} />
);
}
return mountedAppScreen;
}
it("it always renders div", () => {
const divs = appScreen().find("div");
expect(divs.length).toBeGreaterThanOrEqual(1);
});
});
Using the latest version of the libraries, I've faced the same error reported in every answer of this question. Error: TypeError: Adapter is not a constructor.
I've grouped all the necessary steps in order to proper test your ReactJS component using Enzyme (I've used Jest but it might work with Mocha as well, in that case, just switch the main test package):
1) Libraries (package.json):
"dependencies": {
"jest": "^24.6.0",
(...)
}
"devDependencies": {
"chai": "^4.2.0",
"enzyme": "^3.7.0",
"enzyme-adapter-react-16": "^1.7.0",
(...)
}
2) TEST SETUP: You can setup the Enzyme in every test. But as type_master_flash wisely suggested, you can add a script to do that. In order to do so, create a new setting in your package.json file at the same level of the sessions scripts, dependencies, etc:
Jest Version 23.x (or previous):
"devDependencies": {
(...)
},
"jest": {
"setupTestFrameworkScriptFile": "./tests.setup.js"
},
After Jest 24.0 version: According to Jest Documentation, "setupTestFrameworkScriptFile is deprecated in favor of setupFilesAfterEnv".
"devDependencies": {
(...)
},
"jest": {
"setupFilesAfterEnv": ["./tests.setup.js"]
},
This file can be anywhere you prefer and you can name it as you wish. Just remember to setup the proper file location. In the current example I've stored my file in the root of my project.
3) tests.setup.js: As I've discovered in Enzyme: TypeError: Adapter is not a constructor, the problem here is that we cannot "import '' a module with a default export". The proper way of configuring your file is:
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
Just that and you are good to test your components.
Cheers and hope this helps.
For everyone who read this in the future, setupTestFrameworkScriptFile is deprecated in favor of setupFilesAfterEnv by the documentation, in new versions. We can add our file like this:
"setupFiles": [
"<rootDir>/src/setupTests.js"
]
I faced the same error and for some reason React wasn't picking up setupTests.js file automatically.
I created a new file called jest.config.js at the root directory and added
{ "jest": { "setupTestFrameworkScriptFile": "<rootDir>/path/to/your/file.js", } }
After this, error disappeared.
Note: Later on, I removed the jest.config.js file but it still works now.
Not sure what was actually causing the problem though!
The file configuration must be in setupFilesAfterEnv property of jest.config.js
{
...
setupFilesAfterEnv: ["<rootDir>/jest.transform.js"],
...
}
If anyone comes across this while trying to fix this after setting up Testing React Components with Jest in GatsbyJs (https://www.gatsbyjs.org/docs/testing-react-components/)
In the setup-test-env.js you make, edit it to look like this:
import "#testing-library/jest-dom/extend-expect"
import { configure } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
configure({ adapter: new Adapter() })
Create a file named setupTests.js in the root of your project. jest will automatically look for this file before running any test suits. Add the following content to the file.
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({adapter:new Adapter()})
Note: the filename should be exactly the same.no need to import this setupTests.js file into your test files.it will work automatically
For those who use VS Code and the Jest Runner extension for a React CRA app, don't forget to configure Jest Runner to use CRA's built in script runner by setting the jest command to:
npm test -- --watchAll=false
You will get the error in topic if you forget to do that. And since you are using CRA you won't be able to configure setupFilesAfterEnv in package.json nor jest.config.js. Trying that will result in this error:
These options in your package.json Jest configuration are not currently supported by Create React App
npm i enzyme-adapter-react-16 enzyme-to-json --save-dev
Add to package.json
enter image description here
"jest": {
"collectCoverageFrom": [ "src/**/*.js", "!src/index.js" ]
};
Add two files to src folder ->
setupTests.js
tempPolyfills.js
setupTests.js :
import requestAnimationFrame from './tempPolyfills';
import { configure } from "enzyme";
import Adapter from 'enzyme-adapter-react-16';
configure({adapter: new Adapter(), disableLifecycleMethods:true});
tempPolyfills.js:
const requestAnimationFrame = global.requestAnimationFrame = callback => {
setTimeout(callback,0);
};
export default requestAnimationFrame;
in case shallow -> expect() fails in test case use toJson() :
Example :
import { shallow } from "enzyme";
import App from "./App";
import toJson from 'enzyme-to-json';
describe('App', () => {
const app = shallow(<App />);
it('renders correctly', () => {
expect(toJson(app)).toMatchSnapshot();
});
});
If you think you've otherwise setup everything correctly (e.g. have the #wojtekmaj/enzyme-adapter-react-17 for React 17 support installed), one more pitfall to check with Typescript:
Do you have
"esModuleInterop": true,
and the matching import format for the adapter?
import Adapter from '#wojtekmaj/enzyme-adapter-react-17';
import Enzyme from 'enzyme';

Resources