import { App, Component, mount, onMounted, useState, xml } from "../../src/index";
import { children, makeTestFixture, nextTick, snapshotEverything } from "../helpers";
snapshotEverything();
let originalconsoleWarn = console.warn;
let mockConsoleWarn: any;
let fixture: HTMLElement;
beforeEach(() => {
fixture = makeTestFixture();
mockConsoleWarn = jest.fn(() => {});
console.warn = mockConsoleWarn;
});
afterEach(() => {
console.warn = originalconsoleWarn;
});
describe("slots", () => {
test("simple default slot", async () => {
class Child extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml`some text `;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("some text ");
});
test("simple default slot, variation", async () => {
class Child extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml`some text `;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("some text");
});
test("simple slot with slot scope", async () => {
let child: any;
class Child extends Component {
static template = xml` `;
state = useState({ bool: true });
setup() {
child = this;
}
}
class Parent extends Component {
static template = xml`
some text
other text
`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("some text ");
child.state.bool = false;
await nextTick();
expect(fixture.innerHTML).toBe("other text ");
});
test("default slot with slot scope: shorthand syntax", async () => {
let child: any;
class Child extends Component {
static template = xml` `;
state = useState({ bool: true });
setup() {
child = this;
}
}
class Parent extends Component {
static template = xml`
some text
other text
`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("some text ");
child.state.bool = false;
await nextTick();
expect(fixture.innerHTML).toBe("other text ");
});
test("simple default slot with params", async () => {
class Child extends Component {
static template = xml` `;
state = useState({ bool: true });
}
class Parent extends Component {
static template = xml`
some text
other text
`;
static components = { Child };
}
let error = null;
try {
await mount(Parent, fixture);
} catch (e) {
error = e;
}
expect(error).not.toBeNull();
expect(mockConsoleWarn).toBeCalledTimes(1);
});
test("fun: two calls to the same slot", async () => {
class Child extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml`some text `;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("some textsome text");
});
test("slot content is bound to caller", async () => {
class Child extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml`some text `;
static components = { Child };
state = useState({ value: 0 });
inc() {
this.state.value++;
}
}
const parent = await mount(Parent, fixture);
expect(parent.state.value).toBe(0);
fixture.querySelector("button")!.click();
expect(parent.state.value).toBe(1);
});
test("slot content is bound to caller (variation)", async () => {
class Child extends Component {
static template = xml` `;
}
class Parent extends Component {
// t-set t-value in template is to force compiler to protect the scope
// which in turns means that the ctx propagated to the slot is a sub object
static template = xml`
some text
`;
static components = { Child };
state = useState({ value: 0 });
inc() {
expect(this).toBe(parent);
this.state.value++;
}
}
const parent = await mount(Parent, fixture);
expect(parent.state.value).toBe(0);
fixture.querySelector("button")!.click();
expect(parent.state.value).toBe(1);
});
test("can define and call slots", async () => {
class Dialog extends Component {
static template = xml`
`;
}
class Parent extends Component {
static components = { Dialog };
static template = xml`
header
footer
`;
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(
""
);
});
test("can define and call slots with params", async () => {
class Dialog extends Component {
static template = xml`
`;
}
class Parent extends Component {
static components = { Dialog };
static template = xml`
header
footer
`;
var = 3;
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(
""
);
});
test("no named slot content => just no children", async () => {
class Dialog extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml` `;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(" ");
});
test("named slots can define a default content", async () => {
class Dialog extends Component {
static template = xml`
default content
`;
}
class Parent extends Component {
static template = xml`
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("default content
");
});
test("can define a default content", async () => {
class Dialog extends Component {
static template = xml`
default content
`;
}
class Parent extends Component {
static template = xml`
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("default content
");
});
test("default content is not rendered if slot is provided", async () => {
class Dialog extends Component {
static template = xml`
default content
`;
}
class Parent extends Component {
static template = xml`hey
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("hey
");
});
test("default content is not rendered if named slot is provided", async () => {
class Dialog extends Component {
static template = xml`
default content
`;
}
class Parent extends Component {
static template = xml`hey
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("hey
");
});
test("slots are properly bound to correct component", async () => {
let child: any = null;
class Child extends Component {
// t-set t-value in template is to force compiler to protect the scope
// which in turns means that the ctx propagated to the slot is a sub object
static template = xml`
`;
state = useState({ value: 1 });
setup() {
child = this;
}
increment() {
expect(this).toBe(child);
this.state.value++;
}
}
class Parent extends Component {
static template = xml` `;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("1 ");
fixture.querySelector("button")!.click();
await nextTick();
expect(fixture.innerHTML).toBe("2 ");
});
test("slots are rendered with proper context", async () => {
class Dialog extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml`
do something
`;
static components = { Dialog };
state = useState({ val: 0 });
doSomething() {
this.state.val++;
}
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(
'0 do something
'
);
fixture.querySelector("button")!.click();
await nextTick();
expect(fixture.innerHTML).toBe(
'1 do something
'
);
});
test("slots are rendered with proper context, part 2", async () => {
class Link extends Component {
static template = xml`
`;
}
class App extends Component {
static template = xml`
User
`;
state = useState({
users: [
{ id: 1, name: "Aaron" },
{ id: 2, name: "David" },
],
});
static components = { Link };
}
const app = await mount(App, fixture);
expect(fixture.innerHTML).toBe(
''
);
// test updateprops here
app.state.users[1].name = "Mathieu";
await nextTick();
expect(fixture.innerHTML).toBe(
''
);
});
test("slots are rendered with proper context, part 3", async () => {
class Link extends Component {
static template = xml`
`;
}
class App extends Component {
static template = xml`
`;
state = useState({
users: [
{ id: 1, name: "Aaron" },
{ id: 2, name: "David" },
],
});
static components = { Link };
}
const app = await mount(App, fixture);
expect(fixture.innerHTML).toBe(
''
);
// test updateprops here
app.state.users[1].name = "Mathieu";
await nextTick();
expect(fixture.innerHTML).toBe(
''
);
});
test("slots are rendered with proper context, part 4", async () => {
class Link extends Component {
static template = xml`
`;
}
class App extends Component {
static template = xml`
`;
static components = { Link };
state = useState({ user: { id: 1, name: "Aaron" } });
}
const app = await mount(App, fixture);
expect(fixture.innerHTML).toBe('');
// test updateprops here
app.state.user.name = "David";
await nextTick();
expect(fixture.innerHTML).toBe('');
});
test("content is the default slot", async () => {
class Dialog extends Component {
static template = xml`
`;
}
class Parent extends Component {
static template = xml`
sts rocks
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("");
});
test("content is the default slot (variation)", async () => {
class Dialog extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml`
sts rocks
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("sts rocks ");
});
test("default slot work with text nodes", async () => {
class Dialog extends Component {
static template = xml`
`;
}
class Parent extends Component {
static template = xml`
sts rocks
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("");
});
test("default slot work with text nodes (variation)", async () => {
class Dialog extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml`sts rocks `;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("sts rocks");
});
test("multiple roots are allowed in a named slot", async () => {
class Dialog extends Component {
static template = xml`
`;
}
class Parent extends Component {
static template = xml`
sts
rocks
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("");
});
test("multiple roots are allowed in a default slot", async () => {
class Dialog extends Component {
static template = xml`
`;
}
class Parent extends Component {
static template = xml`
sts
rocks
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("");
});
test("missing slots are ignored", async () => {
class Dialog extends Component {
static template = xml`
some content
`;
}
class Parent extends Component {
static template = xml`
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("some content
");
});
test("t-debug on a t-set-slot (defining a slot)", async () => {
const consoleLog = console.log;
console.log = jest.fn();
class Dialog extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml`
abc
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(console.log).toHaveBeenCalledTimes(0);
console.log = consoleLog;
});
test("slot preserves properly parented relationship", async () => {
class Child extends Component {
static template = xml` `;
}
class GrandChild extends Component {
static template = xml`Grand Child`;
}
class Parent extends Component {
static template = xml`
`;
static components = { Child, GrandChild };
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("Grand Child
");
const parentChildren = children(parent);
expect(parentChildren.length).toBe(1);
expect(parentChildren[0]).toBeInstanceOf(Child);
const childrenChildren = children(parentChildren[0]);
expect(childrenChildren.length).toBe(1);
expect(childrenChildren[0]).toBeInstanceOf(GrandChild);
});
test("slot preserves properly parented relationship, even through t-call", async () => {
class Child extends Component {
static template = xml` `;
}
class GrandChild extends Component {
static template = xml`Grand Child`;
}
class Parent extends Component {
static template = xml`
`;
static components = { Child, GrandChild };
}
// throw new Error("boom")
const parent = await mount(Parent, fixture, {
templates: `
`,
});
expect(fixture.innerHTML).toBe("Grand Child
");
const parentChildren = children(parent);
expect(parentChildren.length).toBe(1);
expect(parentChildren[0]).toBeInstanceOf(Child);
const childrenChildren = children(parentChildren[0]);
expect(childrenChildren.length).toBe(1);
expect(childrenChildren[0]).toBeInstanceOf(GrandChild);
});
test("t-slot scope context", async () => {
expect.assertions(4);
class Wrapper extends Component {
static template = xml` `;
}
let dialog: any;
class Dialog extends Component {
static template = xml`
`;
static components = { Wrapper };
setup() {
dialog = this;
}
onClick() {
// we do not use expect(this).toBe(dialog) here because if it fails, it
// may blow up jest because it then tries to compute a diff, which is
// infinite if there is a cycle
expect(this === dialog).toBe(true);
}
}
class Parent extends Component {
static template = xml`
The Button
`;
static components = { Dialog };
}
await mount(Parent, fixture);
fixture.querySelector("button")!.click();
await nextTick();
});
test("t-slot in recursive templates", async () => {
class Wrapper extends Component {
static template = xml`
`;
}
class Parent extends Component {
static template = "_test_recursive_template";
static components = { Wrapper };
name = "foo";
items = [
{
name: "foo-0",
children: [
{ name: "foo-00", children: [] },
{
name: "foo-01",
children: [
{ name: "foo-010", children: [] },
{ name: "foo-011", children: [] },
{
name: "foo-012",
children: [
{ name: "foo-0120", children: [] },
{ name: "foo-0121", children: [] },
{ name: "foo-0122", children: [] },
],
},
],
},
{ name: "foo-02", children: [] },
],
},
{ name: "foo-1", children: [] },
{ name: "foo-2", children: [] },
];
}
const recursiveTemplate = `
`;
const app = new App(Parent);
app.addTemplate("_test_recursive_template", recursiveTemplate);
await app.mount(fixture);
expect(fixture.innerHTML).toBe(
"foofoo-0foo-00foo-01foo-010foo-011foo-012foo-0120foo-0121foo-0122 foo-02 foo-1foo-2 "
);
});
test("t-slot within dynamic t-call", async () => {
class Child extends Component {
static template = xml`
`;
}
class Slotted extends Component {
static template = xml`
`;
}
class UsingTcallInSlotted extends Component {
tcallTemplate = "sometemplate";
static template = xml`
`;
static components = { Slotted, Child };
}
const parent = await mount(UsingTcallInSlotted, fixture, {
templates: `
`,
});
expect(parent).toBeInstanceOf(UsingTcallInSlotted);
expect(children(parent).length).toBe(1);
const slotted = children(parent)[0];
expect(slotted).toBeInstanceOf(Slotted);
expect(children(slotted).length).toBe(1);
const child = children(slotted)[0];
expect(child).toBeInstanceOf(Child);
expect(fixture.innerHTML).toBe(
``
);
});
test("slots in t-foreach in t-foreach", async () => {
class Child extends Component {
static template = xml`
`;
}
class App extends Component {
static template = xml`
`;
static components = { Child };
tree = [
{
key: "a",
value: "A",
nodes: [
{
key: "1",
value: "A-1",
},
{
key: "2",
value: "A-2",
},
],
},
{
key: "b",
value: "B",
nodes: [
{
key: "1",
value: "B-1",
},
{
key: "2",
value: "B-2",
},
],
},
];
}
await mount(App, fixture);
expect(fixture.innerHTML).toBe(
""
);
});
test("default slot next to named slot, with default content", async () => {
class Dialog extends Component {
// We're using 2 slots here: a "default" one and a "footer",
// both having default children nodes.
static template = xml`
`;
}
class App extends Component {
// Here we're trying to assign the "footer" slot with some content
static components = { Dialog };
static template = xml`
Overridden footer
`;
}
await mount(App, fixture);
expect(fixture.innerHTML).toBe(
''
);
});
test("dynamic t-slot call", async () => {
class Toggler extends Component {
static template = xml` `;
current = useState({ slot: "slot1" });
toggle() {
this.current.slot = this.current.slot === "slot1" ? "slot2" : "slot1";
}
}
class Parent extends Component {
static template = xml`
`;
static components = { Toggler };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("");
fixture.querySelector("button")!.click();
await nextTick();
expect(fixture.innerHTML).toBe("slot2
");
fixture.querySelector("button")!.click();
await nextTick();
expect(fixture.innerHTML).toBe("");
});
test("dynamic t-slot call with default", async () => {
class Toggler extends Component {
static template = xml`
owl
`;
current = useState({ slot: "slot1" });
toggle() {
this.current.slot = this.current.slot === "slot1" ? "slot2" : "slot1";
}
}
class Parent extends Component {
static template = xml`
`;
static components = { Toggler };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("");
fixture.querySelector("button")!.click();
await nextTick();
expect(fixture.innerHTML).toBe("slot2
");
});
test("slot are properly rendered if inner props are changed", async () => {
class SomeComponent extends Component {
static template = xml`
SC:
`;
}
class GenericComponent extends Component {
static template = xml`
`;
}
class App extends Component {
static template = xml`
Inc[ ]
`;
static components = { GenericComponent, SomeComponent };
state = useState({ val: 4 });
inc() {
this.state.val++;
}
}
await mount(App, fixture);
expect(fixture.innerHTML).toBe("");
(fixture.querySelector("button")).click();
await nextTick();
expect(fixture.innerHTML).toBe("");
});
test("slots and wrapper components", async () => {
class Link extends Component {
static template = xml`
`;
}
class A extends Component {
static template = xml` hey`;
static components = { Link: Link };
}
await mount(A, fixture);
expect(fixture.innerHTML).toBe(`hey `);
});
test("template can just return a slot", async () => {
class Child extends Component {
static template = xml` `;
}
class SlotComponent extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml`
`;
static components = { SlotComponent, Child };
state = useState({ value: 3 });
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("3
");
parent.state.value = 5;
await nextTick();
expect(fixture.innerHTML).toBe("5
");
});
test("multiple slots containing components", async () => {
class C extends Component {
static template = xml` `;
}
class B extends Component {
static template = xml`
`;
}
class A extends Component {
static template = xml`
`;
static components = { B, C };
}
await mount(A, fixture);
expect(fixture.innerHTML).toBe(`1 2
`);
});
test("slots in t-foreach and re-rendering", async () => {
class Child extends Component {
static template = xml` `;
state = useState({ val: "A" });
setup() {
onMounted(() => {
this.state.val = "B";
});
}
}
class Parent extends Component {
static components = { Child };
static template = xml`
`;
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("A0 A1
");
await nextTick(); // wait for the changes triggered in mounted to be applied
expect(fixture.innerHTML).toBe("B0 B1
");
});
test("slots in t-foreach with t-set and re-rendering", async () => {
class Child extends Component {
static template = xml`
`;
state = useState({ val: "A" });
setup() {
onMounted(() => {
this.state.val = "B";
});
}
}
class ParentWidget extends Component {
static components = { Child };
static template = xml`
`;
}
await mount(ParentWidget, fixture);
expect(fixture.innerHTML).toBe("A0 A1
");
await nextTick(); // wait for changes triggered in mounted to be applied
expect(fixture.innerHTML).toBe("B0 B1
");
});
test("nested slots in same template", async () => {
let child: any = null;
let child2: any = null;
let child3: any = null;
class Child extends Component {
static template = xml`
`;
setup() {
child = this;
}
}
class Child2 extends Component {
static template = xml`
`;
setup() {
child2 = this;
}
}
class Child3 extends Component {
static template = xml`
Child 3 `;
setup() {
child3 = this;
}
}
class Parent extends Component {
static components = { Child, Child2, Child3 };
static template = xml`
`;
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(
'Child 3
'
);
expect(children(child2)).toEqual([child3]);
expect(children(child)).toEqual([child2]);
expect(children(parent)).toEqual([child]);
});
test("t-slot nested within another slot", async () => {
let portal: any = null;
let modal: any = null;
let child3: any = null;
class Child3 extends Component {
static template = xml`Child 3 `;
setup() {
child3 = this;
}
}
class Modal extends Component {
static template = xml` `;
setup() {
modal = this;
}
}
class Portal extends Component {
static template = xml` `;
setup() {
portal = this;
}
}
class Dialog extends Component {
static components = { Modal, Portal };
static template = xml`
`;
}
class Parent extends Component {
static components = { Child3, Dialog };
static template = xml`
`;
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(
'Child 3 '
);
expect(children(portal)[0]).toBe(child3);
expect(children(modal)[0]).toBe(portal);
});
test("slots in slots, with vars", async () => {
class B extends Component {
static template = xml` `;
}
class A extends Component {
static template = xml`
`;
static components = { B };
}
class Parent extends Component {
static template = xml`
`;
static components = { A };
state = { name: "aaron" };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("");
});
test("t-set t-value in a slot", async () => {
class Dialog extends Component {
static template = xml`
`;
}
class Parent extends Component {
static template = xml`
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("dash
");
});
test("slot and t-esc", async () => {
class Dialog extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml`
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("toph
");
});
test("slot and t-call", async () => {
let sokka = xml`sokka
`;
class Dialog extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml`
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("");
});
test("slot and (inline) t-call", async () => {
let sokka = xml`sokka
`;
class Dialog extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml`
`;
static components = { Dialog };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("");
});
test("nested slots: evaluation context and parented relationship", async () => {
let slot: any = null;
let grandChild: any = null;
class Slot extends Component {
static template = xml` `;
setup() {
slot = this;
}
}
class GrandChild extends Component {
static template = xml`
`;
setup() {
grandChild = this;
}
}
class Child extends Component {
static components = { GrandChild };
static template = xml`
`;
}
class Parent extends Component {
static components = { Child, Slot };
static template = xml` `;
state = useState({ val: 3 });
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("3
");
expect(children(grandChild)).toEqual([slot]);
});
test("named slot inside slot", async () => {
class Child extends Component {
static template = xml`
`;
}
class Parent extends Component {
static template = xml`
`;
static components = { Child };
value = "blip";
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("");
});
test("named slots inside slot, again", async () => {
class Child extends Component {
static template = xml`
default1
default2
`;
}
class Parent extends Component {
static template = xml`
`;
static components = { Child };
value = "blip";
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(
"Ablip
default2default1Bblip
"
);
});
test("named slot inside slot, part 3", async () => {
class Child extends Component {
static template = xml`
`;
}
class Parent extends Component {
static template = xml`
`;
static components = { Child };
value = "blip";
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("");
});
test("can render only empty slot", async () => {
class Parent extends Component {
static template = xml` `;
}
let error = null;
try {
await mount(Parent, fixture);
} catch (e) {
error = e;
}
expect(error).toBeNull();
expect(fixture.innerHTML).toEqual("");
});
test("can render node with t-ref and Component in same slot", async () => {
class Child extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml`
`;
static components = { Child };
}
let error = null;
try {
await mount(Parent, fixture);
} catch (e) {
error = e;
}
expect(error).toBeNull();
});
test("can use t-call in default-content of t-slot", async () => {
const template = xml``;
class Child extends Component {
static template = xml` `;
}
class Parent extends Component {
static template = xml` `;
static components = { Child };
}
await mount(Parent, fixture);
});
test("can use component in default-content of t-slot", async () => {
class GrandChild extends Component {
static template = xml``;
}
class Child extends Component {
static template = xml` `;
static components = { GrandChild };
}
class Parent extends Component {
static template = xml` `;
static components = { Child };
}
await mount(Parent, fixture);
});
test("slot content has different key from other content -- static slot", async () => {
class Child extends Component {
static template = xml`
`;
}
class SlotDisplay extends Component {
static components = { Child };
static template = xml` `;
}
class Parent extends Component {
static components = { Child, SlotDisplay };
static template = xml`
`;
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("SlotDisplay
Parent
");
});
test("slot content has different key from other content -- dynamic slot", async () => {
class Child extends Component {
static template = xml`
`;
}
class SlotDisplay extends Component {
static components = { Child };
slotName = "default";
static template = xml` `;
}
class Parent extends Component {
static components = { Child, SlotDisplay };
static template = xml`
`;
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("SlotDisplay
Parent
");
});
});