Jest configuration - javascript

I'm adding Jest Testing framework to my React Native project. I'm getting the following error:
Failed to get mock metadata: /Users/me/Documents/Development/project/node_modules/global/window.js
My test file looks like this:
import 'react-native'
import React from 'react'
import { MyComponent } from '../components/MyComponent'
import renderer from 'react-test-renderer'
it('renders correctly', () => {
const tree = renderer.create(<MyComponent />).toJSON()
expect(tree).toMatchSnapshot()
})
And also the Jest configuration in my package.json:
"jest": {
"preset": "jest-react-native",
"testPathIgnorePatterns": ["/node_modules/", "/example/", "/lib/"],
"testRegex": "(/tests/.*|\\.(test|spec))\\.(js|jsx)$",
"automock": "true",
"unmockedModulePathPatterns": [ "lodash" ],
"transformIgnorePatterns": [
"node_modules/(?!#exponent/ex-navigation",
")"
]
}
I had a look over http://facebook.github.io/jest/docs/manual-mocks.html#content as suggested on the error prompted.

I think something is wrong with your jest configuration in package.json.
Here is a sample jest config snippet:
"jest": {
"preset": "react-native",
"cacheDirectory": "./cache",
"coveragePathIgnorePatterns": [
"./app/utils/vendor"
],
"coverageThreshold": {
"global": {
"statements": 80
}
},
"transformIgnorePatterns": [
"/node_modules/(?!react-native|react-clone-referenced-element|react-navigation)"
]
}
preset: The preset is a node environment that mimics the environment of a React Native app. Because it doesn’t load any DOM or browser APIs, it greatly improves Jest’s startup time.
cacheDirectory: It helps you greatly improve the test speed. It does so by creating cache of compiled modules so that next time it doesn’t have to compile the node_modules while running tests.
coveragePathIgnorePatterns: Define the files which want to skip for coverage reports.
coverageThreshold: Defines the threshold limit for all the tests to pass. If the coverage is less than the defined limit, the tests would fail. This helped us to keep a good amount of coverage at all point of time.
transformIgnorePatterns: We pass all the NPM modules here which needs to be transpiled. These modules are basically ES6/7 modules.
PS: I have written a blog on how to setup jest for react-native project. Here is the URL : http://rahulgaba.com/react-native/2017/05/19/Jest-test-suite-with-superpowers.html

Set "automock": "false" in your package.json (automocking with the jest-react-native preset isn't supported)

Related

Compiling React projects in MonoRepo failing

I'm trying to setup yarn workspaces with my docker instance. This is my directory structure:
/monorepo/
/node_modules/
#libs/common
#services/common
#services/project-A
...OTHER DEPS...
package.json
/services/
/common/
index.jsx
package.json
/project-A/
webpack.base.config.js
**REACT project with babel, webpack, etc**
/libs/
/tools/
/common/
index.jsx
package.json
To simplify my docker setup I just configured this volume within my docker compose that maps the entire monorepo directory:
volumes:
- '../../../monorepo:/monorepo'
From there in my Project-A I import #libs/common and #services/common. This works fine when the common libraries are exporting simple functions like:
export const Add = (a,b) => a+b
Webpack has no issue resolving this and building Project-A.
However when I try to import a component from one of the common libraries like this:
/libs/tools/common:
import React from 'react'
export MySharedComponent = () => <>HELLLO</>
I get an error in the build process:
Error: Cannot find module '/monorepo/libs/tools/common/webpack.base.config.js'
Require stack:
- /monorepo/node_modules/eslint-import-resolver-webpack/index.js
- /monorepo/node_modules/eslint-module-utils/resolve.js
- /monorepo/node_modules/eslint-plugin-import/lib/rules/no-unresolved.js
- /monorepo/node_modules/eslint-plugin-import/lib/index.js
The eslint file under Project-A:
{
"parser": "babel-eslint",
"env": {
"browser": true,
"node": true,
"jest": true,
"cypress/globals": true
},
"settings": {
"import/resolver": {
"webpack": {
"config": "webpack.base.config.js"
}
}
}
}
The babel.rc under Project-A
{
"presets": [
[
"#babel/preset-env",
{
"targets": {
"node": "current"
}
}
],
"#babel/preset-react",
"#babel/preset-flow"
],
"env": {
"test": {
"plugins": [
[
"babel-plugin-webpack-alias",
{
"config": "./webpack.base.config.js"
}
]
]
}
}
}
My Question:
Is the main issue that there's no webpack config set up in the common repositories. Therefore the workspace does not know how to compile my shared resources?
Should there only be 1 webpack build config in my workspace used by all projects within the workspace? Currently I only have 1 config under Project-A?
What happens if I have specific webpack needs per project, does 1 config (if that's the answer) make sense?
1) First, there is a line in your code that you are referring to webpack.base.config.js in both babelrc and eslint,
so if that file does not exist, this error that says module not found makes sense.
2) Second: if you build and use your repositories in the same situation and environment, yes you can have one config for both but you might need environment setup (Development, Production) for your config.
But if you really want to make your dependencies and configs apart, webpack support multiple entries for your project which you can check that out.

