cumulocity-cypress
Version:
Cypress commands for Cumulocity IoT
96 lines (95 loc) • 3.08 kB
JavaScript
import _ from "lodash";
import * as semver from "semver";
import Ajv from "ajv";
import addFormats from "ajv-formats";
import draft06Schema from "ajv/lib/refs/json-schema-draft-06.json";
/**
* Default implementation of C8ySchemaMatcher using AJV. By default
* json-schema-draft-07 meta schema is used. Other meta schema can be added
* by passing in constructor. If options.strictMatching is disabled for match,
* additionalProperties will be set to true allowing additional properties
* in the object to match the schema.
*/
export class C8yAjvSchemaMatcher {
constructor(metas, strict = false) {
if (_.isBoolean(metas)) {
{
strict = metas;
metas = undefined;
}
}
//https://ajv.js.org/options.html
this.ajv = new Ajv({ strict, allowUnionTypes: true });
addFormats(this.ajv, [
"uri",
"uri-reference",
"url",
"uuid",
"hostname",
"date-time",
"date",
"password",
]);
this.ajv.addFormat("integer", {
type: "number",
validate: (x) => _.isInteger(x),
});
this.ajv.addFormat("boolean", {
validate: (x) => _.isBoolean(x),
});
this.ajv.addFormat("boolean", {
type: "string",
validate: (x) => _.isString(x) && ["true", "false"].includes(_.lowerCase(x)),
});
this.ajv.addFormat("semver-range", {
type: "string",
validate: (x) => {
return semver.validRange(x) != null;
},
});
this.ajv.addFormat("semver-version", {
type: "string",
validate: (x) => {
return semver.valid(x) != null;
},
});
if (metas && _.isArrayLike(metas)) {
metas.forEach((m) => {
this.ajv.addMetaSchema(m);
});
}
}
match(obj, schema, strictMatching) {
if (!schema)
return false;
const schemaClone = _.cloneDeep(schema);
if (strictMatching != null) {
this.updateAdditionalProperties(schemaClone, !strictMatching);
}
const valid = this.ajv.validate(schemaClone, obj);
if (!valid) {
throw new Error(this.ajv.errorsText());
}
return valid;
}
updateAdditionalProperties(schema, value) {
if (_.isObjectLike(schema)) {
if ("additionalProperties" in schema || schema.type === "object") {
schema.additionalProperties = value;
}
Object.values(schema).forEach((v) => {
this.updateAdditionalProperties(v, value);
});
}
else if (_.isArray(schema)) {
schema.forEach((v) => {
this.updateAdditionalProperties(v, value);
});
}
}
}
export class C8yAjvJson6SchemaMatcher extends C8yAjvSchemaMatcher {
constructor() {
super([draft06Schema]);
}
}