alsatian-fluent-assertions
Version:
Fluent assertions extension to Alsatian xUnit framework.
266 lines • 12.5 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const deepEqual = require("deep-equal");
const alsatian_1 = require("alsatian");
const operators_1 = require("./operators");
class SimpleMatcher extends operators_1.Operators {
constructor(actualValue, nextValue, initial, prevCore, ctxt) {
super(actualValue, nextValue, initial, prevCore, ctxt);
}
contains(expected, location = "anywhere" /* anywhere */) {
this.setCurrentNode(this.contains.name, location);
if (typeof expected !== "string") {
throw new TypeError(`Parameter 'expected' should be a string, but was a ${typeof expected}.`);
}
if (typeof this.actualValue !== "string") {
throw new TypeError(`Actual value should be a string, but was a ${typeof this.actualValue}.`);
}
if (["anywhere" /* anywhere */, "end" /* end */, "start" /* start */].indexOf(location) < 0) {
throw new TypeError(`Location parameter should be one of: start, end, anywhere. Was: ${location}.`);
}
const ops = {
"start": (pos) => pos !== 0,
"end": (pos) => pos !== this.actualValue.length - expected.length,
"anywhere": (pos) => pos < 0
};
const pos = this.actualValue.indexOf(expected);
if (this.maybeInvert(ops[location](pos))) {
this.specError(`should${this.negation}contain string (position: ${location})`, expected, this.actualValue);
}
return this.generateFluentState(this.actualValue, null, false);
}
strictlyEquals(expected) {
this.setCurrentNode(this.strictlyEquals.name, typeof expected);
if (this.maybeInvert(this.actualValue !== expected)) {
this.specError("should strictly (===) equal", expected, this.actualValue);
}
return this.generateFluentState(this.actualValue, null, false);
}
looselyEquals(expected) {
this.setCurrentNode(this.looselyEquals.name, typeof expected);
/*tslint:disable:triple-equals*/
if (this.maybeInvert(this.actualValue != expected)) {
/*tslint:enable:triple-equals*/
this.specError("should loosely (==) equal", expected, this.actualValue);
}
return this.generateFluentState(this.actualValue, null, false);
}
deeplyEquals(expected, eqType = "strictly" /* strictly */) {
this.setCurrentNode(this.deeplyEquals.name, typeof expected + ", " + eqType);
const equal = this._deeplyEquals(this.actualValue, expected, eqType);
if (this.maybeInvert(!equal)) {
this.specError(`should${this.negation}deeply equal (${eqType})`, expected, this.actualValue);
}
return this.generateFluentState(this.actualValue, null, false);
}
deepStrictlyEquals(expected) {
this.setCurrentNode(this.deepStrictlyEquals.name, typeof expected);
return this.deeplyEquals(expected, "strictly" /* strictly */);
}
deepLooselyEquals(expected) {
this.setCurrentNode(this.deepLooselyEquals.name, typeof expected);
return this.deeplyEquals(expected, "loosely" /* loosely */);
}
isDefined() {
this.setCurrentNode(this.isDefined.name, null);
if (this.maybeInvert(typeof this.actualValue === "undefined")) {
this.specError(`should${this.negation}be defined`, `${this.negation}defined`, `${this.actualValue}`);
}
return this.generateFluentState(this.actualValue, null, false);
}
isNull() {
this.setCurrentNode(this.isNull.name, null);
if (this.maybeInvert(this.actualValue !== null)) {
this.specError(`should${this.negation}be null`, `${this.negation}null`, `${this.actualValue}`);
}
return this.generateFluentState(this.actualValue, null, false);
}
matches(matcher) {
this.setCurrentNode(this.matches.name, `${matcher}`);
this._match(matcher);
return this.generateFluentState(this.actualValue, null, false);
}
hasMatch(matcher) {
this.setCurrentNode(this.hasMatch.name, `${matcher}`);
this._match(matcher);
const matches = this.actualValue.match(matcher);
return this.generateFluentState(this.actualValue, matches, false, true);
}
throws(errorType) {
this.setCurrentNode(this.throws.name, errorType ? typeof errorType : null);
let threw = null;
this._assertActualFunction();
try {
this.actualValue();
}
catch (err) {
threw = err;
}
this._assertThrew(threw, errorType);
return this.generateFluentState(this.actualValue, threw, false, true);
}
throwsAsync(errorType) {
return __awaiter(this, void 0, void 0, function* () {
this.setCurrentNode(this.throwsAsync.name, errorType ? typeof errorType : null);
this._assertActualFunction();
let threw = null;
try {
// make sure its a promise and wait.
yield Promise.resolve(this.actualValue());
}
catch (err) {
threw = err;
}
this._assertThrew(threw, errorType);
return this.generateFluentState(this.actualValue, threw, false, true);
});
}
satisfies(predicate) {
this.setCurrentNode(this.satisfies.name, null);
if (!(predicate instanceof Function)) {
this.specError("predicate in satisfies(predicate) should be a function", "[a function]", this.id(predicate));
}
if (this.maybeInvert(!predicate(this.actualValue))) {
this.specError(`should${this.negation}match lambda`, this.getFnString(predicate), this.actualValue);
}
return this.generateFluentState(this.actualValue, null, false);
}
is(expectedType) {
const eActualName = (expectedType || {}).name;
this.setCurrentNode(this.is.name, eActualName);
if (typeof expectedType !== "function") {
throw new TypeError(`Expected type 'function' for instance check, but got type '${typeof expectedType}'.`);
}
if (this.maybeInvert(!(this.actualValue instanceof expectedType))) {
const ename = eActualName || `(Unnamed type; JS type: ${typeof expectedType})`;
const aname = (this.actualValue || {}).name ||
`(Unnamed type; JS type: ${typeof this.actualValue})`;
this.specError(`should${this.negation}be of type`, ename, aname);
}
return this.generateFluentState(this.actualValue, null, false);
}
hasProperty(expected) {
this.setCurrentNode(this.hasProperty.name, null);
let selected;
let expDescrip;
if (this.nullOrUndefined(this.actualValue)) {
if (!this.invertedContext) {
this.specError(`contextual value should be defined`, "[an object]", "undefined");
}
return; // .not.hasProperty always passes when target not defined.
}
if (typeof expected === "string") {
selected = this.actualValue[expected];
expDescrip = expected;
}
else if (expected instanceof Function) {
selected = expected(this.actualValue);
expDescrip = this.getFnString(expected);
}
else {
this.specError("Provided selector was not a function or key type.", undefined, undefined);
}
if (this.maybeInvert(typeof selected === "undefined")) {
this.specError(`property should${this.negation}be defined`, expDescrip, this.actualValue);
}
return this.generateFluentState(this.actualValue, selected, false, true);
}
hasSingle() {
this.setCurrentNode(this.hasSingle.name, null);
if (!(this.actualValue instanceof Array ||
typeof this.actualValue === "string")) {
throw new TypeError("Expected type is not an array or string.");
}
if (this.maybeInvert(this.actualValue.length !== 1)) {
this.specError(`should${this.negation}have single element or character`, "single element", this.actualValue);
}
return this.generateFluentState(this.actualValue, this.actualValue[0], false, true);
}
isEmpty() {
this.setCurrentNode(this.isEmpty.name, null);
if (!(typeof this.actualValue === "object" ||
typeof this.actualValue === "string")) {
throw new TypeError("Expected type is not an array, string, or object.");
}
const isObject = !(typeof this.actualValue === "string" || this.actualValue instanceof Array);
let length;
if (isObject) {
length = Object.keys(this.actualValue).length;
}
else {
length = this.actualValue.length;
}
if (this.maybeInvert(length !== 0)) {
this.specError(`should${this.negation}be empty`, "[an empty array, string, or object]", this.actualValue);
}
return this.generateFluentState(this.actualValue, null, false);
}
isTruthy() {
return this._assertBooly(!this.actualValue, this.isTruthy.name, "truthy");
}
isFalsy() {
return this._assertBooly(!!this.actualValue, this.isFalsy.name, "falsy");
}
converted(lambda) {
this.setCurrentNode(this.converted.name);
if (typeof lambda !== "function") {
throw new TypeError(`Given value is not a function, but a ${typeof lambda}.`);
}
const r = lambda(this.actualValue);
return this.generateFluentState(r, null, false);
}
_assertActualFunction() {
if (!(this.actualValue instanceof Function)) {
this.specError(`should be a function`, "[a function]", this.id(this.actualValue));
}
}
_assertBooly(val, name, expVal) {
this.setCurrentNode(name, `${!!this.actualValue}`);
if (this.maybeInvert(val)) {
this.specError(`should${this.negation}be ${expVal}`, `[any ${expVal} value]`, this.actualValue);
}
return this.generateFluentState(this.actualValue, null, false);
}
_assertThrew(threw, errorType) {
if (this.maybeInvert(!threw)) {
const expMsg = this.invertedContext
? "[no error thrown]"
: (errorType || Error).name;
this.specError(`should${this.negation}throw`, expMsg, this.formatShortError(threw));
}
else if (errorType &&
this.maybeInvert(!(threw instanceof errorType))) {
const tname = errorType.name;
const taname = threw.name || "[Unnamed error]";
this.specError(`should${this.negation}throw type ${tname} but threw ${taname}`, tname, this.formatShortError(threw));
}
}
// tslint:disable-next-line
/** Convert to lib's deep equals. */
_deeplyEquals(actual, expected, eqType) {
return deepEqual(expected, actual, {
strict: eqType === "strictly" /* strictly */
});
}
_match(matcher) {
if (typeof this.actualValue !== "string") {
throw new alsatian_1.MatchError("actual value type was not a string");
}
if (!(matcher instanceof RegExp)) {
this.specError(`matcher should be a regular expression`, "[a RegExp]", this.id(matcher));
}
if (this.maybeInvert(!matcher.test(this.actualValue))) {
this.specError(`should${this.negation}match`, matcher.toString(), this.actualValue);
}
}
}
exports.SimpleMatcher = SimpleMatcher;
//# sourceMappingURL=simple-matcher.js.map