From 7606368ca188c928970e56514e1b2725d9e92e21 Mon Sep 17 00:00:00 2001 From: Daniel Marcano Date: Mon, 9 Oct 2023 00:28:55 +0200 Subject: [PATCH] Feat: add PaginationListItem unit tests, and minor refactors to improve code consistency --- __mocks__/nextJsRouter.mjs | 2 +- .../__tests__/index.test.mjs | 56 +++++++++++++++++++ .../PaginationListItem/index.module.css | 12 ++-- .../Pagination/PaginationListItem/index.tsx | 12 +--- components/Common/Pagination/index.tsx | 16 ++---- .../Common/Pagination/useGetPageElements.tsx | 3 + 6 files changed, 75 insertions(+), 26 deletions(-) create mode 100644 components/Common/Pagination/PaginationListItem/__tests__/index.test.mjs diff --git a/__mocks__/nextJsRouter.mjs b/__mocks__/nextJsRouter.mjs index a6a57785d2ac0..23ac5937456bf 100644 --- a/__mocks__/nextJsRouter.mjs +++ b/__mocks__/nextJsRouter.mjs @@ -2,7 +2,7 @@ jest.mock('next/router', () => ({ useRouter() { return { isReady: true, - asPath: '/link', + asPath: '/', }; }, })); diff --git a/components/Common/Pagination/PaginationListItem/__tests__/index.test.mjs b/components/Common/Pagination/PaginationListItem/__tests__/index.test.mjs new file mode 100644 index 0000000000000..e5d91a4c10d52 --- /dev/null +++ b/components/Common/Pagination/PaginationListItem/__tests__/index.test.mjs @@ -0,0 +1,56 @@ +import { render, screen } from '@testing-library/react'; +import { IntlProvider } from 'react-intl'; + +import PaginationListItem from '@/components/Common/Pagination/PaginationListItem'; + +function renderPaginationListItem({ + url, + pageNumber, + currentPage, + totalPages, +}) { + render( + + + + ); +} + +describe('PaginationListItem', () => { + it('Renders the list item correctly, including the corresponding ARIA attributes', () => { + const pageNumber = 1; + const totalPages = 10; + const url = 'http://'; + + renderPaginationListItem({ + url, + currentPage: 1, + pageNumber, + totalPages, + }); + + const listItem = screen.getByRole('listitem'); + + expect(listItem).toBeVisible(); + expect(listItem).toHaveAttribute('aria-posinset', String(pageNumber)); + expect(listItem).toHaveAttribute('aria-setsize', String(totalPages)); + + expect(screen.getByRole('link')).toHaveAttribute('href', url); + }); + + it('Assigns aria-current="page" attribute to the link when the current page is equal to the page number', () => { + renderPaginationListItem({ + url: 'http://', + currentPage: 1, + pageNumber: 1, + totalPages: 10, + }); + + expect(screen.getByRole('link')).toHaveAttribute('aria-current', 'page'); + }); +}); diff --git a/components/Common/Pagination/PaginationListItem/index.module.css b/components/Common/Pagination/PaginationListItem/index.module.css index 60ae5cdd9ccd0..e175539a42218 100644 --- a/components/Common/Pagination/PaginationListItem/index.module.css +++ b/components/Common/Pagination/PaginationListItem/index.module.css @@ -1,16 +1,18 @@ -.listItem { +.listItem, +.listItem:link, +.listItem:active { @apply flex - h-10 + h-10 w-10 items-center justify-center rounded px-3 py-2.5 - !text-neutral-800 + text-neutral-800 hover:bg-neutral-100 aria-current:bg-green-600 - aria-current:!text-white - dark:!text-neutral-200 + aria-current:text-white + dark:text-neutral-200 hover:dark:bg-neutral-900; } diff --git a/components/Common/Pagination/PaginationListItem/index.tsx b/components/Common/Pagination/PaginationListItem/index.tsx index 5f5bd783f0c67..105ee30eeb17e 100644 --- a/components/Common/Pagination/PaginationListItem/index.tsx +++ b/components/Common/Pagination/PaginationListItem/index.tsx @@ -8,9 +8,7 @@ import styles from './index.module.css'; export type PaginationListItemProps = { url: string; pageNumber: number; - /** - * One-based number of the current page - */ + // One-based number of the current page currentPage: number; totalPages: number; }; @@ -29,12 +27,8 @@ const PaginationListItem: FC = ({ prefetch={false} href={url} aria-label={intl.formatMessage( - { - id: 'components.common.pagination.pageLabel', - }, - { - pageNumber, - } + { id: 'components.common.pagination.pageLabel' }, + { pageNumber } )} className={styles.listItem} {...(pageNumber === currentPage && { 'aria-current': 'page' })} diff --git a/components/Common/Pagination/index.tsx b/components/Common/Pagination/index.tsx index 4897fddf04847..8eff8017e01cf 100644 --- a/components/Common/Pagination/index.tsx +++ b/components/Common/Pagination/index.tsx @@ -3,24 +3,18 @@ import type { FC } from 'react'; import { FormattedMessage, useIntl } from 'react-intl'; import Button from '@/components/Common/Button'; +import { useGetPageElements } from '@/components/Common/Pagination/useGetPageElements'; import styles from './index.module.css'; -import { useGetPageElements } from './useGetPageElements'; -type Page = { - url: string; -}; +type Page = { url: string }; export type PaginationProps = { - /** - * One-based number of the current page - */ + // One-based number of the current page currentPage: number; pages: Page[]; - /** - * The number of page buttons on each side of the current page button - * @default 1 - */ + // The number of page buttons on each side of the current page button + // @default 1 currentPageSiblingsCount?: number; }; diff --git a/components/Common/Pagination/useGetPageElements.tsx b/components/Common/Pagination/useGetPageElements.tsx index 6b5cb36914a8a..a6e02f44d23af 100644 --- a/components/Common/Pagination/useGetPageElements.tsx +++ b/components/Common/Pagination/useGetPageElements.tsx @@ -29,6 +29,9 @@ const MINIMUM_AMOUNT_OF_ELEMENTS = 3; // Not more than two ellipses will be shown at the same time const MAXIMUM_AMOUNT_OF_ELLIPSES = 2; +// The logic of this custom hook has taken the internal logic of +// React MUI's Pagination component as reference. More info here: +// https://github.com/mui/material-ui/blob/master/packages/mui-material/src/usePagination/usePagination.js export const useGetPageElements = ( currentPage: PaginationProps['currentPage'], pages: PaginationProps['pages'],