Skip to content

Commit

Permalink
[Fix] mount: Recursive isEmptyRender
Browse files Browse the repository at this point in the history
 - [New] `utils`: add `recursiveEmptyRender` and `isEmptyValue`

Fixes #1866.
  • Loading branch information
sstern6 authored and ljharb committed Nov 17, 2018
1 parent cc6c3dc commit 7a08723
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 1 deletion.
103 changes: 103 additions & 0 deletions packages/enzyme-test-suite/test/ReactWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3223,6 +3223,109 @@ describeWithDOM('mount', () => {
expect(wrapper.isEmptyRender()).to.equal(data.expectResponse);
});

describe('nested nodes', () => {
class RenderChildren extends React.Component {
render() {
return this.props.children;
}
}

class RenderNull extends React.Component {
render() {
return null;
}
}

it('returns true for nested elements that return null', () => {
const wrapper = mount((
<RenderChildren>
<RenderNull />
</RenderChildren>
));

expect(wrapper.isEmptyRender()).to.equal(true);
});

it('returns false for multiple nested elements that all return null', () => {
const wrapper = mount((
<RenderChildren>
<div />
</RenderChildren>
));

expect(wrapper.isEmptyRender()).to.equal(false);
});

it('returns false for multiple nested elements where one fringe returns a non null value', () => {
const wrapper = mount((
<RenderChildren>
<div>Hello</div>
</RenderChildren>
));

expect(wrapper.isEmptyRender()).to.equal(false);
});

itIf(is('>= 16'), 'returns false for multiple nested elements that all return null', () => {
const wrapper = mount((
<RenderChildren>
<RenderNull />
<RenderChildren>
<RenderNull />
<div />
</RenderChildren>
</RenderChildren>
));

expect(wrapper.isEmptyRender()).to.equal(false);
});

itIf(is('>= 16'), 'returns false for multiple nested elements where one fringe returns a non null value', () => {
const wrapper = mount((
<RenderChildren>
<RenderNull />
<RenderChildren>
<RenderNull />
<RenderNull />
</RenderChildren>
<RenderChildren>
<RenderNull />
<RenderChildren>
<RenderNull />
<RenderNull />
<RenderNull />
<div>Hello</div>
</RenderChildren>
</RenderChildren>
</RenderChildren>
));

expect(wrapper.isEmptyRender()).to.equal(false);
});

itIf(is('>= 16'), 'returns true for multiple nested elements where all values are null', () => {
const wrapper = mount((
<RenderChildren>
<RenderNull />
<RenderChildren>
<RenderNull />
<RenderNull />
</RenderChildren>
<RenderChildren>
<RenderNull />
<RenderChildren>
<RenderNull />
<RenderNull />
<RenderNull />
</RenderChildren>
</RenderChildren>
</RenderChildren>
));

expect(wrapper.isEmptyRender()).to.equal(true);
});
});

it('does not return true for HTML elements', () => {
const wrapper = mount(<div className="bar baz" />);
expect(wrapper.isEmptyRender()).to.equal(false);
Expand Down
46 changes: 46 additions & 0 deletions packages/enzyme-test-suite/test/Utils-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
nodeHasType,
isCustomComponentElement,
makeOptions,
isEmptyValue,
renderedDive,
} from 'enzyme/build/Utils';
import getAdapter from 'enzyme/build/getAdapter';
import {
Expand Down Expand Up @@ -693,6 +695,50 @@ describe('Utils', () => {
});
});

describe('isEmptyValue', () => {
it('returns true with `false` or `null`', () => {
const validValues = [false, null];

validValues.forEach((value) => {
expect([value, isEmptyValue(value)]).to.eql([value, true]);
});
});

it('returns false when it recieves any other value than "false" or null', () => {
const values = [undefined, true, 'test', []];

values.forEach((value) => {
expect([value, isEmptyValue(value)]).to.eql([value, false]);
});
});
});

describe('renderedDive', () => {
const emptyNodetestData = [
[{ rendered: null }, { rendered: false }],
{ rendered: { rendered: false } },
false,
null,
{ rendered: false },
{ rendered: null },
];
const nonEmptyNodeData = [
[{ rendered: null }, { rendered: <div /> }],
[{ rendered: null }, { rendered: { rendered: 'hello test' } }],
[{ rendered: null }, { rendered: { rendered: [{ rendered: null }, { rendered: <span /> }] } }],
{ rendered: '' },
{ rendered: { rendered: [{ rendered: null }, { rendered: <span /> }] } },
];

it('returns true when renderedDive receives nodes that render validEmpty values', () => {
emptyNodetestData.forEach(node => expect(renderedDive(node)).to.equal(true));
});

it('returns false when renderedDive receives nodes that render non-valid empty values', () => {
nonEmptyNodeData.forEach(node => expect(renderedDive(node)).to.equal(false));
});
});

describe('spyMethod', () => {
it('can spy last return value and restore it', () => {
class Counter {
Expand Down
5 changes: 4 additions & 1 deletion packages/enzyme/src/ReactWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
sym,
privateSet,
cloneElement,
renderedDive,
} from './Utils';
import getAdapter from './getAdapter';
import { debugNodes } from './Debug';
Expand Down Expand Up @@ -522,7 +523,9 @@ class ReactWrapper {
* @returns {boolean}
*/
isEmptyRender() {
return this.single('isEmptyRender', n => n.rendered === null);
const nodes = this.getNodeInternal();

return renderedDive(nodes);
}

/**
Expand Down
41 changes: 41 additions & 0 deletions packages/enzyme/src/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,44 @@ export function shallowEqual(objA, objB) {

return true;
}

export function isEmptyValue(renderedValue) {
return renderedValue === null || renderedValue === false;
}

export function renderedDive(nodes) {
let isEmptyRender = true;

function dive(renderedNodes) {
const isList = Array.isArray(renderedNodes) && renderedNodes.length > 0;
if (isList) {
renderedNodes.some((n) => {
if (n) {
if (has(n, 'rendered')) {
dive(n.rendered);
} else if (!isEmptyValue(n.rendered)) {
isEmptyRender = false;
}
} else if (!isEmptyValue(n)) {
isEmptyRender = false;
}

return !isEmptyRender;
});
} else if (!isEmptyValue(renderedNodes)) {
if (has(renderedNodes, 'rendered')) {
dive(renderedNodes.rendered);
} else if (has(renderedNodes, 'rendered') && !isEmptyValue(renderedNodes.rendered)) {
isEmptyRender = false;
} else if (!has(renderedNodes, 'rendered') && !isEmptyValue(renderedNodes)) {
isEmptyRender = false;
} else {
dive(renderedNodes.rendered);
}
}

return isEmptyRender;
}

return dive(nodes);
}

0 comments on commit 7a08723

Please sign in to comment.