add assertShape to validate templateElement (#10198)
* add assertShape to validate templateElement * Update packages/babel-types/src/definitions/utils.js Co-Authored-By: Nicolò Ribaudo <nicolo.ribaudo@gmail.com> * templateElement optional cooked
This commit is contained in:
parent
d3fe22f0e1
commit
ee68d6d1b0
@ -31,6 +31,29 @@ module.exports = function stringifyValidator(validator, nodePrefix) {
|
||||
return validator.type;
|
||||
}
|
||||
|
||||
if (validator.shapeOf) {
|
||||
return (
|
||||
"{ " +
|
||||
Object.keys(validator.shapeOf)
|
||||
.map(shapeKey => {
|
||||
const propertyDefinition = validator.shapeOf[shapeKey];
|
||||
if (propertyDefinition.validate) {
|
||||
const isOptional =
|
||||
propertyDefinition.optional || propertyDefinition.default != null;
|
||||
return (
|
||||
shapeKey +
|
||||
(isOptional ? "?: " : ": ") +
|
||||
stringifyValidator(propertyDefinition.validate)
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(Boolean)
|
||||
.join(", ") +
|
||||
" }"
|
||||
);
|
||||
}
|
||||
|
||||
return ["any"];
|
||||
};
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
// @flow
|
||||
import defineType, {
|
||||
assertShape,
|
||||
assertNodeType,
|
||||
assertValueType,
|
||||
chain,
|
||||
@ -542,7 +543,15 @@ defineType("TemplateElement", {
|
||||
builder: ["value", "tail"],
|
||||
fields: {
|
||||
value: {
|
||||
// todo: flatten `raw` into main node
|
||||
validate: assertShape({
|
||||
raw: {
|
||||
validate: assertValueType("string"),
|
||||
},
|
||||
cooked: {
|
||||
validate: assertValueType("string"),
|
||||
optional: true,
|
||||
},
|
||||
}),
|
||||
},
|
||||
tail: {
|
||||
validate: assertValueType("boolean"),
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
// @flow
|
||||
import is from "../validators/is";
|
||||
import { validateField } from "../validators/validate";
|
||||
|
||||
export const VISITOR_KEYS: { [string]: Array<string> } = {};
|
||||
export const ALIAS_KEYS: { [string]: Array<string> } = {};
|
||||
@ -161,6 +162,34 @@ export function assertValueType(type: string): Validator {
|
||||
return validate;
|
||||
}
|
||||
|
||||
export function assertShape(shape: { [string]: FieldOptions }): Validator {
|
||||
function validate(node, key, val) {
|
||||
const errors = [];
|
||||
for (const property of Object.keys(shape)) {
|
||||
try {
|
||||
validateField(node, property, val[property], shape[property]);
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
errors.push(error.message);
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
if (errors.length) {
|
||||
throw new TypeError(
|
||||
`Property ${key} of ${
|
||||
node.type
|
||||
} expected to have the following:\n${errors.join("\n")}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
validate.shapeOf = shape;
|
||||
|
||||
return validate;
|
||||
}
|
||||
|
||||
export function chain(...fns: Array<Validator>): Validator {
|
||||
function validate(...args) {
|
||||
for (const fn of fns) {
|
||||
|
||||
@ -8,6 +8,15 @@ export default function validate(node?: Object, key: string, val: any): void {
|
||||
if (!fields) return;
|
||||
|
||||
const field = fields[key];
|
||||
validateField(node, key, val, field);
|
||||
}
|
||||
|
||||
export function validateField(
|
||||
node?: Object,
|
||||
key: string,
|
||||
val: any,
|
||||
field: any,
|
||||
): void {
|
||||
if (!field || !field.validate) return;
|
||||
if (field.optional && val == null) return;
|
||||
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`builders es2015 templateElement should validate 1`] = `
|
||||
Object {
|
||||
"tail": false,
|
||||
"type": "TemplateElement",
|
||||
"value": Object {
|
||||
"cooked": "foo",
|
||||
"raw": "foo",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`builders es2015 templateElement should validate 2`] = `
|
||||
Object {
|
||||
"tail": false,
|
||||
"type": "TemplateElement",
|
||||
"value": Object {
|
||||
"raw": "foo",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`builders es2015 templateElement should validate 3`] = `
|
||||
"Property value of TemplateElement expected to have the following:
|
||||
Property raw expected type of string but got number"
|
||||
`;
|
||||
|
||||
exports[`builders es2015 templateElement should validate 4`] = `
|
||||
"Property value of TemplateElement expected to have the following:
|
||||
Property cooked expected type of string but got number"
|
||||
`;
|
||||
|
||||
exports[`builders es2015 templateElement should validate 5`] = `
|
||||
"Property value of TemplateElement expected to have the following:
|
||||
Property raw expected type of string but got undefined"
|
||||
`;
|
||||
25
packages/babel-types/test/builders/es2015/templateElement.js
Normal file
25
packages/babel-types/test/builders/es2015/templateElement.js
Normal file
@ -0,0 +1,25 @@
|
||||
import * as t from "../../..";
|
||||
|
||||
describe("builders", function() {
|
||||
describe("es2015", function() {
|
||||
describe("templateElement", function() {
|
||||
it("should validate", function() {
|
||||
expect(
|
||||
t.templateElement({ raw: "foo", cooked: "foo" }),
|
||||
).toMatchSnapshot();
|
||||
|
||||
expect(t.templateElement({ raw: "foo" })).toMatchSnapshot();
|
||||
|
||||
expect(() =>
|
||||
t.templateElement({ raw: 1 }),
|
||||
).toThrowErrorMatchingSnapshot();
|
||||
|
||||
expect(() =>
|
||||
t.templateElement({ raw: "foo", cooked: 1 }),
|
||||
).toThrowErrorMatchingSnapshot();
|
||||
|
||||
expect(() => t.templateElement("foo")).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user