validate pages... started testing
This commit is contained in:
parent
4b12a6a193
commit
70082147c7
|
@ -11,13 +11,29 @@ const defaultDef = typeName => () => ({
|
||||||
required:false,
|
required:false,
|
||||||
default:types[typeName].default,
|
default:types[typeName].default,
|
||||||
options: typeName === "options" ? [] : undefined,
|
options: typeName === "options" ? [] : undefined,
|
||||||
elementDefinition: typeName === "array" ? "string" : undefined
|
elementDefinition: typeName === "array" ? {} : undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
const propType = (defaultValue, isOfType, defaultDefinition) => ({
|
const propType = (defaultValue, isOfType, defaultDefinition) => ({
|
||||||
isOfType, default:defaultValue, defaultDefinition
|
isOfType, default:defaultValue, defaultDefinition
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*export const expandPropDef = propDef => {
|
||||||
|
const p = isString(propDef)
|
||||||
|
? types[propDef].defaultDefinition()
|
||||||
|
: propDef;
|
||||||
|
|
||||||
|
if(!isString(propDef)) {
|
||||||
|
const def = types[propDef.type].defaultDefinition();
|
||||||
|
assign(propDef, def);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p.type === "array" && isString(p.elementDefinition)) {
|
||||||
|
p.elementDefinition = types[p.elementDefinition].defaultDefinition()
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}*/
|
||||||
|
|
||||||
const isComponent = isObjectLike;
|
const isComponent = isObjectLike;
|
||||||
|
|
||||||
export const types = {
|
export const types = {
|
||||||
|
@ -26,5 +42,6 @@ export const types = {
|
||||||
number: propType(() => 0, isNumber, defaultDef("number")),
|
number: propType(() => 0, isNumber, defaultDef("number")),
|
||||||
array: propType(() => [], isArray, defaultDef("array")),
|
array: propType(() => [], isArray, defaultDef("array")),
|
||||||
options: propType(() => "", isString, defaultDef("options")),
|
options: propType(() => "", isString, defaultDef("options")),
|
||||||
component: propType(() => ({_component:""}), isComponent, defaultDef("component"))
|
component: propType(() => ({_component:""}), isComponent, defaultDef("component")),
|
||||||
|
asset: propType(() => "", isString, defaultDef("asset")),
|
||||||
};
|
};
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { recursivelyValidate } from "./validateProps";
|
||||||
|
import {
|
||||||
|
isString,
|
||||||
|
keys,
|
||||||
|
flatten,
|
||||||
|
isArray,
|
||||||
|
map,
|
||||||
|
filter
|
||||||
|
} from "lodash/fp";
|
||||||
|
import { common } from "budibase-core";
|
||||||
|
const pipe = common.$;
|
||||||
|
|
||||||
|
export const validatePage = (page, getComponent) => {
|
||||||
|
const errors = [];
|
||||||
|
const error = message => errors.push(message);
|
||||||
|
|
||||||
|
const noIndex = !page.index || !page.index._component;
|
||||||
|
if(noIndex) {
|
||||||
|
error("Must choose a component for your index.html");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!page.appBody
|
||||||
|
|| !isString(page.appBody)
|
||||||
|
|| !page.appBody.endsWith(".json")) {
|
||||||
|
error("App body must be set toa valid JSON file");
|
||||||
|
}
|
||||||
|
|
||||||
|
const indexHtmlErrors = noIndex
|
||||||
|
? []
|
||||||
|
: pipe(
|
||||||
|
recursivelyValidate(page.index, getComponent), [
|
||||||
|
map(e => `Index.html: ${e.error}`)
|
||||||
|
]);
|
||||||
|
|
||||||
|
return [...errors, ...indexHtmlErrors];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const validatePages = (pages, getComponent) => {
|
||||||
|
|
||||||
|
let errors = [];
|
||||||
|
const error = message => errors.push(message);
|
||||||
|
|
||||||
|
if(!pages.main) {
|
||||||
|
error("must have a 'main' page");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!pages.unauthenticated) {
|
||||||
|
error("must have a 'unauthenticated' (login) page");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!pages.componentLibraries
|
||||||
|
|| !isArray(pages.componentLibraries)
|
||||||
|
|| pages.componentLibraries.length === 0) {
|
||||||
|
|
||||||
|
error("componentLibraries must be set to a non-empty array of strings");
|
||||||
|
}
|
||||||
|
|
||||||
|
const pageErrors = pipe(pages, [
|
||||||
|
keys,
|
||||||
|
filter(k => k !== "componentLibraries"),
|
||||||
|
map(k => validatePage(pages[k], getComponent)),
|
||||||
|
flatten
|
||||||
|
]);
|
||||||
|
|
||||||
|
return [...errors, ...pageErrors];
|
||||||
|
}
|
|
@ -30,6 +30,13 @@ export const recursivelyValidate = (rootProps, getComponent, stack=[]) => {
|
||||||
return getComponent(componentName);
|
return getComponent(componentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!rootProps._component) {
|
||||||
|
const errs = [];
|
||||||
|
makeError(errs, "_component", stack)("Component is not set");
|
||||||
|
return errs;
|
||||||
|
// this would break everything else anyway
|
||||||
|
}
|
||||||
|
|
||||||
const propsDef = getComponentPropsDefinition(
|
const propsDef = getComponentPropsDefinition(
|
||||||
rootProps._component);
|
rootProps._component);
|
||||||
|
|
||||||
|
@ -80,18 +87,26 @@ export const recursivelyValidate = (rootProps, getComponent, stack=[]) => {
|
||||||
return flattenDeep([errors, ...childErrors, ...childArrayErrors]);
|
return flattenDeep([errors, ...childErrors, ...childArrayErrors]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const expandPropDef = propDef =>
|
const expandPropDef = propDef => {
|
||||||
isString(propDef)
|
const p = isString(propDef)
|
||||||
? types[propDef].defaultDefinition()
|
? types[propDef].defaultDefinition()
|
||||||
: propDef;
|
: propDef;
|
||||||
|
if(p.type === "array" && isString(p.elementDefinition)) {
|
||||||
|
p.elementDefinition = types[p.elementDefinition].defaultDefinition()
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export const validateProps = (propsDefinition, props, stack=[], isFinal=true) => {
|
export const validateProps = (propsDefinition, props, stack=[], isFinal=true) => {
|
||||||
|
|
||||||
const errors = [];
|
const errors = [];
|
||||||
|
|
||||||
if(!props._component)
|
if(!props._component) {
|
||||||
makeError(errors, "_component", stack)("Component is not set");
|
makeError(errors, "_component", stack)("Component is not set");
|
||||||
|
return errors;
|
||||||
|
// this would break everything else anyway
|
||||||
|
}
|
||||||
|
|
||||||
for(let propDefName in propsDefinition) {
|
for(let propDefName in propsDefinition) {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
import {
|
||||||
|
validatePages,
|
||||||
|
validatePage
|
||||||
|
} from "../src/userInterface/propsDefinitionParsing/validatePages";
|
||||||
|
|
||||||
|
const validPages = () => ({
|
||||||
|
"main" : {
|
||||||
|
"index" : {
|
||||||
|
"_component": "testIndexHtml",
|
||||||
|
"title": "My Cool App",
|
||||||
|
"customScripts": [
|
||||||
|
{"url": "MyCustomComponents.js"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"appBody" : "./main.app.json"
|
||||||
|
},
|
||||||
|
"unauthenticated" : {
|
||||||
|
"index" : {
|
||||||
|
"_component": "testIndexHtml",
|
||||||
|
"title": "My Cool App - Login",
|
||||||
|
"customScripts": [
|
||||||
|
{"url": "MyCustomComponents.js"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"appBody" : "./unauthenticated.app.json"
|
||||||
|
},
|
||||||
|
"componentLibraries": ["./myComponents"]
|
||||||
|
});
|
||||||
|
|
||||||
|
const getComponent = name => ({
|
||||||
|
testIndexHtml : {
|
||||||
|
title: "string",
|
||||||
|
customScripts: {
|
||||||
|
type:"array",
|
||||||
|
elementDefinition: {
|
||||||
|
url: "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}[name])
|
||||||
|
|
||||||
|
describe("validate single page", () => {
|
||||||
|
|
||||||
|
it("should return no errors when page is valid", () => {
|
||||||
|
const errors = validatePage(
|
||||||
|
validPages().main,
|
||||||
|
getComponent);
|
||||||
|
|
||||||
|
expect(errors).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return error when index is not set, or set incorrectly", () => {
|
||||||
|
let page = validPages().main;
|
||||||
|
delete page.index;
|
||||||
|
expect(validatePage(page, getComponent).length).toEqual(1);
|
||||||
|
|
||||||
|
page.index = {title:"something"}; // no _component
|
||||||
|
const noComponent = validatePage(page, getComponent);
|
||||||
|
expect(noComponent.length).toEqual(1);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return error when appBody is not set, or set incorrectly", () => {
|
||||||
|
let page = validPages().main;
|
||||||
|
delete page.appBody;
|
||||||
|
expect(validatePage(page, getComponent).length).toEqual(1);
|
||||||
|
|
||||||
|
page.appBody = true; // not a string
|
||||||
|
expect(validatePage(page, getComponent).length).toEqual(1);
|
||||||
|
|
||||||
|
page.appBody = "something.js"; // not a json
|
||||||
|
expect(validatePage(page, getComponent).length).toEqual(1);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("validate pages", () => {
|
||||||
|
|
||||||
|
it("should return no errors when pages are valid", () => {
|
||||||
|
const errors = validatePages(
|
||||||
|
validPages(),
|
||||||
|
getComponent);
|
||||||
|
|
||||||
|
expect(errors).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return error when index is not set, or set incorrectly", () => {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue