Files
pn-new-crm/tests/unit/entity-diff.test.ts
Matt 67d7e6e3d5
Some checks failed
Build & Push Docker Images / build-and-push (push) Has been cancelled
Build & Push Docker Images / deploy (push) Has been cancelled
Build & Push Docker Images / lint (push) Has been cancelled
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00

92 lines
3.5 KiB
TypeScript

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 = { 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 = { 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({});
});
});