import { Component, mount, useState } from "../../src";
import { xml } from "../../src/tags";
import { makeTestFixture, nextTick, snapshotEverything, useLogLifecycle } from "../helpers";
let fixture: HTMLElement;
snapshotEverything();
beforeEach(() => {
fixture = makeTestFixture();
});
describe("t-component", () => {
test("t-component works in simple case", async () => {
let steps: string[] = [];
class Child extends Component {
static template = xml`
child
`;
setup() {
useLogLifecycle(steps);
}
}
class Parent extends Component {
static template = xml``;
Child = Child;
setup() {
useLogLifecycle(steps);
}
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("child
");
expect(steps).toEqual([
"Parent:setup",
"Parent:willStart",
"Parent:render",
"Child:setup",
"Child:willStart",
"Child:render",
"Child:mounted",
"Parent:mounted",
]);
});
test("switching dynamic component", async () => {
let steps: string[] = [];
class ChildA extends Component {
static template = xml`child a
`;
setup() {
useLogLifecycle(steps);
}
}
class ChildB extends Component {
static template = xml`child b`;
setup() {
useLogLifecycle(steps);
}
}
class Parent extends Component {
static template = xml``;
Child = ChildA;
setup() {
useLogLifecycle(steps);
}
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("child a
");
parent.Child = ChildB;
parent.render();
await nextTick();
expect(fixture.innerHTML).toBe("child b");
expect(steps).toEqual([
"Parent:setup",
"Parent:willStart",
"Parent:render",
"ChildA:setup",
"ChildA:willStart",
"ChildA:render",
"ChildA:mounted",
"Parent:mounted",
"Parent:render",
"ChildB:setup",
"ChildB:willStart",
"ChildB:render",
"Parent:willPatch",
"ChildA:willUnmount",
"ChildA:destroyed",
"ChildB:mounted",
"Parent:patched",
]);
});
test("can switch between dynamic components without the need for a t-key", async () => {
class A extends Component {
static template = xml`child a`;
}
class B extends Component {
static template = xml`child b`;
}
class App extends Component {
static template = xml`
`;
static components = { A, B };
state = useState({ child: "A" });
}
const app = await mount(App, fixture);
expect(fixture.innerHTML).toBe("child a
");
app.state.child = "B";
await nextTick();
expect(fixture.innerHTML).toBe("child b
");
});
test("can use dynamic components (the class) if given", async () => {
class A extends Component {
static template = xml`child a`;
}
class B extends Component {
static template = xml`child b`;
}
class Parent extends Component {
static template = xml``;
state = useState({
child: "a",
});
get myComponent() {
return this.state.child === "a" ? A : B;
}
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("child a");
parent.state.child = "b";
await nextTick();
expect(fixture.innerHTML).toBe("child b");
});
test("can use dynamic components (the class) if given (with different root tagname)", async () => {
class A extends Component {
static template = xml`child a`;
}
class B extends Component {
static template = xml`child b
`;
}
class Parent extends Component {
static template = xml``;
state = useState({
child: "a",
});
get myComponent() {
return this.state.child === "a" ? A : B;
}
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("child a");
parent.state.child = "b";
await nextTick();
expect(fixture.innerHTML).toBe("child b
");
});
test("modifying a sub widget", async () => {
class Counter extends Component {
static template = xml`
`;
state = useState({
counter: 0,
});
}
class ParentWidget extends Component {
static template = xml`
`;
get Counter() {
return Counter;
}
}
await mount(ParentWidget, fixture);
expect(fixture.innerHTML).toBe("");
const button = fixture.getElementsByTagName("button")[0];
await button.click();
await nextTick();
expect(fixture.innerHTML).toBe("");
});
});