could you please tell me why the test case not running in react using enzyme?
I install enzyme js and follow this tutorial
https://javascriptplayground.com/introduction-to-react-tests-enzyme/
here is my code
import React from 'react';
import Hello from './Hello';
import { shallow } from 'enzyme';
it('renders', () => {
const wrapper = shallow(<Hello name="Jack" />);
expect(wrapper.find('h1').text()).toEqual('Hello, Jack!');
});
https://codesandbox.io/s/5x6oqkyknn
The issue you are facing with test not being found was an issue with naming.
codesandbox is using character sensitive regex and you have to make it Hello.spec.js for it to be detected.
Here is the sandbox forked from your code: https://codesandbox.io/s/649owm14o3
Also, to have the test actually work you have to setup a enzyme-adapter-react-16 and have it setup like:
import Enzyme, { shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
Typically you would do this in a different file, but for the purposes of this demo, I have set it up in the same file.
Also note the typo comma "Hello Jack"
Related
I need to check if there are any variables in App.js and then check their type. I checked all the docs for jest, enzyme and react testing library but found nothing useful.
If anyone can give me a hand it'll be very much appreaciated. Sharing my code below.
App.js:
const names = ["George", "Lewis", "Max", "Charles", "Fernando"];
const surnames = ["Pedrosa", "Rossi", "Crivillé", "Márquez", "Lorenzo"];
return <div className="App"></div>;
}
export default App;
Test:
import Adapter from "enzyme-adapter-react-16";
import "#testing-library/jest-dom";
import Test from "../../block02/ex02/src/App.js";
import { screen, render } from "#testing-library/react";
configure({ adapter: new Adapter() });
describe("b2ex02: Display name and surname side by side", () => {
it("Declare two arrays", () => {
// here I need to select the "names" and "surnames" variables and check that they are typeof array
});
});
If I can provide any other useful piece of information I will be happy to. Thanks!
Edit
I fully recommend testing variable existence through some kind of using them. Otherwise this has proven imposible to achieve.
In relation to a previous question - How can Enzyme check for component visibility? I tried using jest-dom to specifically use their toBeVisible function.
Despite following the documentation I cannot get it to work in my test and get the error
"TypeError: expect(...).not.toBeVisible is not a function"
Fully reproduced in CodeSandbox here
import Enzyme, { mount } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import React from "react";
import MyCheckbox from "./MyCheckbox";
import MyCheckboxesInUse from "./MyCheckboxesInUse";
Enzyme.configure({ adapter: new Adapter() });
test("Check that one checkbox is hidden and the other is visible", () => {
const wrapper = mount(<MyCheckboxesInUse />);
const checkboxes = wrapper.find(MyCheckbox);
expect(checkboxes).toHaveLength(2);
//HOW DO I CHECK THAT ONE IS VISIBLE AND THE OTHER IS NOT ?
expect(checkboxes.get(0)).not.toBeVisible();
expect(checkboxes.get(1)).toBeVisible();
});
I was facing a similar issue. In my case, it was resolved by the following steps:-
Adding the #testing-library/jest-dom package to the devDependencies instead of dependencies in the package.json file.
Next add one of the following:
Adding import '#testing-library/jest-dom'; to the setupTests.js
Or adding in jest configuration (package.json): "setupFilesAfterEnv": [ "#testing-library/jest-dom/extend-expect" ]
The expect().not.toBeVisible method comes from the #testing-library/jest-dom library, since there is no setup or reference to that library the default jest expect is used (thus the function is not found). A quick fix would be to add this import to the top of your test file (assuming you have already imported the library into your project via npm or yarn):
import '#testing-library/jest-dom';
For scalability you may want to add a setupTest.js file (reference here: https://create-react-app.dev/docs/running-tests/)
importing '#testing-library/jest-dom' doesn't help me but
importing #testing-library/jest-dom/extend-expect' help me resolve the error.
import '#testing-library/jest-dom/extend-expect'
Below is a a little test file that I made for a React project that is using both Jest and Enzyme for testing. In this test, I'm simply trying to find an element in the component and see that it exists (as a truthy conditional). The whole point of this test wasn't just to see if the element existed, but I figured I'd start here. I'm very new to testing, so this syntax/implementation may be bonkers:
import React from 'react';
import ReactDOM from 'react-dom';
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import HamburgerIcon from './HamburgerIcon';
Enzyme.configure({ adapter: new Adapter() });
test('my first test -- will add better text here later', () => {
const div = document.createElement('div');
ReactDOM.render(<HamburgerIcon />, div);
expect(div.find('.closed').exists()).toBeTruthy();
ReactDOM.unmountComponentAtNode(div);
});
Running this results in this error:
TypeError: div.find is not a function
I originally built this test after seeing this Stack Overflow answer.
I'm not sure how to troubleshoot this, but I'm guessing that maybe I haven't properly "mounted" the component in this test? In the same Stack Overflow thread from the previous link, this answer shows how you would mount a component, but another comment on that answer says that another package needs to be installed in order to do that.
I sort of figured that using the div variable as the container to be searched with find would work, but am I wrong in thinking that?
Here's the sample code for you, may not be 100% what you need but should get you started. I also included console.log so that you know what gets rendered.
To explain a bit on what happens, is in your test case you are calling shallow method and passing your React component to it to render. Test cases are run in virtual browser/renderer not the real browser (unless you configure it that way).
import React from 'react';
import ReactDOM from 'react-dom';
import Enzyme, { shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import HamburgerIcon from './HamburgerIcon';
Enzyme.configure({ adapter: new Adapter() });
test('my first test -- will add better text here later', () => {
const wrapper = shallow(<HamburgerIcon />);
console.log(wrapper);
expect(wrapper.find('.closed').exists()).toBeTruthy();
});
I have a minimum test react app with following component:
import React from 'react';
import $ from 'jquery';
export default class App extends React.Component {
componentDidMount() {
console.log('componentDidMount', $('#helloDiv').length);
}
render() {
return <div id='helloDiv'>
Hello React!
</div>;
}
}
this works fine when loading it in browser (Chrome). The console.log() in componentDidMount() prints out 1 helloDiv element found
However, if I run the test using mocha + enzyme + jsdom, the same console.log() in App component prints out 0:
import React from 'react';
import { mount } from 'enzyme';
import { expect } from 'chai';
import App from '../src/client/app/first'
describe('first test', () => {
it('should pass', () => {
const app = mount(<App />);
expect(app.find('#helloDiv').length).to.eq(1);
});
});
Note: I don't have problem with this unit test, it's passing. The real problem is when < App /> is mounted using enzyme, componentDidMount() is called but the console.log() statement inside it prints out 0, instead of 1
Here is how I run mocha:
mocha --require enzyme/withDom --compilers js:babel-core/register test/index.test.js
Any idea why jquery selector doesn't find anything in the test? It should not be mocha issue because the same issue happens if I change to jest
Finally found the issue:
Enzyme mount(<SomeComponent />) by default will do full DOM rendering but not insert the rendered component into current document (JSDom). That's why jQuery cannot find any element in current document
To do full DOM rendering AND attach to current document:
mount(<SomeComponent />, { attachTo: document.getElementById('app') });
Where app is empty div available when jsdom is setup:
global.document = jsdom('<html><head></head><body><div id="app" /></body></html>');
There needs to be some setup done before you could jsdom with jquery in node-env.
Try this if it helps.
Create a test helper file like this -
test_helper.js
import _$ from 'jquery';
import jsdom from 'jsdom';
import chai, { expect } from 'chai';
import chaiJquery from 'chai-jquery';
global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
global.window = global.document.defaultView;
global.navigator = global.window.navigator;
const $ = _$(window);
chaiJquery(chai, chai.util, $);
export {expect};
While running -
mocha --require enzyme/withDom --compilers js:babel-core/register --require test/test_helper.js test/index.test.js
or another way use jsdom-global without test_helper.js file.
npm install --save-dev jsdom-global
Then :
import 'jsdom-global/register';
//at the top of file , even , before importing react
I couldn't get Phuong Nguyen's answer to work. I did find the relevant page in the enzyme docs. I ended up with something like, based on the final example on that page:
const div = global.document.createElement('div');
global.document.body.appendChild(graphDiv);
const wrapper = mount(<SomeComponent />, { attachTo: div }); // same as the other answer
// clean up after ourselves
wrapper.detach();
global.document.body.removeChild(div);
In my Rails project, I am using the react-rails gem, which does the following:
window.React = React;
This is pretty handy, but when I run unit tests using Jest, that global is not there and I get an error from the file containing the component I am testing saying that React is not defined.
If I define React in the component file using
import React from 'react';
Then it causes errors due to loading React twice.
How should I define a global React variable in my unit tests so they work?
In your test file, do:
import React from 'react'
describe('something',() => {
window.React = React
// so when you require() your component, window.React is already set
var MyComponent = require('MyComponent').default
it('does something', () => {
// do something
})
})