11import 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' ;
34import {
45 matchDayLive ,
56 matchFixture ,
67 matchResult ,
78} from '../../../fixtures/manual/footballMatches' ;
89import type { FEFootballMatchHeader } from '../../frontend/feFootballMatchHeader' ;
10+ import { FootballMatchHeader as FootballMatchHeaderComponent } from './FootballMatchHeader' ;
911
1012const 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
1424export 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
6486export 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
108140export 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+ } ) ;
0 commit comments