Repository: mui/material-ui (TypeScript) — Bug Fix

Issue:
Drawer with keepMounted has incorrect aria-hidden value
<!--- Provide a general summary of the issue in the Title above -->
When using the following snippet:

```jsx
<Drawer
    variant="temporary"
    ModalProps={{
        keepMounted: true
    }}
    {..other}
/>
```

The `aria-hidden` attribute logic gets applied incorrectly.

<!-- Checked checkbox should look like this: [x] -->
- [x] This is a v1.x issue. <!-- (v0.x is no longer maintained) -->
- [x] I have searched the [issues](https://github.com/mui-org/material-ui/issues) of this repository and believe that this is not a duplicate.

## Expected Behavior

When the drawer is open, the content gets `aria-hidden="true"` and drawer modal gets `aria-hidden="false"`.
When drawer is closed, the content gets `aria-hidden="false"` and drawer modal gets `aria-hidden="true"`.

## Current Behavior

When the drawer is open, the both the content and drawer modal get `aria-hidden="true"` (resulting in a screen reader stating that there is no content).
When drawer is closed, both the content and drawer modal get `aria-hidden="false"`.

![Looping GIF demonstrating the issue](https://user-images.githubusercontent.com/65596/44816607-fd929200-abe2-11e8-869e-0cea5f03ec7a.gif)


## Steps to Reproduce
<!---
    Provide a link to a live example (you can use codesandbox.io) and an unambiguous set of steps to reproduce this bug.
    Include code to reproduce, if relevant (which it most likely is).

    This codesandbox.io template _may_ be a good starting point:
    https://codesandbox.io/s/github/mui-org/material-ui/tree/master/examples/create-react-app

    If you're using typescript a better starting point would be
    https://codesandbox.io/s/github/mui-org/material-ui/tree/master/examples/create-react-app-with-typescript

    If YOU DO NOT take time to provide a codesandbox.io reproduction, should the COMMUNITY take time to help you?

-->
Link: https://material-ui.com/

1. Open drawer
2. Open dev-tools
3. Check aria-hidden attributes for drawer modal & content
4. Close drawer
5. Recheck aria-hidden attributes for drawer modal & content


## Context

To make temporary drawer apps friendly to screen readers.

## Your Environment

| Tech         | Version |
|--------------|---------|
| Material-UI  | v1.4.2  |
| React        |  v16.4.0 |
| TypeScript   | 3.0.1    |
| etc.         |         |



Discussion:

Resolving patch:
diff --git a/docs/src/pages/demos/cards/ImgMediaCard.js b/docs/src/pages/demos/cards/ImgMediaCard.js
--- a/docs/src/pages/demos/cards/ImgMediaCard.js
+++ b/docs/src/pages/demos/cards/ImgMediaCard.js
@@ -14,7 +14,7 @@ const styles = {
     maxWidth: 345,
   },
   media: {
-    // ⚠️ object-fit is not supported by IE11.
+    // ⚠️ object-fit is not supported by IE 11.
     objectFit: 'cover',
   },
 };
diff --git a/docs/src/pages/page-layout-examples/sign-in/SignIn.js b/docs/src/pages/page-layout-examples/sign-in/SignIn.js
--- a/docs/src/pages/page-layout-examples/sign-in/SignIn.js
+++ b/docs/src/pages/page-layout-examples/sign-in/SignIn.js
@@ -16,7 +16,7 @@ import withStyles from '@material-ui/core/styles/withStyles';
 const styles = theme => ({
   layout: {
     width: 'auto',
-    display: 'block', // Fix IE11 issue.
+    display: 'block', // Fix IE 11 issue.
     marginLeft: theme.spacing.unit * 3,
     marginRight: theme.spacing.unit * 3,
     [theme.breakpoints.up(400 + theme.spacing.unit * 3 * 2)]: {
@@ -37,7 +37,7 @@ const styles = theme => ({
     backgroundColor: theme.palette.secondary.main,
   },
   form: {
-    width: '100%', // Fix IE11 issue.
+    width: '100%', // Fix IE 11 issue.
     marginTop: theme.spacing.unit,
   },
   submit: {
diff --git a/packages/material-ui/src/Avatar/Avatar.js b/packages/material-ui/src/Avatar/Avatar.js
--- a/packages/material-ui/src/Avatar/Avatar.js
+++ b/packages/material-ui/src/Avatar/Avatar.js
@@ -31,7 +31,7 @@ export const styles = theme => ({
     width: '100%',
     height: '100%',
     textAlign: 'center',
-    // Handle non-square image. The property isn't supported by IE11.
+    // Handle non-square image. The property isn't supported by IE 11.
     objectFit: 'cover',
   },
 });
diff --git a/packages/material-ui/src/ClickAwayListener/ClickAwayListener.js b/packages/material-ui/src/ClickAwayListener/ClickAwayListener.js
--- a/packages/material-ui/src/ClickAwayListener/ClickAwayListener.js
+++ b/packages/material-ui/src/ClickAwayListener/ClickAwayListener.js
@@ -30,7 +30,7 @@ class ClickAwayListener extends React.Component {
       return;
     }
 
-    // IE11 support, which trigger the handleClickAway even after the unbind
+    // IE 11 support, which trigger the handleClickAway even after the unbind
     if (!this.mounted) {
       return;
     }
diff --git a/packages/material-ui/src/Dialog/Dialog.js b/packages/material-ui/src/Dialog/Dialog.js
--- a/packages/material-ui/src/Dialog/Dialog.js
+++ b/packages/material-ui/src/Dialog/Dialog.js
@@ -30,7 +30,7 @@ export const styles = theme => ({
     flexDirection: 'column',
     margin: 48,
     position: 'relative',
-    overflowY: 'auto', // Fix IE11 issue, to remove at some point.
+    overflowY: 'auto', // Fix IE 11 issue, to remove at some point.
     // We disable the focus ring for mouse, touch and keyboard users.
     outline: 'none',
   },
diff --git a/packages/material-ui/src/FilledInput/FilledInput.js b/packages/material-ui/src/FilledInput/FilledInput.js
--- a/packages/material-ui/src/FilledInput/FilledInput.js
+++ b/packages/material-ui/src/FilledInput/FilledInput.js
@@ -37,7 +37,7 @@ export const styles = theme => {
         borderBottom: `2px solid ${theme.palette.primary[light ? 'dark' : 'light']}`,
         left: 0,
         bottom: 0,
-        // Doing the other way around crash on IE11 "''" https://github.com/cssinjs/jss/issues/242
+        // Doing the other way around crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
         content: '""',
         position: 'absolute',
         right: 0,
@@ -59,7 +59,7 @@ export const styles = theme => {
         borderBottom: `1px solid ${bottomLineColor}`,
         left: 0,
         bottom: 0,
-        // Doing the other way around crash on IE11 "''" https://github.com/cssinjs/jss/issues/242
+        // Doing the other way around crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
         content: '"\\00a0"',
         position: 'absolute',
         right: 0,
diff --git a/packages/material-ui/src/IconButton/IconButton.js b/packages/material-ui/src/IconButton/IconButton.js
--- a/packages/material-ui/src/IconButton/IconButton.js
+++ b/packages/material-ui/src/IconButton/IconButton.js
@@ -16,7 +16,7 @@ export const styles = theme => ({
     fontSize: theme.typography.pxToRem(24),
     padding: 12,
     borderRadius: '50%',
-    overflow: 'visible', // Explicitly set the default value to solve a bug on IE11.
+    overflow: 'visible', // Explicitly set the default value to solve a bug on IE 11.
     color: theme.palette.action.active,
     transition: theme.transitions.create('background-color', {
       duration: theme.transitions.duration.shortest,
diff --git a/packages/material-ui/src/Input/Input.js b/packages/material-ui/src/Input/Input.js
--- a/packages/material-ui/src/Input/Input.js
+++ b/packages/material-ui/src/Input/Input.js
@@ -31,7 +31,7 @@ export const styles = theme => {
         borderBottom: `2px solid ${theme.palette.primary[light ? 'dark' : 'light']}`,
         left: 0,
         bottom: 0,
-        // Doing the other way around crash on IE11 "''" https://github.com/cssinjs/jss/issues/242
+        // Doing the other way around crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
         content: '""',
         position: 'absolute',
         right: 0,
@@ -53,7 +53,7 @@ export const styles = theme => {
         borderBottom: `1px solid ${bottomLineColor}`,
         left: 0,
         bottom: 0,
-        // Doing the other way around crash on IE11 "''" https://github.com/cssinjs/jss/issues/242
+        // Doing the other way around crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
         content: '"\\00a0"',
         position: 'absolute',
         right: 0,
diff --git a/packages/material-ui/src/InputBase/InputBase.js b/packages/material-ui/src/InputBase/InputBase.js
--- a/packages/material-ui/src/InputBase/InputBase.js
+++ b/packages/material-ui/src/InputBase/InputBase.js
@@ -76,7 +76,7 @@ export const styles = theme => {
       display: 'block',
       // Make the flex item shrink with Firefox
       minWidth: 0,
-      width: '100%', // Fix IE11 width issue
+      width: '100%', // Fix IE 11 width issue
       '&::-webkit-input-placeholder': placeholder,
       '&::-moz-placeholder': placeholder, // Firefox 19+
       '&:-ms-input-placeholder': placeholder, // IE 11
@@ -222,7 +222,7 @@ class InputBase extends React.Component {
   }
 
   handleFocus = event => {
-    // Fix a bug with IE11 where the focus/blur events are triggered
+    // Fix a bug with IE 11 where the focus/blur events are triggered
     // while the input is disabled.
     if (
       formControlState({ props: this.props, context: this.context, states: ['disabled'] }).disabled
diff --git a/packages/material-ui/src/Modal/Modal.js b/packages/material-ui/src/Modal/Modal.js
--- a/packages/material-ui/src/Modal/Modal.js
+++ b/packages/material-ui/src/Modal/Modal.js
@@ -64,7 +64,8 @@ class Modal extends React.Component {
 
   componentDidUpdate(prevProps) {
     if (!prevProps.open && this.props.open) {
-      this.checkForFocus();
+      // check for focus
+      this.lastFocus = ownerDocument(this.mountNode).activeElement;
     }
 
     if (prevProps.open && !this.props.open && !getHasTransition(this.props)) {
@@ -100,31 +101,50 @@ class Modal extends React.Component {
     return null;
   }
 
-  handleRendered = () => {
-    this.autoFocus();
+  handleOpen = () => {
+    const doc = ownerDocument(this.mountNode);
+    const container = getContainer(this.props.container, doc.body);
 
-    // Fix a bug on Chrome where the scroll isn't initially 0.
-    this.modalRef.scrollTop = 0;
+    this.props.manager.add(this, container);
+    doc.addEventListener('keydown', this.handleDocumentKeyDown);
+    doc.addEventListener('focus', this.enforceFocus, true);
 
+    if (this.dialogRef) {
+      this.handleOpened();
+    }
+  };
+
+  handleRendered = () => {
     if (this.props.onRendered) {
       this.props.onRendered();
     }
+
+    if (this.props.open) {
+      this.handleOpened();
+    } else {
+      const doc = ownerDocument(this.mountNode);
+      const container = getContainer(this.props.container, doc.body);
+      this.props.manager.add(this, container);
+      this.props.manager.remove(this);
+    }
   };
 
-  handleOpen = () => {
-    const doc = ownerDocument(this.mountNode);
-    const container = getContainer(this.props.container, doc.body);
+  handleOpened = () => {
+    this.autoFocus();
 
-    this.props.manager.add(this, container);
-    doc.addEventListener('keydown', this.handleDocumentKeyDown);
-    doc.addEventListener('focus', this.enforceFocus, true);
+    // Fix a bug on Chrome where the scroll isn't initially 0.
+    this.modalRef.scrollTop = 0;
   };
 
+  handleDisplay = () => {};
+
   handleClose = () => {
     this.props.manager.remove(this);
+
     const doc = ownerDocument(this.mountNode);
     doc.removeEventListener('keydown', this.handleDocumentKeyDown);
     doc.removeEventListener('focus', this.enforceFocus, true);
+
     this.restoreLastFocus();
   };
 
@@ -148,12 +168,8 @@ class Modal extends React.Component {
   };
 
   handleDocumentKeyDown = event => {
-    if (!this.isTopModal() || keycode(event) !== 'esc') {
-      return;
-    }
-
     // Ignore events that have been `event.preventDefault()` marked.
-    if (event.defaultPrevented) {
+    if (keycode(event) !== 'esc' || !this.isTopModal() || event.defaultPrevented) {
       return;
     }
 
@@ -166,32 +182,28 @@ class Modal extends React.Component {
     }
   };
 
-  checkForFocus = () => {
-    this.lastFocus = ownerDocument(this.mountNode).activeElement;
-  };
-
   enforceFocus = () => {
-    if (this.props.disableEnforceFocus || !this.mounted || !this.isTopModal()) {
+    // The Modal might not already be mounted.
+    if (!this.isTopModal() || this.props.disableEnforceFocus || !this.mounted || !this.dialogRef) {
       return;
     }
 
     const currentActiveElement = ownerDocument(this.mountNode).activeElement;
 
-    if (this.dialogRef && !this.dialogRef.contains(currentActiveElement)) {
+    if (!this.dialogRef.contains(currentActiveElement)) {
       this.dialogRef.focus();
     }
   };
 
   autoFocus() {
-    if (this.props.disableAutoFocus) {
+    // We might render an empty child.
+    if (this.props.disableAutoFocus || !this.dialogRef) {
       return;
     }
 
     const currentActiveElement = ownerDocument(this.mountNode).activeElement;
 
-    if (this.dialogRef && !this.dialogRef.contains(currentActiveElement)) {
-      this.lastFocus = currentActiveElement;
-
+    if (!this.dialogRef.contains(currentActiveElement)) {
       if (!this.dialogRef.hasAttribute('tabIndex')) {
         warning(
           false,
@@ -204,25 +216,24 @@ class Modal extends React.Component {
         this.dialogRef.setAttribute('tabIndex', -1);
       }
 
+      this.lastFocus = currentActiveElement;
       this.dialogRef.focus();
     }
   }
 
   restoreLastFocus() {
-    if (this.props.disableRestoreFocus) {
+    if (this.props.disableRestoreFocus || !this.lastFocus) {
       return;
     }
 
-    if (this.lastFocus) {
-      // Not all elements in IE11 have a focus method.
-      // Because IE11 market share is low, we accept the restore focus being broken
-      // and we silent the issue.
-      if (this.lastFocus.focus) {
-        this.lastFocus.focus();
-      }
-
-      this.lastFocus = null;
+    // Not all elements in IE 11 have a focus method.
+    // Because IE 11 market share is low, we accept the restore focus being broken
+    // and we silent the issue.
+    if (this.lastFocus.focus) {
+      this.lastFocus.focus();
     }
+
+    this.lastFocus = null;
   }
 
   isTopModal() {
@@ -255,12 +266,13 @@ class Modal extends React.Component {
     } = this.props;
     const { exited } = this.state;
     const hasTransition = getHasTransition(this.props);
-    const childProps = {};
 
     if (!keepMounted && !open && (!hasTransition || exited)) {
       return null;
     }
 
+    const childProps = {};
+
     // It's a Transition like component
     if (hasTransition) {
       childProps.onExited = createChainedFunction(this.handleExited, children.props.onExited);
@@ -414,6 +426,7 @@ Modal.propTypes = {
 };
 
 Modal.defaultProps = {
+  BackdropComponent: Backdrop,
   disableAutoFocus: false,
   disableBackdropClick: false,
   disableEnforceFocus: false,
@@ -424,7 +437,6 @@ Modal.defaultProps = {
   keepMounted: false,
   // Modals don't open on the server so this won't conflict with concurrent requests.
   manager: new ModalManager(),
-  BackdropComponent: Backdrop,
 };
 
 export default withStyles(styles, { flip: false, name: 'MuiModal' })(Modal);
diff --git a/packages/material-ui/src/Modal/ModalManager.js b/packages/material-ui/src/Modal/ModalManager.js
--- a/packages/material-ui/src/Modal/ModalManager.js
+++ b/packages/material-ui/src/Modal/ModalManager.js
@@ -2,7 +2,7 @@ import css from 'dom-helpers/style';
 import getScrollbarSize from 'dom-helpers/util/scrollbarSize';
 import ownerDocument from '../utils/ownerDocument';
 import isOverflowing from './isOverflowing';
-import { ariaHidden, hideSiblings, showSiblings } from './manageAriaHidden';
+import { ariaHidden, ariaHiddenSiblings } from './manageAriaHidden';
 
 function findIndexOf(data, callback) {
   let idx = -1;
@@ -93,8 +93,12 @@ class ModalManager {
     modalIdx = this.modals.length;
     this.modals.push(modal);
 
+    // If the modal we are adding is already in the DOM.
+    if (modal.modalRef) {
+      ariaHidden(modal.modalRef, false);
+    }
     if (this.hideSiblingNodes) {
-      hideSiblings(container, modal.mountNode);
+      ariaHiddenSiblings(container, modal.mountNode, modal.modalRef, true);
     }
 
     const containerIdx = this.containers.indexOf(container);
@@ -139,14 +143,18 @@ class ModalManager {
         removeContainerStyle(data, container);
       }
 
+      // In case the modal wasn't in the DOM yet.
+      if (modal.modalRef) {
+        ariaHidden(modal.modalRef, true);
+      }
       if (this.hideSiblingNodes) {
-        showSiblings(container, modal.mountNode);
+        ariaHiddenSiblings(container, modal.mountNode, modal.modalRef, false);
       }
       this.containers.splice(containerIdx, 1);
       this.data.splice(containerIdx, 1);
     } else if (this.hideSiblingNodes) {
       // Otherwise make sure the next top modal is visible to a screan reader.
-      ariaHidden(false, data.modals[data.modals.length - 1].mountNode);
+      ariaHidden(data.modals[data.modals.length - 1].modalRef, false);
     }
 
     return modalIdx;
diff --git a/packages/material-ui/src/Modal/manageAriaHidden.js b/packages/material-ui/src/Modal/manageAriaHidden.js
--- a/packages/material-ui/src/Modal/manageAriaHidden.js
+++ b/packages/material-ui/src/Modal/manageAriaHidden.js
@@ -4,19 +4,17 @@ function isHidable(node) {
   return node.nodeType === 1 && BLACKLIST.indexOf(node.tagName.toLowerCase()) === -1;
 }
 
-function siblings(container, mount, callback) {
-  mount = [].concat(mount); // eslint-disable-line no-param-reassign
+function siblings(container, mount, currentNode, callback) {
+  const blacklist = [mount, currentNode]; // eslint-disable-line no-param-reassign
+
   [].forEach.call(container.children, node => {
-    if (mount.indexOf(node) === -1 && isHidable(node)) {
+    if (blacklist.indexOf(node) === -1 && isHidable(node)) {
       callback(node);
     }
   });
 }
 
-export function ariaHidden(show, node) {
-  if (!node) {
-    return;
-  }
+export function ariaHidden(node, show) {
   if (show) {
     node.setAttribute('aria-hidden', 'true');
   } else {
@@ -24,10 +22,6 @@ export function ariaHidden(show, node) {
   }
 }
 
-export function hideSiblings(container, mountNode) {
-  siblings(container, mountNode, node => ariaHidden(true, node));
-}
-
-export function showSiblings(container, mountNode) {
-  siblings(container, mountNode, node => ariaHidden(false, node));
+export function ariaHiddenSiblings(container, mountNode, currentNode, show) {
+  siblings(container, mountNode, currentNode, node => ariaHidden(node, show));
 }
diff --git a/packages/material-ui/src/NativeSelect/NativeSelect.js b/packages/material-ui/src/NativeSelect/NativeSelect.js
--- a/packages/material-ui/src/NativeSelect/NativeSelect.js
+++ b/packages/material-ui/src/NativeSelect/NativeSelect.js
@@ -37,7 +37,7 @@ export const styles = theme => ({
       color: 'transparent',
       textShadow: '0 0 0 #000',
     },
-    // Remove IE11 arrow
+    // Remove IE 11 arrow
     '&::-ms-expand': {
       display: 'none',
     },
diff --git a/packages/material-ui/src/utils/getDisplayName.js b/packages/material-ui/src/utils/getDisplayName.js
--- a/packages/material-ui/src/utils/getDisplayName.js
+++ b/packages/material-ui/src/utils/getDisplayName.js
@@ -1,6 +1,6 @@
-// Fork of recompose/getDisplayName with added IE11 support
+// Fork of recompose/getDisplayName with added IE 11 support
 
-// Simplified polyfill for IE11 support
+// Simplified polyfill for IE 11 support
 // https://github.com/JamesMGreene/Function.name/blob/58b314d4a983110c3682f1228f845d39ccca1817/Function.name.js#L3
 const fnNameMatchRegex = /^\s*function(?:\s|\s*\/\*.*\*\/\s*)+([^(\s/]*)\s*/;
 export function getFunctionName(fn) {


Test patch:
diff --git a/packages/material-ui/src/ClickAwayListener/ClickAwayListener.test.js b/packages/material-ui/src/ClickAwayListener/ClickAwayListener.test.js
--- a/packages/material-ui/src/ClickAwayListener/ClickAwayListener.test.js
+++ b/packages/material-ui/src/ClickAwayListener/ClickAwayListener.test.js
@@ -155,7 +155,7 @@ describe('<ClickAwayListener />', () => {
     });
   });
 
-  describe('IE11 issue', () => {
+  describe('IE 11 issue', () => {
     it('should not call the hook if the event is triggered after being unmounted', () => {
       const handleClickAway = spy();
       wrapper = mount(
diff --git a/packages/material-ui/src/InputBase/InputBase.test.js b/packages/material-ui/src/InputBase/InputBase.test.js
--- a/packages/material-ui/src/InputBase/InputBase.test.js
+++ b/packages/material-ui/src/InputBase/InputBase.test.js
@@ -84,7 +84,7 @@ describe('<InputBase />', () => {
       assert.strictEqual(handleBlur.callCount, 1);
     });
 
-    // IE11 bug
+    // IE 11 bug
     it('should not respond the focus event when disabled', () => {
       const wrapper = shallow(<InputBase disabled />);
       const instance = wrapper.instance();
diff --git a/packages/material-ui/src/Modal/Modal.test.js b/packages/material-ui/src/Modal/Modal.test.js
--- a/packages/material-ui/src/Modal/Modal.test.js
+++ b/packages/material-ui/src/Modal/Modal.test.js
@@ -274,7 +274,9 @@ describe('<Modal />', () => {
       topModalStub.returns(false);
       wrapper.setProps({ manager: { isTopModal: topModalStub } });
 
-      instance.handleDocumentKeyDown(undefined);
+      instance.handleDocumentKeyDown({
+        keyCode: keycode('esc'),
+      });
       assert.strictEqual(topModalStub.callCount, 1);
       assert.strictEqual(onEscapeKeyDownSpy.callCount, 0);
       assert.strictEqual(onCloseSpy.callCount, 0);
@@ -286,7 +288,7 @@ describe('<Modal />', () => {
       event = { keyCode: keycode('j') }; // Not 'esc'
 
       instance.handleDocumentKeyDown(event);
-      assert.strictEqual(topModalStub.callCount, 1);
+      assert.strictEqual(topModalStub.callCount, 0);
       assert.strictEqual(onEscapeKeyDownSpy.callCount, 0);
       assert.strictEqual(onCloseSpy.callCount, 0);
     });
@@ -348,6 +350,16 @@ describe('<Modal />', () => {
       );
       assert.strictEqual(wrapper.contains(children), false);
     });
+
+    it('should mount', () => {
+      mount(
+        <Modal keepMounted open={false}>
+          <div />
+        </Modal>,
+      );
+      const modalNode = document.querySelector('[data-mui-test="Modal"]');
+      assert.strictEqual(modalNode.getAttribute('aria-hidden'), 'true');
+    });
   });
 
   describe('prop: onExited', () => {
diff --git a/packages/material-ui/src/Modal/ModalManager.test.js b/packages/material-ui/src/Modal/ModalManager.test.js
--- a/packages/material-ui/src/Modal/ModalManager.test.js
+++ b/packages/material-ui/src/Modal/ModalManager.test.js
@@ -30,9 +30,9 @@ describe('ModalManager', () => {
     let modal3;
 
     before(() => {
-      modal1 = {};
-      modal2 = {};
-      modal3 = {};
+      modal1 = { modalRef: document.createElement('div') };
+      modal2 = { modalRef: document.createElement('div') };
+      modal3 = { modalRef: document.createElement('div') };
     });
 
     it('should add modal1', () => {
@@ -122,15 +122,15 @@ describe('ModalManager', () => {
   });
 
   describe('container aria-hidden', () => {
-    let mountNode1;
+    let modalRef1;
     let container2;
 
     beforeEach(() => {
       container2 = document.createElement('div');
       document.body.appendChild(container2);
 
-      mountNode1 = document.createElement('div');
-      container2.appendChild(mountNode1);
+      modalRef1 = document.createElement('div');
+      container2.appendChild(modalRef1);
 
       modalManager = new ModalManager();
     });
@@ -139,46 +139,45 @@ describe('ModalManager', () => {
       document.body.removeChild(container2);
     });
 
+    it('should not contain aria-hidden on modal', () => {
+      const modal2 = document.createElement('div');
+      modal2.setAttribute('aria-hidden', 'true');
+
+      assert.strictEqual(modal2.getAttribute('aria-hidden'), 'true');
+      modalManager.add({ modalRef: modal2 }, container2);
+      assert.strictEqual(modal2.getAttribute('aria-hidden'), null);
+    });
+
     it('should add aria-hidden to container siblings', () => {
       modalManager.add({}, container2);
-      assert.strictEqual(mountNode1.getAttribute('aria-hidden'), 'true');
+      assert.strictEqual(container2.children[0].getAttribute('aria-hidden'), 'true');
     });
 
     it('should add aria-hidden to previous modals', () => {
-      const modal2 = {};
-      const modal3 = {};
-      const mountNode2 = document.createElement('div');
+      const modal2 = document.createElement('div');
+      const modal3 = document.createElement('div');
 
-      modal2.mountNode = mountNode2;
-      container2.appendChild(mountNode2);
-      modalManager.add(modal2, container2);
-      modalManager.add(modal3, container2);
-      assert.strictEqual(mountNode1.getAttribute('aria-hidden'), 'true');
-      assert.strictEqual(mountNode2.getAttribute('aria-hidden'), 'true');
-    });
+      container2.appendChild(modal2);
+      container2.appendChild(modal3);
 
-    it('should remove aria-hidden on americas next top modal', () => {
-      const modal2 = {};
-      const modal3 = {};
-      const mountNode2 = document.createElement('div');
+      modalManager.add({ modalRef: modal2 }, container2);
+      // Simulate the main React DOM true.
+      assert.strictEqual(container2.children[0].getAttribute('aria-hidden'), 'true');
+      assert.strictEqual(container2.children[1].getAttribute('aria-hidden'), null);
 
-      modal2.mountNode = mountNode2;
-      container2.appendChild(mountNode2);
-      modalManager.add({}, container1);
-      modalManager.add(modal2, container2);
-      modalManager.add(modal3, container2);
-      assert.strictEqual(mountNode2.getAttribute('aria-hidden'), 'true');
-      modalManager.remove(modal3, container2);
-      assert.strictEqual(mountNode2.getAttribute('aria-hidden'), null);
+      modalManager.add({ modalRef: modal3 }, container2);
+      assert.strictEqual(container2.children[0].getAttribute('aria-hidden'), 'true');
+      assert.strictEqual(container2.children[1].getAttribute('aria-hidden'), 'true');
+      assert.strictEqual(container2.children[2].getAttribute('aria-hidden'), null);
     });
 
     it('should remove aria-hidden on siblings', () => {
-      const modal = {};
+      const modal = { modalRef: container2.children[0] };
 
       modalManager.add(modal, container2);
-      assert.strictEqual(mountNode1.getAttribute('aria-hidden'), 'true');
+      assert.strictEqual(container2.children[0].getAttribute('aria-hidden'), null);
       modalManager.remove(modal, container2);
-      assert.strictEqual(mountNode1.getAttribute('aria-hidden'), null);
+      assert.strictEqual(container2.children[0].getAttribute('aria-hidden'), 'true');
     });
   });
 });
diff --git a/packages/material-ui/test/integration/Select.test.js b/packages/material-ui/test/integration/Select.test.js
--- a/packages/material-ui/test/integration/Select.test.js
+++ b/packages/material-ui/test/integration/Select.test.js
@@ -17,7 +17,7 @@ describe('<Select> integration', () => {
 
   describe('with Dialog', () => {
     it('should focus the selected item', done => {
-      const wrapper = mount(<SelectAndDialog open />);
+      const wrapper = mount(<SelectAndDialog />);
       const portalLayer = wrapper
         .find(Portal)
         .instance()