import { AsyncGuardOperator } from '../../src'; import { describe, expect, it } from '@jest/globals'; // ═══════════════════════════════════════════════════════════════ // AsyncGuardOperator // ═══════════════════════════════════════════════════════════════ // AsyncGuardOperator — async validator. Returns data if validation // passes (true), or undefined if it fails. The validator can be // synchronous (return boolean) or asynchronous (return Promise). // apply() always returns a Promise. // ═══════════════════════════════════════════════════════════════ // AsyncGuardOperator with sync validator // ═══════════════════════════════════════════════════════════════ describe.each([ ...dataProviderForAsyncGuardOperatorSyncPositiveNumber(), ] as Array<[number, number | undefined]>)( 'AsyncGuardOperator with sync validator positive number test', (input: number, expected: number | undefined) => { it('', async () => { const operator = new AsyncGuardOperator((n) => n > 0); const result = await operator.apply(input); expect(result).toEqual(expected); }); }, ); /** * Data provider for AsyncGuardOperator (sync, positive numbers). */ function dataProviderForAsyncGuardOperatorSyncPositiveNumber(): Array { return [ [1, 1], [100, 100], [0.5, 0.5], [0, undefined], [-1, undefined], [-100, undefined], ]; } describe.each([ ...dataProviderForAsyncGuardOperatorSyncEmail(), ] as Array<[string, string | undefined]>)( 'AsyncGuardOperator with sync validator email test', (input: string, expected: string | undefined) => { it('', async () => { const operator = new AsyncGuardOperator((s) => s.includes('@')); const result = await operator.apply(input); expect(result).toEqual(expected); }); }, ); /** * Data provider for AsyncGuardOperator (sync, email by presence of '@'). */ function dataProviderForAsyncGuardOperatorSyncEmail(): Array { return [ ['test@example.com', 'test@example.com'], ['user@domain.org', 'user@domain.org'], ['invalid', undefined], ['@', '@'], ['test@', 'test@'], ]; } describe.each([ ...dataProviderForAsyncGuardOperatorSyncNonEmptyString(), ] as Array<[string, string | undefined]>)( 'AsyncGuardOperator with sync validator non-empty string test', (input: string, expected: string | undefined) => { it('', async () => { const operator = new AsyncGuardOperator((s) => s.length > 0); const result = await operator.apply(input); expect(result).toEqual(expected); }); }, ); /** * Data provider for AsyncGuardOperator (sync, non-empty string). */ function dataProviderForAsyncGuardOperatorSyncNonEmptyString(): Array { return [ ['test', 'test'], ['a', 'a'], ['', undefined], ]; } // ═══════════════════════════════════════════════════════════════ // AsyncGuardOperator with async validator // ═══════════════════════════════════════════════════════════════ describe.each([ ...dataProviderForAsyncGuardOperatorAsyncPositiveNumber(), ] as Array<[number, number | undefined]>)( 'AsyncGuardOperator with async validator positive number test', (input: number, expected: number | undefined) => { it('', async () => { const operator = new AsyncGuardOperator(async (n) => { return Promise.resolve(n > 0); }); const result = await operator.apply(input); expect(result).toEqual(expected); }); }, ); /** * Data provider for AsyncGuardOperator (async, positive numbers). */ function dataProviderForAsyncGuardOperatorAsyncPositiveNumber(): Array { return [ [1, 1], [100, 100], [0, undefined], [-1, undefined], ]; } describe.each([ ...dataProviderForAsyncGuardOperatorAsyncEvenNumber(), ] as Array<[number, number | undefined]>)( 'AsyncGuardOperator with async validator even number test', (input: number, expected: number | undefined) => { it('', async () => { const operator = new AsyncGuardOperator(async (n) => { return Promise.resolve(n % 2 === 0); }); const result = await operator.apply(input); expect(result).toEqual(expected); }); }, ); /** * Data provider for AsyncGuardOperator (async, even numbers). */ function dataProviderForAsyncGuardOperatorAsyncEvenNumber(): Array { return [ [2, 2], [4, 4], [0, 0], [1, undefined], [3, undefined], ]; } describe.each([ ...dataProviderForAsyncGuardOperatorAsyncStringLength(), ] as Array<[string, string | undefined]>)( 'AsyncGuardOperator with async validator string length test', (input: string, expected: string | undefined) => { it('', async () => { const operator = new AsyncGuardOperator(async (s) => { return Promise.resolve(s.length >= 3); }); const result = await operator.apply(input); expect(result).toEqual(expected); }); }, ); /** * Data provider for AsyncGuardOperator (async, string length >= 3). */ function dataProviderForAsyncGuardOperatorAsyncStringLength(): Array { return [ ['hello', 'hello'], ['abc', 'abc'], ['ab', undefined], ['', undefined], ]; } // ═══════════════════════════════════════════════════════════════ // AsyncGuardOperator edge cases // ═══════════════════════════════════════════════════════════════ describe( 'AsyncGuardOperator handles null value test', () => { it('', async () => { const operator = new AsyncGuardOperator(() => true); const result = await operator.apply(null); expect(result).toEqual(null); }); }, ); describe( 'AsyncGuardOperator handles undefined value test', () => { it('', async () => { const operator = new AsyncGuardOperator(() => false); const result = await operator.apply(undefined); expect(result).toBeUndefined(); }); }, ); describe( 'AsyncGuardOperator returns Promise from apply test', () => { it('', () => { const operator = new AsyncGuardOperator((n) => n > 0); const result = operator.apply(42); expect(result).toBeInstanceOf(Promise); }); }, ); describe( 'AsyncGuardOperator sync validator still returns Promise test', () => { it('', () => { const operator = new AsyncGuardOperator(() => true); const result = operator.apply(42); expect(result).toBeInstanceOf(Promise); }); }, ); describe( 'AsyncGuardOperator async validator with delayed resolution test', () => { it('', async () => { const operator = new AsyncGuardOperator((n) => { return new Promise((resolve) => { setTimeout(() => resolve(n > 10), 10); }); }); const result = await operator.apply(42); expect(result).toEqual(42); const result2 = await operator.apply(5); expect(result2).toBeUndefined(); }); }, ); describe( 'AsyncGuardOperator async validator propagates rejection test', () => { it('', async () => { const operator = new AsyncGuardOperator(async () => { throw new Error('validator error'); }); await expect(operator.apply(42)).rejects.toThrow('validator error'); }); }, ); describe( 'AsyncGuardOperator with object value test', () => { it('', async () => { interface User { id: number; active: boolean } const operator = new AsyncGuardOperator((u) => u.active); const activeUser: User = { id: 1, active: true }; const inactiveUser: User = { id: 2, active: false }; expect(await operator.apply(activeUser)).toEqual(activeUser); expect(await operator.apply(inactiveUser)).toBeUndefined(); }); }, );