Skip to content

Commit

Permalink
Merge dee03b7 into 88d2ae1
Browse files Browse the repository at this point in the history
  • Loading branch information
fuller committed Jun 16, 2017
2 parents 88d2ae1 + dee03b7 commit 40aa1d0
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 113 deletions.
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,8 @@
"karma-webpack": "^1.8.1",
"mocha": "3.2.0",
"npm-run-all": "^3.1.2",
"react": "^15.0.0",
"react-addons-test-utils": "^15.0.0",
"react-dom": "^15.0.0",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"rf-release": "0.4.0",
"sinon": "next",
"uglify-js": "2.4.24",
Expand All @@ -64,7 +63,7 @@
"dependencies": {
"element-class": "^0.2.0",
"exenv": "1.2.0",
"prop-types": "^15.5.7",
"prop-types": "^15.5.10",
"react-dom-factories": "^1.0.0"
},
"peerDependencies": {
Expand Down
17 changes: 12 additions & 5 deletions specs/Modal.events.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ import sinon from 'sinon';
import expect from 'expect';
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
import Modal from '../src/components/Modal';
import {
moverlay, mcontent,
clickAt, mouseDownAt, mouseUpAt, escKeyDown, tabKeyDown,
renderModal, emptyDOM
moverlay,
mcontent,
clickAt,
mouseDownAt,
mouseUpAt,
escKeyDown,
tabKeyDown,
renderModal,
emptyDOM
} from './helper';

describe('Events', () => {
Expand All @@ -26,7 +31,9 @@ describe('Events', () => {
const content = mcontent(modal);
expect(document.activeElement).toEqual(content);
tabKeyDown(content, {
preventDefault() { tabPrevented = true; }
preventDefault() {
tabPrevented = true;
}
});
expect(tabPrevented).toEqual(true);
});
Expand Down
149 changes: 75 additions & 74 deletions specs/Modal.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
import expect from 'expect';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
import Modal from '../src/components/Modal';
import * as ariaAppHider from '../src/helpers/ariaAppHider';
import {
isBodyWithReactModalOpenClass,
contentAttribute,
mcontent, moverlay,
mcontent,
moverlay,
escKeyDown,
renderModal, unmountModal, emptyDOM
renderModal,
unmountModal,
emptyDOM
} from './helper';

describe('State', () => {
Expand Down Expand Up @@ -41,15 +43,13 @@ describe('State', () => {
expect(props.shouldCloseOnOverlayClick).toBe(true);
ReactDOM.unmountComponentAtNode(node);
ariaAppHider.resetForTesting();
Modal.setAppElement(document.body); // restore default
Modal.setAppElement(document.body); // restore default
});

it('accepts appElement as a prop', () => {
const el = document.createElement('div');
const node = document.createElement('div');
ReactDOM.render((
<Modal isOpen={true} appElement={el} />
), node);
ReactDOM.render(<Modal isOpen={true} appElement={el} />, node);
expect(el.getAttribute('aria-hidden')).toEqual('true');
ReactDOM.unmountComponentAtNode(node);
});
Expand All @@ -69,11 +69,7 @@ describe('State', () => {
}
Modal.setAppElement(node);
ReactDOM.render(<App />, node);
expect(
document.body.querySelector('.ReactModalPortal').parentNode
).toEqual(
document.body
);
expect(document.body.querySelector('.ReactModalPortal').parentNode).toEqual(document.body);
ReactDOM.unmountComponentAtNode(node);
});

Expand All @@ -85,13 +81,14 @@ describe('State', () => {

it('set aria-label based on the contentLabel prop', () => {
const child = 'I am a child of Modal, and he has sent me here...';
const modal = renderModal({
isOpen: true,
contentLabel: 'Special Modal'
}, child);
expect(
contentAttribute(modal, 'aria-label')
).toEqual('Special Modal');
const modal = renderModal(
{
isOpen: true,
contentLabel: 'Special Modal'
},
child
);
expect(contentAttribute(modal, 'aria-label')).toEqual('Special Modal');
});

it('removes the portal node', () => {
Expand All @@ -106,37 +103,48 @@ describe('State', () => {
});

it('give back focus to previous element or modal.', done => {
function cleanup () {
function cleanup() {
unmountModal();
done();
}
const modalA = renderModal({
isOpen: true,
className: 'modal-a',
onRequestClose: cleanup
}, null);
const modalA = renderModal(
{
isOpen: true,
className: 'modal-a',
onRequestClose: cleanup
},
null
);

const modalContent = mcontent(modalA);
expect(document.activeElement).toEqual(modalContent);

const modalB = renderModal({
isOpen: true,
className: 'modal-b',
onRequestClose() {
const modalContent = mcontent(modalB);
expect(document.activeElement).toEqual(mcontent(modalA));
escKeyDown(modalContent);
expect(document.activeElement).toEqual(modalContent);
}
}, null);
const modalB = renderModal(
{
isOpen: true,
className: 'modal-b',
onRequestClose() {
const modalContent = mcontent(modalB);
expect(document.activeElement).toEqual(mcontent(modalA));
escKeyDown(modalContent);
expect(document.activeElement).toEqual(modalContent);
}
},
null
);

escKeyDown(modalContent);
});

it('does not steel focus when a descendent is already focused', () => {
let content;
const input = (
<input ref={(el) => { el && el.focus(); content = el; }} />
<input
ref={el => {
el && el.focus();
content = el;
}}
/>
);
renderModal({ isOpen: true }, input, () => {
expect(document.activeElement).toEqual(content);
Expand All @@ -153,19 +161,15 @@ describe('State', () => {

it('supports custom className', () => {
const modal = renderModal({ isOpen: true, className: 'myClass' });
expect(
mcontent(modal).className.includes('myClass')
).toBeTruthy();
expect(mcontent(modal).className.includes('myClass')).toBeTruthy();
});

it('supports overlayClassName', () => {
const modal = renderModal({
isOpen: true,
overlayClassName: 'myOverlayClass'
});
expect(
moverlay(modal).className.includes('myOverlayClass')
).toBeTruthy();
expect(moverlay(modal).className.includes('myOverlayClass')).toBeTruthy();
});

it('overrides content classes with custom object className', () => {
Expand All @@ -177,11 +181,7 @@ describe('State', () => {
beforeClose: 'myClass_before-close'
}
});
expect(
mcontent(modal).className
).toEqual(
'myClass myClass_after-open'
);
expect(mcontent(modal).className).toEqual('myClass myClass_after-open');
unmountModal();
});

Expand All @@ -194,11 +194,7 @@ describe('State', () => {
beforeClose: 'myOverlayClass_before-close'
}
});
expect(
moverlay(modal).className
).toEqual(
'myOverlayClass myOverlayClass_after-open'
);
expect(moverlay(modal).className).toEqual('myOverlayClass myOverlayClass_after-open');
unmountModal();
});

Expand All @@ -207,12 +203,10 @@ describe('State', () => {
isOpen: true,
bodyOpenClassName: 'custom-modal-open'
});
expect(
document.body.className.indexOf('custom-modal-open') > -1
).toBeTruthy();
expect(document.body.className.indexOf('custom-modal-open') > -1).toBeTruthy();
});

it('don\'t append class to document.body if modal is not open', () => {
it("don't append class to document.body if modal is not open", () => {
renderModal({ isOpen: false });
expect(!isBodyWithReactModalOpenClass()).toBeTruthy();
unmountModal();
Expand Down Expand Up @@ -243,9 +237,7 @@ describe('State', () => {
it('removes aria-hidden from appElement when unmounted w/o closing', () => {
const el = document.createElement('div');
const node = document.createElement('div');
ReactDOM.render((
<Modal isOpen appElement={el} />
), node);
ReactDOM.render(<Modal isOpen appElement={el} />, node);
expect(el.getAttribute('aria-hidden')).toEqual('true');
ReactDOM.unmountComponentAtNode(node);
expect(el.getAttribute('aria-hidden')).toEqual(null);
Expand Down Expand Up @@ -312,30 +304,35 @@ describe('State', () => {
// content is still mounted after modal is gone
checkDOM(1);

setTimeout(() => {
// content is unmounted after specified timeout
checkDOM(0);
done();
}, closeTimeoutMS);
setTimeout(
() => {
// content is unmounted after specified timeout
checkDOM(0);
done();
},
closeTimeoutMS
);
});

it('shouldn\'t throw if forcibly unmounted during mounting', () => {
it("shouldn't throw if forcibly unmounted during mounting", () => {
/* eslint-disable camelcase, react/prop-types */
class Wrapper extends Component {
constructor (props) {
constructor(props) {
super(props);
this.state = { error: false };
}
unstable_handleError () {
unstable_handleError() {
this.setState({ error: true });
}
render () {
return this.state.error ? null : <div>{ this.props.children }</div>;
render() {
return this.state.error ? null : <div>{this.props.children}</div>;
}
}
/* eslint-enable camelcase, react/prop-types */

const Throw = () => { throw new Error('reason'); };
const Throw = () => {
throw new Error('reason');
};
const TestCase = () => (
<Wrapper>
<Modal />
Expand Down Expand Up @@ -375,15 +372,19 @@ describe('State', () => {
}

render() {
const portalClassName = this.state.testHasChanged === true ?
'myPortalClass-modifier' : 'myPortalClass';
const portalClassName = this.state.testHasChanged === true
? 'myPortalClass-modifier'
: 'myPortalClass';

return (
<div>
<Modal
ref={modalComponent => { modal = modalComponent; }}
ref={modalComponent => {
modal = modalComponent;
}}
isOpen
portalClassName={portalClassName}>
portalClassName={portalClassName}
>
<span>Test</span>
</Modal>
</div>
Expand Down
22 changes: 8 additions & 14 deletions specs/Modal.style.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@
import expect from 'expect';
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
import Modal from '../src/components/Modal';
import * as ariaAppHider from '../src/helpers/ariaAppHider';
import {
mcontent, moverlay,
renderModal, emptyDOM
} from './helper';
import { mcontent, moverlay, renderModal, emptyDOM } from './helper';

describe('Style', () => {
afterEach('Unmount modal', emptyDOM);
Expand All @@ -18,15 +14,13 @@ describe('Style', () => {
expect(mcontent(modal).style.top).toEqual('');
});

it('overrides the default styles when a custom overlayClassName is used',
() => {
const modal = renderModal({
isOpen: true,
overlayClassName: 'myOverlayClass'
});
expect(moverlay(modal).style.backgroundColor).toEqual('');
}
);
it('overrides the default styles when a custom overlayClassName is used', () => {
const modal = renderModal({
isOpen: true,
overlayClassName: 'myOverlayClass'
});
expect(moverlay(modal).style.backgroundColor).toEqual('');
});

it('supports adding style to the modal contents', () => {
const style = { content: { width: '20px' } };
Expand Down
Loading

0 comments on commit 40aa1d0

Please sign in to comment.