Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

event search collection replaces a start-param for past with the "now" #134

Merged
merged 3 commits into from
Nov 14, 2023
Merged
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
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@
"@storybook/react": "^7.3.1",
"@storybook/react-webpack5": "^7.3.1",
"@storybook/testing-library": "^0.2.0",
"@testing-library/jest-dom": "^6.0.1",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.0.0-beta",
"@testing-library/jest-dom": "^6.1.4",
"@testing-library/react": "^14.1.0",
"@testing-library/user-event": "^14.5.1",
"@types/dompurify": "^3.0.2",
"@types/jest": "^29.5.3",
"@types/jest-axe": "^3.5.5",
Expand Down
2 changes: 1 addition & 1 deletion src/common/components/htmlToReact/HtmlToReact.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import React from 'react';
import { StoryFn, Meta } from '@storybook/react';

import kukkuuTestPage from '../../../mocks/responses/page/kukkuu-page-demosivu.json';
import kukkuuTestPage from '../../../mocks/responses/cms/page/kukkuu-page-demosivu.json';
import { HtmlToReact, HtmlToReactProps, TABLE_VARIANTS } from './HtmlToReact';

// Real embedded video content from the Wordpress headless CMS.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';

import { render } from '../../../utils/testingLibrary';
import { HtmlToReact, HtmlToReactProps } from '../HtmlToReact';
import kukkuuPageDemosivu from '../../../../mocks/responses/page/kukkuu-page-demosivu.json';
import kukkuuPageDemosivu from '../../../../mocks/responses/cms/page/kukkuu-page-demosivu.json';

