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

Make nodeToHostNode handle arrays #2001

Merged
merged 2 commits into from
Feb 4, 2019
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
17 changes: 12 additions & 5 deletions packages/enzyme-adapter-react-16.1/src/ReactSixteenOneAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,22 @@ function nodeToHostNode(_node) {
while (node && !Array.isArray(node) && node.instance === null) {
node = node.rendered;
}
if (Array.isArray(node)) {
// TODO(lmr): throw warning regarding not being able to get a host node here
throw new Error('Trying to get host node of an array');
}
// if the SFC returned null effectively, there is no host node.
if (!node) {
return null;
}
return ReactDOM.findDOMNode(node.instance);

const mapper = (item) => {
if (item && item.instance) return ReactDOM.findDOMNode(item.instance);
return null;
};
if (Array.isArray(node)) {
return node.map(mapper);
}
if (Array.isArray(node.rendered) && node.nodeType === 'class') {
return node.rendered.map(mapper);
}
return mapper(node);
}

const eventOptions = { animation: true };
Expand Down
17 changes: 12 additions & 5 deletions packages/enzyme-adapter-react-16.2/src/ReactSixteenTwoAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,15 +202,22 @@ function nodeToHostNode(_node) {
while (node && !Array.isArray(node) && node.instance === null) {
node = node.rendered;
}
if (Array.isArray(node)) {
// TODO(lmr): throw warning regarding not being able to get a host node here
throw new Error('Trying to get host node of an array');
}
// if the SFC returned null effectively, there is no host node.
if (!node) {
return null;
}
return ReactDOM.findDOMNode(node.instance);

const mapper = (item) => {
if (item && item.instance) return ReactDOM.findDOMNode(item.instance);
return null;
};
if (Array.isArray(node)) {
return node.map(mapper);
}
if (Array.isArray(node.rendered) && node.nodeType === 'class') {
return node.rendered.map(mapper);
}
return mapper(node);
}

const eventOptions = { animation: true };
Expand Down
17 changes: 12 additions & 5 deletions packages/enzyme-adapter-react-16.3/src/ReactSixteenThreeAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,15 +219,22 @@ function nodeToHostNode(_node) {
while (node && !Array.isArray(node) && node.instance === null) {
node = node.rendered;
}
if (Array.isArray(node)) {
// TODO(lmr): throw warning regarding not being able to get a host node here
throw new Error('Trying to get host node of an array');
}
// if the SFC returned null effectively, there is no host node.
if (!node) {
return null;
}
return ReactDOM.findDOMNode(node.instance);

const mapper = (item) => {
if (item && item.instance) return ReactDOM.findDOMNode(item.instance);
return null;
};
if (Array.isArray(node)) {
return node.map(mapper);
}
if (Array.isArray(node.rendered) && node.nodeType === 'class') {
return node.rendered.map(mapper);
}
return mapper(node);
}

const eventOptions = { animation: true };
Expand Down
17 changes: 12 additions & 5 deletions packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,15 +219,22 @@ function nodeToHostNode(_node) {
while (node && !Array.isArray(node) && node.instance === null) {
node = node.rendered;
}
if (Array.isArray(node)) {
// TODO(lmr): throw warning regarding not being able to get a host node here
throw new Error('Trying to get host node of an array');
}
// if the SFC returned null effectively, there is no host node.
if (!node) {
return null;
}
return ReactDOM.findDOMNode(node.instance);

const mapper = (item) => {
if (item && item.instance) return ReactDOM.findDOMNode(item.instance);
return null;
};
if (Array.isArray(node)) {
return node.map(mapper);
}
if (Array.isArray(node.rendered) && node.nodeType === 'class') {
return node.rendered.map(mapper);
}
return mapper(node);
}

const eventOptions = {
Expand Down
62 changes: 62 additions & 0 deletions packages/enzyme-test-suite/test/ReactWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3702,6 +3702,38 @@ describeWithDOM('mount', () => {
expect(wrapper.text()).to.equal('{ some text }');
});
});

describeIf(is('> 16.2'), 'fragments', () => {
class FragmentClassExample extends React.Component {
render() {
return (
<Fragment>
<div>Foo</div>
<div>Bar</div>
</Fragment>
);
}
}

const FragmentConstExample = () => (
<Fragment>
<div><span>Foo</span></div>
<div><span>Bar</span></div>
</Fragment>
);

it('correctly gets text for both children for class', () => {
const classWrapper = mount(<FragmentClassExample />);
expect(classWrapper.text()).to.include('Foo');
expect(classWrapper.text()).to.include('Bar');
});

it('correctly gets text for both children for const', () => {
const constWrapper = mount(<FragmentConstExample />);
expect(constWrapper.text()).to.include('Foo');
expect(constWrapper.text()).to.include('Bar');
});
});
});

