From 78803d74c001181d35119401a3d06e2fe217748c Mon Sep 17 00:00:00 2001 From: "Daniel A.C. Martin" Date: Wed, 28 Aug 2024 21:34:20 +0100 Subject: [PATCH 1/3] Update react-helmet-async to v2 --- apps/govuk-docs/package.json | 2 +- apps/govuk-template/package.json | 2 +- lib/app-composer/src/index.ts | 10 +++++++--- lib/server-renderer/package.json | 2 +- package.json | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/apps/govuk-docs/package.json b/apps/govuk-docs/package.json index 2bd174a68..2303bb218 100644 --- a/apps/govuk-docs/package.json +++ b/apps/govuk-docs/package.json @@ -56,7 +56,7 @@ "plop": "3.1.2", "react": "16.14.0", "react-dom": "16.14.0", - "react-helmet-async": "1.3.0", + "react-helmet-async": "2.0.5", "react-router": "5.3.4", "react-router-dom": "5.3.4", "serverless": "3.39.0", diff --git a/apps/govuk-template/package.json b/apps/govuk-template/package.json index 12ce50bcf..3001afe59 100644 --- a/apps/govuk-template/package.json +++ b/apps/govuk-template/package.json @@ -60,7 +60,7 @@ "plop": "3.1.2", "react": "16.14.0", "react-dom": "16.14.0", - "react-helmet-async": "1.3.0", + "react-helmet-async": "2.0.5", "react-router": "5.3.4", "react-router-dom": "5.3.4", "serverless": "3.39.0", diff --git a/lib/app-composer/src/index.ts b/lib/app-composer/src/index.ts index 7943f8e77..9a5c1e1c8 100644 --- a/lib/app-composer/src/index.ts +++ b/lib/app-composer/src/index.ts @@ -2,7 +2,7 @@ import { GraphQLSchema } from 'graphql'; import { ApolloClient, ApolloProvider, InMemoryCache, createHttpLink } from '@apollo/client'; import { SchemaLink } from '@apollo/client/link/schema'; import { ComponentType, Fragment, ReactNode, Suspense, createElement as h, lazy } from 'react'; -import { Helmet, HelmetProvider, FilledContext } from 'react-helmet-async'; +import { Helmet, HelmetProvider, HelmetServerState } from 'react-helmet-async'; import { StaticRouter, StaticRouterProps, Switch } from 'react-router'; import { BrowserRouter, BrowserRouterProps } from 'react-router-dom'; import { Route, RouteComponentProps, withRouter } from '@not-govuk/route-utils'; @@ -54,6 +54,10 @@ type ServerError = { message: string }; +export type HelmetDataContext = { + helmet: HelmetServerState +} + export type ApplicationPropsSSR = ApplicationPropsCommon & { pages: PageInfoSSR[] }; @@ -63,7 +67,7 @@ export type ApplicationProps = ApplicationPropsCSR | ApplicationPropsSSR; type ApplicationCSR = ComponentType; type ApplicationSSR = ComponentType & { extractDataCache: () => object - helmetContext: FilledContext + helmetContext: HelmetDataContext }; export type Application = ComponentType; @@ -304,7 +308,7 @@ export const compose: Compose = options => { return Object.assign(App, { extractDataCache, - helmetContext: helmetContext as FilledContext + helmetContext: helmetContext as HelmetDataContext }); }; diff --git a/lib/server-renderer/package.json b/lib/server-renderer/package.json index 23c2ea4d1..870177fc6 100644 --- a/lib/server-renderer/package.json +++ b/lib/server-renderer/package.json @@ -32,7 +32,7 @@ "@types/react": "16.14.60", "@types/react-dom": "16.9.24", "graphql": "15.9.0", - "react-helmet-async": "1.3.0", + "react-helmet-async": "2.0.5", "typescript": "4.9.5" } } diff --git a/package.json b/package.json index c2c8304f8..e02f5e3b1 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "process": "^0.11.10", "react": "16.14.0", "react-dom": "16.14.0", - "react-helmet-async": "1.3.0", + "react-helmet-async": "2.0.5", "react-router": "5.3.4", "react-router-dom": "5.3.4", "ts-jest": "29.2.3", From 94cffc76a459874cbf7fc38693f88510997f0d7a Mon Sep 17 00:00:00 2001 From: "Daniel A.C. Martin" Date: Fri, 30 Aug 2024 16:23:54 +0100 Subject: [PATCH 2/3] Workaround to import react-helmet-async There appears to be a bug in which named imports do not work. This bug only appears for us when running under Jest, but not when bundling with webpack. This workaround allows us to import react-helmet-async in different contexts. If this issue is fixed upstream, then this commit can be reverted. See: https://github.com/staylor/react-helmet-async/issues/208 --- components/page/src/GovUKPage.tsx | 5 ++++- components/page/src/NotGovUKPage.tsx | 5 ++++- components/page/src/Page.tsx | 5 ++++- lib/component-test-helpers/src/index.ts | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/components/page/src/GovUKPage.tsx b/components/page/src/GovUKPage.tsx index 4814e99e4..107698cd5 100644 --- a/components/page/src/GovUKPage.tsx +++ b/components/page/src/GovUKPage.tsx @@ -1,5 +1,5 @@ import { FC, createElement as h } from 'react'; -import { Helmet } from 'react-helmet-async'; +import reactHelmetDefault, * as reactHelmetNamed from 'react-helmet-async'; import { Page, PageProps } from './Page'; import favicon from 'govuk-frontend/govuk/assets/images/favicon.ico'; @@ -12,6 +12,9 @@ import ogImage from 'govuk-frontend/govuk/assets/images/govuk-opengraph-image.pn import '../assets/GovUKPage.scss'; +const reactHelmet = reactHelmetDefault || reactHelmetNamed; +const { Helmet } = reactHelmet; + export type GovUKPageProps = Omit; export const GovUKPage: FC = ({ children, classModifiers, ...props }) => ( diff --git a/components/page/src/NotGovUKPage.tsx b/components/page/src/NotGovUKPage.tsx index 50a65e4a4..53190bd84 100644 --- a/components/page/src/NotGovUKPage.tsx +++ b/components/page/src/NotGovUKPage.tsx @@ -1,5 +1,5 @@ import { FC, createElement as h } from 'react'; -import { Helmet } from 'react-helmet-async'; +import reactHelmetDefault, * as reactHelmetNamed from 'react-helmet-async'; import { Page, PageProps } from './Page'; import favicon from '../assets/coat-favicon.ico'; @@ -11,6 +11,9 @@ import ogImage from '../assets/coat-opengraph-image.png'; import '../assets/NotGovUKPage.scss'; +const reactHelmet = reactHelmetDefault || reactHelmetNamed; +const { Helmet } = reactHelmet; + export type NotGovUKPageProps = Omit; export const NotGovUKPage: FC = ({ children, classModifiers, ...props }) => ( diff --git a/components/page/src/Page.tsx b/components/page/src/Page.tsx index e2f36a857..0d1647e33 100644 --- a/components/page/src/Page.tsx +++ b/components/page/src/Page.tsx @@ -1,5 +1,5 @@ import { FC, Fragment, HTMLProps, ReactNode, createElement as h } from 'react'; -import { Helmet } from 'react-helmet-async'; +import reactHelmetDefault, * as reactHelmetNamed from 'react-helmet-async'; import { BackLink } from '@not-govuk/back-link'; import { Breadcrumb, Breadcrumbs } from '@not-govuk/breadcrumbs'; import { StandardProps, classBuilder } from '@not-govuk/component-helpers'; @@ -12,6 +12,9 @@ import { WidthContainer } from '@not-govuk/width-container'; import '../assets/Page.scss'; +const reactHelmet = reactHelmetDefault || reactHelmetNamed; +const { Helmet } = reactHelmet; + export type PageProps = ( StandardProps & HTMLProps & diff --git a/lib/component-test-helpers/src/index.ts b/lib/component-test-helpers/src/index.ts index cb354786e..c8bfdf748 100644 --- a/lib/component-test-helpers/src/index.ts +++ b/lib/component-test-helpers/src/index.ts @@ -1,11 +1,14 @@ import { FC, ReactElement, ReactNode, createElement as h } from 'react'; -import { HelmetProvider } from 'react-helmet-async'; +import reactHelmetDefault, * as reactHelmetNamed from 'react-helmet-async'; import { MemoryRouter } from 'react-router'; import { render as _render, RenderOptions } from '@testing-library/react'; import userEventDefault from '@testing-library/user-event'; import '@testing-library/jest-dom'; +const reactHelmet = reactHelmetDefault || reactHelmetNamed; +const { HelmetProvider } = reactHelmet; + const Providers: FC<{ children?: ReactNode, routerProps?: object }> = ({ children, routerProps From 99cb418a45a0e47b67c48a5bdf9c2098b8e79b0d Mon Sep 17 00:00:00 2001 From: "Daniel A.C. Martin" Date: Fri, 30 Aug 2024 16:29:37 +0100 Subject: [PATCH 3/3] Update package lock-file --- pnpm-lock.yaml | 70 ++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1b4cdcd2b..fa690fd00 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,7 +39,7 @@ importers: process: ^0.11.10 react: 16.14.0 react-dom: 16.14.0 - react-helmet-async: 1.3.0 + react-helmet-async: 2.0.5 react-router: 5.3.4 react-router-dom: 5.3.4 ts-jest: 29.2.3 @@ -84,7 +84,7 @@ importers: process: 0.11.10 react: 16.14.0 react-dom: 16.14.0_react@16.14.0 - react-helmet-async: 1.3.0_wcqkhtmu7mswc6yz4uyexck3ty + react-helmet-async: 2.0.5_react@16.14.0 react-router: 5.3.4_react@16.14.0 react-router-dom: 5.3.4_react@16.14.0 ts-jest: 29.2.3_emrc4okhxugh6ej24zdudb2ocy @@ -119,7 +119,7 @@ importers: plop: 3.1.2 react: 16.14.0 react-dom: 16.14.0 - react-helmet-async: 1.3.0 + react-helmet-async: 2.0.5 react-router: 5.3.4 react-router-dom: 5.3.4 serverless: 3.39.0 @@ -154,7 +154,7 @@ importers: plop: 3.1.2 react: 16.14.0 react-dom: 16.14.0_react@16.14.0 - react-helmet-async: 1.3.0_wcqkhtmu7mswc6yz4uyexck3ty + react-helmet-async: 2.0.5_react@16.14.0 react-router: 5.3.4_react@16.14.0 react-router-dom: 5.3.4_react@16.14.0 serverless: 3.39.0 @@ -195,7 +195,7 @@ importers: plop: 3.1.2 react: 16.14.0 react-dom: 16.14.0 - react-helmet-async: 1.3.0 + react-helmet-async: 2.0.5 react-router: 5.3.4 react-router-dom: 5.3.4 serverless: 3.39.0 @@ -234,7 +234,7 @@ importers: plop: 3.1.2 react: 16.14.0 react-dom: 16.14.0_react@16.14.0 - react-helmet-async: 1.3.0_wcqkhtmu7mswc6yz4uyexck3ty + react-helmet-async: 2.0.5_react@16.14.0 react-router: 5.3.4_react@16.14.0 react-router-dom: 5.3.4_react@16.14.0 serverless: 3.39.0 @@ -1935,7 +1935,7 @@ importers: '@types/react': 16.14.60 '@types/react-dom': 16.9.24 graphql: 15.9.0 - react-helmet-async: 1.3.0 + react-helmet-async: 2.0.5 restify-errors: ^8.0.2 typescript: 4.9.5 dependencies: @@ -1947,7 +1947,7 @@ importers: '@types/react': 16.14.60 '@types/react-dom': 16.9.24 graphql: 15.9.0 - react-helmet-async: 1.3.0 + react-helmet-async: 2.0.5 typescript: 4.9.5 lib/storybook-preset: @@ -2144,8 +2144,8 @@ packages: es5-ext: 0.10.62 dev: true - /@adobe/css-tools/4.2.0: - resolution: {integrity: sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==} + /@adobe/css-tools/4.4.0: + resolution: {integrity: sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==} dev: false /@ampproject/remapping/2.2.0: @@ -9406,8 +9406,8 @@ packages: defer-to-connect: 2.0.1 dev: true - /@testing-library/dom/8.20.0: - resolution: {integrity: sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==} + /@testing-library/dom/8.20.1: + resolution: {integrity: sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==} engines: {node: '>=12'} dependencies: '@babel/code-frame': 7.24.7 @@ -9416,7 +9416,7 @@ packages: aria-query: 5.1.3 chalk: 4.1.2 dom-accessibility-api: 0.5.16 - lz-string: 1.4.4 + lz-string: 1.5.0 pretty-format: 27.5.1 dev: false @@ -9424,9 +9424,9 @@ packages: resolution: {integrity: sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==} engines: {node: '>=8', npm: '>=6', yarn: '>=1'} dependencies: - '@adobe/css-tools': 4.2.0 + '@adobe/css-tools': 4.4.0 '@babel/runtime': 7.21.0 - '@types/testing-library__jest-dom': 5.14.5 + '@types/testing-library__jest-dom': 5.14.9 aria-query: 5.1.3 chalk: 3.0.0 css.escape: 1.5.1 @@ -9443,7 +9443,7 @@ packages: react-dom: <18.0.0 dependencies: '@babel/runtime': 7.21.0 - '@testing-library/dom': 8.20.0 + '@testing-library/dom': 8.20.1 '@types/react-dom': 16.9.24 dev: false @@ -9859,8 +9859,8 @@ packages: /@types/tapable/1.0.8: resolution: {integrity: sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==} - /@types/testing-library__jest-dom/5.14.5: - resolution: {integrity: sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==} + /@types/testing-library__jest-dom/5.14.9: + resolution: {integrity: sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==} dependencies: '@types/jest': 29.5.12 dev: false @@ -16083,7 +16083,7 @@ packages: chalk: 4.1.2 diff-sequences: 29.4.3 jest-get-type: 29.4.3 - pretty-format: 29.5.0 + pretty-format: 29.7.0 /jest-diff/29.7.0: resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} @@ -16214,7 +16214,7 @@ packages: chalk: 4.1.2 jest-diff: 29.5.0 jest-get-type: 29.4.3 - pretty-format: 29.5.0 + pretty-format: 29.7.0 /jest-matcher-utils/29.7.0: resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} @@ -16236,7 +16236,7 @@ packages: chalk: 4.1.2 graceful-fs: 4.2.11 micromatch: 4.0.5 - pretty-format: 29.5.0 + pretty-format: 29.7.0 slash: 3.0.0 stack-utils: 2.0.6 @@ -17029,8 +17029,8 @@ packages: es5-ext: 0.10.62 dev: true - /lz-string/1.4.4: - resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==} + /lz-string/1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true dev: false @@ -18706,7 +18706,6 @@ packages: '@jest/schemas': 29.6.3 ansi-styles: 5.2.0 react-is: 18.2.0 - dev: true /pretty-hrtime/1.0.3: resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==} @@ -19037,35 +19036,28 @@ packages: resolution: {integrity: sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==} dev: false - /react-fast-compare/3.2.0: - resolution: {integrity: sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==} + /react-fast-compare/3.2.2: + resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} dev: true - /react-helmet-async/1.3.0: - resolution: {integrity: sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==} + /react-helmet-async/2.0.5: + resolution: {integrity: sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg==} peerDependencies: react: ^16.6.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0 dependencies: - '@babel/runtime': 7.21.0 invariant: 2.2.4 - prop-types: 15.8.1 - react-fast-compare: 3.2.0 + react-fast-compare: 3.2.2 shallowequal: 1.1.0 dev: true - /react-helmet-async/1.3.0_wcqkhtmu7mswc6yz4uyexck3ty: - resolution: {integrity: sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==} + /react-helmet-async/2.0.5_react@16.14.0: + resolution: {integrity: sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg==} peerDependencies: react: ^16.6.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0 dependencies: - '@babel/runtime': 7.21.0 invariant: 2.2.4 - prop-types: 15.8.1 react: 16.14.0 - react-dom: 16.14.0_react@16.14.0 - react-fast-compare: 3.2.0 + react-fast-compare: 3.2.2 shallowequal: 1.1.0 dev: true