import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import MockAdapter from 'axios-mock-adapter'; import { apiClient } from '@/api/client'; import { downloadEngagementExport } from '@/api/exports'; describe('downloadEngagementExport — Content-Disposition fallback', () => { let mock: MockAdapter; let capturedAnchor: HTMLAnchorElement | null = null; beforeEach(() => { mock = new MockAdapter(apiClient); capturedAnchor = null; globalThis.URL.createObjectURL = vi.fn().mockReturnValue('blob:fake-url'); globalThis.URL.revokeObjectURL = vi.fn(); const origCreateElement = document.createElement.bind(document); vi.spyOn(document, 'createElement').mockImplementation((tag: string) => { const el = origCreateElement(tag); if (tag === 'a') { capturedAnchor = el as HTMLAnchorElement; vi.spyOn(el as HTMLAnchorElement, 'click').mockImplementation(() => {}); } return el; }); vi.spyOn(document.body, 'appendChild').mockImplementation((node) => node); vi.spyOn(document.body, 'removeChild').mockImplementation((node) => node); }); afterEach(() => { mock.restore(); vi.restoreAllMocks(); }); it('uses fallback filename engagement-{id}.md when Content-Disposition is absent', async () => { mock.onGet('/engagements/42/export').reply(200, new Blob(['# test']), { 'content-type': 'text/markdown', }); await downloadEngagementExport(42, 'md'); expect(capturedAnchor?.download).toBe('engagement-42.md'); }); it('uses fallback filename engagement-{id}.csv when Content-Disposition is malformed (no filename=)', async () => { mock.onGet('/engagements/7/export').reply(200, new Blob(['col1,col2']), { 'content-type': 'text/csv', 'content-disposition': 'attachment', }); await downloadEngagementExport(7, 'csv'); expect(capturedAnchor?.download).toBe('engagement-7.csv'); }); it('uses filename from Content-Disposition when header is well-formed', async () => { mock.onGet('/engagements/5/export').reply(200, new Blob(['data']), { 'content-type': 'application/pdf', 'content-disposition': 'attachment; filename="engagement-5-slug-20260101.pdf"', }); await downloadEngagementExport(5, 'pdf'); expect(capturedAnchor?.download).toBe('engagement-5-slug-20260101.pdf'); }); });