Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mounted portals show in debug and can be found #1760

Merged
merged 2 commits into from
Aug 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion packages/enzyme-adapter-react-16.1/src/ReactSixteenOneAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,17 @@ function toTree(vnode) {
case HostRoot: // 3
return childrenToTree(node.child);
case HostPortal: { // 4
return childrenToTree(node.child);
const { stateNode: { containerInfo } } = node;
const props = { containerInfo };
return {
nodeType: 'portal',
type: Portal,
props,
key: ensureKeyOrUndefined(node.key),
ref: node.ref,
instance: null,
rendered: childrenToTree(node.child),
};
}
case ClassComponent:
return {
Expand Down
12 changes: 11 additions & 1 deletion packages/enzyme-adapter-react-16.2/src/ReactSixteenTwoAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,17 @@ function toTree(vnode) {
case HostRoot: // 3
return childrenToTree(node.child);
case HostPortal: { // 4
return childrenToTree(node.child);
const { stateNode: { containerInfo } } = node;
const props = { containerInfo };
return {
nodeType: 'portal',
type: Portal,
props,
key: ensureKeyOrUndefined(node.key),
ref: node.ref,
instance: null,
rendered: childrenToTree(node.child),
};
}
case ClassComponent:
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,17 @@ function toTree(vnode) {
case HostRoot: // 3
return childrenToTree(node.child);
case HostPortal: { // 4
return childrenToTree(node.child);
const { stateNode: { containerInfo } } = node;
const props = { containerInfo };
return {
nodeType: 'portal',
type: Portal,
props,
key: ensureKeyOrUndefined(node.key),
ref: node.ref,
instance: null,
rendered: childrenToTree(node.child),
};
}
case ClassComponent:
return {
Expand Down
12 changes: 11 additions & 1 deletion packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,17 @@ function toTree(vnode) {
case HostRoot: // 3
return childrenToTree(node.child);
case HostPortal: { // 4
return childrenToTree(node.child);
const { stateNode: { containerInfo } } = node;
const props = { containerInfo };
return {
nodeType: 'portal',
type: Portal,
props,
key: ensureKeyOrUndefined(node.key),
ref: node.ref,
instance: null,
rendered: childrenToTree(node.child),
};
}
case ClassComponent:
return {
Expand Down
3 changes: 2 additions & 1 deletion packages/enzyme-adapter-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"dependencies": {
"function.prototype.name": "^1.1.0",
"object.assign": "^4.1.0",
"prop-types": "^15.6.2"
"prop-types": "^15.6.2",
"react-is": "^16.4.2"
},
"peerDependencies": {
"react": "0.13.x || 0.14.x || ^15.0.0-0 || ^16.0.0-0"
Expand Down
10 changes: 10 additions & 0 deletions packages/enzyme-adapter-utils/src/Utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import functionName from 'function.prototype.name';
import {
Portal,
} from 'react-is';
import createMountWrapper from './createMountWrapper';
import createRenderWrapper from './createRenderWrapper';

Expand Down Expand Up @@ -107,6 +110,10 @@ export function displayNameOfNode(node) {

if (!type) return null;

if (type === Portal) {
return 'Portal';

This comment was marked as resolved.

}

return type.displayName || (typeof type === 'function' ? functionName(type) : type.name || type);
}

Expand All @@ -117,6 +124,9 @@ export function nodeTypeFromType(type) {
if (type && type.prototype && type.prototype.isReactComponent) {
return 'class';
}
if (type && type === Portal) {
return 'portal';

This comment was marked as resolved.

}
return 'function';
}

Expand Down
21 changes: 17 additions & 4 deletions packages/enzyme-test-suite/test/Adapter-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import jsdom from 'jsdom';
import { get } from 'enzyme/build/configuration';
import { configure, shallow } from 'enzyme';
import inspect from 'object-inspect';
import {
Portal,
} from 'react-is';

import './_helpers/setupAdapters';
import Adapter from './_helpers/adapter';
Expand Down Expand Up @@ -226,13 +229,23 @@ describe('Adapter', () => {
ref: null,
instance: null,
rendered: {
nodeType: 'host',
type: 'div',
props: { className: 'Foo' },
nodeType: 'portal',
type: Portal,
props: {
containerInfo: document.body,
},
key: undefined,
ref: null,
instance: null,
rendered: ['Hello World!'],
rendered: {
nodeType: 'host',
type: 'div',
props: { className: 'Foo' },
key: undefined,
ref: null,
instance: null,
rendered: ['Hello World!'],
},
},
}));
});
Expand Down
139 changes: 139 additions & 0 deletions packages/enzyme-test-suite/test/ReactWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import {
sym,
} from 'enzyme/build/Utils';
import getAdapter from 'enzyme/build/getAdapter';
import {
Portal,
} from 'react-is';

import './_helpers/setupAdapters';
import {
Expand Down Expand Up @@ -426,6 +429,103 @@ describeWithDOM('mount', () => {
});
});

describeIf(is('>= 16'), 'portals', () => {
it('should show portals in mount debug tree', () => {
const containerDiv = global.document.createElement('div');
const Foo = () => (
<div>
{createPortal(
<div className="in-portal">InPortal</div>,
containerDiv,
)}
</div>
);

const wrapper = mount(<Foo />);
expect(wrapper.debug()).to.equal(`<Foo>
<div>
<Portal containerInfo={{...}}>
<div className="in-portal">
InPortal
</div>
</Portal>
</div>
</Foo>`);
});

it('should show portal container in debug tree', () => {
const containerDiv = global.document.createElement('div');
containerDiv.setAttribute('data-foo', 'bar');
const Foo = () => (
<div className="foo">
{createPortal(
<div className="in-portal">InPortal</div>,
containerDiv,
)}
</div>
);

const wrapper = mount(<Foo />);
expect(wrapper.debug({ verbose: true })).to.equal(`<Foo>
<div className="foo">
<Portal containerInfo={<div data-foo="bar">...</div>}>
<div className="in-portal">
InPortal
</div>
</Portal>
</div>
</Foo>`);
});

it('should show nested portal children in debug tree', () => {
const Bar = () => null;

const containerDiv = global.document.createElement('div');
const Foo = () => (
<div className="foo">
{createPortal(
<div className="in-portal">
<div className="nested-in-portal">
<Bar />
</div>
</div>,
containerDiv,
)}
</div>
);

const wrapper = mount(<Foo />);
expect(wrapper.debug()).to.equal(`<Foo>
<div className="foo">
<Portal containerInfo={{...}}>
<div className="in-portal">
<div className="nested-in-portal">
<Bar />
</div>
</div>
</Portal>
</div>
</Foo>`);
});

it('should have top level portals in debug tree', () => {
const containerDiv = global.document.createElement('div');
const Foo = () => createPortal(
<div className="in-portal">InPortal</div>,
containerDiv,
);

const wrapper = mount(<Foo />);
expect(wrapper.debug()).to.equal(`<Foo>
<Portal containerInfo={{...}}>
<div className="in-portal">
InPortal
</div>
</Portal>
</Foo>`);
});
});

describe('.contains(node)', () => {
it('should allow matches on the root node', () => {
const a = <div className="foo" />;
Expand Down Expand Up @@ -1260,6 +1360,25 @@ describeWithDOM('mount', () => {
expect(wrapper.children()).to.have.lengthOf(1);
});
});

itIf(is('>= 16'), 'should find mounted portals by name', () => {
const containerDiv = global.document.createElement('div');
const Foo = () => (
<div>
{createPortal(
<div className="in-portal">InPortal</div>,
containerDiv,
)}
</div>
);

const wrapper = mount(<Foo />);
expect(wrapper.find('Portal').debug()).to.equal(`<Portal containerInfo={{...}}>
<div className="in-portal">
InPortal
</div>
</Portal>`);
});
});

describe('.findWhere(predicate)', () => {
Expand Down Expand Up @@ -1582,6 +1701,26 @@ describeWithDOM('mount', () => {
wrapper.findWhere(spy);
expect(spy).to.have.property('callCount', 2);
});

itIf(is('>= 16'), 'should find mounted portals by react-is Portal type', () => {
const containerDiv = global.document.createElement('div');
const Foo = () => (
<div>
{createPortal(
<div className="in-portal">InPortal</div>,
containerDiv,
)}
</div>
);

const wrapper = mount(<Foo />);
expect(wrapper.findWhere(node => node.type() === Portal).debug())
.to.equal(`<Portal containerInfo={{...}}>
<div className="in-portal">
InPortal
</div>
</Portal>`);
});
});

describe('.setProps(newProps[, callback])', () => {
Expand Down