const defaultAllowedUnsafeTags = ['iframe'];
const defaultTrustedOrigins = [
Expand Down
18 changes: 17 additions & 1 deletion src/core/collection/Collection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ import { Link } from '../link/Link';
import { useVenuesByIdsQuery } from '../../common/venuesService/__generated__';
import { VenueType } from '../../common/venuesService/types';
import { LanguageCodeEnum } from '../../common/headlessService/types';
import { getVenueIds, isEventClosed, normalizeParamsValues } from './utils';
import {
convertDateStringInPastToNow,
getVenueIds,
isEventClosed,
normalizeParamsValues,
} from './utils';
import { DEFAULT_LOCALE } from '../../constants';
import { isPageType, isArticleType } from '../../common/headlessService/utils';

Expand Down Expand Up @@ -215,10 +220,17 @@ export function getEventCollectionCards({

export type EventSearchCollectionProps = Omit<CollectionProps, 'cards'> & {
collection: EventSearchCollectionType;
convertPastDatesToNow?: boolean;
};

/**
* EventSearchCollection uses an (LinkedEvents) URL to make a API query to fetch the related events.
*
* Use `convertPastDatesToNow = true` to fix an issue (between the CMS and the LinkedEvents) when old ended events are shown.
*/
export function EventSearchCollection({
collection,
convertPastDatesToNow = true,
...delegatedProps
}: EventSearchCollectionProps) {
const eventsApolloClient = useEventsApolloClientFromConfig();
Expand All @@ -238,8 +250,12 @@ export function EventSearchCollection({
);
const params = Object.fromEntries(searchParams.entries());
const normalizedParams = normalizeParamsValues(params);
const start = convertPastDatesToNow
? convertDateStringInPastToNow(normalizedParams.start)
: normalizedParams.start;
const variables = {
...normalizedParams,
start,
pageSize,
include: ['in_language', 'keywords', 'location', 'audience'],
};
Expand Down
122 changes: 112 additions & 10 deletions src/core/collection/__tests__/Collection.test.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
import React from 'react';
import { addDays, addYears, subDays, subYears } from 'date-fns';

import { EventSelectionCollectionType } from '../types';
import {
EventSearchCollectionType,
EventSelectionCollectionType,
} from '../types';
import { render, screen, waitFor } from '../../../common/utils/testingLibrary';
import { server } from '../../../mocks/server';
import { EventSelectionCollection } from '../Collection';
import { EventSearchCollection, EventSelectionCollection } from '../Collection';
import {
eventIds,
activeEvents,
pastEventsWithoutEndingTime,
} from '../../../mocks/queries/pageEventSelectionModule';
} from '../../../mocks/responses/linkedEvents/eventMocks';
import { CmsEndpoint } from '../../../storybook-common/constants';
import { getApolloConfig } from '../../../tests/apolloConfig';
import { frontPageCarouselVariables } from '../../../mocks/queries/linkedEvents/eventList';
import tapahtumatEventListFrontPageCarousel from '../../../mocks/responses/linkedEvents/eventList/tapahtumat-eventlist-frontpage.json';
import * as CollectionUtils from '../utils';

// Establish API mocking before all tests.
beforeAll(() => {
server.listen();
expect(activeEvents.length).toBe(2);
});

afterEach(() => {
jest.resetAllMocks();
});

describe('event selection module', () => {
it('excludes the events that have already ended', async () => {
const collection = { events: eventIds } as EventSelectionCollectionType;
Expand All @@ -33,10 +44,8 @@ describe('event selection module', () => {
});

// All the ongoing events should be shown
activeEvents.forEach(async (event) => {
expect(
await screen.findByRole('link', { name: event.name.fi }),
).toBeInTheDocument();
activeEvents.forEach((event) => {
expect(screen.getByText(event.name.fi)).toBeInTheDocument();
});

// Events without the ending time but a start time in the future are also included
Expand All @@ -46,9 +55,7 @@ describe('event selection module', () => {

// The events withoiut the ending time in the past are not
pastEventsWithoutEndingTime.forEach((event) => {
expect(
screen.queryByRole('link', { name: event.name.fi }),
).not.toBeInTheDocument();
expect(screen.queryByText(event.name.fi)).not.toBeInTheDocument();
});

// No other cards than the ongoing events should be shown.
Expand All @@ -59,3 +66,98 @@ describe('event selection module', () => {
expect(screen.getAllByRole('link').length).toBe(activeEvents.length);
});
});

describe('event search module', () => {
it.each(
[
new Date(),
subDays(new Date(), 1),
subDays(new Date(), 10),
subDays(new Date(), 100),
subYears(new Date(), 1),
subYears(new Date(), 10),
subYears(new Date(), 100),
].map((d) => d.toISOString().substring(0, 'YYYY-MM-DD'.length)),
)(
'replace the start-parameter past date-string value "%s" with "now"',
async (dateInPast) => {
const convertDateStringInPastToNowSpy = jest.spyOn(
CollectionUtils,
'convertDateStringInPastToNow',
);
const { data } = tapahtumatEventListFrontPageCarousel.eventList;
const variables = {
...Object.fromEntries(frontPageCarouselVariables),
start: dateInPast,
};
const eventSearchUrl = new URLSearchParams(variables).toString();
const collection = { url: eventSearchUrl } as EventSearchCollectionType;

render(
<EventSearchCollection collection={collection} type="carousel" />,
null,
{ ...getApolloConfig(CmsEndpoint.events) },
);

await waitFor(() => {
expect(screen.queryByText(/Page is loading/)).not.toBeInTheDocument();
});

// All the events should be shown
data.forEach((event) => {
expect(screen.getByText(event.name.fi)).toBeInTheDocument();
});

expect(convertDateStringInPastToNowSpy).toBeCalledWith(dateInPast);
expect(convertDateStringInPastToNowSpy).toHaveReturnedWith('now');
},
);

it.each(
[
addDays(new Date(), 1),
addDays(new Date(), 10),
addDays(new Date(), 100),
addYears(new Date(), 1),
addYears(new Date(), 10),
addYears(new Date(), 100),
'now',
'today',
].map((d) =>
typeof d === 'string' ? d : d.toISOString().substring(0, 10),
),
)(
'dont replace the start-parameter future date-string value "%s"',
async (dateInFuture) => {
const convertDateStringInPastToNowSpy = jest.spyOn(
CollectionUtils,
'convertDateStringInPastToNow',
);
const { data } = tapahtumatEventListFrontPageCarousel.eventList;
const variables = {
...Object.fromEntries(frontPageCarouselVariables),
start: dateInFuture,
};
const eventSearchUrl = new URLSearchParams(variables).toString();
const collection = { url: eventSearchUrl } as EventSearchCollectionType;

render(
<EventSearchCollection collection={collection} type="carousel" />,
null,
{ ...getApolloConfig(CmsEndpoint.events) },
);

await waitFor(() => {
expect(screen.queryByText(/Page is loading/)).not.toBeInTheDocument();
});

// All the events should be shown
data.forEach((event) => {
expect(screen.getByText(event.name.fi)).toBeInTheDocument();
});

expect(convertDateStringInPastToNowSpy).toBeCalledWith(dateInFuture);
expect(convertDateStringInPastToNowSpy).toHaveReturnedWith(dateInFuture);
},
);
});
1 change: 1 addition & 0 deletions src/core/collection/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const LINKEDEVENTS_DATE_NOW = 'now';
15 changes: 15 additions & 0 deletions src/core/collection/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import isPast from 'date-fns/isPast';

import { EventType } from '../../common/eventsService/types';
import normalizeKeys from '../../linkedEvents/utils/normalizeKeys';
import { LINKEDEVENTS_DATE_NOW } from './constants';

export function getVenueIds(ids: number[]): string[] {
return ids.map((id) => `tprek:${id}`);
Expand Down Expand Up @@ -41,3 +42,17 @@ export const normalizeParamsValues = (params: Record<string, string>) => {

return normalizedParams;
};

export function isValidDate(dateString: string) {
return !Number.isNaN(Date.parse(dateString));
}

export const convertDateStringInPastToNow = (start: string): string => {
const startDate = new Date(start);
const now = new Date();

if (isValidDate(start) && startDate <= now) {
return LINKEDEVENTS_DATE_NOW;
}
return start;
};
2 changes: 1 addition & 1 deletion src/core/pageContent/__tests__/Page.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import { render, screen } from '../../../common/utils/testingLibrary';
import pageMock, { sidebarLinkList } from '../__mocks__/page.mock';
import { PageContent } from '../PageContent';
import kukkuuPageDemosivu from '../../../mocks/responses/page/kukkuu-page-demosivu.json';
import kukkuuPageDemosivu from '../../../mocks/responses/cms/page/kukkuu-page-demosivu.json';
import { PageType } from '../../../common/headlessService/types';
import { ConfigProvider } from '../../configProvider/ConfigProvider';
import { Config } from '../../configProvider/configContext';
Expand Down
7 changes: 4 additions & 3 deletions src/mocks/handlers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { queryPage } from './queries/page';
import { queryPageEventSelectioModule } from './queries/pageEventSelectionModule';
import { queryPage } from './queries/cms/page';
import { queryEventList } from './queries/linkedEvents/eventList';
import { queryEventsByIds } from './queries/linkedEvents/eventsByIds';

export const handlers = [queryPageEventSelectioModule(), queryPage()];
export const handlers = [queryEventList(), queryEventsByIds(), queryPage()];
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { graphql } from 'msw';

import kukkuuPageDemosivu from '../responses/page/kukkuu-page-demosivu.json';
import kukkuuPageDemosivu from '../../responses/cms/page/kukkuu-page-demosivu.json';

export const queryPage = () =>
graphql.query('Page', (req, res, ctx) => {
Expand Down
Loading