UNPKG

type-fns

Version:

A set of types, type checks, and type guards for simpler, safer, and easier to read code.

131 lines 7.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const test_fns_1 = require("test-fns"); const withAssure_1 = require("../wrappers/withAssure"); const assure_1 = require("./assure"); describe('assure', () => { // example type guards for testing const isString = (input) => typeof input === 'string'; const isNumber = (input) => typeof input === 'number'; const isPositive = (input) => input > 0; const isNonEmptyString = (input) => input.length > 0; describe('happy path', () => { it('should return the value when it satisfies a string check', () => { const result = (0, assure_1.assure)('hello', isString); expect(result).toEqual('hello'); }); it('should return the value when it satisfies a number check', () => { const result = (0, assure_1.assure)(42, isNumber); expect(result).toEqual(42); }); it('should return the value when it satisfies a narrowing check on already-typed input', () => { const result = (0, assure_1.assure)(5, isPositive); expect(result).toEqual(5); }); }); describe('rejection boundaries', () => { it('should throw when string check receives a number', () => { const error = (0, test_fns_1.getError)(() => (0, assure_1.assure)(123, isString)); expect(error).toBeInstanceOf(withAssure_1.AssureIsOfTypeRejectionError); expect(error.message).toContain("input does not satisfy type.check 'isString'"); }); it('should throw when number check receives a string', () => { const error = (0, test_fns_1.getError)(() => (0, assure_1.assure)('not a number', isNumber)); expect(error).toBeInstanceOf(withAssure_1.AssureIsOfTypeRejectionError); expect(error.message).toContain("input does not satisfy type.check 'isNumber'"); }); it('should throw when positive check receives zero', () => { const error = (0, test_fns_1.getError)(() => (0, assure_1.assure)(0, isPositive)); expect(error).toBeInstanceOf(withAssure_1.AssureIsOfTypeRejectionError); expect(error.message).toContain("input does not satisfy type.check 'isPositive'"); }); it('should throw when positive check receives a negative number', () => { const error = (0, test_fns_1.getError)(() => (0, assure_1.assure)(-1, isPositive)); expect(error).toBeInstanceOf(withAssure_1.AssureIsOfTypeRejectionError); expect(error.message).toContain("input does not satisfy type.check 'isPositive'"); }); it('should throw when non-empty string check receives an empty string', () => { const error = (0, test_fns_1.getError)(() => (0, assure_1.assure)('', isNonEmptyString)); expect(error).toBeInstanceOf(withAssure_1.AssureIsOfTypeRejectionError); expect(error.message).toContain("input does not satisfy type.check 'isNonEmptyString'"); }); }); describe('edge cases', () => { it('should handle null input', () => { const error = (0, test_fns_1.getError)(() => (0, assure_1.assure)(null, isString)); expect(error).toBeInstanceOf(withAssure_1.AssureIsOfTypeRejectionError); expect(error.message).toContain("input does not satisfy type.check 'isString'"); }); it('should handle undefined input and include it in error context', () => { const error = (0, test_fns_1.getError)(() => (0, assure_1.assure)(undefined, isString)); expect(error).toBeInstanceOf(withAssure_1.AssureIsOfTypeRejectionError); expect(error.message).toContain("input does not satisfy type.check 'isString'"); }); it('should handle falsy values that pass the check', () => { const result = (0, assure_1.assure)(0, isNumber); expect(result).toEqual(0); }); it('should handle empty string that passes a string check', () => { const result = (0, assure_1.assure)('', isString); expect(result).toEqual(''); }); }); describe('custom name option', () => { it('should use custom name in error message when provided', () => { const error = (0, test_fns_1.getError)(() => (0, assure_1.assure)('test', isNumber, { name: 'customNumberCheck' })); expect(error.message).toContain("input does not satisfy type.check 'customNumberCheck'"); }); it('should use function name when custom name is not provided', () => { const error = (0, test_fns_1.getError)(() => (0, assure_1.assure)('test', isNumber)); expect(error.message).toContain("input does not satisfy type.check 'isNumber'"); }); it('should handle anonymous functions gracefully', () => { const error = (0, test_fns_1.getError)(() => (0, assure_1.assure)('test', (input) => typeof input === 'number')); expect(error).toBeInstanceOf(withAssure_1.AssureIsOfTypeRejectionError); }); }); describe('type narrowing', () => { it('should narrow union types', () => { const input = 'hello'; const result = (0, assure_1.assure)(input, isString); // narrows to string // @ts-expect-error - result is string, not number const badResult = (0, assure_1.assure)(input, isString); expect(result).toBeDefined(); expect(badResult).toBeDefined(); }); it('should narrow unknown to specific type', () => { const input = 42; const result = (0, assure_1.assure)(input, isNumber); // narrows to number // @ts-expect-error - result is number, not string const badResult = (0, assure_1.assure)(input, isNumber); expect(result).toBeDefined(); expect(badResult).toBeDefined(); }); it('should work with branded types', () => { const isUserId = (input) => input.startsWith('user_'); const result = (0, assure_1.assure)('user_123', isUserId); // narrows to UserId // @ts-expect-error - result is UserId, not number const badResult = (0, assure_1.assure)('user_123', isUserId); expect(result).toBeDefined(); expect(badResult).toBeDefined(); const error = (0, test_fns_1.getError)(() => (0, assure_1.assure)('invalid', isUserId)); expect(error).toBeInstanceOf(withAssure_1.AssureIsOfTypeRejectionError); }); it('should work with enum checks', () => { let Status; (function (Status) { Status["ACTIVE"] = "ACTIVE"; Status["INACTIVE"] = "INACTIVE"; })(Status || (Status = {})); const isStatus = (input) => Object.values(Status).includes(input); const result = (0, assure_1.assure)('ACTIVE', isStatus); // narrows to Status // @ts-expect-error - result is Status, not number const badResult = (0, assure_1.assure)('ACTIVE', isStatus); expect(result).toBeDefined(); expect(badResult).toBeDefined(); const error = (0, test_fns_1.getError)(() => (0, assure_1.assure)('INVALID', isStatus)); expect(error).toBeInstanceOf(withAssure_1.AssureIsOfTypeRejectionError); }); }); }); //# sourceMappingURL=assure.test.js.map