Skip to content

Commit 4594798

Browse files
test(html-to-react): refactor tests for HTMLReactParser
1 parent 92582a8 commit 4594798

File tree

1 file changed

+87
-133
lines changed

1 file changed

+87
-133
lines changed

test/html-to-react.test.js

Lines changed: 87 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,25 @@ const React = require('react');
22
const parse = require('..');
33
const { data, render } = require('./helpers/');
44

5-
describe('exports', () => {
6-
it('has default ES Module', () => {
5+
describe('module', () => {
6+
it('exports default', () => {
77
expect(parse.default).toBe(parse);
88
});
99

10-
it('has domToReact', () => {
10+
it('exports domToReact', () => {
1111
expect(parse.domToReact).toBe(require('../lib/dom-to-react'));
1212
});
1313

14-
it('has htmlToDOM', () => {
14+
it('exports htmlToDOM', () => {
1515
expect(parse.htmlToDOM).toBe(require('html-dom-parser'));
1616
});
1717

18-
it('has attributesToProps', () => {
18+
it('exports attributesToProps', () => {
1919
expect(parse.attributesToProps).toBe(require('../lib/attributes-to-props'));
2020
});
2121
});
2222

23-
describe('parser', () => {
23+
describe('HTMLReactParser', () => {
2424
it.each([undefined, null, {}, [], true, false, 0, 1, () => {}, new Date()])(
2525
'throws error for value: %p',
2626
value => {
@@ -30,191 +30,145 @@ describe('parser', () => {
3030
}
3131
);
3232

33-
it('converts "" to []', () => {
33+
it('parses "" to []', () => {
3434
expect(parse('')).toEqual([]);
3535
});
3636

37-
it('returns string if it cannot be parsed as HTML', () => {
38-
const string = 'foo';
37+
it("returns string if it's not HTML", () => {
38+
const string = 'text';
3939
expect(parse(string)).toBe(string);
4040
});
4141

42-
it('converts single HTML element to React', () => {
42+
it('parses single HTML element', () => {
4343
const html = data.html.single;
4444
const reactElement = parse(html);
45-
4645
expect(render(reactElement)).toBe(html);
4746
});
4847

49-
it('converts single HTML element and ignores comment', () => {
48+
it('parses single HTML element with comment', () => {
5049
const html = data.html.single;
5150
// comment should be ignored
5251
const reactElement = parse(html + data.html.comment);
53-
5452
expect(render(reactElement)).toBe(html);
5553
});
5654

57-
it('converts multiple HTML elements to React', () => {
55+
it('parses multiple HTML elements', () => {
5856
const html = data.html.multiple;
5957
const reactElements = parse(html);
60-
6158
expect(render(React.createElement(React.Fragment, {}, reactElements))).toBe(
6259
html
6360
);
6461
});
6562

66-
it('converts complex HTML to React', () => {
63+
it('parses complex HTML', () => {
6764
const html = data.html.complex;
6865
const reactElement = parse(data.html.doctype + html);
69-
7066
expect(render(reactElement)).toBe(html);
7167
});
7268

73-
it('converts empty <script> to React', () => {
69+
it('parses empty <script>', () => {
7470
const html = '<script></script>';
7571
const reactElement = parse(html);
76-
7772
expect(render(reactElement)).toBe(html);
7873
});
7974

80-
it('converts empty <style> to React', () => {
75+
it('parses empty <style>', () => {
8176
const html = '<style></style>';
8277
const reactElement = parse(html);
83-
8478
expect(render(reactElement)).toBe(html);
8579
});
8680

87-
it('converts SVG to React', () => {
81+
it('parses SVG', () => {
8882
const svg = data.svg.complex;
8983
const reactElement = parse(svg);
90-
9184
expect(render(reactElement)).toBe(svg);
9285
});
9386

9487
it('decodes HTML entities', () => {
9588
const encodedEntities = 'asdf &amp; &yuml; &uuml; &apos;';
9689
const decodedEntities = "asdf & ÿ ü '";
9790
const reactElement = parse('<i>' + encodedEntities + '</i>');
98-
9991
expect(reactElement.props.children).toBe(decodedEntities);
10092
});
10193
});
10294

103-
describe('options', () => {
104-
describe('replace', () => {
105-
it('overrides the element if a valid React element is returned', () => {
106-
const html = data.html.complex;
107-
const reactElement = parse(html, {
108-
replace: node => {
109-
if (node.name === 'title') {
110-
return React.createElement('title', {}, 'Replaced Title');
111-
}
112-
}
113-
});
114-
115-
expect(render(reactElement)).toBe(
116-
html.replace('<title>Title</title>', '<title>Replaced Title</title>')
117-
);
118-
});
119-
120-
it('does not override the element if an invalid React element is returned', () => {
121-
const html = data.html.complex;
122-
const options = {
123-
replace: node => {
124-
if (node.attribs && node.attribs.id === 'header') {
125-
return {
126-
type: 'h1',
127-
props: { children: 'Heading' }
128-
};
129-
}
95+
describe('replace option', () => {
96+
it('replaces the element if a valid React element is returned', () => {
97+
const html = data.html.complex;
98+
const options = {
99+
replace: node => {
100+
if (node.name === 'title') {
101+
return React.createElement('title', {}, 'Replaced Title');
130102
}
131-
};
132-
const reactElement = parse(html, options);
133-
134-
expect(render(reactElement)).toBe(html);
135-
});
136-
137-
it('use attributesToProps to converts attributes to React props', () => {
138-
const { attributesToProps } = parse;
139-
const html = data.html.attributes;
140-
141-
let props;
142-
const options = {
143-
replace: node => {
144-
if (node.attribs && node.name === 'hr') {
145-
props = attributesToProps(node.attribs);
146-
return {
147-
type: 'hr',
148-
props
149-
};
150-
}
103+
}
104+
};
105+
const reactElement = parse(html, options);
106+
expect(render(reactElement)).toBe(
107+
html.replace('<title>Title</title>', '<title>Replaced Title</title>')
108+
);
109+
});
110+
111+
it('does not replace the element if an invalid React element is returned', () => {
112+
const html = data.html.complex;
113+
const options = {
114+
replace: node => {
115+
if (node.attribs && node.attribs.id === 'header') {
116+
return {
117+
type: 'h1',
118+
props: { children: 'Heading' }
119+
};
151120
}
152-
};
153-
const reactElement = parse(html, options);
154-
155-
expect(props).toEqual({
156-
id: 'foo',
157-
className: 'bar baz',
158-
style: {
159-
background: '#fff',
160-
textAlign: 'center'
161-
},
162-
['data-foo']: 'bar'
163-
});
164-
expect(render(reactElement)).toBe(html);
165-
});
166-
});
167-
168-
describe('library', () => {
169-
const Preact = require('preact');
170-
171-
it('converts with Preact instead of React', () => {
172-
const parsedElement = parse(data.html.single, { library: Preact });
173-
const preactElement = Preact.createElement('p', {}, 'foo');
174-
175-
expect(React.isValidElement(parsedElement)).toBe(false);
176-
expect(Preact.isValidElement(parsedElement)).toBe(true);
177-
178-
// remove `__v` key since it's causing test equality to fail
179-
delete parsedElement.__v;
180-
delete preactElement.__v;
181-
expect(parsedElement).toEqual(preactElement);
182-
});
183-
});
184-
185-
describe('htmlparser2', () => {
186-
it('parses XHTML with xmlMode enabled', () => {
187-
// using self-closing syntax (`/>`) for non-void elements is invalid
188-
// which causes elements to nest instead of being rendered correctly
189-
// enabling htmlparser2 option xmlMode resolves this issue
190-
const html = '<ul><li/><li/></ul>';
191-
const options = { htmlparser2: { xmlMode: true } };
192-
const reactElements = parse(html, options);
193-
194-
expect(render(reactElements)).toBe('<ul><li></li><li></li></ul>');
195-
});
196-
});
197-
198-
describe('trim', () => {
199-
it('preserves whitespace text nodes when disabled (default)', () => {
200-
const html = `<table>
121+
}
122+
};
123+
const reactElement = parse(html, options);
124+
expect(render(reactElement)).toBe(html);
125+
});
126+
});
127+
128+
describe('library option', () => {
129+
const Preact = require('preact');
130+
131+
it('converts with Preact instead of React', () => {
132+
const parsedElement = parse(data.html.single, { library: Preact });
133+
const preactElement = Preact.createElement('p', {}, 'foo');
134+
expect(React.isValidElement(parsedElement)).toBe(false);
135+
expect(Preact.isValidElement(parsedElement)).toBe(true);
136+
// remove `__v` key since it's causing test equality to fail
137+
delete parsedElement.__v;
138+
delete preactElement.__v;
139+
expect(parsedElement).toEqual(preactElement);
140+
});
141+
});
142+
143+
describe('htmlparser2 option', () => {
144+
it('parses XHTML with xmlMode enabled', () => {
145+
// using self-closing syntax (`/>`) for non-void elements is invalid
146+
// which causes elements to nest instead of being rendered correctly
147+
// enabling htmlparser2 option xmlMode resolves this issue
148+
const html = '<ul><li/><li/></ul>';
149+
const options = { htmlparser2: { xmlMode: true } };
150+
const reactElements = parse(html, options);
151+
expect(render(reactElements)).toBe('<ul><li></li><li></li></ul>');
152+
});
153+
});
154+
155+
describe('trim option', () => {
156+
it('preserves whitespace text nodes when disabled (default)', () => {
157+
const html = `<table>
201158
<tbody>
202159
</tbody>
203160
</table>`;
204-
const reactElement = parse(html);
205-
206-
expect(render(reactElement)).toBe(html);
207-
});
161+
const reactElement = parse(html);
162+
expect(render(reactElement)).toBe(html);
163+
});
208164

209-
it('removes whitespace text nodes when enabled', () => {
210-
const html = `<table>
165+
it('removes whitespace text nodes when enabled', () => {
166+
const html = `<table>
211167
<tbody><tr><td> text </td><td> </td>\t</tr>\r</tbody>\n</table>`;
212-
const options = { trim: true };
213-
const reactElement = parse(html, options);
214-
215-
expect(render(reactElement)).toBe(
216-
'<table><tbody><tr><td> text </td><td></td></tr></tbody></table>'
217-
);
218-
});
168+
const options = { trim: true };
169+
const reactElement = parse(html, options);
170+
expect(render(reactElement)).toBe(
171+
'<table><tbody><tr><td> text </td><td></td></tr></tbody></table>'
172+
);
219173
});
220174
});

0 commit comments

Comments
 (0)