From 6e791df1980579b3b651df1ecfcfc75e529f9983 Mon Sep 17 00:00:00 2001 From: Lee Freeman Date: Fri, 6 Dec 2024 16:10:47 +0100 Subject: [PATCH 1/2] feat(react 19): update react to 19, testing libraries deps to latest and fix broken tests --- __tests__/auth-provider.test.tsx | 478 +++++++++--------- __tests__/use-auth.test.tsx | 20 +- __tests__/with-auth0.test.tsx | 6 +- .../with-authentication-required.test.tsx | 10 +- package-lock.json | 303 +++-------- package.json | 16 +- 6 files changed, 341 insertions(+), 492 deletions(-) diff --git a/__tests__/auth-provider.test.tsx b/__tests__/auth-provider.test.tsx index 41ea0832..0ec66d3c 100644 --- a/__tests__/auth-provider.test.tsx +++ b/__tests__/auth-provider.test.tsx @@ -1,18 +1,17 @@ -import '@testing-library/jest-dom/extend-expect'; -import React, { StrictMode, useContext } from 'react'; -import Auth0Context, { - Auth0ContextInterface, - initialContext, -} from '../src/auth0-context'; -import { render, screen, waitFor } from '@testing-library/react'; -import { renderHook, act } from '@testing-library/react-hooks'; import { Auth0Client, GetTokenSilentlyVerboseResponse, } from '@auth0/auth0-spa-js'; +import '@testing-library/jest-dom'; +import { act, render, renderHook, screen, waitFor } from '@testing-library/react'; +import React, { StrictMode, useContext } from 'react'; import pkg from '../package.json'; -import { createWrapper } from './helpers'; import { Auth0Provider, useAuth0 } from '../src'; +import Auth0Context, { + Auth0ContextInterface, + initialContext, +} from '../src/auth0-context'; +import { createWrapper } from './helpers'; const clientMock = jest.mocked(new Auth0Client({ clientId: '', domain: '' })); @@ -23,12 +22,13 @@ describe('Auth0Provider', () => { it('should provide the Auth0Provider result', async () => { const wrapper = createWrapper(); - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - expect(result.current).toBeDefined(); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current).toBeDefined(); + }); }); it('should configure an instance of the Auth0Client', async () => { @@ -42,21 +42,22 @@ describe('Auth0Provider', () => { }, }; const wrapper = createWrapper(opts); - const { waitForNextUpdate } = renderHook(() => useContext(Auth0Context), { + renderHook(() => useContext(Auth0Context), { wrapper, }); - expect(Auth0Client).toHaveBeenCalledWith( - expect.objectContaining({ - clientId: 'foo', - domain: 'bar', - authorizationParams: { - redirect_uri: 'baz', - max_age: 'qux', - extra_param: '__test_extra_param__', - }, - }) - ); - await waitForNextUpdate(); + await waitFor(() => { + expect(Auth0Client).toHaveBeenCalledWith( + expect.objectContaining({ + clientId: 'foo', + domain: 'bar', + authorizationParams: { + redirect_uri: 'baz', + max_age: 'qux', + extra_param: '__test_extra_param__', + }, + }) + ); + }); }); it('should support redirectUri', async () => { @@ -67,20 +68,21 @@ describe('Auth0Provider', () => { redirectUri: 'baz', }; const wrapper = createWrapper(opts); - const { waitForNextUpdate } = renderHook(() => useContext(Auth0Context), { + renderHook(() => useContext(Auth0Context), { wrapper, }); - expect(Auth0Client).toHaveBeenCalledWith( - expect.objectContaining({ - clientId: 'foo', - domain: 'bar', - authorizationParams: { - redirect_uri: 'baz', - }, - }) - ); - expect(warn).toHaveBeenCalled(); - await waitForNextUpdate(); + await waitFor(() => { + expect(Auth0Client).toHaveBeenCalledWith( + expect.objectContaining({ + clientId: 'foo', + domain: 'bar', + authorizationParams: { + redirect_uri: 'baz', + }, + }) + ); + expect(warn).toHaveBeenCalled(); + }); }); it('should support authorizationParams.redirectUri', async () => { @@ -93,20 +95,21 @@ describe('Auth0Provider', () => { }, }; const wrapper = createWrapper(opts); - const { waitForNextUpdate } = renderHook(() => useContext(Auth0Context), { + renderHook(() => useContext(Auth0Context), { wrapper, }); - expect(Auth0Client).toHaveBeenCalledWith( - expect.objectContaining({ - clientId: 'foo', - domain: 'bar', - authorizationParams: { - redirect_uri: 'baz', - }, - }) - ); - expect(warn).toHaveBeenCalled(); - await waitForNextUpdate(); + await waitFor(() => { + expect(Auth0Client).toHaveBeenCalledWith( + expect.objectContaining({ + clientId: 'foo', + domain: 'bar', + authorizationParams: { + redirect_uri: 'baz', + }, + }) + ); + expect(warn).toHaveBeenCalled(); + }); }); it('should pass user agent to Auth0Client', async () => { @@ -115,45 +118,48 @@ describe('Auth0Provider', () => { domain: 'bar', }; const wrapper = createWrapper(opts); - const { waitForNextUpdate } = renderHook(() => useContext(Auth0Context), { + renderHook(() => useContext(Auth0Context), { wrapper, }); - expect(Auth0Client).toHaveBeenCalledWith( - expect.objectContaining({ - auth0Client: { - name: 'auth0-react', - version: pkg.version, - }, - }) - ); - await waitForNextUpdate(); + await waitFor(() => { + expect(Auth0Client).toHaveBeenCalledWith( + expect.objectContaining({ + auth0Client: { + name: 'auth0-react', + version: pkg.version, + }, + }) + ); + }); }); it('should check session when logged out', async () => { const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); - expect(result.current.isLoading).toBe(false); - expect(clientMock.checkSession).toHaveBeenCalled(); - expect(result.current.isAuthenticated).toBe(false); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + expect(clientMock.checkSession).toHaveBeenCalled(); + expect(result.current.isAuthenticated).toBe(false); + }); }); it('should check session when logged in', async () => { const user = { name: '__test_user__' }; clientMock.getUser.mockResolvedValue(user); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(clientMock.checkSession).toHaveBeenCalled(); - expect(result.current.isAuthenticated).toBe(true); - expect(result.current.user).toBe(user); + await waitFor(() => { + expect(clientMock.checkSession).toHaveBeenCalled(); + expect(result.current.isAuthenticated).toBe(true); + expect(result.current.user).toBe(user); + }); }); it('should handle errors when checking session', async () => { @@ -162,16 +168,17 @@ describe('Auth0Provider', () => { error_description: '__test_error_description__', }); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(clientMock.checkSession).toHaveBeenCalled(); - expect(() => { - throw result.current.error; - }).toThrowError('__test_error_description__'); - expect(result.current.isAuthenticated).toBe(false); + await waitFor(() => { + expect(clientMock.checkSession).toHaveBeenCalled(); + expect(() => { + throw result.current.error; + }).toThrowError('__test_error_description__'); + expect(result.current.isAuthenticated).toBe(false); + }); }); it('should handle redirect callback success and clear the url', async () => { @@ -187,12 +194,13 @@ describe('Auth0Provider', () => { appState: undefined, }); const wrapper = createWrapper(); - const { waitForNextUpdate } = renderHook(() => useContext(Auth0Context), { + renderHook(() => useContext(Auth0Context), { wrapper, }); - await waitForNextUpdate(); - expect(clientMock.handleRedirectCallback).toHaveBeenCalled(); - expect(window.location.href).toBe('https://www.example.com/'); + await waitFor(() => { + expect(clientMock.handleRedirectCallback).toHaveBeenCalled(); + expect(window.location.href).toBe('https://www.example.com/'); + }); }); it('should handle redirect callback success and return to app state param', async () => { @@ -208,12 +216,13 @@ describe('Auth0Provider', () => { appState: { returnTo: '/foo' }, }); const wrapper = createWrapper(); - const { waitForNextUpdate } = renderHook(() => useContext(Auth0Context), { + renderHook(() => useContext(Auth0Context), { wrapper, }); - await waitForNextUpdate(); - expect(clientMock.handleRedirectCallback).toHaveBeenCalled(); - expect(window.location.href).toBe('https://www.example.com/foo'); + await waitFor(() => { + expect(clientMock.handleRedirectCallback).toHaveBeenCalled(); + expect(window.location.href).toBe('https://www.example.com/foo'); + }); }); it('should handle redirect callback errors', async () => { @@ -226,15 +235,16 @@ describe('Auth0Provider', () => { new Error('__test_error__') ); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(clientMock.handleRedirectCallback).toHaveBeenCalled(); - expect(() => { - throw result.current.error; - }).toThrowError('__test_error__'); + await waitFor(() => { + expect(clientMock.handleRedirectCallback).toHaveBeenCalled(); + expect(() => { + throw result.current.error; + }).toThrowError('__test_error__'); + }); }); it('should handle redirect and call a custom handler', async () => { @@ -252,11 +262,12 @@ describe('Auth0Provider', () => { const wrapper = createWrapper({ onRedirectCallback, }); - const { waitForNextUpdate } = renderHook(() => useContext(Auth0Context), { + renderHook(() => useContext(Auth0Context), { wrapper, }); - await waitForNextUpdate(); - expect(onRedirectCallback).toHaveBeenCalledWith({ foo: 'bar' }, user); + await waitFor(() => { + expect(onRedirectCallback).toHaveBeenCalledWith({ foo: 'bar' }, user); + }); }); it('should skip redirect callback for non auth0 redirect callback handlers', async () => { @@ -272,72 +283,79 @@ describe('Auth0Provider', () => { const wrapper = createWrapper({ skipRedirectCallback: true, }); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(clientMock.handleRedirectCallback).not.toHaveBeenCalled(); - expect(result.current.isAuthenticated).toBe(true); - expect(result.current.error).not.toBeDefined(); + await waitFor(() => { + expect(clientMock.handleRedirectCallback).not.toHaveBeenCalled(); + expect(result.current.isAuthenticated).toBe(true); + expect(result.current.error).not.toBeDefined(); + }); }); it('should login with a popup', async () => { clientMock.getUser.mockResolvedValue(undefined); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(result.current.user).toBeUndefined(); + await waitFor(() => { + expect(result.current.user).toBeUndefined(); + }); const user = { name: '__test_user__' }; clientMock.getUser.mockResolvedValue(user); act(() => { result.current.loginWithPopup(); }); expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); - expect(result.current.isLoading).toBe(false); - expect(clientMock.loginWithPopup).toHaveBeenCalled(); - expect(result.current.isAuthenticated).toBe(true); - expect(result.current.user).toBe(user); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + expect(clientMock.loginWithPopup).toHaveBeenCalled(); + expect(result.current.isAuthenticated).toBe(true); + expect(result.current.user).toBe(user); + }); }); it('should handle errors when logging in with a popup', async () => { clientMock.getUser.mockResolvedValue(undefined); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(result.current.isAuthenticated).toBe(false); - expect(result.current.user).toBeUndefined(); + await waitFor(() => { + expect(result.current.isAuthenticated).toBe(false); + expect(result.current.user).toBeUndefined(); + }); clientMock.getUser.mockResolvedValue(undefined); clientMock.loginWithPopup.mockRejectedValue(new Error('__test_error__')); act(() => { result.current.loginWithPopup(); }); expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); - expect(result.current.isLoading).toBe(false); - expect(clientMock.loginWithPopup).toHaveBeenCalled(); - expect(result.current.isAuthenticated).toBe(false); - expect(result.current.user).toBeUndefined(); - expect(() => { - throw result.current.error; - }).toThrowError('__test_error__'); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + expect(clientMock.loginWithPopup).toHaveBeenCalled(); + expect(result.current.isAuthenticated).toBe(false); + expect(result.current.user).toBeUndefined(); + expect(() => { + throw result.current.error; + }).toThrowError('__test_error__'); + }); }); it('should provide a login method', async () => { const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(result.current.loginWithRedirect).toBeInstanceOf(Function); + await waitFor(() => { + + expect(result.current.loginWithRedirect).toBeInstanceOf(Function); + }); await result.current.loginWithRedirect({ authorizationParams: { redirect_uri: '__redirect_uri__', @@ -353,12 +371,13 @@ describe('Auth0Provider', () => { it('should provide a login method supporting redirectUri', async () => { const warn = jest.spyOn(console, "warn").mockImplementation(() => undefined); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(result.current.loginWithRedirect).toBeInstanceOf(Function); + await waitFor(() => { + expect(result.current.loginWithRedirect).toBeInstanceOf(Function); + }); await result.current.loginWithRedirect({ redirectUri: '__redirect_uri__', } as never); @@ -373,12 +392,13 @@ describe('Auth0Provider', () => { it('should provide a login method supporting authorizationParams.redirectUri', async () => { const warn = jest.spyOn(console, "warn").mockImplementation(() => undefined); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(result.current.loginWithRedirect).toBeInstanceOf(Function); + await waitFor(() => { + expect(result.current.loginWithRedirect).toBeInstanceOf(Function); + }); await result.current.loginWithRedirect({ authorizationParams: { redirectUri: '__redirect_uri__', @@ -396,12 +416,13 @@ describe('Auth0Provider', () => { const user = { name: '__test_user__' }; clientMock.getUser.mockResolvedValue(user); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(result.current.logout).toBeInstanceOf(Function); + await waitFor(() => { + expect(result.current.logout).toBeInstanceOf(Function); + }); act(() => { result.current.logout(); }); @@ -417,15 +438,16 @@ describe('Auth0Provider', () => { // get logout to return a Promise to simulate async cache. clientMock.logout.mockResolvedValue(); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(result.current.isAuthenticated).toBe(true); + await waitFor(() => { + expect(result.current.isAuthenticated).toBe(true); + }); await act(async () => { // eslint-disable-next-line @typescript-eslint/no-empty-function - await result.current.logout({ openUrl: async () => {} }); + await result.current.logout({ openUrl: async () => { } }); }); expect(result.current.isAuthenticated).toBe(false); }); @@ -440,12 +462,13 @@ describe('Auth0Provider', () => { logoutSpy(); }); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(result.current.isAuthenticated).toBe(true); + await waitFor(() => { + expect(result.current.isAuthenticated).toBe(true); + }); await act(async () => { await result.current.logout(); }); @@ -456,33 +479,36 @@ describe('Auth0Provider', () => { const user = { name: '__test_user__' }; clientMock.getUser.mockResolvedValue(user); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(result.current.isAuthenticated).toBe(true); - expect(result.current.user).toBe(user); + await waitFor(() => { + expect(result.current.isAuthenticated).toBe(true); + expect(result.current.user).toBe(user); + }); act(() => { result.current.logout({ openUrl: false }); }); expect(clientMock.logout).toHaveBeenCalledWith({ openUrl: false, }); - await waitForNextUpdate(); - expect(result.current.isAuthenticated).toBe(false); - expect(result.current.user).toBeUndefined(); + await waitFor(() => { + expect(result.current.isAuthenticated).toBe(false); + expect(result.current.user).toBeUndefined(); + }); }); it('should provide a getAccessTokenSilently method', async () => { clientMock.getTokenSilently.mockResolvedValue('token'); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - expect(result.current.getAccessTokenSilently).toBeInstanceOf(Function); + await waitFor(() => { + expect(result.current.getAccessTokenSilently).toBeInstanceOf(Function); + }); await act(async () => { const token = await result.current.getAccessTokenSilently(); expect(token).toBe('token'); @@ -499,12 +525,10 @@ describe('Auth0Provider', () => { }; (clientMock.getTokenSilently as jest.Mock).mockResolvedValue(tokenResponse); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - await act(async () => { const token = await result.current.getAccessTokenSilently({ detailedResponse: true, @@ -517,11 +541,10 @@ describe('Auth0Provider', () => { it('should normalize errors from getAccessTokenSilently method', async () => { clientMock.getTokenSilently.mockRejectedValue(new ProgressEvent('error')); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); await act(async () => { await expect(result.current.getAccessTokenSilently).rejects.toThrowError( 'Get access token failed' @@ -532,11 +555,10 @@ describe('Auth0Provider', () => { it('should call getAccessTokenSilently in the scope of the Auth0 client', async () => { clientMock.getTokenSilently.mockReturnThis(); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); await act(async () => { const returnedThis = await result.current.getAccessTokenSilently(); @@ -548,13 +570,13 @@ describe('Auth0Provider', () => { clientMock.getTokenSilently.mockReturnThis(); clientMock.getUser.mockResolvedValue({ name: 'foo' }); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - - expect(result.current.user?.name).toEqual('foo'); + await waitFor(async () => { + expect(result.current.user?.name).toEqual('foo'); + }); clientMock.getUser.mockResolvedValue({ name: 'bar' }); await act(async () => { await result.current.getAccessTokenSilently(); @@ -566,13 +588,14 @@ describe('Auth0Provider', () => { clientMock.getTokenSilently.mockReturnThis(); clientMock.getUser.mockResolvedValue({ name: 'foo' }); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.isAuthenticated).toBeTruthy(); + }); - expect(result.current.isAuthenticated).toBeTruthy(); clientMock.getTokenSilently.mockRejectedValue({ error: 'login_required' }); clientMock.getUser.mockResolvedValue(undefined); await act(async () => { @@ -588,32 +611,34 @@ describe('Auth0Provider', () => { const userObject = { name: 'foo' }; clientMock.getUser.mockResolvedValue(userObject); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - - const prevUser = result.current.user; - clientMock.getUser.mockResolvedValue(userObject); - await act(async () => { - await result.current.getAccessTokenSilently(); + await waitFor(async () => { + const prevUser = result.current.user; + clientMock.getUser.mockResolvedValue(userObject); + await act(async () => { + await result.current.getAccessTokenSilently(); + }); + expect(result.current.user).toBe(prevUser); }); - expect(result.current.user).toBe(prevUser); }); it('should not update getAccessTokenSilently after auth state change', async () => { clientMock.getTokenSilently.mockReturnThis(); clientMock.getUser.mockResolvedValue({ name: 'foo' }); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - const memoized = result.current.getAccessTokenSilently; - expect(result.current.user?.name).toEqual('foo'); - clientMock.getUser.mockResolvedValue({ name: 'bar' }); + let memoized + await waitFor(async () => { + memoized = result.current.getAccessTokenSilently; + expect(result.current.user?.name).toEqual('foo'); + clientMock.getUser.mockResolvedValue({ name: 'bar' }); + }); await act(async () => { await result.current.getAccessTokenSilently(); }); @@ -637,11 +662,10 @@ describe('Auth0Provider', () => { it('should provide a getAccessTokenWithPopup method', async () => { clientMock.getTokenWithPopup.mockResolvedValue('token'); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); expect(result.current.getAccessTokenWithPopup).toBeInstanceOf(Function); await act(async () => { const token = await result.current.getAccessTokenWithPopup(); @@ -653,11 +677,10 @@ describe('Auth0Provider', () => { it('should call getAccessTokenWithPopup in the scope of the Auth0 client', async () => { clientMock.getTokenWithPopup.mockReturnThis(); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); await act(async () => { const returnedThis = await result.current.getAccessTokenWithPopup(); expect(returnedThis).toStrictEqual(clientMock); @@ -668,11 +691,10 @@ describe('Auth0Provider', () => { clientMock.getTokenSilently.mockReturnThis(); clientMock.getUser.mockResolvedValue({ name: 'foo' }); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); const prevUser = result.current.user; clientMock.getUser.mockResolvedValue({ name: 'foo' }); @@ -686,13 +708,14 @@ describe('Auth0Provider', () => { clientMock.getTokenSilently.mockReturnThis(); clientMock.getUser.mockResolvedValue({ name: 'foo' }); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.isAuthenticated).toBeTruthy(); + }); - expect(result.current.isAuthenticated).toBeTruthy(); clientMock.getTokenWithPopup.mockRejectedValueOnce({ error: 'login_required', }); @@ -710,28 +733,27 @@ describe('Auth0Provider', () => { const userObject = { name: 'foo' }; clientMock.getUser.mockResolvedValue(userObject); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - - const prevState = result.current; - clientMock.getUser.mockResolvedValue(userObject); - await act(async () => { - await result.current.getAccessTokenWithPopup(); + await waitFor(async () => { + const prevState = result.current; + clientMock.getUser.mockResolvedValue(userObject); + await act(async () => { + await result.current.getAccessTokenWithPopup(); + }); + expect(result.current).toBe(prevState); }); - expect(result.current).toBe(prevState); }); it('should normalize errors from getAccessTokenWithPopup method', async () => { clientMock.getTokenWithPopup.mockRejectedValue(new ProgressEvent('error')); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); await act(async () => { await expect(result.current.getAccessTokenWithPopup).rejects.toThrowError( 'Get access token failed' @@ -758,13 +780,16 @@ describe('Auth0Provider', () => { __raw: '__test_raw_token__', }); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); + expect(result.current.getIdTokenClaims).toBeInstanceOf(Function); - const claims = await result.current.getIdTokenClaims(); + let claims; + await act(async () => { + claims = await result.current.getIdTokenClaims(); + }) expect(clientMock.getIdTokenClaims).toHaveBeenCalled(); expect(claims).toStrictEqual({ claim: '__test_claim__', @@ -774,14 +799,15 @@ describe('Auth0Provider', () => { it('should memoize the getIdTokenClaims method', async () => { const wrapper = createWrapper(); - const { waitForNextUpdate, result, rerender } = renderHook( + const { result, rerender } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - const memoized = result.current.getIdTokenClaims; - rerender(); - expect(result.current.getIdTokenClaims).toBe(memoized); + await waitFor(() => { + const memoized = result.current.getIdTokenClaims; + rerender(); + expect(result.current.getIdTokenClaims).toBe(memoized); + }); }); it('should provide a handleRedirectCallback method', async () => { @@ -789,11 +815,10 @@ describe('Auth0Provider', () => { appState: { redirectUri: '/' }, }); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); expect(result.current.handleRedirectCallback).toBeInstanceOf(Function); await act(async () => { const response = await result.current.handleRedirectCallback(); @@ -809,11 +834,10 @@ describe('Auth0Provider', () => { it('should call handleRedirectCallback in the scope of the Auth0 client', async () => { clientMock.handleRedirectCallback.mockReturnThis(); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); await act(async () => { const returnedThis = await result.current.handleRedirectCallback(); expect(returnedThis).toStrictEqual(clientMock); @@ -824,11 +848,10 @@ describe('Auth0Provider', () => { clientMock.handleRedirectCallback.mockReturnThis(); clientMock.getUser.mockResolvedValue({ name: 'foo' }); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); const prevUser = result.current.user; clientMock.getUser.mockResolvedValue({ name: 'foo' }); @@ -842,13 +865,13 @@ describe('Auth0Provider', () => { clientMock.handleRedirectCallback.mockReturnThis(); clientMock.getUser.mockResolvedValue({ name: 'foo' }); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - - expect(result.current.isAuthenticated).toBeTruthy(); + await waitFor(async () => { + expect(result.current.isAuthenticated).toBeTruthy(); + }); clientMock.handleRedirectCallback.mockRejectedValueOnce({ error: 'login_required', }); @@ -866,18 +889,19 @@ describe('Auth0Provider', () => { const userObject = { name: 'foo' }; clientMock.getUser.mockResolvedValue(userObject); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - - const prevState = result.current; - clientMock.getUser.mockResolvedValue(userObject); - await act(async () => { - await result.current.handleRedirectCallback(); + await waitFor(async () => { + const prevState = result.current; + clientMock.getUser.mockResolvedValue(userObject); + await act(async () => { + await result.current.handleRedirectCallback(); + }); + expect(result.current).toBe(prevState); }); - expect(result.current).toBe(prevState); + }); it('should normalize errors from handleRedirectCallback method', async () => { @@ -885,11 +909,10 @@ describe('Auth0Provider', () => { new ProgressEvent('error') ); const wrapper = createWrapper(); - const { waitForNextUpdate, result } = renderHook( + const { result } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); await act(async () => { await expect(result.current.handleRedirectCallback).rejects.toThrowError( 'Get access token failed' @@ -921,16 +944,15 @@ describe('Auth0Provider', () => { clientMock.getTokenSilently.mockReturnThis(); clientMock.getUser.mockResolvedValue({ name: 'foo' }); const wrapper = createWrapper(); - const { waitForNextUpdate, result, rerender } = renderHook( + const { result, rerender } = renderHook( () => useContext(Auth0Context), { wrapper } ); - await waitForNextUpdate(); - const memoized = result.current; - - rerender(); - - expect(result.current).toBe(memoized); + await waitFor(() => { + const memoized = result.current; + rerender(); + expect(result.current).toBe(memoized); + }); }); it('should only handle redirect callback once', async () => { diff --git a/__tests__/use-auth.test.tsx b/__tests__/use-auth.test.tsx index 481484b5..b188757a 100644 --- a/__tests__/use-auth.test.tsx +++ b/__tests__/use-auth.test.tsx @@ -1,18 +1,18 @@ +import { act, renderHook, waitFor } from '@testing-library/react'; import React from 'react'; +import { Auth0ContextInterface, initialContext } from '../src/auth0-context'; import useAuth0 from '../src/use-auth0'; -import { act, renderHook } from '@testing-library/react-hooks'; import { createWrapper } from './helpers'; -import { Auth0ContextInterface, initialContext } from '../src/auth0-context'; describe('useAuth0', () => { it('should provide the auth context', async () => { const wrapper = createWrapper(); const { - result: { current }, - waitForNextUpdate, + result: { current } } = renderHook(() => useAuth0(), { wrapper }); - await waitForNextUpdate(); - expect(current).toBeDefined(); + await waitFor(() => { + expect(current).toBeDefined(); + }); }); it('should throw with no provider', () => { @@ -42,10 +42,10 @@ describe('useAuth0', () => { const wrapper = createWrapper({ context }); const { result: { current }, - waitForNextUpdate, } = renderHook(() => useAuth0(context), { wrapper }); - await waitForNextUpdate(); - expect(current).toBeDefined(); - expect(current.loginWithRedirect).not.toThrowError(); + await waitFor(() => { + expect(current).toBeDefined(); + expect(current.loginWithRedirect).not.toThrowError(); + }); }); }); diff --git a/__tests__/with-auth0.test.tsx b/__tests__/with-auth0.test.tsx index 2d781418..6ea18ebf 100644 --- a/__tests__/with-auth0.test.tsx +++ b/__tests__/with-auth0.test.tsx @@ -1,8 +1,8 @@ -import '@testing-library/jest-dom/extend-expect'; -import React, { Component } from 'react'; -import withAuth0, { WithAuth0Props } from '../src/with-auth0'; +import '@testing-library/jest-dom'; import { render, screen } from '@testing-library/react'; +import React, { Component } from 'react'; import { Auth0ContextInterface, initialContext } from '../src/auth0-context'; +import withAuth0, { WithAuth0Props } from '../src/with-auth0'; describe('withAuth0', () => { it('should wrap a class component', () => { diff --git a/__tests__/with-authentication-required.test.tsx b/__tests__/with-authentication-required.test.tsx index 49d7bee4..7d69456a 100644 --- a/__tests__/with-authentication-required.test.tsx +++ b/__tests__/with-authentication-required.test.tsx @@ -1,10 +1,10 @@ -import '@testing-library/jest-dom/extend-expect'; -import React from 'react'; -import withAuthenticationRequired from '../src/with-authentication-required'; -import { render, screen, waitFor, act } from '@testing-library/react'; import { Auth0Client, User } from '@auth0/auth0-spa-js'; -import Auth0Provider from '../src/auth0-provider'; +import '@testing-library/jest-dom'; +import { act, render, screen, waitFor } from '@testing-library/react'; +import React from 'react'; import { Auth0ContextInterface, initialContext } from '../src/auth0-context'; +import Auth0Provider from '../src/auth0-provider'; +import withAuthenticationRequired from '../src/with-authentication-required'; import { defer } from './helpers'; const mockClient = jest.mocked(new Auth0Client({ clientId: '', domain: '' })); diff --git a/package-lock.json b/package-lock.json index d99c9be5..d251771c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,9 +15,9 @@ "@rollup/plugin-node-resolve": "^15.0.1", "@rollup/plugin-replace": "^5.0.1", "@rollup/plugin-terser": "^0.4.3", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^14.0.0", - "@testing-library/react-hooks": "^7.0.2", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.0.0", "@types/jest": "^29.2.3", "@types/react": "^18.2.27", "@types/react-dom": "^18.2.12", @@ -35,9 +35,9 @@ "oidc-provider": "^8.0.0", "prettier": "^2.8.1", "pretty-quick": "^3.1.3", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-test-renderer": "^18.2.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-test-renderer": "^19.0.0", "rollup": "^3.7.0", "rollup-plugin-analyzer": "^4.0.0", "rollup-plugin-delete": "^2.0.0", @@ -53,8 +53,8 @@ "typescript": "^4.9.4" }, "peerDependencies": { - "react": "^16.11.0 || ^17 || ^18", - "react-dom": "^16.11.0 || ^17 || ^18" + "react": "^16.11.0 || ^17 || ^18|| ^19", + "react-dom": "^16.11.0 || ^17 || ^18 || ^19" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -67,9 +67,9 @@ } }, "node_modules/@adobe/css-tools": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.2.tgz", - "integrity": "sha512-DA5a1C0gD/pLOvhv33YMrbf2FK3oUzwNl9oOJqE4XVjuEtt6XIakRcsd7eLiOSPkp1kTRQGICTA8cKra/vFbjw==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.1.tgz", + "integrity": "sha512-12WGKBQzjUAI4ayyF4IAtfw2QR/IDoqk6jTddXDhtYTJF9ASmoE1zst7cVtP0aL/F1jUJL5r+JxKXKEgHNbEUQ==", "dev": true }, "node_modules/@ampproject/remapping": { @@ -1707,31 +1707,22 @@ } }, "node_modules/@testing-library/dom": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz", - "integrity": "sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^5.0.1", - "aria-query": "5.1.3", + "aria-query": "5.3.0", "chalk": "^4.1.0", "dom-accessibility-api": "^0.5.9", "lz-string": "^1.5.0", "pretty-format": "^27.0.2" }, "engines": { - "node": ">=14" - } - }, - "node_modules/@testing-library/dom/node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" + "node": ">=18" } }, "node_modules/@testing-library/dom/node_modules/chalk": { @@ -1750,100 +1741,55 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@testing-library/dom/node_modules/deep-equal": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", - "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.1", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/@testing-library/jest-dom": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", - "integrity": "sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz", + "integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==", "dev": true, "dependencies": { - "@adobe/css-tools": "^4.0.1", - "@babel/runtime": "^7.9.2", - "@types/testing-library__jest-dom": "^5.9.1", + "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", "chalk": "^3.0.0", "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", "redent": "^3.0.0" }, "engines": { - "node": ">=8", + "node": ">=14", "npm": ">=6", "yarn": ">=1" } }, - "node_modules/@testing-library/react": { - "version": "14.3.1", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.3.1.tgz", - "integrity": "sha512-H99XjUhWQw0lTgyMN05W3xQG1Nh4lq574D8keFf1dDoNTJgp66VbJozRaczoF+wsiaPJNt/TcnfpLGufGxSrZQ==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^9.0.0", - "@types/react-dom": "^18.0.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true }, - "node_modules/@testing-library/react-hooks": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-7.0.2.tgz", - "integrity": "sha512-dYxpz8u9m4q1TuzfcUApqi8iFfR6R0FaMbr2hjZJy1uC8z+bO/K4v8Gs9eogGKYQop7QsrBTFkv/BCF7MzD2Cg==", + "node_modules/@testing-library/react": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.1.0.tgz", + "integrity": "sha512-Q2ToPvg0KsVL0ohND9A3zLJWcOXXcO8IDu3fj11KhNt0UlCWyFyvnCIBkd12tidB2lkiVRG8VFqdhcqhqnAQtg==", "dev": true, "dependencies": { - "@babel/runtime": "^7.12.5", - "@types/react": ">=16.9.0", - "@types/react-dom": ">=16.9.0", - "@types/react-test-renderer": ">=16.9.0", - "react-error-boundary": "^3.1.0" + "@babel/runtime": "^7.12.5" }, "engines": { - "node": ">=12" + "node": ">=18" }, "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0", - "react-test-renderer": ">=16.9.0" + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { - "react-dom": { + "@types/react": { "optional": true }, - "react-test-renderer": { + "@types/react-dom": { "optional": true } } @@ -1858,9 +1804,9 @@ } }, "node_modules/@types/aria-query": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", - "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true }, "node_modules/@types/babel__core": { @@ -2056,15 +2002,6 @@ "@types/react": "*" } }, - "node_modules/@types/react-test-renderer": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.0.1.tgz", - "integrity": "sha512-LjEF+jTUCjzd+Qq4eWqsmZvEWPA/l4L0my+YWN5US8Fo3wZOMiyrpBshHDFbkO8usjdO1B430mEWNU/i1MF7Qg==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -2101,15 +2038,6 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, - "node_modules/@types/testing-library__jest-dom": { - "version": "5.14.9", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz", - "integrity": "sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==", - "dev": true, - "dependencies": { - "@types/jest": "*" - } - }, "node_modules/@types/tough-cookie": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", @@ -4891,26 +4819,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/es-iterator-helpers": { "version": "1.0.14", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.14.tgz", @@ -6601,22 +6509,6 @@ "node": ">= 0.4" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -9787,22 +9679,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -10917,44 +10793,24 @@ } }, "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", + "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", "dev": true, - "dependencies": { - "loose-envify": "^1.1.0" - }, "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", + "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", "dev": true, "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" + "scheduler": "^0.25.0" }, "peerDependencies": { - "react": "^18.2.0" - } - }, - "node_modules/react-error-boundary": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz", - "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - }, - "peerDependencies": { - "react": ">=16.13.1" + "react": "^19.0.0" } }, "node_modules/react-is": { @@ -10963,37 +10819,23 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, - "node_modules/react-shallow-renderer": { - "version": "16.15.0", - "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", - "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", - "dev": true, - "dependencies": { - "object-assign": "^4.1.1", - "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependencies": { - "react": "^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/react-test-renderer": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.2.0.tgz", - "integrity": "sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-19.0.0.tgz", + "integrity": "sha512-oX5u9rOQlHzqrE/64CNr0HB0uWxkCQmZNSfozlYvwE71TLVgeZxVf0IjouGEr1v7r1kcDifdAJBeOhdhxsG/DA==", "dev": true, "dependencies": { - "react-is": "^18.2.0", - "react-shallow-renderer": "^16.15.0", - "scheduler": "^0.23.0" + "react-is": "^19.0.0", + "scheduler": "^0.25.0" }, "peerDependencies": { - "react": "^18.2.0" + "react": "^19.0.0" } }, "node_modules/react-test-renderer/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz", + "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==", "dev": true }, "node_modules/readable-stream": { @@ -11707,13 +11549,10 @@ } }, "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "dev": true, - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", + "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", + "dev": true }, "node_modules/seek-bzip": { "version": "1.0.6", @@ -12078,18 +11917,6 @@ "node": ">= 0.8" } }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/stream-combiner": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", diff --git a/package.json b/package.json index 31b4a725..297737f7 100644 --- a/package.json +++ b/package.json @@ -54,9 +54,9 @@ "@rollup/plugin-node-resolve": "^15.0.1", "@rollup/plugin-replace": "^5.0.1", "@rollup/plugin-terser": "^0.4.3", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^14.0.0", - "@testing-library/react-hooks": "^7.0.2", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.0.0", "@types/jest": "^29.2.3", "@types/react": "^18.2.27", "@types/react-dom": "^18.2.12", @@ -74,9 +74,9 @@ "oidc-provider": "^8.0.0", "prettier": "^2.8.1", "pretty-quick": "^3.1.3", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-test-renderer": "^18.2.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-test-renderer": "^19.0.0", "rollup": "^3.7.0", "rollup-plugin-analyzer": "^4.0.0", "rollup-plugin-delete": "^2.0.0", @@ -92,8 +92,8 @@ "typescript": "^4.9.4" }, "peerDependencies": { - "react": "^16.11.0 || ^17 || ^18", - "react-dom": "^16.11.0 || ^17 || ^18" + "react": "^16.11.0 || ^17 || ^18|| ^19", + "react-dom": "^16.11.0 || ^17 || ^18 || ^19" }, "dependencies": { "@auth0/auth0-spa-js": "^2.1.3" From 0d87378233c7ee82f3912173c6dce1613ac724f8 Mon Sep 17 00:00:00 2001 From: Lee Freeman Date: Fri, 6 Dec 2024 16:19:03 +0100 Subject: [PATCH 2/2] chore: update @types/react and @types/react-dom to version 19.0.0 --- package-lock.json | 30 ++++++++---------------------- package.json | 4 ++-- 2 files changed, 10 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index d251771c..be7532cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,8 +19,8 @@ "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.0.0", "@types/jest": "^29.2.3", - "@types/react": "^18.2.27", - "@types/react-dom": "^18.2.12", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", "@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/parser": "^5.45.0", "browserstack-cypress-cli": "^1.19.1", @@ -1976,27 +1976,19 @@ "integrity": "sha512-mlaecDKQ7rIZrYD7iiKNdzFb6e/qD5I9U1rAhq+Fd+DWvYVs+G2kv74UFHmSOlg5+i/vF3XxuR522V4u8BqO+Q==", "dev": true }, - "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", - "dev": true - }, "node_modules/@types/react": { - "version": "18.2.64", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.64.tgz", - "integrity": "sha512-MlmPvHgjj2p3vZaxbQgFUQFvD8QiZwACfGqEdDSWou5yISWxDQ4/74nCAwsUiX7UFLKZz3BbVSPj+YxeoGGCfg==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.0.tgz", + "integrity": "sha512-MY3oPudxvMYyesqs/kW1Bh8y9VqSmf+tzqw3ae8a9DZW68pUe3zAdHeI1jc6iAysuRdACnVknHP8AhwD4/dxtg==", "dev": true, "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.2.18", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", - "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.1.tgz", + "integrity": "sha512-hljHij7MpWPKF6u5vojuyfV0YA4YURsQG7KT6SzV0Zs2BXAtgdTxG6A229Ub/xiWV4w/7JL8fi6aAyjshH4meA==", "dev": true, "dependencies": { "@types/react": "*" @@ -2008,12 +2000,6 @@ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "dev": true }, - "node_modules/@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", - "dev": true - }, "node_modules/@types/semver": { "version": "7.5.1", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.1.tgz", diff --git a/package.json b/package.json index 297737f7..37ff343b 100644 --- a/package.json +++ b/package.json @@ -58,8 +58,8 @@ "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.0.0", "@types/jest": "^29.2.3", - "@types/react": "^18.2.27", - "@types/react-dom": "^18.2.12", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", "@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/parser": "^5.45.0", "browserstack-cypress-cli": "^1.19.1",