2020-06-15 07:30:23 +12:00
|
|
|
import jsdom, { JSDOM } from "jsdom"
|
2020-02-03 22:24:25 +13:00
|
|
|
import { loadBudibase } from "../src/index"
|
|
|
|
|
2020-06-15 07:30:23 +12:00
|
|
|
export const load = async (page, screens, url, host = "test.com") => {
|
2020-02-22 04:20:00 +13:00
|
|
|
screens = screens || []
|
|
|
|
url = url || "/"
|
2020-06-15 07:30:23 +12:00
|
|
|
|
|
|
|
const fullUrl = `http://${host}${url}`
|
|
|
|
const cookieJar = new jsdom.CookieJar()
|
2020-06-19 18:04:55 +12:00
|
|
|
const cookie = `${btoa("{}")}.${btoa('{"appId":"TEST_APP_ID"}')}.signature`
|
2020-06-15 07:30:23 +12:00
|
|
|
cookieJar.setCookie(
|
2020-11-03 09:14:10 +13:00
|
|
|
`budibase:local:TEST_APP_ID=${cookie};domain=${host};path=/`,
|
2020-06-15 07:30:23 +12:00
|
|
|
fullUrl,
|
|
|
|
{
|
|
|
|
looseMode: false,
|
|
|
|
},
|
|
|
|
() => {}
|
|
|
|
)
|
|
|
|
|
2020-02-11 04:51:09 +13:00
|
|
|
const dom = new JSDOM("<!DOCTYPE html><html><body></body><html>", {
|
2020-06-15 07:30:23 +12:00
|
|
|
url: fullUrl,
|
|
|
|
cookieJar,
|
2020-02-11 04:51:09 +13:00
|
|
|
})
|
2020-06-15 07:30:23 +12:00
|
|
|
|
2020-02-11 04:51:09 +13:00
|
|
|
autoAssignIds(page.props)
|
|
|
|
for (let s of screens) {
|
|
|
|
autoAssignIds(s.props)
|
|
|
|
}
|
|
|
|
setAppDef(dom.window, page, screens)
|
2020-06-13 07:42:55 +12:00
|
|
|
addWindowGlobals(dom.window, page, screens, {
|
2020-02-13 01:45:24 +13:00
|
|
|
hierarchy: {},
|
|
|
|
actions: [],
|
|
|
|
triggers: [],
|
|
|
|
})
|
2020-02-19 01:29:38 +13:00
|
|
|
setComponentCodeMeta(page, screens)
|
2020-02-03 22:24:25 +13:00
|
|
|
const app = await loadBudibase({
|
|
|
|
componentLibraries: allLibs(dom.window),
|
|
|
|
window: dom.window,
|
|
|
|
localStorage: createLocalStorage(),
|
|
|
|
})
|
|
|
|
return { dom, app }
|
2020-01-25 02:18:31 +13:00
|
|
|
}
|
|
|
|
|
2020-06-13 07:42:55 +12:00
|
|
|
const addWindowGlobals = (window, page, screens) => {
|
2020-02-13 01:45:24 +13:00
|
|
|
window["##BUDIBASE_FRONTEND_DEFINITION##"] = {
|
|
|
|
page,
|
|
|
|
screens,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-11 04:51:09 +13:00
|
|
|
export const makePage = props => ({ props })
|
|
|
|
export const makeScreen = (route, props) => ({ props, route })
|
|
|
|
|
|
|
|
export const timeout = ms => new Promise(resolve => setTimeout(resolve, ms))
|
|
|
|
|
|
|
|
export const walkComponentTree = (node, action) => {
|
|
|
|
action(node)
|
|
|
|
|
2020-02-19 01:29:38 +13:00
|
|
|
// works for nodes or props
|
|
|
|
const children = node.children || node._children
|
|
|
|
|
|
|
|
if (children) {
|
|
|
|
for (let child of children) {
|
2020-02-11 04:51:09 +13:00
|
|
|
walkComponentTree(child, action)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-03 22:24:25 +13:00
|
|
|
// this happens for real by the builder...
|
2020-01-29 03:14:53 +13:00
|
|
|
// ..this only assigns _ids when missing
|
2020-02-03 22:24:25 +13:00
|
|
|
const autoAssignIds = (props, count = 0) => {
|
|
|
|
if (!props._id) {
|
|
|
|
props._id = `auto_id_${count}`
|
|
|
|
}
|
|
|
|
if (props._children) {
|
|
|
|
for (let child of props._children) {
|
|
|
|
count += 1
|
|
|
|
autoAssignIds(child, count)
|
2020-01-29 03:14:53 +13:00
|
|
|
}
|
2020-02-03 22:24:25 +13:00
|
|
|
}
|
|
|
|
}
|
2020-01-29 03:14:53 +13:00
|
|
|
|
2020-02-19 01:29:38 +13:00
|
|
|
// any component with an id that include "based_on_store" is
|
|
|
|
// assumed to have code that depends on store value
|
|
|
|
const setComponentCodeMeta = (page, screens) => {
|
|
|
|
const setComponentCodeMeta_single = props => {
|
|
|
|
walkComponentTree(props, c => {
|
|
|
|
if (c._id.indexOf("based_on_store") >= 0) {
|
|
|
|
c._codeMeta = { dependsOnStore: true }
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
setComponentCodeMeta_single(page.props)
|
|
|
|
for (let s of screens || []) {
|
|
|
|
setComponentCodeMeta_single(s.props)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-11 04:51:09 +13:00
|
|
|
const setAppDef = (window, page, screens) => {
|
2020-02-11 10:35:51 +13:00
|
|
|
window["##BUDIBASE_FRONTEND_DEFINITION##"] = {
|
2020-02-03 22:24:25 +13:00
|
|
|
componentLibraries: [],
|
2020-02-11 04:51:09 +13:00
|
|
|
page,
|
|
|
|
screens,
|
2020-02-03 22:24:25 +13:00
|
|
|
}
|
2020-01-25 02:18:31 +13:00
|
|
|
}
|
|
|
|
|
2020-02-03 22:24:25 +13:00
|
|
|
const allLibs = window => ({
|
|
|
|
testlib: maketestlib(window),
|
|
|
|
})
|
2020-01-25 02:18:31 +13:00
|
|
|
|
|
|
|
const createLocalStorage = () => {
|
2020-02-03 22:24:25 +13:00
|
|
|
const data = {}
|
|
|
|
return {
|
|
|
|
getItem: key => data[key],
|
|
|
|
setItem: (key, value) => (data[key] = value),
|
|
|
|
}
|
2020-01-25 02:18:31 +13:00
|
|
|
}
|
|
|
|
|
2020-02-03 22:24:25 +13:00
|
|
|
const maketestlib = window => ({
|
|
|
|
div: function(opts) {
|
|
|
|
const node = window.document.createElement("DIV")
|
|
|
|
const defaultChild = window.document.createElement("DIV")
|
|
|
|
defaultChild.className = "default-child"
|
|
|
|
node.appendChild(defaultChild)
|
|
|
|
|
|
|
|
let currentProps = { ...opts.props }
|
|
|
|
let childNodes = []
|
|
|
|
|
|
|
|
const set = props => {
|
|
|
|
currentProps = Object.assign(currentProps, props)
|
|
|
|
node.className = currentProps.className || ""
|
|
|
|
if (currentProps._children && currentProps._children.length > 0) {
|
|
|
|
if (currentProps.append) {
|
|
|
|
for (let c of childNodes) {
|
|
|
|
node.removeChild(c)
|
|
|
|
}
|
2020-02-15 00:51:45 +13:00
|
|
|
const components = currentProps._bb.attachChildren(node, {
|
|
|
|
hydrate: false,
|
|
|
|
})
|
2020-02-03 22:24:25 +13:00
|
|
|
childNodes = components.map(c => c.component._element)
|
|
|
|
} else {
|
2020-02-15 00:51:45 +13:00
|
|
|
currentProps._bb.attachChildren(node)
|
2020-01-25 02:18:31 +13:00
|
|
|
}
|
2020-02-03 22:24:25 +13:00
|
|
|
}
|
2020-01-25 02:18:31 +13:00
|
|
|
}
|
|
|
|
|
2020-02-11 04:51:09 +13:00
|
|
|
this.$destroy = () => opts.target.removeChild(node)
|
|
|
|
|
2020-02-03 22:24:25 +13:00
|
|
|
this.$set = set
|
|
|
|
this._element = node
|
|
|
|
set(opts.props)
|
|
|
|
opts.target.appendChild(node)
|
|
|
|
},
|
2020-01-29 03:14:53 +13:00
|
|
|
|
2020-02-03 22:24:25 +13:00
|
|
|
h1: function(opts) {
|
|
|
|
const node = window.document.createElement("H1")
|
2020-01-25 02:18:31 +13:00
|
|
|
|
2020-02-03 22:24:25 +13:00
|
|
|
let currentProps = { ...opts.props }
|
2020-01-29 03:14:53 +13:00
|
|
|
|
2020-02-03 22:24:25 +13:00
|
|
|
const set = props => {
|
|
|
|
currentProps = Object.assign(currentProps, props)
|
|
|
|
if (currentProps.text) {
|
|
|
|
node.innerText = currentProps.text
|
|
|
|
}
|
2020-01-29 03:14:53 +13:00
|
|
|
}
|
2020-01-25 02:18:31 +13:00
|
|
|
|
2020-02-11 04:51:09 +13:00
|
|
|
this.$destroy = () => opts.target.removeChild(node)
|
|
|
|
|
2020-02-03 22:24:25 +13:00
|
|
|
this.$set = set
|
|
|
|
this._element = node
|
|
|
|
set(opts.props)
|
|
|
|
opts.target.appendChild(node)
|
|
|
|
},
|
2020-02-19 01:29:38 +13:00
|
|
|
|
|
|
|
button: function(opts) {
|
|
|
|
const node = window.document.createElement("BUTTON")
|
|
|
|
|
|
|
|
let currentProps = { ...opts.props }
|
|
|
|
|
|
|
|
const set = props => {
|
|
|
|
currentProps = Object.assign(currentProps, props)
|
|
|
|
if (currentProps.onClick) {
|
|
|
|
node.addEventListener("click", () => {
|
2020-09-11 08:11:05 +12:00
|
|
|
currentProps._bb.call("onClick")
|
2020-02-19 01:29:38 +13:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.$destroy = () => opts.target.removeChild(node)
|
|
|
|
|
|
|
|
this.$set = set
|
|
|
|
this._element = node
|
|
|
|
set(opts.props)
|
|
|
|
opts.target.appendChild(node)
|
|
|
|
},
|
2020-08-07 08:12:35 +12:00
|
|
|
|
|
|
|
list: function(opts) {
|
|
|
|
const node = window.document.createElement("DIV")
|
|
|
|
|
|
|
|
let currentProps = { ...opts.props }
|
|
|
|
|
|
|
|
const set = props => {
|
|
|
|
currentProps = Object.assign(currentProps, props)
|
|
|
|
if (currentProps._children && currentProps._children.length > 0) {
|
|
|
|
currentProps._bb.attachChildren(node, {
|
|
|
|
context: currentProps.data || {},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.$destroy = () => opts.target.removeChild(node)
|
|
|
|
|
|
|
|
this.$set = set
|
|
|
|
this._element = node
|
|
|
|
set(opts.props)
|
|
|
|
opts.target.appendChild(node)
|
|
|
|
},
|
|
|
|
|
|
|
|
input: function(opts) {
|
|
|
|
const node = window.document.createElement("INPUT")
|
|
|
|
let currentProps = { ...opts.props }
|
|
|
|
|
|
|
|
const set = props => {
|
|
|
|
currentProps = Object.assign(currentProps, props)
|
|
|
|
opts.props._bb.setBinding("value", props.value)
|
|
|
|
}
|
|
|
|
|
|
|
|
node.addEventListener("change", e => {
|
|
|
|
opts.props._bb.setBinding("value", e.target.value)
|
|
|
|
})
|
|
|
|
|
|
|
|
this.$destroy = () => opts.target.removeChild(node)
|
|
|
|
|
|
|
|
this.$set = set
|
|
|
|
this._element = node
|
|
|
|
set(opts.props)
|
|
|
|
opts.target.appendChild(node)
|
|
|
|
},
|
2020-06-01 21:41:28 +12:00
|
|
|
})
|