/** * Integration test: dry-run classifier dedup + conflict-policy matrix. * * Seeds an existing company, then classifies a 3-row "file" (one matching the * existing record, one new, one invalid) under each conflict policy and asserts * the per-row outcomes + summary counts. Runs against the real test DB. */ import { beforeAll, describe, expect, it } from 'vitest'; import { classifyRows } from '@/lib/import/classify'; import { companiesAdapter } from '@/lib/import/adapters/companies'; import type { RawRow } from '@/lib/import/types'; let makePort: typeof import('../helpers/factories').makePort; let makeCompany: typeof import('../helpers/factories').makeCompany; let makeAuditMeta: typeof import('../helpers/factories').makeAuditMeta; beforeAll(async () => { const f = await import('../helpers/factories'); makePort = f.makePort; makeCompany = f.makeCompany; makeAuditMeta = f.makeAuditMeta; }); const MAPPING = { name: 'Name' }; describe('classifyRows — dedup + conflict policy', () => { async function setup() { const port = await makePort(); await makeCompany({ portId: port.id, overrides: { name: 'Acme Marine' } }); const ctx = { portId: port.id, meta: makeAuditMeta({ portId: port.id }) }; const rows: RawRow[] = [ { Name: 'Acme Marine' }, // matches existing (case-insensitive) { Name: 'Brand New Co' }, // insert { Name: '' }, // error: required ]; return { ctx, rows }; } it('skip-matches: existing→skip, new→insert, blank→error', async () => { const { ctx, rows } = await setup(); const r = await classifyRows(companiesAdapter, rows, MAPPING, 'skip-matches', ctx); expect({ insert: r.insert, update: r.update, skip: r.skip, error: r.error }).toEqual({ insert: 1, update: 0, skip: 1, error: 1, }); expect(r.rows.map((x) => x.outcome)).toEqual(['skip', 'insert', 'error']); expect(r.rows[0]!.existingId).toBeTruthy(); }); it('update-matches: existing→update (adapter supports update)', async () => { const { ctx, rows } = await setup(); const r = await classifyRows(companiesAdapter, rows, MAPPING, 'update-matches', ctx); expect(r.rows[0]!.outcome).toBe('update'); expect(r.update).toBe(1); }); it('error-on-match: existing→error', async () => { const { ctx, rows } = await setup(); const r = await classifyRows(companiesAdapter, rows, MAPPING, 'error-on-match', ctx); expect(r.rows[0]!.outcome).toBe('error'); // The blank row is still an error too → 2 errors total. expect(r.error).toBe(2); }); });