import * as plugins from './smartexpect.plugins'; export type TExecutionType = 'sync' | 'async'; export class Assertion { executionMode: TExecutionType; baseReference: any; private notSetting = false; private timeoutSetting = 0; constructor(baseReferenceArg: any, executionModeArg: TExecutionType) { this.baseReference = baseReferenceArg; this.executionMode = executionModeArg; } public get not() { this.notSetting = true; return this; } public timeout(millisArg: number) { this.timeoutSetting = millisArg; return this; } private runCheck(checkFunction: () => any) { const runDirectOrNegated = (checkFunction: () => any) => { if (!this.notSetting) { return checkFunction(); } else { let isOk = false; try { runDirectOrNegated(checkFunction()) } catch (e) { isOk = true; } if (!isOk) { throw new Error('Negated assertion is not ok!'); } } } if (this.executionMode === 'async') { const done = plugins.smartpromise.defer(); if (!(this.baseReference instanceof Promise)) { done.reject(new Error(`${this.baseReference} is not of type promise.`)); } else { if (this.timeoutSetting) { plugins.smartdelay.delayFor(this.timeoutSetting).then(() => { if (done.status === 'pending') { done.reject(new Error(`${this.baseReference} timed out at ${this.timeoutSetting}!`)) } }); } this.baseReference.then(promiseResultArg => { this.baseReference = promiseResultArg; done.resolve(runDirectOrNegated(checkFunction)); }) } return done.promise; } else { return runDirectOrNegated(checkFunction); } } public toBeTypeofString() { return this.runCheck(() => { if (typeof this.baseReference !== 'string') { throw new Error( `Assertion failed: ${this.baseReference} is not of type string, but typeof ${typeof this.baseReference}` ); } }); } public toBeTypeofNumber() { return this.runCheck(() => { if (typeof this.baseReference !== 'number') { throw new Error( `Assertion failed: ${this.baseReference} is not of type string, but typeof ${typeof this.baseReference}` ); } }); } public toBeTypeofBoolean() { return this.runCheck(() => { if (typeof this.baseReference !== 'boolean') { throw new Error( `Assertion failed: ${this.baseReference} is not of type string, but typeof ${typeof this.baseReference}` ); } }); } public toEqual(comparisonObject: any) { return this.runCheck(() => { const result = plugins.fastDeepEqual(this.baseReference, comparisonObject); if (!result) { throw new Error(`${this.baseReference} does not equal ${comparisonObject}`); } }); } public toBeTrue() { return this.runCheck(() => { const result = typeof this.baseReference === 'boolean' && this.baseReference === true; if (!result) { throw new Error(`${this.baseReference} is not true or not of type boolean`); } }); } public toBeFalse() { return this.runCheck(() => { const result = typeof this.baseReference === 'boolean' && this.baseReference === false; if (!result) { throw new Error(`${this.baseReference} is not false or not of type boolean`); } }); } public toBeInstanceOf(classArg: any) { return this.runCheck(() => { const result = this.baseReference instanceof classArg; if (!result) { throw new Error(`${this.baseReference} is not an instance of ${classArg}`); } }); } }