/** * CM-9: proxy service — per-entity CRUD/upsert, tenant guard, and the * yacht → interest → client resolution precedence. */ import { describe, it, expect } from 'vitest'; import { createInterest } from '@/lib/services/interests.service'; import { clearProxy, getProxy, resolveEffectiveProxy, setProxy, } from '@/lib/services/proxies.service'; import { makeAuditMeta, makeClient, makePort, makeYacht } from '../helpers/factories'; describe('proxies.service (CM-9)', () => { it('sets, reads, upserts and clears a client proxy', async () => { const port = await makePort(); const meta = makeAuditMeta({ portId: port.id }); const client = await makeClient({ portId: port.id }); expect(await getProxy(port.id, 'client', client.id)).toBeNull(); const p = await setProxy( port.id, 'client', client.id, { name: 'Broker Bob', email: 'bob@example.com' }, meta, ); expect(p.name).toBe('Broker Bob'); expect(p.email).toBe('bob@example.com'); // Upsert: one proxy per entity — setting again updates the same row. const p2 = await setProxy( port.id, 'client', client.id, { name: 'Broker Bob', email: '', phone: '+100' }, meta, ); expect(p2.id).toBe(p.id); expect(p2.email).toBeNull(); // empty string normalised to null expect(p2.phone).toBe('+100'); await clearProxy(port.id, 'client', client.id, meta); expect(await getProxy(port.id, 'client', client.id)).toBeNull(); }); it('rejects an entity from a foreign port', async () => { const portA = await makePort(); const portB = await makePort(); const meta = makeAuditMeta({ portId: portA.id }); const foreign = await makeClient({ portId: portB.id }); await expect(setProxy(portA.id, 'client', foreign.id, { name: 'X' }, meta)).rejects.toThrow( /not found in this port/, ); }); it('resolves the most specific proxy: yacht → interest → client', async () => { const port = await makePort(); const meta = makeAuditMeta({ portId: port.id }); const client = await makeClient({ portId: port.id }); const interest = await createInterest( port.id, { clientId: client.id, pipelineStage: 'enquiry', tagIds: [], reminderEnabled: false }, meta, ); const yacht = await makeYacht({ portId: port.id, ownerType: 'client', ownerId: client.id }); await setProxy(port.id, 'client', client.id, { name: 'Client PoC' }, meta); await setProxy(port.id, 'interest', interest.id, { name: 'Deal PoC' }, meta); await setProxy(port.id, 'yacht', yacht.id, { name: 'Vessel PoC' }, meta); const ctx = { portId: port.id, clientId: client.id, interestId: interest.id, yachtId: yacht.id, }; expect((await resolveEffectiveProxy(ctx))?.source).toBe('yacht'); await clearProxy(port.id, 'yacht', yacht.id, meta); expect((await resolveEffectiveProxy(ctx))?.source).toBe('interest'); await clearProxy(port.id, 'interest', interest.id, meta); const eff = await resolveEffectiveProxy(ctx); expect(eff?.source).toBe('client'); expect(eff?.proxy.name).toBe('Client PoC'); await clearProxy(port.id, 'client', client.id, meta); expect(await resolveEffectiveProxy(ctx)).toBeNull(); }); });