import { tap } from '@push.rocks/tapbundle'; // Import the built library (dist_ts) so all matcher implementations are available import * as smartexpect from '../dist_ts/index.js'; tap.test('basic type assertions', async () => { // String type checks smartexpect.expect('hello').type.toBeTypeofString(); smartexpect.expect(1).not.type.toBeTypeofString(); // Boolean type checks smartexpect.expect(true).type.toBeTypeofBoolean(); smartexpect.expect(false).type.toBeTypeofBoolean(); smartexpect.expect(1).not.type.toBeTypeofBoolean(); // Number type checks smartexpect.expect(42).type.toBeTypeofNumber(); smartexpect.expect(true).not.type.toBeTypeofNumber(); // Generic type checks with new method smartexpect.expect(() => {}).type.toBeTypeOf('function'); smartexpect.expect(class Test {}).type.toBeTypeOf('function'); smartexpect.expect({}).type.toBeTypeOf('object'); smartexpect.expect(Symbol('test')).type.toBeTypeOf('symbol'); }); tap.test('async tests', async (toolsArg) => { const deferred = toolsArg.defer(); toolsArg.delayFor(1000).then(() => { deferred.resolve('hello'); }); // Using .resolves to test promise resolution with timeout await smartexpect.expect(deferred.promise).resolves.withTimeout(2000).type.toBeTypeofString(); await smartexpect.expect(deferred.promise).resolves.not.type.toBeTypeofBoolean(); // Test async timeout handling const longOperation = toolsArg.defer(); toolsArg.delayFor(3000).then(() => { longOperation.resolve('completed'); }); try { // Assert that resolution must occur within timeout await smartexpect.expect(longOperation.promise).resolves.withTimeout(1000).toBeDefined(); throw new Error('Should have timed out'); } catch (err) { // Successfully caught timeout error from .withTimeout console.log('Successfully caught timeout:', err.message); } }); tap.test('equality and matching assertions', async () => { // Basic equality smartexpect.expect('hithere').object.toEqual('hithere'); smartexpect.expect('hithere').not.object.toEqual('hithere2'); // Object equality const obj1 = { a: 1, b: { c: true } }; const obj2 = { a: 1, b: { c: true } }; const obj3 = { a: 1, b: { c: false } }; smartexpect.expect(obj1).object.toEqual(obj2); smartexpect.expect(obj1).not.object.toEqual(obj3); // RegExp matching smartexpect.expect('hithere').string.toMatch(/hi/); smartexpect.expect('hithere').string.toMatch(/^hithere$/); smartexpect.expect('hithere').not.string.toMatch(/ho/); // String inclusion smartexpect.expect('hithere').string.toInclude('hit'); smartexpect.expect('hithere').not.string.toInclude('missing'); // String start/end smartexpect.expect('hithere').string.toStartWith('hi'); smartexpect.expect('hithere').string.toEndWith('ere'); }); tap.test('object property assertions', async () => { const testObject = { topLevel: 'hello', nested: { prop: 42, deeplyNested: { array: [1, 2, 3], }, }, }; // Basic property checks smartexpect.expect(testObject).object.toHaveProperty('topLevel'); smartexpect.expect(testObject).object.toHaveProperty('topLevel', 'hello'); smartexpect.expect(testObject).not.object.toHaveProperty('missing'); // Drill-down property navigation smartexpect.expect(testObject).property('nested').object.toHaveProperty('prop', 42); smartexpect .expect(testObject) .property('nested') .property('deeplyNested') .property('array') .array.toBeArray(); // Deep property checks smartexpect.expect(testObject).object.toHaveDeepProperty(['nested', 'deeplyNested', 'array']); // Array item navigation smartexpect .expect(testObject) .property('nested') .property('deeplyNested') .property('array') .arrayItem(0) .number.toEqual(1); // numeric equality via number namespace }); tap.test('numeric comparison assertions', async () => { // Greater/less than smartexpect.expect(4).number.toBeGreaterThan(3); smartexpect.expect(4).number.toBeLessThan(5); smartexpect.expect(4).number.toBeGreaterThanOrEqual(4); smartexpect.expect(4).number.toBeLessThanOrEqual(4); // Approximate equality smartexpect.expect(0.1 + 0.2).number.toBeCloseTo(0.3, 10); }); tap.test('array assertions', async () => { const obj1 = { id: 1 }; const obj2 = { id: 2 }; const testArray = [1, 'two', obj1, true]; // Basic array checks smartexpect.expect(testArray).array.toBeArray(); smartexpect.expect(testArray).array.toHaveLength(4); // Content checks smartexpect.expect(testArray).array.toContain('two'); smartexpect.expect(testArray).array.toContain(obj1); smartexpect.expect(testArray).not.array.toContain(obj2); // Array with equal items (not same reference) smartexpect.expect([{ a: 1 }, { b: 2 }]).array.toContainEqual({ a: 1 }); // Multiple values smartexpect.expect(testArray).array.toContainAll([1, 'two']); smartexpect.expect(testArray).array.toExclude('missing'); // Empty array smartexpect.expect([]).array.toBeEmptyArray(); // Length comparisons smartexpect.expect(testArray).array.toHaveLengthGreaterThan(3); smartexpect.expect(testArray).array.toHaveLengthLessThan(5); }); tap.test('boolean assertions', async () => { // True/False smartexpect.expect(true).boolean.toBeTrue(); smartexpect.expect(false).boolean.toBeFalse(); // Truthy/Falsy smartexpect.expect('something').boolean.toBeTruthy(); smartexpect.expect(0).boolean.toBeFalsy(); // Null/Undefined smartexpect.expect(null).object.toBeNull(); smartexpect.expect(undefined).object.toBeUndefined(); smartexpect.expect(null).object.toBeNullOrUndefined(); smartexpect.expect(undefined).object.toBeNullOrUndefined(); }); tap.test('function assertions', async () => { // Function that throws const throwingFn = () => { throw new Error('test error'); }; smartexpect.expect(throwingFn).function.toThrow(); smartexpect.expect(throwingFn).function.toThrow(Error); // Function that doesn't throw const nonThrowingFn = () => 'safe'; smartexpect.expect(nonThrowingFn).not.function.toThrow(); }); tap.test('date assertions', async () => { const now = new Date(); const past = new Date(Date.now() - 10000); const future = new Date(Date.now() + 10000); smartexpect.expect(now).date.toBeDate(); smartexpect.expect(now).date.toBeAfterDate(past); smartexpect.expect(now).date.toBeBeforeDate(future); }); tap.test('custom assertions', async () => { // Custom validation logic smartexpect.expect(42).customAssertion((value) => value % 2 === 0, 'Expected number to be even'); // With fail message smartexpect.expect('test').setFailMessage('Custom fail message for assertion').string.toHaveLength(4); }); tap.test('logging and debugging', async () => { // Using log() for debugging const complexObject = { level1: { level2: { value: 'nested value', }, }, }; // This logs the current value in the chain for debugging smartexpect .expect(complexObject) .property('level1') .property('level2') .log() .property('value') .object.toEqual('nested value'); }); export default tap.start();