import { createBlock, mount, patch, remove, text } from "../../src/blockdom";
import { makeTestFixture } from "./helpers";
//------------------------------------------------------------------------------
// Setup and helpers
//------------------------------------------------------------------------------
let fixture: HTMLElement;
beforeEach(() => {
fixture = makeTestFixture();
});
afterEach(() => {
fixture.remove();
});
describe("adding/patching blocks", () => {
test("simple block", async () => {
const block = createBlock("
foo
");
const tree = block();
expect(tree.el).toBe(undefined);
mount(tree, fixture);
expect(tree.el).not.toBe(undefined);
expect(fixture.innerHTML).toBe("foo
");
});
test("block with dynamic content", async () => {
const block = createBlock("");
const tree = block(["foo"]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("");
patch(tree, block(["bar"]));
expect(fixture.innerHTML).toBe("");
patch(tree, block(["foo"]));
expect(fixture.innerHTML).toBe("");
});
test("block with 2 dynamic text nodes", async () => {
const block = createBlock("");
const tree = block(["foo", "bar"]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("");
patch(tree, block(["appa", "yip yip"]));
expect(fixture.innerHTML).toBe("");
});
test("block with multiple references", async () => {
const block1 = createBlock(
""
);
const tree = block1(["1", "2", "3", "4"]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("");
});
test("falsy values in block nodes", () => {
const cases = [
[false, "false"],
[undefined, ""],
[null, ""],
[0, "0"],
["", ""],
];
const block = createBlock("
");
for (let [value, result] of cases) {
const fixture = makeTestFixture();
mount(block([value as any]), fixture);
expect(fixture.innerHTML).toBe(`${result}
`);
}
});
});
describe("sub blocks", () => {
test("block with subblock (only child)", async () => {
const block1 = createBlock("
");
const block2 = createBlock("yip yip
");
const tree = block1([], [block2()]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("");
});
test("block with subblock (first child with sibling)", async () => {
const block1 = createBlock("something
");
const block2 = createBlock("yip yip
");
const tree = block1([], [block2()]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("");
});
test("block with subblock (last child with sibling)", async () => {
const block1 = createBlock("something
");
const block2 = createBlock("yip yip
");
const tree = block1([], [block2()]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("");
});
test("block with 2 subblocks", async () => {
const block1 = createBlock("
");
const block2 = createBlock("yip yip
");
const tree = block1([], [block2(), text("appa")]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("");
});
test("block with subblock with siblings", async () => {
const block1 = createBlock("");
const block2 = createBlock("yip yip
");
const tree = block1([], [block2()]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("");
});
test("block with text, subblock and siblings", async () => {
let block1 = createBlock(``);
let tree = block1([], [text("water"), text("fire")]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("");
});
test("block with conditional child", async () => {
const block1 = createBlock("");
const block2 = createBlock("foo");
const tree = block1();
mount(tree, fixture);
expect(fixture.innerHTML).toBe("");
patch(tree, block1([], [block2()]));
expect(fixture.innerHTML).toBe("");
patch(tree, block1());
expect(fixture.innerHTML).toBe("");
});
test("block with subblock with dynamic content", async () => {
const block1 = createBlock("
");
const block2 = createBlock("
");
const tree = block1([], [block2(["yip yip"])]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("");
patch(tree, block1([], [block2(["foo"])]));
expect(fixture.innerHTML).toBe("");
});
test("block with dynamic content and subblock", async () => {
const block1 = createBlock("");
const block2 = createBlock("sub block
");
const tree = block1(["yip yip"], [block2()]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("");
patch(tree, block1(["foo"], [block2()]));
expect(fixture.innerHTML).toBe("");
});
});
describe("remove elem blocks", () => {
test("elem block can be removed", async () => {
const block = createBlock("foo
");
const tree = block();
mount(tree, fixture);
expect(fixture.innerHTML).toBe("foo
");
remove(tree);
expect(fixture.innerHTML).toBe("");
expect(fixture.childNodes.length).toBe(0);
});
});
describe("misc", () => {
test("constructed block as correct number of refs", () => {
const block = createBlock("
");
const tree = block(["a", "b"]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("a
b");
expect((tree as any).refs.length).toBe(2);
});
test("block vnode can be used as text", () => {
const block = createBlock("a
");
mount(text(block() as any), fixture);
expect(fixture.textContent).toBe("a
");
});
test("block vnode can be used to represent a ", () => {
const block = createBlock("
| tomato |
");
const tree = block();
const fixture = document.createElement("table");
mount(tree, fixture);
expect(fixture.outerHTML).toBe("");
});
test("block vnode with can be used as text ", () => {
const block = createBlock("
| tomato |
");
mount(text(block() as any), fixture);
expect(fixture.textContent).toBe("| tomato |
");
});
test("call toString for function/objects if used as inline text in block", () => {
const block = createBlock("
");
const f = () => 3;
const g = () => 4;
g.toString = () => "tostring";
mount(block([f, g]), fixture);
expect(fixture.innerHTML).toBe("() => 3tostring
");
});
// test.skip("reusing a block skips patching process", async () => {
// const block = createBlock('
');
// const foo = block(["foo"]);
// const bar = block(["bar"]);
// let fooCounter = 0;
// let barCounter = 0;
// let fooValue = "foo";
// let barValue = "bar";
// Object.defineProperty(foo.data, 0, {
// get() {
// fooCounter++;
// return fooValue;
// },
// });
// Object.defineProperty(bar.data, 0, {
// get() {
// barCounter++;
// return barValue;
// },
// set(val) {
// barValue = val;
// },
// });
// const bdom = multi([foo, bar]);
// mount(bdom, fixture);
// expect(fooCounter).toBe(1);
// expect(barCounter).toBe(1);
// expect(fixture.innerHTML).toBe("foo
bar
");
// patch(bdom, multi([foo, block(["otherbar"])]));
// expect(fixture.innerHTML).toBe("foootherbar");
// expect(fooCounter).toBe(1);
// expect(barCounter).toBe(2);
// });
});