UNPKG

@lucaspaganini/value-objects

Version:

TypeScript first validation and class creation library

110 lines (92 loc) 3.45 kB
import { expectTypeOf } from 'expect-type' import { Noneable, RawTypeError, VOOptional } from '../..' describe('VOOptional', () => { class Base { constructor(raw: number) {} valueOf(): 'base test' { return 'base test' } } it('Should return a class that can be extended', () => { class Test extends VOOptional(Base) { test() { return 'test' } } const instance = new Test(123) expect(instance.test()).toBe('test') }) it('Should throw on base class creation if one of the values in the nones is not Noneable', () => { const tests = nonNoneableValues.map(nonNoneable => [...noneableValues, nonNoneable]) for (const test of tests) { const fn = () => VOOptional(Base, <Array<any>>test) expect(fn).toThrowError('Wrong raw value type') } }) it('Should adapt the raw value types it expects according to the nones values', () => { const tests = [ { type: 'undefined', nones: [undefined] }, { type: 'null', nones: [null] }, { type: 'undefined | null', nones: [undefined, null] }, { type: '', nones: [] }, ] class Base { constructor(raw: number) { throw new RawTypeError('number', typeof raw) } } for (const test of tests) { const Test = VOOptional(Base, test.nones) const raw = new Date() const fn = () => new Test(raw as any) expect(fn).toThrowError('Wrong raw value type') expect(fn).toThrowMatching(err => { const errorType = err.expected.split(' | ') const testType = test.type .split(' | ') .concat('number') .filter(type => type !== '') return testType.every(type => errorType.includes(type)) }) } }) it("Should return some if it' a some raw value", () => { class Test extends VOOptional(Base) {} const instance = new Test(123) expect(instance.isSome()).toBe(true) expect(instance.isNone()).toBe(false) expect(instance.value instanceof Base).toBe(true) expect(instance.value!.valueOf()).toBe('base test') }) it("Should return none if it's a none raw value", () => { const tests = [ { nones: [null], raw: null }, { nones: [undefined], raw: undefined }, { nones: [undefined, null], raw: undefined }, { nones: [undefined, null], raw: null }, ] for (const test of tests) { class Test extends VOOptional(Base, test.nones) {} const instance = new Test(test.raw) expect(instance.isNone()).toBe(true) expect(instance.isSome()).toBe(false) expect(instance.value instanceof Base).toBe(false) expect(instance.value).toBe(test.raw) } }) it('Should have the correct types', () => { class Test { constructor(raw: number) {} valueOf(): string { return '' } } expectTypeOf(new (VOOptional(Test, [null, undefined]))(434).valueOf()).toEqualTypeOf<string | null | undefined>() expectTypeOf(new (VOOptional(Test, [null]))(123).valueOf()).toEqualTypeOf<string | null>() expectTypeOf(new (VOOptional(Test, [undefined]))(434).valueOf()).toEqualTypeOf<string | undefined>() expectTypeOf(new (VOOptional(Test, []))(434).valueOf()).toEqualTypeOf<string>() expectTypeOf(new (VOOptional(Test))(434).valueOf()).toEqualTypeOf<string | undefined>() }) }) const noneableValues: Array<Noneable> = [null, undefined] const nonNoneableValues = [0, false, []]