diff --git a/specs/Modal.spec.js b/specs/Modal.spec.js
index 84918551..0fb47fc3 100644
--- a/specs/Modal.spec.js
+++ b/specs/Modal.spec.js
@@ -1,47 +1,37 @@
/* eslint-env mocha */
-import { renderModal, unmountModal } from './helper';
import TestUtils from 'react-addons-test-utils';
import React from 'react';
import ReactDOM from 'react-dom';
import Modal from '../lib/components/Modal';
-import ariaAppHider from '../lib/helpers/ariaAppHider';
+import * as ariaAppHider from '../lib/helpers/ariaAppHider';
+import { renderModal, unmountModal, emptyDOM } from './helper';
+
const Simulate = TestUtils.Simulate;
import sinon from 'sinon';
import expect from 'expect';
describe('Modal', () => {
- afterEach('check if test cleaned up rendered modals', function () {
- var overlay = document.querySelectorAll('.ReactModal__Overlay');
- var content = document.querySelectorAll('.ReactModal__Content');
- expect(overlay.length).toBe(0);
- expect(content.length).toBe(0);
- });
+ afterEach('check if test cleaned up rendered modals', emptyDOM);
it('scopes tab navigation to the modal');
it('focuses the last focused element when tabbing in from browser chrome');
-
- it('can be open initially', function() {
- var component = renderModal({isOpen: true}, 'hello');
+ it('can be open initially', () => {
+ const component = renderModal({ isOpen: true }, 'hello');
expect(component.portal.refs.content.innerHTML.trim()).toEqual('hello');
- unmountModal();
});
it('can be closed initially', function() {
var component = renderModal({}, 'hello');
expect(ReactDOM.findDOMNode(component.portal).innerHTML.trim()).toEqual('');
- unmountModal();
});
it('accepts appElement as a prop', function() {
var el = document.createElement('div');
var node = document.createElement('div');
- ReactDOM.render(
-
- , node);
+ ReactDOM.render((
+
+ ), node);
expect(el.getAttribute('aria-hidden')).toEqual('true');
ReactDOM.unmountComponentAtNode(node);
});
@@ -50,13 +40,13 @@ describe('Modal', () => {
var node = document.createElement('div');
var App = React.createClass({
render() {
- return (
-
-
- hello
-
-
- );
+ return (
+
+
+ hello
+
+
+ );
}
});
Modal.setAppElement(node);
@@ -66,25 +56,18 @@ describe('Modal', () => {
ReactDOM.unmountComponentAtNode(node);
});
- it('renders children', function() {
- var child = 'I am a child of Modal, and he has sent me here...';
- var component = renderModal({isOpen: true}, child);
- expect(component.portal.refs.content.innerHTML).toEqual(child);
- unmountModal();
- });
+ it('renders children [tested indirectly]');
it('renders the modal content with a dialog aria role when provided ', function () {
var child = 'I am a child of Modal, and he has sent me here...';
var component = renderModal({isOpen: true, role: 'dialog'}, child);
expect(component.portal.refs.content.getAttribute('role')).toEqual('dialog');
- unmountModal();
});
it('renders the modal with a aria-label based on the contentLabel prop', function () {
var child = 'I am a child of Modal, and he has sent me here...';
var component = renderModal({isOpen: true, contentLabel: 'Special Modal'}, child);
expect(component.portal.refs.content.getAttribute('aria-label')).toEqual('Special Modal');
- unmountModal();
});
it('has default props', function() {
@@ -108,10 +91,10 @@ describe('Modal', () => {
expect(!document.querySelector('.ReactModalPortal')).toExist();
});
- it('focuses the modal content', function() {
+ it('focuses the modal content', function(done) {
renderModal({isOpen: true}, null, function () {
expect(document.activeElement).toEqual(this.portal.refs.content);
- unmountModal();
+ done();
});
});
@@ -119,54 +102,45 @@ describe('Modal', () => {
var modal = renderModal({
isOpen: true,
onRequestClose: function () {
- unmountModal();
- done();
+ done();
}
}, null);
renderModal({
isOpen: true,
onRequestClose: function () {
- Simulate.keyDown(modal.portal.refs.content, {
- // The keyCode is all that matters, so this works
- key: 'FakeKeyToTestLater',
- keyCode: 27,
- which: 27
- });
- expect(document.activeElement).toEqual(modal.portal.refs.content);
+ Simulate.keyDown(modal.portal.refs.content, {
+ // The keyCode is all that matters, so this works
+ key: 'esc',
+ keyCode: 27,
+ which: 27
+ });
+ expect(document.activeElement).toEqual(modal.portal.refs.content);
}
}, null, function checkPortalFocus () {
expect(document.activeElement).toEqual(this.portal.refs.content);
Simulate.keyDown(this.portal.refs.content, {
- // The keyCode is all that matters, so this works
- key: 'FakeKeyToTestLater',
- keyCode: 27,
- which: 27
+ // The keyCode is all that matters, so this works
+ key: 'esc',
+ keyCode: 27,
+ which: 27
});
});
});
-
it('does not focus the modal content when a descendent is already focused', function() {
var input = (
- { el && el.focus(); }}
- />
+ { el && el.focus(); }} />
);
renderModal({isOpen: true}, input, function () {
expect(document.activeElement).toEqual(document.querySelector('.focus_input'));
- unmountModal();
});
});
it('handles case when child has no tabbable elements', function() {
var component = renderModal({isOpen: true}, 'hello');
- expect(function() {
- Simulate.keyDown(component.portal.refs.content, {key: "Tab", keyCode: 9, which: 9})
- }).toNotThrow;
- unmountModal();
+ Simulate.keyDown(component.portal.refs.content, {key: "Tab", keyCode: 9, which: 9});
});
it('keeps focus inside the modal when child has no tabbable elements', function() {
@@ -174,72 +148,71 @@ describe('Modal', () => {
var modal = renderModal({isOpen: true}, 'hello');
expect(document.activeElement).toEqual(modal.portal.refs.content);
Simulate.keyDown(modal.portal.refs.content, {
- key: "Tab",
- keyCode: 9,
- which: 9,
- preventDefault: function() { tabPrevented = true; }
+ key: "Tab",
+ keyCode: 9,
+ which: 9,
+ preventDefault: function() { tabPrevented = true; }
});
expect(tabPrevented).toEqual(true);
- unmountModal();
});
it('supports portalClassName', function () {
var modal = renderModal({isOpen: true, portalClassName: 'myPortalClass'});
expect(modal.node.className).toEqual('myPortalClass');
- unmountModal();
});
- it('supports custom className', function() {
- var modal = renderModal({isOpen: true, className: 'myClass'});
- expect(modal.portal.refs.content.className.indexOf('myClass')).toNotEqual(-1);
- unmountModal();
+ it('supports custom className', () => {
+ const modal = renderModal({ isOpen: true, className: 'myClass' });
+ expect(
+ modal.portal.refs.content.className.indexOf('myClass')
+ ).toNotEqual(-1);
});
- it('supports overlayClassName', function () {
- var modal = renderModal({isOpen: true, overlayClassName: 'myOverlayClass'});
- expect(modal.portal.refs.overlay.className.indexOf('myOverlayClass')).toNotEqual(-1);
- unmountModal();
+ it('supports overlayClassName', () => {
+ const modal = renderModal({ isOpen: true, overlayClassName: 'myOverlayClass' });
+ expect(
+ modal.portal.refs.overlay.className.indexOf('myOverlayClass')
+ ).toNotEqual(-1);
});
- it('overrides the default styles when a custom classname is used', function () {
- var modal = renderModal({isOpen: true, className: 'myClass'});
+ it('overrides the default styles when a custom classname is used', () => {
+ const modal = renderModal({ isOpen: true, className: 'myClass' });
expect(modal.portal.refs.content.style.top).toEqual('');
- unmountModal();
});
- it('overrides the default styles when a custom overlayClassName is used', function () {
- var modal = renderModal({isOpen: true, overlayClassName: 'myOverlayClass'});
+ it('overrides the default styles when a custom overlayClassName is used', () => {
+ const modal = renderModal({ isOpen: true, overlayClassName: 'myOverlayClass' });
expect(modal.portal.refs.overlay.style.backgroundColor).toEqual('');
});
- it('supports adding style to the modal contents', function () {
- var modal = renderModal({isOpen: true, style: {content: {width: '20px'}}});
+ it('supports adding style to the modal contents', () => {
+ const modal = renderModal({ isOpen: true, style: { content: { width: '20px' } } });
expect(modal.portal.refs.content.style.width).toEqual('20px');
});
- it('supports overriding style on the modal contents', function() {
- var modal = renderModal({isOpen: true, style: {content: {position: 'static'}}});
+ it('supports overriding style on the modal contents', () => {
+ const modal = renderModal({ isOpen: true, style: { content: { position: 'static' } } });
expect(modal.portal.refs.content.style.position).toEqual('static');
});
- it('supports adding style on the modal overlay', function() {
- var modal = renderModal({isOpen: true, style: {overlay: {width: '75px'}}});
+ it('supports adding style on the modal overlay', () => {
+ const modal = renderModal({ isOpen: true, style: { overlay: { width: '75px' } } });
expect(modal.portal.refs.overlay.style.width).toEqual('75px');
});
- it('supports overriding style on the modal overlay', function() {
- var modal = renderModal({isOpen: true, style: {overlay: {position: 'static'}}});
+ it('supports overriding style on the modal overlay', () => {
+ const modal = renderModal({ isOpen: true, style: { overlay: { position: 'static' } } });
expect(modal.portal.refs.overlay.style.position).toEqual('static');
});
- it('supports overriding the default styles', function() {
- var previousStyle = Modal.defaultStyles.content.position
- //Just in case the default style is already relative, check that we can change it
- var newStyle = previousStyle === 'relative' ? 'static': 'relative'
- Modal.defaultStyles.content.position = newStyle
- var modal = renderModal({isOpen: true});
+ it('supports overriding the default styles', () => {
+ const previousStyle = Modal.defaultStyles.content.position;
+ // Just in case the default style is already relative, check that we can change it
+ const newStyle = previousStyle === 'relative' ? 'static' : 'relative';
+ Modal.defaultStyles.content.position = newStyle;
+ const modal = renderModal({ isOpen: true });
expect(modal.portal.refs.content.style.position).toEqual(newStyle);
- Modal.defaultStyles.content.position = previousStyle
+ Modal.defaultStyles.content.position = previousStyle;
});
it('adds class to body when open', function() {
@@ -280,19 +253,12 @@ describe('Modal', () => {
var content = document.querySelector('.ReactModal__Content');
expect(overlay.className.match(/ReactModal__Overlay--after-open/)).toExist();
expect(content.className.match(/ReactModal__Content--after-open/)).toExist();
- unmountModal();
});
it('should trigger the onAfterOpen callback', function() {
var afterOpenCallback = sinon.spy();
- renderModal({
- isOpen: true,
- onAfterOpen: function() {
- afterOpenCallback();
- }
- });
+ renderModal({ isOpen: true, onAfterOpen: afterOpenCallback });
expect(afterOpenCallback.called).toBeTruthy();
- unmountModal();
});
it('check the state of the modal after close with time out and reopen it', function() {
@@ -305,121 +271,120 @@ describe('Modal', () => {
modal.portal.open();
modal.portal.closeWithoutTimeout();
expect(!modal.portal.state.isOpen).toBeTruthy();
- unmountModal();
});
- describe('should close on overlay click', function() {
- afterEach('Unmount modal', function() {
- unmountModal();
- });
+ describe('should close on overlay click', () => {
+ afterEach('Unmount modal', emptyDOM);
- describe('verify props', function() {
- it('verify default prop of shouldCloseOnOverlayClick', function () {
- var modal = renderModal({isOpen: true});
- expect(modal.props.shouldCloseOnOverlayClick).toEqual(true);
+ describe('verify props', () => {
+ afterEach('Unmount modal', emptyDOM);
+
+ it('verify default prop of shouldCloseOnOverlayClick', () => {
+ const modal = renderModal({ isOpen: true });
+ expect(modal.props.shouldCloseOnOverlayClick).toEqual(true);
});
it('verify prop of shouldCloseOnOverlayClick', function () {
- var modal = renderModal({isOpen: true, shouldCloseOnOverlayClick: false});
- expect(modal.props.shouldCloseOnOverlayClick).toEqual(false);
+ var modal = renderModal({isOpen: true, shouldCloseOnOverlayClick: false});
+ expect(modal.props.shouldCloseOnOverlayClick).toEqual(false);
});
});
- describe('verify clicks', function() {
- it('verify overlay click when shouldCloseOnOverlayClick sets to false', function () {
- var requestCloseCallback = sinon.spy();
- var modal = renderModal({
- isOpen: true,
- shouldCloseOnOverlayClick: false
- });
- expect(modal.props.isOpen).toEqual(true);
- var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay');
- expect(overlay.length).toEqual(1);
- Simulate.click(overlay[0]); // click the overlay
- expect(!requestCloseCallback.called).toBeTruthy();
+ describe('verify clicks', () => {
+ afterEach('Unmount modal', emptyDOM);
+
+ it('verify overlay click when shouldCloseOnOverlayClick sets to false', () => {
+ const requestCloseCallback = sinon.spy();
+ const modal = renderModal({
+ isOpen: true,
+ shouldCloseOnOverlayClick: false
+ });
+ expect(modal.props.isOpen).toEqual(true);
+ var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay');
+ expect(overlay.length).toEqual(1);
+ Simulate.click(overlay[0]); // click the overlay
+ expect(!requestCloseCallback.called).toBeTruthy();
});
it('verify overlay click when shouldCloseOnOverlayClick sets to true', function() {
- var requestCloseCallback = sinon.spy();
- var modal = renderModal({
- isOpen: true,
- shouldCloseOnOverlayClick: true,
- onRequestClose: function() {
- requestCloseCallback();
- }
- });
- expect(modal.props.isOpen).toEqual(true);
- var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay');
- expect(overlay.length).toEqual(1);
- Simulate.click(overlay[0]); // click the overlay
- expect(requestCloseCallback.called).toBeTruthy();
+ var requestCloseCallback = sinon.spy();
+ var modal = renderModal({
+ isOpen: true,
+ shouldCloseOnOverlayClick: true,
+ onRequestClose: function() {
+ requestCloseCallback();
+ }
+ });
+ expect(modal.props.isOpen).toEqual(true);
+ var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay');
+ expect(overlay.length).toEqual(1);
+ Simulate.click(overlay[0]); // click the overlay
+ expect(requestCloseCallback.called).toBeTruthy();
});
- it('verify overlay mouse down and content mouse up when shouldCloseOnOverlayClick sets to true', function() {
- var requestCloseCallback = sinon.spy();
- var modal = renderModal({
- isOpen: true,
- shouldCloseOnOverlayClick: true,
- onRequestClose: function() {
- requestCloseCallback();
- }
- });
- expect(modal.props.isOpen).toEqual(true);
- var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay');
- var content = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Content');
- expect(overlay.length).toEqual(1);
- expect(content.length).toEqual(1);
- Simulate.mouseDown(overlay[0]); // click the overlay
- Simulate.mouseUp(content[0]);
- expect(!requestCloseCallback.called).toBeTruthy();
+ it('verify overlay mouse down and content mouse up when shouldCloseOnOverlayClick sets to true', () => {
+ const requestCloseCallback = sinon.spy();
+ const modal = renderModal({
+ isOpen: true,
+ shouldCloseOnOverlayClick: true,
+ onRequestClose: requestCloseCallback
+ });
+ expect(modal.props.isOpen).toEqual(true);
+ var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay');
+ var content = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Content');
+ expect(overlay.length).toEqual(1);
+ expect(content.length).toEqual(1);
+ Simulate.mouseDown(overlay[0]); // click the overlay
+ Simulate.mouseUp(content[0]);
+ expect(!requestCloseCallback.called).toBeTruthy();
});
it('verify content mouse down and overlay mouse up when shouldCloseOnOverlayClick sets to true', function() {
- var requestCloseCallback = sinon.spy();
- var modal = renderModal({
- isOpen: true,
- shouldCloseOnOverlayClick: true,
- onRequestClose: function() {
- requestCloseCallback();
- }
- });
- expect(modal.props.isOpen).toEqual(true);
- var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay');
- var content = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Content');
- expect(content.length).toEqual(1);
- expect(overlay.length).toEqual(1);
- Simulate.mouseDown(content[0]); // click the overlay
- Simulate.mouseUp(overlay[0]);
- expect(!requestCloseCallback.called).toBeTruthy();
+ var requestCloseCallback = sinon.spy();
+ var modal = renderModal({
+ isOpen: true,
+ shouldCloseOnOverlayClick: true,
+ onRequestClose: function() {
+ requestCloseCallback();
+ }
+ });
+ expect(modal.props.isOpen).toEqual(true);
+ var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay');
+ var content = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Content');
+ expect(content.length).toEqual(1);
+ expect(overlay.length).toEqual(1);
+ Simulate.mouseDown(content[0]); // click the overlay
+ Simulate.mouseUp(overlay[0]);
+ expect(!requestCloseCallback.called).toBeTruthy();
});
it('should not stop event propagation', function() {
- var hasPropagated = false
- var modal = renderModal({
- isOpen: true,
- shouldCloseOnOverlayClick: true
- });
- var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay');
- window.addEventListener('click', function () { hasPropagated = true })
- overlay[0].dispatchEvent(new MouseEvent('click', { bubbles: true }))
- expect(hasPropagated).toBeTruthy();
+ var hasPropagated = false
+ var modal = renderModal({
+ isOpen: true,
+ shouldCloseOnOverlayClick: true
+ });
+ var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay');
+ window.addEventListener('click', function () { hasPropagated = true })
+ overlay[0].dispatchEvent(new MouseEvent('click', { bubbles: true }))
+ expect(hasPropagated).toBeTruthy();
});
});
it('verify event passing on overlay click', function() {
var requestCloseCallback = sinon.spy();
var modal = renderModal({
- isOpen: true,
- shouldCloseOnOverlayClick: true,
- onRequestClose: requestCloseCallback
+ isOpen: true,
+ shouldCloseOnOverlayClick: true,
+ onRequestClose: requestCloseCallback
});
expect(modal.props.isOpen).toEqual(true);
var overlay = TestUtils.scryRenderedDOMComponentsWithClass(modal.portal, 'ReactModal__Overlay');
expect(overlay.length).toEqual(1);
// click the overlay
Simulate.click(overlay[0], {
- // Used to test that this was the event received
- fakeData: 'ABC'
+ // Used to test that this was the event received
+ fakeData: 'ABC'
});
expect(requestCloseCallback.called).toBeTruthy();
// Check if event is passed to onRequestClose callback.
@@ -438,9 +403,7 @@ describe('Modal', () => {
onRequestClose: requestCloseCallback
});
expect(modal.props.isOpen).toEqual(true);
- expect(function() {
- Simulate.keyDown(modal.portal.refs.content, {key: "Esc", keyCode: 27, which: 27})
- }).toNotThrow();
+ Simulate.keyDown(modal.portal.refs.content, {key: "Esc", keyCode: 27, which: 27})
expect(requestCloseCallback.called).toBeTruthy();
// Check if event is passed to onRequestClose callback.
var event = requestCloseCallback.getCall(0).args[0];
@@ -455,7 +418,6 @@ describe('Modal', () => {
isOpen: true,
closeTimeoutMS
});
-
modal.portal.closeWithTimeout();
const overlay = TestUtils.findRenderedDOMComponentWithClass(modal.portal, 'ReactModal__Overlay');
@@ -465,33 +427,27 @@ describe('Modal', () => {
expect(/ReactModal__Content--before-close/.test(content.className)).toBe(true);
modal.portal.closeWithoutTimeout();
- unmountModal();
});
it('keeps the modal in the DOM until closeTimeoutMS elapses', (done) => {
- const closeTimeoutMS = 50;
+ const closeTimeoutMS = 100;
- renderModal({
- isOpen: true,
- closeTimeoutMS
- });
-
- unmountModal();
+ const modal = renderModal({ isOpen: true, closeTimeoutMS });
+ modal.portal.closeWithTimeout();
- const checkDOM = (expectMounted) => {
+ function checkDOM(count) {
const overlay = document.querySelectorAll('.ReactModal__Overlay');
const content = document.querySelectorAll('.ReactModal__Content');
- const numNodes = expectMounted ? 1 : 0;
- expect(overlay.length).toBe(numNodes);
- expect(content.length).toBe(numNodes);
- };
+ expect(overlay.length).toBe(count);
+ expect(content.length).toBe(count);
+ }
// content is still mounted after modal is gone
- checkDOM(true);
+ checkDOM(1);
setTimeout(() => {
// content is unmounted after specified timeout
- checkDOM(false);
+ checkDOM(0);
done();
}, closeTimeoutMS);
});
diff --git a/specs/helper.js b/specs/helper.js
index e21def25..f50fbab2 100644
--- a/specs/helper.js
+++ b/specs/helper.js
@@ -20,3 +20,9 @@ export const unmountModal = function() {
ReactDOM.unmountComponentAtNode(currentDiv);
document.body.removeChild(currentDiv);
};
+
+export const emptyDOM = () => {
+ while (divStack.length) {
+ unmountModal();
+ }
+};