import { Component, mount, onMounted, useState, xml } from "../../src/index"; import { makeTestFixture, nextTick, snapshotEverything, useLogLifecycle } from "../helpers"; snapshotEverything(); let fixture: HTMLElement; beforeEach(() => { fixture = makeTestFixture(); }); describe("list of components", () => { test("simple list", async () => { class Child extends Component { static template = xml``; } class Parent extends Component { static template = xml` `; static components = { Child }; state = useState({ elems: [ { id: 1, value: "a" }, { id: 2, value: "b" }, ], }); } const parent = await mount(Parent, fixture); expect(fixture.innerHTML).toBe("ab"); parent.state.elems.push({ id: 4, value: "d" }); await nextTick(); expect(fixture.innerHTML).toBe("abd"); parent.state.elems.pop(); await nextTick(); expect(fixture.innerHTML).toBe("ab"); }); test("components in a node in a t-foreach ", async () => { const steps: string[] = []; class Child extends Component { static template = xml`
`; setup() { useLogLifecycle(steps); } } class Parent extends Component { static template = xml`
`; static components = { Child }; setup() { useLogLifecycle(steps); } get items() { return [1, 2]; } } await mount(Parent, fixture); expect(fixture.innerHTML).toBe( "
" ); expect(steps).toEqual([ "Parent:setup", "Parent:willStart", "Parent:render", "Child:setup", "Child:willStart", "Child:setup", "Child:willStart", "Child:render", "Child:render", "Child:mounted", "Child:mounted", "Parent:mounted", ]); }); test("reconciliation alg works for t-foreach in t-foreach", async () => { class Child extends Component { static template = xml`
`; } class Parent extends Component { static template = xml`
`; static components = { Child }; state = { s: [{ blips: ["a1", "a2"] }, { blips: ["b1"] }] }; } await mount(Parent, fixture); expect(fixture.innerHTML).toBe("
a1
a2
b1
"); }); test("reconciliation alg works for t-foreach in t-foreach, 2", async () => { class Child extends Component { static template = xml`
`; } class Parent extends Component { static template = xml`

`; static components = { Child }; state = useState({ rows: [1, 2], cols: ["a", "b"] }); } const parent = await mount(Parent, fixture); expect(fixture.innerHTML).toBe( "

1_a

1_b

2_a

2_b

" ); parent.state.rows = [2, 1]; await nextTick(); expect(fixture.innerHTML).toBe( "

2_a

2_b

1_a

1_b

" ); }); test("sub components rendered in a loop", async () => { class Child extends Component { static template = xml`

`; } class Parent extends Component { static template = xml`
`; static components = { Child }; state = useState({ numbers: [1, 2, 3] }); } await mount(Parent, fixture); expect(fixture.innerHTML).toBe(`

1

2

3

`); }); test("sub components with some state rendered in a loop", async () => { let n = 1; class Child extends Component { static template = xml`

`; state: any; setup() { this.state = useState({ n }); n++; } } class Parent extends Component { static template = xml`
`; static components = { Child }; state = useState({ numbers: [1, 2, 3], }); } const parent = await mount(Parent, fixture); parent.state.numbers = [1, 3]; await nextTick(); expect(fixture.innerHTML).toBe(`

1

3

`); }); test("list of sub components inside other nodes", async () => { // this confuses the patching algorithm... class SubComponent extends Component { static template = xml`asdf`; } class Parent extends Component { static template = xml`
`; static components = { SubComponent }; state = useState({ blips: [ { a: "a", id: 1 }, { b: "b", id: 2 }, { c: "c", id: 4 }, ], }); } const parent = await mount(Parent, fixture); expect(fixture.innerHTML).toBe( "
asdf
asdf
asdf
" ); parent.state.blips.splice(0, 1); await nextTick(); expect(fixture.innerHTML).toBe( "
asdf
asdf
" ); }); test("t-foreach with t-component, and update", 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("
A0A1
"); await nextTick(); // wait for changes triggered in mounted to be applied expect(fixture.innerHTML).toBe("
B0B1
"); }); });