import { describe, it, expect } from 'vitest'; import { diffEntity } from '@/lib/entity-diff'; describe('diffEntity', () => { it('returns changed=false and empty diff for identical objects', () => { const old = { name: 'Alice', status: 'active', count: 5 }; const result = diffEntity(old, { name: 'Alice', status: 'active', count: 5 }); expect(result).toEqual({ changed: false, diff: {} }); }); it('detects a single field change with correct old/new values', () => { const old = { name: 'Alice', status: 'active' }; const result = diffEntity(old, { status: 'inactive' }); expect(result.changed).toBe(true); expect(result.diff).toEqual({ status: { old: 'active', new: 'inactive' }, }); }); it('detects multiple field changes', () => { const old = { name: 'Alice', status: 'active', count: 1 }; const result = diffEntity(old, { name: 'Bob', status: 'inactive', count: 2 }); expect(result.changed).toBe(true); expect(Object.keys(result.diff)).toHaveLength(3); expect(result.diff.name).toEqual({ old: 'Alice', new: 'Bob' }); expect(result.diff.status).toEqual({ old: 'active', new: 'inactive' }); expect(result.diff.count).toEqual({ old: 1, new: 2 }); }); it('detects null-to-value transition', () => { const old: Record = { note: null }; const result = diffEntity(old, { note: 'Hello' }); expect(result.changed).toBe(true); expect(result.diff.note).toEqual({ old: null, new: 'Hello' }); }); it('detects value-to-null transition', () => { const old: Record = { note: 'Hello' }; const result = diffEntity(old, { note: null }); expect(result.changed).toBe(true); expect(result.diff.note).toEqual({ old: 'Hello', new: null }); }); it('skips createdAt field', () => { const now = new Date(); const old = { name: 'Alice', createdAt: now }; const result = diffEntity(old, { name: 'Alice', createdAt: new Date() }); expect(result.changed).toBe(false); expect(result.diff).toEqual({}); }); it('skips updatedAt field', () => { const old = { name: 'Alice', updatedAt: new Date('2020-01-01') }; const result = diffEntity(old, { name: 'Alice', updatedAt: new Date('2025-01-01') }); expect(result.changed).toBe(false); expect(result.diff).toEqual({}); }); it('skips portId field', () => { const old = { name: 'Alice', portId: 'port-1' }; const result = diffEntity(old, { name: 'Alice', portId: 'port-2' }); expect(result.changed).toBe(false); expect(result.diff).toEqual({}); }); it('detects nested object (JSON field) changes', () => { const old = { metadata: { color: 'red', size: 10 } }; const result = diffEntity(old, { metadata: { color: 'blue', size: 10 } }); expect(result.changed).toBe(true); expect(result.diff.metadata).toEqual({ old: { color: 'red', size: 10 }, new: { color: 'blue', size: 10 }, }); }); it('only compares keys present in newRecord (partial update)', () => { const old = { name: 'Alice', status: 'active', count: 99 }; // Only updating name; status and count should not appear in diff const result = diffEntity(old, { name: 'Bob' }); expect(result.changed).toBe(true); expect(Object.keys(result.diff)).toEqual(['name']); expect(result.diff.name).toEqual({ old: 'Alice', new: 'Bob' }); }); it('returns changed=false when partial update has no actual changes', () => { const old = { name: 'Alice', status: 'active', count: 99 }; const result = diffEntity(old, { name: 'Alice' }); expect(result.changed).toBe(false); expect(result.diff).toEqual({}); }); });