1
0
Fork 0
mirror of synced 2024-07-04 22:11:23 +12:00

Remove unused validateProps module and tests

This commit is contained in:
pngwn 2020-01-24 16:39:25 +00:00
parent aaae1fd1ef
commit 0490441d09
3 changed files with 13 additions and 389 deletions

View file

@ -1,7 +1,6 @@
import { recursivelyValidate } from "./validateProps";
import {
isString,
keys,
import {
isString,
keys,
flatten,
isArray,
map,
@ -15,12 +14,12 @@ export const validatePage = (page, getComponent) => {
const error = message => errors.push(message);
const noIndex = !page.index;
if(noIndex) {
if (noIndex) {
error("Page does not define an index member");
}
if(!page.appBody
|| !isString(page.appBody)
if (!page.appBody
|| !isString(page.appBody)
|| !page.appBody.endsWith(".json")) {
error("App body must be set toa valid JSON file");
}
@ -28,7 +27,7 @@ export const validatePage = (page, getComponent) => {
/* Commenting this for now
* index is a load of static members just now, but maybe useful
for pageLayout props (which is just a pipe dream at time of writing)
const indexHtmlErrors = noIndex
const indexHtmlErrors = noIndex
? []
: pipe(
recursivelyValidate(page.index, getComponent), [
@ -44,17 +43,17 @@ export const validatePages = (pages, getComponent) => {
let errors = [];
const error = message => errors.push(message);
if(!pages.main) {
if (!pages.main) {
error("must have a 'main' page");
}
if(!pages.unauthenticated) {
if (!pages.unauthenticated) {
error("must have a 'unauthenticated' (login) page");
}
if(!pages.componentLibraries
|| !isArray(pages.componentLibraries)
|| pages.componentLibraries.length === 0) {
if (!pages.componentLibraries
|| !isArray(pages.componentLibraries)
|| pages.componentLibraries.length === 0) {
error("componentLibraries must be set to a non-empty array of strings");
}
@ -67,4 +66,4 @@ export const validatePages = (pages, getComponent) => {
]);
return [...errors, ...pageErrors];
}
}

View file

@ -1,143 +0,0 @@
import { types } from "./types";
import {
createProps, arrayElementComponentName
} from "./createProps";
import { isString } from "util";
import {
includes, filter, map, keys,
flatten, flattenDeep, each,
indexOf, isUndefined
} from "lodash/fp";
import { common } from "../../../../core/src";
import {
isBinding
} from "../../common/binding";
const pipe = common.$;
const makeError = (errors, propName, stack) => (message) =>
errors.push({
stack,
propName,
error: message
});
export const recursivelyValidate = (rootProps, getComponent, stack = []) => {
if (!rootProps._component) {
const errs = [];
makeError(errs, "_component", stack)("Component is not set");
return errs;
// this would break everything else anyway
}
const componentDef = getComponent(
rootProps._component);
const errors = validateProps(
componentDef,
rootProps,
stack,
true);
const validateChildren = (_props, _stack) =>
!_props._children
? []
: pipe(_props._children, [
map(child => recursivelyValidate(
child,
getComponent,
[..._stack, _props._children.indexOf(child)]))
]);
const childErrors = validateChildren(
rootProps, stack);
return flattenDeep([errors, ...childErrors]);
}
const expandPropDef = propDef =>
isString(propDef)
? types[propDef].defaultDefinition()
: propDef;
export const validateProps = (componentDefinition, props, stack = [], isFinal = true) => {
const errors = [];
if (isFinal && !props._component) {
makeError(errors, "_component", stack)("Component is not set");
return errors;
// this would break everything else anyway
}
const propsDefinition = componentDefinition.props;
for (let propDefName in props) {
const ignore = ['_component', "_children", '_layout', 'name', 'description', 'location'];
if (ignore.includes(propDefName)) continue;
const propDef = expandPropDef(propsDefinition[propDefName]);
const type = types[propDef.type];
const error = makeError(errors, propDefName, stack);
const propValue = props[propDefName];
// component declarations dont need to define al props.
if (!isFinal && isUndefined(propValue)) continue;
if (isFinal && propDef.required && propValue) {
error(`Property ${propDefName} is required`);
continue;
}
if (isBinding(propValue)) {
if (propDef.type === "event") {
error(`Cannot apply binding to type ${propDef.type}`);
continue;
}
}
else if (!type.isOfType(propValue)) {
error(`Property ${propDefName} is not of type ${propDef.type}. Actual value ${propValue}`)
continue;
}
if (propDef.type === "options"
&& propValue
&& !isBinding(propValue)
&& !includes(propValue)(propDef.options)) {
error(`Property ${propDefName} is not one of allowed options. Acutal value is ${propValue}`);
}
}
return errors;
}
export const validateComponentDefinition = (componentDefinition) => {
const { errors } = createProps(componentDefinition);
const propDefinitions = expandPropDef(componentDefinition.props);
pipe(propDefinitions, [
keys,
map(k => ({
propDef: propDefinitions[k],
propName: k
})),
filter(d => d.propDef.type === "options"
&& (!d.propDef.options || d.propDef.options.length === 0)),
each(d => makeError(errors, d.propName)(`${d.propName} does not have any options`))
]);
return errors;
}

View file

@ -1,232 +0,0 @@
import {
validateComponentDefinition,
validateProps,
recursivelyValidate
} from "../src/userInterface/pagesParsing/validateProps";
import { createProps } from "../src/userInterface/pagesParsing/createProps";
import {
setBinding
} from "../src/common/binding";
// not that allot of this functionality is covered
// in createDefaultProps - as validate props uses that.
describe("validateComponentDefinition", () => {
it("should return error when no options for options field", () => {
const compDef = {
name:"some_component",
props: {
size: {
type: "options",
options: []
}
}
};
const errors = validateComponentDefinition(compDef);
expect(errors.length).toEqual(1);
expect(errors[0].propName).toBe("size");
});
it("should not return error when options field has options", () => {
const compDef = {
name: "some_component",
props: {
size: {
type: "options",
options: ["small", "medium", "large"]
}
}
};
const errors = validateComponentDefinition(compDef);
expect(errors).toEqual([]);
});
});
const validComponentDef = {
name: "some_component",
props: {
size: {
type: "options",
options: ["small", "medium", "large"],
default:"medium"
},
rowCount : "number"
}
};
const childComponentDef = {
name: "child_component",
props: {
width: "number",
units: {
type: "string",
default: "px"
}
}
};
const validProps = () => {
const { props } = createProps(validComponentDef);
props._children.push(
createProps(childComponentDef));
return props;
}
describe("validateProps", () => {
it("should have no errors with a big list of valid props", () => {
const errors = validateProps(validComponentDef, validProps(), [], true);
expect(errors).toEqual([]);
});
it("should return error with invalid value", () => {
const props = validProps();
props.rowCount = "1";
const errors = validateProps(validComponentDef, props, [], true);
expect(errors.length).toEqual(1);
expect(errors[0].propName).toBe("rowCount");
});
it("should return error with invalid option", () => {
const props = validProps();
props.size = "really_small";
const errors = validateProps(validComponentDef, props, [], true);
expect(errors.length).toEqual(1);
expect(errors[0].propName).toBe("size");
});
it("should not return error when has binding", () => {
const props = validProps();
props._children[0].width = setBinding({path:"some_path"});
props.size = setBinding({path:"other path", fallback:"small"});
const errors = validateProps(validComponentDef, props, [], true);
expect(errors.length).toEqual(0);
});
});
describe("recursivelyValidateProps", () => {
const rootComponent = {
name: "rootComponent",
children: true,
props: {
width: "number"
}
};
const todoListComponent = {
name: "todoListComponent",
props:{
showTitle: "bool"
}
};
const headerComponent = {
name: "headerComponent",
props: {
text: "string"
}
};
const iconComponent = {
name: "iconComponent",
props: {
iconName: "string"
}
};
const navItemComponent = {
name: "navItemComponent",
props: {
text: "string"
}
};
const getComponent = name => ({
rootComponent,
todoListComponent,
headerComponent,
iconComponent,
navItemComponent
})[name];
const rootProps = () => ({
_component: "rootComponent",
width: 100,
_children: [{
_component: "todoListComponent",
showTitle: true,
_children : [
{
_component: "navItemComponent",
text: "todos"
},
{
_component: "headerComponent",
text: "Your todo list"
},
{
_component: "iconComponent",
iconName: "fa fa-list"
},
{
_component: "iconComponent",
iconName:"fa fa-cog"
}
]
}]
});
it("should return no errors for valid structure", () => {
const result = recursivelyValidate(
rootProps(),
getComponent);
expect(result).toEqual([]);
});
it("should return error on root component", () => {
const root = rootProps();
root.width = "yeeeoooo";
const result = recursivelyValidate(root, getComponent);
expect(result.length).toBe(1);
expect(result[0].propName).toBe("width");
});
it("should return error on first nested child component", () => {
const root = rootProps();
root._children[0].showTitle = "yeeeoooo";
const result = recursivelyValidate(root, getComponent);
expect(result.length).toBe(1);
expect(result[0].stack).toEqual([0]);
expect(result[0].propName).toBe("showTitle");
});
it("should return error on second nested child component", () => {
const root = rootProps();
root._children[0]._children[0].text = false;
const result = recursivelyValidate(root, getComponent);
expect(result.length).toBe(1);
expect(result[0].stack).toEqual([0,0]);
expect(result[0].propName).toBe("text");
});
});