I'm new at jest testing. Now I'm trying to test my react components using snapshot testing. I've encountered such problem: jest only updates snapshot for AppComponent, but does not for another component, also it passes all both snapshot tests. What's wrong?
Have tried passing names to snapshot toMatchSnapshot(), have tried to change type of TestComponent from function to class extending Component, have tried deleting old snapshots and testing again, all in wain. Also, tried to render TestComponent in AppComponent below AppComponent default html and it caused updating AppComponent snapshot only.
AppComponent
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { TestComponent } from './TestComponent';
export function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer">
Learn React
</a>
</header>
</div>
);
}
export default App;
AppComponent test
import React from 'react';
import ReactDOM from 'react-dom';
import { App, reverseOfReverse, addTwoIntegers } from './App';
import renderer from 'react-test-renderer';
describe('snapshot tests', () => {
test('matches the snapshot', () => {
const tree = renderer.create(<App />).toJSON();
expect(tree).toMatchSnapshot('AppComponentSnapshot');
});
});
AppComponent snapshot
// Jest Snapshot v1
exports[`snapshot tests matches the snapshot: AppComponentSnapshot 1`] = `
<div
className="App"
>
<header
className="App-header"
>
<img
alt="logo"
className="App-logo"
src="logo.svg"
/>
<p>
Edit
<code>
src/App.js
</code>
and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
rel="noopener noreferrer"
target="_blank"
>
Learn React
</a>
</header>
</div>
`;
TestComponent
import logo from './logo.svg';
import React, { Component } from 'react';
export class TestComponent extends Component {
render() {
return (
<div className="TestComponent">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer">
Learn React
</a>
</header>
<div>lola</div>
<div>amanda</div>
</div>
);
}
}
export default TestComponent;
TestComponent test
import React from 'react';
import renderer from 'react-test-renderer';
import { TestComponent } from './TestComponent';
describe('snapshot for second component', () => {
test('matches second snapshot', () => {
const tree = renderer.create(<TestComponent />).toJSON;
expect(tree).toMatchSnapshot('TestComponentSnapshot');
});
});
TestComponent snapshot
// Jest Snapshot v1
exports[`snapshot for second component matches second snapshot: TestComponentSnapshot 1`] = `[Function]`;
I expected that snapshot test would also fill TestComponent snapshot with appropriate snapshot, or the test would fail, but neither happened.
I just faced this problem too. Spent an hour to realize that toJSON is missing a pair of parentheses. It's supposed to be a function call toJSON() instead of just toJSON. How silly
Related
I recently came back to coding and I'm trying learn react on udemy. this code should fetch json files from a website and console.log them. instead I'm getting a this is undefined error.how do I get it to correctly log the information from the fetched website and remove this is undefined error?
import {Component} from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component() {
constructor(){
super();
this.state ={
monsters:[],
};
}
componentDidMount(){
fetch('https://jsonplaceholder.typicode.com/users').then((response)=>response.json()).then((users)=>console.log(users));
}
render(){
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}}
export default App;
Try this, We can use function component and hooks nowadays because it is easy to use and redable to others.
import React, { useEffect } from 'react';
const App = () => {
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then((response)=>response.json())
.then((users)=>console.log(users));
}, []);
return (
<div className='App'>
<h1>Hello React.</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
export default App;
import React, {Component} from 'react'
const Greet=()=> <h1>Say helllo</h1>
export default Greet;
This functional component i've created and imported in App.js
import logo from './logo.svg';
import './App.css';
import './Components/Greet'
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
<br></br>
<button>Submit</button>
</header>
<Greet/>
</div>
);
}
export default App;
But getting error in chrome web:
**src\App.js
Line 24:8: 'Greet' is not defined react/jsx-no-undef
src\Components\Greet.js
Line 7:16: 'Greet' is not defined no-undef**
New to React Helpful if someone can help me with this.
const greet=()=> <h1>Say helllo</h1>
Try Greet instead of greet
Also in your App.js write in this way
import Greet from "./Components/Greet";
I'm a newbie to react, I'm using the create-react-app package, and express generator. I can't seem to be able to render the react component due to undefined property, which I can't see to understand why is it undefined? Here is my code:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import PageContent from './App';
import * as serviceWorker from './serviceWorker';
const pageContent = new PageContent();
ReactDOM.render(
<React.StrictMode>
<pageContent.App />
</React.StrictMode>,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();
App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
class PageContent extends React.Component {
constructor(props) {
super(props)
this.state = {
apiResponse: 'test test test'
};
}
callAPI() {
fetch("http://localhost:3127/testAPI")
.then(res => res.text())
.then(res => this.setState({ apiResponse: 'hello' }));
}
componentWillMount() {
this.callAPI();
}
App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
<p className="App-intro">**{PageContent.state.apiResponse}</p>
</header>
</div>
);
}
}
export default PageContent;
This is the error I get:
TypeError: Cannot read property 'apiResponse' of undefined
App
src/App.js:39
36 | >
37 | Learn React
38 | </a>
> 39 | <p className="App-intro">**{PageContent.state.apiResponse}</p>
40 | ^ </header>
41 | </div>
42 | );
Thanks everyone for the help
You want to use:
{this.state.apiResponse}
Edit: I noticed you're rendering the App method directly after creating an instance of the PageContent class. You don't need to do this. You can simply rename the App() method to be render(), then remove the const pageContent = new PageContent(); and you can then render <PageContent /> instead of <pageContent.App />.
You are making 2 mistakes -
first write it as {this.state.apiResponse}
Your app.js file is not written properly, It should be something like this
import React from 'react';
import logo from './logo.svg';
import './App.css';
export default class PageContent extends React.Component {
constructor(props) {
super(props)
this.state = {
apiResponse: 'test test test'
};
}
callAPI() {
fetch("http://localhost:3127/testAPI")
.then(res => res.text())
.then(res => this.setState({ apiResponse: 'hello' }));
}
componentWillMount() {
this.callAPI();
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
<p className="App-intro">{this.state.apiResponse}</p>
</header>
</div>
);
}
}
after this import this PageContent in your index.js like this -
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import PageContent from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<React.StrictMode>
<PageContent />
</React.StrictMode>,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();
based on React Docs and this medium article, I did something as simple as this to try profiler in react
import React, { unstable_Profiler as Profiler } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends React.Component {
logProfile = (id, phase, actualTime, baseTime, startTime, commitTime) => {
console.log(`${id}'s ${phase} phase:`);
console.log(`Actual time: ${actualTime}`);
console.log(`Base time: ${baseTime}`);
console.log(`Start time: ${startTime}`);
console.log(`Commit time: ${commitTime}`);
};
render () {
return (
<div>
<Profiler id="app" onRender={this.logProfile}>
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
</Profiler>
</div>
);
}
}
export default App;
but this is throwing following error
Error: Element type is invalid: expected a string (for built-in
components) or a class/function (for composite components) but got:
undefined. You likely forgot to export your component from the file
it's defined in, or you might have mixed up default and named imports.
Check the render method of App.
Can someone tell me what I am doing wrong here?
I face the same issue and I change the import object from unstable_Profiler to Profiler directly and it works.
// import React, { unstable_Profiler as Profiler } from 'react';
import React, { Profiler } from 'react';
const App = () => (
<div>
<Profiler>
<OtherComponents />
</Profiler>
</div>
)
I check the test scenario of Profiler here at github.
I have created a basic create-react-app and added the below statement
const [stateA, setStateA] = useState(false);
and I have put a console.log inside my component.
The complete component code is
import React, { useState } from 'react';
import logo from './logo.svg';
import './App.css';
const App = () => {
const [stateA, setStateA] = useState(false);
console.log("rendered");
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
It is showing "rendered" twice. Can any one tell why this is happening ?
If you notice index.js (as create-react-app now uses React.StrictMode by default ) file you may have a wrapper called React.StrictMode which is responsible for this extra re-render. The wrapper will invoke render, constructor and other lifecycle methods to detect side effects. So this is expected.
You can read more here: https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects
Hope this helps!