Skip to content

Commit

Permalink
[Portal] Global option to disable the portal
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviertassinari committed Apr 20, 2018
1 parent e3e8c13 commit e680368
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 2 deletions.
2 changes: 1 addition & 1 deletion docs/src/pages/guides/composition/composition.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,6 @@ class ListItemLink extends React.Component {
}
```

`renderLink` will now always reference the same component. Here is a demo:
`renderLink` will now always reference the same component. Here is a demo with react-router:

{{"demo": "pages/guides/composition/ComponentProperty.js"}}
6 changes: 6 additions & 0 deletions docs/src/pages/utils/portal/portal.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ You have to wait for the client side reconciliation to see the children.
## Simple Portal

{{"demo": "pages/utils/portal/SimplePortal.js"}}

## Portal & tests

The portal behavior can be challenging for testing libraries, like [enzyme](https://github.com/airbnb/enzyme/issues/252), to handle.
We provide a global option to disable the behavior: `global.__MUI_PORTAL_DISABLE__`.
When set to `true`, the portal will behave as a pass-through component.
21 changes: 20 additions & 1 deletion packages/material-ui/src/Portal/Portal.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable no-underscore-dangle */

import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
Expand Down Expand Up @@ -44,13 +46,30 @@ class Portal extends React.Component {
* @public
*/
getMountNode = () => {
if (this.disable) {
return ReactDOM.findDOMNode(this);
}

return this.mountNode;
};

// Hack waiting for https://github.com/airbnb/enzyme/issues/252 to be solved.
// When `global.__MUI_PORTAL_DISABLE__` is set to `true`,
// the portal will behave as a pass-through component.
disable = typeof global !== 'undefined' && global.__MUI_PORTAL_DISABLE__;

render() {
const { children } = this.props;

return this.mountNode ? ReactDOM.createPortal(children, this.mountNode) : null;
if (this.mountNode) {
if (this.disable) {
return children;
}

return ReactDOM.createPortal(children, this.mountNode);
}

return null;
}
}

Expand Down
24 changes: 24 additions & 0 deletions packages/material-ui/src/Portal/Portal.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-underscore-dangle */
/* eslint-disable react/no-multi-comp */

import React from 'react';
Expand All @@ -24,6 +25,29 @@ describe('<Portal />', () => {
mount.cleanUp();
});

describe('disable portal for tests', () => {
const Portal = NewPortal;

before(() => {
global.__MUI_PORTAL_DISABLE__ = true;
});

after(() => {
global.__MUI_PORTAL_DISABLE__ = false;
});

it('should disable the portal feature', () => {
const wrapper = mount(
<Portal>
<h1 className="woofPortal">Foo</h1>
</Portal>,
);
assert.strictEqual(wrapper.children().length, 1, 'should have one children');
const instance = wrapper.instance();
assert.strictEqual(instance.getMountNode().nodeName.toLowerCase(), 'h1');
});
});

versions.map(verion => {
describe(verion, () => {
let Portal;
Expand Down

0 comments on commit e680368

Please sign in to comment.