Get rid of "regeneratorRuntime is not defined" without importing the polyfill

I wrote a library of elements, and want to make sure designers can just add the right source file to their HTML pages to start using it.
I am creating a bundle using rollup (to roll it up to one file) and babel (to make sure any browser can use it).
My rollup.conf is pretty simple:
import resolve from 'rollup-plugin-node-resolve'
import babel from 'rollup-plugin-babel'
import minify from 'rollup-plugin-babel-minify'
module.exports = [
// IIFE
{
input: './tpe.js',
output: {
file: 'distr/tpe.js', // IIFE ONE FILE
format: 'iife'
},
plugins: [resolve({}), babel({})]
},
{
input: './themes/material/material.js',
output: {
file: 'distr/material.js', // IIFE ONE FILE
format: 'iife'
},
plugins: [resolve({}), minify({})]
}
]
Note that ./tpe.js contains a long list of imports:
import './ee-autocomplete-input-spans.js'
import './ee-autocomplete-item-country.js'
import './ee-autocomplete-item-email.js'
import './ee-autocomplete-item-li.js'
import './ee-autocomplete.js'
import './ee-drawer.js'
import './ee-fab.js'
import './ee-header.js'
import './ee-nav-bar.js'
import './ee-network.js'
import './ee-snack-bar.js'
import './ee-tabs.js'
...
My babel.conf.js is even simpler:
module.exports = function (api) {
api.cache(true)
const presets = [
[
'#babel/env', {
modules: false,
exclude: [],
targets: {
ie: "9"
}
}
]
]
const plugins = []
return {
presets,
plugins
}
This is all fine, except that I have to ask my users to do this:
<script src="https://unpkg.com/#babel/polyfill/dist/polyfill.min.js"></script>
<script src="./distr/material.js"></script>
<script src="./distr/tpe.js"></script>
<nn-input-text id="input" name="aName"></nn-input-text>
Without that polyfill.min.js, I get the dreaded regeneratorRuntime is not defined.
I spent hours, and hours, and hours trying to make sure that I don't need to ask users to have that polyfill.min.js.
To "fix" the problem, I added this to my ./tpe.js:
import 'regenerator-runtime/runtime'
import './ee-autocomplete-input-spans.js'
import './ee-autocomplete-item-country.js'
import './ee-autocomplete-item-email.js'
import './ee-autocomplete-item-li.js'
This actually allows me to have just this:
<script src="./distr/material.js"></script>
<script src="./distr/tpe.js"></script>
<nn-input-text id="input" name="aName"></nn-input-text>
QUESTIONS:
Babel is compiling things in node_modules, which in my case is exactly lit-html and lit-element (both ES6 source). I had problems at the beginning where lit-element (in node_modules) didn't compile. However, the problem disappeared and I don't know how/why.
Is regenerator-runtime/runtime the ONLY thing I will ever need to polyfill? I am targeting IE9 after all...
Is there a better way to add regenerator-runtime/runtime without having it in the includes in tpe.js?
I read about "corejs" being important is it provides more polyfills. However, adding this
useBuiltIns: "usage",
corejs: 3
Results in a lot of warnings. And then if I add an exclude in rollup.conf.js like this:
plugins: [resolve({}), babel({exclude: [/\/core-js\//]}), minify({})]
Things compile, but the result doesn't work (Uncaught SyntaxError: Cannot use import statement outside a module).
If I instead do:
useBuiltIns: "entry",
corejs: 3
I don't need the "exclude", but it doesn't seem to do anything.
Do I actually need the corejs polyfills?
I saw the Github issue you opened and linked to this post.
I have also been trying to diagnose this setup and the problems I've run into trying to configure it.
Checkout this recommended config on the rollup-plugin-babel repo.
I was running into the same issue with regeneratorRuntime is not defined and couldn't figure out why the polyfills weren't being loaded as I hoped/expected.
The key seems to be that 3 plugins are required for this use-case.
// We need all 3 of these to end up with the 'usage'-based babel polyfills
import babel from "rollup-plugin-babel";
import commonjs from "rollup-plugin-commonjs";
import resolve from "rollup-plugin-node-resolve";
export default [
{
input: "src/index.js",
output: {
file: "dist/index.js",
format: "iife"
},
plugins: [
resolve(),
babel({
exclude: "node_modules/**",
presets: [
[
"#babel/preset-env",
{
corejs: 3,
modules: false,
useBuiltIns: "usage",
targets: {
ie: "11"
}
}
]
]
}),
commonjs()
]
}
];
Here's my dependenices from package.json:
"scripts": {
"start": "rollup -c --compact --watch"
}
"dependencies": {
"core-js": "^3.3.4",
"regenerator-runtime": "^0.13.3"
},
"devDependencies": {
"#babel/core": "^7.6.4",
"#babel/preset-env": "^7.6.3",
"rollup": "^1.26.0",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
}
My output dist/index.js ends up including this assignment for regeneratorRuntime, which wasn't there before I had all 3 of the above rollup plugins:
try {
regeneratorRuntime = runtime;
} catch (accidentalStrictMode) {
// This module should not be running in strict mode, so the above
// assignment should always work unless something is misconfigured. Just
// in case runtime.js accidentally runs in strict mode, we can escape
// strict mode using a global Function call. This could conceivably fail
// if a Content Security Policy forbids using Function, but in that case
// the proper solution is to fix the accidental strict mode problem. If
// you've misconfigured your bundler to force strict mode and applied a
// CSP to forbid Function, and you're not willing to fix either of those
// problems, please detail your unique predicament in a GitHub issue.
Function("r", "regeneratorRuntime = r")(runtime);
}

CSS module #import fails the Jest test suit

I am using Jest and Enzyme to test my application. I am getting error:
FAIL app/containers/Navbar/NavbarContainer.test.js
● Test suite failed to run
app/components/Navbar/styles.css: Unexpected token (1:0)
> 1 | #import "../../styles/base/_variables";
| ^
2 |
3 | .navbar{
4 | width: $navbar-width;
This is my Jest configuration in package.json:
"jest": {
"verbose": true,
"globals": {
"env": {
"isProd": false,
"isDev": true,
"command": "start"
}
},
"moduleNameMapper": {
"\\.(css)$": "identity-obj-proxy"
},
"moduleFileExtensions": [
"js",
"jsx",
"json",
"css"
],
"modulePaths": [
"/app"
],
"moduleDirectories": [
"node_modules"
],
"verbose": true,
"setupFiles": [
"./setupJest.js"
],
"setupTestFrameworkScriptFile": "<rootDir>/setupTests.js"
}
I was following the guides while setting up the application, and I found that identity-obj-proxy will help to mock css-modules functionality, but that's not working in my case. Please let me know what am I missing here.
P.S. this is about not ES6 modules import. The suit failed because there is a #import in css.
UPDATE who use create-react-app from feb 2018.
You cannot override the moduleNameMapper in package.json but in jest.config.js it works, unfortunately i havent found any docs about why it does the trick.
So my jest.config.js look like this:
module.exports = {
...,
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(scss|sass|css)$": "identity-obj-proxy"
}
}
and it skips scss files and #import quite well.
I added to devDependencies identity-obj-proxy
Backing my answer i followed jest webpack
So, I've found the solution to this problem. I was importing CSS without the extension in my components and Jest was confusing that import with JS file. Solution is instead of importing css like:
import * as styles from './styles'
you should import it like:
import * as styles from './styles.css'
One quick gotcha that I found with this. If you have a jest.config.js file, then you need to set your moduleNameWrapper inside of that config file.
I know this post is old but i solved this issue by adding jest-transform-css as a devDependency
npm i --save-dev jest-transform-css
and then adding the following inside jest.config.js
transform: {
'^.+\\.js$': 'babel-jest',
'.+\\.(css|styl|less|sass|scss)$': 'jest-transform-css'
}
you can refer to this github issue for more information

How to write unit test for loading handlebars template file in Jest?

In my reactjs project, I am using handlebars to generate source code from the template. These templates are saved in files. In order to load these files into javascript, I configured below configuration in webpack:
{
test: /\.handlebars|hbs$/,
loader:
'handlebars-loader?helperDirs[]=' +
path.join(__dirname, '../src/helpers/handlebars')
},
it works fine when I launch the production. But it doesn't work in my unit tests. I am using jest as unit test framework. I have seen some people suggest to use Handlebars.registerHelper. I know it works only for the template from string. How to solve the issue when I load the template from files?
I created a preprocessor that simply put the handlebars template into a module so when imported in javascript via an es6 import, it can be used.
// preprocessor.js
module.exports = {
process(src) {
return `
const Handlebars = require('handlebars');
module.exports = \`${src}\`;
`;
},
};
Then in my package.json...
// package.json
"jest": {
"collectCoverage": true,
"modulePaths": [
"./app",
"./node_modules"
],
"testPathIgnorePatterns": [
"/node_modules/",
"/app/bower_components/"
],
"moduleFileExtensions": [
"js",
"hbs"
],
"transform": {
"\\.js$": "babel-jest",
"\\.hbs$": "<rootDir>/app/scripts/preprocessor.js"
}
}
In a src file...
import Mn from 'backbone.marionette';
import template from './template.hbs';
const ToggleList = Mn.CompositeView.extend({
template,
});
export default ToggleList;
When loading handlebar templates while testing with Jest, I found that the jest-handlebars package solved my problem.
From the docs:
npm i jest-handlebars --save-dev
To enable the processor please add the following rule to the transform
object in your jest configuration:
"jest": {
// ...
transform: {
"\\.hbs$": "jest-handlebars",
}
// ...
}
Now all imported handlebars files will get compiled by the processor
and the render function is imported.

Ava doesn't know to import .jsx dependencies from source files used in tests

I have the following ava config in my package.json:
{
"ava": {
"require": [
"./tests/helpers/setup-browser-env.js",
"./tests/helpers/module-stubber.js",
"babel-register"
],
"babel": {
"presets": [
"es2015",
"stage-0",
"react"
]
},
"failFast": true,
"verbose": false,
"no-cache": false,
"concurrency": 5
}
}
and I have the following project structure:
src
index.jsx
components
input.jsx
tests
index.test.js
index.jsx
import Input from './components/input';
console.log(Input);
input.jsx
import react from 'react';
export default () => <input></input>;
input.test.js
import app from '../src';
// ...
The problem is that ava is able to transpile my src/index.jsx file but it doesn't transpile input.jsx and I am seing an empty object logged in my console. It only works if I import the component using the .jsx extension like so: import Input from './component/input.jsx. I can't make it to work without specifying the extension.
Is this possible in AVA? In Webpack it is a simple config which handles these kinds of patterns.
Looking in the ava docs under the configuration section: https://github.com/avajs/ava#configuration I can't see any field which can help me. (also the config fields don't seem to be really detailed).
Any ideas?
Thanks in advance.
babel-register is in charge of requiring input.jsx, not AVA. It's surprising that importing from ../src works, but importing input does not. I don't really have an answer for you though.

Categories

Resources