@domx/statecontroller
Version:
A StateController base class for handling data state changes on a LitElement
146 lines (119 loc) • 5.39 kB
text/typescript
import { html, LitElement } from "lit";
import { customElement, property } from "lit/decorators.js";
import { StateController, RootState } from "../StateController";
import { stateProperty, windowEvent, hostEvent } from "../decorators";
import { fixture } from "@domx/testutils/fixture";
describe("StateController/decorators", () => {
describe("trackState", () => {
it("it adds a state property to the controller constructor", () => {
const el = fixture<TestElement1>(html`<test-element-1></test-element-1>`);
expect(el.testState instanceof StateController).toBe(true);
expect((el.testState.constructor as typeof StateController).stateProperties[0]).toBe("state");
el.restore();
});
});
describe("windowEvent", () => {
it("it handles the event", () => {
const el = fixture<TestElement1>(html`<test-element-1></test-element-1>`);
expect(el.testState.state.foo).toBe("bar");
el.testWindowEvent("new foo value");
expect(el.testState.state.foo).toBe("new foo value");
el.restore();
});
it("removes the event handler when disconnected", () => {
const el = fixture<TestElement1>(html`<test-element-1></test-element-1>`);
expect(el.testState.state.foo).toBe("bar");
el.testWindowEvent("new foo value");
expect(el.testState.state.foo).toBe("new foo value");
el.restore();
el.testWindowEvent("new foo value 2");
expect(el.testState.state.foo).toBe("new foo value");
});
});
describe("hostEvent", () => {
it("it handles the event", () => {
const el = fixture<TestElement1>(html`<test-element-1></test-element-1>`);
expect(el.testState.state.foo).toBe("bar");
el.testHostEvent("new foo value");
expect(el.testState.state.foo).toBe("new foo value");
el.restore();
});
it("removes the event handler when disconnected", () => {
const el = fixture<TestElement1>(html`<test-element-1></test-element-1>`);
expect(el.testState.state.foo).toBe("bar");
el.testHostEvent("new foo value");
expect(el.testState.state.foo).toBe("new foo value");
el.restore();
el.testWindowEvent("new foo value 2");
expect(el.testState.state.foo).toBe("new foo value");
});
});
describe("capture", () => {
it("stops propagation when the capture option is not set", () => {
const el = fixture<TestElement1>(html`<test-element-1></test-element-1>`);
const el2 = document.createElement("test-element-1") as TestElement1;
el.parentElement?.appendChild(el2);
const elSpy = jest.spyOn( el.testState, "testHostEvent");
const el2Spy = jest.spyOn(el2.testState, "testHostEvent");
el.testHostEvent("foo");
expect(elSpy).toBeCalledTimes(1);
expect(el2Spy).toBeCalledTimes(0);
el2.parentElement?.removeChild(el2);
el.restore();
});
it("does not stop propagation when the capture option is set to false", () => {
const el = fixture<TestElement1>(html`<test-element-1></test-element-1>`);
const el2 = document.createElement("test-element-1") as TestElement1;
el.parentElement?.appendChild(el2);
const elSpy = jest.spyOn( el.testState, "testWindowEvent");
const el2Spy = jest.spyOn(el2.testState, "testWindowEvent");
el.testWindowEvent("foo");
expect(elSpy).toBeCalledTimes(1);
expect(el2Spy).toBeCalledTimes(1);
el2.parentElement?.removeChild(el2);
el.restore();
});
});
});
interface ITestControllerStateData {
foo: string
}
class TestWindowEvent extends Event {
static eventType = "test-window-event";
testValue:string;
constructor(testValue:string) {
super(TestWindowEvent.eventType, { bubbles: true, composed: true});
this.testValue = testValue;
}
}
class TestHostEvent extends Event {
static eventType = "test-host-event";
testValue:string;
constructor(testValue:string) {
super(TestHostEvent.eventType);
this.testValue = testValue;
}
}
class TestStateController1 extends StateController {
static defaultState:ITestControllerStateData = { foo: "bar"};
()
state:ITestControllerStateData = TestStateController1.defaultState;
(TestWindowEvent, {capture: false})
testWindowEvent(event:TestWindowEvent) {
this.state = { foo: event.testValue };
}
(TestHostEvent)
testHostEvent(event:TestHostEvent) {
this.state = { foo: event.testValue };
}
}
("test-element-1")
class TestElement1 extends LitElement {
public testState = new TestStateController1(this);
public testWindowEvent(testValue:string) {
this.dispatchEvent(new TestWindowEvent(testValue));
}
public testHostEvent(testValue:string) {
this.dispatchEvent(new TestHostEvent(testValue));
}
}