@qavajs/validation
Version:
Lib that transform plain english definition to validation functions
139 lines • 5.23 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.expect = exports.Expect = exports.SoftAssertionError = exports.AssertionError = void 0;
const node_util_1 = __importDefault(require("node:util"));
class AssertionError extends Error {
name = 'AssertionError';
}
exports.AssertionError = AssertionError;
class SoftAssertionError extends AssertionError {
name = 'SoftAssertionError';
}
exports.SoftAssertionError = SoftAssertionError;
const customMatchers = {};
class Expect {
received;
isSoft = false;
isPoll = false;
pollConfiguration = { timeout: 5000, interval: 100 };
isNot = false;
constructor(received, configuration) {
this.received = received;
this.isSoft = configuration?.soft ?? false;
this.isPoll = configuration?.poll ?? false;
this.isNot = configuration?.not ?? false;
}
/**
* Negates matcher
*/
get not() {
this.isNot = true;
return this;
}
/**
* Enables soft matcher
*/
get soft() {
this.isSoft = true;
return this;
}
get Error() {
return this.isSoft ? SoftAssertionError : AssertionError;
}
poll({ timeout, interval } = {}) {
if (typeof this.received !== 'function') {
throw new TypeError('Provided value must be a function');
}
this.isPoll = true;
this.pollConfiguration.timeout = timeout ?? 5000;
this.pollConfiguration.interval = interval ?? 100;
return this;
}
configure(options) {
this.isNot = options.not ?? this.isNot;
this.isSoft = options.soft ?? this.isSoft;
this.isPoll = options.poll ?? this.isPoll;
this.pollConfiguration.timeout = options.timeout ?? this.pollConfiguration.timeout;
this.pollConfiguration.interval = options.interval ?? this.pollConfiguration.interval;
return this;
}
/**
* Format error message
* @param received
* @param expected
* @param assert
* @param isNot
*/
formatMessage(received, expected, assert, isNot) {
return `expected ${this.asString(received)} ${isNot ? 'not ' : ''}${assert} ${this.asString(expected)}`;
}
asString(value) {
if (typeof value === 'function')
return value.toString();
return node_util_1.default.inspect(value, { depth: 1, compact: true });
}
;
}
exports.Expect = Expect;
function createExpect() {
function expect(target) {
const instance = new Expect(target);
const sleep = (ms) => new Promise(res => setTimeout(res, ms));
return new Proxy(instance, {
get(target, prop, receiver) {
if (prop in target)
return Reflect.get(target, prop, receiver);
const matcher = customMatchers[prop];
if (!matcher)
throw new TypeError(`${prop} matcher not found`);
return (...expected) => {
if (target.isPoll) {
return (async () => {
const { timeout, interval } = target.pollConfiguration;
const start = Date.now();
while (true) {
try {
const pollTarget = Object.create(target);
pollTarget.received = await target.received();
const { pass, message } = await matcher.call(pollTarget, ...expected);
if (target.isNot !== pass)
return;
if (Date.now() - start >= timeout) {
throw new target.Error(message);
}
}
catch (err) {
if (Date.now() - start >= timeout)
throw err;
}
await sleep(interval);
}
})();
}
const result = matcher.call(target, ...expected);
if (result instanceof Promise) {
return result.then(({ pass, message }) => {
if (target.isNot === pass)
throw new target.Error(message);
});
}
else {
const { pass, message } = result;
if (target.isNot === pass)
throw new target.Error(message);
}
};
},
});
}
expect.extend = function (matchers) {
Object.assign(customMatchers, matchers);
return createExpect();
};
return expect;
}
exports.expect = createExpect();
//# sourceMappingURL=expect.js.map