import {
renderToBdom,
renderToString,
snapshotEverything,
TestContext,
makeTestFixture,
} from "../helpers";
import { mount, patch } from "../../src/runtime/blockdom";
snapshotEverything();
// -----------------------------------------------------------------------------
// t-foreach
// -----------------------------------------------------------------------------
describe("t-foreach", () => {
test("simple iteration", () => {
const template = ``;
expect(renderToString(template)).toBe("321");
});
test("simple iteration with two nodes inside", () => {
const template = `
a
b
`;
const expected =
"a3b3a2b2a1b1";
expect(renderToString(template)).toBe(expected);
});
test("t-key on t-foreach", async () => {
const template = `
`;
const fixture = makeTestFixture();
const vnode1 = renderToBdom(template, { things: [1, 2] });
mount(vnode1, fixture);
let elm = fixture;
expect(elm.innerHTML).toBe("
");
const first = elm.querySelectorAll("span")[0];
const second = elm.querySelectorAll("span")[1];
const vnode2 = renderToBdom(template, { things: [2, 1] });
patch(vnode1, vnode2);
expect(elm.innerHTML).toBe("
");
expect(first).toBe(elm.querySelectorAll("span")[1]);
expect(second).toBe(elm.querySelectorAll("span")[0]);
});
test("simple iteration (in a node)", () => {
const template = `
`;
expect(renderToString(template)).toBe("321
");
});
test("iterate on items", () => {
const template = `
[: ]
`;
expect(renderToString(template)).toBe(" [0: 3 3] [1: 2 2] [2: 1 1]
");
});
test("iterate on items (on a element node)", () => {
const template = `
`;
const expected = `12
`;
expect(renderToString(template)).toBe(expected);
});
test("iterate, position", () => {
const template = `
- first last ()
`;
const expected = ` - first (0) - (1) - (2) - (3) - last (4)
`;
expect(renderToString(template)).toBe(expected);
});
test("iterate, dict param", () => {
const template = `
[: ]
`;
const expected = ` [0: a 1] [1: b 2] [2: c 3]
`;
const context = { value: { a: 1, b: 2, c: 3 } };
expect(renderToString(template, context)).toBe(expected);
});
test("iterate, Map param", () => {
const template = `
[: ]
`;
const expected = ` [0: a 1] [1: b 2] [2: c 3] `;
const context = {
value: new Map([
["a", 1],
["b", 2],
["c", 3],
]),
};
expect(renderToString(template, context)).toBe(expected);
});
test("iterate, Set param", () => {
const template = `
[: ]
`;
const expected = ` [0: 1 1] [1: 2 2] [2: 3 3] `;
const context = { value: new Set([1, 2, 3]) };
expect(renderToString(template, context)).toBe(expected);
});
test("iterate, string param", () => {
const template = `
[: ]
`;
const expected = ` [0: a a] [1: b b] [2: c c] `;
expect(renderToString(template)).toBe(expected);
});
test("iterate, iterable param", () => {
const template = `
[: ]
`;
const expected = ` [0: 1 1] [1: 2 2] [2: 3 3] `;
const context = {
map: new Map([
["a", 1],
["b", 2],
["c", 3],
]),
};
expect(renderToString(template, context)).toBe(expected);
});
test("iterate, generator param", () => {
const template = `
[: ]
`;
const expected = ` [0: 1 1] [1: 2 2] [2: 3 3] `;
const context = {
*gen() {
yield 1;
yield 2;
yield 3;
},
};
expect(renderToString(template, context)).toBe(expected);
});
test("does not pollute the rendering context", () => {
const template = `
`;
const context = { __owl__: {} };
renderToString(template, context);
expect(Object.keys(context)).toEqual(["__owl__"]);
});
test("t-foreach in t-foreach", () => {
const template = `
[]
`;
const context = { numbers: [1, 2, 3], letters: ["a", "b"] };
const expected = " [1a] [1b] [2a] [2b] [3a] [3b]
";
expect(renderToString(template, context)).toBe(expected);
});
test("t-call without body in t-foreach in t-foreach", () => {
const context = new TestContext();
const sub = `
[]
[]
[]
`;
const main = `
[][][]
`;
context.addTemplate("sub", sub);
context.addTemplate("main", main);
const ctx = { numbers: [1, 2, 3], letters: ["a", "b"] };
const expected =
" [1] [a] [x_1_a] [1] [b] [x_1_b] [2] [a] [x_2_a] [2] [b] [x_2_b] [3] [a] [x_3_a] [3] [b] [x_3_b] [][][]
";
expect(context.renderToString("main", ctx)).toBe(expected);
});
test("t-call with body in t-foreach in t-foreach", () => {
const context = new TestContext();
const sub = `
[]
[]
[]
`;
const main = `
[][][]
`;
context.addTemplate("sub", sub);
context.addTemplate("main", main);
const ctx = { numbers: [1, 2, 3], letters: ["a", "b"] };
const expected =
" [1] [a] [x_1_a] [1] [b] [x_1_b] [2] [a] [x_2_a] [2] [b] [x_2_b] [3] [a] [x_3_a] [3] [b] [x_3_b] [][][]
";
expect(context.renderToString("main", ctx)).toBe(expected);
});
test("throws error if invalid loop expression", () => {
const test = `
`;
expect(() => renderToString(test)).toThrow(
'Invalid loop expression: "undefined" is not iterable'
);
});
test("t-foreach with t-if inside", () => {
const template = `
`;
const ctx = {
elems: [
{ id: 1, text: "a" },
{ id: 2, text: "b" },
{ id: 3, text: "c" },
],
};
expect(renderToString(template, ctx)).toBe("ab
");
});
test("t-foreach with t-if inside (no external node)", () => {
const template = `
`;
const ctx = {
elems: [
{ id: 1, text: "a" },
{ id: 2, text: "b" },
{ id: 3, text: "c" },
],
};
expect(renderToString(template, ctx)).toBe("ab");
});
test("with t-memo", () => {
const items = [
{ id: 1, x: 1, y: 1 },
{ id: 2, x: 1, y: 1 },
];
const template = `
`;
const expected = ``;
expect(renderToString(template, { items })).toBe(expected);
});
});