Skip to content

Commit d9cc09e

Browse files
ottosichertljharb
authored andcommitted
[enzyme] [new] & [fix]: render: handle Fiber strings and numbers
- [enzyme] [fix] `render`: handle Fiber strings and numbers - [enzyme] [new] `Utils`: add `loadCheerioRoot` Fixes #2098
1 parent 66ff0d4 commit d9cc09e

File tree

7 files changed

+82
-8
lines changed

7 files changed

+82
-8
lines changed

packages/enzyme-test-suite/test/Utils-spec.jsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
isEmptyValue,
1515
renderedDive,
1616
isCustomComponent,
17+
loadCheerioRoot,
1718
} from 'enzyme/build/Utils';
1819
import getAdapter from 'enzyme/build/getAdapter';
1920
import EnzymeAdapter from 'enzyme/build/EnzymeAdapter';
@@ -1073,4 +1074,17 @@ describe('Utils', () => {
10731074
expect(() => isCustomComponent({}, {})).to.throw(Error);
10741075
});
10751076
});
1077+
1078+
describe('loadCheerioRoot', () => {
1079+
it('always returns a Cheerio instance', () => {
1080+
expect(loadCheerioRoot()).to.have.property('cheerio', '[cheerio object]');
1081+
expect(loadCheerioRoot(null)).to.have.property('cheerio', '[cheerio object]');
1082+
expect(loadCheerioRoot('')).to.have.property('cheerio', '[cheerio object]');
1083+
expect(loadCheerioRoot('foo')).to.have.property('cheerio', '[cheerio object]');
1084+
expect(loadCheerioRoot('123')).to.have.property('cheerio', '[cheerio object]');
1085+
expect(loadCheerioRoot('<div>bar</div>')).to.have.property('cheerio', '[cheerio object]');
1086+
expect(loadCheerioRoot('leading <span>text</span>')).to.have.property('cheerio', '[cheerio object]');
1087+
expect(loadCheerioRoot('<div>malformed</><<html')).to.have.property('cheerio', '[cheerio object]');
1088+
});
1089+
});
10761090
});

packages/enzyme-test-suite/test/staticRender-spec.jsx

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,51 @@ describeWithDOM('render', () => {
7878
});
7979

8080
const context = { name: 'foo' };
81-
expect(() => render(<SimpleComponent />, { context })).to.not.throw(Error);
81+
expect(() => render(<SimpleComponent />, { context })).not.to.throw();
82+
});
83+
});
84+
85+
describe('rendering non-elements', () => {
86+
it('can render strings', () => {
87+
const StringComponent = createClass({
88+
render() {
89+
return 'foo';
90+
},
91+
});
92+
93+
const getWrapper = (options) => render(<StringComponent />, options);
94+
if (is('>= 16')) {
95+
expect(getWrapper).to.not.throw();
96+
97+
const wrapper = getWrapper();
98+
expect(wrapper.text()).to.equal('foo');
99+
expect(wrapper.html()).to.equal('foo');
100+
expect(String(wrapper)).to.equal('foo');
101+
expect(wrapper).to.have.lengthOf(1);
102+
} else {
103+
expect(getWrapper).to.throw();
104+
}
105+
});
106+
107+
it('can render numbers', () => {
108+
const NumberComponent = createClass({
109+
render() {
110+
return 42;
111+
},
112+
});
113+
114+
const getWrapper = (options) => render(<NumberComponent />, options);
115+
if (is('>= 16')) {
116+
expect(getWrapper).to.not.throw();
117+
118+
const wrapper = getWrapper();
119+
expect(wrapper.text()).to.equal('42');
120+
expect(wrapper.html()).to.equal('42');
121+
expect(String(wrapper)).to.equal('42');
122+
expect(wrapper).to.have.lengthOf(1);
123+
} else {
124+
expect(getWrapper).to.throw();
125+
}
82126
});
83127
});
84128

packages/enzyme/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"license": "MIT",
3737
"dependencies": {
3838
"array.prototype.flat": "^1.2.1",
39-
"cheerio": "^1.0.0-rc.2",
39+
"cheerio": "^1.0.0-rc.3",
4040
"enzyme-shallow-equal": "^1.0.0",
4141
"function.prototype.name": "^1.1.0",
4242
"has": "^1.0.3",

packages/enzyme/src/ReactWrapper.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import cheerio from 'cheerio';
21
import flat from 'array.prototype.flat';
32
import has from 'has';
43

@@ -15,6 +14,7 @@ import {
1514
cloneElement,
1615
renderedDive,
1716
isCustomComponent,
17+
loadCheerioRoot,
1818
} from './Utils';
1919
import getAdapter from './getAdapter';
2020
import { debugNodes } from './Debug';
@@ -650,7 +650,7 @@ class ReactWrapper {
650650
*/
651651
render() {
652652
const html = this.html();
653-
return html === null ? cheerio() : cheerio.load('')(html);
653+
return loadCheerioRoot(html);
654654
}
655655

656656
/**

packages/enzyme/src/ShallowWrapper.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import flat from 'array.prototype.flat';
2-
import cheerio from 'cheerio';
32
import has from 'has';
43
import shallowEqual from 'enzyme-shallow-equal';
54

@@ -20,6 +19,7 @@ import {
2019
cloneElement,
2120
spyMethod,
2221
isEmptyValue,
22+
loadCheerioRoot,
2323
} from './Utils';
2424
import getAdapter from './getAdapter';
2525
import { debugNodes } from './Debug';
@@ -1103,7 +1103,8 @@ class ShallowWrapper {
11031103
* @returns {CheerioWrapper}
11041104
*/
11051105
render() {
1106-
return this.type() === null ? cheerio() : cheerio.load('')(this.html());
1106+
const html = this.html();
1107+
return loadCheerioRoot(html);
11071108
}
11081109

11091110
/**

packages/enzyme/src/Utils.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import functionName from 'function.prototype.name';
66
import has from 'has';
77
import flat from 'array.prototype.flat';
88
import trim from 'string.prototype.trim';
9+
import cheerio from 'cheerio';
10+
import { isHtml } from 'cheerio/lib/utils';
911

1012
import { get } from './configuration';
1113
import { childrenOfNode } from './RSTTraversal';
@@ -350,3 +352,16 @@ export function renderedDive(nodes) {
350352
return isEmptyValue(n);
351353
});
352354
}
355+
356+
export function loadCheerioRoot(html) {
357+
if (!html) {
358+
return cheerio.root();
359+
}
360+
361+
if (!isHtml(html)) {
362+
// use isDocument=false to create fragment
363+
return cheerio.load(html, null, false).root();
364+
}
365+
366+
return cheerio.load('')(html);
367+
}

packages/enzyme/src/render.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import cheerio from 'cheerio';
21
import getAdapter from './getAdapter';
2+
import { loadCheerioRoot } from './Utils';
33

44
/**
55
* Renders a react component into static HTML and provides a cheerio wrapper around it. This is
@@ -19,5 +19,5 @@ export default function render(node, options = {}) {
1919
const adapter = getAdapter(options);
2020
const renderer = adapter.createRenderer({ mode: 'string', ...options });
2121
const html = renderer.render(node, options.context);
22-
return cheerio.load('')(html);
22+
return loadCheerioRoot(html);
2323
}

0 commit comments

Comments
 (0)