Comments (29)
Bump. We're currently struggling this as well. Has anyone figured out a reasonable pattern for testing with enzyme?
from react-modal.
@jkimbo I figured out my issue. You example worked fine so it was indeed an issue on my side.
I was rendering from an external module like
var renderedModal = TestUtils.renderIntoDocument(
<MyModule
props1:{stubblabla}
/>
);
and calling MyModule.portal, which was obviously wrong, I needed the Modal.portal
So for whoever is in trouble like I was: remember to get the Modal component !
TestUtils.findRenderedComponentWithType(component, Modal);
from react-modal.
I know this issue is about React test utils, but is it possible to make testing work with Enzyme.js?
Enzyme.js provides a simpler/cleaner API over React test utils (in my opinion) and it would be handy to be able to utilise that when testing code regarding react-modal.
from react-modal.
This blog post has some examples for testing react-modal with enzyme: http://remarkablemark.org/blog/2017/05/17/testing-react-modal/
from react-modal.
With enzyme, shallow supports portal components while mount does not. If you absolutely must use mount, you can use ref={(ref) => { this.namedRef = ref; } in order to access the element and then wrap it in an enzyme ReactWrapper.
from react-modal.
@ramusus I too am unable to get this to work with enzyme 3 and enzyme-adapter-react-15. If you've come up with a workaround, please share.
I've tried react-dom/test-utils renderIntoDocument
then ReactDOM.findDOMNode
and scryRenderedDOMComponentsWithClass
as recommended here with little to no success.
I've also tried the examples from the blog post recommended by @dy-dx with limited success. I've been able to get a reference to the portal component but it doesn't seem to contain any HTML. (Yes, I've set isOpen
to true
.)
I've tried using both shallow
and mount
from enzyme and despite @bethcodes' experience with shallow
, I actually got further with mount
. With shallow
I had no luck finding any portal.
from react-modal.
Having trouble testing this as well.
👍 thanks for the pointer @baer !
from react-modal.
@baer I guess this is because the modal creates a "portal" by mounting the actual modal in a new div at the bottom of the page. You can see in the Modal.js
component the render method is not actually returning anything: https://github.com/rackt/react-modal/blob/1ff6a02c689e9fdc03616c4ab82ec53317f14c69/lib/components/Modal.js#L74
To get around this you need to access the .portal
property (https://github.com/rackt/react-modal/blob/1ff6a02c689e9fdc03616c4ab82ec53317f14c69/lib/components/Modal.js#L70) on the renderedModal
to access the correct React tree to run the TestUtils on. So React.scryRenderedDOMComponentsWithClass(renderedModal.portal, "my-modal-class");
should work.
Hope that makes sense!
from react-modal.
@jkimbo that sounded promising, unfortunately that didn't do the trick for me. I get an undefined on renderedModal.portal. Do you get the React tree on that ?
from react-modal.
@ArthurCid I've written up a passing test for you using mocha and jsdom: https://gist.github.com/jkimbo/872f42732e6c772bf8e1
from react-modal.
I'm still having trouble with this. I've tried [email protected]
w/ [email protected]
and [email protected]
w/ [email protected]
. Testing with karma, karma-chrome and mocha.
the .portal
property exists and renders but it appears to have no children
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
import { expect } from 'chai';
import Modal from 'react-modal';
describe('component - common - Modal', () => {
it('renders without problems', () => {
const renderedModal = TestUtils.renderIntoDocument(
<Modal>
<div className="my-modal-class">
<h1>Hi!</h1>
</div>
</Modal>
);
// passing
expect(ReactDOM.findDOMNode(renderedModal.portal).tagName).to.equal('DIV');
expect(ReactDOM.findDOMNode(renderedModal.portal).children).to.be.empty;
const divs = TestUtils.scryRenderedDOMComponentsWithClass(renderedModal.portal, 'my-modal-class');
// fails
expect(divs.length).to.equal(1);
});
});
from react-modal.
@gbrassey you need to set isOpen={true}
on the modal component for it to render it's children.
from react-modal.
wow thanks @jkimbo 😵 🔫
from react-modal.
@ArthurCid glad you figured it out!
from react-modal.
There hasn't been much traction on this issue in over a year. I'm assuming that this is no longer an issue, especially given that #136 was merged. If it is, please feel free to re-open.
from react-modal.
@begincalendar Is there a specific issue with using Enzyme? In theory it should "just work" assuming the notes about testing from the read me are followed. If there's a specific issue where it fails, please file an issue for it
from react-modal.
There is no issue per se, it's more of that the React test utils give you DOM elements, whereas Enzyme gives you wrappers and pseudo elements.
I.e. The whole library is designed to work with these wrappers/pseudoelements, e.g. for making simulate()
calls.
So getting back DOM elements from React test utils, means that Enzyme can't really be utilised completely.
from react-modal.
Right. I actually really like Enzyme and have used it frequently in other projects. I don't see any reason that you couldn't use Enzyme when testing a component that uses react-modal.
from react-modal.
But you need to extract the portal
property to get access to child elements, right?
As far as I'm aware, with Enzyme, once you take out the reference to the portal
property, you can't then go do things such as: render the child elements, render the text of the child elements, find sub-child elements, etc.
Am I missing something?
from react-modal.
Hmmm... I'd have to put together an example of this to be sure. I don't have time at the moment, but I'll see if I can't put something together soon.
from react-modal.
I'm also interested on how to test with Enzyme. I've been struggling with this for a while.
from react-modal.
Anyone.. ?
from react-modal.
from react-modal.
Here's an example where I used enzyme to test a component with react-modal. The modal is used to confirm a user wants to go forward, and tests to see if confirmed()
was called.
confirm_modal.jsx
import React from 'react';
import ReactModal from 'react-modal';
import PropTypes from 'prop-types';
export default class ConfirmModal extends React.Component {
static propTypes = {
closeModal: PropTypes.func.isRequired,
isOpen: PropTypes.bool.isRequired,
}
confirmed() {
console.log('PASSED');
}
modalContent() {
return (
<div>
<div className="c-modal__main">
Do you wish to proceed?
</div>
<div className="c-modal__bottom">
<button
type="button"
className="c-btn c-btn--gray"
onClick={this.props.closeModal}
>
No
</button>
<button
type="button"
className="c-btn c-btn--blue"
onClick={() => this.confirmed()}
>
Yes
</button>
</div>
</div>
);
}
render() {
return (
<ReactModal
isOpen={this.props.isOpen}
onRequestClose={this.props.closeModal}
contentLabel="Modal"
overlayClassName="c-modal__background"
className="c-modal is-open"
>
{this.modalContent()}
</ReactModal>
);
}
}
confirm_modal.spec.jsx
import React from 'react';
import { shallow } from 'enzyme';
import ConfirmModal from './confirm_modal';
describe('confirm modal', () => {
let props;
beforeEach(() => {
props = {
closeModal: () => {},
isOpen: true,
};
});
it('confirms user wants to proceed', () => {
spyOn(ConfirmModal.prototype, 'confirmed');
const wrapper = shallow(<ConfirmModal {...props} />);
const content = wrapper.instance().modalContent();
const modalContent = shallow(content);
modalContent.find('.c-btn--blue').simulate('click');
expect(wrapper.instance().confirmed).toHaveBeenCalled();
});
it('renders modalContent', () => {
spyOn(ConfirmModal.prototype, 'modalContent');
const wrapper = shallow(<ConfirmModal {...props} />);
expect(wrapper.instance().modalContent).toHaveBeenCalled();
});
});
Hopefully that helps you guys out 👍
from react-modal.
@dy-dx thanks for great solution, but it doesn't work with the last enzyme
"enzyme": "3.1.1",
"enzyme-adapter-react-15": "1.0.5",
Do you have any workaround?
from react-modal.
@ryanhomer, found solution - do not use ReactWrapper or any other hacks - content of modals get rendered into the main wrapper, properly in place where it should be logically (but not in the real DOM).
So everything becomes more simple and easy to test, just not forget to do wrapper.update() ...
from react-modal.
@ramusus Are you able to post an example? I'm still have issues rendering modal content without ReactWrapper.
from react-modal.
// ModalContainer.js
import React, { Component } from 'react';
import ReactModal from 'react-modal';
export default class ModalContainer extends Component {
constructor(props) {
super(props);
this.state = {
isModalOpen: false
};
this.toggleModal = this.toggleModal.bind(this);
}
toggleModal() {
this.setState({
isModalOpen: !this.state.isModalOpen
});
}
render() {
return (
<div>
<button onClick={this.toggleModal}>
Open Modal
</button>
<ReactModal
{...this.props}
isOpen={this.state.isModalOpen}
onRequestClose={this.toggleModal}
>
<div>Content</div>
</ReactModal>
</div>
);
}
}
// ModalContainer.spec.js
import React from 'react';
import ReactModal from 'react-modal';
import ModalContainer from './ModalContainer';
import { mount } from 'enzyme';
describe('<ModalContainer>', () => {
it('opens modal and render it\'s content when button is clicked', () => {
const wrapper = mount(<ModalContainer />);
wrapper.find('button').simulate('click');
expect(wrapper.find(ReactModal).text()).toBe('Content');
});
});
from react-modal.
@ramusus The example above no longer works for me. I got this error
- opens modal and render it's content when button is clicked:
TypeError: Cannot read property 'textContent' of null
at ReactWrapper. (node_modules/enzyme/build/ReactWrapper.js:799:43)
at ReactWrapper.single (node_modules/enzyme/build/ReactWrapper.js:1534:25)
at ReactWrapper.text (node_modules/enzyme/build/ReactWrapper.js:798:21)
at Context. (src/a/test.spec.js:14:37)
I'm using react-modal 3.4.4 and enzyme 3.3.0. Is there anything that I miss?
Update: If I shallow render the modal, then its children is rendered.
from react-modal.
Related Issues (20)
- Focus on the input element is lost when trying to scroll modal content by dragging scrollbar
- Focus trap incorrectly finds tabbable elements HOT 11
- Modal doesn't close on the first click on the overlay after click on elements containing event.stopPropagation() inside modal HOT 11
- Add support for React & Node 18 (as easy as adding startTransition() on each setState) HOT 18
- When I try to apply css variables from css modules in React, nothing is passed HOT 9
- Npm start related issue
- Why convert position property to inset? HOT 2
- Analysis: 90% of dependency updates in this repository can be merged.
- Should use event.key not event.code
- How can i make the modal overlay non blocking? HOT 2
- Resize error when moving tab around HOT 2
- Display blurry when elements with position attributes and have scrollbars. HOT 3
- Close the modal window on the first click when using stopPropagation() HOT 3
- Moving to a "modern" build system (hardcore level) HOT 6
- Refactor react-modal to use TypeScript HOT 1
- Replace Karma (now deprecated) with a new test runner HOT 6
- Runtime error when tabbing elements where shadowDom is a document fragment rather than an element
- Consider dropping support for React versions <= v16 HOT 3
- Avoid Scroll position being kept HOT 7
- react-modal issue
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-modal.