feat: sprint 6 — engagement export (md/csv/pdf) #9
67
frontend/tests/exports.test.ts
Normal file
67
frontend/tests/exports.test.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
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');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user