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.

774 lines (537 loc) 18.2 kB
import { expectType } from '../../expect-type.mjs'; import { range as rangeIterator } from '../../iterator/index.mjs'; import { asNonZeroSafeInt, asSafeInt, asSafeUint, asUint32, } from '../../number/index.mjs'; import { copy, create, generate, generateAsync, newArray, range, seq, zeros, } from './array-utils-creation.mjs'; describe('Arr creations', () => { describe(zeros, () => { test('fixed length', () => { const result = zeros(3); expectType<typeof result, readonly [0, 0, 0]>('='); assert.deepStrictEqual(result, [0, 0, 0]); }); test('fixed length (empty)', () => { const result = zeros(0); expectType<typeof result, readonly []>('='); assert.deepStrictEqual(result, []); }); test('unknown length', () => { const n: number = 3; const result = zeros(asUint32(n)); expectType<typeof result, readonly 0[]>('='); assert.deepStrictEqual(result, [0, 0, 0]); }); test('should create array with zero length', () => { const result = zeros(0); assert.deepStrictEqual(result, []); expect(result).toHaveLength(0); }); test('should create large arrays', () => { const result = zeros(asUint32(1000)); expect(result).toHaveLength(1000); // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition assert.isTrue(result.every((x) => x === 0)); }); test('should work with curried version', () => { const createTenZeros = zeros(10); assert.deepStrictEqual(createTenZeros, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); }); }); describe(seq, () => { test('fixed length', () => { const result = seq(5); expectType<typeof result, readonly [0, 1, 2, 3, 4]>('='); assert.deepStrictEqual(result, [0, 1, 2, 3, 4]); }); test('fixed length (empty)', () => { const result = seq(0); expectType<typeof result, readonly []>('='); assert.deepStrictEqual(result, []); }); test('unknown length', () => { const n: number = 3; const result = seq(asUint32(n)); expectType<typeof result, readonly SizeType.Arr[]>('='); assert.deepStrictEqual(result, [asUint32(0), asUint32(1), asUint32(2)]); }); test('should create sequence with zero length', () => { const result = seq(0); assert.deepStrictEqual(result, []); }); test('should create sequence with large length', () => { const result = 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 = seq(5); assert.deepStrictEqual(createFiveSeq, [0, 1, 2, 3, 4]); }); }); describe(create, () => { test('fixed length with primitive value', () => { const result = create(3, 'a'); expectType<typeof result, readonly ['a', 'a', 'a']>('='); assert.deepStrictEqual(result, ['a', 'a', 'a']); }); test('fixed length with null', () => { const result = create(2, null); expectType<typeof result, readonly [null, null]>('='); assert.deepStrictEqual(result, [null, null]); }); test('fixed length with object (shallow copy)', () => { const obj = { id: 1 }; const result = create(2, obj); expectType<typeof result, readonly [{ id: number }, { id: number }]>( '~=', ); assert.deepStrictEqual(result, [obj, obj]); expect(result[0]).toBe(obj); expect(result[1]).toBe(obj); }); test('fixed length (empty)', () => { const result = create(0, 123); expectType<typeof result, readonly []>('='); assert.deepStrictEqual(result, []); }); test('unknown length', () => { const n: number = 2; const result = create(asUint32(n), true); expectType<typeof result, readonly true[]>('='); assert.deepStrictEqual(result, [true, true]); }); test('should create array with function values', () => { const fn = (): string => 'test'; const result = create(3, fn); assert.deepStrictEqual(result, [fn, fn, fn]); expect(result[0]).toBe(fn); }); test('should create array with object values', () => { const obj = { a: 1 }; const result = create(2, obj); assert.deepStrictEqual(result, [obj, obj]); expect(result[0]).toBe(obj); // Same reference }); test('should create empty array when length is 0', () => { const result = create(0, 'value'); assert.deepStrictEqual(result, []); }); test('newArray is alias for create', () => { const created1 = create(3, 'test'); const created2 = newArray(3, 'test'); assert.deepStrictEqual(created1, created2); assert.deepStrictEqual(created1, ['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 = copy(original); expectType<typeof copied, readonly [1, 2, 3]>('='); assert.deepStrictEqual(copied, 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 = copy(original); expectType<typeof copied, readonly [{ id: number }, { id: number }]>('='); assert.deepStrictEqual(copied, 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 = copy(original); expectType<typeof copied, readonly []>('='); assert.deepStrictEqual(copied, 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 = copy(original); expectType<typeof copied, readonly [1, 'hello', true, null, undefined]>( '=', ); assert.deepStrictEqual(copied, original); expect(copied).not.toBe(original); }); test('should handle unknown array type', () => { const mut_original: number[] = [1, 2, 3]; const copied = copy(mut_original); expectType<typeof copied, number[]>('='); assert.deepStrictEqual(copied, mut_original); expect(copied).not.toBe(mut_original); // Modify original to ensure copy is shallow mut_original.push(4); assert.deepStrictEqual(mut_original, [1, 2, 3, 4]); assert.deepStrictEqual(copied, [1, 2, 3]); }); test('should create shallow copy of array', () => { const original = [1, 2, 3] as const; const copied = copy(original); expectType<typeof copied, readonly [1, 2, 3]>('='); assert.deepStrictEqual(copied, original); expect(copied).not.toBe(original); }); test('should work with empty array', () => { const empty = [] as const; const copied = copy(empty); assert.deepStrictEqual(copied, []); expect(copied).not.toBe(empty); }); test('should preserve array type', () => { const mixed = [1, 'hello', true] as const; const copied = copy(mixed); expectType<typeof copied, readonly [1, 'hello', true]>('='); assert.deepStrictEqual(copied, [1, 'hello', true]); }); }); describe(range, () => { test('start < end, step = 1 (default)', () => { const result = range(1, 5); expectType<typeof result, readonly [1, 2, 3, 4]>('='); assert.deepStrictEqual(result, [1, 2, 3, 4]); }); test('start === end, step = 1 (default)', () => { const result = range(3, 3); expectType<typeof result, readonly []>('='); assert.deepStrictEqual(result, []); }); test('start > end, step = 1 (default)', () => { const result = range(5, 1); expectType<typeof result, readonly []>('='); assert.deepStrictEqual(result, []); }); test('start < end, step > 1', () => { const result = range(0, 6, 2); expectType<typeof result, readonly SafeUint[]>('='); // Type is less specific with explicit step assert.deepStrictEqual(result, [ asSafeUint(0), asSafeUint(2), asSafeUint(4), ]); }); test('start < end, step > 1, not reaching end', () => { const result = range(0, 5, 2); assert.deepStrictEqual(result, [ asSafeUint(0), asSafeUint(2), asSafeUint(4), ]); }); test('start > end, step < 0', () => { const result = range(5, 0, -1); assert.deepStrictEqual(result, [ asSafeInt(5), asSafeInt(4), asSafeInt(3), asSafeInt(2), asSafeInt(1), ]); }); test('start > end, step < 0, not reaching end', () => { const result = range(5, 1, -2); assert.deepStrictEqual(result, [asSafeInt(5), asSafeInt(3)]); }); test('start < end, step < 0 (empty result)', () => { const result = range(1, 5, -1); assert.deepStrictEqual(result, []); }); test('start > end, step > 0 (empty result)', () => { const result = range(5, 1, 1); assert.deepStrictEqual(result, []); }); test('unknown start/end/step', () => { const start: number = 1; const end: number = 4; const step: number = 1; const result = range( asUint32(start), asUint32(end), asNonZeroSafeInt(step), ); expectType<typeof result, readonly SafeInt[]>('='); assert.deepStrictEqual(result, [ asSafeInt(1), asSafeInt(2), asSafeInt(3), ]); }); test('range(1, 3)', () => { const result = range(1, 3); expectType<typeof result, readonly [1, 2]>('='); assert.deepStrictEqual(result, [1, 2]); }); test('range(1, 3, 1)', () => { const result = range(1, 3, 1); expectType<typeof result, readonly [1, 2]>('='); assert.deepStrictEqual(result, [1, 2]); }); test('range(0, 0)', () => { const result = range(0, 0); expectType<typeof result, readonly []>('='); assert.deepStrictEqual(result, []); }); test('range(0, 1)', () => { const result = range(0, 1); expectType<typeof result, readonly [0]>('='); assert.deepStrictEqual(result, [asSafeUint(0)]); }); test('range(0, -1)', () => { const result = range(0, -1); expectType<typeof result, readonly SafeInt[]>('='); assert.deepStrictEqual(result, []); }); test('range(SmallUint, SmallUint)', () => { const result = 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 )[] >('='); assert.deepStrictEqual(result, [asSafeUint(0)]); }); test('range(0 | 1 | 2, 1 | 2 | 3)', () => { const result = range<0 | 1 | 2, 1 | 2 | 3>(0, 1); expectType<typeof result, readonly (0 | 1 | 2)[]>('='); assert.deepStrictEqual(result, [0]); }); test('range(2|3, 5|6|7)', () => { const result = range<2 | 3, 5 | 6 | 7>(2, 5); expectType<typeof result, readonly (2 | 3 | 4 | 5 | 6)[]>('='); assert.deepStrictEqual(result, [2, 3, 4]); }); test('range(0, 10, 2)', () => { const result = range(0, 10, 2); expectType<typeof result, readonly SafeUint[]>('='); assert.deepStrictEqual(result, [ asSafeUint(0), asSafeUint(2), asSafeUint(4), asSafeUint(6), asSafeUint(8), ]); }); test('range(0, 11, 2)', () => { const result = range(0, 11, 2); expectType<typeof result, readonly SafeUint[]>('='); assert.deepStrictEqual(result, [ asSafeUint(0), asSafeUint(2), asSafeUint(4), asSafeUint(6), asSafeUint(8), asSafeUint(10), ]); }); test('range(1, 12, 2)', () => { const result = range(1, 12, 2); expectType<typeof result, readonly SafeUint[]>('='); assert.deepStrictEqual(result, [ asSafeUint(1), asSafeUint(3), asSafeUint(5), asSafeUint(7), asSafeUint(9), asSafeUint(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 = range(0, 5, 10); assert.deepStrictEqual(result, [asSafeUint(0)]); }); test('should handle negative step with increasing range', () => { const result = range(0, 5, -1); assert.deepStrictEqual(result, []); // Should be empty when step direction conflicts }); test('should work with basic range functionality', () => { // Test basic range functionality without currying assumptions const result = range(0, 5, 1); assert.deepStrictEqual(result, [ asSafeUint(0), asSafeUint(1), asSafeUint(2), asSafeUint(3), asSafeUint(4), ]); }); }); describe(generate, () => { test('basic generator usage', () => { const result = generate<number>(function* () { yield 1; yield 2; yield 3; }); expectType<typeof result, readonly number[]>('='); assert.deepStrictEqual(result, [1, 2, 3]); }); test('generator with yield*', () => { const result = generate<number>(function* () { yield 1; yield* [2, 3]; yield 4; }); expectType<typeof result, readonly number[]>('='); assert.deepStrictEqual(result, [1, 2, 3, 4]); }); test('empty generator', () => { const result = generate<string>(function* () { // No yields }); expectType<typeof result, readonly string[]>('='); assert.deepStrictEqual(result, []); }); test('generator with conditional logic', () => { const condition = true as boolean; // Simulating a condition const result = generate<number>(function* () { yield 1; if (condition) { yield 2; } yield 3; }); expectType<typeof result, readonly number[]>('='); assert.deepStrictEqual(result, [1, 2, 3]); }); test('generator with early return', () => { const condition = true as boolean; // Simulating a condition const result = generate<number>(function* () { yield 1; if (condition) { return; // Early return is OK } yield 2; // This won't be reached }); expectType<typeof result, readonly number[]>('='); assert.deepStrictEqual(result, [1]); }); test('generator with complex data types', () => { const result = generate<{ id: number; name: string }>(function* () { yield { id: 1, name: 'Alice' }; yield { id: 2, name: 'Bob' }; }); expectType<typeof result, readonly { id: number; name: string }[]>('='); assert.deepStrictEqual(result, [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, ]); }); test('generator with different types', () => { const result = generate<string | number>(function* () { yield 'hello'; yield 42; yield 'world'; }); expectType<typeof result, readonly (string | number)[]>('='); assert.deepStrictEqual(result, ['hello', 42, 'world']); }); test('generator with loops', () => { const result = generate<number>(function* () { for (const i of rangeIterator(3)) { yield i; } }); expectType<typeof result, readonly number[]>('='); assert.deepStrictEqual(result, [0, 1, 2]); }); }); describe(generateAsync, () => { test('should generate array from async generator', async () => { // eslint-disable-next-line @typescript-eslint/require-await const result = await generateAsync<number>(async function* () { yield 1; yield 2; yield 3; }); expectType<typeof result, readonly number[]>('='); assert.deepStrictEqual(result, [1, 2, 3]); }); test('should handle async operations in generator', async () => { const result = await generateAsync<string>(async function* () { await Promise.resolve(); yield 'a'; await Promise.resolve(); yield 'b'; await Promise.resolve(); yield 'c'; }); assert.deepStrictEqual(result, ['a', 'b', 'c']); }); test('should generate empty array from empty async generator', async () => { const result = await generateAsync<number>(async function* () { // Empty generator }); assert.deepStrictEqual(result, []); }); test('should handle async generator with delays', async () => { const result = await generateAsync<number>(async function* () { // eslint-disable-next-line functional/no-let for (let i = 0; i < 3; i++) { // eslint-disable-next-line no-promise-executor-return, no-await-in-loop await new Promise((resolve) => setTimeout(resolve, 0)); yield i; } }); assert.deepStrictEqual(result, [0, 1, 2]); }); }); });