describe('.props()', () => {
Expand Down Expand Up @@ -5135,6 +5167,36 @@ describeWithDOM('mount', () => {
expect(wrapper.find(Foo).html()).to.equal('<div class="in-foo"></div>');
});
});

describeIf(is('>16.2'), 'fragments', () => {
class FragmentClassExample extends React.Component {
render() {
return (
<Fragment>
<div><span>Foo</span></div>
<div><span>Bar</span></div>
</Fragment>
);
}
}

const FragmentConstExample = () => (
<Fragment>
<div><span>Foo</span></div>
<div><span>Bar</span></div>
</Fragment>
);

it('correctly renders html for both children for class', () => {
const classWrapper = mount(<FragmentClassExample />);
expect(classWrapper.html()).to.equal('<div><span>Foo</span></div><div><span>Bar</span></div>');
});

it('correctly renders html for both children for const', () => {
const constWrapper = mount(<FragmentConstExample />);
expect(constWrapper.html()).to.equal('<div><span>Foo</span></div><div><span>Bar</span></div>');
});
});
});

describe('.unmount()', () => {
Expand Down
62 changes: 62 additions & 0 deletions packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3653,6 +3653,38 @@ describe('shallow', () => {
expect(wrapper.text()).to.equal('{ some text }');
});
});

describeIf(is('> 16.2'), 'fragments', () => {
class FragmentClassExample extends React.Component {
render() {
return (
<Fragment>
<div>Foo</div>
<div>Bar</div>
</Fragment>
);
}
}

const FragmentConstExample = () => (
<Fragment>
<div><span>Foo</span></div>
<div><span>Bar</span></div>
</Fragment>
);

it('correctly gets text for both children for class', () => {
const classWrapper = shallow(<FragmentClassExample />);
expect(classWrapper.text()).to.include('Foo');
expect(classWrapper.text()).to.include('Bar');
});

it('correctly gets text for both children for const', () => {
const constWrapper = shallow(<FragmentConstExample />);
expect(constWrapper.text()).to.include('Foo');
expect(constWrapper.text()).to.include('Bar');
});
});
});

describe('.props()', () => {
Expand Down Expand Up @@ -5207,6 +5239,36 @@ describe('shallow', () => {
));
});
});

describeIf(is('>16.2'), 'fragments', () => {
class FragmentClassExample extends React.Component {
render() {
return (
<Fragment>
<div><span>Foo</span></div>
<div><span>Bar</span></div>
</Fragment>
);
}
}

const FragmentConstExample = () => (
<Fragment>
<div><span>Foo</span></div>
<div><span>Bar</span></div>
</Fragment>
);

it('correctly renders html for both children for class', () => {
const classWrapper = shallow(<FragmentClassExample />);
expect(classWrapper.html()).to.equal('<div><span>Foo</span></div><div><span>Bar</span></div>');
});

it('correctly renders html for both children for const', () => {
const constWrapper = shallow(<FragmentConstExample />);
expect(constWrapper.html()).to.equal('<div><span>Foo</span></div><div><span>Bar</span></div>');
});
});
});

describe('.unmount()', () => {
Expand Down
3 changes: 1 addition & 2 deletions packages/enzyme/src/RSTTraversal.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,5 @@ export function getTextFromNode(node) {
return `<${node.type.displayName || functionName(node.type)} />`;
}

return childrenOfNode(node).map(getTextFromNode)
.join('');
return childrenOfNode(node).map(getTextFromNode).join('');
}
24 changes: 20 additions & 4 deletions packages/enzyme/src/ReactWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,16 @@ class ReactWrapper {
if (!node) {
return typeof n === 'string' ? n : node;
}
return node.textContent;

const nodeArray = Array.isArray(node) ? node : [node];
const textContent = nodeArray.map((item) => {
if (!item) {
return '';
}
return item.textContent || '';
});

return textContent.join('');
});
}

Expand All @@ -594,10 +603,17 @@ class ReactWrapper {
return this.single('html', (n) => {
if (n === null) return null;
const adapter = getAdapter(this[OPTIONS]);
const node = adapter.nodeToHostNode(n);
return node === null
const node = adapter.nodeToHostNode(n, true);

if (node === null) return null;

const nodeArray = Array.isArray(node) ? node : [node];
const nodesHTML = nodeArray.map(item => (item === null
? null
: node.outerHTML.replace(/\sdata-(reactid|reactroot)+="([^"]*)+"/g, '');
: item.outerHTML.replace(/\sdata-(reactid|reactroot)+="([^"]*)+"/g, '')
));

return nodesHTML.join('');
});
}

Expand Down