I am trying to test a basic react component with Jest but am getting an error when importing the component into my test. It works fine outside of my tests.
The error is:
Invariant Violation: _registerComponent(...): Target container is not a DOM element.
App.js
const App = () => (
<h1>Hello World</h1>
)
app.test.js
import React from 'react'
import App from '../app'
test('App renders', () => {
...
}
Add the following to your config.js or package.json :
{
"env": {
"development": {
"plugins": ["transform-es2015-modules-commonjs"]
},
"test": {
"plugins": ["transform-es2015-modules-commonjs", "#babel/plugin-proposal-class-properties"],
"presets": [
"#babel/preset-react"
]
}
}
}
Related
I am currently testing a Vue project with Jest that uses Vuex and Vuetify in it. When testing something on any component, it gives me a bunch of errors of this nature:
console.error node_modules/vue/dist/vue.runtime.common.dev.js:621
[Vue warn]: Error in created hook: "TypeError: Cannot read property 'dispatch' of undefined"
found in
---> <DashboardSlots>
<StatusDashboard>
<Root>
console.error node_modules/vue/dist/vue.runtime.common.dev.js:1884
TypeError: Cannot read property 'dispatch' of undefined
at VueComponent.mappedAction (D:\Users\ftg\git\DVBIP_GATEWAY_9\usr\nonius\webadmin\node_modules\vuex\dist\vuex.common.js:1052:34)
at VueComponent.created (D:\Users\ftg\git\DVBIP_GATEWAY_9\usr\nonius\webadmin\src\components\DashboardSlots.vue:197:1)
console.error node_modules/vue/dist/vue.runtime.common.dev.js:621
[Vue warn]: Unknown custom element: <v-card> - did you register the component correctly? For recursive components, make
sure to provide the "name" option.
found in
---> <DashboardSlots>
<StatusDashboard>
<Root>
And much more of these! I dont know why this is happening.
This is my jest.config.js file:
module.exports = {
verbose: true,
roots: ["<rootDir>/src/", "<rootDir>/test/"],
moduleFileExtensions: ['js', 'vue'],
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1',
},
transform: {
"^.+\\.js$": "babel-jest",
"^.+\\.vue$": "vue-jest",
},
snapshotSerializers: [
"<rootDir>/node_modules/jest-serializer-vue"
]
}
This is my babel.config.js file:
module.exports = {
presets: [
[
'#babel/preset-env',
{
targets: {
node: 'current',
},
},
],
],
};
And this is my simple test (just printing something):
import Component from '#/components/StatusDashboard.vue';
import { mount , createLocalVue } from '#vue/test-utils'
import Vuex from 'vuex'
import Vuetify from 'vuetify';
import Actions from '#/vuex/actions.js'
const localVue = createLocalVue();
localVue.use(Vuex);
localVue.use(Vuetify, {});
localVue.use(Vuex)
describe('Component test', () => {
it('check test', () => {
const wrapper = mount(Component)
const test = wrapper.vm.items
console.log(test);
})
})
Tried uninstalling node modules and reinstalling but did not solve it.
You've setup localVue, but you haven't passed it into mount() as an option.
It should be:
mount(Component, { localVue })
//or
shallowMount(Component, { localVue })
I want to try Server Side Render in React, but my code doesn't work.
I should be missing something. But I don't know what it is as I'm new to react.
Here's the code as well:
server/app.js
import express from 'express';
import { renderToString } from 'react-dom/server';
import Home from '../src/index.js';
const app = express();
const content = renderToString(<Home />);
app.get('/', function (req, res) {
res.send(
`
<html>
<head>
<title>ssr</title>
</head>
<body>
<div id="root">${content}</div>
</body>
</html>
`
);
})
app.listen(3001, () => {
console.log('listen:3001')
})
src/index.js
import React from 'react';
const Home = () => {
return (
<div>
<div>Hello World</div>
</div>
)
}
export default Home
package.json
{
"scripts": {
"start": "nodemon --exec babel-node server/app.js"
}
}
.babelrc
{
"presets": [
"env"
],
"plugins": []
}
You can not render react page from nodejs like ejs because react is not like any template. it is a library.But if you actually want it, then you need server side rendering. (SSR)
const content = renderToString(<Home />);
you are using jsx here but not transpiling jsx into js. you need to install
npm i #babel/preset-react
also instead of "babel-preset-env" use this
npm i #babel/preset-env
then
{
"presets": ["#babel/preset-react", ""#babel/preset-env]
}
I'm trying to install Vue Typer in my Nuxt js app but no luck. I keep getting "document not defined". I tried importing it in my nuxt.config.js as a plugin but it doesn't work.
I got it working in my VueCLI 3, seems to work fine with this method.
Appreciate it!
Getting
NuxtServerError render function or template not defined in component: anonymous
////plugins///
import Vue from vue;
if (process.client) {
const VueTyper = require('vue-typer');
Vue.use(VueTyper);
}
///nuxt.config.js///
plugins: [
{src: '~/plugins/vue-typer.js', ssr: false}
],
<template>
<vue-typer text='Hello World! I was registered locally!'></vue-typer>
</template>
<script>
const VueTyper = processs.client ? require('vue-typer'): '';
export default {
components: {
VueTyper
}
}
</script>
To fix this, create a file called vueTyper.client.js under plugin folder then type this;
import Vue from 'vue';
import { VueTyper } from 'vue-typer';
Vue.component('vue-typer', VueTyper);
then in your nuxt.config.js add this to your plugin
plugins: [
{src: '~/plugins/vueTyper.client.js', mode: 'client',}
]
after doing this you can easily use it anywhere in your application without error:
<vue-typer text='Hello World! I was registered locally!'></vue-typer>
The path to my styled objects is correct, however not sure why I'm getting the following error:
Cannot find module '../../shared/models' from 'Astronaut.tsx'
import { moonHoldings } from '../../shared/models';
My simple Jest test:
import React from 'react';
import { shallow } from 'enzyme';
import toJson from 'enzyme-to-json';
// #ts-ignore (works with .tsx)
import Astronaut from '../Astronaut.tsx';
describe('<Astronaut /> component', () => {
describe('should render', () => {
const wrapper = shallow(<Astronaut showLogo={true} />);
it ('should render a component matching the snapshot', () => {
const tree = toJson(wrapper);
expect(tree).toMatchSnapshot();
expect(wrapper).toHaveLength(1);
});
});
});
The Astronaut component
import React from 'react';
import { moonHoldings } from '../../shared/models'; // <-- The problem
import { astronaut } from '../../styles'; // <-- This works
const { AstronautContainer, Heading } = astronaut;
interface LogoCheck {
showLogo: boolean;
}
export default (showLogo: LogoCheck) => (
<AstronautContainer>
{ showLogo.showLogo === true ? <Heading>{moonHoldings}</Heading> : null }
<img src="static/astronaut.png" alt="astronaut" />
</AstronautContainer>
);
The Jest config section of my Package.json
"jest": {
"setupTestFrameworkScriptFile": "<rootDir>/jest.setup.js",
"testPathIgnorePatterns": [
"<rootDir>/.next/",
"<rootDir>/node_modules/"
],
"transform": {
"\\.(gql|graphql)$": "jest-transform-graphql",
".*": "babel-jest",
"^.+\\.js?$": "babel-jest"
},
"moduleFileExtensions": [
"js",
"json",
"ts",
"tsx"
],
"modulePaths": [
"<rootDir>/components/",
"<rootDir>/pages/",
"<rootDir>/shared/"
]
}
And my folder structure:
You need to do little configuration for your jest test.
Adding this snippet to your package.json should allow you to take your custom name and map it to your actual folder:
"moduleNameMapper": {
"^#fooBar/(.*)": "<rootDir>/src/barFoo/$1"
},
Ok I just fixed this by created an index file inside of the /shared folder and then exporting out the models that way (Though it should have still worked without the index file):
import { moonHoldings } from '../../shared';
And the index.js:
export { moonHoldings, nomicsLink } from './copy';
In my case, I got this error in a lot of instances inside my test file and the solution was to use file paths based mapping in the moduleNameMapper option inside my jest.config file. This helps us to map our absolute paths with their corresponding relative ones.
For example, if you are getting this error -
● Test suite failed to run
Cannot find module 'jsroot/io' from 'src/some-file.ts'
Adding this should work -
moduleNameMapper: {
// 'absolute-path': 'relative-path'
'jsroot/io': '<rootDir>/node_modules/jsroot/',
},
where <rootDir> is the root of the directory containing your Jest config file or the package.json.
I'm trying to figure out how to test an "onPress" event with Jest in a React-Native app so I can make sure the right function is called.
I went through the documentation and Google but couldn't find a solution for it in React-Native.
This is what I found that is supposed to work for React-Native with enzyme:
const mockFunc = jest.fn();
const component = mount(<MyComponent onPress={mockFunc} />);
component.simulate('press');
expect(mockFunc).toHaveBeenCalled();
But this doesn't work. Seems like mount doesn't work and I get this output:
ReferenceError: document is not defined
I tried with shallow instead but the TouchableOpacity is not getting rendered when I look at the output of the function... and you've guessed it, it doesn't work either. Not sure what to do.
Does anyone found a way to test events on React-Native?
Thanks
Enzyme does not support React-Native, because it's rendered differently and doesn't use the DOM. That's why you're getting the error ReferenceError: document is not defined. You can see this issue for more information. The React team is currently working to expose a .find() method in react-test-renderer to simulate actions on components. Then it should work for both React/React-native without needing a DOM environment.
There's a hack you can do (and that's what we did in our company) that is rendering a custom component that extends TouchableOpacity and map onClick to call onPress. Something like this:
const mockPressable = (name) => {
const RealComponent = require.requireActual(name);
class Component extends RealComponent {
render() {
return React.createElement(
RealComponent.displayName || RealComponent.name,
{ ...this.props, onClick: this.props.onPress },
this.props.children
);
}
}
return Component;
};
jest.mock('TouchableOpacity', () => mockPressable('TouchableOpacity'));
And in your test code, you call component.simulate('click').
It's a hack and I'm not sure what are the consequences of doing this but it has worked for our use cases.
You should use shallow instead, then called .dive()
const mockFunc = jest.fn();
const component = shallow(<MyComponent onPress={mockFunc} />);
component.dive().simulate('press');
expect(mockFunc).toHaveBeenCalled();
I'm able to run tests like what you've described in your question in React Native. Here is my configuration:
package.json
"scripts": {
...
"test": "node_modules/jest/bin/jest.js",
}
"devDependencies": {
...
"enzyme": "^3.1.0",
"enzyme-adapter-react-16": "^1.0.1",
"enzyme-to-json": "^3.1.2",
"jest": "^21.2.1",
"jest-enzyme": "^4.0.0",
"jest-expo": "~21.0.0",
}
"jest": {
"preset": "jest-expo",
"setupFiles": [
"./test/jestSetup.js"
],
"snapshotSerializers": [
"./node_modules/enzyme-to-json/serializer"
]
}
test/jestSetup.js
import { configure, shallow, render, mount } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
configure( { adapter: new Adapter() } )
// enzyme
global.shallow = shallow
global.render = render
global.mount = mount
Example component:
import React from 'react'
import { Button } from 'react-native'
const CancelButton = ( props ) =>
<Button
{ ...props }
onPress={ () => { props.navigation.goBack() } }
title="Cancel"
/>
export { CancelButton }
Example test
import React from 'react'
import { CancelButton } from '../CancelButton'
test( 'onPress', () => {
const goBackFunc = jest.fn()
const navigation = {
goBack: goBackFunc,
}
const component = shallow(
<CancelButton
navigation={ navigation }
/>
)
component.simulate( 'press' )
expect( goBackFunc ).toHaveBeenCalled()
} )
.babelrc
{
"presets": ["babel-preset-expo"],
"env": {
"development": {
"plugins": ["transform-react-jsx-source"]
}
}
}