Skip to content

Commit 03273b7

Browse files
committed
chore: better HTML normalization test helper
1 parent b5fcd11 commit 03273b7

File tree

6 files changed

+66
-48
lines changed

6 files changed

+66
-48
lines changed

packages/svelte/tests/html_equal.js

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@ import { assert } from 'vitest';
33
/** @param {Element} node */
44
function clean_children(node) {
55
let previous = null;
6+
let has_element_children = false;
7+
let template =
8+
node.nodeName === 'TEMPLATE' ? /** @type {HTMLTemplateElement} */ (node) : undefined;
9+
10+
if (template) {
11+
const div = document.createElement('div');
12+
div.append(template.content);
13+
node = div;
14+
}
615

716
// sort attributes
817
const attributes = Array.from(node.attributes).sort((a, b) => {
@@ -14,6 +23,10 @@ function clean_children(node) {
1423
});
1524

1625
attributes.forEach((attr) => {
26+
if ((attr.name === 'onload' || attr.name === 'onerror') && attr.value === 'this.__e=event') {
27+
return;
28+
}
29+
1730
node.setAttribute(attr.name, attr.value);
1831
});
1932

@@ -27,23 +40,35 @@ function clean_children(node) {
2740
node.tagName !== 'tspan'
2841
) {
2942
node.removeChild(child);
43+
continue;
3044
}
3145

32-
text.data = text.data.replace(/[ \t\n\r\f]+/g, '\n');
46+
text.data = text.data.replace(/[^\S]+/g, ' ');
3347

3448
if (previous && previous.nodeType === 3) {
3549
const prev = /** @type {Text} */ (previous);
3650

3751
prev.data += text.data;
38-
prev.data = prev.data.replace(/[ \t\n\r\f]+/g, '\n');
39-
4052
node.removeChild(text);
53+
4154
text = prev;
55+
text.data = text.data.replace(/[^\S]+/g, ' ');
56+
57+
continue;
4258
}
4359
} else if (child.nodeType === 8) {
4460
// comment
45-
// do nothing
46-
} else {
61+
child.remove();
62+
continue;
63+
} else if (child.nodeType === 1) {
64+
if (previous?.nodeType === 3) {
65+
const prev = /** @type {Text} */ (previous);
66+
prev.data = prev.data.replace(/^[^\S]+$/, '\n');
67+
} else if (previous?.nodeType === 1) {
68+
node.insertBefore(document.createTextNode('\n'), child);
69+
}
70+
71+
has_element_children = true;
4772
clean_children(/** @type {Element} */ (child));
4873
}
4974

@@ -53,37 +78,35 @@ function clean_children(node) {
5378
// collapse whitespace
5479
if (node.firstChild && node.firstChild.nodeType === 3) {
5580
const text = /** @type {Text} */ (node.firstChild);
56-
text.data = text.data.replace(/^[ \t\n\r\f]+/, '');
57-
if (!text.data.length) node.removeChild(text);
81+
text.data = text.data.trimStart();
5882
}
5983

6084
if (node.lastChild && node.lastChild.nodeType === 3) {
6185
const text = /** @type {Text} */ (node.lastChild);
62-
text.data = text.data.replace(/[ \t\n\r\f]+$/, '');
63-
if (!text.data.length) node.removeChild(text);
86+
text.data = text.data.trimEnd();
87+
}
88+
89+
if (has_element_children && node.parentNode) {
90+
node.innerHTML = `\n\t${node.innerHTML.replace(/\n/g, '\n\t')}\n`;
91+
}
92+
93+
if (template) {
94+
template.innerHTML = node.innerHTML;
6495
}
6596
}
6697

6798
/**
6899
* @param {Window} window
69100
* @param {string} html
70-
* @param {{ removeDataSvelte?: boolean, preserveComments?: boolean }} param2
101+
* @param {{ preserveComments?: boolean }} opts
71102
*/
72-
export function normalize_html(
73-
window,
74-
html,
75-
{ removeDataSvelte = false, preserveComments = false }
76-
) {
103+
export function normalize_html(window, html, { preserveComments = false } = {}) {
77104
try {
78105
const node = window.document.createElement('div');
79-
node.innerHTML = html
80-
.replace(/(<!(--)?.*?\2>)/g, preserveComments ? '$1' : '')
81-
.replace(/(data-svelte-h="[^"]+")/g, removeDataSvelte ? '' : '$1')
82-
.replace(/>[ \t\n\r\f]+</g, '><')
83-
// Strip out the special onload/onerror hydration events from the test output
84-
.replace(/\s?onerror="this.__e=event"|\s?onload="this.__e=event"/g, '')
85-
.trim();
106+
node.innerHTML = html.replace(/(<!(--)?.*?\2>)/g, preserveComments ? '$1' : '').trim();
107+
86108
clean_children(node);
109+
87110
return node.innerHTML;
88111
} catch (err) {
89112
throw new Error(`Failed to normalize HTML:\n${html}\nCause: ${err}`);
@@ -98,22 +121,15 @@ export function normalize_new_line(html) {
98121
return html.replace(/\r\n/g, '\n');
99122
}
100123

101-
/**
102-
* @param {{ removeDataSvelte?: boolean }} options
103-
*/
104-
export function setup_html_equal(options = {}) {
124+
export function setup_html_equal() {
105125
/**
106126
* @param {string} actual
107127
* @param {string} expected
108128
* @param {string} [message]
109129
*/
110130
const assert_html_equal = (actual, expected, message) => {
111131
try {
112-
assert.deepEqual(
113-
normalize_html(window, actual, options),
114-
normalize_html(window, expected, options),
115-
message
116-
);
132+
assert.deepEqual(normalize_html(window, actual), normalize_html(window, expected), message);
117133
} catch (e) {
118134
if (Error.captureStackTrace)
119135
Error.captureStackTrace(/** @type {Error} */ (e), assert_html_equal);
@@ -137,15 +153,17 @@ export function setup_html_equal(options = {}) {
137153
try {
138154
assert.deepEqual(
139155
withoutNormalizeHtml
140-
? normalize_new_line(actual.trim())
141-
.replace(/(\sdata-svelte-h="[^"]+")/g, options.removeDataSvelte ? '' : '$1')
142-
.replace(/(<!(--)?.*?\2>)/g, preserveComments !== false ? '$1' : '')
143-
: normalize_html(window, actual.trim(), { ...options, preserveComments }),
156+
? normalize_new_line(actual.trim()).replace(
157+
/(<!(--)?.*?\2>)/g,
158+
preserveComments !== false ? '$1' : ''
159+
)
160+
: normalize_html(window, actual.trim(), { preserveComments }),
144161
withoutNormalizeHtml
145-
? normalize_new_line(expected.trim())
146-
.replace(/(\sdata-svelte-h="[^"]+")/g, options.removeDataSvelte ? '' : '$1')
147-
.replace(/(<!(--)?.*?\2>)/g, preserveComments !== false ? '$1' : '')
148-
: normalize_html(window, expected.trim(), { ...options, preserveComments }),
162+
? normalize_new_line(expected.trim()).replace(
163+
/(<!(--)?.*?\2>)/g,
164+
preserveComments !== false ? '$1' : ''
165+
)
166+
: normalize_html(window, expected.trim(), { preserveComments }),
149167
message
150168
);
151169
} catch (e) {

packages/svelte/tests/runtime-legacy/samples/binding-select/_config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export default test({
2525
<p>selected: one</p>
2626
2727
<select>
28-
<option${variant === 'hydrate' ? ' selected' : ''}>one</option$>
28+
<option${variant === 'hydrate' ? ' selected' : ''}>one</option>
2929
<option>two</option>
3030
<option>three</option>
3131
</select>
@@ -54,7 +54,7 @@ export default test({
5454
<p>selected: two</p>
5555
5656
<select>
57-
<option${variant === 'hydrate' ? ' selected' : ''}>one</option$>
57+
<option${variant === 'hydrate' ? ' selected' : ''}>one</option>
5858
<option>two</option>
5959
<option>three</option>
6060
</select>

packages/svelte/tests/runtime-legacy/samples/input-list/_config.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ export default test({
44
html: `
55
<input list='suggestions'>
66
<datalist id='suggestions'>
7-
<option value='foo'/><option value='bar'/><option value='baz'/>
7+
<option value='foo'></option>
8+
<option value='bar'></option>
9+
<option value='baz'></option>
810
</datalist>
911
`
1012
});

packages/svelte/tests/runtime-legacy/samples/namespace-html/_config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export default test({
99
1010
<math>
1111
<mrow></mrow>
12-
</svg>
12+
</math>
1313
1414
<div class="hi">hi</div>
1515
`,

packages/svelte/tests/runtime-legacy/samples/select-in-each/_config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default test({
77
target.innerHTML,
88
`
99
<select>
10-
<option${variant === 'hydrate' ? ' selected' : ''} value="a">A</option$>
10+
<option${variant === 'hydrate' ? ' selected' : ''} value="a">A</option>
1111
<option value="b">B</option>
1212
</select>
1313
selected: a
@@ -23,7 +23,7 @@ export default test({
2323
target.innerHTML,
2424
`
2525
<select>
26-
<option${variant === 'hydrate' ? ' selected' : ''} value="a">A</option$>
26+
<option${variant === 'hydrate' ? ' selected' : ''} value="a">A</option>
2727
<option value="b">B</option>
2828
</select>
2929
selected: b

packages/svelte/tests/runtime-legacy/shared.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,7 @@ function unhandled_rejection_handler(err: Error) {
8686

8787
const listeners = process.rawListeners('unhandledRejection');
8888

89-
const { assert_html_equal, assert_html_equal_with_options } = setup_html_equal({
90-
removeDataSvelte: true
91-
});
89+
const { assert_html_equal, assert_html_equal_with_options } = setup_html_equal();
9290

9391
beforeAll(() => {
9492
// @ts-expect-error TODO huh?

0 commit comments

Comments
 (0)