diff --git a/__fixtures__/test-project/api/db/migrations/20220101120000_create_post_user/migration.sql b/__fixtures__/test-project/api/db/migrations/20230118153725_create_post_user/migration.sql similarity index 100% rename from __fixtures__/test-project/api/db/migrations/20220101120000_create_post_user/migration.sql rename to __fixtures__/test-project/api/db/migrations/20230118153725_create_post_user/migration.sql diff --git a/__fixtures__/test-project/api/db/migrations/20220102120000_create_contact/migration.sql b/__fixtures__/test-project/api/db/migrations/20230118153843_create_contact/migration.sql similarity index 100% rename from __fixtures__/test-project/api/db/migrations/20220102120000_create_contact/migration.sql rename to __fixtures__/test-project/api/db/migrations/20230118153843_create_contact/migration.sql diff --git a/__fixtures__/test-project/web/package.json b/__fixtures__/test-project/web/package.json index 5ee0a9648f29..13ad823aacbb 100644 --- a/__fixtures__/test-project/web/package.json +++ b/__fixtures__/test-project/web/package.json @@ -19,8 +19,8 @@ "@redwoodjs/web": "3.2.0", "humanize-string": "2.1.0", "prop-types": "15.8.1", - "react": "17.0.2", - "react-dom": "17.0.2" + "react": "18.2.0", + "react-dom": "18.2.0" }, "devDependencies": { "autoprefixer": "^10.4.13", diff --git a/__fixtures__/test-project/web/src/pages/ProfilePage/ProfilePage.tsx b/__fixtures__/test-project/web/src/pages/ProfilePage/ProfilePage.tsx index 43848b6f6c13..39abea2fa43d 100644 --- a/__fixtures__/test-project/web/src/pages/ProfilePage/ProfilePage.tsx +++ b/__fixtures__/test-project/web/src/pages/ProfilePage/ProfilePage.tsx @@ -24,14 +24,18 @@ const ProfilePage = () => { - {Object.keys(currentUser).map((key) => { - return ( - - {key.toUpperCase()} - {currentUser[key]} - - ) - })} + + ID + {currentUser.id} + + + ROLES + {currentUser.roles} + + + EMAIL + {currentUser.email} + isAuthenticated diff --git a/babel.config.js b/babel.config.js index df2764c24df2..78e835b51e24 100644 --- a/babel.config.js +++ b/babel.config.js @@ -38,9 +38,47 @@ module.exports = { }, ], '@babel/preset-react', + /** + * TODO(pc): w/ '@babel/plugin-transform-typescript' in plugins now, is '@babel/typescript' preset still needed? + * + * - Plugins run before Presets. + * - Plugin ordering is first to last. + * - Preset ordering is reversed (last to first). + * + * https://babeljs.io/docs/en/plugins/#plugin-ordering + */ '@babel/typescript', ], plugins: [ + /** + * NOTE + * Needed for react@18 + * + * ``` + * ✖ @redwoodjs/router:build + * SyntaxError: /code/redwood/packages/router/src/location.tsx: TypeScript 'declare' fields must first be transformed by @babel/plugin-transform-typescript. + * If you have already enabled that plugin (or '@babel/preset-typescript'), make sure that it runs before any plugin related to additional class features: + * - @babel/plugin-proposal-class-properties + * - @babel/plugin-proposal-private-methods + * - @babel/plugin-proposal-decorators + * 25 | // When prerendering, there might be more than one level of location + * 26 | // providers. Use the values from the one above. + * > 27 | declare context: React.ContextType + * | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * 28 | HISTORY_LISTENER_ID: string | undefined = undefined + * 29 | + * 30 | state = { + * ``` + */ + [ + '@babel/plugin-transform-typescript', + { + allowDeclareFields: true, + /** needed in order build `packages/web/dist/entry/index.js` */ + isTSX: true, + allExtensions: true, + }, + ], /** * NOTE * Experimental decorators are used in `@redwoodjs/structure`. diff --git a/docs/docs/custom-web-index.md b/docs/docs/custom-web-index.md index 97262a50285d..a713be6282bf 100644 --- a/docs/docs/custom-web-index.md +++ b/docs/docs/custom-web-index.md @@ -19,7 +19,7 @@ yarn rw setup custom-web-index This generates a file named `index.js` in `web/src` that looks like this: ```jsx title="web/src/index.js" -import ReactDOM from 'react-dom' +import { hydrateRoot, createRoot } from 'react-dom/client' import App from './App' /** @@ -31,9 +31,11 @@ import App from './App' const rootElement = document.getElementById('redwood-app') if (rootElement.hasChildNodes()) { - ReactDOM.hydrate(, rootElement) + hydrateRoot(redwoodAppElement, ) } else { - ReactDOM.render(, rootElement) + const root = createRoot(redwoodAppElement) + root.render() +} ``` This's actually the same file Redwood uses [internally](https://github.com/redwoodjs/redwood/blob/main/packages/web/src/entry/index.js). diff --git a/package.json b/package.json index ed7f6bd46034..768000aa461b 100644 --- a/package.json +++ b/package.json @@ -27,12 +27,6 @@ "test-ci": "lerna run test --concurrency 2 -- --colors --maxWorkers" }, "resolutions": { - "@types/react": "17.0.53", - "microtime": "3.1.1", - "prop-types": "15.8.1", - "react": "17.0.2", - "react-dom": "17.0.2", - "typescript": "4.7.4", "vscode-languageserver": "6.1.1", "vscode-languageserver-protocol": "3.15.3", "vscode-languageserver-textdocument": "1.0.8", @@ -61,8 +55,7 @@ "@playwright/test": "1.29.2", "@replayio/playwright": "0.3.15", "@testing-library/jest-dom": "5.16.5", - "@testing-library/react": "12.1.5", - "@testing-library/react-hooks": "8.0.1", + "@testing-library/react": "13.4.0", "@testing-library/user-event": "14.4.3", "@tsd/typescript": "4.9.4", "@types/babel__generator": "7.6.4", diff --git a/packages/auth-providers/auth0/web/package.json b/packages/auth-providers/auth0/web/package.json index fd151b6ee1cd..6f5f3d2dcf86 100644 --- a/packages/auth-providers/auth0/web/package.json +++ b/packages/auth-providers/auth0/web/package.json @@ -30,10 +30,9 @@ "@auth0/auth0-spa-js": "1.22.6", "@babel/cli": "7.20.7", "@babel/core": "7.20.12", - "@testing-library/react-hooks": "8.0.1", - "@types/react": "17.0.53", + "@types/react": "18.0.27", "jest": "29.3.1", - "react": "17.0.2", + "react": "18.2.0", "typescript": "4.7.4" }, "peerDependencies": { diff --git a/packages/auth-providers/auth0/web/src/__tests__/auth0.test.tsx b/packages/auth-providers/auth0/web/src/__tests__/auth0.test.tsx index 4e4eed120b98..79c390734338 100644 --- a/packages/auth-providers/auth0/web/src/__tests__/auth0.test.tsx +++ b/packages/auth-providers/auth0/web/src/__tests__/auth0.test.tsx @@ -4,7 +4,7 @@ import type { GetTokenSilentlyVerboseResponse, User, } from '@auth0/auth0-spa-js' -import { renderHook, act } from '@testing-library/react-hooks' +import { renderHook, act } from '@testing-library/react' import { CurrentUser } from '@redwoodjs/auth' diff --git a/packages/auth-providers/azureActiveDirectory/web/package.json b/packages/auth-providers/azureActiveDirectory/web/package.json index a2227577c717..af9778d6b67c 100644 --- a/packages/auth-providers/azureActiveDirectory/web/package.json +++ b/packages/auth-providers/azureActiveDirectory/web/package.json @@ -30,11 +30,10 @@ "@azure/msal-browser": "2.32.2", "@babel/cli": "7.20.7", "@babel/core": "7.20.12", - "@testing-library/react-hooks": "8.0.1", "@types/netlify-identity-widget": "1.9.3", - "@types/react": "17.0.53", + "@types/react": "18.0.27", "jest": "29.3.1", - "react": "17.0.2", + "react": "18.2.0", "typescript": "4.7.4" }, "peerDependencies": { diff --git a/packages/auth-providers/azureActiveDirectory/web/src/__tests__/azureActiveDirectory.test.tsx b/packages/auth-providers/azureActiveDirectory/web/src/__tests__/azureActiveDirectory.test.tsx index cb3b6a0bffc2..e60866f10837 100644 --- a/packages/auth-providers/azureActiveDirectory/web/src/__tests__/azureActiveDirectory.test.tsx +++ b/packages/auth-providers/azureActiveDirectory/web/src/__tests__/azureActiveDirectory.test.tsx @@ -3,7 +3,7 @@ import type { PublicClientApplication as AzureActiveDirectoryClient, RedirectRequest, } from '@azure/msal-browser' -import { renderHook, act } from '@testing-library/react-hooks' +import { renderHook, act } from '@testing-library/react' import { CurrentUser } from '@redwoodjs/auth' diff --git a/packages/auth-providers/clerk/web/package.json b/packages/auth-providers/clerk/web/package.json index 9fada5ba18eb..2db131560476 100644 --- a/packages/auth-providers/clerk/web/package.json +++ b/packages/auth-providers/clerk/web/package.json @@ -31,10 +31,9 @@ "@babel/core": "7.20.12", "@clerk/clerk-react": "3.5.1", "@clerk/types": "2.21.0", - "@testing-library/react-hooks": "8.0.1", - "@types/react": "17.0.53", + "@types/react": "18.0.27", "jest": "29.3.1", - "react": "17.0.2", + "react": "18.2.0", "typescript": "4.7.4" }, "peerDependencies": { diff --git a/packages/auth-providers/clerk/web/src/__tests__/clerk.test.tsx b/packages/auth-providers/clerk/web/src/__tests__/clerk.test.tsx index 68f8502c7351..826b5186dd22 100644 --- a/packages/auth-providers/clerk/web/src/__tests__/clerk.test.tsx +++ b/packages/auth-providers/clerk/web/src/__tests__/clerk.test.tsx @@ -4,7 +4,7 @@ import { EmailAddressResource, ActiveSessionResource, } from '@clerk/types' -import { renderHook, act } from '@testing-library/react-hooks' +import { renderHook, act } from '@testing-library/react' import { CurrentUser } from '@redwoodjs/auth' diff --git a/packages/auth-providers/dbAuth/web/package.json b/packages/auth-providers/dbAuth/web/package.json index 2a170064eac1..6c3777272717 100644 --- a/packages/auth-providers/dbAuth/web/package.json +++ b/packages/auth-providers/dbAuth/web/package.json @@ -32,10 +32,9 @@ "@babel/cli": "7.20.7", "@babel/core": "7.20.12", "@simplewebauthn/typescript-types": "6.2.1", - "@testing-library/react-hooks": "8.0.1", - "@types/react": "17.0.53", + "@types/react": "18.0.27", "jest": "29.3.1", - "react": "17.0.2", + "react": "18.2.0", "typescript": "4.7.4" }, "gitHead": "3905ed045508b861b495f8d5630d76c7a157d8f1" diff --git a/packages/auth-providers/dbAuth/web/src/__tests__/dbAuth.test.ts b/packages/auth-providers/dbAuth/web/src/__tests__/dbAuth.test.ts index 5dd5bb37f201..f6be7466faf5 100644 --- a/packages/auth-providers/dbAuth/web/src/__tests__/dbAuth.test.ts +++ b/packages/auth-providers/dbAuth/web/src/__tests__/dbAuth.test.ts @@ -1,4 +1,4 @@ -import { renderHook, act } from '@testing-library/react-hooks' +import { renderHook, act } from '@testing-library/react' import { CurrentUser } from '@redwoodjs/auth' diff --git a/packages/auth-providers/firebase/web/package.json b/packages/auth-providers/firebase/web/package.json index c37ead11d9bd..fb962be8e1d0 100644 --- a/packages/auth-providers/firebase/web/package.json +++ b/packages/auth-providers/firebase/web/package.json @@ -29,11 +29,10 @@ "devDependencies": { "@babel/cli": "7.20.7", "@babel/core": "7.20.12", - "@testing-library/react-hooks": "8.0.1", - "@types/react": "17.0.53", + "@types/react": "18.0.27", "firebase": "9.16.0", "jest": "29.3.1", - "react": "17.0.2", + "react": "18.2.0", "typescript": "4.7.4" }, "peerDependencies": { diff --git a/packages/auth-providers/firebase/web/src/__tests__/firebase.test.tsx b/packages/auth-providers/firebase/web/src/__tests__/firebase.test.tsx index b39dc0c9709e..eec862b29d55 100644 --- a/packages/auth-providers/firebase/web/src/__tests__/firebase.test.tsx +++ b/packages/auth-providers/firebase/web/src/__tests__/firebase.test.tsx @@ -1,4 +1,4 @@ -import { renderHook, act } from '@testing-library/react-hooks' +import { renderHook, act } from '@testing-library/react' import type FirebaseAuthNamespace from 'firebase/auth' import { User, OperationType, OAuthProvider, Auth } from 'firebase/auth' diff --git a/packages/auth-providers/netlify/web/package.json b/packages/auth-providers/netlify/web/package.json index 86cfe4a6fb39..da1cd9cb9db7 100644 --- a/packages/auth-providers/netlify/web/package.json +++ b/packages/auth-providers/netlify/web/package.json @@ -29,11 +29,10 @@ "devDependencies": { "@babel/cli": "7.20.7", "@babel/core": "7.20.12", - "@testing-library/react-hooks": "8.0.1", "@types/netlify-identity-widget": "1.9.3", - "@types/react": "17.0.53", + "@types/react": "18.0.27", "jest": "29.3.1", - "react": "17.0.2", + "react": "18.2.0", "typescript": "4.7.4" }, "peerDependencies": { diff --git a/packages/auth-providers/netlify/web/src/__tests__/netlify.test.tsx b/packages/auth-providers/netlify/web/src/__tests__/netlify.test.tsx index bd6a0532746d..25a6f79cde80 100644 --- a/packages/auth-providers/netlify/web/src/__tests__/netlify.test.tsx +++ b/packages/auth-providers/netlify/web/src/__tests__/netlify.test.tsx @@ -1,4 +1,4 @@ -import { renderHook, act } from '@testing-library/react-hooks' +import { renderHook, act } from '@testing-library/react' import * as NetlifyIdentityNS from 'netlify-identity-widget' import { CurrentUser } from '@redwoodjs/auth' diff --git a/packages/auth-providers/supabase/web/package.json b/packages/auth-providers/supabase/web/package.json index 52a39aae0a63..97a69eff4c18 100644 --- a/packages/auth-providers/supabase/web/package.json +++ b/packages/auth-providers/supabase/web/package.json @@ -29,10 +29,9 @@ "@babel/cli": "7.20.7", "@babel/core": "7.20.12", "@supabase/supabase-js": "1.35.7", - "@testing-library/react-hooks": "8.0.1", - "@types/react": "17.0.53", + "@types/react": "18.0.27", "jest": "29.3.1", - "react": "17.0.2", + "react": "18.2.0", "typescript": "4.7.4" }, "peerDependencies": { diff --git a/packages/auth-providers/supabase/web/src/__tests__/supabase.test.tsx b/packages/auth-providers/supabase/web/src/__tests__/supabase.test.tsx index 7b9b81d2dbdd..36edf9430bb5 100644 --- a/packages/auth-providers/supabase/web/src/__tests__/supabase.test.tsx +++ b/packages/auth-providers/supabase/web/src/__tests__/supabase.test.tsx @@ -1,5 +1,5 @@ import type { SupabaseClient, User } from '@supabase/supabase-js' -import { renderHook, act } from '@testing-library/react-hooks' +import { renderHook, act } from '@testing-library/react' import { CurrentUser } from '@redwoodjs/auth' diff --git a/packages/auth-providers/supertokens/web/package.json b/packages/auth-providers/supertokens/web/package.json index 1f0d339e97bc..c9f2cbd1b51f 100644 --- a/packages/auth-providers/supertokens/web/package.json +++ b/packages/auth-providers/supertokens/web/package.json @@ -29,10 +29,9 @@ "devDependencies": { "@babel/cli": "7.20.7", "@babel/core": "7.20.12", - "@testing-library/react-hooks": "8.0.1", - "@types/react": "17.0.53", + "@types/react": "18.0.27", "jest": "29.3.1", - "react": "17.0.2", + "react": "18.2.0", "typescript": "4.7.4" }, "peerDependencies": { diff --git a/packages/auth-providers/supertokens/web/src/__tests__/supertokens.test.tsx b/packages/auth-providers/supertokens/web/src/__tests__/supertokens.test.tsx index 77d6fdb26986..f235f80f1924 100644 --- a/packages/auth-providers/supertokens/web/src/__tests__/supertokens.test.tsx +++ b/packages/auth-providers/supertokens/web/src/__tests__/supertokens.test.tsx @@ -1,4 +1,4 @@ -import { renderHook, act } from '@testing-library/react-hooks' +import { renderHook, act } from '@testing-library/react' import { CurrentUser } from '@redwoodjs/auth' diff --git a/packages/auth/package.json b/packages/auth/package.json index f15ce5882c84..a08beebd43b7 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -24,14 +24,13 @@ "dependencies": { "@babel/runtime-corejs3": "7.20.13", "core-js": "3.27.2", - "react": "17.0.2" + "react": "18.2.0" }, "devDependencies": { "@babel/cli": "7.20.7", "@babel/core": "7.20.12", "@testing-library/jest-dom": "5.16.5", - "@testing-library/react": "12.1.5", - "@testing-library/react-hooks": "8.0.1", + "@testing-library/react": "13.4.0", "jest": "29.3.1", "msw": "0.49.3", "typescript": "4.7.4" diff --git a/packages/auth/src/__tests__/AuthProvider.test.tsx b/packages/auth/src/__tests__/AuthProvider.test.tsx index 115d56709044..24eadacd6ea7 100644 --- a/packages/auth/src/__tests__/AuthProvider.test.tsx +++ b/packages/auth/src/__tests__/AuthProvider.test.tsx @@ -9,7 +9,7 @@ import { waitFor, configure, } from '@testing-library/react' -import { renderHook, act } from '@testing-library/react-hooks' +import { renderHook, act } from '@testing-library/react' import '@testing-library/jest-dom/extend-expect' import { graphql } from 'msw' import { setupServer } from 'msw/node' @@ -711,9 +711,7 @@ describe('Custom auth provider', () => { ) - await waitFor(() => mockedForgotPassword.mock.calls.length === 1) - - expect.assertions(1) + await waitFor(() => expect(mockedForgotPassword).toBeCalledWith('username')) }) test('proxies resetPassword() calls to client', async () => { diff --git a/packages/create-redwood-app/template/web/package.json b/packages/create-redwood-app/template/web/package.json index bf290661ac8e..505d93d018d4 100644 --- a/packages/create-redwood-app/template/web/package.json +++ b/packages/create-redwood-app/template/web/package.json @@ -17,7 +17,7 @@ "@redwoodjs/router": "3.2.0", "@redwoodjs/web": "3.2.0", "prop-types": "15.8.1", - "react": "17.0.2", - "react-dom": "17.0.2" + "react": "18.2.0", + "react-dom": "18.2.0" } } diff --git a/packages/forms/package.json b/packages/forms/package.json index 2f1fab714715..5e108ce4155f 100644 --- a/packages/forms/package.json +++ b/packages/forms/package.json @@ -32,22 +32,22 @@ "@babel/core": "7.20.12", "@testing-library/dom": "8.20.0", "@testing-library/jest-dom": "5.16.5", - "@testing-library/react": "12.1.5", + "@testing-library/react": "13.4.0", "@testing-library/user-event": "14.4.3", "@types/pascalcase": "1.0.1", - "@types/react": "17.0.53", - "@types/react-dom": "17.0.18", + "@types/react": "18.0.27", + "@types/react-dom": "18.0.10", "@types/testing-library__jest-dom": "5.14.5", "graphql": "16.6.0", "jest": "29.3.1", "nodemon": "2.0.20", - "react": "17.0.2", - "react-dom": "17.0.2", + "react": "18.2.0", + "react-dom": "18.2.0", "typescript": "4.7.4" }, "peerDependencies": { "graphql": "16.6.0", - "react": "17.0.2" + "react": "18.2.0" }, "gitHead": "3905ed045508b861b495f8d5630d76c7a157d8f1" } diff --git a/packages/prerender/package.json b/packages/prerender/package.json index 013a4fb2dcca..1a42d4005e62 100644 --- a/packages/prerender/package.json +++ b/packages/prerender/package.json @@ -46,8 +46,8 @@ "typescript": "4.7.4" }, "peerDependencies": { - "react": "17.0.2", - "react-dom": "17.0.2" + "react": "18.2.0", + "react-dom": "18.2.0" }, "externals": { "react": "react", diff --git a/packages/router/package.json b/packages/router/package.json index b4ff4c1d5495..4c3ea44aaa66 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -30,16 +30,16 @@ "devDependencies": { "@babel/cli": "7.20.7", "@babel/core": "7.20.12", - "@types/react": "17.0.53", - "@types/react-dom": "17.0.18", + "@types/react": "18.0.27", + "@types/react-dom": "18.0.10", "jest": "29.3.1", - "react": "17.0.2", - "react-dom": "17.0.2", + "react": "18.2.0", + "react-dom": "18.2.0", "typescript": "4.7.4" }, "peerDependencies": { - "react": "17.0.2", - "react-dom": "17.0.2" + "react": "18.2.0", + "react-dom": "18.2.0" }, "gitHead": "3905ed045508b861b495f8d5630d76c7a157d8f1" } diff --git a/packages/router/src/__tests__/router.test.tsx b/packages/router/src/__tests__/router.test.tsx index 4b7b8055514e..8f32891d7f7d 100644 --- a/packages/router/src/__tests__/router.test.tsx +++ b/packages/router/src/__tests__/router.test.tsx @@ -43,6 +43,10 @@ import { useParams } from '../params' import { Set } from '../Set' import { Spec } from '../util' +/** running into intermittent test timeout behavior in https://github.com/redwoodjs/redwood/pull/4992 + attempting to work around by bumping the default timeout of 5000 */ +const timeoutForFlakeyAsyncTests = 8000 + type UnknownAuthContextInterface = AuthContextInterface< unknown, unknown, @@ -284,209 +288,253 @@ describe('slow imports', () => { mockDelay = 0 }) - test('Basic home page', async () => { - const screen = render() - await waitFor(() => screen.getByText('HomePagePlaceholder')) - await waitFor(() => screen.getByText('Home Page')) - }) - - test('Navigation', async () => { - const screen = render() - // First we should render an empty page while waiting for pageLoadDelay to - // pass - expect(screen.container).toBeEmptyDOMElement() - - // Then we should render whileLoadingPage - await waitFor(() => screen.getByText('HomePagePlaceholder')) - - // Finally we should render the actual page - await waitFor(() => screen.getByText('Home Page')) - - act(() => navigate('/about')) - - // Now after navigating we should keep rendering the previous page until - // the new page has loaded, or until pageLoadDelay has passed. This - // ensures we don't show a "white flash", i.e. render an empty page, while - // navigating the page - expect(screen.container).not.toBeEmptyDOMElement() - await waitFor(() => screen.getByText('Home Page')) - expect(screen.container).not.toBeEmptyDOMElement() - - // As for HomePage we first render the placeholder... - await waitFor(() => screen.getByText('AboutPagePlaceholder')) - // ...and then the actual page - await waitFor(() => screen.getByText('About Page')) - }) - - test('Redirect page', async () => { - act(() => navigate('/redirect')) - const screen = render() - await waitFor(() => screen.getByText('RedirectPagePlaceholder')) - await waitFor(() => screen.getByText('About Page')) - }) - - test('Redirect route', async () => { - const screen = render() - await waitFor(() => screen.getByText('HomePagePlaceholder')) - await waitFor(() => screen.getByText('Home Page')) - act(() => navigate('/redirect2/redirected?q=cue')) - await waitFor(() => screen.getByText('ParamPagePlaceholder')) - await waitFor(() => screen.getByText('param redirectedcue')) - }) - - test('Private page when not authenticated', async () => { - act(() => navigate('/private')) - const screen = render() - await waitFor(() => { - expect( - screen.queryByText('PrivatePagePlaceholder') - ).not.toBeInTheDocument() - expect(screen.queryByText('Private Page')).not.toBeInTheDocument() - expect(screen.queryByText('LoginPagePlaceholder')).toBeInTheDocument() - }) - await waitFor(() => screen.getByText('Login Page')) - }) - - test('Private page when authenticated', async () => { - act(() => navigate('/private')) - const screen = render() - - await waitFor(() => screen.getByText('PrivatePagePlaceholder')) - await waitFor(() => screen.getByText('Private Page')) - await waitFor(() => { - expect(screen.queryByText('Login Page')).not.toBeInTheDocument() - }) - }) - - test('Private page when authenticated but does not have the role', async () => { - act(() => navigate('/private_with_role')) - const screen = render() - - await waitFor(() => { - expect( - screen.queryByText('PrivatePagePlaceholder') - ).not.toBeInTheDocument() - expect(screen.queryByText('Private Page')).not.toBeInTheDocument() - expect(screen.queryByText('LoginPagePlaceholder')).toBeInTheDocument() - }) - await waitFor(() => screen.getByText('Login Page')) - }) - - test('Private page when authenticated but does have the role', async () => { - act(() => navigate('/private_with_role')) - const screen = render() - - await waitFor(() => { - expect( - screen.queryByText('PrivatePagePlaceholder') - ).not.toBeInTheDocument() - expect(screen.queryByText('Private Page')).toBeInTheDocument() - }) - }) - - test('useLocation', async () => { - act(() => navigate('/location')) - const screen = render() - await waitFor(() => screen.getByText('Location Page')) - await waitFor(() => screen.getByText('/location')) - - act(() => navigate('/about')) - // After navigating we will keep rendering the previous page for 100 ms, - // (which is our configured delay) before rendering the "whileLoading" - // page. - await waitFor(() => screen.getByText('Location Page')) - - // Because we're still rendering the LocationPage, the pathname returned - // by useLocation should still be /location - // But because of a limitation in our implementation, that's currently - // not the case. - // TODO: Update this test when #3779 is fixed. (It'll start failing) - await waitFor(() => screen.getByText('/about')) - // await waitFor(() => screen.getByText('/location')) - - // And then we'll render the placeholder... - await waitFor(() => screen.getByText('AboutPagePlaceholder')) - // ...followed by the actual page - await waitFor(() => screen.getByText('About Page')) - }) - - test('path params should never be empty', async () => { - const PathParamPage = ({ value }) => { - expect(value).not.toBeFalsy() - return

{value}

- } - - const TestRouter = () => ( - - - - - ) - - act(() => navigate('/path-param-test/test_value')) - const screen = render() + test( + 'Basic home page', + async () => { + const screen = render() + await waitFor(() => screen.getByText('HomePagePlaceholder')) + await waitFor(() => screen.getByText('Home Page')) + }, + timeoutForFlakeyAsyncTests + ) - // First we render the path parameter value "test_value" - await waitFor(() => screen.getByText('test_value')) + test( + 'Navigation', + async () => { + const screen = render() + // First we should render an empty page while waiting for pageLoadDelay to + // pass + expect(screen.container).toBeEmptyDOMElement() + + // Then we should render whileLoadingPage + await waitFor(() => screen.getByText('HomePagePlaceholder')) + + // Finally we should render the actual page + await waitFor(() => screen.getByText('Home Page')) + + act(() => navigate('/about')) + + // Now after navigating we should keep rendering the previous page until + // the new page has loaded, or until pageLoadDelay has passed. This + // ensures we don't show a "white flash", i.e. render an empty page, while + // navigating the page + expect(screen.container).not.toBeEmptyDOMElement() + await waitFor(() => screen.getByText('Home Page')) + expect(screen.container).not.toBeEmptyDOMElement() + + // As for HomePage we first render the placeholder... + await waitFor(() => screen.getByText('AboutPagePlaceholder')) + // ...and then the actual page + await waitFor(() => screen.getByText('About Page')) + }, + timeoutForFlakeyAsyncTests + ) - act(() => navigate('/about')) - // After navigating we should keep displaying the old path value... - await waitFor(() => screen.getByText('test_value')) - // ...until we switch over to render the about page loading component... - await waitFor(() => screen.getByText('AboutPagePlaceholder')) - // ...followed by the actual page - await waitFor(() => screen.getByText('About Page')) - }) + test( + 'Redirect page', + async () => { + act(() => navigate('/redirect')) + const screen = render() + await waitFor(() => screen.getByText('RedirectPagePlaceholder')) + await waitFor(() => screen.getByText('About Page')) + }, + timeoutForFlakeyAsyncTests + ) - test('usePageLoadingContext', async () => { - // We want to show a loading indicator if loading pages is taking a long - // time. But at the same time we don't want to show it right away, because - // then there'll be a flash of the loading indicator on every page load. - // So we have a `pageLoadingDelay` delay to control how long it waits - // before showing the loading state (default is 1000 ms). - // - // RW lazy loads pages by default, that's why it could potentially take a - // while to load a page. But during tests we don't do that. So we have to - // fake a delay. That's what `mockDelay` is for. `mockDelay` has to be - // longer than `pageLoadingDelay`, but not too long so the test takes - // longer than it has to, and also not too long so the entire test times - // out. + test( + 'Redirect route', + async () => { + const screen = render() + await waitFor(() => screen.getByText('HomePagePlaceholder')) + await waitFor(() => screen.getByText('Home Page')) + act(() => navigate('/redirect2/redirected?q=cue')) + await waitFor(() => screen.getByText('ParamPagePlaceholder')) + await waitFor(() => screen.getByText('param redirectedcue')) + }, + timeoutForFlakeyAsyncTests + ) - // Had to increase this to make the test pass on Windows - mockDelay = 700 + test( + 'Private page when not authenticated', + async () => { + act(() => navigate('/private')) + const screen = render() + await waitFor(() => { + expect( + screen.queryByText('PrivatePagePlaceholder') + ).not.toBeInTheDocument() + expect(screen.queryByText('Private Page')).not.toBeInTheDocument() + expect(screen.queryByText('LoginPagePlaceholder')).toBeInTheDocument() + }) + await waitFor(() => screen.getByText('Login Page')) + }, + timeoutForFlakeyAsyncTests + ) - // sets pageLoadingDelay={200}. (Default is 1000.) - const screen = render() + test( + 'Private page when authenticated', + async () => { + act(() => navigate('/private')) + const screen = render() + + await waitFor(() => screen.getByText('PrivatePagePlaceholder')) + await waitFor(() => screen.getByText('Private Page')) + await waitFor(() => { + expect(screen.queryByText('Login Page')).not.toBeInTheDocument() + }) + }, + timeoutForFlakeyAsyncTests + ) - act(() => navigate('/page-loading-context')) + test( + 'Private page when authenticated but does not have the role', + async () => { + act(() => navigate('/private_with_role')) + const screen = render() + + await waitFor(() => { + expect( + screen.queryByText('PrivatePagePlaceholder') + ).not.toBeInTheDocument() + expect(screen.queryByText('Private Page')).not.toBeInTheDocument() + expect(screen.queryByText('LoginPagePlaceholder')).toBeInTheDocument() + }) + await waitFor(() => screen.getByText('Login Page')) + }, + timeoutForFlakeyAsyncTests + ) - // 'Page Loading Context Layout' should always be shown - await waitFor(() => screen.getByText('Page Loading Context Layout')) + test( + 'Private page when authenticated but does have the role', + async () => { + act(() => navigate('/private_with_role')) + const screen = render() + + await waitFor(() => { + expect( + screen.queryByText('PrivatePagePlaceholder') + ).not.toBeInTheDocument() + expect(screen.queryByText('Private Page')).toBeInTheDocument() + }) + }, + timeoutForFlakeyAsyncTests + ) - // 'loading in layout...' should only be shown while the page is loading. - // So in this case, for the first 700ms - await waitFor(() => screen.getByText('loading in layout...')) + test( + 'useLocation', + async () => { + act(() => navigate('/location')) + const screen = render() + await waitFor(() => screen.getByText('Location Page')) + await waitFor(() => screen.getByText('/location')) + + act(() => navigate('/about')) + // After navigating we will keep rendering the previous page for 100 ms, + // (which is our configured delay) before rendering the "whileLoading" + // page. + await waitFor(() => screen.getByText('Location Page')) + + // Because we're still rendering the LocationPage, the pathname returned + // by useLocation should still be /location + // But because of a limitation in our implementation, that's currently + // not the case. + // TODO: Update this test when #3779 is fixed. (It'll start failing) + await waitFor(() => screen.getByText('/about')) + // await waitFor(() => screen.getByText('/location')) + + // And then we'll render the placeholder... + await waitFor(() => screen.getByText('AboutPagePlaceholder')) + // ...followed by the actual page + await waitFor(() => screen.getByText('About Page')) + }, + timeoutForFlakeyAsyncTests + ) - // After 700ms 'Page Loading Context Page' should be rendered - await waitFor(() => screen.getByText('Page Loading Context Page')) + test( + 'path params should never be empty', + async () => { + const PathParamPage = ({ value }) => { + expect(value).not.toBeFalsy() + return

{value}

+ } - // This shouldn't show up, because the page shouldn't render before it's - // fully loaded - expect(screen.queryByText('loading in page...')).not.toBeInTheDocument() + const TestRouter = () => ( + + + + + ) + + act(() => navigate('/path-param-test/test_value')) + const screen = render() + + // First we render the path parameter value "test_value" + await waitFor(() => screen.getByText('test_value')) + + act(() => navigate('/about')) + // After navigating we should keep displaying the old path value... + await waitFor(() => screen.getByText('test_value')) + // ...until we switch over to render the about page loading component... + await waitFor(() => screen.getByText('AboutPagePlaceholder')) + // ...followed by the actual page + await waitFor(() => screen.getByText('About Page')) + }, + timeoutForFlakeyAsyncTests + ) - await waitFor(() => screen.getByText('done loading in page')) - await waitFor(() => screen.getByText('done loading in layout')) - }) + test( + 'usePageLoadingContext', + async () => { + // We want to show a loading indicator if loading pages is taking a long + // time. But at the same time we don't want to show it right away, because + // then there'll be a flash of the loading indicator on every page load. + // So we have a `pageLoadingDelay` delay to control how long it waits + // before showing the loading state (default is 1000 ms). + // + // RW lazy loads pages by default, that's why it could potentially take a + // while to load a page. But during tests we don't do that. So we have to + // fake a delay. That's what `mockDelay` is for. `mockDelay` has to be + // longer than `pageLoadingDelay`, but not too long so the test takes + // longer than it has to, and also not too long so the entire test times + // out. + + // Had to increase this to make the test pass on Windows + mockDelay = 700 + + // sets pageLoadingDelay={200}. (Default is 1000.) + const screen = render() + + act(() => navigate('/page-loading-context')) + + // 'Page Loading Context Layout' should always be shown + await waitFor(() => screen.getByText('Page Loading Context Layout')) + + // 'loading in layout...' should only be shown while the page is loading. + // So in this case, for the first 700ms + await waitFor(() => screen.getByText('loading in layout...')) + + // After 700ms 'Page Loading Context Page' should be rendered + await waitFor(() => screen.getByText('Page Loading Context Page')) + + // This shouldn't show up, because the page shouldn't render before it's + // fully loaded + expect(screen.queryByText('loading in page...')).not.toBeInTheDocument() + + await waitFor(() => screen.getByText('done loading in page')) + await waitFor(() => screen.getByText('done loading in layout')) + }, + timeoutForFlakeyAsyncTests + ) }) describe('inits routes and navigates as expected', () => { diff --git a/packages/router/src/__tests__/set.test.tsx b/packages/router/src/__tests__/set.test.tsx index 369d86f725b4..3c73111137e8 100644 --- a/packages/router/src/__tests__/set.test.tsx +++ b/packages/router/src/__tests__/set.test.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { type ReactNode } from 'react' import { render, waitFor } from '@testing-library/react' import '@testing-library/jest-dom/extend-expect' @@ -10,14 +10,14 @@ import { Set } from '../Set' const ChildA = () =>

ChildA

const ChildB = () =>

ChildB

const ChildC = () =>

ChildC

-const GlobalLayout: React.FC = ({ children }) => ( +const GlobalLayout: React.FC<{ children?: ReactNode }> = ({ children }) => (

Global Layout

{children}
This is a footer
) -const CustomWrapper: React.FC = ({ children }) => ( +const CustomWrapper: React.FC<{ children?: ReactNode }> = ({ children }) => (

Custom Wrapper

{children} @@ -89,6 +89,7 @@ test('passes props to wrappers', async () => { interface Props { propOne: string propTwo: string + children?: ReactNode } const PropWrapper: React.FC = ({ children, propOne, propTwo }) => ( diff --git a/packages/router/src/active-route-loader.tsx b/packages/router/src/active-route-loader.tsx index 20b2d4cd20dd..d2a6d2575a72 100644 --- a/packages/router/src/active-route-loader.tsx +++ b/packages/router/src/active-route-loader.tsx @@ -1,6 +1,10 @@ -import React, { useRef, useState, useEffect } from 'react' - -import { unstable_batchedUpdates } from 'react-dom' +import React, { + useRef, + useState, + useEffect, + SetStateAction, + ReactNode, +} from 'react' import { getAnnouncement, getFocus, resetFocus } from './a11yUtils' import { @@ -97,19 +101,17 @@ export const ActiveRouteLoader = ({ // Consumers of the context can show a loading indicator // to signal to the user that something is happening. loadingTimeout.current = setTimeout(() => { - unstable_batchedUpdates(() => { - setLoadingState((loadingState) => ({ - ...loadingState, - [path]: { - page: whileLoadingPage || ArlWhileLoadingNullPage, - specName: '', - state: 'SHOW_LOADING', - location, - }, - })) - setRenderedChildren(children) - setRenderedPath(path) - }) + setLoadingState((loadingState) => ({ + ...loadingState, + [path]: { + page: whileLoadingPage || ArlWhileLoadingNullPage, + specName: '', + state: 'SHOW_LOADING', + location, + }, + })) + setRenderedChildren(children) + setRenderedPath(path) }, delay) // Wait to download and parse the page. @@ -122,26 +124,25 @@ export const ActiveRouteLoader = ({ // Only update all state if we're still interested (i.e. we're still // waiting for the page that just finished loading) if (isMounted() && name === waitingFor.current) { - unstable_batchedUpdates(() => { - setLoadingState((loadingState) => ({ - ...loadingState, - [path]: { - page: module.default, - specName: name, - state: 'DONE', - location, - }, - })) - // `children` could for example be a Set or a Route. Either way the - // just-loaded page will be somewhere in the children tree. But - // children could also be undefined, in which case we'll just render - // the just-loaded page itself. For example, when we render the - // NotFoundPage children will be undefined and the default export in - // `module` will be the NotFoundPage itself. - setRenderedChildren(children ?? module.default) - setRenderedPath(path) - setPageName(name) - }) + setLoadingState((loadingState) => ({ + ...loadingState, + [path]: { + page: module.default, + specName: name, + state: 'DONE', + location, + }, + })) + // `children` could for example be a Set or a Route. Either way the + // just-loaded page will be somewhere in the children tree. But + // children could also be undefined, in which case we'll just render + // the just-loaded page itself. For example, when we render the + // NotFoundPage children will be undefined and the default export in + // `module` will be the NotFoundPage itself. + const renderedChildren = children ?? module.default + setRenderedChildren(renderedChildren as SetStateAction) //FIXME: test this? + setRenderedPath(path) + setPageName(name) } } @@ -149,32 +150,30 @@ export const ActiveRouteLoader = ({ clearLoadingTimeout() startPageLoadTransition(spec, delay) } else { - unstable_batchedUpdates(() => { - // Handle navigating to the same page again, but with different path - // params (i.e. new `location` or route params) - setLoadingState((loadingState) => { - // If path is same, fetch the page again - let existingPage = loadingState[path]?.page - // If path is different, try to find the existing page - if (!existingPage) { - const pageState = Object.values(loadingState).find( - (state) => state?.specName === spec.name - ) - existingPage = pageState?.page - } - return { - ...loadingState, - [path]: { - page: existingPage || ArlNullPage, - specName: spec.name, - state: 'DONE', - location, - }, - } - }) - setRenderedChildren(children) - setRenderedPath(path) + // Handle navigating to the same page again, but with different path + // params (i.e. new `location` or route params) + setLoadingState((loadingState) => { + // If path is same, fetch the page again + let existingPage = loadingState[path]?.page + // If path is different, try to find the existing page + if (!existingPage) { + const pageState = Object.values(loadingState).find( + (state) => state?.specName === spec.name + ) + existingPage = pageState?.page + } + return { + ...loadingState, + [path]: { + page: existingPage || ArlNullPage, + specName: spec.name, + state: 'DONE', + location, + }, + } }) + setRenderedChildren(children) + setRenderedPath(path) } return () => { diff --git a/packages/router/src/location.tsx b/packages/router/src/location.tsx index 9c734fbe7e2b..bccad5cdff37 100644 --- a/packages/router/src/location.tsx +++ b/packages/router/src/location.tsx @@ -25,6 +25,7 @@ class LocationProvider extends React.Component { // When prerendering, there might be more than one level of location // providers. Use the values from the one above. static contextType = LocationContext + declare context: React.ContextType HISTORY_LISTENER_ID: string | undefined = undefined state = { diff --git a/packages/testing/package.json b/packages/testing/package.json index 507ed4c578af..5b53bf82bfe5 100644 --- a/packages/testing/package.json +++ b/packages/testing/package.json @@ -40,15 +40,14 @@ "@storybook/manager-webpack5": "6.5.15", "@storybook/react": "6.5.15", "@testing-library/jest-dom": "5.16.5", - "@testing-library/react": "12.1.5", - "@testing-library/react-hooks": "8.0.1", + "@testing-library/react": "13.4.0", "@testing-library/user-event": "14.4.3", "@types/aws-lambda": "8.10.109", "@types/babel-core": "6.25.7", "@types/jest": "29.2.6", "@types/node": "16.18.11", - "@types/react": "17.0.53", - "@types/react-dom": "17.0.18", + "@types/react": "18.0.27", + "@types/react-dom": "18.0.10", "@types/webpack": "5.28.0", "babel-jest": "29.3.1", "babel-plugin-inline-react-svg": "2.0.1", diff --git a/packages/testing/src/web/customRender.tsx b/packages/testing/src/web/customRender.tsx index dbea63cf3842..f6d353a8fd55 100644 --- a/packages/testing/src/web/customRender.tsx +++ b/packages/testing/src/web/customRender.tsx @@ -1,19 +1,17 @@ import React from 'react' -import { render } from '@testing-library/react' -import type { RenderResult, RenderOptions } from '@testing-library/react' +import { render, renderHook } from '@testing-library/react' import type { + RenderResult, + RenderOptions, RenderHookOptions, RenderHookResult, -} from '@testing-library/react-hooks' -// `@testing-library/react-hooks` is being deprecated -// since the functionality is moving into v13 of `@testing-library/react`. -// But v13 of `@testing-library/react` drops support for React 17, so we can't upgrade just yet. -// We can remove `@testing-library/react-hooks` after upgrading Redwood to React 18. -import { renderHook } from '@testing-library/react-hooks/dom' +} from '@testing-library/react' import { MockProviders } from './MockProviders' +export type CustomRenderHookOptions = RenderHookOptions + export const customRender = ( ui: React.ReactElement, options: RenderOptions = {} @@ -26,8 +24,8 @@ export const customRender = ( export const customRenderHook = ( render: (props: Props) => Result, - options?: RenderHookOptions -): RenderHookResult => { + options?: CustomRenderHookOptions +): RenderHookResult => { return renderHook(render, { wrapper: (props: any) => , ...options, diff --git a/packages/web/package.json b/packages/web/package.json index d74f1a01e92b..4d15f20230c6 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -51,22 +51,22 @@ "@babel/cli": "7.20.7", "@babel/core": "7.20.12", "@testing-library/jest-dom": "5.16.5", - "@testing-library/react": "12.1.5", + "@testing-library/react": "13.4.0", "@types/prop-types": "15.7.5", - "@types/react": "17.0.53", - "@types/react-dom": "17.0.18", + "@types/react": "18.0.27", + "@types/react-dom": "18.0.10", "@types/testing-library__jest-dom": "5.14.5", "jest": "29.3.1", "nodemon": "2.0.20", "prop-types": "15.8.1", - "react": "17.0.2", - "react-dom": "17.0.2", + "react": "18.2.0", + "react-dom": "18.2.0", "typescript": "4.7.4" }, "peerDependencies": { "prop-types": "15.8.1", - "react": "17.0.2", - "react-dom": "17.0.2" + "react": "18.2.0", + "react-dom": "18.2.0" }, "gitHead": "3905ed045508b861b495f8d5630d76c7a157d8f1" } diff --git a/packages/web/src/entry/index.js b/packages/web/src/entry/index.js index 6837340bc6c1..e45fd3b19f35 100644 --- a/packages/web/src/entry/index.js +++ b/packages/web/src/entry/index.js @@ -1,16 +1,17 @@ -import ReactDOM from 'react-dom' +import { hydrateRoot, createRoot } from 'react-dom/client' import App from '~redwood-app-root' /** * When `#redwood-app` isn't empty then it's very likely that you're using * prerendering. So React attaches event listeners to the existing markup * rather than replacing it. - * https://reactjs.org/docs/react-dom.html#hydrate + * https://reactjs.org/docs/react-dom-client.html#hydrateroot */ -const rootElement = document.getElementById('redwood-app') +const redwoodAppElement = document.getElementById('redwood-app') -if (rootElement.children?.length > 0) { - ReactDOM.hydrate(, rootElement) +if (redwoodAppElement.children?.length > 0) { + hydrateRoot(redwoodAppElement, ) } else { - ReactDOM.render(, rootElement) + const root = createRoot(redwoodAppElement) + root.render() } diff --git a/tasks/test-project/codemods/profilePage.js b/tasks/test-project/codemods/profilePage.js index 9aba697730f7..3da4567fa0ca 100644 --- a/tasks/test-project/codemods/profilePage.js +++ b/tasks/test-project/codemods/profilePage.js @@ -18,14 +18,18 @@ return ( - {Object.keys(currentUser).map((key) => { - return ( - - {key.toUpperCase()} - {currentUser[key]} - - ) - })} + + ID + {currentUser.id} + + + ROLES + {currentUser.roles} + + + EMAIL + {currentUser.email} + isAuthenticated diff --git a/yarn.lock b/yarn.lock index 8388218e1579..fe5840d6ee81 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6044,17 +6044,17 @@ __metadata: linkType: hard "@octokit/app@npm:^13.1.1": - version: 13.1.1 - resolution: "@octokit/app@npm:13.1.1" + version: 13.1.2 + resolution: "@octokit/app@npm:13.1.2" dependencies: "@octokit/auth-app": ^4.0.8 "@octokit/auth-unauthenticated": ^3.0.0 "@octokit/core": ^4.0.0 "@octokit/oauth-app": ^4.0.7 - "@octokit/plugin-paginate-rest": ^5.0.0 - "@octokit/types": ^8.0.0 + "@octokit/plugin-paginate-rest": ^6.0.0 + "@octokit/types": ^9.0.0 "@octokit/webhooks": ^10.0.0 - checksum: 02865fd0f7d8fa5688fd2f5ac53ff3ab0a7ee35de240e0345ab76423c2032d5eff67b2bac6230f77ae765b38cfb7a204a9dc41f51c70841934e1d6dd81abb6b4 + checksum: 3127e8c95a8bf9ba50e5635dadfc7ae0fb9f0910bf411d2436fff95ffa239dab46331431f32b5a68c023c5c9e3e97738b5abaefc1e3f1f927e7be55f37e7b40c languageName: node linkType: hard @@ -6242,6 +6242,17 @@ __metadata: languageName: node linkType: hard +"@octokit/plugin-paginate-rest@npm:^6.0.0": + version: 6.0.0 + resolution: "@octokit/plugin-paginate-rest@npm:6.0.0" + dependencies: + "@octokit/types": ^9.0.0 + peerDependencies: + "@octokit/core": ">=4" + checksum: 5dbde9bc44d5b70f977d343af7eb65b1a3c6d7178dc52440e5dc565ba2bb772d84a43a235161ae022b59b6a48b089fab0d3aa58157e0636a12fbcead0dc19d84 + languageName: node + linkType: hard + "@octokit/plugin-request-log@npm:^1.0.4": version: 1.0.4 resolution: "@octokit/plugin-request-log@npm:1.0.4" @@ -6252,14 +6263,14 @@ __metadata: linkType: hard "@octokit/plugin-rest-endpoint-methods@npm:^6.7.0": - version: 6.7.0 - resolution: "@octokit/plugin-rest-endpoint-methods@npm:6.7.0" + version: 6.8.1 + resolution: "@octokit/plugin-rest-endpoint-methods@npm:6.8.1" dependencies: - "@octokit/types": ^8.0.0 + "@octokit/types": ^8.1.1 deprecation: ^2.3.1 peerDependencies: "@octokit/core": ">=3" - checksum: 4f6290cb405ad0a8e9f149a259836ef1bd2d82670571a108c613385e4fde1f940c265fa7047441f234f7b659934545a22b9feaba2b0ca5abeeeef94b7fc2859b + checksum: 1ab8d3042fac9673f7152a783551c60cdbd3fa1383e6fc026f0ab5aca9105419e1cfa12c6e7955b5904a8c7dc9d2da413b31f3f6c45f6fb048cfb378b4e3dd66 languageName: node linkType: hard @@ -6336,12 +6347,12 @@ __metadata: languageName: node linkType: hard -"@octokit/types@npm:^8.0.0": - version: 8.1.1 - resolution: "@octokit/types@npm:8.1.1" +"@octokit/types@npm:^8.0.0, @octokit/types@npm:^8.1.1": + version: 8.2.1 + resolution: "@octokit/types@npm:8.2.1" dependencies: "@octokit/openapi-types": ^14.0.0 - checksum: 0b908a047c3fc307e18b0da0a4312c26a31fb67aa30694945e9ecb3e7bb441480096ea984a7acda2d09a680f50dce52739632bd521aa1249c2020def8d389ad3 + checksum: 85a97bca714b88ea0d34066b4821e48ba4f8dda8f3970f1a00deb02b3e3f1cc315720d25430082dc651c400717510273193ac6af610268488160bb9e6a30bef8 languageName: node linkType: hard @@ -7019,11 +7030,10 @@ __metadata: "@babel/core": 7.20.12 "@babel/runtime-corejs3": 7.20.13 "@redwoodjs/auth": 3.2.0 - "@testing-library/react-hooks": 8.0.1 - "@types/react": 17.0.53 + "@types/react": 18.0.27 core-js: 3.27.2 jest: 29.3.1 - react: 17.0.2 + react: 18.2.0 typescript: 4.7.4 peerDependencies: "@auth0/auth0-spa-js": 1.22.6 @@ -7072,12 +7082,11 @@ __metadata: "@babel/core": 7.20.12 "@babel/runtime-corejs3": 7.20.13 "@redwoodjs/auth": 3.2.0 - "@testing-library/react-hooks": 8.0.1 "@types/netlify-identity-widget": 1.9.3 - "@types/react": 17.0.53 + "@types/react": 18.0.27 core-js: 3.27.2 jest: 29.3.1 - react: 17.0.2 + react: 18.2.0 typescript: 4.7.4 peerDependencies: "@azure/msal-browser": 2.32.2 @@ -7125,11 +7134,10 @@ __metadata: "@clerk/clerk-react": 3.5.1 "@clerk/types": 2.21.0 "@redwoodjs/auth": 3.2.0 - "@testing-library/react-hooks": 8.0.1 - "@types/react": 17.0.53 + "@types/react": 18.0.27 core-js: 3.27.2 jest: 29.3.1 - react: 17.0.2 + react: 18.2.0 typescript: 4.7.4 peerDependencies: "@clerk/clerk-react": 3.5.1 @@ -7204,11 +7212,10 @@ __metadata: "@redwoodjs/auth": 3.2.0 "@simplewebauthn/browser": 6.2.2 "@simplewebauthn/typescript-types": 6.2.1 - "@testing-library/react-hooks": 8.0.1 - "@types/react": 17.0.53 + "@types/react": 18.0.27 core-js: 3.27.2 jest: 29.3.1 - react: 17.0.2 + react: 18.2.0 typescript: 4.7.4 languageName: unknown linkType: soft @@ -7252,12 +7259,11 @@ __metadata: "@babel/core": 7.20.12 "@babel/runtime-corejs3": 7.20.13 "@redwoodjs/auth": 3.2.0 - "@testing-library/react-hooks": 8.0.1 - "@types/react": 17.0.53 + "@types/react": 18.0.27 core-js: 3.27.2 firebase: 9.16.0 jest: 29.3.1 - react: 17.0.2 + react: 18.2.0 typescript: 4.7.4 peerDependencies: firebase: 9.16.0 @@ -7304,12 +7310,11 @@ __metadata: "@babel/core": 7.20.12 "@babel/runtime-corejs3": 7.20.13 "@redwoodjs/auth": 3.2.0 - "@testing-library/react-hooks": 8.0.1 "@types/netlify-identity-widget": 1.9.3 - "@types/react": 17.0.53 + "@types/react": 18.0.27 core-js: 3.27.2 jest: 29.3.1 - react: 17.0.2 + react: 18.2.0 typescript: 4.7.4 peerDependencies: netlify-identity-widget: 1.9.2 @@ -7356,11 +7361,10 @@ __metadata: "@babel/core": 7.20.12 "@babel/runtime-corejs3": 7.20.13 "@supabase/supabase-js": 1.35.7 - "@testing-library/react-hooks": 8.0.1 - "@types/react": 17.0.53 + "@types/react": 18.0.27 core-js: 3.27.2 jest: 29.3.1 - react: 17.0.2 + react: 18.2.0 typescript: 4.7.4 peerDependencies: "@supabase/supabase-js": 1.35.7 @@ -7409,11 +7413,10 @@ __metadata: "@babel/core": 7.20.12 "@babel/runtime-corejs3": 7.20.13 "@redwoodjs/auth": 3.2.0 - "@testing-library/react-hooks": 8.0.1 - "@types/react": 17.0.53 + "@types/react": 18.0.27 core-js: 3.27.2 jest: 29.3.1 - react: 17.0.2 + react: 18.2.0 typescript: 4.7.4 peerDependencies: supertokens-auth-react: 0.30.2 @@ -7428,12 +7431,11 @@ __metadata: "@babel/core": 7.20.12 "@babel/runtime-corejs3": 7.20.13 "@testing-library/jest-dom": 5.16.5 - "@testing-library/react": 12.1.5 - "@testing-library/react-hooks": 8.0.1 + "@testing-library/react": 13.4.0 core-js: 3.27.2 jest: 29.3.1 msw: 0.49.3 - react: 17.0.2 + react: 18.2.0 typescript: 4.7.4 languageName: unknown linkType: soft @@ -7664,24 +7666,24 @@ __metadata: "@babel/runtime-corejs3": 7.20.13 "@testing-library/dom": 8.20.0 "@testing-library/jest-dom": 5.16.5 - "@testing-library/react": 12.1.5 + "@testing-library/react": 13.4.0 "@testing-library/user-event": 14.4.3 "@types/pascalcase": 1.0.1 - "@types/react": 17.0.53 - "@types/react-dom": 17.0.18 + "@types/react": 18.0.27 + "@types/react-dom": 18.0.10 "@types/testing-library__jest-dom": 5.14.5 core-js: 3.27.2 graphql: 16.6.0 jest: 29.3.1 nodemon: 2.0.20 pascalcase: 1.0.0 - react: 17.0.2 - react-dom: 17.0.2 + react: 18.2.0 + react-dom: 18.2.0 react-hook-form: 7.42.1 typescript: 4.7.4 peerDependencies: graphql: 16.6.0 - react: 17.0.2 + react: 18.2.0 languageName: unknown linkType: soft @@ -7799,8 +7801,8 @@ __metadata: mime-types: 2.1.35 typescript: 4.7.4 peerDependencies: - react: 17.0.2 - react-dom: 17.0.2 + react: 18.2.0 + react-dom: 18.2.0 languageName: unknown linkType: soft @@ -7828,16 +7830,16 @@ __metadata: "@babel/runtime-corejs3": 7.20.13 "@reach/skip-nav": 0.18.0 "@redwoodjs/auth": 3.2.0 - "@types/react": 17.0.53 - "@types/react-dom": 17.0.18 + "@types/react": 18.0.27 + "@types/react-dom": 18.0.10 core-js: 3.27.2 jest: 29.3.1 - react: 17.0.2 - react-dom: 17.0.2 + react: 18.2.0 + react-dom: 18.2.0 typescript: 4.7.4 peerDependencies: - react: 17.0.2 - react-dom: 17.0.2 + react: 18.2.0 + react-dom: 18.2.0 languageName: unknown linkType: soft @@ -7922,15 +7924,14 @@ __metadata: "@storybook/manager-webpack5": 6.5.15 "@storybook/react": 6.5.15 "@testing-library/jest-dom": 5.16.5 - "@testing-library/react": 12.1.5 - "@testing-library/react-hooks": 8.0.1 + "@testing-library/react": 13.4.0 "@testing-library/user-event": 14.4.3 "@types/aws-lambda": 8.10.109 "@types/babel-core": 6.25.7 "@types/jest": 29.2.6 "@types/node": 16.18.11 - "@types/react": 17.0.53 - "@types/react-dom": 17.0.18 + "@types/react": 18.0.27 + "@types/react-dom": 18.0.10 "@types/webpack": 5.28.0 babel-jest: 29.3.1 babel-plugin-inline-react-svg: 2.0.1 @@ -7977,10 +7978,10 @@ __metadata: "@babel/runtime-corejs3": 7.20.13 "@redwoodjs/auth": 3.2.0 "@testing-library/jest-dom": 5.16.5 - "@testing-library/react": 12.1.5 + "@testing-library/react": 13.4.0 "@types/prop-types": 15.7.5 - "@types/react": 17.0.53 - "@types/react-dom": 17.0.18 + "@types/react": 18.0.27 + "@types/react-dom": 18.0.10 "@types/testing-library__jest-dom": 5.14.5 core-js: 3.27.2 graphql: 16.6.0 @@ -7988,8 +7989,8 @@ __metadata: jest: 29.3.1 nodemon: 2.0.20 prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2 + react: 18.2.0 + react-dom: 18.2.0 react-helmet-async: 1.3.0 react-hot-toast: 2.4.0 stacktracey: 2.1.8 @@ -7997,8 +7998,8 @@ __metadata: typescript: 4.7.4 peerDependencies: prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2 + react: 18.2.0 + react-dom: 18.2.0 bin: build-storybook: ./dist/bins/build-storybook.js cross-env: ./dist/bins/cross-env.js @@ -9438,7 +9439,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/dom@npm:8.20.0, @testing-library/dom@npm:^8.0.0, @testing-library/dom@npm:^8.11.1": +"@testing-library/dom@npm:8.20.0, @testing-library/dom@npm:^8.11.1, @testing-library/dom@npm:^8.5.0": version: 8.20.0 resolution: "@testing-library/dom@npm:8.20.0" dependencies: @@ -9471,39 +9472,17 @@ __metadata: languageName: node linkType: hard -"@testing-library/react-hooks@npm:8.0.1": - version: 8.0.1 - resolution: "@testing-library/react-hooks@npm:8.0.1" +"@testing-library/react@npm:13.4.0": + version: 13.4.0 + resolution: "@testing-library/react@npm:13.4.0" dependencies: "@babel/runtime": ^7.12.5 - react-error-boundary: ^3.1.0 + "@testing-library/dom": ^8.5.0 + "@types/react-dom": ^18.0.0 peerDependencies: - "@types/react": ^16.9.0 || ^17.0.0 - react: ^16.9.0 || ^17.0.0 - react-dom: ^16.9.0 || ^17.0.0 - react-test-renderer: ^16.9.0 || ^17.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - react-dom: - optional: true - react-test-renderer: - optional: true - checksum: 83bef2d4c437b84143213b5275ef00ef14e5bcd344f9ded12b162d253dc3c799138ead4428026b9c725e5a38dbebf611f2898aa43f3e43432bcaccbd7bf413e5 - languageName: node - linkType: hard - -"@testing-library/react@npm:12.1.5": - version: 12.1.5 - resolution: "@testing-library/react@npm:12.1.5" - dependencies: - "@babel/runtime": ^7.12.5 - "@testing-library/dom": ^8.0.0 - "@types/react-dom": <18.0.0 - peerDependencies: - react: <18.0.0 - react-dom: <18.0.0 - checksum: 3c2433d2fdb6535261f62cd85d79657989cebd96f9072da03c098a1cfa56dec4dfec83d7c2e93633a3ccebdb178ea8578261533d11551600966edab77af00c8b + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 371bf982dd0deb27da004f368b06904353eac0f23f9c08ff0f24443c3f51a6d647009e366034417565d2484c40f1c7eff74413738abf4ec55209da9bd3253b0e languageName: node linkType: hard @@ -10367,23 +10346,23 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:17.0.18, @types/react-dom@npm:<18.0.0": - version: 17.0.18 - resolution: "@types/react-dom@npm:17.0.18" +"@types/react-dom@npm:18.0.10, @types/react-dom@npm:^18.0.0": + version: 18.0.10 + resolution: "@types/react-dom@npm:18.0.10" dependencies: - "@types/react": ^17 - checksum: a787471157d66e834ee2afa57d81171c8cae26d3b0def23709da8256433d0b3c5c9f35c03913c9c4137f79acf78af9e2483ee1578197f77298344f33b7186791 + "@types/react": "*" + checksum: a07b900a2d5559830f88b3e525cf279f9f04b4893f4d17e64f5adb08d8abe0e3151e0d3c0ea17d836104ae47594be577529a004265600e4304a43a93b0d5d61e languageName: node linkType: hard -"@types/react@npm:17.0.53": - version: 17.0.53 - resolution: "@types/react@npm:17.0.53" +"@types/react@npm:*, @types/react@npm:18.0.27": + version: 18.0.27 + resolution: "@types/react@npm:18.0.27" dependencies: "@types/prop-types": "*" "@types/scheduler": "*" csstype: ^3.0.2 - checksum: 4ff3fa58ab32deefacdbd0ee002e294548391238ce2dea2cad213e11b4cc61480be48cb2b7ed3c53220ee1a5b9cadf3417a20db817ab2ca4669c9a4a45042b92 + checksum: 87711931b14cdca07c4149531b4c96e7a56609ed2d010c52bf6bde14b417ac128c326924b14b25667fdaeddacfe98c31fa9625a95af52dae45061df8e30b46a3 languageName: node linkType: hard @@ -26728,7 +26707,7 @@ __metadata: languageName: node linkType: hard -"prop-types@npm:15.8.1": +"prop-types@npm:15.8.1, prop-types@npm:^15.0.0, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": version: 15.8.1 resolution: "prop-types@npm:15.8.1" dependencies: @@ -27168,16 +27147,15 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:17.0.2": - version: 17.0.2 - resolution: "react-dom@npm:17.0.2" +"react-dom@npm:18.2.0": + version: 18.2.0 + resolution: "react-dom@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - scheduler: ^0.20.2 + scheduler: ^0.23.0 peerDependencies: - react: 17.0.2 - checksum: 51abbcb72450fe527ebf978c3bc989ba266630faaa53f47a2fae5392369729e8de62b2e4683598cbe651ea7873cd34ec7d5127e2f50bf4bfe6bd0c3ad9bddcb0 + react: ^18.2.0 + checksum: 66dfc5f93e13d0674e78ef41f92ed21dfb80f9c4ac4ac25a4b51046d41d4d2186abc915b897f69d3d0ebbffe6184e7c5876f2af26bfa956f179225d921be713a languageName: node linkType: hard @@ -27195,17 +27173,6 @@ __metadata: languageName: node linkType: hard -"react-error-boundary@npm:^3.1.0": - version: 3.1.4 - resolution: "react-error-boundary@npm:3.1.4" - dependencies: - "@babel/runtime": ^7.12.5 - peerDependencies: - react: ">=16.13.1" - checksum: f977ca61823e43de2381d53dd7aa8b4d79ff6a984c9afdc88dc44f9973b99de7fd382d2f0f91f2688e24bb987c0185bf45d0b004f22afaaab0f990a830253bfb - languageName: node - linkType: hard - "react-fast-compare@npm:^3.2.0": version: 3.2.0 resolution: "react-fast-compare@npm:3.2.0" @@ -27310,13 +27277,12 @@ __metadata: languageName: node linkType: hard -"react@npm:17.0.2": - version: 17.0.2 - resolution: "react@npm:17.0.2" +"react@npm:18.2.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: 07ae8959acf1596f0550685102fd6097d461a54a4fd46a50f88a0cd7daaa97fdd6415de1dcb4bfe0da6aa43221a6746ce380410fa848acc60f8ac41f6649c148 + checksum: b562d9b569b0cb315e44b48099f7712283d93df36b19a39a67c254c6686479d3980b7f013dc931f4a5a3ae7645eae6386b4aa5eea933baa54ecd0f9acb0902b8 languageName: node linkType: hard @@ -28233,8 +28199,7 @@ __metadata: "@playwright/test": 1.29.2 "@replayio/playwright": 0.3.15 "@testing-library/jest-dom": 5.16.5 - "@testing-library/react": 12.1.5 - "@testing-library/react-hooks": 8.0.1 + "@testing-library/react": 13.4.0 "@testing-library/user-event": 14.4.3 "@tsd/typescript": 4.9.4 "@types/babel__generator": 7.6.4 @@ -28436,13 +28401,12 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:^0.20.2": - version: 0.20.2 - resolution: "scheduler@npm:0.20.2" +"scheduler@npm:^0.23.0": + version: 0.23.0 + resolution: "scheduler@npm:0.23.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: b0982e4b0f34f4ffa4f2f486161c0fd9ce9b88680b045dccbf250eb1aa4fd27413570645455187a83535e2370f5c667a251045547765408492bd883cbe95fcdb + checksum: b777f7ca0115e6d93e126ac490dbd82642d14983b3079f58f35519d992fa46260be7d6e6cede433a92db70306310c6f5f06e144f0e40c484199e09c1f7be53dd languageName: node linkType: hard @@ -30876,7 +30840,17 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A4.7.4#~builtin": +"typescript@npm:^3 || ^4": + version: 4.9.4 + resolution: "typescript@npm:4.9.4" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 5008b97a2a3afdbe57ea70e504ebc8ec98f18d888059dfb7932a41f566a1360a28afc8de2a440fd6143b4014cc6d2616079931dc690c7513c2d21fa53957e0ec + languageName: node + linkType: hard + +"typescript@patch:typescript@4.7.4#~builtin": version: 4.7.4 resolution: "typescript@patch:typescript@npm%3A4.7.4#~builtin::version=4.7.4&hash=65a307" bin: @@ -30886,6 +30860,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@^3 || ^4#~builtin": + version: 4.9.4 + resolution: "typescript@patch:typescript@npm%3A4.9.4#~builtin::version=4.9.4&hash=ad5954" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: a98c97a7abb391a00c51a427b074ab58c02df490358b7db7c3f4cc4fceb6d620457a0ef5d58e1c8db08fcb4ece9f3ba656cbfef3f81c12a383b0b8df8f198c7c + languageName: node + linkType: hard + "ua-parser-js@npm:^0.7.30": version: 0.7.32 resolution: "ua-parser-js@npm:0.7.32"