import { load, makePage, makeScreen } from "./testAppDef" import { EVENT_TYPE_MEMBER_NAME } from "../src/state/eventHandlers" describe("initialiseApp (binding)", () => { it("should populate root element prop from store value", async () => { const { dom } = await load( makePage({ _component: "testlib/div", className: { "##bbstate": "divClassName", "##bbsource": "state", "##bbstatefallback": "default", }, }) ) const rootDiv = dom.window.document.body.children[0] expect(rootDiv.className.includes("default")).toBe(true) }) it("should update root element from store", async () => { const { dom, app } = await load( makePage({ _component: "testlib/div", className: { "##bbstate": "divClassName", "##bbsource": "state", "##bbstatefallback": "default", }, }) ) app.pageStore().update(s => { s.divClassName = "newvalue" return s }) const rootDiv = dom.window.document.body.children[0] expect(rootDiv.className.includes("newvalue")).toBe(true) }) it("should update root element from store, using binding expression", async () => { const { dom, app } = await load( makePage({ _component: "testlib/div", className: "state.divClassName", }) ) app.pageStore().update(s => { s.divClassName = "newvalue" return s }) const rootDiv = dom.window.document.body.children[0] expect(rootDiv.className.includes("newvalue")).toBe(true) }) it("should populate child component with store value", async () => { const { dom } = await load( makePage({ _component: "testlib/div", _children: [ { _component: "testlib/h1", text: { "##bbstate": "headerOneText", "##bbsource": "state", "##bbstatefallback": "header one", }, }, { _component: "testlib/h1", text: { "##bbstate": "headerTwoText", "##bbsource": "state", "##bbstatefallback": "header two", }, }, ], }) ) const rootDiv = dom.window.document.body.children[0] expect(rootDiv.children.length).toBe(2) expect(rootDiv.children[0].tagName).toBe("H1") expect(rootDiv.children[0].innerText).toBe("header one") expect(rootDiv.children[1].tagName).toBe("H1") expect(rootDiv.children[1].innerText).toBe("header two") }) it("should populate child component with store value", async () => { const { dom, app } = await load( makePage({ _component: "testlib/div", _children: [ { _component: "testlib/h1", text: { "##bbstate": "headerOneText", "##bbsource": "state", "##bbstatefallback": "header one", }, }, { _component: "testlib/h1", text: { "##bbstate": "headerTwoText", "##bbsource": "state", "##bbstatefallback": "header two", }, }, ], }) ) app.pageStore().update(s => { s.headerOneText = "header 1 - new val" s.headerTwoText = "header 2 - new val" return s }) const rootDiv = dom.window.document.body.children[0] expect(rootDiv.children.length).toBe(2) expect(rootDiv.children[0].tagName).toBe("H1") expect(rootDiv.children[0].innerText).toBe("header 1 - new val") expect(rootDiv.children[1].tagName).toBe("H1") expect(rootDiv.children[1].innerText).toBe("header 2 - new val") }) it("should populate screen child with store value", async () => { const { dom, app } = await load( makePage({ _component: "testlib/div", _children: [ { _component: "##builtin/screenslot", text: "header one", }, ], }), [ makeScreen("/", { _component: "testlib/div", className: "screen-class", _children: [ { _component: "testlib/h1", text: { "##bbstate": "headerOneText", "##bbsource": "state", "##bbstatefallback": "header one", }, }, { _component: "testlib/h1", text: { "##bbstate": "headerTwoText", "##bbsource": "state", "##bbstatefallback": "header two", }, }, ], }), ] ) app.screenStore().update(s => { s.headerOneText = "header 1 - new val" s.headerTwoText = "header 2 - new val" return s }) const rootDiv = dom.window.document.body.children[0] expect(rootDiv.children.length).toBe(1) const screenRoot = rootDiv.children[0] expect(screenRoot.children.length).toBe(1) expect(screenRoot.children[0].children.length).toBe(2) expect(screenRoot.children[0].children[0].innerText).toBe( "header 1 - new val" ) expect(screenRoot.children[0].children[1].innerText).toBe( "header 2 - new val" ) }) it("should fire events", async () => { const { dom, app } = await load( makePage({ _component: "testlib/button", onClick: [ event("Set State", { path: "address", value: "123 Main Street", }), ], }) ) const button = dom.window.document.body.children[0] expect(button.tagName).toBe("BUTTON") let storeAddress app.pageStore().subscribe(s => { storeAddress = s.address }) button.dispatchEvent(new dom.window.Event("click")) expect(storeAddress).toBe("123 Main Street") }) it("should alter event parameters based on store values", async () => { const { dom, app } = await load( makePage({ _component: "testlib/button", onClick: [ event("Set State", { path: "address", value: { "##bbstate": "sourceaddress", "##bbsource": "state", "##bbstatefallback": "fallback address", }, }), ], }) ) const button = dom.window.document.body.children[0] expect(button.tagName).toBe("BUTTON") let storeAddress app.pageStore().subscribe(s => { storeAddress = s.address }) button.dispatchEvent(new dom.window.Event("click")) expect(storeAddress).toBe("fallback address") app.pageStore().update(s => { s.sourceaddress = "new address" return s }) button.dispatchEvent(new dom.window.Event("click")) expect(storeAddress).toBe("new address") }) it("should take event parameters from context values", async () => { const { dom, app } = await load( makePage({ _component: "testlib/button", _id: "with_context", onClick: [ event("Set State", { path: "address", value: { "##bbstate": "testKey", "##bbsource": "context", "##bbstatefallback": "fallback address", }, }), ], }) ) const button = dom.window.document.body.children[0] expect(button.tagName).toBe("BUTTON") let storeAddress app.pageStore().subscribe(s => { storeAddress = s.address }) button.dispatchEvent(new dom.window.Event("click")) expect(storeAddress).toBe("test value") }) }) it("should rerender components when their code is bound to the store ", async () => { const { dom, app } = await load( makePage({ _component: "testlib/div", _children: [ { _component: "testlib/div", _id: "n_clones_based_on_store", className: "child_div", }, ], }) ) const rootDiv = dom.window.document.body.children[0] expect(rootDiv.tagName).toBe("DIV") expect(rootDiv.children.length).toBe(0) app.pageStore().update(s => { s.componentCount = 3 return s }) expect(rootDiv.children.length).toBe(3) expect(rootDiv.children[0].className.includes("child_div")).toBe(true) app.pageStore().update(s => { s.componentCount = 5 return s }) expect(rootDiv.children.length).toBe(5) expect(rootDiv.children[0].className.includes("child_div")).toBe(true) app.pageStore().update(s => { s.componentCount = 0 return s }) expect(rootDiv.children.length).toBe(0) }) it("should be able to read value from context, passed fromm parent, through code", async () => { const { dom, app } = await load( makePage({ _component: "testlib/div", _children: [ { _component: "testlib/div", _id: "n_clones_based_on_store", className: { "##bbstate": "index", "##bbsource": "context", "##bbstatefallback": "nothing", }, }, ], }) ) const rootDiv = dom.window.document.body.children[0] expect(rootDiv.tagName).toBe("DIV") expect(rootDiv.children.length).toBe(0) app.pageStore().update(s => { s.componentCount = 3 return s }) expect(rootDiv.children.length).toBe(3) expect(rootDiv.children[0].className.includes("index_0")).toBe(true) expect(rootDiv.children[1].className.includes("index_1")).toBe(true) expect(rootDiv.children[2].className.includes("index_2")).toBe(true) }) const event = (handlerType, parameters) => { const e = {} e[EVENT_TYPE_MEMBER_NAME] = handlerType e.parameters = parameters return e }