budibase/packages/client/tests/bindingDom.spec.js

364 lines
9.5 KiB
JavaScript

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
}