import { expectType, Result } from 'ts-data-forge'; import { type NonEmptyArray } from 'ts-type-forge'; import { number } from '../primitives/index.mjs'; import { type TypeOf } from '../type.mjs'; import { type ValidationError, validationErrorsToMessages, } from '../utils/index.mjs'; import { nonEmptyArray } from './non-empty-array.mjs'; describe(nonEmptyArray, () => { describe('arg patterns', () => { test('without explicit default value', () => { assert.deepStrictEqual( nonEmptyArray(number()).defaultValue, [0], ); }); test('with explicit default value, case 1', () => { assert.deepStrictEqual( nonEmptyArray(number(1)).defaultValue, [1], ); }); test('with explicit default value, case 2', () => { assert.deepStrictEqual( nonEmptyArray(number(), { typeName: 'xs', defaultValue: [2], }).defaultValue, [2], ); }); }); const xs = nonEmptyArray(number(), { defaultValue: [1], typeName: 'xs', }); type Xs = TypeOf; expectType>('='); expectType('='); describe('is', () => { test('truthy case', () => { const ys: unknown = [1, 2, 3] as const; if (xs.is(ys)) { expectType('='); } else { expectType('='); } assert.isTrue(xs.is(ys)); }); test('falsy case 1', () => { const ys: unknown = [] as const; if (xs.is(ys)) { expectType('='); } else { expectType('='); } assert.isFalse(xs.is(ys)); }); test('falsy case 2', () => { const ys: unknown = ['1', '', 3] as const; if (xs.is(ys)) { expectType('='); } else { expectType('='); } assert.isFalse(xs.is(ys)); }); }); describe('validate', () => { test('truthy case', () => { const ys: unknown = [1, 2, 3] as const; const result = xs.validate(ys); expectType>('='); assert.isTrue(Result.isOk(result)); const resultValue = Result.unwrapThrow(result); assert.deepStrictEqual(resultValue, [1, 2, 3]); }); test('validate returns input as-is for OK cases', () => { const input = [1, 2, 3] as const; const result = xs.validate(input); assert.isTrue(Result.isOk(result)); const resultValue1 = Result.unwrapThrow(result); expect(resultValue1).toBe(input); // ✅ same reference }); test('falsy case 1', () => { const ys: unknown = [] as const; const result = xs.validate(ys); assert.isTrue(Result.isErr(result)); const resultError = Result.unwrapErrThrow(result); assert.deepStrictEqual(resultError, [ { path: [], actualValue: ys, expectedType: 'xs', typeName: 'xs', details: { kind: 'non-empty-array', }, }, ]); assert.deepStrictEqual(validationErrorsToMessages(resultError), [ 'Error: expected non-empty array but empty array was passed.', ]); }); test('falsy case 2', () => { const ys: unknown = ['1', '', 3] as const; const result = xs.validate(ys); assert.isTrue(Result.isErr(result)); const resultError1 = Result.unwrapErrThrow(result); assert.deepStrictEqual(resultError1, [ { path: ['0'], actualValue: '1', expectedType: 'number', typeName: 'number', details: undefined, }, { path: ['1'], actualValue: '', expectedType: 'number', typeName: 'number', details: undefined, }, ]); assert.deepStrictEqual(validationErrorsToMessages(resultError1), [ 'Error at 0: expected type but type value "1" was passed.', 'Error at 1: expected type but type value "" was passed.', ]); }); }); describe('fill', () => { test('noop', () => { const ys: unknown = [1, 2, 3] as const; assert.deepStrictEqual(xs.fill(ys), [1, 2, 3]); }); test('fill with the default value', () => { const ys: unknown = ['1', '', 3] as const; assert.deepStrictEqual(xs.fill(ys), [0, 0, 3]); }); test('fill empty array', () => { const ys: unknown = [] as const; assert.deepStrictEqual(xs.fill(ys), [1]); }); }); });