import { DisputeFlowService } from '../../backend/src/dispute-flow/dispute-flow.service'; import { db } from '../../backend/src/db'; // Mock the database connection for testing jest.mock('../../backend/src/db', () => ({ db: { query: jest.fn() } })); describe('Dispute Flow Contract Tests', () => { let service: DisputeFlowService; beforeEach(() => { service = new DisputeFlowService(); // Reset all mocks before each test jest.clearAllMocks(); }); it('should create a dispute with all required fields', async () => { const mockDispute = { id: 1, dealId: 123, openedByUserId: 456, status: 'open', reasonCode: 'NO_SHOW', summary: 'Helper did not show up', requestedOutcome: 'refund', createdAt: new Date(), updatedAt: new Date() }; (db.query as jest.Mock).mockResolvedValue({ rows: [mockDispute] }); const result = await service.createDispute({ dealId: 123, openedByUserId: 456, reasonCode: 'NO_SHOW', summary: 'Helper did not show up', requestedOutcome: 'refund' }); expect(result).toHaveProperty('id'); expect(result).toHaveProperty('dealId'); expect(result).toHaveProperty('openedByUserId'); expect(result).toHaveProperty('status', 'open'); expect(result).toHaveProperty('reasonCode'); expect(result).toHaveProperty('summary'); expect(result).toHaveProperty('requestedOutcome'); }); it('should transition dispute status correctly through the flow', async () => { // Mock initial creation (db.query as jest.Mock) .mockResolvedValueOnce({ rows: [{ id: 1, dealId: 123, openedByUserId: 456, status: 'open', reasonCode: 'NO_SHOW', summary: 'Helper did not show up', requestedOutcome: 'refund', createdAt: new Date(), updatedAt: new Date() }] }) .mockResolvedValueOnce({}) // updateDisputeStatus .mockResolvedValueOnce({}) // addEvidence .mockResolvedValueOnce({}) // updateDisputeStatus to mediation .mockResolvedValueOnce({}) // resolveDispute .mockResolvedValueOnce({ rows: [{ id: 1, disputeId: 1, eventType: 'resolved', actorUserId: 456, payloadJson: JSON.stringify({ decision: 'refund', reason: 'Helper did not show up' }), createdAt: new Date() }] }); // getDisputeEvents const dispute = await service.createDispute({ dealId: 123, openedByUserId: 456, reasonCode: 'NO_SHOW', summary: 'Helper did not show up', requestedOutcome: 'refund' }); expect(dispute.status).toBe('open'); // Transition to evidence await service.updateDisputeStatus(1, 'evidence', 456); // Add evidence await service.addEvidence(1, { file: 'test.jpg' }, 456); // Transition to mediation await service.updateDisputeStatus(1, 'mediation', 456); // Resolve dispute await service.resolveDispute(1, { decision: 'refund', decisionReason: 'Helper did not show up' }, 456); const events = await service.getDisputeEvents(1); expect(events).toHaveLength(4); // open, evidence, mediation, resolved }); it('should log all dispute events correctly', async () => { (db.query as jest.Mock) .mockResolvedValueOnce({ rows: [{ id: 1, dealId: 123, openedByUserId: 456, status: 'open', reasonCode: 'NO_SHOW', summary: 'Helper did not show up', requestedOutcome: 'refund', createdAt: new Date(), updatedAt: new Date() }] }) .mockResolvedValueOnce({}) // addEvidence .mockResolvedValueOnce({ rows: [{ id: 1, disputeId: 1, eventType: 'evidence', actorUserId: 456, payloadJson: JSON.stringify({ file: 'test.jpg' }), createdAt: new Date() }] }); const dispute = await service.createDispute({ dealId: 123, openedByUserId: 456, reasonCode: 'NO_SHOW', summary: 'Helper did not show up', requestedOutcome: 'refund' }); await service.addEvidence(1, { file: 'test.jpg' }, 456); const events = await service.getDisputeEvents(1); expect(events[0]).toHaveProperty('eventType', 'evidence'); expect(events[0].payloadJson).toContain('test.jpg'); }); it('should handle final decision with audit trail', async () => { (db.query as jest.Mock) .mockResolvedValueOnce({ rows: [{ id: 1, dealId: 123, openedByUserId: 456, status: 'open', reasonCode: 'NO_SHOW', summary: 'Helper did not show up', requestedOutcome: 'refund', createdAt: new Date(), updatedAt: new Date() }] }) .mockResolvedValueOnce({}) // resolveDispute .mockResolvedValueOnce({ rows: [{ id: 1, disputeId: 1, eventType: 'resolved', actorUserId: 456, payloadJson: JSON.stringify({ decision: 'refund', reason: 'Helper did not show up' }), createdAt: new Date() }] }); const dispute = await service.createDispute({ dealId: 123, openedByUserId: 456, reasonCode: 'NO_SHOW', summary: 'Helper did not show up', requestedOutcome: 'refund' }); await service.resolveDispute(1, { decision: 'refund', decisionReason: 'Helper did not show up' }, 456); const events = await service.getDisputeEvents(1); expect(events[events.length - 1]).toHaveProperty('eventType', 'resolved'); expect(events[events.length - 1].payloadJson).toContain('refund'); expect(events[events.length - 1].payloadJson).toContain('Helper did not show up'); }); });