"use strict"; var core = require("@shedevro/core"); class MessageBuilder { static expected(expected, actual) { const gotLine = actual ? `. Got: ${actual}` : ""; return `expected ${expected.trim()}${gotLine}`; } static expectedValue(expected, actual) { return this.expected(`value ${expected.trim()}`, actual); } static expectedToBe(expected, actual) { return this.expectedValue(`to be ${expected.trim()}`, actual); } } class WebUtilsAssertionError extends core.AbstractAppError { message; customMessageApplied; constructor(message, customMessageApplied) { super(message); this.message = message; this.customMessageApplied = customMessageApplied; } } class AssertionHelper { static valueToString(value) { if (core.TypeHelper.isArray(value)) { return `[${value.map((v => this.valueToString(v))).join(", ")}]`; } if (core.TypeHelper.isString(value)) { return value.startsWith('"') && value.endsWith('"') ? value : `"${value}"`; } if (core.TypeHelper.isFunction(value)) { return value.name || "Function"; } if (core.TypeHelper.isObject(value)) { return value.constructor.name; } return String(value); } } class AssertClass { options; constructor(options = {}) { this.options = options; } get newInstance() { return new AssertClass; } get all() { const instance = new AssertClass(Object.assign({}, this.options)); instance.options.allOperator = true; return instance; } get is() { const instance = new AssertClass(Object.assign({}, this.options)); instance.options.isOperator = true; return instance; } get not() { const instance = new AssertClass(Object.assign({}, this.options)); instance.options.notOperator = true; return instance; } get nullOr() { const instance = new AssertClass(Object.assign({}, this.options)); instance.options.nullOrOperator = true; return instance; } string(value, customMessage) { const message = MessageBuilder.expectedToBe("a string", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isString(v); return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } emptyString(value, customMessage) { const prefix = this.options.notOperator ? "non-empty" : "empty"; const message = MessageBuilder.expectedToBe(`${prefix} string`, "{1}"); this.setMessage({ message, customMessage }); const expression = v => { if (this.options.notOperator) { return !core.TypeHelper.isString(v) || !v.trim(); } else { return core.TypeHelper.isString(v) && !v.trim(); } }; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } contains(value, subString, customMessage) { const prefix = this.options.notOperator ? "not to" : "to"; const message = MessageBuilder.expectedValue(`${prefix} contain {2}`, "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isString(v) && v.includes(subString); return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } startsWith(value, prefix, customMessage) { const msgPrefix = this.options.notOperator ? "not" : ""; const message = MessageBuilder.expectedValue(`${msgPrefix} to start with {2}`, "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isString(v) && v.startsWith(prefix); return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } endsWith(value, suffix, customMessage) { const prefix = this.options.notOperator ? "not" : ""; const message = MessageBuilder.expectedValue(`${prefix} to end with {2}`, "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isString(v) && v.endsWith(suffix); return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } oneOf(value, values, customMessage) { this.newInstance.array(values, "Assert.oneOf:values should be an array. Got: {1}"); const prefix = this.options.notOperator ? " not" : ""; const message = MessageBuilder.expectedToBe(`${prefix} one of {2}`, "{1}"); this.setMessage({ message, customMessage }); const expression = v => values.includes(v); return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } number(value, customMessage) { const message = MessageBuilder.expectedToBe("a number", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isNumber(v); return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } natural(value, customMessage) { const message = MessageBuilder.expectedToBe("a posistive number", "{1}"); this.greaterThanOrEqual(value, 0, customMessage ?? message); } greaterThan(value, limit, customMessage) { const message = MessageBuilder.expectedToBe("greater than {2}", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isNumber(v) && v > limit; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } greaterThanOrEqual(value, limit, customMessage) { const message = MessageBuilder.expectedToBe("greater than or equal to {2}", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isNumber(v) && v >= limit; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } lessThan(value, limit, customMessage) { const message = MessageBuilder.expectedToBe("less than {2}", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isNumber(v) && v < limit; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } lessThanOrEqual(value, limit, customMessage) { const message = MessageBuilder.expectedToBe("less than or equal to {2}", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isNumber(v) && v <= limit; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } range(value, min, max, customMessage) { const prefix = this.options.notOperator ? "not" : ""; const message = MessageBuilder.expectedToBe(`${prefix} between {2} and {3}`, "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isNumber(v) && v >= min && v <= max; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } boolean(value, customMessage) { const message = MessageBuilder.expectedToBe("a boolean", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isBoolean(v); return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } true(value, customMessage) { const message = MessageBuilder.expectedToBe("true", "{1}"); this.setMessage({ message, customMessage }); const expression = v => v === true; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } false(value, customMessage) { const message = MessageBuilder.expectedToBe("false", "{1}"); this.setMessage({ message, customMessage }); const expression = v => v === false; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } object(value, customMessage) { const message = MessageBuilder.expectedToBe("an object", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isObject(v); return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } function(value, customMessage) { const message = MessageBuilder.expectedToBe("a function", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isFunction(v); return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } array(value, customMessage) { const message = MessageBuilder.expectedToBe("an array", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isArray(v); return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } arrayLength(value, expectedLength, customMessage) { const message = MessageBuilder.expected("array length to be {2}", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isArray(v) && v.length === expectedLength; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } arrayMinLength(value, minLimit, customMessage) { const message = MessageBuilder.expected("array min length to be {2}", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isArray(v) && v.length >= minLimit; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } arrayMaxLength(value, maxLimit, customMessage) { const message = MessageBuilder.expected("array max length to be {2}", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isArray(v) && v.length <= maxLimit; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } arrayLengthBetween(value, min, max, customMessage) { const message = MessageBuilder.expected("array length to be between {2} and {3}", "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isArray(v) && v.length >= min && v.length <= max; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } instanceOf(value, instanceClass, customMessage) { const prefix = this.options.notOperator ? "not" : ""; const message = MessageBuilder.expectedToBe(`${prefix} an instance of {2}`, "{1}"); this.setMessage({ message, customMessage }); const expression = v => v instanceof instanceClass; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } instanceOfAny(value, instanceClasses, customMessage) { const assertInstance = this.newInstance; assertInstance.array(instanceClasses, "Assert.instanceOfAny:instanceClasses should be an array. Got: {1}"); const prefix = this.options.notOperator ? "not" : ""; const message = MessageBuilder.expectedToBe(`${prefix} an instance of {2}`, "{1}"); this.setMessage({ message, customMessage }); const expression = v => instanceClasses.some((instanceClass => v instanceof instanceClass)); return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } match(value, regExp, customMessage) { const prefix = this.options.notOperator ? "not" : ""; const message = MessageBuilder.expectedValue(`${prefix} to match {2}`, "{1}"); this.setMessage({ message, customMessage }); const expression = v => typeof v === "string" && regExp.test(v); return this.processAssertion(value, expression, (() => this.throwError(value, String(regExp)))); } defined(value, customMessage) { const prefix = this.options.notOperator ? "undefined" : "defined"; const message = MessageBuilder.expectedToBe(prefix, "{1}"); this.setMessage({ message, customMessage }); const expression = v => core.TypeHelper.isDefined(v); return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } equal(value, expect, customMessage) { const message = this.options.notOperator ? MessageBuilder.expectedValue("not equal to {2}") : MessageBuilder.expected("{1} to equal {2}"); this.setMessage({ message, customMessage }); const expression = v => v === expect; return this.processAssertion(value, expression, (() => this.throwError(...arguments))); } throws(expression, expectedErrorClass, customMessage) { const operatorIsApplied = this.options.isOperator ?? false; let throwedError; let expressionResult; try { const assertInstance = this.newInstance; assertInstance.function(expression, "Assert.throws:expression must be function. Gor {1}"); expressionResult = expression(); } catch (error) { throwedError = error; } if (throwedError) { let isRightInstance = !expectedErrorClass || throwedError instanceof expectedErrorClass; if (this.options.notOperator) { isRightInstance = !isRightInstance; } if (isRightInstance) { if (operatorIsApplied) { return true; } return; } expressionResult = AssertionHelper.valueToString(throwedError); if (throwedError.message?.trim()) { expressionResult += `: ${throwedError.message}`; } } else { if (this.options.notOperator) { if (operatorIsApplied) { return true; } return; } } if (operatorIsApplied) { return false; } const message = (() => { const expectedErrorStr = expectedErrorClass ? "{2}" : "error"; const prefix = this.options.notOperator ? "not" : ""; return MessageBuilder.expected(`${prefix} to throw ${expectedErrorStr}`, "{1}"); })(); this.setMessage({ message, customMessage }); this.throwError(expressionResult, expectedErrorClass); } processAssertion(value, assertExpression, throwError) { const operatorIsApplied = this.options.isOperator ?? false; try { if (this.options.nullOrOperator && core.TypeHelper.isUndefined(value)) { return operatorIsApplied ? true : void 0; } this.processAllOperator(value, assertExpression, throwError); let condition = assertExpression(value); if (this.options.notOperator) { condition = !condition; } if (!condition) { throwError(); } } catch (error) { if (error instanceof core.ExitFunctionError) { if (operatorIsApplied) { return true; } return; } if (error instanceof WebUtilsAssertionError) { if (operatorIsApplied) { return false; } throwError(); } throw error; } if (operatorIsApplied) { return true; } } processAllOperator(array, assertExpression, throwError) { if (!this.options.allOperator) { return; } const assertInstance = this.newInstance; assertInstance.array(array); array.forEach(((value, index) => { const condition = assertExpression(value); if (!condition) { this.options.message += ` (item #${index})`; throwError(); } })); throw new core.ExitFunctionError; } setMessage(messages) { const {message, customMessage = null} = messages; this.options.message = message; this.options.customMessage = customMessage; } throwError(...params) { let message = this.options.customMessage ?? this.options.message; if (!message) { throw new Error("assert message should be set"); } message = message.replace(/{\d+}/g, (propPos => { const index = Number(propPos.replace(/\D/g, "")) - 1; return params.length > index ? AssertionHelper.valueToString(params[index]) : ""; })); throw new WebUtilsAssertionError(message, !!this.options.customMessage); } } const Assert = new AssertClass; exports.Assert = Assert; exports.AssertionHelper = AssertionHelper; exports.WebUtilsAssertionError = WebUtilsAssertionError; //# sourceMappingURL=index.cjs.map