Files
helpers/test/array.ts
T

267 lines
6.4 KiB
TypeScript

import assert from "node:assert/strict"
import { describe, it } from "node:test"
import {
arrayFromNonNullable,
count,
countBy,
countByMany,
ensureNonEmpty,
filterNonNullable,
groupBy,
partition,
range,
rangeSafe,
reduceWhile,
someCount,
sum,
sumWith,
unique,
} from "../src/array.js"
describe("arrayFromNonNullable", () => {
it("returns an array with null and undefined removed", () => {
assert.deepEqual(
arrayFromNonNullable(1, 2, null, 3, undefined, 4, 5),
[1, 2, 3, 4, 5]
)
})
})
describe("filterNonNullable", () => {
it("returns an array with null and undefined removed", () => {
assert.deepEqual(
filterNonNullable([1, 2, null, 3, undefined, 4, 5]),
[1, 2, 3, 4, 5]
)
})
})
describe("range", () => {
it("returns an array with all values between and including its bounds", () => {
assert.deepEqual(range(3, 3), [3])
assert.deepEqual(range(3, 8), [3, 4, 5, 6, 7, 8])
})
it("throws an errors if the upper bound is lower than the lower bound", () => {
assert.throws(() => range(3, 2))
})
})
describe("rangeSafe", () => {
it("returns an array with all values between and including its bounds", () => {
assert.deepEqual(rangeSafe(3, 3), [3])
assert.deepEqual(rangeSafe(3, 8), [3, 4, 5, 6, 7, 8])
assert.deepEqual(rangeSafe(8, 3), [3, 4, 5, 6, 7, 8])
})
})
describe("sum", () => {
it("returns 0 if the array is empty", () => {
assert.equal(sum([]), 0)
})
it("returns the sum of all numbers in the array", () => {
assert.equal(sum([1]), 1)
assert.equal(sum([1, 2]), 3)
assert.equal(sum([1, 2, 3]), 6)
assert.equal(sum([1, 2, 3, 4]), 10)
})
})
describe("sumWith", () => {
it("returns 0 if the array is empty", () => {
assert.equal(
sumWith([], (x) => x * 2),
0
)
})
it("returns the sum of all mapped numbers in the array", () => {
assert.equal(
sumWith([1], (x) => x * 2),
2
)
assert.equal(
sumWith([1, 2], (x) => x * 2),
6
)
assert.equal(
sumWith([1, 2, 3], (x) => x * 2),
12
)
assert.equal(
sumWith([1, 2, 3, 4], (x) => x * 2),
20
)
})
})
describe("unique", () => {
it("filters out duplicate values from an array", () => {
assert.deepEqual(unique([]), [])
assert.deepEqual(unique([1, 2, 3]), [1, 2, 3])
assert.deepEqual(unique([1, 2, 1, 3]), [1, 2, 3])
})
})
describe("ensureNonEmpty", () => {
it("returns undefined if the array is empty", () => {
assert.deepEqual(ensureNonEmpty([]), undefined)
})
it("returns the non-empty array as-is", () => {
assert.deepEqual(ensureNonEmpty([1, 2]), [1, 2])
})
})
describe("count", () => {
it("returns how many elements satify the given predicate", () => {
assert.equal(
count([], (x) => x > 3),
0
)
assert.equal(
count([0, 2, 3], (x) => x >= 3),
1
)
assert.equal(
count([0, 2, 4, 6, 8], (x) => x > 3),
3
)
})
})
describe("countBy", () => {
it("returns an empty object of the array is empty", () => {
assert.deepEqual(
countBy([], (x) => x % 2),
{}
)
})
it("returns for how many elements the function returns the same value", () => {
assert.deepEqual(
countBy([0, 2, 3], (x) => x % 2),
{ 0: 2, 1: 1 }
)
assert.deepEqual(
countBy([0, 2, 4, 6, 8], (x) => x % 2),
{ 0: 5 }
)
})
})
describe("countByMany", () => {
it("returns an empty object of the array is empty", () => {
assert.deepEqual(
countByMany([], (x) => [x, Math.round(x / 2), x % 2]),
{}
)
})
it("returns for how many elements the function returns the same value", () => {
assert.deepEqual(
countByMany([0, 2, 3], (x) => [x, Math.round(x / 2), x % 2]),
{ 0: 2, 1: 2, 2: 2, 3: 1 }
)
assert.deepEqual(
countByMany([0, 2, 4, 6, 8], (x) => [x, Math.round(x / 2), x % 2]),
{ 0: 5, 1: 1, 2: 2, 3: 1, 4: 2, 6: 1, 8: 1 }
)
})
})
describe("partition", () => {
it("splits all array elements into two separate arrays based on a predicate", () => {
assert.deepEqual(
partition([], (x) => x >= 3),
[[], []]
)
assert.deepEqual(
partition([0, 2, 3], (x) => x >= 3),
[[3], [0, 2]]
)
assert.deepEqual(
partition([0, 2, 4, 6, 8], (x) => x >= 3),
[
[4, 6, 8],
[0, 2],
]
)
})
it("keeps the original order of elements", () => {
assert.deepEqual(
partition([4, 8, 2, 7, 5, 6, 1, 3], (x) => x >= 3),
[
[4, 8, 7, 5, 6, 3],
[2, 1],
]
)
})
})
describe("reduceWhile", () => {
it("should return the initial value for an empty array", () => {
const result = reduceWhile(
[],
(acc, value) => acc + value,
() => false,
10
)
assert.equal(result, 10)
})
it("should correctly reduce the array", () => {
const result = reduceWhile(
[1, 2, 3, 4, 5],
(acc, value) => acc + value,
() => false,
0
)
assert.equal(result, 15)
})
it("should break early and return the correct value", () => {
const result = reduceWhile(
[1, 2, 3, 4, 5],
(acc, value) => acc + value,
(acc) => acc > 3,
0
)
assert.equal(result, 6)
})
})
describe("someCount", () => {
it("should return true if the array has the required minimum elements that satisfy the predicate", () => {
const result = someCount([1, 2, 3, 4, 5], (value) => value > 2, 3)
assert.equal(result, true)
})
it("should return false if the array does not have the required minimum elements that satisfy the predicate", () => {
const result = someCount([1, 2, 3, 4, 5], (value) => value > 5, 3)
assert.equal(result, false)
})
it("should return true for an array that has exactly the required number of elements satisfying the predicate", () => {
const result = someCount([1, 2, 3, 4, 5], (value) => value > 3, 2)
assert.equal(result, true)
})
it("should return false for an empty array", () => {
const result = someCount([], (value) => value === 0, 2)
assert.equal(result, false)
})
})
describe("groupBy", () => {
it("should return an empty array for an empty input", () => {
const result = groupBy([], (a, b) => a === b)
assert.deepEqual(result, [])
})
it("should group adjacent elements that are equal", () => {
const result = groupBy([1, 1, 2, 2, 2, 3, 4, 4, 4, 4], (a, b) => a === b)
assert.deepEqual(result, [[1, 1], [2, 2, 2], [3], [4, 4, 4, 4]])
})
})