Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { GetServerSidePropsContext } from 'next';
import * as getPageDataModule from '#utilities/pageRequests/getPageData';
import handleLiveTvRoute from './handleLiveTvRoute';

jest.mock('#utilities/pageRequests/getPageData');
jest.mock('#utilities/logResponseTime');

jest.mock('#app/lib/utilities/isTest', () => {
const originalModule = jest.requireActual('#app/lib/utilities/isTest');
return {
__esModule: true,
...originalModule,
};
});

const hindiLiveTvPageData = {
title: 'बीबीसी हिन्दी पर देखें देश-दुनिया की बड़ी ख़बरें और विश्लेषण',
description:
'देश और दुनिया की हर बड़ी ख़बर और उसका विश्लेषण. राजनीति, विज्ञान, मनोरंजन, इतिहास, खेल और भी बहुत कुछ.',
curations: [],
metadata: { atiAnalytics: [] },
};

describe('handleLiveTvRoute', () => {
const mockSetHeader = jest.fn();
const mockGetServerSidePropsContext = {
req: {
headers: {},
} as unknown as GetServerSidePropsContext['req'],
res: {
setHeader: mockSetHeader,
removeHeader: jest.fn(),
} as unknown as GetServerSidePropsContext['res'],
resolvedUrl: '/hindi/watch/bbc_hindi_tv/live',
query: { service: 'hindi' },
} satisfies GetServerSidePropsContext;

beforeEach(() => {
jest.restoreAllMocks();
jest.clearAllMocks();
jest.spyOn(getPageDataModule, 'default').mockResolvedValue({
data: {
pageData: hindiLiveTvPageData,
status: 200,
},
});
});

it('returns expected props if data fetch succeeds', async () => {
const result = await handleLiveTvRoute(mockGetServerSidePropsContext);

expect(result.props.status).toEqual(200);
expect(result.props.pageType).toEqual('liveTV');
});

it('returns error props if data fetch returns 500', async () => {
jest.spyOn(getPageDataModule, 'default').mockResolvedValue({
data: {
pageData: {},
status: 500,
},
});

const result = await handleLiveTvRoute(mockGetServerSidePropsContext);

expect(result).toEqual({
props: expect.objectContaining({
status: 500,
pageType: 'liveTV',
pathname: '/hindi/watch/bbc_hindi_tv/live',
}),
});
});

it('returns error props if data fetch returns 404', async () => {
jest.spyOn(getPageDataModule, 'default').mockResolvedValue({
data: {
pageData: {},
status: 404,
},
});

const result = await handleLiveTvRoute(mockGetServerSidePropsContext);

expect(result).toEqual({
props: expect.objectContaining({
status: 404,
pageType: 'liveTV',
pathname: '/hindi/watch/bbc_hindi_tv/live',
}),
});
});

it('throws if pageData is missing', async () => {
jest.spyOn(getPageDataModule, 'default').mockResolvedValue({
data: { pageData: null, status: 200 },
});

await expect(
handleLiveTvRoute(mockGetServerSidePropsContext),
).rejects.toThrow('AudioPage data is malformed');
});

it('sets correct cache-control header', async () => {
await handleLiveTvRoute(mockGetServerSidePropsContext);

expect(mockSetHeader).toHaveBeenCalledWith(
'Cache-Control',
expect.stringContaining('max-age=30'),
);
});
});
93 changes: 93 additions & 0 deletions ws-nextjs-app/pages/[service]/watch/[id]/live/handleLiveTvRoute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import deriveVariant from '#utilities/deriveVariant';
import { GetServerSidePropsContext } from 'next';
import { LIVE_TV_PAGE } from '#app/routes/utils/pageTypes';
import nodeLogger from '#lib/logger.node';
import PageDataParams from '#app/models/types/pageDataParams';
import { PageTypes } from '#app/models/types/global';
import getPageData from '#utilities/pageRequests/getPageData';
import logResponseTime from '#utilities/logResponseTime';
import { OK } from '#app/lib/statusCodes.const';
import { ROUTING_INFORMATION } from '#app/lib/logger.const';
import handleError from '#app/routes/utils/handleError';

const logger = nodeLogger(__filename);

export default async (context: GetServerSidePropsContext) => {
context.res.setHeader(
'Cache-Control',
'public, stale-if-error=300, stale-while-revalidate=120, max-age=30',
);

logResponseTime(
{
path: context.resolvedUrl,
},
context.res,
() => null,
);

const {
id,
service,
renderer_env: rendererEnv,
variant: variantFromUrl,
} = context.query as PageDataParams;

const variant = deriveVariant(variantFromUrl);

const { data } = await getPageData({
id,
service,
rendererEnv,
variant,
resolvedUrl: context.resolvedUrl,
pageType: LIVE_TV_PAGE,
});

const { pageData, status } = data;

let routingInfoLogger = logger.debug;
if (status !== OK) {
routingInfoLogger = logger.error;
}

if (!pageData) {
throw handleError('AudioPage data is malformed', 500);
}

routingInfoLogger(ROUTING_INFORMATION, {
url: context.resolvedUrl,
status,
pageType: LIVE_TV_PAGE,
});

context.res.statusCode = status;

const baseProps = {
status,
pageType: LIVE_TV_PAGE as PageTypes,
id,
service,
pageData: data?.pageData
? {
...data.pageData,
metadata: {
...data.pageData.metadata,
type: LIVE_TV_PAGE,
atiAnalytics: {
...data.pageData.metadata?.atiAnalytics,
contentType: 'player-live',
pageIdentifier: `${service}.${id}.livetv.page`,
},
},
}
: null,
pathname: context?.resolvedUrl,
};

return {
props: {
...baseProps,
},
};
};
5 changes: 5 additions & 0 deletions ws-nextjs-app/utilities/derivePageType/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
TV_PAGE,
MOST_READ_PAGE,
LIVE_RADIO_PAGE,
LIVE_TV_PAGE,
} from '#app/routes/utils/pageTypes';
import {
isOptimoIdCheck,
Expand Down Expand Up @@ -51,6 +52,9 @@ const isOnDemandTvPath = (pathname: string) =>
const isLiveRadioPath = (pathname: string) =>
/\/bbc_[a-z]+_radio\/liveradio/.test(pathname);

const isLiveTvPath = (path: string) =>
/\/([a-zA-Z]+)\/watch\/([^/]+)\/live/.test(path);

export default function derivePageType(pathname: string): PageTypes {
const sanitisedPathname = new URL(
removeRendererExtension(pathname),
Expand All @@ -75,6 +79,7 @@ export default function derivePageType(pathname: string): PageTypes {
if (isOnDemandTvPath(sanitisedPathname)) return TV_PAGE;
if (isOptimoIdCheck(sanitisedPathname)) return ARTICLE_PAGE;
if (isCpsIdCheck(sanitisedPathname)) return ARTICLE_PAGE;
if (isLiveTvPath(sanitisedPathname)) return LIVE_TV_PAGE;

return UNKNOWN_PAGE;
}
Loading