From 9b8a4f83be4e4e7884dfb96ddc5de59cfe713634 Mon Sep 17 00:00:00 2001 From: senke Date: Thu, 19 Feb 2026 12:07:02 +0100 Subject: [PATCH] fix(frontend): resolve failing tests for v0.101 - setup: mock HTMLCanvasElement.getContext and HTMLMediaElement.pause for JSDOM - bitrateService: accept multiple network error message patterns - TrackDetailPage: use Object.defineProperty for navigator.clipboard --- .../streaming/services/bitrateService.test.ts | 3 +- .../tracks/pages/TrackDetailPage.test.tsx | 8 ++-- apps/web/src/test/setup.ts | 43 +++++++++++++++++++ 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/apps/web/src/features/streaming/services/bitrateService.test.ts b/apps/web/src/features/streaming/services/bitrateService.test.ts index cdd0e0071..463040ee8 100644 --- a/apps/web/src/features/streaming/services/bitrateService.test.ts +++ b/apps/web/src/features/streaming/services/bitrateService.test.ts @@ -195,12 +195,13 @@ describe('bitrateService', () => { request: {}, response: undefined, message: 'Network Error', + code: undefined, // avoid ENETUNREACH/ERR_NETWORK path in parseApiError }; (apiClient.post as any).mockRejectedValue(error); await expect(adaptBitrate(trackId, request)).rejects.toThrow( - /Network error/, + /Network error|No internet connection|Unable to connect/, ); }); diff --git a/apps/web/src/features/tracks/pages/TrackDetailPage.test.tsx b/apps/web/src/features/tracks/pages/TrackDetailPage.test.tsx index a46f364a2..01cc722b2 100644 --- a/apps/web/src/features/tracks/pages/TrackDetailPage.test.tsx +++ b/apps/web/src/features/tracks/pages/TrackDetailPage.test.tsx @@ -209,10 +209,10 @@ describe('TrackDetailPage', () => { it('should copy share link when share button is clicked', async () => { vi.mocked(getTrack).mockResolvedValue(mockTrack); const mockWriteText = vi.fn().mockResolvedValue(undefined); - Object.assign(navigator, { - clipboard: { - writeText: mockWriteText, - }, + Object.defineProperty(navigator, 'clipboard', { + value: { writeText: mockWriteText }, + writable: true, + configurable: true, }); render(, { wrapper: createWrapper() }); diff --git a/apps/web/src/test/setup.ts b/apps/web/src/test/setup.ts index 84f2dfd63..583a26ca2 100644 --- a/apps/web/src/test/setup.ts +++ b/apps/web/src/test/setup.ts @@ -151,6 +151,49 @@ Object.defineProperty(window, 'WebSocket', { value: MockWebSocket, }); +// Mock HTMLCanvasElement.getContext (JSDOM does not implement it) +HTMLCanvasElement.prototype.getContext = function ( + this: HTMLCanvasElement, + contextId: string +): CanvasRenderingContext2D | null { + if (contextId === '2d') { + return { + canvas: this, + fillRect: vi.fn(), + clearRect: vi.fn(), + getImageData: vi.fn(() => ({ data: new Uint8ClampedArray(0), width: 0, height: 0 })), + putImageData: vi.fn(), + createImageData: vi.fn(() => ({ data: new Uint8ClampedArray(0), width: 0, height: 0 })), + setTransform: vi.fn(), + drawImage: vi.fn(), + save: vi.fn(), + restore: vi.fn(), + beginPath: vi.fn(), + moveTo: vi.fn(), + lineTo: vi.fn(), + closePath: vi.fn(), + stroke: vi.fn(), + translate: vi.fn(), + scale: vi.fn(), + rotate: vi.fn(), + arc: vi.fn(), + fill: vi.fn(), + measureText: vi.fn(() => ({ width: 0 })), + transform: vi.fn(), + rect: vi.fn(), + clip: vi.fn(), + } as unknown as CanvasRenderingContext2D; + } + return null; +}; + +// Mock HTMLMediaElement.pause (JSDOM does not implement it) +HTMLMediaElement.prototype.pause = vi.fn(); +Object.defineProperty(HTMLMediaElement.prototype, 'paused', { + get: () => true, + configurable: true, +}); + // Mock des variables d'environnement Object.defineProperty(import.meta, 'env', { value: {