mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] validation: add support for value types
This commit add supports for value types in prop validation. To describe
a value V type, one has to simply write {value: V}.
Note that this commit also improves the validation typing.
closes #1198
closes #910
This commit is contained in:
committed by
Sam Degueldre
parent
55ac43c1db
commit
9c4c3e3b83
@@ -159,6 +159,7 @@ For each key, a `prop` definition is either a boolean, a constructor, a list of
|
||||
- a boolean: indicate that the props exists, and is mandatory.
|
||||
- a constructor: this should describe the type, for example: `id: Number` describe
|
||||
the props `id` as a number
|
||||
- an object describing a value as type. This is done by using the `value` key. For example, `{value: false}` specifies that the corresponding value should be equal to false.
|
||||
- a list of constructors. In that case, this means that we allow more than one
|
||||
type. For example, `id: [Number, String]` means that `id` can be either a string
|
||||
or a number.
|
||||
@@ -240,6 +241,7 @@ class ComponentB extends owl.Component {
|
||||
size: {
|
||||
validate: e => ["small", "medium", "large"].includes(e)
|
||||
},
|
||||
someId: [Number, {value: false}], // either a number or false
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
@@ -8,9 +8,6 @@ type BaseType =
|
||||
| true
|
||||
| "*";
|
||||
|
||||
type UnionType = (TypeInfo | BaseType)[];
|
||||
type TypeDescription = BaseType | UnionType | TypeInfo;
|
||||
|
||||
interface TypeInfo {
|
||||
type?: TypeDescription;
|
||||
optional?: boolean;
|
||||
@@ -19,6 +16,9 @@ interface TypeInfo {
|
||||
element?: TypeDescription;
|
||||
}
|
||||
|
||||
type ValueType = { value: any };
|
||||
|
||||
type TypeDescription = BaseType | TypeInfo | ValueType | TypeDescription[];
|
||||
type SimplifiedSchema = string[];
|
||||
type NormalizedSchema = { [key: string]: TypeDescription };
|
||||
export type Schema = SimplifiedSchema | NormalizedSchema;
|
||||
@@ -26,8 +26,10 @@ export type Schema = SimplifiedSchema | NormalizedSchema;
|
||||
// -----------------------------------------------------------------------------
|
||||
// helpers
|
||||
// -----------------------------------------------------------------------------
|
||||
const isUnionType = (t: TypeDescription): t is UnionType => Array.isArray(t);
|
||||
const isUnionType = (t: TypeDescription): t is TypeDescription[] => Array.isArray(t);
|
||||
const isBaseType = (t: TypeDescription): t is BaseType => typeof t !== "object";
|
||||
const isValueType = (t: TypeDescription): t is ValueType =>
|
||||
typeof t === "object" && t && "value" in t;
|
||||
|
||||
export function isOptional(t: TypeDescription): Boolean {
|
||||
return typeof t === "object" && "optional" in t ? t.optional || false : false;
|
||||
@@ -42,6 +44,8 @@ function describe(info: TypeDescription): string {
|
||||
return describeType(info);
|
||||
} else if (isUnionType(info)) {
|
||||
return info.map(describe).join(" or ");
|
||||
} else if (isValueType(info)) {
|
||||
return String(info.value);
|
||||
}
|
||||
if ("element" in info) {
|
||||
return `list of ${describe({ type: info.element, optional: false })}s`;
|
||||
@@ -134,6 +138,8 @@ function validateType(key: string, value: any, descr: TypeDescription): string |
|
||||
return isOptional(descr) ? null : `'${key}' is undefined (should be a ${describe(descr)})`;
|
||||
} else if (isBaseType(descr)) {
|
||||
return validateBaseType(key, value, descr);
|
||||
} else if (isValueType(descr)) {
|
||||
return value === descr.value ? null : `'${key}' is not equal to '${descr.value}'`;
|
||||
} else if (isUnionType(descr)) {
|
||||
let validDescr = descr.find((p) => !validateType(key, value, p));
|
||||
return validDescr ? null : `'${key}' is not a ${describe(descr)}`;
|
||||
|
||||
@@ -248,4 +248,30 @@ describe("validateSchema", () => {
|
||||
expect(validateSchema({ size: "sall" }, schema)).toEqual(["'size' is not valid"]);
|
||||
expect(validateSchema({ size: 1 }, schema)).toEqual(["'size' is not a string"]);
|
||||
});
|
||||
|
||||
test("value as type", () => {
|
||||
expect(validateSchema({ a: false }, { a: { value: false } })).toEqual([]);
|
||||
expect(validateSchema({ a: true }, { a: { value: false } })).toEqual([
|
||||
"'a' is not equal to 'false'",
|
||||
]);
|
||||
});
|
||||
|
||||
test("value as type (some other values)", () => {
|
||||
expect(validateSchema({ a: null }, { a: { value: null } })).toEqual([]);
|
||||
expect(validateSchema({ a: false }, { a: { value: null } })).toEqual([
|
||||
"'a' is not equal to 'null'",
|
||||
]);
|
||||
expect(validateSchema({ a: "hey" }, { a: { value: "hey" } })).toEqual([]);
|
||||
expect(validateSchema({ a: true }, { a: { value: "hey" } })).toEqual([
|
||||
"'a' is not equal to 'hey'",
|
||||
]);
|
||||
});
|
||||
|
||||
test("value as type work in union type", () => {
|
||||
expect(validateSchema({ a: false }, { a: [String, { value: false }] })).toEqual([]);
|
||||
expect(validateSchema({ a: true }, { a: [String, { value: false }] })).toEqual([
|
||||
"'a' is not a string or false",
|
||||
]);
|
||||
expect(validateSchema({ a: "string" }, { a: [String, { value: false }] })).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user