component prop definition - create
This commit is contained in:
parent
601755f17a
commit
a81af3f18b
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"presets": ["@babel/preset-env"],
|
||||||
|
"sourceMaps": "inline",
|
||||||
|
"retainLines": true,
|
||||||
|
"plugins": [
|
||||||
|
["@babel/plugin-transform-runtime",
|
||||||
|
{
|
||||||
|
"regenerator": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
|
@ -6,6 +6,30 @@
|
||||||
"build": "rollup -c",
|
"build": "rollup -c",
|
||||||
"start": "rollup -c -w"
|
"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": {
|
"dependencies": {
|
||||||
"@nx-js/compiler-util": "^2.0.0",
|
"@nx-js/compiler-util": "^2.0.0",
|
||||||
"budibase-core": "file:../core/dist",
|
"budibase-core": "file:../core/dist",
|
||||||
|
@ -20,8 +44,14 @@
|
||||||
"uikit": "^3.1.5"
|
"uikit": "^3.1.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"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",
|
"browser-sync": "^2.26.7",
|
||||||
"http-proxy-middleware": "^0.19.1",
|
"http-proxy-middleware": "^0.19.1",
|
||||||
|
"jest": "^24.8.0",
|
||||||
"ncp": "^2.0.0",
|
"ncp": "^2.0.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"rollup": "^1.12.0",
|
"rollup": "^1.12.0",
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
Loading…
Reference in New Issue