import test from 'node:test' import assert from 'node:assert/strict' import { range, dropLast, contains, pipe, compose, deepFreeze } from '../src/util.js' import { freeze } from './helpers.js' test('m01 range(0) is empty', () => assert.deepEqual(range(0), [])) test('m01 range(3) counts from zero up to n-1', () => assert.deepEqual(range(3), [0, 1, 2])) test('m01 dropLast of an empty list is empty', () => assert.deepEqual(dropLast([]), [])) test('m01 dropLast removes only the last element', () => assert.deepEqual(dropLast([1, 2, 3]), [1, 2])) test('m01 dropLast leaves its input untouched', () => { const xs = freeze([1, 2, 3]) assert.deepEqual(dropLast(xs), [1, 2]) assert.deepEqual(xs, [1, 2, 3]) }) const sameParity = (a, b) => a % 2 === b % 2 test('m01 contains finds an element using the supplied equality', () => assert.equal(contains([1, 2, 3], 5, sameParity), true)) test('m01 contains is false when no element is equal', () => assert.equal(contains([2, 4], 3, sameParity), false)) test('m01 contains is false for an empty list', () => assert.equal(contains([], 1, (a, b) => a === b), false)) test('m01 contains compares structurally when given a structural equality', () => { const eq = (a, b) => a.x === b.x && a.y === b.y assert.equal(contains(freeze([{ x: 1, y: 2 }]), { x: 1, y: 2 }, eq), true) }) test('m01 pipe threads a value through functions left to right', () => assert.equal(pipe(2, (x) => x + 1, (x) => x * 10), 30)) test('m01 pipe with no functions returns the value', () => assert.equal(pipe(5), 5)) test('m01 compose applies functions right to left', () => assert.equal(compose((x) => x * 10, (x) => x + 1)(2), 30)) test('m01 compose with no functions is the identity', () => assert.equal(compose()(5), 5)) test('m01 deepFreeze freezes nested objects and arrays', () => { const o = deepFreeze({ a: { b: [1, { c: 2 }] } }) assert.ok(Object.isFrozen(o)) assert.ok(Object.isFrozen(o.a)) assert.ok(Object.isFrozen(o.a.b)) assert.ok(Object.isFrozen(o.a.b[1])) }) test('m01 deepFreeze returns the same object it was given', () => { const o = {} assert.equal(deepFreeze(o), o) }) test('m01 deepFreeze reaches unfrozen children of an already-frozen parent', () => { const o = deepFreeze({ a: Object.freeze({ b: { c: 1 } }) }) assert.ok(Object.isFrozen(o.a.b)) }) test('m01 deepFreeze handles cyclic objects', () => { const o = { child: {} } o.child.parent = o deepFreeze(o) assert.ok(Object.isFrozen(o) && Object.isFrozen(o.child)) })