I'm trying to set up Jest in an React app using Typescript.
My set up is like this
My package.json
{
"name": "react-tdd-ts",
"version": "0.1.0",
"private": true,
"dependencies": {
"#types/jest": "24.0.23",
"#types/node": "12.12.9",
"#types/react": "16.9.11",
"#types/react-dom": "16.9.4",
"enzyme": "^3.10.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-scripts": "3.2.0",
"typescript": "3.7.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"#types/enzyme": "^3.10.3",
"#types/enzyme-adapter-react-16": "^1.0.5",
"#types/react-test-renderer": "^16.9.1",
"enzyme-adapter-react-16": "^1.15.1",
"react-test-renderer": "^16.12.0"
}
}
My App.tsx
import React from "react";
import "./App.css";
import Footer from "./components/Footer";
const App: React.FC = () => {
return (
<div className="App">
<Footer />
</div>
);
};
export default App;
My Footer.tsx
import React from "react";
const Footer: React.FC = () => {
return (
<div>
<hr />
<span>Text here</span>
</div>
);
};
export default Footer;
My Footer.test.tsx
import React from "react";
import { shallow } from "enzyme";
import Footer from "./Footer";
it("should render text", () => {
const wrapper = shallow(<Footer />);
const span = wrapper.find("span");
const result = span.text();
expect(result).toBe("Text here");
});
MY setupTest.tsx
import { configure } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
configure({ adapter: new Adapter() });
In the terminal I'm getting the following error
PASS src/App.test.tsx
FAIL src/components/Footer.test.tsx
● should render text
Enzyme Internal Error: Enzyme expects an adapter to be configured, but found none.
To configure an adapter, you should call `Enzyme.configure({ adapter: new Adapter() })`
before using any of Enzyme's top level APIs, where `Adapter` is the adapter
corresponding to the library currently being tested. For example:
import Adapter from 'enzyme-adapter-react-15';
To find out more about this, see http://airbnb.io/enzyme/docs/installation/index.html
4 |
5 | it("should render text", () => {
> 6 | const wrapper = shallow(<Footer />);
| ^
7 | const span = wrapper.find("span");
8 | const result = span.text();
9 |
at validateAdapter (node_modules/enzyme/src/validateAdapter.js:5:11)
at getAdapter (node_modules/enzyme/src/getAdapter.js:10:3)
at makeShallowOptions (node_modules/enzyme/src/ShallowWrapper.js:345:19)
at new ShallowWrapper (node_modules/enzyme/src/ShallowWrapper.js:379:21)
at shallow (node_modules/enzyme/src/shallow.js:10:10)
at Object.<anonymous>.it (src/components/Footer.test.tsx:6:19)
Sorry I don't have a working demo but can anyone see what I'm doing wrong.
Is there a different way to set up enzyme and Jest when using typescript
I need this in the test file
import Enzyme from "enzyme";
import Adapter from "enzyme-adapter-react-16";
Enzyme.configure({ adapter: new Adapter() });
it was posted here but then removed
Related
I'm trying to follow along with this youtube video https://youtu.be/tbvguOj8C-o?t=33570
I'm having issue at this point forward in the video until the next code update (Roughly one minute in)
Specifically, the creator is adding these changes which causes an Invalid Hook Call
import RadioButtonUncheckedIcon from '#mui/icons-material/RadioButtonUnchecked';
...
const capture = useCallback(() => {
const imageSrc = webcamRef.current.getScreenshot();
console.log(imageSrc);
}, [webcamRef]);
...
<RadioButtonUncheckedIcon
className='WebcamCapture__button'
onClick={capture}
/>
The full code for the file is here:
import React, {useCallback, useRef} from "react";
import Webcam from "react-webcam";
import RadioButtonUncheckedIcon from '#mui/icons-material/RadioButtonUnchecked';
const videoConstraints = {
width: 250,
height: 400,
facingMode: "user",
};
function WebcamCapture() {
const webcamRef = useRef(null);
const capture = useCallback(() => {
const imageSrc = webcamRef.current.getScreenshot();
console.log(imageSrc);
}, [webcamRef]);
return (
<div className="webcamCapture">
<Webcam
audio={false}
height={videoConstraints.height}
ref={webcamRef}
screenshotFormat="image/jpeg"
width={videoConstraints.width}
videoConstraints={videoConstraints}
/>
<RadioButtonUncheckedIcon
className='WebcamCapture__button'
onClick={capture}
/>
</div>
);
}
export default WebcamCapture;
The WebcamCapture component is used here:
import React from 'react';
import WebcamCapture from './WebcamCapture';
function App() {
return (
<div className="app">
<h1>Test build</h1>
<WebcamCapture />
</div>
);
}
export default App;
The error code displayed in the chrome console is this:
Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
This is my best guess for the issue. It's the first issue called that causes declerations to be null. The full error stacktrace can be found here: https://pastebin.com/UKQm9TYi
The package.json looks like this,
{
"name": "snapchat-clone",
"version": "0.1.0",
"private": true,
"dependencies": {
"#mui/base": "^5.0.0-alpha.91",
"#mui/icons-material": "^5.8.4",
"#mui/material": "^5.9.2",
"#reduxjs/toolkit": "^1.8.3",
"#testing-library/jest-dom": "^5.16.4",
"#testing-library/react": "^13.3.0",
"#testing-library/user-event": "^14.3.0",
"react": "^16.8.0",
"react-dom": "16.8.0",
"react-redux": "^8.0.2",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"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"
]
}
}
To the best of my knowledge, React and the renderer are matching versions, I haven't violated the Rules of Hooks (most tentative!), and there is only one copy of React running in the app as every other call is dedupped.
I'm very new to React and Node.JS so any feedback or criticisms are welcome. Thank you for your time.
I found the issue to the problem. There was a missing dependency in the package.json that I hadn't noticed until I placed the code into a sandbox.
Specifically, it was
"#mui/icons-material": "5.8.4",
**
TypeError: unable to read Undefined property 'getState' I couldn't find a solution.would you look at my codes?How do you think the solution should be?**
index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import {createStore} from 'redux';
import rootReducer from './store/reducers/rootReducer';
import {Provider} from 'react-redux';
const store=createStore(rootReducer);
ReactDOM.render(<Provider>store={store}<App /></Provider>, document.getElementById('root'));
provider.js
import React, { useMemo, useEffect } from 'react';
import PropTypes from 'prop-types';
import { ReactReduxContext } from './Context';
import Subscription from '../utils/Subscription';
function Provider(_ref) {
var store = _ref.store,
context = _ref.context,
children = _ref.children;
var contextValue = useMemo(function () {
var subscription = new Subscription(store);
subscription.onStateChange = subscription.notifyNestedSubs;
return {
store: store,
subscription: subscription
};
}, [store]);
var previousState = useMemo(function () {
return store.getState();
}, [store]);
useEffect(function () {
var subscription = contextValue.subscription;
subscription.trySubscribe();
if (previousState !== store.getState()) {
subscription.notifyNestedSubs();
}
return function () {
subscription.tryUnsubscribe();
subscription.onStateChange = null;
};
}, [contextValue, previousState]);
var Context = context || ReactReduxContext;
return React.createElement(Context.Provider, {
value: contextValue
}, children);
}
Provider.propTypes = {
store: PropTypes.shape({
subscribe: PropTypes.func.isRequired,
dispatch: PropTypes.func.isRequired,
getState: PropTypes.func.isRequired
}),
context: PropTypes.object,
children: PropTypes.any
};
export default Provider;
projectlist.jsx
import React from 'react';
import ProjectSummary from './ProjectSummary';
const ProjectList = ({projects}) => {
return (
<div className="project-list secion">
{projects && projects.map(project=>{
return(
<ProjectSummary project={project} key={projects.id} />
)
})}
</div>
)
}
export default ProjectList;
rootReducer.jsx
import authReducer from './authReducer';
import projectReducer from './projectReducer';
import {combineReducers} from 'redux';
const rootReducer=combineReducers({
auth:authReducer,
project:projectReducer
})
export default rootReducer
**************************
authreducer.jsx
const initState={}
const authReducer=(state=initState,action)=>{
return state
}
export default authReducer
projectreducer.jsx
const initState={
projects:[
{id:1,baslik:'React Yazılım',icerik:'Geliştirme'},
{id:1,baslik:'Redux Yazılım',icerik:'Geliştirme'},
{id:1,baslik:'Firebase Yazılım',icerik:'Geliştirme'}
]
}
const projectReducer=(state=initState,action)=>{
return state
}
export default projectReducer
authreducer.jsx
const initState={}
const authReducer=(state=initState,action)=>{
return state
}
export default authReducer
package.json
{
"name": "omaga-yazilim",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.4.0",
"#testing-library/user-event": "^7.2.1",
"firebase": "^5.5.8",
"jest-leak-detector": "^25.1.0",
"moment": "^2.22.2",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-redux": "^5.1.1",
"react-redux-firebase": "^2.2.1",
"react-router-dom": "^4.3.1",
"react-scripts": "2.1.1",
"redux": "^4.0.1",
"redux-firestore": "^0.6.0",
"redux-thunk": "^2.3.0",
"start": "webpack-dev-server --mode development"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Store must be passed as a prop to <Provider>:
index.jsx
<Provider>store={store}<App /></Provider>
^^^^^^^^^^^^^
ooops! 👻
store should be before and inside the > tag:
<Provider store={store}><App /></Provider>
I am new to ReactJs testing, i am trying to run npm test, it was working fine until i installed enzyme-adapter-react-16. I am getting below error. TypeError: Super expression must either be null or a function, not undefined
1 | import { configure } from 'enzyme';
> 2 | import Adapter from 'enzyme-adapter-react-16';
| ^
3 | configure({ adapter: new Adapter() });
I tried different ways to solve the problem I added setupTests.js file
and i deleted npm module folder, i deletd package.lock.json, installed npm again none off them worked.
setupTests.js
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
App.test.js
import Enzyme from "enzyme";
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
package.json
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"jest-environment-enzyme": "^7.0.2",
"jest-enzyme": "^7.0.2",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-scripts": "3.0.1"
},
"devDependencies": {
"enzyme": "^2.9.1",
"enzyme-adapter-react-16": "^1.14.0",
"enzyme-to-json": "^3.3.5",
"react-test-renderer": "^16.8.6"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
It used to run fine until I install enzyme.
My test does not fail when making changes to App.js.
I'm using jest, enzyme, react.js, react-create-app, and react-scripts.
As I update the App.js component, I expect that the test should fail because it does not match the snapshot of App.js. I think it has to do with my _ snapshot _/App.test.js file... How do I fix this? Any ideas?
Here is my code:
src/components/App.js:
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div>
<h2>Gift Giver</h2>
</div>
);
}
}
export default App;
src/components/App.test.js:
import React from 'react';
import { shallow } from 'enzyme';
import App from './App';
const app = shallow(<App />);
it('renders correctly', () => {
expect(app).toMatchSnapshot();
});
src/components/__ snapshots __/App.test.js.snap
exports[`renders correctly 1`] = `ShallowWrapper {}`;
package.json:
{
"name": "giftgiver",
"version": "0.1.0",
"private": true,
"dependencies": {
"enzyme": "^3.10.0",
"react": "^16.8.6",
"react-bootstrap": "^1.0.0-beta.9",
"react-dom": "^16.8.6",
"react-scripts": "3.0.1",
"react-test-render": "^1.1.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"enzyme-adapter-react-16": "^1.14.0"
}
}
As I update the App.js component, I expect that the test should fail because it does not match the snapshot of App.js
You have to use .debug() when rendering snapshots.
import React from 'react';
import { shallow } from 'enzyme';
import App from './App';
const app = shallow(<App />);
it('renders correctly', () => {
expect(app.debug()).to.matchSnapshot();
});
As an aside, generally it's better to use mount instead of shallow unless there's a very good reason not to.
I created a react app using create-react-app with typescript and trying to console log a couple of things from the test file but it's not working.
This is the tutorial I followed to set up create react app with typescript. I just added a console.log statement in the App.test.tsx file that comes with the setup and it didn't work.
It worked fine when I removed the 2 lines of code that used ReactDOM
package.json
{
"name": "testing2",
"version": "0.1.0",
"private": true,
"dependencies": {
"#types/jest": "24.0.11",
"#types/node": "11.12.0",
"#types/react": "16.8.10",
"#types/react-dom": "16.8.3",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-scripts": "2.1.8",
"typescript": "3.3.4000"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
App.test.tsx (doesn't work)
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
console.log('hello thereeeeeeee');
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
App.test.tsx (works)
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
console.log('hello thereeeeeeee');
const div = document.createElement('div');
// ReactDOM.render(<App />, div);
// ReactDOM.unmountComponentAtNode(div);
});
console.log statement is supposed to print. But it is not printing. The test is passing but the console statement is not printing when I use ReactDOM in the test