/** * Copyright 2018 Google Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const { html, Component, render } = require('../preact/index.js'); describe('preact-html', () => { const scratch = document.createElement('div'); document.body.appendChild(scratch); class Foo extends Component { render({ name }, { count = 0 }) { return html`

Name: ${name}

Hello world!

Count: ${count}
xml-style end tags: <${Bar} hello /> explicit end tags: <${Bar} hello>some children (count=${count}) implicit end tags: (${''}) <${Bar} hello>some children (count=${count}) some text at the end
`; } } const Bar = ({ hello, children }) => html`
Value of hello: ${hello + ''} ${children}
`; const fullHtml = '
\n\t\t\t\t\t

Name: jason

\n\t\t\t\t\t

Hello world!

\n\t\t\t\t\t\n\t\t\t\t\t
Count: 0
\n\t\t\t\t\txml-style end tags:\n\t\t\t\t\t
\n\t\tValue of hello: true\n\t\t\n\t
\n\t\t\t\t\texplicit end tags:\n\t\t\t\t\t
\n\t\tValue of hello: true\n\t\tsome children (count=0)\n\t
\n\t\t\t\t\timplicit end tags: (<//>)\n\t\t\t\t\t
\n\t\tValue of hello: true\n\t\tsome children (count=0)\n\t
\n\t\t\t\t\tsome text at the end\n\t\t\t\t
'; test('initial render', () => { render(html`<${Foo} name=jason />`, scratch); expect(scratch.innerHTML).toBe(fullHtml); }); test('rerenders in-place', () => { render(html`<${Foo} name=tom />`, scratch); expect(scratch.innerHTML).toBe(fullHtml.replace('jason', 'tom')); }); test('state update re-renders', done => { document.querySelector('button').click(); document.querySelector('button').click(); setTimeout(() => { expect(scratch.innerHTML).toBe(fullHtml.replace('jason', 'tom').replace(/\b0\b/g, '2')); done(); }); }); test('spread props', () => { scratch.textContent = ''; const props = { a: 1, b: 2, c: 3 }; render(html`
`, scratch); expect(scratch.innerHTML).toBe(`
`); scratch.innerHTML = ''; render(html`
`, scratch); expect(scratch.innerHTML).toBe(`
`); scratch.innerHTML = ''; render(html`
`, scratch); expect(scratch.innerHTML).toBe(`
`); scratch.innerHTML = ''; render(html`
`, scratch); expect(scratch.innerHTML).toBe(`
`); }); }); describe('performance', () => { test('creation', () => { const results = []; const Foo = ({ name }) => html`
${name}
`; const statics = [ '\n
\n\t

Hello World

\n\t
    \n\t', '\n\t
\n\t\n\t<', ' name="foo" />\n\t<', ' name="other">content\n\n
' ]; let count = 0; function go(count) { return html( statics.concat(['count:', count]), `id${count}`, html(['
  • ', '
  • '], 'i'+count, 'some text #'+count), Foo, Foo, Foo ); } let now = performance.now(); const start = now; while ((now = performance.now()) < start+2000) { count++; if (results.push(String(go(count)))===10) results.length = 0; } const elapsed = now - start; const hz = count / elapsed * 1000; // eslint-disable-next-line no-console console.log(`Creation: ${hz|0}/s, average: ${elapsed/count.toFixed(4)}ms`); expect(elapsed).toBeGreaterThan(999); expect(hz).toBeGreaterThan(10); }); });