component prop definition - create

This commit is contained in:
michael shanks 2019-07-19 12:52:08 +01:00
parent 601755f17a
commit a81af3f18b
4 changed files with 272 additions and 0 deletions

12
packages/builder/.babelrc Normal file
View File

@ -0,0 +1,12 @@
{
"presets": ["@babel/preset-env"],
"sourceMaps": "inline",
"retainLines": true,
"plugins": [
["@babel/plugin-transform-runtime",
{
"regenerator": true
}
]
]
}

View File

@ -6,6 +6,30 @@
"build": "rollup -c",
"start": "rollup -c -w"
},
"jest": {
"globals": {
"GLOBALS": {
"client": "web"
}
},
"testURL": "http://jest-breaks-if-this-does-not-exist",
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/internals/mocks/fileMock.js",
"\\.(css|less|sass|scss)$": "identity-obj-proxy"
},
"moduleFileExtensions": [
"js"
],
"moduleDirectories": [
"node_modules"
],
"transform": {
"^.+\\.js$": "babel-jest"
},
"transformIgnorePatterns": [
"/node_modules/(?!svelte).+\\.js$"
]
},
"dependencies": {
"@nx-js/compiler-util": "^2.0.0",
"budibase-core": "file:../core/dist",
@ -20,8 +44,14 @@
"uikit": "^3.1.5"
},
"devDependencies": {
"@babel/core": "^7.5.5",
"@babel/plugin-transform-runtime": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@babel/runtime": "^7.5.5",
"babel-jest": "^24.8.0",
"browser-sync": "^2.26.7",
"http-proxy-middleware": "^0.19.1",
"jest": "^24.8.0",
"ncp": "^2.0.0",
"npm-run-all": "^4.1.5",
"rollup": "^1.12.0",

View File

@ -0,0 +1,68 @@
import {
isString,
isBoolean,
isNumber,
isArray,
isUndefined
} from "lodash/fp";
import { assign } from "lodash";
export const createDefaultProps = (propsDefinition, derivedFromProps) => {
const props = {};
const errors = [];
for(let propDef in propsDefinition) {
const parsedPropDef = parsePropDef(propsDefinition[propDef]);
if(parsedPropDef.error)
errors.push({propName:propDef, error:parsedPropDef.error});
else
props[propDef] = parsedPropDef;
}
if(derivedFromProps) {
assign(props, ...derivedFromProps);
}
return ({
props, errors
});
}
const parsePropDef = propDef => {
const error = message => ({error:message});
if(isString(propDef)) {
if(!types[propDef])
return error(`Do not recognise type ${propDef}`);
return types[propDef].default();
}
if(!propDef.type)
return error("Property Definition must declare a type");
const type = types[propDef.type];
if(!type)
return error(`Do not recognise type ${propDef.type}`);
if(isUndefined(propDef.default))
return type.default(propDef);
if(!type.isOfType(propDef.default))
return error(`${propDef.default} is not of type ${type}`);
return propDef.default;
}
const propType = (defaultValue, isOfType) => ({
isOfType, default:defaultValue
});
const types = {
string: propType(() => "", isString),
bool: propType(() => false, isBoolean),
number: propType(() => 0, isNumber),
array: propType(() => [], isArray)
}

View File

@ -0,0 +1,162 @@
import { createDefaultProps } from "../src/userInterface/propsDefinitionParsing/createDefaultProps";
import {
keys, some
} from "lodash/fp";
describe("createDefaultProps", () => {
it("should create a object with single string value, when default string field set", () => {
const propDef = {
fieldName: {type:"string", default:"something"}
};
const { props, errors } = createDefaultProps(propDef);
expect(errors).toEqual([]);
expect(props.fieldName).toBeDefined();
expect(props.fieldName).toBe("something");
expect(keys(props).length).toBe(1);
});
it("should create a object with single blank string value, when no default", () => {
const propDef = {
fieldName: {type:"string"}
};
const { props, errors } = createDefaultProps(propDef);
expect(errors).toEqual([]);
expect(props.fieldName).toBeDefined();
expect(props.fieldName).toBe("");
});
it("should create a object with single blank string value, when prop definition is 'string' ", () => {
const propDef = {
fieldName: "string"
};
const { props, errors } = createDefaultProps(propDef);
expect(errors).toEqual([]);
expect(props.fieldName).toBeDefined();
expect(props.fieldName).toBe("");
});
it("should create a object with single fals value, when prop definition is 'bool' ", () => {
const propDef = {
fieldName: "bool"
};
const { props, errors } = createDefaultProps(propDef);
expect(errors).toEqual([]);
expect(props.fieldName).toBeDefined();
expect(props.fieldName).toBe(false);
});
it("should create a object with single 0 value, when prop definition is 'number' ", () => {
const propDef = {
fieldName: "number"
};
const { props, errors } = createDefaultProps(propDef);
expect(errors).toEqual([]);
expect(props.fieldName).toBeDefined();
expect(props.fieldName).toBe(0);
});
it("should create a object with single 0 value, when prop definition is 'array' ", () => {
const propDef = {
fieldName: "array"
};
const { props, errors } = createDefaultProps(propDef);
expect(errors).toEqual([]);
expect(props.fieldName).toBeDefined();
expect(props.fieldName).toEqual([]);
});
it("should create an object with multiple prop names", () => {
const propDef = {
fieldName: "string",
fieldLength: { type: "number", default: 500 }
};
const { props, errors } = createDefaultProps(propDef);
expect(errors).toEqual([]);
expect(props.fieldName).toBeDefined();
expect(props.fieldName).toBe("");
expect(props.fieldLength).toBeDefined();
expect(props.fieldLength).toBe(500);
expect(keys(props).length).toBe(2);
})
it("should return error when invalid type", () => {
const propDef = {
fieldName: "invalid type name",
fieldLength: { type: "invalid type name "}
};
const { errors } = createDefaultProps(propDef);
expect(errors.length).toBe(2);
expect(some(e => e.propName === "fieldName")(errors)).toBeTruthy();
expect(some(e => e.propName === "fieldLength")(errors)).toBeTruthy();
});
it("should return error default value is not of declared type", () => {
const propDef = {
fieldName: {type:"string", default: 1}
};
const { errors } = createDefaultProps(propDef);
expect(errors.length).toBe(1);
expect(some(e => e.propName === "fieldName")(errors)).toBeTruthy();
});
it("should merge in derived props", () => {
const propDef = {
fieldName: "string",
fieldLength: { type: "number", default: 500}
};
const derivedFrom = {
fieldName: "surname"
};
const { props, errors } = createDefaultProps(propDef, [derivedFrom]);
expect(errors.length).toBe(0);
expect(props.fieldName).toBe("surname");
expect(props.fieldLength).toBe(500);
});
it("should merge in derived props, last in list taking priority", () => {
const propDef = {
fieldName: "string",
fieldLength: { type: "number", default: 500}
};
const derivedFrom1 = {
fieldName: "surname",
fieldLength: 200
};
const derivedFrom2 = {
fieldName: "forename"
};
const { props, errors } = createDefaultProps(propDef, [derivedFrom1, derivedFrom2]);
expect(errors.length).toBe(0);
expect(props.fieldName).toBe("forename");
expect(props.fieldLength).toBe(200);
});
})