diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 77988cb..99b9a3f 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -2,7 +2,7 @@ * autocreated commitinfo by @pushrocks/commitinfo */ export const commitinfo = { - name: '@pushrocks/smartexpect', - version: '1.0.15', - description: 'manage expectations in code', -}; + name: '@push.rocks/smartexpect', + version: '1.0.16', + description: 'manage expectations in code' +} diff --git a/ts/smartexpect.classes.assertion.ts b/ts/smartexpect.classes.assertion.ts index 089353f..370ce55 100644 --- a/ts/smartexpect.classes.assertion.ts +++ b/ts/smartexpect.classes.assertion.ts @@ -277,6 +277,207 @@ export class Assertion { }); } + // ... previous code ... + + public toBeOneOf(values: any[]) { + return this.runCheck(() => { + const result = values.includes(this.getObjectToTestReference()); + if (!result) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} is not one of ${values}` + ); + } + }); + } + + public toHaveLength(length: number) { + return this.runCheck(() => { + const obj = this.getObjectToTestReference(); + if (typeof obj.length !== 'number' || obj.length !== length) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} does not have a length of ${length}` + ); + } + }); + } + + public toBeCloseTo(value: number, precision = 2) { + return this.runCheck(() => { + const difference = Math.abs(this.getObjectToTestReference() - value); + if (difference > Math.pow(10, -precision) / 2) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} is not close to ${value} up to ${precision} decimal places` + ); + } + }); + } + + public toThrow(expectedError?: any) { + return this.runCheck(() => { + let thrown = false; + try { + this.getObjectToTestReference()(); + } catch (e) { + thrown = true; + if (expectedError && !(e instanceof expectedError)) { + throw new Error( + `Expected function to throw ${expectedError.name}, but it threw ${e.name}` + ); + } + } + if (!thrown) { + throw new Error(`Expected function to throw, but it didn't.`); + } + }); + } + + public toBeTruthy() { + return this.runCheck(() => { + if (!this.getObjectToTestReference()) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} is not truthy` + ); + } + }); + } + + public toBeFalsy() { + return this.runCheck(() => { + if (this.getObjectToTestReference()) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} is not falsy` + ); + } + }); + } + + public toBeGreaterThanOrEqual(numberArg: number) { + return this.runCheck(() => { + if (this.getObjectToTestReference() <= numberArg) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} is not greater than or equal to ${numberArg}` + ); + } + }); + } + + public toBeLessThanOrEqual(numberArg: number) { + return this.runCheck(() => { + if (this.getObjectToTestReference() >= numberArg) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} is not less than or equal to ${numberArg}` + ); + } + }); + } + + public toMatchObject(objectArg: object) { + return this.runCheck(() => { + function deepEqual(obj1: any, obj2: any): boolean { + // If both are of primitive types and are equal + if (obj1 === obj2) { + return true; + } + + // If either of them is null or not an object + if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) { + return false; + } + + const keys1 = Object.keys(obj1); + const keys2 = Object.keys(obj2); + + // If their properties' count doesn't match + if (keys1.length !== keys2.length) { + return false; + } + + // Checking if every property in obj1 has a counterpart in obj2 + for (const key of keys1) { + if (!keys2.includes(key)) { + return false; + } + if (!deepEqual(obj1[key], obj2[key])) { + return false; + } + } + + return true; + } + const partialMatch = deepEqual( + this.getObjectToTestReference(), + objectArg + ); // Note: Implement a deep comparison function or use one from a library + if (!partialMatch) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} does not match the object ${objectArg}` + ); + } + }); + } + + public toContainEqual(value: any) { + return this.runCheck(() => { + const arr = this.getObjectToTestReference(); + const found = arr.some((item: any) => plugins.fastDeepEqual(item, value)); // Assuming fastDeepEqual checks deep equality + if (!found) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} does not contain the value ${value}` + ); + } + }); + } + + public toBeArray() { + return this.runCheck(() => { + if (!Array.isArray(this.getObjectToTestReference())) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} is not an array` + ); + } + }); + } + + public toInclude(substring: string) { + return this.runCheck(() => { + if (!this.getObjectToTestReference().includes(substring)) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} does not include the substring ${substring}` + ); + } + }); + } + + public toBeDate() { + return this.runCheck(() => { + if (!(this.getObjectToTestReference() instanceof Date)) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} is not a date` + ); + } + }); + } + + public toBeBeforeDate(date: Date) { + return this.runCheck(() => { + if (!(this.getObjectToTestReference() < date)) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} is not before ${date}` + ); + } + }); + } + + public toBeAfterDate(date: Date) { + return this.runCheck(() => { + if (!(this.getObjectToTestReference() > date)) { + throw new Error( + `${this.baseReference} with drill down ${this.propertyDrillDown} is not after ${date}` + ); + } + }); + } + public property(propertyNameArg: string) { this.propertyDrillDown.push(propertyNameArg); return this;