Skip to content

Commit 1dd66a7

Browse files
Added storybook interaction tests for football match header
Co-authored-by: James M <1166188+jamesmockett@users.noreply.github.com>
1 parent 18a1d7a commit 1dd66a7

4 files changed

Lines changed: 77 additions & 15 deletions

File tree

dotcom-rendering/fixtures/manual/footballMatches.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export const matchDayLive: FEMatchDay = {
6666
},
6767
awayTeam: {
6868
...matchData.awayTeam,
69-
score: 3,
69+
score: 4,
7070
},
7171
};
7272

dotcom-rendering/src/components/FootballMatchHeader/FootballMatchHeader.stories.tsx

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
11
import type { Meta, StoryObj } from '@storybook/react-webpack5';
2-
import { FootballMatchHeader as FootballMatchHeaderComponent } from './FootballMatchHeader';
2+
import { expect, waitFor, within } from 'storybook/test';
3+
import { SWRConfig } from 'swr';
34
import {
45
matchDayLive,
56
matchFixture,
67
matchResult,
78
} from '../../../fixtures/manual/footballMatches';
89
import type { FEFootballMatchHeader } from '../../frontend/feFootballMatchHeader';
10+
import { FootballMatchHeader as FootballMatchHeaderComponent } from './FootballMatchHeader';
911

1012
const meta = {
1113
component: FootballMatchHeaderComponent,
14+
decorators: [
15+
(Story) => (
16+
// This resets the SWR cache on every story
17+
<SWRConfig value={{ provider: () => new Map() }}>
18+
<Story />
19+
</SWRConfig>
20+
),
21+
],
1222
} satisfies Meta<typeof FootballMatchHeaderComponent>;
1323

