diff --git a/dotcom-rendering/src/components/GetMatchNav.importable.tsx b/dotcom-rendering/src/components/GetMatchNav.importable.tsx index c643904422f..ae599b6fb21 100644 --- a/dotcom-rendering/src/components/GetMatchNav.importable.tsx +++ b/dotcom-rendering/src/components/GetMatchNav.importable.tsx @@ -1,4 +1,5 @@ import { css } from '@emotion/react'; +import { isObject } from '@guardian/libs'; import { from } from '@guardian/source/foundations'; import type { SWRConfiguration } from 'swr'; import { ArticleDesign, type ArticleFormat } from '../lib/articleFormat'; @@ -36,6 +37,36 @@ const fallbackData = { awayTeam: fallbackTeam, } satisfies MatchData; +const validateMatchData = (data: unknown): data is MatchData => { + if (!isObject(data)) { + return false; + } + + const homeTeam = data.homeTeam; + if ( + !isObject(homeTeam) || + typeof homeTeam.name !== 'string' || + homeTeam.name.length === 0 || + typeof homeTeam.score !== 'number' || + isNaN(homeTeam.score) + ) { + return false; + } + + const awayTeam = data.awayTeam; + if ( + !isObject(awayTeam) || + typeof awayTeam.name !== 'string' || + awayTeam.name.length === 0 || + typeof awayTeam.score !== 'number' || + isNaN(awayTeam.score) + ) { + return false; + } + + return true; +}; + /** * Wrapper around `MatchNav` with loading and fallback. * @@ -97,7 +128,14 @@ export const GetMatchNav = ({ ); } } - if (data) { + + if (!data) { + // this should never happen because we pass fallback data to SWR + return null; + } + + const isDataValid = validateMatchData(data); + if (isDataValid) { return (