Skip to content

Commit

Permalink
All tests passing!
Browse files Browse the repository at this point in the history
  • Loading branch information
tbranyen committed Nov 19, 2022
1 parent d657635 commit d7ec910
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 41 deletions.
24 changes: 12 additions & 12 deletions packages/diffhtml-components/test/integration/web-component.js
Expand Up @@ -95,7 +95,7 @@ describe('Web Component', function() {
equal(this.fixture.innerHTML, '<custom-component></custom-component>');
});

it.skip('will re-render a component with string props', async () => {
it('will re-render a component with string props', async () => {
class CustomComponent extends Component {
render() {
return html`
Expand All @@ -117,11 +117,11 @@ describe('Web Component', function() {

await instance.forceUpdate();

equal(instance.shadowRoot.childNodes[0].outerHTML, '<div>world</div>');
equal(instance.shadowRoot.childNodes[1].outerHTML, '<div>world</div>');
equal(this.fixture.innerHTML, '<custom-component message="world"></custom-component>');
});

it.skip('will re-render a component with object props', async () => {
it('will re-render a component with object props', async () => {
class CustomComponent extends Component {
render() {
return html`
Expand All @@ -148,11 +148,11 @@ describe('Web Component', function() {

await instance.forceUpdate();

equal(instance.shadowRoot.childNodes[0].outerHTML, '<div>world</div>');
equal(instance.shadowRoot.childNodes[1].outerHTML, '<div>world</div>');
equal(this.fixture.innerHTML, '<custom-component></custom-component>');
});

it.skip('will re-render a nested component with object props', async () => {
it('will re-render a nested component with object props', async () => {
class InnerComponent extends Component {
render() {
return html`
Expand Down Expand Up @@ -187,7 +187,7 @@ describe('Web Component', function() {
const outer = this.fixture.querySelector('outer-component');
const inner = outer.shadowRoot.querySelector('inner-component');

equal(inner.shadowRoot.childNodes[0].outerHTML, '<div>hello</div>');
equal(inner.shadowRoot.childNodes[1].outerHTML, '<div>hello</div>');
equal(this.fixture.innerHTML, '<outer-component></outer-component>');

message.contents = 'world';
Expand All @@ -197,7 +197,7 @@ describe('Web Component', function() {
await outer.forceUpdate();
await inner.forceUpdate();

equal(inner.shadowRoot.childNodes[0].outerHTML, '<div>world</div>');
equal(inner.shadowRoot.childNodes[1].outerHTML, '<div>world</div>');
equal(this.fixture.innerHTML, '<outer-component></outer-component>');
});

Expand All @@ -221,7 +221,7 @@ describe('Web Component', function() {
equal(this.fixture.innerHTML, '<div><custom-component></custom-component></div>');
});

it.skip('will re-render a nested component with props', () => {
it('will re-render a nested component with props', () => {
class OuterComponent extends Component {
render() {
return html`
Expand Down Expand Up @@ -264,7 +264,7 @@ describe('Web Component', function() {
const inner = this.fixture.querySelector('inner-component');
const outer = this.fixture.querySelector('outer-component');

equal(inner.shadowRoot.childNodes[0].outerHTML, '<div>world</div>');
equal(inner.shadowRoot.childNodes[1].outerHTML, '<div>world</div>');
equal(
this.fixture.innerHTML.replace(whitespaceEx, ''),
'<outer-component><inner-component message="world"></inner-component></outer-component>',
Expand Down Expand Up @@ -446,7 +446,7 @@ describe('Web Component', function() {
});

describe('Stateful components', () => {
it.skip('will re-render with setState', async () => {
it('will re-render with setState', async () => {
let ref = null;

customElements.define('stateful-test', class extends Component {
Expand All @@ -469,14 +469,14 @@ describe('Web Component', function() {
);

equal(
this.fixture.firstChild.shadowRoot.childNodes[0].outerHTML,
this.fixture.firstChild.shadowRoot.childNodes[1].outerHTML,
'<div>default</div>',
);

await ref.setState({ msg: 'it works' });

equal(
this.fixture.firstChild.shadowRoot.childNodes[0].outerHTML,
this.fixture.firstChild.shadowRoot.childNodes[1].outerHTML,
'<div>it works</div>',
);
});
Expand Down
8 changes: 7 additions & 1 deletion packages/diffhtml/lib/util/parse.js
Expand Up @@ -47,6 +47,10 @@ const endTagOmissionRules = {
li: { li: EMPTY.NUM },
dt: { dt: EMPTY.NUM, dd: EMPTY.NUM },
dd: { dt: EMPTY.NUM, dd: EMPTY.NUM },
td: { td: EMPTY.NUM, th: EMPTY.NUM },
th: { td: EMPTY.NUM, th: EMPTY.NUM },
tbody: { tbody: EMPTY.NUM, tfoot: EMPTY.NUM },
tfoot: { tbody: EMPTY.NUM, tfoot: EMPTY.NUM },
};

// List of regular expressions to match various HTML features.
Expand Down Expand Up @@ -367,13 +371,15 @@ export default function parse(html, options = {}) {
index: textIndex,
} = text.exec(html) || EMPTY.OBJ;

if (!isOpen && textIndex === i) {
if (!isOpen && textIndex === i && fullTextMatch.length) {
const newTree = createTree('#text', fullTextMatch);
pointer.childNodes.push(newTree);
i = textIndex + fullTextMatch.length;
continue;
}

// Use remaining values as text
pointer.childNodes.push(createTree('#text', html.slice(i, html.length)));
i = html.length;
}

Expand Down
65 changes: 37 additions & 28 deletions packages/diffhtml/test/util.js
Expand Up @@ -422,7 +422,7 @@ describe('Util', () => {
// Elements

it('will parse a comment', (...parseOpts) => {
const vTree = parse('<!-- This is a comment -->', ...parseOpts);
const vTree = parse('<!-- This is a comment -->');

strictEqual(vTree.childNodes[0].nodeName, '#comment');
strictEqual(vTree.childNodes[0].nodeValue.trim(), 'This is a comment');
Expand All @@ -431,14 +431,14 @@ describe('Util', () => {
it('will parse a multi-line comment', (...parseOpts) => {
const vTree = parse(`<!--
This is a comment
-->`, ...parseOpts);
-->`);

strictEqual(vTree.childNodes[0].nodeName, '#comment');
strictEqual(vTree.childNodes[0].nodeValue.trim(), 'This is a comment');
});

it('will parse multiple comments', (...parseOpts) => {
const vTree = parse('<!-- Comment 1 --><!-- Comment 2 -->', ...parseOpts);
const vTree = parse('<!-- Comment 1 --><!-- Comment 2 -->');

strictEqual(vTree.childNodes[0].nodeName, '#comment');
strictEqual(vTree.childNodes[0].nodeValue.trim(), 'Comment 1');
Expand All @@ -448,21 +448,21 @@ describe('Util', () => {
});

it('will parse comment without closing tag', (...parseOpts) => {
const vTree = parse('<!-- Comment 1 ', ...parseOpts);
const vTree = parse('<!-- Comment 1 ');

strictEqual(vTree.childNodes[0].nodeName, '#comment');
strictEqual(vTree.childNodes[0].nodeValue.trim(), 'Comment 1');
});

it('will parse comment with html markup', (...parseOpts) => {
const vTree = parse('<!-- <div></div> -->', ...parseOpts);
const vTree = parse('<!-- <div></div> -->');

strictEqual(vTree.childNodes[0].nodeName, '#comment');
strictEqual(vTree.childNodes[0].nodeValue.trim(), '<div></div>');
});

it('will parse text', (...parseOpts) => {
const vTree = parse('This is text', ...parseOpts);
const vTree = parse('This is text');

strictEqual(vTree.childNodes[0].nodeName, '#text');
strictEqual(vTree.childNodes[0].nodeValue, 'This is text');
Expand All @@ -471,42 +471,51 @@ describe('Util', () => {
it('will parse multi-line text', (...parseOpts) => {
const vTree = parse(`
This is text
`, ...parseOpts);
`);

strictEqual(vTree.childNodes[0].nodeName, '#text');
strictEqual(vTree.childNodes[0].nodeValue.trim(), 'This is text');
});

it('will ignore doctypes', (...parseOpts) => {
const vTree = parse('<!doctype html>', ...parseOpts).childNodes[0];
const vTree = parse('<!doctype html>').childNodes[0];
strictEqual(vTree, undefined);
});

it('will parse text after an element', (...parseOpts) => {
const vTrees = parse(`<div></div> Hello world`, ...parseOpts).childNodes;
const vTrees = parse(`<div></div> Hello world`).childNodes;

strictEqual(vTrees[0].nodeName, 'div');
strictEqual(vTrees[1].nodeName, '#text');
strictEqual(vTrees[1].nodeValue, ' Hello world');
});

it('will parse text before an element', (...parseOpts) => {
const vTrees = parse(`Hello <div></div>`, ...parseOpts).childNodes;
const vTrees = parse(`Hello <div></div>`).childNodes;

strictEqual(vTrees.length, 2);
strictEqual(vTrees[0].nodeName, '#text');
strictEqual(vTrees[0].nodeValue, 'Hello ');
strictEqual(vTrees[1].nodeName, 'div');
});

it('will parse invalid markup as text', () => {
const vTrees = parse(`
<>"']/;
test
`).childNodes;

strictEqual(vTrees[1].nodeValue, `<>"']/;\n test\n `);
});

it('will parse an open tag', (...parseOpts) => {
const vTree = parse('<div>', ...parseOpts);
const vTree = parse('<div>');

strictEqual(vTree.childNodes[0].nodeName, 'div');
});

it('will support single line parsing with nested element', (...parseOpts) => {
const vTree = parse('<a href="#"><img src="#"></a>', ...parseOpts).childNodes[0];
const vTree = parse('<a href="#"><img src="#"></a>').childNodes[0];

strictEqual(vTree.nodeName, 'a');
strictEqual(vTree.attributes.href, '#');
Expand All @@ -515,47 +524,47 @@ describe('Util', () => {
});

it('will support boolean attributes', (...parseOpts) => {
const vTree = parse('<option value="test" selected></option>', ...parseOpts).childNodes[0];
const vTree = parse('<option value="test" selected></option>').childNodes[0];

strictEqual(vTree.attributes.value, 'test');
strictEqual(vTree.attributes.selected, true);
});

it('will parse links without quotes', (...parseOpts) => {
const vTree = parse('<a href=http://google.com>Google</a>', ...parseOpts).childNodes[0];
const vTree = parse('<a href=http://google.com>Google</a>').childNodes[0];
strictEqual(vTree.attributes.href, 'http://google.com');
});

it('will support quote-less values', (...parseOpts) => {
const vTree = parse('<option value=test></option>', ...parseOpts).childNodes[0];
const vTree = parse('<option value=test></option>').childNodes[0];
strictEqual(vTree.attributes.value, 'test');
});

it('will not parse whitespace from inside <html></html> tags', (...parseOpts) => {
const vTree = parse('<html>\n</html>', ...parseOpts).childNodes[0];
const vTree = parse('<html>\n</html>').childNodes[0];
strictEqual(vTree.childNodes.length, 2); // head & body
});

it('will support simple text attributes alongside an empty attribute', (...parseOpts) => {
const vTree = parse('<option value="test" selected=""></option>', ...parseOpts).childNodes[0];
const vTree = parse('<option value="test" selected=""></option>').childNodes[0];

strictEqual(vTree.attributes.value, 'test');
strictEqual(vTree.attributes.selected, '');
});

it('will support HTML comments inside script tags', (...parseOpts) => {
const vTree = parse('<script>before<!-- in -->after</script>', ...parseOpts).childNodes[0];
const vTree = parse('<script>before<!-- in -->after</script>').childNodes[0];
strictEqual(vTree.childNodes[0].nodeValue, 'before<!-- in -->after');
});

it('will support dot attributes', (...parseOpts) => {
const vTree = parse('<option dot.value="test" />', ...parseOpts).childNodes[0];
const vTree = parse('<option dot.value="test" />').childNodes[0];

strictEqual(vTree.attributes['dot.value'], 'test');
});

it('will properly separate elements on a single line', (...parseOpts) => {
const { childNodes } = parse(`<div attr="1" /><p attr="2">test</p>`, ...parseOpts);
const { childNodes } = parse(`<div attr="1" /><p attr="2">test</p>`);

strictEqual(childNodes.length, 2);
});
Expand All @@ -566,7 +575,7 @@ describe('Util', () => {
<body></body>
<script></script>
</html>
`.trim(), ...parseOpts).childNodes[0];
`.trim()).childNodes[0];

strictEqual(vTree.childNodes.length, 2);
strictEqual(vTree.childNodes[0].nodeName, 'head');
Expand All @@ -585,7 +594,7 @@ describe('Util', () => {
<body></body>
<p></p>
</html>
`.trim(), ...parseOpts).childNodes[0];
`.trim()).childNodes[0];

strictEqual(vTree.childNodes.length, 2);
strictEqual(vTree.childNodes[0].nodeName, 'head');
Expand All @@ -599,22 +608,22 @@ describe('Util', () => {
});

it('will support brackets in attribute values', (...parseOpts) => {
const vTree = parse(`<a data-text="<>"></a>`, ...parseOpts).childNodes[0];
const vTree = parse(`<a data-text="<>"></a>`).childNodes[0];

strictEqual(vTree.nodeName, 'a');
strictEqual(vTree.attributes['data-text'], '<>');
});

it('will support complex markup in attribute values', (...parseOpts) => {
const vTree = parse(`<a data-text="<li class='test'></li>"></a>`, ...parseOpts).childNodes[0];
const vTree = parse(`<a data-text="<li class='test'></li>"></a>`).childNodes[0];

strictEqual(vTree.nodeName, 'a');
strictEqual(vTree.attributes['data-text'], '<li class=\'test\'></li>');
});

it('will parse out full token attributes', (...parseOpts) => {
const token = '__DIFFHTML_BABEL__';
const vTrees = parse(`<input ${token}/>`, ...parseOpts).childNodes;
const vTrees = parse(`<input ${token}/>`).childNodes;

strictEqual(vTrees[0].nodeName, 'input');
deepStrictEqual(vTrees[0].attributes, { [token]: true });
Expand All @@ -624,7 +633,7 @@ describe('Util', () => {
it('will support mixed cased elements being self closed', (...parseOpts) => {
const vTrees = parse(`<CustomElement
attr="test"
/><div>Hello world</div>`, ...parseOpts).childNodes;
/><div>Hello world</div>`).childNodes;

strictEqual(vTrees[0].nodeName, 'customelement');
deepStrictEqual(vTrees[0].attributes, { attr: 'test' });
Expand Down Expand Up @@ -930,7 +939,7 @@ describe('Util', () => {
it('will correctly parse surrounding text nodes', (...parseOpts) => {
const vTree = parse(`<div>
<h1>Attach/Detach Template</h1>
</div>`, ...parseOpts);
</div>`);

deepStrictEqual(vTree, {
rawNodeName: '#document-fragment',
Expand Down Expand Up @@ -991,7 +1000,7 @@ describe('Util', () => {

it('will correctly parse hard return text node', (...parseOpts) => {
const vTree = parse(`<code>
</code>`, ...parseOpts).childNodes[0];
</code>`).childNodes[0];

deepStrictEqual(vTree, {
"attributes": {},
Expand Down

0 comments on commit d7ec910

Please sign in to comment.