fix(tests): resolve URL.createObjectURL and fetch mocking failures on CI

Three interrelated issues caused 4 tests to pass locally but fail on CI:

1. setup.ts only applied the URL.createObjectURL stub when it was
   undefined, but jsdom already defines it (returning ''). Changed to
   always override with configurable:true so the predictable 'blob:mock'
   value is set in every environment.

2. FE-API-013 used Object.defineProperty (non-configurable in jsdom) and
   MSW to handle a native fetch call. Replaced with vi.spyOn for both
   URL.createObjectURL/revokeObjectURL and a direct fetch mock, which is
   more reliable across environments.

3. FE-COMP-AUTHURL-012's vi.spyOn(URL, 'createObjectURL') returned the
   same vi.fn() instance set in setup.ts, accumulating calls from all
   prior tests in the file (1+8+7+6=22 instead of 6). Added mockClear()
   immediately after the spy setup to reset the count.
This commit is contained in:
jubnl
2026-04-07 22:51:19 +02:00
parent 9e23766b51
commit d8da0fffa5
3 changed files with 13 additions and 17 deletions
+8 -10
View File
@@ -334,10 +334,14 @@ describe('API client interceptors', () => {
// ── backupApi.download ───────────────────────────────────────────────────────
it('FE-API-013: backupApi.download creates a temp anchor and clicks it', async () => {
const createObjectURL = vi.fn(() => 'blob:mock-url');
const revokeObjectURL = vi.fn();
Object.defineProperty(URL, 'createObjectURL', { writable: true, value: createObjectURL });
Object.defineProperty(URL, 'revokeObjectURL', { writable: true, value: revokeObjectURL });
// backupApi.download uses native fetch (not axios), so mock it directly to
// avoid jsdom/MSW interception differences across environments.
const blob = new Blob(['zip-bytes'], { type: 'application/zip' });
vi.spyOn(globalThis, 'fetch').mockResolvedValueOnce(
new Response(blob, { status: 200 })
);
const createObjectURL = vi.spyOn(URL, 'createObjectURL').mockReturnValue('blob:mock-url');
const revokeObjectURL = vi.spyOn(URL, 'revokeObjectURL').mockImplementation(() => {});
// Spy on createElement to intercept the anchor click
const originalCreate = document.createElement.bind(document);
@@ -350,12 +354,6 @@ describe('API client interceptors', () => {
return el;
});
server.use(
http.get('/api/backup/download/backup.zip', () => {
return new HttpResponse(new Blob(['zip-bytes'], { type: 'application/zip' }), { status: 200 });
})
);
await expect(backupApi.download('backup.zip')).resolves.toBeUndefined();
expect(createObjectURL).toHaveBeenCalled();
expect(revokeObjectURL).toHaveBeenCalled();