diff --git a/renovate.json b/renovate.json index 8446f969c..b7ea1a645 100644 --- a/renovate.json +++ b/renovate.json @@ -81,7 +81,6 @@ "@hocuspocus/provider", "@hocuspocus/server", "@react-pdf/renderer", - "fetch-mock", "node", "node-fetch", "react-resizable-panels", diff --git a/src/frontend/apps/impress/package.json b/src/frontend/apps/impress/package.json index 6508e74f1..b287167f8 100644 --- a/src/frontend/apps/impress/package.json +++ b/src/frontend/apps/impress/package.json @@ -98,7 +98,7 @@ "cross-env": "10.1.0", "dotenv": "17.4.2", "eslint-plugin-docs": "*", - "fetch-mock": "9.11.0", + "fetch-mock": "12.6.0", "jsdom": "29.1.1", "node-fetch": "2.7.0", "prettier": "3.9.5", diff --git a/src/frontend/apps/impress/src/api/__tests__/fetchApi.test.tsx b/src/frontend/apps/impress/src/api/__tests__/fetchApi.test.tsx index 2ac1dd1f5..f0b0e54a6 100644 --- a/src/frontend/apps/impress/src/api/__tests__/fetchApi.test.tsx +++ b/src/frontend/apps/impress/src/api/__tests__/fetchApi.test.tsx @@ -5,23 +5,27 @@ import { fetchAPI } from '@/api'; describe('fetchAPI', () => { beforeEach(() => { - fetchMock.restore(); + fetchMock.hardReset(); + fetchMock.mockGlobal(); }); it('adds correctly the basename', () => { - fetchMock.mock('http://test.jest/api/v1.0/some/url', 200); + fetchMock.route('http://test.jest/api/v1.0/some/url', 200); void fetchAPI('some/url'); - expect(fetchMock.lastUrl()).toEqual('http://test.jest/api/v1.0/some/url'); + expect(fetchMock.callHistory.lastCall()?.url).toEqual( + 'http://test.jest/api/v1.0/some/url', + ); }); it('adds the credentials automatically', () => { - fetchMock.mock('http://test.jest/api/v1.0/some/url', 200); + fetchMock.route('http://test.jest/api/v1.0/some/url', 200); - void fetchAPI('some/url', { body: 'some body' }); + void fetchAPI('some/url', { method: 'POST', body: 'some body' }); - expect(fetchMock.lastOptions()).toEqual({ + expect(fetchMock.callHistory.lastCall()?.args[1]).toEqual({ + method: 'POST', body: 'some body', credentials: 'include', headers: { @@ -31,19 +35,21 @@ describe('fetchAPI', () => { }); it('check the versioning', () => { - fetchMock.mock('http://test.jest/api/v2.0/some/url', 200); + fetchMock.route('http://test.jest/api/v2.0/some/url', 200); void fetchAPI('some/url', {}, '2.0'); - expect(fetchMock.lastUrl()).toEqual('http://test.jest/api/v2.0/some/url'); + expect(fetchMock.callHistory.lastCall()?.url).toEqual( + 'http://test.jest/api/v2.0/some/url', + ); }); it('removes Content-Type header when withoutContentType is true', async () => { - fetchMock.mock('http://test.jest/api/v1.0/some/url', 200); + fetchMock.route('http://test.jest/api/v1.0/some/url', 200); await fetchAPI('some/url', { withoutContentType: true }); - const options = fetchMock.lastOptions(); + const options = fetchMock.callHistory.lastCall()?.options; expect(options?.headers).not.toHaveProperty('Content-Type'); }); }); diff --git a/src/frontend/apps/impress/src/features/auth/__tests__/UserReconciliation.test.tsx b/src/frontend/apps/impress/src/features/auth/__tests__/UserReconciliation.test.tsx index 43b18bd94..59fb47ea0 100644 --- a/src/frontend/apps/impress/src/features/auth/__tests__/UserReconciliation.test.tsx +++ b/src/frontend/apps/impress/src/features/auth/__tests__/UserReconciliation.test.tsx @@ -13,7 +13,8 @@ vi.mock('../assets/mail-check-filled.svg', () => ({ describe('UserReconciliation', () => { beforeEach(() => { - fetchMock.reset(); + fetchMock.hardReset(); + fetchMock.mockGlobal(); }); ['active', 'inactive'].forEach((type) => { @@ -34,7 +35,7 @@ describe('UserReconciliation', () => { ); await waitFor(() => { - expect(fetchMock.calls().length).toBe(1); + expect(fetchMock.callHistory.calls().length).toBe(1); }); expect( @@ -58,7 +59,7 @@ describe('UserReconciliation', () => { }); await waitFor(() => { - expect(fetchMock.calls().length).toBe(1); + expect(fetchMock.callHistory.calls().length).toBe(1); }); expect( diff --git a/src/frontend/apps/impress/src/features/auth/__tests__/utils.test.tsx b/src/frontend/apps/impress/src/features/auth/__tests__/utils.test.tsx index c144b818e..e93b37222 100644 --- a/src/frontend/apps/impress/src/features/auth/__tests__/utils.test.tsx +++ b/src/frontend/apps/impress/src/features/auth/__tests__/utils.test.tsx @@ -21,7 +21,7 @@ const setItemSpy = vi.spyOn(Storage.prototype, 'setItem'); describe('utils', () => { afterEach(() => { vi.clearAllMocks(); - fetchMock.restore(); + fetchMock.hardReset(); mockReplace.mockClear(); setItemSpy.mockClear(); localStorage.clear(); diff --git a/src/frontend/apps/impress/src/features/auth/hooks/__tests__/useAuth.test.tsx b/src/frontend/apps/impress/src/features/auth/hooks/__tests__/useAuth.test.tsx index 809958de9..6c8d61c96 100644 --- a/src/frontend/apps/impress/src/features/auth/hooks/__tests__/useAuth.test.tsx +++ b/src/frontend/apps/impress/src/features/auth/hooks/__tests__/useAuth.test.tsx @@ -45,7 +45,8 @@ const dummyUser = { id: '123', email: 'test@example.com' }; describe('useAuth hook - trackEvent effect', () => { beforeEach(() => { vi.clearAllMocks(); - fetchMock.restore(); + fetchMock.hardReset(); + fetchMock.mockGlobal(); }); test('calls trackEvent when user exists, isSuccess is true, and event was not tracked yet', async () => { diff --git a/src/frontend/apps/impress/src/features/docs/doc-comments/api/__tests__/DocsThreadStore.test.ts b/src/frontend/apps/impress/src/features/docs/doc-comments/api/__tests__/DocsThreadStore.test.ts index c3e06b9fe..284bb21bc 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-comments/api/__tests__/DocsThreadStore.test.ts +++ b/src/frontend/apps/impress/src/features/docs/doc-comments/api/__tests__/DocsThreadStore.test.ts @@ -37,13 +37,14 @@ describe('DocsThreadStore - Orphan Thread Handling', () => { let dispatchEventSpy: ReturnType; beforeEach(() => { - fetchMock.reset(); + fetchMock.hardReset(); + fetchMock.mockGlobal(); dispatchEventSpy = vi .spyOn(document, 'dispatchEvent') .mockReturnValue(true); // Default: empty thread list - fetchMock.get(THREADS_URL, []); + fetchMock.get(THREADS_URL, [], { name: 'threads-list' }); mockAuth = { canSee: true, @@ -55,7 +56,7 @@ describe('DocsThreadStore - Orphan Thread Handling', () => { afterEach(() => { vi.restoreAllMocks(); - fetchMock.reset(); + fetchMock.hardReset(); }); describe('initThreads()', () => { @@ -64,8 +65,9 @@ describe('DocsThreadStore - Orphan Thread Handling', () => { const orphanEmpty = makeThread('orphan-1', []); const orphanNull = makeThread('orphan-2', null); + fetchMock.removeRoute('threads-list'); fetchMock.get(THREADS_URL, [validThread, orphanEmpty, orphanNull], { - overwriteRoutes: true, + name: 'threads-list', }); // initThreads calls deleteThread for orphans fetchMock.delete(threadUrl('orphan-1'), 204); @@ -81,20 +83,24 @@ describe('DocsThreadStore - Orphan Thread Handling', () => { }); it('should delete orphan threads via the API', async () => { + fetchMock.removeRoute('threads-list'); fetchMock.get(THREADS_URL, [makeThread('orphan-1', [])], { - overwriteRoutes: true, + name: 'threads-list', }); fetchMock.delete(threadUrl('orphan-1'), 204); await threadStore.initThreads(); expect( - fetchMock.called(threadUrl('orphan-1'), { method: 'DELETE' }), + fetchMock.callHistory.called(threadUrl('orphan-1'), { + method: 'DELETE', + }), ).toBe(true); }); it('should handle an empty thread list', async () => { - fetchMock.get(THREADS_URL, [], { overwriteRoutes: true }); + fetchMock.removeRoute('threads-list'); + fetchMock.get(THREADS_URL, [], { name: 'threads-list' }); await threadStore.initThreads(); @@ -102,10 +108,11 @@ describe('DocsThreadStore - Orphan Thread Handling', () => { }); it('should throw when the API returns an error', async () => { + fetchMock.removeRoute('threads-list'); fetchMock.get( THREADS_URL, { status: 500, body: {} }, - { overwriteRoutes: true }, + { name: 'threads-list' }, ); await expect(threadStore.initThreads()).rejects.toThrow( @@ -122,9 +129,9 @@ describe('DocsThreadStore - Orphan Thread Handling', () => { await threadStore.refreshThread(threadId); - expect(fetchMock.called(threadUrl(threadId), { method: 'DELETE' })).toBe( - true, - ); + expect( + fetchMock.callHistory.called(threadUrl(threadId), { method: 'DELETE' }), + ).toBe(true); }); it('should store a valid thread (with comments) without deleting it', async () => { @@ -134,16 +141,17 @@ describe('DocsThreadStore - Orphan Thread Handling', () => { await threadStore.refreshThread(threadId); - expect(fetchMock.called(threadUrl(threadId), { method: 'DELETE' })).toBe( - false, - ); + expect( + fetchMock.callHistory.called(threadUrl(threadId), { method: 'DELETE' }), + ).toBe(false); expect(threadStore.getThreads().has(threadId)).toBe(true); }); it('should dispatch Escape and call refreshThreads on 404', async () => { const threadId = 'deleted-thread'; fetchMock.get(threadUrl(threadId), 404); - fetchMock.get(THREADS_URL, [], { overwriteRoutes: true }); + fetchMock.removeRoute('threads-list'); + fetchMock.get(THREADS_URL, [], { name: 'threads-list' }); await threadStore.refreshThread(threadId); @@ -159,11 +167,12 @@ describe('DocsThreadStore - Orphan Thread Handling', () => { const commentId = 'comment-1'; // Seed the store with a thread that has one comment + fetchMock.removeRoute('threads-list'); fetchMock.get( THREADS_URL, [makeThread(threadId, [makeComment(commentId)])], { - overwriteRoutes: true, + name: 'threads-list', }, ); await threadStore.initThreads(); @@ -176,9 +185,9 @@ describe('DocsThreadStore - Orphan Thread Handling', () => { await threadStore.deleteComment({ threadId, commentId }); - expect(fetchMock.called(threadUrl(threadId), { method: 'DELETE' })).toBe( - true, - ); + expect( + fetchMock.callHistory.called(threadUrl(threadId), { method: 'DELETE' }), + ).toBe(true); expect(threadStore.getThreads().has(threadId)).toBe(false); }); @@ -186,6 +195,7 @@ describe('DocsThreadStore - Orphan Thread Handling', () => { const threadId = 'thread-1'; const commentToDelete = 'comment-1'; + fetchMock.removeRoute('threads-list'); fetchMock.get( THREADS_URL, [ @@ -194,7 +204,7 @@ describe('DocsThreadStore - Orphan Thread Handling', () => { makeComment('comment-2'), ]), ], - { overwriteRoutes: true }, + { name: 'threads-list' }, ); await threadStore.initThreads(); @@ -205,9 +215,9 @@ describe('DocsThreadStore - Orphan Thread Handling', () => { await threadStore.deleteComment({ threadId, commentId: commentToDelete }); - expect(fetchMock.called(threadUrl(threadId), { method: 'DELETE' })).toBe( - false, - ); + expect( + fetchMock.callHistory.called(threadUrl(threadId), { method: 'DELETE' }), + ).toBe(false); expect(threadStore.getThreads().has(threadId)).toBe(true); expect(threadStore.getThreads().get(threadId)?.comments).toHaveLength(1); }); diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/api/__tests__/checkDocMediaStatus.test.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/api/__tests__/checkDocMediaStatus.test.tsx index 88660831e..23640c08b 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/api/__tests__/checkDocMediaStatus.test.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/api/__tests__/checkDocMediaStatus.test.tsx @@ -10,11 +10,12 @@ const VALID_URL = 'http://test.jest/media-check/some-file-id'; describe('checkDocMediaStatus', () => { beforeEach(() => { - fetchMock.restore(); + fetchMock.hardReset(); + fetchMock.mockGlobal(); }); afterEach(() => { - fetchMock.restore(); + fetchMock.hardReset(); }); it('returns the response when the status is ready', async () => { @@ -25,7 +26,7 @@ describe('checkDocMediaStatus', () => { const result = await checkDocMediaStatus({ urlMedia: VALID_URL }); expect(result).toEqual({ status: 'ready', file: '/media/some-file.pdf' }); - expect(fetchMock.lastOptions(VALID_URL)).toMatchObject({ + expect(fetchMock.callHistory.lastCall(VALID_URL)?.options).toMatchObject({ credentials: 'include', }); }); @@ -45,7 +46,7 @@ describe('checkDocMediaStatus', () => { checkDocMediaStatus({ urlMedia: 'javascript:alert(1)' }), ).rejects.toMatchObject({ status: 400 }); - expect(fetchMock.calls().length).toBe(0); + expect(fetchMock.callHistory.calls().length).toBe(0); }); it('throws an APIError when the URL does not contain the analyze path', async () => { @@ -53,7 +54,7 @@ describe('checkDocMediaStatus', () => { checkDocMediaStatus({ urlMedia: 'http://test.jest/other/path' }), ).rejects.toMatchObject({ status: 400 }); - expect(fetchMock.calls().length).toBe(0); + expect(fetchMock.callHistory.calls().length).toBe(0); }); it('throws an APIError when the fetch response is not ok', async () => { @@ -82,12 +83,13 @@ describe('checkDocMediaStatus', () => { describe('loopCheckDocMediaStatus', () => { beforeEach(() => { vi.useFakeTimers(); - fetchMock.restore(); + fetchMock.hardReset(); + fetchMock.mockGlobal(); }); afterEach(() => { vi.useRealTimers(); - fetchMock.restore(); + fetchMock.hardReset(); }); it('resolves immediately when the status is already ready', async () => { @@ -101,12 +103,12 @@ describe('loopCheckDocMediaStatus', () => { ); expect(result).toEqual({ status: 'ready', file: '/media/file.pdf' }); - expect(fetchMock.calls().length).toBe(1); + expect(fetchMock.callHistory.calls().length).toBe(1); }); it('retries until the status becomes ready', async () => { let callCount = 0; - fetchMock.mock(VALID_URL, () => { + fetchMock.route(VALID_URL, () => { callCount++; return { status: 200, @@ -129,7 +131,7 @@ describe('loopCheckDocMediaStatus', () => { const result = await promise; expect(result).toEqual({ status: 'ready', file: '/media/file.pdf' }); - expect(fetchMock.calls().length).toBe(3); + expect(fetchMock.callHistory.calls().length).toBe(3); }); it('throws an AbortError immediately when the signal is already aborted', async () => { @@ -142,7 +144,7 @@ describe('loopCheckDocMediaStatus', () => { loopCheckDocMediaStatus(VALID_URL, controller.signal), ).rejects.toMatchObject({ name: 'AbortError' }); - expect(fetchMock.calls().length).toBe(0); + expect(fetchMock.callHistory.calls().length).toBe(0); }); it('stops the loop when the signal is aborted during a sleep', async () => { @@ -158,7 +160,7 @@ describe('loopCheckDocMediaStatus', () => { await rejectExpectation; // Only the first request should have been made - expect(fetchMock.calls().length).toBe(1); + expect(fetchMock.callHistory.calls().length).toBe(1); }); it('rejects when a fetch error occurs', async () => { @@ -172,6 +174,6 @@ describe('loopCheckDocMediaStatus', () => { loopCheckDocMediaStatus(VALID_URL, new AbortController().signal), ).rejects.toMatchObject({ status: 500 }); - expect(fetchMock.calls().length).toBe(1); + expect(fetchMock.callHistory.calls().length).toBe(1); }); }); diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/hook/__tests__/useSaveDoc.test.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/hook/__tests__/useSaveDoc.test.tsx index 878d0ece4..8ed670d6b 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/hook/__tests__/useSaveDoc.test.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/hook/__tests__/useSaveDoc.test.tsx @@ -30,7 +30,8 @@ describe('useSaveDoc', () => { beforeEach(() => { vi.clearAllMocks(); - fetchMock.restore(); + fetchMock.hardReset(); + fetchMock.mockGlobal(); (useRouter as Mock).mockReturnValue({ events: mockRouterEvents, @@ -92,7 +93,7 @@ describe('useSaveDoc', () => { vi.useRealTimers(); await waitFor(() => { - expect(fetchMock.lastCall()?.[0]).toBe( + expect(fetchMock.callHistory.lastCall()?.url).toBe( `http://test.jest/api/v1.0/documents/${docId}/content/`, ); }); @@ -123,7 +124,7 @@ describe('useSaveDoc', () => { }); // Since there are no local changes, no API call should be made - expect(fetchMock.calls().length).toBe(0); + expect(fetchMock.callHistory.calls().length).toBe(0); vi.useRealTimers(); }); diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/hooks/__tests__/useDocTitleUpdate.test.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/hooks/__tests__/useDocTitleUpdate.test.tsx index b6408d680..ac5b8827d 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-management/hooks/__tests__/useDocTitleUpdate.test.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-management/hooks/__tests__/useDocTitleUpdate.test.tsx @@ -22,7 +22,8 @@ vi.mock('@gouvfr-lasuite/ui-kit', async () => ({ describe('useDocTitleUpdate', () => { beforeEach(() => { vi.clearAllMocks(); - fetchMock.restore(); + fetchMock.hardReset(); + fetchMock.mockGlobal(); }); it('should return the correct functions and state', () => { @@ -57,12 +58,12 @@ describe('useDocTitleUpdate', () => { expect(sanitizedTitle).toBe('My Document'); await waitFor(() => { - expect(fetchMock.calls().length).toBe(1); + expect(fetchMock.callHistory.calls().length).toBe(1); }); - expect(fetchMock.calls()[0][0]).toBe( + expect(fetchMock.callHistory.calls()[0].url).toBe( 'http://test.jest/api/v1.0/documents/test-doc-id/', ); - expect(fetchMock.calls()[0][1]).toEqual({ + expect(fetchMock.callHistory.calls()[0].args[1]).toEqual({ method: 'PATCH', credentials: 'include', body: JSON.stringify({ title: 'My Document' }), @@ -90,7 +91,7 @@ describe('useDocTitleUpdate', () => { expect(sanitizedTitle).toBe(''); await waitFor(() => { - expect(fetchMock.calls().length).toBe(0); + expect(fetchMock.callHistory.calls().length).toBe(0); }); }); @@ -114,7 +115,7 @@ describe('useDocTitleUpdate', () => { expect(sanitizedTitle).toBe('Titlewithnewlines'); await waitFor(() => { - expect(fetchMock.calls().length).toBe(1); + expect(fetchMock.callHistory.calls().length).toBe(1); }); }); }); @@ -135,12 +136,12 @@ describe('useDocTitleUpdate', () => { result.current.updateDocEmoji('test-doc-id', 'My Document', '🚀'); await waitFor(() => { - expect(fetchMock.calls().length).toBe(1); + expect(fetchMock.callHistory.calls().length).toBe(1); }); - expect(fetchMock.calls()[0][0]).toBe( + expect(fetchMock.callHistory.calls()[0].url).toBe( 'http://test.jest/api/v1.0/documents/test-doc-id/', ); - expect(fetchMock.calls()[0][1]).toEqual({ + expect(fetchMock.callHistory.calls()[0].args[1]).toEqual({ method: 'PATCH', credentials: 'include', body: JSON.stringify({ title: '🚀 My Document' }), @@ -163,9 +164,9 @@ describe('useDocTitleUpdate', () => { result.current.updateDocEmoji('test-doc-id', '📝 My Document', '🚀'); await waitFor(() => { - expect(fetchMock.calls().length).toBe(1); + expect(fetchMock.callHistory.calls().length).toBe(1); }); - expect(fetchMock.calls()[0][1]).toEqual({ + expect(fetchMock.callHistory.calls()[0].args[1]).toEqual({ method: 'PATCH', credentials: 'include', body: JSON.stringify({ title: '🚀 My Document' }), @@ -188,9 +189,9 @@ describe('useDocTitleUpdate', () => { result.current.updateDocEmoji('test-doc-id', '📝', '🚀'); await waitFor(() => { - expect(fetchMock.calls().length).toBe(1); + expect(fetchMock.callHistory.calls().length).toBe(1); }); - expect(fetchMock.calls()[0][1]).toEqual({ + expect(fetchMock.callHistory.calls()[0].args[1]).toEqual({ method: 'PATCH', credentials: 'include', body: JSON.stringify({ title: '🚀 ' }), @@ -213,9 +214,9 @@ describe('useDocTitleUpdate', () => { result.current.updateDocEmoji('test-doc-id', '', '🚀'); await waitFor(() => { - expect(fetchMock.calls().length).toBe(1); + expect(fetchMock.callHistory.calls().length).toBe(1); }); - expect(fetchMock.calls()[0][1]).toEqual({ + expect(fetchMock.callHistory.calls()[0].args[1]).toEqual({ method: 'PATCH', credentials: 'include', body: JSON.stringify({ title: '🚀 ' }), @@ -244,7 +245,7 @@ describe('useDocTitleUpdate', () => { ); await waitFor(() => { - expect(fetchMock.calls().length).toBe(1); + expect(fetchMock.callHistory.calls().length).toBe(1); }); expect(onSuccess).toHaveBeenCalledWith({ @@ -271,7 +272,7 @@ describe('useDocTitleUpdate', () => { 'Updated Document', ); } catch { - expect(fetchMock.calls().length).toBe(1); + expect(fetchMock.callHistory.calls().length).toBe(1); expect(onError).toHaveBeenCalledWith(new Error('Update failed')); } }); diff --git a/src/frontend/apps/impress/src/features/docs/docs-grid/components/__tests__/DocsGridItemDate.test.tsx b/src/frontend/apps/impress/src/features/docs/docs-grid/components/__tests__/DocsGridItemDate.test.tsx index 8c1d6d42e..21476f301 100644 --- a/src/frontend/apps/impress/src/features/docs/docs-grid/components/__tests__/DocsGridItemDate.test.tsx +++ b/src/frontend/apps/impress/src/features/docs/docs-grid/components/__tests__/DocsGridItemDate.test.tsx @@ -12,7 +12,8 @@ import { DocsGridItemDate } from '../DocsGridItem'; describe('DocsGridItemDate', () => { beforeEach(() => { vi.clearAllMocks(); - fetchMock.restore(); + fetchMock.hardReset(); + fetchMock.mockGlobal(); }); it('should not render date when not on desktop', () => { diff --git a/src/frontend/yarn.lock b/src/frontend/yarn.lock index 78eeabe8c..25eb245f7 100644 --- a/src/frontend/yarn.lock +++ b/src/frontend/yarn.lock @@ -200,7 +200,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.29.7.tgz#6f0237f0f36d2e51c0570a636faed9d2d0efe629" integrity sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg== -"@babel/core@^7.0.0", "@babel/core@^7.18.5", "@babel/core@^7.21.3", "@babel/core@^7.23.9", "@babel/core@^7.24.4", "@babel/core@^7.27.4": +"@babel/core@^7.18.5", "@babel/core@^7.21.3", "@babel/core@^7.23.9", "@babel/core@^7.24.4", "@babel/core@^7.27.4": version "7.29.6" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.29.6.tgz#2f2c2ca1728ae73c9b68ece91d1ae6dee18ff83a" integrity sha512-QdxmAo/ikZqqRGA8s43ww8lcql6naWRvEz0FFrl6MIlc7Gi6TroXnSdWa5U/kq6fzcpqpHesicQxFZIieZbyIA== @@ -6288,6 +6288,11 @@ "@types/express-serve-static-core" "^5.0.0" "@types/serve-static" "^2" +"@types/glob-to-regexp@^0.4.4": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@types/glob-to-regexp/-/glob-to-regexp-0.4.4.tgz#409e71290253203185b1ea8a3d6ea406a4bdc902" + integrity sha512-nDKoaKJYbnn1MZxUY0cA1bPmmgZbg0cTq7Rh13d0KWYNOiKbqoR+2d89SnRPszGh7ROzSwZ/GOjZ4jPbmmZ6Eg== + "@types/hast@^3.0.0", "@types/hast@^3.0.4": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" @@ -8342,11 +8347,6 @@ core-js-compat@^3.43.0: dependencies: browserslist "^4.26.3" -core-js@^3.0.0: - version "3.46.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.46.0.tgz#323a092b96381a9184d0cd49ee9083b2f93373bb" - integrity sha512-vDMm9B0xnqqZ8uSBpZ8sNtRtOdmfShrvT6h2TuQGLs0Is+cR0DYbj/KWP6ALVNbWPpqA/qPLoOuppJN07humpA== - core-js@^3.49.0: version "3.49.0" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.49.0.tgz#8b4d520ac034311fa21aa616f017ada0e0dbbddd" @@ -9658,21 +9658,15 @@ fdir@^6.2.0, fdir@^6.5.0: resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== -fetch-mock@9.11.0: - version "9.11.0" - resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-9.11.0.tgz#371c6fb7d45584d2ae4a18ee6824e7ad4b637a3f" - integrity sha512-PG1XUv+x7iag5p/iNHD4/jdpxL9FtVSqRMUQhPab4hVDt80T1MH5ehzVrL2IdXO9Q2iBggArFvPqjUbHFuI58Q== +fetch-mock@12.6.0: + version "12.6.0" + resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-12.6.0.tgz#e5ed5d471eeeb29478260ce48385dca6773b105e" + integrity sha512-oAy0OqAvjAvduqCeWveBix7LLuDbARPqZZ8ERYtBcCURA3gy7EALA3XWq0tCNxsSg+RmmJqyaeeZlOCV9abv6w== dependencies: - "@babel/core" "^7.0.0" - "@babel/runtime" "^7.0.0" - core-js "^3.0.0" - debug "^4.1.1" - glob-to-regexp "^0.4.0" - is-subset "^0.1.1" - lodash.isequal "^4.5.0" - path-to-regexp "^2.2.1" - querystring "^0.2.0" - whatwg-url "^6.5.0" + "@types/glob-to-regexp" "^0.4.4" + dequal "^2.0.3" + glob-to-regexp "^0.4.1" + regexparam "^3.0.0" fflate@^0.4.8: version "0.4.8" @@ -10054,7 +10048,7 @@ glob-stream@^8.0.3: normalize-path "^3.0.0" streamx "^2.12.5" -glob-to-regexp@^0.4.0: +glob-to-regexp@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== @@ -10833,11 +10827,6 @@ is-string@^1.1.1: call-bound "^1.0.3" has-tostringtag "^1.0.2" -is-subset@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" - integrity sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw== - is-symbol@^1.0.4, is-symbol@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" @@ -12606,11 +12595,6 @@ path-scurry@^2.0.2: lru-cache "^11.0.0" minipass "^7.1.2" -path-to-regexp@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.4.0.tgz#35ce7f333d5616f1c1e1bfe266c3aba2e5b2e704" - integrity sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w== - path-to-regexp@^8.0.0: version "8.4.2" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.4.2.tgz#795c420c4f7ca45c5b887366f622ee0c9852cccd" @@ -13102,11 +13086,6 @@ query-selector-shadow-dom@^1.0.1: resolved "https://registry.yarnpkg.com/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz#1c7b0058eff4881ac44f45d8f84ede32e9a2f349" integrity sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw== -querystring@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd" - integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg== - queue-lit@^1.5.1: version "1.5.2" resolved "https://registry.yarnpkg.com/queue-lit/-/queue-lit-1.5.2.tgz#83c24d4f4764802377b05a6e5c73017caf3f8747" @@ -13672,6 +13651,11 @@ regexp.prototype.flags@^1.5.3, regexp.prototype.flags@^1.5.4: gopd "^1.2.0" set-function-name "^2.0.2" +regexparam@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/regexparam/-/regexparam-3.0.0.tgz#1673e09d41cb7fd41eaafd4040a6aa90daa0a21a" + integrity sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q== + regexpu-core@^6.2.0: version "6.4.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.4.0.tgz#3580ce0c4faedef599eccb146612436b62a176e5" @@ -15768,15 +15752,6 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -whatwg-url@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8" - integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ== - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - whatwg-url@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"