flagpole
Version:
Simple and fast DOM integration, headless or headful browser, and REST API testing framework.
258 lines • 9.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const util_1 = require("./util");
const _1 = require(".");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
function getSchemaPath(schemaName) {
let path;
if (schemaName.startsWith("@") && schemaName.length > 1) {
const schemasFolder = _1.FlagpoleExecution.global.config.getSchemasFolder();
if (!schemasFolder) {
throw "Flagpole schema folder path not found.";
}
fs_extra_1.ensureDirSync(schemasFolder);
path = path_1.resolve(schemasFolder, `${schemaName.substr(1)}.json`);
}
else {
path = path_1.resolve(schemaName);
}
fs_extra_1.ensureFileSync(path);
return path;
}
exports.getSchemaPath = getSchemaPath;
function getSchema(schemaName) {
const schemaPath = getSchemaPath(schemaName);
if (fs_extra_1.existsSync(schemaPath)) {
const content = fs_extra_1.readFileSync(schemaPath, "utf8");
return JSON.parse(content);
}
throw `Schema file ${schemaPath} does not exist`;
}
exports.getSchema = getSchema;
function writeSchema(input, schemaName) {
const schema = generateAjvSchema(input);
fs_extra_1.writeFileSync(getSchemaPath(schemaName), JSON.stringify(schema, null, 2));
return schema;
}
exports.writeSchema = writeSchema;
function generateAjvSchema(json) {
const ajvTypes = [
"string",
"number",
"boolean",
"array",
"object",
"null",
];
function parseItem(item) {
const schema = {};
const myType = util_1.toType(item);
if (ajvTypes.includes(myType)) {
schema.type = myType;
}
if (myType === "object") {
schema.properties = {};
Object.keys(item).forEach((key) => {
schema.properties[key] = parseItem(item[key]);
});
}
else if (myType == "array") {
const arr = item;
if (arr.length > 0) {
const containsAllObjects = arr.every((row) => {
return util_1.toType(row) === "object";
});
if (containsAllObjects) {
schema.items = {
type: "object",
properties: {},
};
arr.forEach((row) => {
const rowSchema = parseItem(row);
if (rowSchema.properties) {
Object.keys(rowSchema.properties).forEach((key) => {
const prevItem = schema.items.properties[key];
const newItem = rowSchema.properties[key];
if (!prevItem) {
schema.items.properties[key] = {
type: newItem.type,
};
}
else {
const prevType = typeof schema.items.properties[key].type === "string"
? [schema.items.properties[key].type]
: schema.items.properties[key].type;
if (!prevType.includes(newItem.type)) {
schema.items.properties[key].type = prevType.concat([
newItem.type,
]);
}
}
});
}
});
}
else {
schema.items = [];
item.forEach((value) => {
schema.items.push(util_1.toType(value));
});
schema.items = schema.items.filter((v, i, a) => a.indexOf(v) === i);
}
}
}
return schema;
}
return parseItem(json);
}
exports.generateAjvSchema = generateAjvSchema;
class AssertionSchema {
constructor() {
this._errors = [];
this._root = null;
}
get errors() {
return this._errors;
}
validate(schema, root) {
this._errors = [];
this._schema = schema;
this._root = root;
return new Promise((resolve) => {
resolve(this._isValid(this._schema, this._root, "$"));
});
}
_logError(message) {
const err = new Error(message);
this._errors.push(err);
}
_matchesType(schema, document, path) {
const schemaType = util_1.toType(schema);
const docType = util_1.toType(document);
if (schemaType != "undefined") {
if (schemaType == "string") {
if (docType != schema) {
this._logError(`typeOf ${path} was ${docType}, which did not match ${schema}`);
return false;
}
}
else if (schemaType == "array") {
const allowedTypes = schema;
if (allowedTypes.indexOf(docType) < 0) {
this._logError(`${path} was ${docType}, which did not match ${allowedTypes.join(" | ")}`);
return false;
}
}
}
return true;
}
_matchesEnum(schema, document, path) {
if (util_1.toType(schema) == "array") {
if (schema.indexOf(document) < 0) {
this._logError(`${path} value ${document} is not in enum ${schema.join(", ")}`);
return false;
}
}
return true;
}
_matchesPattern(schema, document, path) {
const schemaType = util_1.toType(schema);
if (schemaType != "undefined" &&
!new RegExp(schema).test(String(document))) {
this._logError(`${path} value ${document} did not match ${String(schema)}`);
return false;
}
return true;
}
_matchesTest(schema, document, path) {
const schemaType = util_1.toType(schema);
if (schemaType == "function") {
let opts = {
path: path,
parent: document,
root: this._root,
};
if (!schema(document, opts)) {
this._logError(`${path} did not pass the test`);
return false;
}
}
return true;
}
_matchesItems(schema, document, path) {
const schemaType = util_1.toType(schema);
const docType = util_1.toType(document);
if (schemaType != "undefined") {
if (docType != "array") {
this._logError(`${path} was not an array, but schema defines items.`);
return false;
}
return document.every((subItem, index) => {
if (schemaType == "string" || schemaType == "array") {
return this._matchesType(schema, subItem, `${path}[${index}]`);
}
else if (schemaType == "object") {
return this._isValid(schema, subItem, `${path}[${index}]`);
}
return true;
});
}
return true;
}
_matchesProperties(schema, document, path) {
const schemaType = util_1.toType(schema);
const docType = util_1.toType(document);
if (schemaType != "undefined") {
if (docType != "object") {
this._logError(`${path} was not an object, but schema defines properties.`);
return false;
}
if (schemaType == "string" || schemaType == "array") {
return Object.keys(document).every((key) => {
return this._matchesType(schema, document[key], `${path}.${key}`);
});
}
if (schemaType == "object") {
return Object.keys(schema).every((key) => {
return this._isValid(schema[key], document[key], `${path}.${key}`);
});
}
}
return true;
}
_isValid(schema, document, path) {
const schemaType = util_1.toType(schema);
const docType = util_1.toType(document);
if (schemaType == "string" || schemaType == "array") {
if (!this._matchesType(schema, document, path)) {
return false;
}
}
else if (schemaType == "object") {
if (!this._matchesType(schema.type, document, path)) {
if (!schema.optional || typeof document != "undefined") {
return false;
}
}
if (!this._matchesEnum(schema.enum, document, path)) {
return false;
}
if (!this._matchesPattern(schema.matches, document, path)) {
return false;
}
if (!this._matchesTest(schema.test, document, path)) {
return false;
}
if (!this._matchesItems(schema.items, document, path)) {
return false;
}
if (!this._matchesProperties(schema.properties, document, path)) {
return false;
}
}
return true;
}
}
exports.AssertionSchema = AssertionSchema;
//# sourceMappingURL=assertionschema.js.map