¡Hola! En este tutorial te mostraré cómo usar React con Vite y Jest. Usaremos pnpm como gestor de paquetes. Para empezar, asumiré que ya has creado un proyecto básico de React con Vite y que has instalado todas las dependencias necesarias.
pnpm create vite
Para este ejemplo usaremos React + typescript
Para este tutorial me "guie" 🤣 por este otro está en inglés, la razón por la que quise contribuir con una nueva versión es que ya ha habido algunos cambios en Jest por lo que todo lo que encuentren allí no funcionará 100%. Aunque allí está mejor explicado todo por alguien si sabe lo que hace ❤️.
Paso 1: Instalar Jest
Primero, debes instalar Jest como una dependencia de desarrollo en tu proyecto. Para hacer esto, abre una terminal en la raíz de tu proyecto y ejecuta el siguiente comando:
pnpm install --save-dev jest @types/jest jest-environment-jsdom jest-watch-typeahead @testing-library/dom @testing-library/jest-dom @testing-library/react @testing-library/user-event @swc/jest @types/testing-library__jest-dom
Paso 2: Configurar Jest
Ahora, necesitas configurar Jest en tu proyecto. Crea un archivo llamado jest.config.cjs
en la raíz de tu proyecto y pega el siguiente código:
module.exports = {
roots: ["<rootDir>/src"],
collectCoverageFrom: [
"src/**/*.{js,jsx,ts,tsx}",
"!src/**/*.d.ts",
"!src/mocks/**",
],
coveragePathIgnorePatterns: [],
setupFilesAfterEnv: ["./config/jest/setupTests.js"],
testEnvironment: "jsdom",
modulePaths: ["<rootDir>/src"],
transform: {
"^.+\\.(ts|js|tsx|jsx)$": "@swc/jest",
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
"^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)":
"<rootDir>/config/jest/fileTransform.js",
},
transformIgnorePatterns: [
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$",
"^.+\\.module\\.(css|sass|scss)$",
],
moduleNameMapper: {
"^react-native$": "react-native-web",
"^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy",
"^.+\\.(svg)$": "<rootDir>/src/__mocks__/fileMock.js",
},
moduleFileExtensions: [
// Place tsx and ts to beginning as suggestion from Jest team
// https://jestjs.io/docs/configuration#modulefileextensions-arraystring
"tsx",
"ts",
"web.js",
"js",
"web.ts",
"web.tsx",
"json",
"web.jsx",
"jsx",
"node",
],
watchPlugins: [
"jest-watch-typeahead/filename",
"jest-watch-typeahead/testname",
],
resetMocks: true,
};
Paso 3: Archivos adicionales
Crea un archivo en /src/__tests__/App.test.tsx
con el siguiente contenido:
import { render, screen } from "@testing-library/react";
import App from "../App";
describe("App", () => {
it("should work as expected", () => {
render(<App />);
expect(1 + 1).toBe(2);
});
});
Crea un archivo en /src/__mocks__/fileMock.js
con el siguiente contenido:
module.exports = "";
Esto es necesario porque Jest no puede entender cómo manejar las importaciones de archivos que no son de JS (en este caso, archivos SVG), por lo que el módulo fileTransform.js intercepta estas importaciones y devuelve el nombre de archivo del recurso. Sin esta transformación, Jest no sería capaz de ejecutar el conjunto de pruebas, ya que fallaría al resolver las importaciones de archivos que no son de JS.
Crea en la raíz del proyecto las siguientes carpetas /config/jest
con los siguientes archivos: cssTransform.js, fileTransform.js, setupTests.js
//cssTransform.js
"use strict";
module.exports = {
process(src, filename, config, options) {
return {
code: "module.exports = {};",
};
},
getCacheKey() {
return "cssTransform";
},
};
//fileTransform.js
"use strict";
const path = require("path");
const camelcase = require("camelcase");
module.exports = {
process(src, filename) {
const assetFilename = JSON.stringify(path.basename(filename));
if (filename.match(/\.svg$/)) {
// Based on how SVGR generates a component name:
// https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6
const pascalCaseFilename = camelcase(path.parse(filename).name, {
pascalCase: true,
});
const componentName = `Svg${pascalCaseFilename}`;
const svgComponentCode = `const React = require('react');
module.exports = {
__esModule: true,
default: ${assetFilename},
ReactComponent: React.forwardRef(function ${componentName}(props, ref) {
return {
$$typeof: Symbol.for('react.element'),
type: 'svg',
ref: ref,
key: null,
props: Object.assign({}, props, {
children: ${assetFilename}
})
};
}),
};`;
return { code: svgComponentCode };
}
const fileModuleCode = `module.exports = ${assetFilename};`;
return { code: fileModuleCode };
},
};
//setupTests.js
import "@testing-library/jest-dom/extend-expect";
window.matchMedia = (query) => ({
matches: false,
media: query,
onchange: null,
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
addListener: jest.fn(),
removeListener: jest.fn(),
});
Object.defineProperty(URL, "createObjectURL", {
writable: true,
value: jest.fn(),
});
Crea en la raíz del proyecto un archivo llamado .swcrc
con lo siguiente:
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"tsx": true,
"decorators": false,
"dynamicImport": false
},
"transform": {
"react": {
"pragma": "React.createElement",
"pragmaFrag": "React.Fragment",
"throwIfNamespace": true,
"development": false,
"useBuiltins": false,
"runtime": "automatic"
},
"hidden": {
"jest": true
}
}
},
"module": {
"type": "commonjs",
"strict": false,
"strictMode": true,
"lazy": false,
"noInterop": false
}
}
swcrc
es un archivo de configuración para el compilador de JavaScript swc
. swc
es un compilador de JavaScript/TypeScript extremadamente rápido que se utiliza para transpilar y optimizar el código fuente de una aplicación.
Paso 4: Edita package.json
"type": "commonjs",
"scripts": {
//...
"test": "jest"
},
Eso sería todo, nótese que tuve que cambiar module
por commonjs
aun así la app corre normalmente.
Por último, si desean contribuir para mejorar o mantener esta guia actualizada, pueden hacerlo desde aquí.
Top comments (5)
hey tienes repetido modulePaths en el fichero jest.config.cjs
Ya esta corregido, gracias por avisar 👍️
gracias a ti por compatir 🤗
excelente guia, para agregar tambien el dato que si tienen alias no le funcionará a la primera, deberan hacer modificaciones en el config de jest
quedando por ejemplo asi
moduleNameMapper: {
..,
'^@/(.*)': '/src/$1',
},
mi alias en tsconfig
"paths": {
"@/": ["./src/"]
}
hola amigo ami me sale el error de
Cannot find module '@testing-library/jest-dom/extend-expect' from 'config/jest/setupTests.js'
ya le busque instalando de diferentes manetras pero no funciona