diff --git a/dotcom-rendering/scripts/deploy/build-riffraff-bundle.js b/dotcom-rendering/scripts/deploy/build-riffraff-bundle.js index 958c5ef61a2..39cf1539689 100755 --- a/dotcom-rendering/scripts/deploy/build-riffraff-bundle.js +++ b/dotcom-rendering/scripts/deploy/build-riffraff-bundle.js @@ -106,8 +106,7 @@ Promise.all([ copyDistServer(), copyScripts(), copyRiffRaff(), -]) - .catch((err) => { - warn(err.stack); - process.exit(1); - }); +]).catch((err) => { + warn(err.stack); + process.exit(1); +}); diff --git a/dotcom-rendering/scripts/jest/setup.ts b/dotcom-rendering/scripts/jest/setup.ts index 73ffa8087f0..33034a43dbb 100644 --- a/dotcom-rendering/scripts/jest/setup.ts +++ b/dotcom-rendering/scripts/jest/setup.ts @@ -114,12 +114,3 @@ global.TextDecoder = TextDecoder as unknown as typeof global.TextDecoder; // Mocks the version number used by CDK, we don't want our tests to fail every time we update our cdk dependency. jest.mock('@guardian/cdk/lib/constants/tracking-tag'); - -// Mocks the useConfig hook in ConfigContext, so that we don't have to use the provider all the time -jest.mock('../../src/components/ConfigContext.tsx', () => { - const mockConfig = { renderingTarget: 'Web' }; - return { - ...jest.requireActual('../../src/components/ConfigContext.tsx'), - useConfig: () => mockConfig, - }; -}); diff --git a/dotcom-rendering/src/components/ArticleMeta.test.tsx b/dotcom-rendering/src/components/ArticleMeta.test.tsx index abf60b82703..972cdf23c08 100644 --- a/dotcom-rendering/src/components/ArticleMeta.test.tsx +++ b/dotcom-rendering/src/components/ArticleMeta.test.tsx @@ -2,6 +2,7 @@ import { ArticleDesign, ArticleDisplay, Pillar } from '@guardian/libs'; import { jest } from '@jest/globals'; import { render } from '@testing-library/react'; import { interactiveLegacyClasses } from '../layouts/lib/interactiveLegacyStyling'; +import { ConfigProvider } from './ConfigContext'; jest.unstable_mockModule('../../src/lib/bridgetApi', () => ({ getNotificationsClient: jest.fn(), @@ -18,26 +19,28 @@ describe('ArticleMeta', () => { }; const { container } = render( - , + + + , ); expect( @@ -58,26 +61,28 @@ describe('ArticleMeta', () => { }; const { container } = render( - , + + + , ); expect( diff --git a/dotcom-rendering/src/components/BylineLink.test.tsx b/dotcom-rendering/src/components/BylineLink.test.tsx index 77771ad4182..a033bef423e 100644 --- a/dotcom-rendering/src/components/BylineLink.test.tsx +++ b/dotcom-rendering/src/components/BylineLink.test.tsx @@ -3,6 +3,7 @@ import { jest } from '@jest/globals'; import { render } from '@testing-library/react'; import { getContributorTagsForToken } from '../lib/byline'; import type { TagType } from '../types/tag'; +import { ConfigProvider } from './ConfigContext'; jest.unstable_mockModule('../../src/lib/bridgetApi', () => ({ getNotificationsClient: jest.fn(), @@ -105,15 +106,17 @@ describe('BylineLink', () => { ]; const { container } = render( - , + + + , ); const links = container.querySelectorAll('a'); @@ -138,15 +141,17 @@ describe('BylineLink', () => { }, ]; const { container } = render( - , + + + , ); const links = container.querySelectorAll('a'); @@ -173,15 +178,17 @@ describe('BylineLink', () => { ]; const { container } = render( - , + + + , ); const links = container.querySelectorAll('a'); diff --git a/dotcom-rendering/src/components/ConfigContext.test.tsx b/dotcom-rendering/src/components/ConfigContext.test.tsx index 85b40baca79..99ce67c5e26 100644 --- a/dotcom-rendering/src/components/ConfigContext.test.tsx +++ b/dotcom-rendering/src/components/ConfigContext.test.tsx @@ -1,8 +1,5 @@ import { render } from '@testing-library/react'; - -// This file is globally mocked in "/dotcom-rendering/scripts/jest/setup.ts" -// so we need to explicitly override this in order to test its functionality -const { useConfig, ConfigProvider } = jest.requireActual('./ConfigContext.tsx'); +import { ConfigProvider, useConfig } from './ConfigContext'; const testId = 'testId'; const TestComponent = () => { @@ -22,7 +19,7 @@ describe('ConfigContext', () => { }); describe('with ConfigProvider', () => { - it.each(['Web', 'Apps'])( + it.each(['Web', 'Apps'] as const)( 'provides correct context through useConfig hook with renderingTarget: "%s"', (renderingTarget) => { const config = { renderingTarget }; diff --git a/dotcom-rendering/src/components/Contributor.test.tsx b/dotcom-rendering/src/components/Contributor.test.tsx index 9ff6362d6c4..5830c46dbc2 100644 --- a/dotcom-rendering/src/components/Contributor.test.tsx +++ b/dotcom-rendering/src/components/Contributor.test.tsx @@ -2,6 +2,7 @@ import { ArticleDesign, ArticleDisplay, Pillar } from '@guardian/libs'; import { jest } from '@jest/globals'; import { render } from '@testing-library/react'; import { interactiveLegacyClasses } from '../layouts/lib/interactiveLegacyStyling'; +import { ConfigProvider } from './ConfigContext'; jest.unstable_mockModule('../../src/lib/bridgetApi', () => ({ getNotificationsClient: jest.fn(), @@ -18,17 +19,19 @@ describe('Contributor', () => { }; const { container } = render( - , + + + , ); expect( @@ -44,17 +47,19 @@ describe('Contributor', () => { }; const { container } = render( - , + + + , ); expect( diff --git a/dotcom-rendering/src/components/EuropeLandingModal.test.tsx b/dotcom-rendering/src/components/EuropeLandingModal.test.tsx index f7625c35212..41710a195c6 100644 --- a/dotcom-rendering/src/components/EuropeLandingModal.test.tsx +++ b/dotcom-rendering/src/components/EuropeLandingModal.test.tsx @@ -1,13 +1,13 @@ -import { getCookie } from '@guardian/libs'; -import { getModalType } from './EuropeLandingModal.importable'; +import { setCookie } from '@guardian/libs'; +import { jest } from '@jest/globals'; -// Mocking the getCookie function -jest.mock('@guardian/libs', () => ({ - // Replace with the actual path to getCookie file - getCookie: jest.fn(), +const mockGetCookie = jest.fn(); +jest.unstable_mockModule('@guardian/libs', () => ({ + setCookie, + getCookie: mockGetCookie, })); -const mockGetCookie = getCookie as jest.MockedFunction; +const { getModalType } = await import('./EuropeLandingModal.importable'); describe('getModalType', () => { beforeEach(() => { @@ -20,45 +20,45 @@ describe('getModalType', () => { }); it('should return "ModalSwitched" if editionCookie is INT and country is in COE', () => { - mockGetCookie.mockImplementation((arg) => { - if (arg.name === 'GU_EDITION') return 'INT'; - if (arg.name === 'GU_geo_country') return 'DE'; // Assuming 'DE' (Germany) is in COE + mockGetCookie.mockImplementation(({ name }) => { + if (name === 'GU_EDITION') return 'INT'; + if (name === 'GU_geo_country') return 'DE'; // Assuming 'DE' (Germany) is in COE return null; }); expect(getModalType()).toEqual('ModalSwitched'); }); it('should return "ModalDoYouWantToSwitch" if editionCookie is INT, country is not in COE or UK/US/AUS', () => { - mockGetCookie.mockImplementation((arg) => { - if (arg.name === 'GU_EDITION') return 'INT'; - if (arg.name === 'GU_geo_country') return 'JP'; // Assuming 'JP' (Japan) is not in COE, UK, US, or AUS + mockGetCookie.mockImplementation(({ name }) => { + if (name === 'GU_EDITION') return 'INT'; + if (name === 'GU_geo_country') return 'JP'; // Assuming 'JP' (Japan) is not in COE, UK, US, or AUS return null; }); expect(getModalType()).toEqual('ModalDoYouWantToSwitch'); }); it('should return "ModalDoYouWantToSwitch" if editionCookie is UK/US/AUS and country is in COE', () => { - mockGetCookie.mockImplementation((arg) => { - if (arg.name === 'GU_EDITION') return 'UK'; - if (arg.name === 'GU_geo_country') return 'DE'; // Assuming 'DE' (Germany) is in COE + mockGetCookie.mockImplementation(({ name }) => { + if (name === 'GU_EDITION') return 'UK'; + if (name === 'GU_geo_country') return 'DE'; // Assuming 'DE' (Germany) is in COE return null; }); expect(getModalType()).toEqual('ModalDoYouWantToSwitch'); }); it('should return "ModalSwitched" if editionCookie is not set and country is in COE', () => { - mockGetCookie.mockImplementation((arg) => { - if (arg.name === 'GU_EDITION') return null; - if (arg.name === 'GU_geo_country') return 'DE'; // Assuming 'DE' (Germany) is in COE + mockGetCookie.mockImplementation(({ name }) => { + if (name === 'GU_EDITION') return null; + if (name === 'GU_geo_country') return 'DE'; // Assuming 'DE' (Germany) is in COE return null; }); expect(getModalType()).toEqual('ModalSwitched'); }); it('should return "NoModal" for all other cases', () => { - mockGetCookie.mockImplementation((arg) => { - if (arg.name === 'GU_EDITION') return 'UK'; - if (arg.name === 'GU_geo_country') return 'US'; // Assuming 'US' is not in COE + mockGetCookie.mockImplementation(({ name }) => { + if (name === 'GU_EDITION') return 'UK'; + if (name === 'GU_geo_country') return 'US'; // Assuming 'US' is not in COE return null; }); expect(getModalType()).toEqual('NoModal'); diff --git a/dotcom-rendering/src/components/MostViewedFooter.test.tsx b/dotcom-rendering/src/components/MostViewedFooter.test.tsx index d52659f6536..fe3adb0979e 100644 --- a/dotcom-rendering/src/components/MostViewedFooter.test.tsx +++ b/dotcom-rendering/src/components/MostViewedFooter.test.tsx @@ -1,6 +1,7 @@ import { ArticleDesign, ArticleDisplay, Pillar } from '@guardian/libs'; import { jest } from '@jest/globals'; import { fireEvent, render } from '@testing-library/react'; +import { ConfigProvider } from './ConfigContext'; import { responseWithTwoTabs } from './MostViewed.mocks'; jest.unstable_mockModule('../../src/lib/useApi', () => ({ @@ -27,16 +28,18 @@ describe('MostViewedFooterData', () => { useApi.mockReturnValue({ data: responseWithTwoTabs, loading: false }); const { getByText, getAllByText, getByTestId } = render( - , + + + , ); // Calls api once only @@ -64,16 +67,18 @@ describe('MostViewedFooterData', () => { useApi.mockReturnValue({ data: responseWithTwoTabs, loading: false }); const { getByTestId, getByText } = render( - , + + + , ); const firstHeading = responseWithTwoTabs.tabs[0].heading; @@ -122,16 +127,18 @@ describe('MostViewedFooterData', () => { }); const { getByText } = render( - , + + + , ); expect(getByText('Live')).toBeInTheDocument(); @@ -165,16 +172,18 @@ describe('MostViewedFooterData', () => { }); const { queryByText } = render( - , + + + , ); expect(queryByText('Live')).not.toBeInTheDocument(); @@ -184,16 +193,18 @@ describe('MostViewedFooterData', () => { useApi.mockReturnValue({ data: responseWithTwoTabs, loading: false }); const { asFragment } = render( - , + + + , ); // Renders tab data link name diff --git a/dotcom-rendering/src/lib/assets.test.ts b/dotcom-rendering/src/lib/assets.test.ts index 5c279844077..458a1fb6064 100644 --- a/dotcom-rendering/src/lib/assets.test.ts +++ b/dotcom-rendering/src/lib/assets.test.ts @@ -1,6 +1,17 @@ -import { readFileSync } from 'node:fs'; +import { jest } from '@jest/globals'; import { BUILD_VARIANT } from '../../scripts/webpack/bundles'; -import { + +const readFileSync = jest.fn(); + +jest.unstable_mockModule('node:fs', () => ({ + readFileSync, +})); +jest.unstable_mockModule('node:path', () => ({ + resolve: () => '', + dirname: () => '', +})); + +const { APPS_SCRIPT, decideAssetOrigin, getModulesBuild, @@ -9,10 +20,7 @@ import { WEB_LEGACY_SCRIPT, WEB_SCHEDULED_SCRIPT, WEB_VARIANT_SCRIPT, -} from './assets'; - -jest.mock('node:fs'); -jest.mock('node:path'); +} = await import('./assets'); describe('decideAssetOrigin for stage', () => { it('PROD', () => { @@ -92,7 +100,7 @@ describe('getPathFromManifest', () => { "7305.web.js": "7305.web.8cdc05567d98ebd9f67e.js", "356.web.js": "356.web.0a1bbdf8c7a5e5826b7c.js" }`; - (readFileSync as jest.Mock).mockReturnValue(assetHash); + readFileSync.mockReturnValue(assetHash); }); afterEach(() => { diff --git a/dotcom-rendering/src/lib/assets.ts b/dotcom-rendering/src/lib/assets.ts index 0d43b43d96b..67195ab214a 100644 --- a/dotcom-rendering/src/lib/assets.ts +++ b/dotcom-rendering/src/lib/assets.ts @@ -1,5 +1,6 @@ import { readFileSync } from 'node:fs'; -import { resolve } from 'node:path'; +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; import { isObject, isString } from '@guardian/libs'; import { adaptive, @@ -10,6 +11,8 @@ import { import type { ServerSideTests, Switches } from '../types/config'; import { makeMemoizedFunction } from './memoize'; +const __dirname = dirname(fileURLToPath(import.meta.url)); + interface AssetHash { [key: string]: string; } @@ -62,6 +65,7 @@ const getManifest = makeMemoizedFunction((path: string): AssetHash => { return assetHash; } catch (e) { + console.error(e); console.error('Could not load manifest in: ', path); console.error('Some filename lookups will fail'); return {}; diff --git a/dotcom-rendering/src/lib/memoize.test.ts b/dotcom-rendering/src/lib/memoize.test.ts index 9a2d394e886..152a0ad8928 100644 --- a/dotcom-rendering/src/lib/memoize.test.ts +++ b/dotcom-rendering/src/lib/memoize.test.ts @@ -1,3 +1,4 @@ +import { jest } from '@jest/globals'; import { makeMemoizedFunction } from './memoize'; describe('memoize', () => { @@ -28,10 +29,10 @@ describe('memoize', () => { }); it('has separate caches for each memoized function', () => { - const f = jest.fn().mockImplementation((key: string) => ({ + const f = jest.fn((key: string) => ({ f: key, })); - const g = jest.fn().mockImplementation((key: string) => ({ + const g = jest.fn((key: string) => ({ g: key, })); diff --git a/dotcom-rendering/src/lib/useIsBridgetCompatible.test.ts b/dotcom-rendering/src/lib/useIsBridgetCompatible.test.ts index 0a60c1874c7..dc357a8f41d 100644 --- a/dotcom-rendering/src/lib/useIsBridgetCompatible.test.ts +++ b/dotcom-rendering/src/lib/useIsBridgetCompatible.test.ts @@ -1,9 +1,9 @@ +import { jest } from '@jest/globals'; import { renderHook, waitFor } from '@testing-library/react'; -import { useIsBridgetCompatible } from './useIsBridgetCompatible'; const mockRequiredVersion = '2.1.1'; -jest.mock('./bridgetApi', () => ({ +jest.unstable_mockModule('../../src/lib/bridgetApi', () => ({ getEnvironmentClient: () => ({ nativeThriftPackageVersion: async () => { return mockRequiredVersion; @@ -11,6 +11,8 @@ jest.mock('./bridgetApi', () => ({ }), })); +const { useIsBridgetCompatible } = await import('./useIsBridgetCompatible'); + describe('useIsBridgetCompatible', () => { test.each([ ['1.9.0', true], diff --git a/dotcom-rendering/src/server/render.front.web.tsx b/dotcom-rendering/src/server/render.front.web.tsx index 6ea1090a8c7..157491a6d59 100644 --- a/dotcom-rendering/src/server/render.front.web.tsx +++ b/dotcom-rendering/src/server/render.front.web.tsx @@ -1,5 +1,5 @@ import { isString, Pillar } from '@guardian/libs'; -import { ConfigProvider } from '../components/ConfigContext.js'; +import { ConfigProvider } from '../components/ConfigContext'; import { FrontPage } from '../components/FrontPage'; import { TagFrontPage } from '../components/TagFrontPage'; import {