Skip to content

Commit dd0def2

Browse files
authored
Merge branch 'latest' into WS-2836-integrate-tool-tip-component-for-save-for-later
2 parents 39576d0 + 138c4bd commit dd0def2

61 files changed

Lines changed: 4661 additions & 2518 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@
9191
"sharp": "0.35.3",
9292
"temporal-polyfill": "0.3.0",
9393
"undici": "8.9.0",
94-
"uuid": "13.0.1",
9594
"winston": "patch:winston@3.8.2#./patches/winston-file-descriptor.patch"
9695
},
9796
"devDependencies": {

src/app/hooks/useSportDataPolling/fixture/fixtureSportData.js renamed to src/app/components-webcore/SportDataHeader/head-to-head-v2/fixture/sportData.js

File renamed without changes.

src/app/hooks/useSportDataPolling/fixture/fixtureSportDataUpdate.js renamed to src/app/components-webcore/SportDataHeader/head-to-head-v2/fixture/sportDataUpdate.js

File renamed without changes.

src/app/components-webcore/SportDataHeader/head-to-head-v2/head-to-head-v2.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { use } from 'react';
22
import { ServiceContext } from '#app/contexts/ServiceContext';
3-
import useSportDataPolling from '#app/hooks/useSportDataPolling';
3+
import usePolling from '#app/hooks/usePolling';
44
import useToggle from '#app/hooks/useToggle';
55
import HeadToHeadHeader from './components/head-to-head-header';
66
import { HeadToHeadBanner } from './components/head-to-head-banner';
@@ -26,10 +26,16 @@ export const HeadToHeadV2 = ({
2626
const { enabled: sportHeaderPollEnabled } = useToggle('sportDataPolling');
2727
const { translations, service } = use(ServiceContext);
2828

29-
const { currentSportData } = useSportDataPolling(
30-
initialSportData,
31-
Boolean(sportHeaderPollEnabled) && isSportDataLive,
32-
);
29+
const currentSportData = usePolling<
30+
{ sportDataEvent: HeadToHeadV2Data },
31+
HeadToHeadV2Data
32+
>({
33+
initialData: initialSportData,
34+
enabled: Boolean(sportHeaderPollEnabled) && isSportDataLive,
35+
endpoint: 'sport',
36+
params: { sportDataEventUrn: initialSportData.urn },
37+
returnedData: response => response.sportDataEvent,
38+
});
3339

3440
const hasActions =
3541
(currentSportData?.home?.actions?.length ?? 0) > 0 ||

src/app/components-webcore/SportDataHeader/head-to-head-v2/tests/index.test.tsx

Lines changed: 119 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
import { act, renderHook } from '@testing-library/react';
12
import {
23
render,
34
screen,
45
} from '#app/components/react-testing-library-with-providers';
6+
import * as fetchPolledData from '#app/lib/utilities/fetchPolledData';
7+
import sportData from '../fixture/sportData';
8+
import sportDataUpdate from '../fixture/sportDataUpdate';
59
import cancelledMockData from '../static-data/event/transformed/cancelled.json';
610
import postponedMockData from '../static-data/event/transformed/postponed.json';
711
import suspendedMockData from '../static-data/event/transformed/suspended.json';
@@ -28,11 +32,9 @@ import {
2832
import HeadToHead from '../head-to-head-v2';
2933
import type { HeadToHeadV2Data } from '../types';
3034

31-
jest.mock('#app/hooks/useSportDataPolling', () => ({
35+
jest.mock('#app/hooks/usePolling', () => ({
3236
__esModule: true,
33-
default: jest.fn(initialSportData => ({
34-
currentSportData: initialSportData,
35-
})),
37+
default: jest.fn(({ initialData }) => initialData),
3638
}));
3739

3840
jest.mock('../helpers/localise-datetime', () => ({
@@ -822,3 +824,116 @@ describe('Head to Head Component', () => {
822824
},
823825
);
824826
});
827+
828+
describe('head-to-head-v2 sport data polling', () => {
829+
const { default: usePolling, POLLING_INTERVAL } = jest.requireActual<
830+
typeof import('#app/hooks/usePolling')
831+
>('#app/hooks/usePolling');
832+
833+
const initialSportData = sportData.data
834+
.sportDataEvent as unknown as HeadToHeadV2Data;
835+
const updatedSportData = sportDataUpdate.data
836+
.sportDataEvent as unknown as HeadToHeadV2Data;
837+
838+
const advancePolling = async () => {
839+
await act(async () => {
840+
jest.advanceTimersByTime(POLLING_INTERVAL);
841+
await Promise.resolve();
842+
});
843+
};
844+
845+
const renderSportDataPolling = (enabled = true) =>
846+
renderHook(() =>
847+
usePolling<{ sportDataEvent: HeadToHeadV2Data }, HeadToHeadV2Data>({
848+
initialData: initialSportData,
849+
enabled,
850+
endpoint: 'sport',
851+
params: { sportDataEventUrn: initialSportData.urn },
852+
returnedData: response => response.sportDataEvent,
853+
}),
854+
);
855+
856+
beforeAll(() => {
857+
jest.useFakeTimers();
858+
});
859+
860+
afterAll(() => {
861+
jest.useRealTimers();
862+
});
863+
864+
beforeEach(() => {
865+
jest.clearAllMocks();
866+
});
867+
868+
it('should return the initial sport data on initialisation', () => {
869+
jest.spyOn(fetchPolledData, 'default').mockResolvedValue(null);
870+
871+
const { result } = renderSportDataPolling();
872+
873+
expect(result.current).toStrictEqual(initialSportData);
874+
});
875+
876+
it('should poll the sport endpoint with the encoded event urn when enabled', async () => {
877+
const fetchSpy = jest
878+
.spyOn(fetchPolledData, 'default')
879+
.mockResolvedValue(null);
880+
881+
renderSportDataPolling(true);
882+
883+
await advancePolling();
884+
885+
expect(fetchSpy).toHaveBeenCalledTimes(1);
886+
expect(fetchSpy).toHaveBeenCalledWith('sport', {
887+
params: { sportDataEventUrn: initialSportData.urn },
888+
});
889+
});
890+
891+
it('should not fetch data when polling is disabled', async () => {
892+
const fetchSpy = jest
893+
.spyOn(fetchPolledData, 'default')
894+
.mockResolvedValue(null);
895+
896+
renderSportDataPolling(false);
897+
898+
await advancePolling();
899+
900+
expect(fetchSpy).not.toHaveBeenCalled();
901+
});
902+
903+
it('should update sport data when new data is returned after polling', async () => {
904+
jest.spyOn(fetchPolledData, 'default').mockResolvedValue({
905+
data: { sportDataEvent: updatedSportData },
906+
status: 200,
907+
});
908+
909+
const { result } = renderSportDataPolling();
910+
911+
await advancePolling();
912+
913+
expect(result.current).toStrictEqual(updatedSportData);
914+
});
915+
916+
it('should keep the current sport data when no data is returned after polling', async () => {
917+
jest.spyOn(fetchPolledData, 'default').mockResolvedValue(null);
918+
919+
const { result } = renderSportDataPolling();
920+
921+
await advancePolling();
922+
923+
expect(result.current).toStrictEqual(initialSportData);
924+
});
925+
926+
it('should clear the polling interval when unmounted', async () => {
927+
const fetchSpy = jest
928+
.spyOn(fetchPolledData, 'default')
929+
.mockResolvedValue(null);
930+
931+
const { unmount } = renderSportDataPolling();
932+
933+
unmount();
934+
935+
await advancePolling();
936+
937+
expect(fetchSpy).not.toHaveBeenCalled();
938+
});
939+
});

src/app/components/Curation/HierarchicalGrid/index.styles.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,23 @@ const styles = {
3535
},
3636
},
3737
}),
38+
inSituMedia: ({ spacings }: Theme) =>
39+
css({
40+
marginBottom: `${spacings.FULL}rem`,
41+
'.media-container': {
42+
margin: 0,
43+
},
44+
// keep hidden player controls from widening rtl pages on mobile
45+
'.media-player': {
46+
overflow: 'hidden',
47+
},
48+
}),
49+
headlineLink: () =>
50+
css({
51+
'&::before': {
52+
display: 'none',
53+
},
54+
}),
3855
list: ({ mq, spacings, isLite }: Theme) =>
3956
css({
4057
padding: 0,

0 commit comments

Comments
 (0)