UNPKG

@joist/element

Version:

Intelligently apply styles to WebComponents

195 lines (149 loc) 4.38 kB
import { assert, expect } from "chai"; import { attr } from "./attr.js"; import { element } from "./element.js"; import { css, html } from "./tags.js"; it("should write default value to attribute", async () => { @element({ tagName: "element-1", }) class MyElement extends HTMLElement { @attr() accessor value1 = "hello"; // no attribute @attr() accessor value2 = 0; // number @attr() accessor value3 = true; // boolean @attr({ reflect: false }) accessor value4 = "foo"; } const el = new MyElement(); document.body.append(el); expect(el.getAttribute("value1")).to.equal("hello"); expect(el.getAttribute("value2")).to.equal("0"); expect(el.getAttribute("value3")).to.equal(""); expect(el.getAttribute("value4")).to.equal(null); el.remove(); }); it("should register attributes", async () => { const observedAttrs: string[] = []; @element({ tagName: "element-2", }) class MyElement extends HTMLElement { @attr() accessor value1 = "hello"; @attr() accessor value2 = 0; @attr() accessor value3 = true; @attr({ observed: false }) accessor value4 = "hello world"; attributeChangedCallback(name: string) { observedAttrs.push(name); } } const el = new MyElement(); el.setAttribute("value1", "foo"); el.setAttribute("value2", "1"); el.setAttribute("value3", "false"); el.setAttribute("value4", "bar"); expect(observedAttrs).to.deep.equal(["value1", "value2", "value3"]); }); it("should attach shadow root when the shadow property exists", async () => { @element({ tagName: "element-3", shadowDom: [], }) class MyElement extends HTMLElement {} const el = new MyElement(); expect(el.shadowRoot).to.be.instanceOf(ShadowRoot); }); it("should apply html and css", async () => { @element({ tagName: "element-4", shadowDom: [ css` :host { display: contents; } `, html`<slot></slot>`, { apply(el) { const div = document.createElement("div"); div.innerHTML = "hello world"; el.append(div); }, }, ], }) class MyElement extends HTMLElement {} const el = new MyElement(); expect(el.shadowRoot?.adoptedStyleSheets.length).to.equal(1); expect(el.shadowRoot?.innerHTML).to.equal("<slot></slot>"); expect(el.innerHTML).to.equal("<div>hello world</div>"); }); it("should the correct shadow dom mode", async () => { @element({ tagName: "element-5", shadowDom: [], shadowDomOpts: { mode: "closed", }, }) class MyElement extends HTMLElement {} const el = new MyElement(); assert.equal(el.shadowRoot, null); }); it("should wait to register itself until all elements it depends on are also registered", async () => { @element({ tagName: "element-6", dependsOn: ["element-7", "element-8"], }) // @ts-ignore class MyElement6 extends HTMLElement {} assert.isUndefined(customElements.get("element-6")); customElements.define("element-7", class extends HTMLElement {}); customElements.define("element-8", class extends HTMLElement {}); await Promise.all([ customElements.whenDefined("element-7"), customElements.whenDefined("element-8"), ]); assert.equal(customElements.get("element-6"), MyElement6); }); it("should wait to register itself until the custom dependsOn function runs", async () => { let resolver: Function; @element({ tagName: "element-9", dependsOn() { return new Promise((resolve) => { resolver = resolve; }); }, }) // @ts-ignore class MyElement extends HTMLElement {} assert.isUndefined(customElements.get("element-9")); resolver!(); await Promise.resolve(); assert.equal(customElements.get("element-9"), MyElement); }); it("should call disconnectedCallback when element is removed from DOM", async () => { let disconnectedCalled = false; @element({ tagName: "element-10", }) class MyElement extends HTMLElement { disconnectedCallback() { disconnectedCalled = true; } } const el = new MyElement(); document.body.append(el); // Verify element is connected expect(disconnectedCalled).to.be.false; // Remove element from DOM el.remove(); // Verify disconnectedCallback was called expect(disconnectedCalled).to.be.true; });