/** * @module tests/unit/db/stableEqual * @description Unit proof for the key-order-insensitive deep-equal that * {@link Brainy.diff} uses to decide whether an id present at both endpoints * actually changed. The risk it guards: a naive JSON.stringify comparison is * key-order-sensitive and would report a no-op re-write as `modified`. */ import { describe, it, expect } from 'vitest' import { stableDeepEqual } from '../../../src/db/stableEqual.js' describe('stableDeepEqual', () => { it('ignores object key order (the core diff requirement)', () => { expect(stableDeepEqual({ a: 1, b: 2 }, { b: 2, a: 1 })).toBe(true) expect(stableDeepEqual({ a: 1, b: 2, c: { x: 1, y: 2 } }, { c: { y: 2, x: 1 }, b: 2, a: 1 })).toBe(true) }) it('honors array order (arrays are order-significant)', () => { expect(stableDeepEqual([1, 2, 3], [1, 2, 3])).toBe(true) expect(stableDeepEqual([1, 2, 3], [3, 2, 1])).toBe(false) expect(stableDeepEqual([1, 2], [1, 2, 3])).toBe(false) }) it('recurses into nested objects and arrays', () => { expect( stableDeepEqual( { tags: ['a', 'b'], meta: { n: 1, deep: { z: [1, { q: 2 }] } } }, { meta: { deep: { z: [1, { q: 2 }] }, n: 1 }, tags: ['a', 'b'] } ) ).toBe(true) expect( stableDeepEqual({ meta: { deep: { z: [1, { q: 2 }] } } }, { meta: { deep: { z: [1, { q: 3 }] } } }) ).toBe(false) }) it('distinguishes primitives, null, and types', () => { expect(stableDeepEqual(1, 1)).toBe(true) expect(stableDeepEqual(1, '1')).toBe(false) expect(stableDeepEqual(null, null)).toBe(true) expect(stableDeepEqual(null, {})).toBe(false) expect(stableDeepEqual({ a: 1 }, { a: 1, b: undefined })).toBe(false) // extra key expect(stableDeepEqual(true, false)).toBe(false) }) it('treats NaN as equal to NaN (stable value comparison)', () => { expect(stableDeepEqual(NaN, NaN)).toBe(true) expect(stableDeepEqual({ x: NaN }, { x: NaN })).toBe(true) expect(stableDeepEqual(NaN, 0)).toBe(false) }) it('an object and an array of the same length are not equal', () => { expect(stableDeepEqual({ 0: 'a', 1: 'b' }, ['a', 'b'])).toBe(false) }) })