Files
mimic/frontend/tests/exports.test.ts

68 lines
2.3 KiB
TypeScript
Raw Permalink Normal View History

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');
});
});