From 42288af46fd7946e5e061be8cc7c61f5687f3fa7 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Fri, 17 Oct 2025 12:54:54 +0100 Subject: [PATCH 1/4] Align pagination with NHS.UK frontend --- docs/upgrade-to-6.0.md | 40 +++-- src/__tests__/index.test.ts | 2 + .../navigation/pagination/Pagination.tsx | 108 +++++++++--- .../pagination/__tests__/Pagination.test.tsx | 92 ++++++---- .../__snapshots__/Pagination.test.tsx.snap | 158 +++++++++++++++++- stories/Navigation/Pagination.stories.tsx | 37 +++- 6 files changed, 356 insertions(+), 81 deletions(-) diff --git a/docs/upgrade-to-6.0.md b/docs/upgrade-to-6.0.md index ddc790a12..43a3ca57f 100644 --- a/docs/upgrade-to-6.0.md +++ b/docs/upgrade-to-6.0.md @@ -51,18 +51,14 @@ The [notification banner](https://service-manual.nhs.uk/design-system/components All components have been tested as React Server Components (RSC) but due to [multipart namespace component limitations](https://ivicabatinic.from.hr/posts/multipart-namespace-components-addressing-rsc-and-dot-notation-issues) an alternative syntax (without dot notation) can be used as a workaround: ```patch - -- -+ - Treatments -- -+ -- -+ - Symptoms -- -+ - + +- Home +- NHS services +- Hospitals ++ Home ++ NHS services ++ Hospitals + ``` ## Breaking changes @@ -441,6 +437,26 @@ To align with NHS.UK frontend, the error summary component is automatically aler ``` +### Pagination + +To align with NHS.UK frontend, the pagination link component automatically renders its own "Previous page" or "Next page" text, with "page" being visually hidden. You will need to make the following changes: + +- rename the `Pagination.Link` component to `Pagination.Item` +- move text content (or the `children` prop) to the `labelText` prop + +```patch + +- +- Treatments +- +- +- Symptoms +- ++ ++ + +``` + ### Select You must rename the `Select` prop `selectRef` to `ref` for consistency with other components: diff --git a/src/__tests__/index.test.ts b/src/__tests__/index.test.ts index 5eab14f0b..5755e98d2 100644 --- a/src/__tests__/index.test.ts +++ b/src/__tests__/index.test.ts @@ -96,7 +96,9 @@ describe('Index', () => { 'NotificationBannerLink', 'NotificationBannerTitle', 'Pagination', + 'PaginationItem', 'PaginationLink', + 'PaginationLinkText', 'Panel', 'PanelTitle', 'Radios', diff --git a/src/components/navigation/pagination/Pagination.tsx b/src/components/navigation/pagination/Pagination.tsx index a202b432a..aa00251ac 100644 --- a/src/components/navigation/pagination/Pagination.tsx +++ b/src/components/navigation/pagination/Pagination.tsx @@ -1,44 +1,98 @@ import classNames from 'classnames'; -import { forwardRef, type ComponentPropsWithoutRef } from 'react'; +import { forwardRef, type ComponentPropsWithoutRef, type FC, type PropsWithChildren } from 'react'; import { ArrowLeftIcon, ArrowRightIcon } from '#components/content-presentation/index.js'; import { type AsElementLink } from '#util/types/LinkTypes.js'; -export interface PaginationLinkProps extends AsElementLink { - previous?: boolean; - next?: boolean; -} +export type PaginationItemProps = PaginationLinkProps; + +export const PaginationItem = forwardRef( + (props, forwardedRef) => { + return ( +
  • + +
  • + ); + }, +); + +export type PaginationLinkProps = PaginationLinkTextProps & AsElementLink; export const PaginationLink = forwardRef( - ({ className, children, asElement: Element = 'a', previous, next, ...rest }, forwardedRef) => ( -
  • + ({ className, asElement: Element = 'a', ...rest }, forwardedRef) => { + const { children, labelText, previous, next, ...elementRest } = rest; + + const isPrevious = !!previous && !next; + const isNext = !!next && !previous; + + return ( - - {previous ? 'Previous' : null} - {next ? 'Next' : null} - - : - {children} - {previous ? : null} - {next ? : null} + + {isPrevious ? : null} + {isNext ? : null} -
  • - ), + ); + }, ); +export type PaginationLinkTextProps = PropsWithChildren & + ( + | WithLabelText<{ + previous: true; + next?: never; + }> + | WithLabelText<{ + previous?: never; + next: true; + }> + ); + +type WithLabelText = T & { + labelText?: string; +}; + +export const PaginationLinkText: FC = ({ + children, + previous, + next, + labelText, +}) => { + return ( + <> + {children || previous || next ? ( + + {children || ( + <> + {previous ? 'Previous' : 'Next'} + page + + )} + + ) : null} + {labelText ? ( + <> + : + {labelText} + + ) : null} + + ); +}; + export type PaginationProps = ComponentPropsWithoutRef<'nav'>; const PaginationComponent = forwardRef( @@ -56,8 +110,10 @@ const PaginationComponent = forwardRef( ); PaginationComponent.displayName = 'Pagination'; +PaginationItem.displayName = 'Pagination.Item'; PaginationLink.displayName = 'Pagination.Link'; +PaginationLinkText.displayName = 'Pagination.LinkText'; export const Pagination = Object.assign(PaginationComponent, { - Link: PaginationLink, + Item: PaginationItem, }); diff --git a/src/components/navigation/pagination/__tests__/Pagination.test.tsx b/src/components/navigation/pagination/__tests__/Pagination.test.tsx index a435ffd7d..d0da8bdaf 100644 --- a/src/components/navigation/pagination/__tests__/Pagination.test.tsx +++ b/src/components/navigation/pagination/__tests__/Pagination.test.tsx @@ -8,45 +8,73 @@ describe('Pagination', () => { expect(container).toMatchSnapshot('Pagination'); }); - describe('Pagination.Link', () => { - it('matches snapshot', () => { - const { container } = render(); + describe('Pagination.Item', () => { + it('matches snapshot with previous item', () => { + const { container } = render(); - expect(container).toMatchSnapshot('Pagination.Link'); + expect(container).toMatchSnapshot(); + }); + + it('matches snapshot with previous item (no label text)', () => { + const { container } = render(); + + expect(container).toMatchSnapshot(); + }); + + it('matches snapshot with next item', () => { + const { container } = render(); + + expect(container).toMatchSnapshot(); + }); + + it('matches snapshot with next item (no label text)', () => { + const { container } = render(); + + expect(container).toMatchSnapshot(); }); it('renders previous elements', () => { - const { container } = render(PreviousText); - - expect(container.querySelector('.nhsuk-pagination-item--previous')).toBeTruthy(); - expect(container.querySelector('.nhsuk-pagination-item--next')).toBeFalsy(); - expect(container.querySelector('.nhsuk-pagination__title')?.textContent).toBe('Previous'); - expect(container.querySelector('.nhsuk-icon--arrow-left')).toBeTruthy(); - expect(container.querySelector('.nhsuk-icon--arrow-right')).toBeFalsy(); - expect(container.querySelector('.nhsuk-pagination__page')?.textContent).toBe('PreviousText'); - expect( - container.querySelector('.nhsuk-pagination__link.nhsuk-pagination__link--prev'), - ).toBeTruthy(); - expect( - container.querySelector('.nhsuk-pagination__link.nhsuk-pagination__link--next'), - ).toBeFalsy(); + const { container } = render(); + + const itemEl = container.querySelector('li'); + const linkEl = container.querySelector('a'); + const titleEl = container.querySelector('.nhsuk-pagination__title'); + const pageEl = container.querySelector('.nhsuk-pagination__page'); + const iconEl = container.querySelector('.nhsuk-icon'); + + expect(itemEl).toHaveClass('nhsuk-pagination-item--previous'); + expect(itemEl).not.toHaveClass('nhsuk-pagination-item--next'); + + expect(linkEl).toHaveClass('nhsuk-pagination__link', 'nhsuk-pagination__link--prev'); + expect(linkEl).not.toHaveClass('nhsuk-pagination__link--next'); + + expect(titleEl).toHaveTextContent('Previous'); + expect(pageEl).toHaveTextContent('Page name'); + + expect(iconEl).toHaveClass('nhsuk-icon--arrow-left'); + expect(iconEl).not.toHaveClass('nhsuk-icon--arrow-right'); }); it('renders next elements', () => { - const { container } = render(NextText); - - expect(container.querySelector('.nhsuk-pagination-item--previous')).toBeFalsy(); - expect(container.querySelector('.nhsuk-pagination-item--next')).toBeTruthy(); - expect(container.querySelector('.nhsuk-pagination__title')?.textContent).toBe('Next'); - expect(container.querySelector('.nhsuk-icon--arrow-left')).toBeFalsy(); - expect(container.querySelector('.nhsuk-icon--arrow-right')).toBeTruthy(); - expect(container.querySelector('.nhsuk-pagination__page')?.textContent).toBe('NextText'); - expect( - container.querySelector('.nhsuk-pagination__link.nhsuk-pagination__link--prev'), - ).toBeFalsy(); - expect( - container.querySelector('.nhsuk-pagination__link.nhsuk-pagination__link--next'), - ).toBeTruthy(); + const { container } = render(); + + const itemEl = container.querySelector('li'); + const linkEl = container.querySelector('a'); + const titleEl = container.querySelector('.nhsuk-pagination__title'); + const pageEl = container.querySelector('.nhsuk-pagination__page'); + const iconEl = container.querySelector('.nhsuk-icon'); + + expect(itemEl).not.toHaveClass('nhsuk-pagination-item--previous'); + expect(itemEl).toHaveClass('nhsuk-pagination-item--next'); + + expect(linkEl).not.toHaveClass('nhsuk-pagination__link--prev'); + expect(linkEl).toHaveClass('nhsuk-pagination__link', 'nhsuk-pagination__link--next'); + + expect(titleEl).toHaveTextContent('Next'); + expect(pageEl).toHaveTextContent('Page name'); + + expect(iconEl).not.toHaveClass('nhsuk-icon--arrow-left'); + expect(iconEl).toHaveClass('nhsuk-icon--arrow-right'); }); }); }); diff --git a/src/components/navigation/pagination/__tests__/__snapshots__/Pagination.test.tsx.snap b/src/components/navigation/pagination/__tests__/__snapshots__/Pagination.test.tsx.snap index 6bc03fa1c..dcac21b2b 100644 --- a/src/components/navigation/pagination/__tests__/__snapshots__/Pagination.test.tsx.snap +++ b/src/components/navigation/pagination/__tests__/__snapshots__/Pagination.test.tsx.snap @@ -1,16 +1,63 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing -exports[`Pagination Pagination.Link matches snapshot: Pagination.Link 1`] = ` +exports[`Pagination Pagination.Item matches snapshot with next item (no label text) 1`] = ` +`; + +exports[`Pagination Pagination.Item matches snapshot with next item 1`] = ` + +`; + +exports[`Pagination Pagination.Item matches snapshot with previous item (no label text) 1`] = ` + +`; + +exports[`Pagination Pagination.Item matches snapshot with previous item 1`] = ` + diff --git a/stories/Navigation/Pagination.stories.tsx b/stories/Navigation/Pagination.stories.tsx index 3d5c46bd9..2441dc3a7 100644 --- a/stories/Navigation/Pagination.stories.tsx +++ b/stories/Navigation/Pagination.stories.tsx @@ -11,12 +11,37 @@ type Story = StoryObj; export const Standard: Story = { render: (args) => ( - - Treatments - - - Symptoms - + + + + ), +}; + +export const WithOnlyNext: Story = { + render: (args) => ( + + + + ), +}; + +export const WithOnlyPrevious: Story = { + render: (args) => ( + + + + ), +}; + +export const WithTranslations: Story = { + render: (args) => ( + + + Blaenorol + + + Nesaf + ), }; From b591d3f0e39d27ad407a4047eea75a16dd374a62 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Thu, 16 Oct 2025 12:14:47 +0100 Subject: [PATCH 2/4] Split out pagination child components --- .../navigation/pagination/Pagination.tsx | 98 +------------------ .../pagination/components/PaginationItem.tsx | 22 +++++ .../pagination/components/PaginationLink.tsx | 36 +++++++ .../components/PaginationLinkText.tsx | 47 +++++++++ .../navigation/pagination/components/index.ts | 3 + src/components/navigation/pagination/index.ts | 1 + 6 files changed, 111 insertions(+), 96 deletions(-) create mode 100644 src/components/navigation/pagination/components/PaginationItem.tsx create mode 100644 src/components/navigation/pagination/components/PaginationLink.tsx create mode 100644 src/components/navigation/pagination/components/PaginationLinkText.tsx create mode 100644 src/components/navigation/pagination/components/index.ts diff --git a/src/components/navigation/pagination/Pagination.tsx b/src/components/navigation/pagination/Pagination.tsx index aa00251ac..80295b46a 100644 --- a/src/components/navigation/pagination/Pagination.tsx +++ b/src/components/navigation/pagination/Pagination.tsx @@ -1,97 +1,6 @@ import classNames from 'classnames'; -import { forwardRef, type ComponentPropsWithoutRef, type FC, type PropsWithChildren } from 'react'; -import { ArrowLeftIcon, ArrowRightIcon } from '#components/content-presentation/index.js'; -import { type AsElementLink } from '#util/types/LinkTypes.js'; - -export type PaginationItemProps = PaginationLinkProps; - -export const PaginationItem = forwardRef( - (props, forwardedRef) => { - return ( -
  • - -
  • - ); - }, -); - -export type PaginationLinkProps = PaginationLinkTextProps & AsElementLink; - -export const PaginationLink = forwardRef( - ({ className, asElement: Element = 'a', ...rest }, forwardedRef) => { - const { children, labelText, previous, next, ...elementRest } = rest; - - const isPrevious = !!previous && !next; - const isNext = !!next && !previous; - - return ( - - - {isPrevious ? : null} - {isNext ? : null} - - ); - }, -); - -export type PaginationLinkTextProps = PropsWithChildren & - ( - | WithLabelText<{ - previous: true; - next?: never; - }> - | WithLabelText<{ - previous?: never; - next: true; - }> - ); - -type WithLabelText = T & { - labelText?: string; -}; - -export const PaginationLinkText: FC = ({ - children, - previous, - next, - labelText, -}) => { - return ( - <> - {children || previous || next ? ( - - {children || ( - <> - {previous ? 'Previous' : 'Next'} - page - - )} - - ) : null} - {labelText ? ( - <> - : - {labelText} - - ) : null} - - ); -}; +import { forwardRef, type ComponentPropsWithoutRef } from 'react'; +import { PaginationItem } from './components/index.js'; export type PaginationProps = ComponentPropsWithoutRef<'nav'>; @@ -110,9 +19,6 @@ const PaginationComponent = forwardRef( ); PaginationComponent.displayName = 'Pagination'; -PaginationItem.displayName = 'Pagination.Item'; -PaginationLink.displayName = 'Pagination.Link'; -PaginationLinkText.displayName = 'Pagination.LinkText'; export const Pagination = Object.assign(PaginationComponent, { Item: PaginationItem, diff --git a/src/components/navigation/pagination/components/PaginationItem.tsx b/src/components/navigation/pagination/components/PaginationItem.tsx new file mode 100644 index 000000000..c780e3505 --- /dev/null +++ b/src/components/navigation/pagination/components/PaginationItem.tsx @@ -0,0 +1,22 @@ +import classNames from 'classnames'; +import { forwardRef } from 'react'; +import { PaginationLink, type PaginationLinkProps } from './PaginationLink.js'; + +export type PaginationItemProps = PaginationLinkProps; + +export const PaginationItem = forwardRef( + (props, forwardedRef) => { + return ( +
  • + +
  • + ); + }, +); + +PaginationItem.displayName = 'Pagination.Item'; diff --git a/src/components/navigation/pagination/components/PaginationLink.tsx b/src/components/navigation/pagination/components/PaginationLink.tsx new file mode 100644 index 000000000..8a8a4be49 --- /dev/null +++ b/src/components/navigation/pagination/components/PaginationLink.tsx @@ -0,0 +1,36 @@ +import classNames from 'classnames'; +import { forwardRef } from 'react'; +import { ArrowLeftIcon, ArrowRightIcon } from '#components/content-presentation/index.js'; +import { type AsElementLink } from '#util/types/LinkTypes.js'; +import { PaginationLinkText, type PaginationLinkTextProps } from './PaginationLinkText.js'; + +export type PaginationLinkProps = PaginationLinkTextProps & AsElementLink; + +export const PaginationLink = forwardRef( + ({ className, asElement: Element = 'a', ...rest }, forwardedRef) => { + const { children, labelText, previous, next, ...elementRest } = rest; + + const isPrevious = !!previous && !next; + const isNext = !!next && !previous; + + return ( + + + {isPrevious ? : null} + {isNext ? : null} + + ); + }, +); + +PaginationLink.displayName = 'Pagination.Link'; diff --git a/src/components/navigation/pagination/components/PaginationLinkText.tsx b/src/components/navigation/pagination/components/PaginationLinkText.tsx new file mode 100644 index 000000000..a62085e13 --- /dev/null +++ b/src/components/navigation/pagination/components/PaginationLinkText.tsx @@ -0,0 +1,47 @@ +import { type FC, type PropsWithChildren } from 'react'; + +export type PaginationLinkTextProps = PropsWithChildren & + ( + | WithLabelText<{ + previous: true; + next?: never; + }> + | WithLabelText<{ + previous?: never; + next: true; + }> + ); + +type WithLabelText = T & { + labelText?: string; +}; + +export const PaginationLinkText: FC = ({ + children, + previous, + next, + labelText, +}) => { + return ( + <> + {children || previous || next ? ( + + {children || ( + <> + {previous ? 'Previous' : 'Next'} + page + + )} + + ) : null} + {labelText ? ( + <> + : + {labelText} + + ) : null} + + ); +}; + +PaginationLinkText.displayName = 'Pagination.LinkText'; diff --git a/src/components/navigation/pagination/components/index.ts b/src/components/navigation/pagination/components/index.ts new file mode 100644 index 000000000..36aa7ca51 --- /dev/null +++ b/src/components/navigation/pagination/components/index.ts @@ -0,0 +1,3 @@ +export * from './PaginationItem.js'; +export * from './PaginationLink.js'; +export * from './PaginationLinkText.js'; diff --git a/src/components/navigation/pagination/index.ts b/src/components/navigation/pagination/index.ts index 454be1781..cd064a997 100644 --- a/src/components/navigation/pagination/index.ts +++ b/src/components/navigation/pagination/index.ts @@ -1 +1,2 @@ +export * from './components/index.js'; export * from './Pagination.js'; From 3518f1b82bad2ab972fb5db627e5f40e1aff8996 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Fri, 17 Oct 2025 11:24:57 +0100 Subject: [PATCH 3/4] Add support for numbered pagination --- .../navigation/pagination/Pagination.tsx | 55 +- .../pagination/__tests__/Pagination.test.tsx | 195 ++++++ .../__snapshots__/Pagination.test.tsx.snap | 604 ++++++++++++++++++ .../pagination/components/PaginationItem.tsx | 42 +- .../pagination/components/PaginationLink.tsx | 43 +- .../components/PaginationLinkText.tsx | 24 + stories/Navigation/Pagination.stories.tsx | 68 ++ 7 files changed, 1002 insertions(+), 29 deletions(-) diff --git a/src/components/navigation/pagination/Pagination.tsx b/src/components/navigation/pagination/Pagination.tsx index 80295b46a..f7d01cff0 100644 --- a/src/components/navigation/pagination/Pagination.tsx +++ b/src/components/navigation/pagination/Pagination.tsx @@ -1,25 +1,54 @@ import classNames from 'classnames'; -import { forwardRef, type ComponentPropsWithoutRef } from 'react'; -import { PaginationItem } from './components/index.js'; +import { Children, forwardRef, type ComponentPropsWithoutRef } from 'react'; +import { PaginationItem, PaginationLink } from './components/index.js'; +import { childIsOfComponentType } from '#util/types/TypeGuards.js'; export type PaginationProps = ComponentPropsWithoutRef<'nav'>; const PaginationComponent = forwardRef( - ({ className, children, 'aria-label': ariaLabel = 'Pagination', ...rest }, forwardedRef) => ( - - ), + ({ className, children, 'aria-label': ariaLabel = 'Pagination', ...rest }, forwardedRef) => { + const items = Children.toArray(children); + + // Filter previous and next links + const links = items.filter((child) => childIsOfComponentType(child, PaginationLink)); + const linkPrevious = links.find(({ props }) => props.previous); + const linkNext = links.find(({ props }) => props.next); + + // Filter numbered list items + const listItems = items.filter((child) => childIsOfComponentType(child, PaginationItem)); + const listItemsNumbered = listItems.filter(({ props }) => props.number || props.ellipsis); + + return ( + + ); + }, ); PaginationComponent.displayName = 'Pagination'; export const Pagination = Object.assign(PaginationComponent, { Item: PaginationItem, + Link: PaginationLink, }); diff --git a/src/components/navigation/pagination/__tests__/Pagination.test.tsx b/src/components/navigation/pagination/__tests__/Pagination.test.tsx index d0da8bdaf..582ce2081 100644 --- a/src/components/navigation/pagination/__tests__/Pagination.test.tsx +++ b/src/components/navigation/pagination/__tests__/Pagination.test.tsx @@ -1,5 +1,6 @@ import { render } from '@testing-library/react'; import { Pagination } from '..'; +import { createRef } from 'react'; describe('Pagination', () => { it('matches snapshot', () => { @@ -8,6 +9,119 @@ describe('Pagination', () => { expect(container).toMatchSnapshot('Pagination'); }); + it('matches snapshot with next item', () => { + const { container } = render( + + + , + ); + + expect(container).toMatchSnapshot(); + }); + + it('matches snapshot with previous item', () => { + const { container } = render( + + + , + ); + + expect(container).toMatchSnapshot(); + }); + + it('matches snapshot with previous and next items', () => { + const { container } = render( + + + + , + ); + + expect(container).toMatchSnapshot(); + }); + + it('matches snapshot with previous and next items (translated)', () => { + const { container } = render( + + + Blaenorol + + + Nesaf + + , + ); + + expect(container).toMatchSnapshot(); + }); + + it('matches snapshot with numbered items', () => { + const { container } = render( + + + + + + + , + ); + + expect(container).toMatchSnapshot(); + }); + + it('matches snapshot with numbered items (translated)', () => { + const { container } = render( + + + Blaenorol + + + + + + Nesaf + + , + ); + + expect(container).toMatchSnapshot(); + }); + + it('forwards refs', () => { + const ref = createRef(); + + const { container } = render( + + + + , + ); + + const paginationEl = container.querySelector('nav'); + + expect(ref.current).toBe(paginationEl); + expect(ref.current).toHaveClass('nhsuk-pagination'); + }); + + it('forwards refs with numbered items', () => { + const ref = createRef(); + + const { container } = render( + + + + + + + , + ); + + const paginationEl = container.querySelector('nav'); + + expect(ref.current).toBe(paginationEl); + expect(ref.current).toHaveClass('nhsuk-pagination', 'nhsuk-pagination--numbered'); + }); + describe('Pagination.Item', () => { it('matches snapshot with previous item', () => { const { container } = render(); @@ -33,6 +147,18 @@ describe('Pagination', () => { expect(container).toMatchSnapshot(); }); + it('matches snapshot with number', () => { + const { container } = render(); + + expect(container).toMatchSnapshot(); + }); + + it('matches snapshot with ellipsis', () => { + const { container } = render(); + + expect(container).toMatchSnapshot(); + }); + it('renders previous elements', () => { const { container } = render(); @@ -76,5 +202,74 @@ describe('Pagination', () => { expect(iconEl).not.toHaveClass('nhsuk-icon--arrow-left'); expect(iconEl).toHaveClass('nhsuk-icon--arrow-right'); }); + + it('renders number elements', () => { + const { container } = render(); + + const itemEl = container.querySelector('li'); + const linkEl = container.querySelector('a'); + + expect(itemEl).toHaveClass('nhsuk-pagination__item'); + expect(linkEl).toHaveClass('nhsuk-pagination__link'); + expect(linkEl).toHaveTextContent('10'); + expect(linkEl).toHaveAccessibleName('Page 10'); + }); + + it('renders ellipsis elements', () => { + const { container } = render(); + + const itemEl = container.querySelector('li'); + const linkEl = container.querySelector('a'); + + expect(itemEl).toHaveClass('nhsuk-pagination__item', 'nhsuk-pagination__item--ellipsis'); + expect(itemEl).toHaveTextContent('⋯'); + expect(linkEl).toBeNull(); + }); + }); + + describe('Pagination.Link', () => { + it('matches snapshot with previous link', () => { + const { container } = render(); + + expect(container).toMatchSnapshot(); + }); + + it('matches snapshot with next link', () => { + const { container } = render(); + + expect(container).toMatchSnapshot(); + }); + + it('renders previous elements', () => { + const { container } = render(); + + const linkEl = container.querySelector('a'); + const titleEl = container.querySelector('.nhsuk-pagination__title'); + const iconEl = container.querySelector('.nhsuk-icon'); + + expect(linkEl).toHaveClass('nhsuk-pagination__previous'); + expect(linkEl).not.toHaveClass('nhsuk-pagination__next'); + + expect(titleEl).toHaveTextContent('Previous'); + + expect(iconEl).toHaveClass('nhsuk-icon--arrow-left'); + expect(iconEl).not.toHaveClass('nhsuk-icon--arrow-right'); + }); + + it('renders next elements', () => { + const { container } = render(); + + const linkEl = container.querySelector('a'); + const titleEl = container.querySelector('.nhsuk-pagination__title'); + const iconEl = container.querySelector('.nhsuk-icon'); + + expect(linkEl).not.toHaveClass('nhsuk-pagination__previous'); + expect(linkEl).toHaveClass('nhsuk-pagination__next'); + + expect(titleEl).toHaveTextContent('Next'); + + expect(iconEl).not.toHaveClass('nhsuk-icon--arrow-left'); + expect(iconEl).toHaveClass('nhsuk-icon--arrow-right'); + }); }); }); diff --git a/src/components/navigation/pagination/__tests__/__snapshots__/Pagination.test.tsx.snap b/src/components/navigation/pagination/__tests__/__snapshots__/Pagination.test.tsx.snap index dcac21b2b..9bc515934 100644 --- a/src/components/navigation/pagination/__tests__/__snapshots__/Pagination.test.tsx.snap +++ b/src/components/navigation/pagination/__tests__/__snapshots__/Pagination.test.tsx.snap @@ -1,5 +1,15 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +exports[`Pagination Pagination.Item matches snapshot with ellipsis 1`] = ` +
    +
  • + ⋯ +
  • +
    +`; + exports[`Pagination Pagination.Item matches snapshot with next item (no label text) 1`] = `
  • `; +exports[`Pagination Pagination.Item matches snapshot with number 1`] = ` +
    +
  • + + 10 + +
  • +
    +`; + exports[`Pagination Pagination.Item matches snapshot with previous item (no label text) 1`] = `
  • `; +exports[`Pagination Pagination.Link matches snapshot with next link 1`] = ` + +`; + +exports[`Pagination Pagination.Link matches snapshot with previous link 1`] = ` + +`; + +exports[`Pagination matches snapshot with next item 1`] = ` + +`; + +exports[`Pagination matches snapshot with numbered items (translated) 1`] = ` + +`; + +exports[`Pagination matches snapshot with numbered items 1`] = ` + +`; + +exports[`Pagination matches snapshot with previous and next items (translated) 1`] = ` + +`; + +exports[`Pagination matches snapshot with previous and next items 1`] = ` + +`; + +exports[`Pagination matches snapshot with previous item 1`] = ` + +`; + exports[`Pagination matches snapshot: Pagination 1`] = `