I'm learning to test React projects using RTL and Jest from one of the Udemy courses. The instructor provides a pure React project. In the video, the test is passing for the instructor but the same code is failing for me and Jest is throwing the error "SyntaxError: Cannot use import statement outside a module".
I researched on google and tried few solutions like transformIgnorePatterns: [/node_modules/(?!axios)
], adding "type": "module" in package.json, and mock axios using Jest but none of them worked for me.
package.json
{
"name": "codesplain",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:8000",
"dependencies": {
"@exuanbo/file-icons-js": "^3.3.0",
"@monaco-editor/react": "^4.4.6",
"@playwright/test": "^1.28.1",
"@primer/octicons-react": "^17.9.0",
"@prisma/client": "^4.7.0",
"@tailwindcss/forms": "^0.5.3",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.6.7",
"classnames": "^2.3.2",
"concurrently": "^7.6.0",
"cookie-session": "^2.0.0",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"msw": "^0.49.2",
"nodemon": "^3.0.3",
"playwright": "^1.28.1",
"prisma": "^4.7.0",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router": "^6.4.4",
"react-router-dom": "^6.4.4",
"react-scripts": "^5.0.1",
"react-split": "^2.0.14",
"swr": "^2.0.0",
"validate.js": "^0.13.1",
"web-vitals": "^2.1.4"
},
"prisma": {
"schema": "server/prisma/schema.prisma"
},
"scripts": {
"start": "concurrently \"npm:start:server\" \"npm:start:client\"",
"start:client": "react-scripts start",
"start:server": "nodemon --watch server server/index.mjs",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"autoprefixer": "^10.4.13",
"postcss": "^8.4.19",
"tailwindcss": "^3.2.4"
}
}
Test File With Mock Axios With Jest
import { render, screen } from "@testing-library/react";
import { setupServer } from "msw/node";
import { rest } from "msw";
import { MemoryRouter } from "react-router-dom";
import HomeRoute from "./HomeRoute";
import axios from "axios";
jest.mock("axios");
const mockedAxios = axios;
const handlers = [
mockedAxios.get("/api/repositories", (req, res, ctx) => {
const language = req.url.searchParams.get("q").split("language:")[1];
return res(
ctx.json({
items: [
{ id: 1, full_name: `${language}_one` },
{ id: 2, full_name: `${language}_two` },
],
})
);
}),
];
const server = setupServer(...handlers);
beforeAll(() => {
server.listen();
});
afterEach(() => {
server.resetHandlers();
});
afterAll(() => {
server.close();
});
test("renders two links for each language", async () => {
render(
<MemoryRouter>
<HomeRoute />
</MemoryRouter>
);
const languages = [
"javascript",
"typescript",
];
for (let language of languages) {
const links = await screen.findAllByRole("link", {
name: new RegExp(`${language}_`),
});
expect(links).toHaveLength(2);
}
});
Test File Without Mock As Per The Course Video
import { render, screen } from "@testing-library/react";
import { setupServer } from "msw/node";
import { rest } from "msw";
import { MemoryRouter } from "react-router-dom";
import HomeRoute from "./HomeRoute";
const handlers = [
rest.get("/api/repositories", (req, res, ctx) => {
const language = req.url.searchParams.get("q").split("language:")[1];
return res(
ctx.json({
items: [
{ id: 1, full_name: `${language}_one` },
{ id: 2, full_name: `${language}_two` },
],
})
);
}),
];
const server = setupServer(...handlers);
beforeAll(() => {
server.listen();
});
afterEach(() => {
server.resetHandlers();
});
afterAll(() => {
server.close();
});
test("renders two links for each language", async () => {
render(
<MemoryRouter>
<HomeRoute />
</MemoryRouter>
);
const languages = [
"javascript",
"typescript",
];
for (let language of languages) {
const links = await screen.findAllByRole("link", {
name: new RegExp(`${language}_`),
});
expect(links).toHaveLength(2);
}
});
Any suggestion on how to fix this error?
If you have a look in node_modules/axios you may check index.js file and see:
import axios from './lib/axios.js';
and this causes that issue, node would not recognize that import syntax.
Try to use that - https://github.com/axios/axios/issues/5101#issuecomment-1296024311. That will force jest to import version of axios which is compatible with node.js instead.
UPD: also have a look - https://stackoverflow.com/a/74297004/19742146
UPD: as you use Jest 27 version also have a look - https://jestjs.io/blog/2022/04/25/jest-28#packagejson-exports Jest 28 supports now exports field and probably it may solves your issue without any jest configs