UNPKG

n4s

Version:

typed schema validation version of enforce

109 lines (91 loc) 4.01 kB
import { describe, it, expect, vi } from 'vitest'; import { RuleRunReturn } from '../RuleRunReturn'; describe('RuleRunReturn', () => { describe('create with boolean', () => { it('returns pass/type/message when message is string', () => { const res = RuleRunReturn.create(true, 'TYPE', 'ok'); expect(res.pass).toBe(true); expect(res.type).toBe('TYPE'); expect(res.message).toBe('ok'); }); it('invokes message function with type and sets pass=false', () => { const msgFn = vi.fn((t: number) => `msg:${t}`); const res = RuleRunReturn.create<number>(false, 123, msgFn); expect(res.pass).toBe(false); expect(res.type).toBe(123); expect(res.message).toBe('msg:123'); expect(msgFn).toHaveBeenCalledTimes(1); expect(msgFn).toHaveBeenCalledWith(123); }); it('keeps message undefined when not provided', () => { const res = RuleRunReturn.create(true, 'TYP'); expect(res.pass).toBe(true); expect(res.type).toBe('TYP'); expect(res.message).toBeUndefined(); }); }); describe('create with RuleRunReturn', () => { it('clones values and invokes message function with the original type', () => { const base = RuleRunReturn.Failing('T', (t: string) => `fail:${t}`); const cloned = RuleRunReturn.create(base, 'T'); expect(cloned.pass).toBe(false); expect(cloned.type).toBe('T'); expect(cloned.message).toBe('fail:T'); }); it('uses pass from inner; explicit type/message take precedence', () => { const inner = RuleRunReturn.Failing('INNER', 'inner'); const res = RuleRunReturn.create(inner, 'OUTER', 'outer'); expect(res.pass).toBe(false); expect(res.type).toBe('OUTER'); // explicit message is preferred over inner expect(res.message).toBe('outer'); }); it('falls back to provided type when inner type is undefined', () => { const inner = new RuleRunReturn<undefined>(false, undefined, 'm'); const res = RuleRunReturn.create(inner, 'FALLBACK', 'outer'); expect(res.pass).toBe(false); expect(res.type).toBe('FALLBACK'); // explicit message is used when provided expect(res.message).toBe('outer'); }); it('falls back to provided type when inner passing type is undefined', () => { const inner = new RuleRunReturn<undefined>(true, undefined); const res = RuleRunReturn.create(inner, 'FALLBACK'); expect(res.pass).toBe(true); expect(res.type).toBe('FALLBACK'); }); it('invokes provided message function with provided type argument', () => { const inner = RuleRunReturn.Passing('INNER'); const msgFn = vi.fn((t: string) => `outer:${t}`); const res = RuleRunReturn.create(inner, 'OUTER', msgFn); // final type preserves inner transformed type on pass expect(res.type).toBe('INNER'); // message function receives the second arg to create (OUTER) expect(res.message).toBe('outer:OUTER'); expect(msgFn).toHaveBeenCalledTimes(1); expect(msgFn).toHaveBeenCalledWith('OUTER'); }); }); describe('Passing/Failing helpers', () => { it('Passing returns pass=true with string or function message', () => { const r1 = RuleRunReturn.Passing('X', 'ok'); expect(r1.pass).toBe(true); expect(r1.type).toBe('X'); expect(r1.message).toBe('ok'); const r2 = RuleRunReturn.Passing('Y', (t: string) => `yay:${t}`); expect(r2.pass).toBe(true); expect(r2.type).toBe('Y'); expect(r2.message).toBe('yay:Y'); }); it('Failing returns pass=false with string or function message', () => { const r1 = RuleRunReturn.Failing('X', 'nope'); expect(r1.pass).toBe(false); expect(r1.type).toBe('X'); expect(r1.message).toBe('nope'); const r2 = RuleRunReturn.Failing('Y', (t: string) => `nay:${t}`); expect(r2.pass).toBe(false); expect(r2.type).toBe('Y'); expect(r2.message).toBe('nay:Y'); }); }); });