UNPKG

@ribajs/core

Version:

Core module of Riba.js

283 lines (231 loc) 9.71 kB
import { Riba } from "../riba.js"; import { EachStarBinder } from "./each-item.binder.js"; import { TextBinder } from "./text.binder.js"; import { dotAdapter } from "../adapters/dot.adapter.js"; describe("each-*", () => { const riba = new Riba(); riba.module.adapter.register(dotAdapter); riba.module.binder.register(EachStarBinder); riba.module.binder.register(TextBinder); let fragment: DocumentFragment; let el: HTMLLIElement; let model: any; beforeEach(() => { fragment = document.createDocumentFragment(); el = document.createElement("li"); el.setAttribute("rv-each-item", "items"); el.setAttribute("rv-text", "item.val"); fragment.appendChild(el); model = { items: [{ val: 0 }, { val: 1 }, { val: 2 }] }; }); it("binds to the model creating a list item for each element in items", () => { riba.bind(fragment, model); // one child for each element in the model plus 1 for the comment placeholder expect(fragment.childNodes.length).toBe(model.items.length + 1); }); it("reflects changes to the model into the DOM", () => { riba.bind(fragment, model); expect(fragment.childNodes[1].textContent).toBe("0"); model.items[0].val = "howdy"; expect(fragment.childNodes[1].textContent).toBe("howdy"); }); it("reflects changes to the model into the DOM after unbind/bind", () => { const view = riba.bind(fragment, model); expect(fragment.childNodes[1].textContent as string).toBe("0"); view.unbind(); view.bind(); model.items[0].val = "howdy"; expect(fragment.childNodes[1].textContent as string).toBe("howdy"); }); it("lets you push an item", () => { riba.bind(fragment, model); const originalLength = model.items.length; // one child for each element in the model plus 1 for the comment placeholder expect(fragment.childNodes.length).toBe(model.items.length + 1); model.items.push({ val: 3 }); expect(model.items.length).toBe(originalLength + 1); expect(fragment.childNodes.length).toBe(model.items.length + 1); }); it("lets you pop an item", () => { riba.bind(fragment, model); const originalLength = model.items.length; // one child for each element in the model plus 1 for the comment placeholder expect(fragment.childNodes.length).toBe(model.items.length + 1); [].forEach.call(fragment.childNodes, (itemEl: any, index: number) => { itemEl._key = index; }); model.items.pop(); expect(model.items.length).toBe(originalLength - 1); expect(fragment.childNodes.length).toBe(model.items.length + 1); expect( Array.prototype.indexOf.call(fragment.childNodes, fragment.childNodes[1]) ).toBe(1); expect((fragment.childNodes[1] as any)._key).toBe(1); expect( Array.prototype.indexOf.call(fragment.childNodes, fragment.childNodes[2]) ).toBe(2); expect((fragment.childNodes[2] as any)._key).toBe(2); }); it("lets you shift an item", () => { riba.bind(fragment, model); const originalLength = model.items.length; // one child for each element in the model plus 1 for the comment placeholder expect(fragment.childNodes.length).toBe(model.items.length + 1); [].forEach.call(fragment.childNodes, (itemEl: any, index: number) => { itemEl._key = index; }); model.items.shift(); expect(model.items.length).toBe(originalLength - 1); expect(fragment.childNodes.length).toBe(model.items.length + 1); expect((fragment.childNodes[1] as any)._key).toBe(2); expect((fragment.childNodes[2] as any)._key).toBe(3); }); it("lets you splice an item", () => { riba.bind(fragment, model); const originalLength = model.items.length; // one child for each element in the model plus 1 for the comment placeholder expect(fragment.childNodes.length).toBe(model.items.length + 1); [].forEach.call(fragment.childNodes, (itemEl: any, index: number) => { itemEl._key = index; }); model.items.splice(1, 1, { val: "x" }, { val: "y" }); expect(model.items.length).toBe(originalLength + 1); expect(fragment.childNodes.length).toBe(model.items.length + 1); expect((fragment.childNodes[1] as any)._key).toBe(1); expect(typeof (fragment.childNodes[2] as any)._key).toEqual("undefined"); expect(typeof (fragment.childNodes[3] as any)._key).toEqual("undefined"); expect((fragment.childNodes[4] as any)._key).toBe(3); }); it("handles replacing the entire array", () => { riba.bind(fragment, model); expect(fragment.childNodes.length).toBe(4); // 3 items + comment model.items = [{ val: "a" }, { val: "b" }]; expect(fragment.childNodes.length).toBe(3); // 2 items + comment expect(fragment.childNodes[1].textContent).toBe("a"); expect(fragment.childNodes[2].textContent).toBe("b"); }); it("handles setting to empty array", () => { riba.bind(fragment, model); expect(fragment.childNodes.length).toBe(4); model.items = []; expect(fragment.childNodes.length).toBe(1); // only comment placeholder }); it("handles going from empty to populated", () => { model.items = []; riba.bind(fragment, model); expect(fragment.childNodes.length).toBe(1); model.items.push({ val: "new" }); expect(fragment.childNodes.length).toBe(2); expect(fragment.childNodes[1].textContent).toBe("new"); }); it("lets you sort items", () => { riba.bind(fragment, model); model.items.sort((a: any, b: any) => b.val - a.val); expect(fragment.childNodes[1].textContent).toBe("2"); expect(fragment.childNodes[2].textContent).toBe("1"); expect(fragment.childNodes[3].textContent).toBe("0"); }); it("lets you reverse items", () => { riba.bind(fragment, model); model.items.reverse(); expect(fragment.childNodes[1].textContent).toBe("2"); expect(fragment.childNodes[3].textContent).toBe("0"); }); it("lets you push an item after unbind/bind", () => { const view = riba.bind(fragment, model); const originalLength = model.items.length; // one child for each element in the model plus 1 for the comment placeholder expect(fragment.childNodes.length).toBe(model.items.length + 1); view.unbind(); view.bind(); model.items.push({ val: 3 }); expect(model.items.length).toBe(originalLength + 1); expect(fragment.childNodes.length).toBe(model.items.length + 1); }); }); describe("nested-each-*", () => { const riba = new Riba(); riba.module.binder.register(EachStarBinder); let fragment: DocumentFragment; let el: HTMLSpanElement; let nestedEl: HTMLSpanElement; let model: any; beforeEach(() => { fragment = document.createDocumentFragment(); el = document.createElement("span"); el.setAttribute("rv-each-item", "items"); nestedEl = document.createElement("span"); nestedEl.setAttribute("rv-each-nested", "item.items"); el.appendChild(nestedEl); fragment.appendChild(el); model = { root: "Root Node", items: [ { name: "Level 1 - 0", items: [{ val: 0 }, { val: 1 }] }, { name: "Level 1 - 1", items: [{ val: 2 }, { val: 3 }] }, { name: "Level 1 - 2", items: [{ val: 4 }, { val: 5 }] }, ], }; }); it("lets you access index from current and parent scope", () => { nestedEl.textContent = "{$parent.%item%}-{%nested%}"; riba.bind(el, model); expect(fragment.childNodes[1].childNodes[1].textContent).toEqual("0-0"); expect(fragment.childNodes[1].childNodes[2].textContent).toEqual("0-1"); expect(fragment.childNodes[2].childNodes[2].textContent).toEqual("1-1"); }); /** * Overwrite the index property name on element and the nested element, * both to `$index` and access both with the parent scope */ it("lets you access overwritten index from current and parent scope with the same name", () => { el.setAttribute("index-property", "$index"); nestedEl.setAttribute("index-property", "$index"); nestedEl.textContent = "{$parent.$index}-{$index}"; riba.bind(el, model); expect(fragment.childNodes[1].childNodes[1].textContent).toEqual("0-0"); expect(fragment.childNodes[1].childNodes[2].textContent).toEqual("0-1"); expect(fragment.childNodes[2].childNodes[2].textContent).toEqual("1-1"); }); it("lets you access properties from parent scopes", () => { nestedEl.textContent = "{root}!{item.name}"; riba.bind(el, model); expect(fragment.childNodes[1].childNodes[1].textContent).toEqual( "Root Node!Level 1 - 0" ); expect(fragment.childNodes[1].childNodes[2].textContent).toEqual( "Root Node!Level 1 - 0" ); expect(fragment.childNodes[2].childNodes[2].textContent).toEqual( "Root Node!Level 1 - 1" ); }); it("reflects changes in parent scopes properties", () => { nestedEl.textContent = "{root}!{item.name}"; riba.bind(el, model); model.root = "New"; expect(fragment.childNodes[1].childNodes[1].textContent).toEqual( "New!Level 1 - 0" ); expect(fragment.childNodes[1].childNodes[2].textContent).toEqual( "New!Level 1 - 0" ); expect(fragment.childNodes[2].childNodes[2].textContent).toEqual( "New!Level 1 - 1" ); }); it("reflects changes when an undefined property is set in root scope", () => { nestedEl.textContent = "{unset}"; riba.bind(el, model); model.unset = "NotUndefined"; expect(fragment.childNodes[1].childNodes[1].textContent).toEqual( "NotUndefined" ); expect(fragment.childNodes[1].childNodes[2].textContent).toEqual( "NotUndefined" ); expect(fragment.childNodes[2].childNodes[2].textContent).toEqual( "NotUndefined" ); }); });