UNPKG

@accounter/server

Version:
133 lines 6.38 kB
import { describe, expect, it, vi } from 'vitest'; import { GraphQLError } from 'graphql'; import { emailIngestionControlResolver } from '../resolvers/email-ingestion-control.resolver.js'; import { EmailIngestionControlProvider } from '../providers/email-ingestion-control.provider.js'; // --------------------------------------------------------------------------- // Mock helpers // --------------------------------------------------------------------------- const GRANT_TTL_MS = 5 * 60 * 1000; // 5 minutes const baseInput = { recipientAlias: 'invoice@tenant.example.com', messageId: 'msg-abc-123', rawMessageHash: 'sha256-abc', receivedAt: new Date().toISOString(), correlationId: 'corr-xyz-001', }; const mockGrant = { jti: 'jti-uuid', tenantId: 'tenant-uuid-1', messageId: 'msg-abc-123', rawMessageHash: 'sha256-abc', action: 'ingest', expiresAt: new Date(Date.now() + GRANT_TTL_MS), decisionId: 'decision-uuid', auditId: 'audit-uuid', }; function makeInjector(overrides = {}) { const controlProvider = { resolveAlias: vi.fn().mockResolvedValue({ found: true, tenantId: 'tenant-uuid-1' }), recognizeBusiness: vi.fn().mockResolvedValue({ businessId: null, config: {} }), issueGrant: vi.fn().mockResolvedValue(mockGrant), ...overrides, }; return { get: (token) => { if (token === EmailIngestionControlProvider) return controlProvider; throw new Error(`Unexpected provider: ${String(token)}`); }, }; } // --------------------------------------------------------------------------- // Mutation.requestIngestControl resolver // --------------------------------------------------------------------------- describe('Mutation.requestIngestControl', () => { const resolver = emailIngestionControlResolver.Mutation.requestIngestControl; it('resolves alias and returns IngestControlDecision on success', async () => { const injector = makeInjector(); const result = await resolver({}, { input: baseInput }, { injector }, {}); expect(result).toMatchObject({ tenantId: 'tenant-uuid-1', decisionId: 'decision-uuid', auditId: 'audit-uuid', grant: expect.objectContaining({ jti: 'jti-uuid', tenantId: 'tenant-uuid-1', action: 'ingest', }), }); }); it('calls resolveAlias with the recipientAlias from input', async () => { const resolveAlias = vi.fn().mockResolvedValue({ found: true, tenantId: 'tenant-uuid-1' }); const injector = makeInjector({ resolveAlias, issueGrant: vi.fn().mockResolvedValue(mockGrant) }); await resolver({}, { input: { ...baseInput, recipientAlias: 'test@example.com' } }, { injector }, {}); expect(resolveAlias).toHaveBeenCalledWith('test@example.com'); }); it('returns CommonError when alias is unknown', async () => { const injector = makeInjector({ resolveAlias: vi.fn().mockResolvedValue({ found: false, reason: 'UNKNOWN_ALIAS' }), }); const result = await resolver({}, { input: baseInput }, { injector }, {}); expect(result).toMatchObject({ __typename: 'CommonError', message: expect.stringContaining('UNKNOWN_ALIAS'), }); }); it('does not call issueGrant when alias resolution fails', async () => { const issueGrant = vi.fn(); const injector = makeInjector({ resolveAlias: vi.fn().mockResolvedValue({ found: false, reason: 'UNKNOWN_ALIAS' }), issueGrant, }); await resolver({}, { input: baseInput }, { injector }, {}); expect(issueGrant).not.toHaveBeenCalled(); }); it('throws GraphQLError on unexpected provider failure', async () => { const injector = makeInjector({ resolveAlias: vi.fn().mockRejectedValue(new Error('DB down')), }); await expect(resolver({}, { input: baseInput }, { injector }, {})).rejects.toThrow(GraphQLError); }); it('passes correlationId and messageId to issueGrant', async () => { const issueGrant = vi.fn().mockResolvedValue(mockGrant); const injector = makeInjector({ issueGrant }); await resolver({}, { input: { ...baseInput, correlationId: 'corr-999' } }, { injector }, {}); const callArg = issueGrant.mock.calls[0][0]; expect(callArg.correlationId).toBe('corr-999'); expect(callArg.messageId).toBe(baseInput.messageId); }); it('selects the issuer from senderEvidence and returns the business config', async () => { const recognizeBusiness = vi.fn().mockResolvedValue({ businessId: 'biz-1', config: { emailBody: true, attachments: ['PDF'], internalEmailLinks: ['https://acme.com/inv'], }, }); const injector = makeInjector({ recognizeBusiness }); const result = await resolver({}, { input: { ...baseInput, senderEvidence: { from: 'vendor@acme.com' } } }, { injector }, {}); expect(recognizeBusiness).toHaveBeenCalledWith('tenant-uuid-1', 'vendor@acme.com'); expect(result).toMatchObject({ businessEmailConfig: { businessId: 'biz-1', emailBody: true, attachments: ['PDF'], internalEmailLinks: ['https://acme.com/inv'], }, }); }); it('returns null businessEmailConfig when no business is recognized', async () => { const injector = makeInjector(); const result = await resolver({}, { input: baseInput }, { injector }, {}); expect(result.businessEmailConfig).toBeNull(); }); it('binds the recognized businessId into the issued grant', async () => { const issueGrant = vi.fn().mockResolvedValue(mockGrant); const recognizeBusiness = vi.fn().mockResolvedValue({ businessId: 'biz-7', config: {} }); const injector = makeInjector({ issueGrant, recognizeBusiness }); await resolver({}, { input: { ...baseInput, senderEvidence: { from: 'vendor@acme.com' } } }, { injector }, {}); expect(issueGrant.mock.calls[0][0].businessId).toBe('biz-7'); }); }); //# sourceMappingURL=email-ingestion-control.resolver.test.js.map