UNPKG

ts-data-forge

Version:

[![npm version](https://img.shields.io/npm/v/ts-data-forge.svg)](https://www.npmjs.com/package/ts-data-forge) [![npm downloads](https://img.shields.io/npm/dm/ts-data-forge.svg)](https://www.npmjs.com/package/ts-data-forge) [![License](https://img.shields.

541 lines (446 loc) 15.9 kB
import { expectType } from '../expect-type.mjs'; import { range } from '../iterator/index.mjs'; import { asNonZeroSafeInt, asUint32 } from '../number/index.mjs'; import { Arr } from './array-utils.mjs'; describe('Arr creations', () => { describe('zeros', () => { test('fixed length', () => { const result = Arr.zeros(3); expectType<typeof result, readonly [0, 0, 0]>('='); expect(result).toStrictEqual([0, 0, 0]); }); test('fixed length (empty)', () => { const result = Arr.zeros(0); expectType<typeof result, readonly []>('='); expect(result).toStrictEqual([]); }); test('unknown length', () => { const n: number = 3; const result = Arr.zeros(asUint32(n)); expectType<typeof result, readonly 0[]>('='); expect(result).toStrictEqual([0, 0, 0]); }); test('should create array with zero length', () => { const result = Arr.zeros(0); expect(result).toStrictEqual([]); expect(result).toHaveLength(0); }); test('should create large arrays', () => { const result = Arr.zeros(asUint32(1000)); expect(result).toHaveLength(1000); // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition expect(result.every((x) => x === 0)).toBe(true); }); test('should work with curried version', () => { const createTenZeros = Arr.zeros(10); expect(createTenZeros).toStrictEqual([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); }); }); describe('seq', () => { test('fixed length', () => { const result = Arr.seq(5); expectType<typeof result, readonly [0, 1, 2, 3, 4]>('='); expect(result).toStrictEqual([0, 1, 2, 3, 4]); }); test('fixed length (empty)', () => { const result = Arr.seq(0); expectType<typeof result, readonly []>('='); expect(result).toStrictEqual([]); }); test('unknown length', () => { const n: number = 3; const result = Arr.seq(asUint32(n)); expectType<typeof result, readonly SizeType.Arr[]>('='); expect(result).toStrictEqual([0, 1, 2]); }); test('should create sequence with zero length', () => { const result = Arr.seq(0); expect(result).toStrictEqual([]); }); test('should create sequence with large length', () => { const result = Arr.seq(asUint32(100)); expect(result).toHaveLength(100); expect(result[0]).toBe(0); expect(result[99]).toBe(99); }); test('should work with curried version', () => { const createFiveSeq = Arr.seq(5); expect(createFiveSeq).toStrictEqual([0, 1, 2, 3, 4]); }); }); describe('create', () => { test('fixed length with primitive value', () => { const result = Arr.create(3, 'a'); expectType<typeof result, readonly ['a', 'a', 'a']>('='); expect(result).toStrictEqual(['a', 'a', 'a']); }); test('fixed length with null', () => { const result = Arr.create(2, null); expectType<typeof result, readonly [null, null]>('='); expect(result).toStrictEqual([null, null]); }); test('fixed length with object (shallow copy)', () => { const obj = { id: 1 }; const result = Arr.create(2, obj); expectType<typeof result, readonly [{ id: number }, { id: number }]>( '~=', ); expect(result).toStrictEqual([obj, obj]); expect(result[0]).toBe(obj); expect(result[1]).toBe(obj); }); test('fixed length (empty)', () => { const result = Arr.create(0, 123); expectType<typeof result, readonly []>('='); expect(result).toStrictEqual([]); }); test('unknown length', () => { const n: number = 2; const result = Arr.create(asUint32(n), true); expectType<typeof result, readonly true[]>('='); expect(result).toStrictEqual([true, true]); }); test('should create array with function values', () => { const fn = (): string => 'test'; const result = Arr.create(3, fn); expect(result).toStrictEqual([fn, fn, fn]); expect(result[0]).toBe(fn); }); test('should create array with object values', () => { const obj = { a: 1 }; const result = Arr.create(2, obj); expect(result).toStrictEqual([obj, obj]); expect(result[0]).toBe(obj); // Same reference }); test('should create empty array when length is 0', () => { const result = Arr.create(0, 'value'); expect(result).toStrictEqual([]); }); test('newArray is alias for create', () => { const created1 = Arr.create(3, 'test'); const created2 = Arr.newArray(3, 'test'); expect(created1).toStrictEqual(created2); expect(created1).toStrictEqual(['test', 'test', 'test']); }); }); describe('copy', () => { test('should create a shallow copy of an array of primitives', () => { const original = [1, 2, 3] as const; const copied = Arr.copy(original); expectType<typeof copied, readonly [1, 2, 3]>('='); expect(copied).toStrictEqual(original); expect(copied).not.toBe(original); }); test('should create a shallow copy of an array of objects', () => { const obj1 = { id: 1 }; const obj2 = { id: 2 }; const original = [obj1, obj2] as const; const copied = Arr.copy(original); expectType<typeof copied, readonly [{ id: number }, { id: number }]>('='); expect(copied).toStrictEqual(original); expect(copied).not.toBe(original); expect(copied[0]).toBe(original[0]); // Object references are the same expect(copied[1]).toBe(original[1]); }); test('should create a copy of an empty array', () => { const original = [] as const; const copied = Arr.copy(original); expectType<typeof copied, readonly []>('='); expect(copied).toStrictEqual(original); expect(copied).not.toBe(original); }); test('should create a copy of an array with mixed types', () => { const original = [1, 'hello', true, null, undefined] as const; const copied = Arr.copy(original); expectType<typeof copied, readonly [1, 'hello', true, null, undefined]>( '=', ); expect(copied).toStrictEqual(original); expect(copied).not.toBe(original); }); test('should handle unknown array type', () => { const mut_original: number[] = [1, 2, 3]; const copied = Arr.copy(mut_original); expectType<typeof copied, number[]>('='); expect(copied).toStrictEqual(mut_original); expect(copied).not.toBe(mut_original); // Modify original to ensure copy is shallow mut_original.push(4); expect(mut_original).toStrictEqual([1, 2, 3, 4]); expect(copied).toStrictEqual([1, 2, 3]); }); test('should create shallow copy of array', () => { const original = [1, 2, 3] as const; const copied = Arr.copy(original); expectType<typeof copied, readonly [1, 2, 3]>('='); expect(copied).toStrictEqual(original); expect(copied).not.toBe(original); }); test('should work with empty array', () => { const empty = [] as const; const copied = Arr.copy(empty); expect(copied).toStrictEqual([]); expect(copied).not.toBe(empty); }); test('should preserve array type', () => { const mixed = [1, 'hello', true] as const; const copied = Arr.copy(mixed); expectType<typeof copied, readonly [1, 'hello', true]>('='); expect(copied).toStrictEqual([1, 'hello', true]); }); }); describe('range', () => { test('start < end, step = 1 (default)', () => { const result = Arr.range(1, 5); expectType<typeof result, readonly [1, 2, 3, 4]>('='); expect(result).toStrictEqual([1, 2, 3, 4]); }); test('start === end, step = 1 (default)', () => { const result = Arr.range(3, 3); expectType<typeof result, readonly []>('='); expect(result).toStrictEqual([]); }); test('start > end, step = 1 (default)', () => { const result = Arr.range(5, 1); expectType<typeof result, readonly []>('='); expect(result).toStrictEqual([]); }); test('start < end, step > 1', () => { const result = Arr.range(0, 6, 2); expectType<typeof result, readonly SafeUint[]>('='); // Type is less specific with explicit step expect(result).toStrictEqual([0, 2, 4]); }); test('start < end, step > 1, not reaching end', () => { const result = Arr.range(0, 5, 2); expect(result).toStrictEqual([0, 2, 4]); }); test('start > end, step < 0', () => { const result = Arr.range(5, 0, -1); expect(result).toStrictEqual([5, 4, 3, 2, 1]); }); test('start > end, step < 0, not reaching end', () => { const result = Arr.range(5, 1, -2); expect(result).toStrictEqual([5, 3]); }); test('start < end, step < 0 (empty result)', () => { const result = Arr.range(1, 5, -1); expect(result).toStrictEqual([]); }); test('start > end, step > 0 (empty result)', () => { const result = Arr.range(5, 1, 1); expect(result).toStrictEqual([]); }); test('unknown start/end/step', () => { const start: number = 1; const end: number = 4; const step: number = 1; const result = Arr.range( asUint32(start), asUint32(end), asNonZeroSafeInt(step), ); expectType<typeof result, readonly SafeInt[]>('='); expect(result).toStrictEqual([1, 2, 3]); }); test('range(1, 3)', () => { const result = Arr.range(1, 3); expectType<typeof result, readonly [1, 2]>('='); expect(result).toStrictEqual([1, 2]); }); test('range(1, 3, 1)', () => { const result = Arr.range(1, 3, 1); expectType<typeof result, readonly [1, 2]>('='); expect(result).toStrictEqual([1, 2]); }); test('range(0, 0)', () => { const result = Arr.range(0, 0); expectType<typeof result, readonly []>('='); expect(result).toStrictEqual([]); }); test('range(0, 1)', () => { const result = Arr.range(0, 1); expectType<typeof result, readonly [0]>('='); expect(result).toStrictEqual([0]); }); test('range(0, -1)', () => { const result = Arr.range(0, -1); expectType<typeof result, readonly SafeInt[]>('='); expect(result).toStrictEqual([]); }); test('range(SmallUint, SmallUint)', () => { const result = Arr.range<SmallUint, SmallUint>(0, 1); expectType< typeof result, readonly ( | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 )[] >('='); expect(result).toStrictEqual([0]); }); test('range(0 | 1 | 2, 1 | 2 | 3)', () => { const result = Arr.range<0 | 1 | 2, 1 | 2 | 3>(0, 1); expectType<typeof result, readonly (0 | 1 | 2)[]>('='); expect(result).toStrictEqual([0]); }); test('range(2|3, 5|6|7)', () => { const result = Arr.range<2 | 3, 5 | 6 | 7>(2, 5); expectType<typeof result, readonly (2 | 3 | 4 | 5 | 6)[]>('='); expect(result).toStrictEqual([2, 3, 4]); }); test('range(0, 10, 2)', () => { const result = Arr.range(0, 10, 2); expectType<typeof result, readonly SafeUint[]>('='); expect(result).toStrictEqual([0, 2, 4, 6, 8]); }); test('range(0, 11, 2)', () => { const result = Arr.range(0, 11, 2); expectType<typeof result, readonly SafeUint[]>('='); expect(result).toStrictEqual([0, 2, 4, 6, 8, 10]); }); test('range(1, 12, 2)', () => { const result = Arr.range(1, 12, 2); expectType<typeof result, readonly SafeUint[]>('='); expect(result).toStrictEqual([1, 3, 5, 7, 9, 11]); }); // Note: These tests were removed as the range function doesn't return Result type // and doesn't validate inputs in this way test('should handle range with step larger than difference', () => { const result = Arr.range(0, 5, 10); expect(result).toStrictEqual([0]); }); test('should handle negative step with increasing range', () => { const result = Arr.range(0, 5, -1); expect(result).toStrictEqual([]); // Should be empty when step direction conflicts }); test('should work with basic range functionality', () => { // Test basic range functionality without currying assumptions const result = Arr.range(0, 5, 1); expect(result).toStrictEqual([0, 1, 2, 3, 4]); }); }); describe('generate', () => { test('basic generator usage', () => { const result = Arr.generate<number>(function* () { yield 1; yield 2; yield 3; }); expectType<typeof result, readonly number[]>('='); expect(result).toStrictEqual([1, 2, 3]); }); test('generator with yield*', () => { const result = Arr.generate<number>(function* () { yield 1; yield* [2, 3]; yield 4; }); expectType<typeof result, readonly number[]>('='); expect(result).toStrictEqual([1, 2, 3, 4]); }); test('empty generator', () => { const result = Arr.generate<string>(function* () { // No yields }); expectType<typeof result, readonly string[]>('='); expect(result).toStrictEqual([]); }); test('generator with conditional logic', () => { const condition = true as boolean; // Simulating a condition const result = Arr.generate<number>(function* () { yield 1; if (condition) { yield 2; } yield 3; }); expectType<typeof result, readonly number[]>('='); expect(result).toStrictEqual([1, 2, 3]); }); test('generator with early return', () => { const condition = true as boolean; // Simulating a condition const result = Arr.generate<number>(function* () { yield 1; if (condition) { return; // Early return is OK } yield 2; // This won't be reached }); expectType<typeof result, readonly number[]>('='); expect(result).toStrictEqual([1]); }); test('generator with complex data types', () => { const result = Arr.generate<{ id: number; name: string }>(function* () { yield { id: 1, name: 'Alice' }; yield { id: 2, name: 'Bob' }; }); expectType<typeof result, readonly { id: number; name: string }[]>('='); expect(result).toStrictEqual([ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, ]); }); test('generator with different types', () => { const result = Arr.generate<string | number>(function* () { yield 'hello'; yield 42; yield 'world'; }); expectType<typeof result, readonly (string | number)[]>('='); expect(result).toStrictEqual(['hello', 42, 'world']); }); test('generator with loops', () => { const result = Arr.generate<number>(function* () { for (const i of range(3)) { yield i; } }); expectType<typeof result, readonly number[]>('='); expect(result).toStrictEqual([0, 1, 2]); }); }); describe('size/length', () => { test('length should be alias for size', () => { const array = [1, 2, 3]; expect(Arr.length(array)).toBe(Arr.size(array)); expect(Arr.length(array)).toBe(3); }); }); });