v0.0.13: Refactored the render-loop to solve hard-to-track bugs and added more (elaborate) unit-tests to make sure it all works
This commit is contained in:
169
jest/components/shadow-dom.test.js
Normal file
169
jest/components/shadow-dom.test.js
Normal file
@@ -0,0 +1,169 @@
|
||||
import { render, CustomElement, Host, ShadowDOM, defineElement, state, prop } from "@cerxes/csx";
|
||||
import { testContainer } from "../utils/test-container";
|
||||
import { nextAnimationFrame } from "../utils/next-animation-frame";
|
||||
|
||||
describe("Shadow-DOM tests", () => {
|
||||
/**
|
||||
* Assert that shadow dom behaves as expected
|
||||
*/
|
||||
test("Simple shadow-component", async () => {
|
||||
@defineElement('shadow-component')
|
||||
class ShadowComponent extends CustomElement{
|
||||
@prop()
|
||||
title = 'Content here';
|
||||
|
||||
render(){
|
||||
return (
|
||||
<Host>
|
||||
<ShadowDOM>
|
||||
<div>
|
||||
<h1>{this.title}</h1>
|
||||
<slot />
|
||||
</div>
|
||||
</ShadowDOM>
|
||||
</Host>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let initialVSpec = <ShadowComponent />;
|
||||
let rendered = render(initialVSpec);
|
||||
let container = testContainer(rendered);
|
||||
document.body.appendChild(container);// Components need to be added to the DOM or their connectecCallback will not be called
|
||||
|
||||
// Initial render
|
||||
expect(
|
||||
container.innerHTML
|
||||
).toBe([
|
||||
`<shadow-component>`,
|
||||
`</shadow-component>`,
|
||||
].join(''));
|
||||
|
||||
expect(
|
||||
rendered.shadowRoot.innerHTML
|
||||
).toBe([
|
||||
`<div>`,
|
||||
`<h1>Content here</h1>`,
|
||||
`<slot></slot>`,
|
||||
`</div>`,
|
||||
].join(''));
|
||||
|
||||
// Update behaves as it should
|
||||
let updatedVSpec = (
|
||||
<ShadowComponent title={"New content here"}>
|
||||
<li><ul>contents</ul></li>
|
||||
</ShadowComponent>
|
||||
);
|
||||
render(updatedVSpec, {host: rendered, old: initialVSpec});
|
||||
|
||||
// Wait for it to update
|
||||
await nextAnimationFrame();
|
||||
|
||||
expect(
|
||||
container.innerHTML
|
||||
).toBe([
|
||||
`<shadow-component>`,
|
||||
`<li><ul>contents</ul></li>`,
|
||||
`</shadow-component>`,
|
||||
].join(''));
|
||||
|
||||
expect(
|
||||
rendered.shadowRoot.innerHTML
|
||||
).toBe([
|
||||
`<div>`,
|
||||
`<h1>New content here</h1>`,
|
||||
`<slot></slot>`,
|
||||
`</div>`,
|
||||
].join(''));
|
||||
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
|
||||
test("Nested shadow-component", async () => {
|
||||
@defineElement('todo-item')
|
||||
class TodoItem extends CustomElement {
|
||||
@prop()
|
||||
get model(){ return this.#model; }
|
||||
set model(value){ this.#model = value; }
|
||||
|
||||
#model;
|
||||
|
||||
render(){
|
||||
return (
|
||||
<Host>
|
||||
<ShadowDOM>
|
||||
<input type="checkbox" checked={ this.model.checked }/>
|
||||
<label>
|
||||
<slot />
|
||||
</label>
|
||||
</ShadowDOM>
|
||||
</Host>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@defineElement('my-todo')
|
||||
class MyTodo extends CustomElement {
|
||||
@state()
|
||||
todos = [
|
||||
{ text: "todo 1", checked: true },
|
||||
{ text: "todo 2", checked: false },
|
||||
];
|
||||
|
||||
rendered = [];
|
||||
|
||||
render(){
|
||||
return (
|
||||
<Host>
|
||||
<h1>Todos</h1>
|
||||
<ul>
|
||||
{this.todos.map((todo,index)=>(
|
||||
<TodoItem model={todo}
|
||||
ref={(el)=>this.rendered[index]=el}
|
||||
>
|
||||
{todo.text}
|
||||
</TodoItem>
|
||||
))}
|
||||
</ul>
|
||||
</Host>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let initialVSpec = <MyTodo />;
|
||||
let rendered = render(initialVSpec);
|
||||
let container = testContainer(rendered);
|
||||
document.body.appendChild(container);// Components need to be added to the DOM or their connectecCallback will not be called
|
||||
|
||||
// Initial render
|
||||
expect(
|
||||
container.innerHTML
|
||||
).toBe([
|
||||
`<my-todo>`,
|
||||
`<h1>Todos</h1>`,
|
||||
`<ul>`,
|
||||
...rendered.todos.map(todo=>(
|
||||
`<todo-item>${todo.text}</todo-item>`
|
||||
)),
|
||||
`</ul>`,
|
||||
`</my-todo>`,
|
||||
].join(''));
|
||||
|
||||
for(let i = 0; i < rendered.todos.length; ++i){
|
||||
let todo = rendered.todos[i];
|
||||
let el = rendered.rendered[i];
|
||||
expect(el).not.toBeUndefined();
|
||||
expect(
|
||||
el.shadowRoot.innerHTML
|
||||
).toBe([
|
||||
`<input type="checkbox"${todo.checked? ' checked=""': ''}>`,
|
||||
`<label>`,
|
||||
`<slot></slot>`,
|
||||
`</label>`
|
||||
].join(''));
|
||||
}
|
||||
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user