1424
export default meta;
@@ -49,7 +59,7 @@ export const Fixture = {
4959
},
5060
edition: 'UK',
5161
getHeaderData: () =>
52-
Promise.resolve({
62+
getMockData({
5363
...feHeaderData,
5464
liveURL: undefined,
5565
reportURL: undefined,
@@ -59,6 +69,18 @@ export const Fixture = {
5969
'https://api.nextgen.guardianapps.co.uk/football/api/match-header/2026/02/08/26247/48490.json',
6070
),
6171
},
72+
play: async ({ canvasElement }) => {
73+
const list = await getListElement(canvasElement);
74+
const items = within(list).getAllByRole('listitem');
75+
void expect(items.length).toBe(1);
76+
void expect(items[0]).toHaveTextContent('Match info');
77+
78+
await waitFor(() => {
79+
const items = within(list).getAllByRole('listitem');
80+
void expect(items.length).toBe(1);
81+
void expect(items[0]).toHaveTextContent('Match info');
82+
});
83+
},
6284
} satisfies Story;
6385

6486
export const Live = {
@@ -93,16 +115,26 @@ export const Live = {
93115
},
94116
edition: 'EUR',
95117
matchHeaderURL: new URL(
96-
'https://api.nextgen.guardianapps.co.uk/football/api/match-header/2026/02/11/39/9.json',
118+
'https://api.nextgen.guardianapps.co.uk/football/api/match-header/2026/02/08/26247/48490.json',
97119
),
98120
refreshInterval: Fixture.args.refreshInterval,
99121
getHeaderData: () =>
100-
Promise.resolve({
122+
getMockData({
101123
...feHeaderData,
102124
footballMatch: matchDayLive,
103125
reportURL: undefined,
104126
}),
105127
},
128+
play: async ({ canvasElement }) => {
129+
const canvas = within(canvasElement);
130+
expect(canvas.getByLabelText('Score: 0')).toBeInTheDocument();
131+
expect(canvas.getByLabelText('Score: 13')).toBeInTheDocument();
132+
133+
await waitFor(() => {
134+
expect(canvas.getByLabelText('Score: 3')).toBeInTheDocument();
135+
expect(canvas.getByLabelText('Score: 4')).toBeInTheDocument();
136+
});
137+
},
106138
} satisfies Story;
107139

108140
export const Result = {
@@ -118,13 +150,43 @@ export const Result = {
118150
},
119151
edition: 'AU',
120152
matchHeaderURL: new URL(
121-
'https://api.nextgen.guardianapps.co.uk/football/api/match-header/2026/02/10/45/42.json',
153+
'https://api.nextgen.guardianapps.co.uk/football/api/match-header/2026/02/08/26247/48490.json',
122154
),
123155
refreshInterval: Fixture.args.refreshInterval,
124156
getHeaderData: () =>
125-
Promise.resolve({
157+
getMockData({
126158
...feHeaderData,
127159
footballMatch: matchResult,
128160
}),
129161
},
162+
163+
play: async ({ canvasElement }) => {
164+
const list = await getListElement(canvasElement);
165+
const items = within(list).getAllByRole('listitem');
166+
void expect(items.length).toBe(1);
167+
void expect(items[0]).toHaveTextContent('Match info');
168+
169+
await waitFor(() => {
170+
const items = within(list).getAllByRole('listitem');
171+
void expect(items.length).toBe(3);
172+
void expect(items[0]).toHaveTextContent('Match report');
173+
void expect(items[1]).toHaveTextContent('Live feed');
174+
void expect(items[2]).toHaveTextContent('Match info');
175+
});
176+
},
130177
} satisfies Story;
178+
179+
const getListElement = async (canvasElement: HTMLElement) => {
180+
const canvas = within(canvasElement);
181+
const nav = await canvas.findByRole('navigation');
182+
const navQueries = within(nav);
183+
// Get the list element that is within a nav element
184+
return await navQueries.findByRole('list');
185+
};
186+
187+
const getMockData = (data: FEFootballMatchHeader) =>
188+
new Promise((resolve) => {
189+
setTimeout(() => {
190+
resolve(data);
191+
}, 1000);
192+
});

dotcom-rendering/src/components/FootballMatchHeader/FootballMatchHeader.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { css } from '@emotion/react';
2+
import { log } from '@guardian/libs';
23
import {
34
from,
45
headlineBold20Object,
@@ -11,6 +12,8 @@ import {
1112
until,
1213
} from '@guardian/source/foundations';
1314
import { type ComponentProps, type ReactNode, useMemo } from 'react';
15+
import type { SWRConfiguration } from 'swr';
16+
import useSWR from 'swr';
1417
import type { FootballMatch } from '../../footballMatchV2';
1518
import { grid } from '../../grid';
1619
import {
@@ -23,11 +26,8 @@ import type { ColourName } from '../../paletteDeclarations';
2326
import { BigNumber } from '../BigNumber';
2427
import { FootballCrest } from '../FootballCrest';
2528
import { background, border, primaryText, secondaryText } from './colours';
26-
import { Tabs } from './Tabs';
27-
import type { SWRConfiguration } from 'swr';
28-
import useSWR from 'swr';
2929
import { type HeaderData, parse as parseHeaderData } from './headerData';
30-
import { log } from '@guardian/libs';
30+
import { Tabs } from './Tabs';
3131

3232
type Props = {
3333
leagueName: string;

dotcom-rendering/src/components/FootballMatchHeader/headerData.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1+
import type { ComponentProps } from 'react';
12
import { safeParse } from 'valibot';
23
import {
3-
parseFootballMatchV2,
44
type FootballMatch,
5+
parseFootballMatchV2,
56
} from '../../footballMatchV2';
6-
import { error, fromValibot, ok, type Result } from '../../lib/result';
77
import {
8-
feFootballMatchHeaderSchema,
98
type FEFootballMatchHeader,
9+
feFootballMatchHeaderSchema,
1010
} from '../../frontend/feFootballMatchHeader';
1111
import { safeParseURL } from '../../lib/parse';
12-
import type { ComponentProps } from 'react';
12+
import { error, fromValibot, ok, type Result } from '../../lib/result';
1313
import type { Tabs } from './Tabs';
1414

1515
export type HeaderData = {

0 commit comments

Comments
 (0)