Merge branch 'master' of github.com:Budibase/budibase
This commit is contained in:
commit
0fd1271de2
|
@ -48,6 +48,7 @@
|
|||
"babel-jest": "^24.8.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"jest": "^24.8.0",
|
||||
"jsdom": "^16.0.1",
|
||||
"rollup": "^1.12.0",
|
||||
"rollup-plugin-commonjs": "^10.0.0",
|
||||
"rollup-plugin-node-builtins": "^2.1.2",
|
||||
|
|
|
@ -19,6 +19,12 @@ export const createApp = (componentLibraries, appDefinition, user) => {
|
|||
|
||||
const childComponents = [];
|
||||
|
||||
if(hydrate) {
|
||||
while (htmlElement.firstChild) {
|
||||
htmlElement.removeChild(htmlElement.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
for(let childProps of childrenProps) {
|
||||
const {componentName, libName} = splitName(childProps._component);
|
||||
|
||||
|
@ -37,7 +43,7 @@ export const createApp = (componentLibraries, appDefinition, user) => {
|
|||
const component = new (componentLibraries[libName][componentName])({
|
||||
target: htmlElement,
|
||||
props: componentProps,
|
||||
hydrate,
|
||||
hydrate:false,
|
||||
anchor
|
||||
});
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { createApp } from "./createApp";
|
||||
import { trimSlash } from "./common/trimSlash";
|
||||
|
||||
export const loadBudibase = async (componentLibraries, props) => {
|
||||
export const loadBudibase = async ({componentLibraries, props, window, localStorage}) => {
|
||||
|
||||
const appDefinition = window["##BUDIBASE_APPDEFINITION##"];
|
||||
|
||||
|
@ -36,8 +36,11 @@ export const loadBudibase = async (componentLibraries, props) => {
|
|||
const _app = createApp(componentLibraries, appDefinition, user);
|
||||
_app.hydrateChildren(
|
||||
[props],
|
||||
document.body);
|
||||
window.document.body);
|
||||
|
||||
return _app;
|
||||
};
|
||||
|
||||
window.loadBudibase = loadBudibase;
|
||||
if(window) {
|
||||
window.loadBudibase = loadBudibase;
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
import { load } from "./testAppDef";
|
||||
|
||||
describe("initialiseApp", () => {
|
||||
|
||||
it("should populate root element prop from store value", async () => {
|
||||
|
||||
const {dom} = await load({
|
||||
_component: "testlib/div",
|
||||
className: {
|
||||
"##bbstate": "divClassName",
|
||||
"##bbsource": "store",
|
||||
"##bbstatefallback":"default"
|
||||
}
|
||||
});
|
||||
|
||||
const rootDiv = dom.window.document.body.children[0];
|
||||
expect(rootDiv.className).toBe("default");
|
||||
|
||||
});
|
||||
|
||||
it("should update root element from store", async () => {
|
||||
|
||||
const {dom, app} = await load({
|
||||
_component: "testlib/div",
|
||||
className: {
|
||||
"##bbstate": "divClassName",
|
||||
"##bbsource": "store",
|
||||
"##bbstatefallback":"default"
|
||||
}
|
||||
});
|
||||
|
||||
app.store.update(s => {
|
||||
s.divClassName = "newvalue";
|
||||
return s;
|
||||
});
|
||||
|
||||
const rootDiv = dom.window.document.body.children[0];
|
||||
expect(rootDiv.className).toBe("newvalue");
|
||||
|
||||
});
|
||||
|
||||
|
||||
it("should populate child component with store value", async () => {
|
||||
const {dom} = await load({
|
||||
_component: "testlib/div",
|
||||
_children: [
|
||||
{
|
||||
_component: "testlib/h1",
|
||||
text: {
|
||||
"##bbstate": "headerOneText",
|
||||
"##bbsource": "store",
|
||||
"##bbstatefallback":"header one"
|
||||
}
|
||||
},
|
||||
{
|
||||
_component: "testlib/h1",
|
||||
text: {
|
||||
"##bbstate": "headerTwoText",
|
||||
"##bbsource": "store",
|
||||
"##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({
|
||||
_component: "testlib/div",
|
||||
_children: [
|
||||
{
|
||||
_component: "testlib/h1",
|
||||
text: {
|
||||
"##bbstate": "headerOneText",
|
||||
"##bbsource": "store",
|
||||
"##bbstatefallback":"header one"
|
||||
}
|
||||
},
|
||||
{
|
||||
_component: "testlib/h1",
|
||||
text: {
|
||||
"##bbstate": "headerTwoText",
|
||||
"##bbsource": "store",
|
||||
"##bbstatefallback":"header two"
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
app.store.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");
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
import { load } from "./testAppDef";
|
||||
|
||||
describe("initialiseApp", () => {
|
||||
|
||||
it("should populate simple div with initial props", async () => {
|
||||
|
||||
const {dom} = await load({
|
||||
_component: "testlib/div",
|
||||
className: "my-test-class"
|
||||
});
|
||||
|
||||
expect(dom.window.document.body.children.length).toBe(1);
|
||||
const child = dom.window.document.body.children[0];
|
||||
expect(child.className).toBe("my-test-class");
|
||||
|
||||
});
|
||||
|
||||
it("should populate child component with props", async () => {
|
||||
const {dom} = await load({
|
||||
_component: "testlib/div",
|
||||
_children: [
|
||||
{
|
||||
_component: "testlib/h1",
|
||||
text: "header one"
|
||||
},
|
||||
{
|
||||
_component: "testlib/h1",
|
||||
text: "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 append children when told to do so", async () => {
|
||||
const {dom} = await load({
|
||||
_component: "testlib/div",
|
||||
_children: [
|
||||
{
|
||||
_component: "testlib/h1",
|
||||
text: "header one"
|
||||
},
|
||||
{
|
||||
_component: "testlib/h1",
|
||||
text: "header two"
|
||||
}
|
||||
],
|
||||
append: true
|
||||
});
|
||||
|
||||
const rootDiv = dom.window.document.body.children[0];
|
||||
|
||||
expect(rootDiv.children.length).toBe(3);
|
||||
expect(rootDiv.children[0].tagName).toBe("DIV");
|
||||
expect(rootDiv.children[0].className).toBe("default-child");
|
||||
expect(rootDiv.children[1].tagName).toBe("H1");
|
||||
expect(rootDiv.children[1].innerText).toBe("header one");
|
||||
expect(rootDiv.children[2].tagName).toBe("H1");
|
||||
expect(rootDiv.children[2].innerText).toBe("header two");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
import { JSDOM } from "jsdom";
|
||||
import { loadBudibase } from "../src/index";
|
||||
|
||||
export const load = async (props) => {
|
||||
const dom = new JSDOM(`<!DOCTYPE html><html><body></body><html>`);
|
||||
setAppDef(dom.window, props);
|
||||
const app = await loadBudibase({
|
||||
componentLibraries: allLibs(dom.window),
|
||||
window: dom.window,
|
||||
localStorage: createLocalStorage(),
|
||||
props
|
||||
});
|
||||
return {dom, app};
|
||||
}
|
||||
|
||||
const setAppDef = (window, props) => {
|
||||
window["##BUDIBASE_APPDEFINITION##"] = ({
|
||||
componentLibraries: [],
|
||||
props,
|
||||
hierarchy: {},
|
||||
appRootPath: ""
|
||||
});
|
||||
}
|
||||
|
||||
const allLibs = (window) => ({
|
||||
testlib: maketestlib(window)
|
||||
});
|
||||
|
||||
const createLocalStorage = () => {
|
||||
const data = {};
|
||||
return ({
|
||||
getItem: key => data[key],
|
||||
setItem: (key, value) => data[key] = value
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
const components = currentProps._bb.appendChildren(currentProps._children, node);
|
||||
childNodes = components.map(c => c._element);
|
||||
} else {
|
||||
currentProps._bb.hydrateChildren(currentProps._children, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.$set = set;
|
||||
this._element = node;
|
||||
set(opts.props);
|
||||
opts.target.appendChild(node);
|
||||
},
|
||||
|
||||
h1: function(opts) {
|
||||
|
||||
const node = window.document.createElement("H1");
|
||||
|
||||
let currentProps = {...opts.props};
|
||||
|
||||
const set = (props) => {
|
||||
currentProps = Object.assign(currentProps, props);
|
||||
if(currentProps.text) {
|
||||
node.innerText = currentProps.text;
|
||||
}
|
||||
}
|
||||
|
||||
this.$set = set;
|
||||
this._element = node;
|
||||
set(opts.props);
|
||||
opts.target.appendChild(node);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -833,13 +833,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@nx-js/compiler-util/-/compiler-util-2.0.0.tgz#c74c12165fa2f017a292bb79af007e8fce0af297"
|
||||
integrity sha512-AxSQbwj9zqt8DYPZ6LwZdytqnwfiOEdcFdq4l8sdjkZmU2clTht7RDLCI8xvkp7KqgcNaOGlTeCM55TULWruyQ==
|
||||
|
||||
"@phc/format@^0.5.0":
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@phc/format/-/format-0.5.0.tgz#a99d27a83d78b3100a191412adda04315e2e3aba"
|
||||
integrity sha512-JWtZ5P1bfXU0bAtTzCpOLYHDXuxSVdtL/oqz4+xa97h8w9E5IlVN333wugXVFv8vZ1hbXObKQf1ptXmFFcMByg==
|
||||
dependencies:
|
||||
safe-buffer "^5.1.2"
|
||||
|
||||
"@types/babel__core@^7.1.0":
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.2.tgz#608c74f55928033fce18b99b213c16be4b3d114f"
|
||||
|
@ -1040,15 +1033,6 @@ are-we-there-yet@~1.1.2:
|
|||
delegates "^1.0.0"
|
||||
readable-stream "^2.0.6"
|
||||
|
||||
argon2@^0.20.1:
|
||||
version "0.20.1"
|
||||
resolved "https://registry.yarnpkg.com/argon2/-/argon2-0.20.1.tgz#f58d2a0aeaf88bbe5762df02c3455e6f4f1bbbf3"
|
||||
integrity sha512-ds6SU6YAXoJQGgc9tMOfb55Dyls+b3oaY9bSED0/O83aqlBOEEKR+mbmrR37MmlGaDqKrGDfWoTlHUqeZw8sHQ==
|
||||
dependencies:
|
||||
"@phc/format" "^0.5.0"
|
||||
bindings "^1.3.0"
|
||||
node-addon-api "^1.6.0"
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
||||
|
@ -1402,18 +1386,16 @@ bcrypt-pbkdf@^1.0.0:
|
|||
dependencies:
|
||||
tweetnacl "^0.14.3"
|
||||
|
||||
bcryptjs@^2.4.3:
|
||||
version "2.4.3"
|
||||
resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb"
|
||||
integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=
|
||||
|
||||
binary-extensions@^1.0.0:
|
||||
version "1.13.1"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
|
||||
integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
|
||||
|
||||
bindings@^1.3.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
|
||||
integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
|
||||
dependencies:
|
||||
file-uri-to-path "1.0.0"
|
||||
|
||||
bl@~0.8.1:
|
||||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-0.8.2.tgz#c9b6bca08d1bc2ea00fc8afb4f1a5fd1e1c66e4e"
|
||||
|
@ -2532,11 +2514,6 @@ file-entry-cache@^5.0.1:
|
|||
dependencies:
|
||||
flat-cache "^2.0.1"
|
||||
|
||||
file-uri-to-path@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
|
||||
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
|
||||
|
||||
filename-regex@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
|
||||
|
@ -4298,11 +4275,6 @@ nice-try@^1.0.4:
|
|||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||
|
||||
node-addon-api@^1.6.0:
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.1.tgz#cf813cd69bb8d9100f6bdca6755fc268f54ac492"
|
||||
integrity sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ==
|
||||
|
||||
node-int64@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
|
||||
|
|
|
@ -327,13 +327,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@nx-js/compiler-util/-/compiler-util-2.0.0.tgz#c74c12165fa2f017a292bb79af007e8fce0af297"
|
||||
integrity sha512-AxSQbwj9zqt8DYPZ6LwZdytqnwfiOEdcFdq4l8sdjkZmU2clTht7RDLCI8xvkp7KqgcNaOGlTeCM55TULWruyQ==
|
||||
|
||||
"@phc/format@^0.5.0":
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@phc/format/-/format-0.5.0.tgz#a99d27a83d78b3100a191412adda04315e2e3aba"
|
||||
integrity sha512-JWtZ5P1bfXU0bAtTzCpOLYHDXuxSVdtL/oqz4+xa97h8w9E5IlVN333wugXVFv8vZ1hbXObKQf1ptXmFFcMByg==
|
||||
dependencies:
|
||||
safe-buffer "^5.1.2"
|
||||
|
||||
"@types/babel__core@^7.1.0":
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.2.tgz#608c74f55928033fce18b99b213c16be4b3d114f"
|
||||
|
@ -526,15 +519,6 @@ are-we-there-yet@~1.1.2:
|
|||
delegates "^1.0.0"
|
||||
readable-stream "^2.0.6"
|
||||
|
||||
argon2@^0.23.0:
|
||||
version "0.23.0"
|
||||
resolved "https://registry.yarnpkg.com/argon2/-/argon2-0.23.0.tgz#0b3cd77ed1501b2ebef23462d91cf114dfee5562"
|
||||
integrity sha512-+CC/bLeHF3c1JmTgmeuVSCsNc/hk2yFPYdxvfX37G6VHgZAZ0gMezPI/qsYUy4YXGya8dGBUEu85itYtf8eIQQ==
|
||||
dependencies:
|
||||
"@phc/format" "^0.5.0"
|
||||
node-addon-api "^1.6.3"
|
||||
node-gyp-build "^4.1.0"
|
||||
|
||||
arr-diff@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
|
||||
|
@ -2759,16 +2743,6 @@ nice-try@^1.0.4:
|
|||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||
|
||||
node-addon-api@^1.6.3:
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.1.tgz#cf813cd69bb8d9100f6bdca6755fc268f54ac492"
|
||||
integrity sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ==
|
||||
|
||||
node-gyp-build@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.0.tgz#3bc3dd7dd4aafecaf64a2e3729e785bc3cdea565"
|
||||
integrity sha512-rGLv++nK20BG8gc0MzzcYe1Nl3p3mtwJ74Q2QD0HTEDKZ6NvOFSelY6s2QBPWIHRR8h7hpad0LiwajfClBJfNg==
|
||||
|
||||
node-int64@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
|
||||
|
|
Loading…
Reference in New Issue