Move Pagination and PageSize to helper plugin and add tests

Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
soupette 2021-09-14 09:09:37 +02:00
parent 02bb3a516c
commit da8bec4d5f
11 changed files with 1276 additions and 73 deletions

View File

@ -1,8 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Box, Row } from '@strapi/parts';
import Pagination from './Pagination';
import PageSize from './PageSize';
import { Pagination, PageSize } from '@strapi/helper-plugin';
const PaginationFooter = ({ pagination }) => {
return (

View File

@ -547,10 +547,6 @@ describe('ADMIN | Pages | USERS | ListPage', () => {
margin-left: 4px;
}
.c59 {
line-height: revert;
}
.c55 {
padding: 12px;
border-radius: 4px;
@ -562,27 +558,6 @@ describe('ADMIN | Pages | USERS | ListPage', () => {
display: flex;
}
.c57 {
padding: 12px;
border-radius: 4px;
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
-webkit-text-decoration: none;
text-decoration: none;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.c58 {
color: #271fe0;
background: #ffffff;
}
.c58:hover {
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
}
.c56 {
font-size: 0.7rem;
pointer-events: none;
@ -597,16 +572,16 @@ describe('ADMIN | Pages | USERS | ListPage', () => {
fill: #c0c0cf;
}
.c60 {
.c57 {
font-size: 0.7rem;
}
.c60 svg path {
.c57 svg path {
fill: #666687;
}
.c60:focus svg path,
.c60:hover svg path {
.c57:focus svg path,
.c57:hover svg path {
fill: #4a4a6a;
}
@ -1347,30 +1322,11 @@ describe('ADMIN | Pages | USERS | ListPage', () => {
</svg>
</a>
</li>
<li>
<a
aria-current="page"
class="c57 c58 active"
href="/settings/user?pageSize=10&page=1&sort=firstname"
>
<div
class="c37"
>
Go to page 1
</div>
<span
aria-hidden="true"
class="c9 c10 c59"
>
1
</span>
</a>
</li>
<li>
<a
aria-current="page"
aria-disabled="false"
class="c55 c60 active"
class="c55 c57 active"
href="/settings/user?pageSize=10&page=1&sort=firstname"
>
<div

View File

@ -1,5 +1,6 @@
import { ThemeProvider, lightTheme } from '@strapi/parts';
import { IntlProvider } from 'react-intl';
import { MemoryRouter } from 'react-router-dom';
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
@ -13,12 +14,14 @@ export const parameters = {
export const decorators = [
Story => (
<ThemeProvider theme={lightTheme}>
<IntlProvider messages={{ en: {} }} textComponent="span" locale="en">
<main>
<Story />
</main>
</IntlProvider>
</ThemeProvider>
<MemoryRouter>
<ThemeProvider theme={lightTheme}>
<IntlProvider messages={{ en: {} }} textComponent="span" locale="en">
<main>
<Story />
</main>
</IntlProvider>
</ThemeProvider>
</MemoryRouter>
),
];

View File

@ -0,0 +1,43 @@
<!--- PageSize.stories.mdx --->
import { useEffect } from 'react';
import { Meta, ArgsTable, Canvas, Story } from '@storybook/addon-docs';
import { Main, Box } from '@strapi/parts';
import useQueryParams from '../../hooks/useQueryParams';
import PageSize from './index';
<Meta title="components/PageSize" />
# PageSize
This component is used to change the page size.
## Imports
```js
import { PageSize } from '@strapi/helper-plugin';
```
## Usage
<Canvas>
<Story name="base">
{() => {
const [{ query }, setQuery] = useQueryParams();
useEffect(() => {
setQuery({ pageSize: 10 });
}, []);
return (
<Main>
<Box paddingTop={6}>
<PageSize />
</Box>
</Main>
);
}}
</Story>
</Canvas>
### Props
This component does not have props.

View File

@ -1,22 +1,25 @@
/**
*
* PageSize
*
*/
import React from 'react';
import { Row, Select, Option } from '@strapi/parts';
import { useQueryParams } from '@strapi/helper-plugin';
import { useIntl } from 'react-intl';
import useQueryParams from '../../hooks/useQueryParams';
const PageSize = () => {
const { formatMessage } = useIntl();
const [
{
query: { pageSize },
},
setQuery,
] = useQueryParams();
const [{ query }, setQuery] = useQueryParams();
const handleChange = e => {
setQuery({
pageSize: e,
page: 1,
});
};
const pageSize = query?.pageSize || '10';
return (
<Row>
@ -34,13 +37,13 @@ const PageSize = () => {
<Option value="100">100</Option>
</Select>
{/* <Box paddingLeft={2}>
<Text textColor="neutral600" as="label" htmlFor="page-size">
{formatMessage({
id: 'components.PageFooter.select',
defaultMessage: 'Entries per page',
})}
</Text>
</Box> */}
<Text textColor="neutral600" as="label" htmlFor="page-size">
{formatMessage({
id: 'components.PageFooter.select',
defaultMessage: 'Entries per page',
})}
</Text>
</Box> */}
</Row>
);
};

View File

@ -0,0 +1,261 @@
/**
*
* Tests for PageSize
*
*/
import React from 'react';
import { render } from '@testing-library/react';
import { IntlProvider } from 'react-intl';
import { Router } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import { ThemeProvider, lightTheme } from '@strapi/parts';
import PageSize from '../index';
const messages = {
en: {
'components.PageFooter.select': 'Entries per page',
},
};
const makeApp = history => (
<Router history={history}>
<ThemeProvider theme={lightTheme}>
<IntlProvider locale="en" messages={messages} textComponent="span">
<PageSize />
</IntlProvider>
</ThemeProvider>
</Router>
);
describe('<PageSize />', () => {
it('renders and matches the snapshot', () => {
const history = createMemoryHistory();
const {
container: { firstChild },
getByText,
} = render(makeApp(history));
expect(firstChild).toMatchInlineSnapshot(`
.c2 {
font-weight: 500;
font-size: 0.75rem;
line-height: 1.33;
color: #32324d;
}
.c8 {
font-weight: 400;
font-size: 0.875rem;
line-height: 1.43;
color: #32324d;
}
.c7 {
padding-right: 16px;
padding-left: 16px;
}
.c9 {
padding-left: 12px;
}
.c0 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c5 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c1 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.c1 > * {
margin-top: 0;
margin-bottom: 0;
}
.c1 > * + * {
margin-top: 4px;
}
.c4 {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
width: 100%;
background: transparent;
border: none;
}
.c4:focus {
outline: none;
}
.c3 {
position: relative;
border: 1px solid #dcdce4;
padding-right: 12px;
border-radius: 4px;
background: #ffffff;
overflow: hidden;
}
.c3:focus-within {
border: 1px solid #4945ff;
}
.c10 {
background: transparent;
border: none;
position: relative;
z-index: 1;
}
.c10 svg {
height: 0.6875rem;
width: 0.6875rem;
}
.c10 svg path {
fill: #666687;
}
.c11 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
background: none;
border: none;
}
.c11 svg {
width: 0.375rem;
}
.c6 {
min-height: 2.5rem;
}
<div
class="c0"
>
<div>
<div
class="c1"
>
<span
class="c2"
for="select-1"
id="select-1-label"
>
Entries per page
</span>
<div
class="c3"
>
<button
aria-disabled="false"
aria-expanded="false"
aria-haspopup="listbox"
aria-labelledby="select-1-label select-1-content"
class="c4"
id="select-1"
type="button"
/>
<div
class="c5 c6"
>
<div
class="c0"
>
<div
class="c7"
>
<span
class="c8"
id="select-1-content"
>
10
</span>
</div>
</div>
<div
class="c0"
>
<button
aria-hidden="true"
class="c9 c10 c11"
tabindex="-1"
>
<svg
fill="none"
height="1em"
viewBox="0 0 14 8"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M14 .889a.86.86 0 01-.26.625L7.615 7.736A.834.834 0 017 8a.834.834 0 01-.615-.264L.26 1.514A.861.861 0 010 .889c0-.24.087-.45.26-.625A.834.834 0 01.875 0h12.25c.237 0 .442.088.615.264a.86.86 0 01.26.625z"
fill="#32324D"
fill-rule="evenodd"
/>
</svg>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
`);
expect(getByText('10')).toBeInTheDocument();
});
it('should display the pageSize correctly', () => {
const history = createMemoryHistory();
history.push({ search: 'pageSize=50' });
const { getByText } = render(makeApp(history));
expect(getByText('50')).toBeInTheDocument();
});
});

View File

@ -0,0 +1,43 @@
<!--- Pagination.stories.mdx --->
import { useEffect } from 'react';
import { Meta, ArgsTable, Canvas, Story } from '@storybook/addon-docs';
import { Main, Box } from '@strapi/parts';
import useQueryParams from '../../hooks/useQueryParams';
import Pagination from './index';
<Meta title="components/Pagination" />
# Pagination
This component is used to change the page size.
## Imports
```js
import { Pagination } from '@strapi/helper-plugin';
```
## Usage
<Canvas>
<Story name="base">
{() => {
const [{ query }, setQuery] = useQueryParams();
useEffect(() => {
setQuery({ pageSize: 10, page: 1, sort: 'firstname' });
}, []);
return (
<Main>
<Box paddingTop={6}>
<Pagination pagination={{ pageCount: 10 }} />
</Box>
</Main>
);
}}
</Story>
</Canvas>
### Props
<ArgsTable of={Pagination} />

View File

@ -30,7 +30,7 @@ import { stringify } from 'qs';
const Pagination = ({ pagination: { pageCount } }) => {
const [{ query }] = useQueryParams();
const activePage = parseInt(query.page, 10);
const activePage = parseInt(query?.page || '1', 10);
const { pathname } = useLocation();
const { formatMessage } = useIntl();
const makeSearch = page => stringify({ ...query, page }, { encode: false });
@ -47,6 +47,39 @@ const Pagination = ({ pagination: { pageCount } }) => {
</PageLink>,
];
if (pageCount <= 4) {
const links = Array.from({ length: pageCount })
.map((_, i) => i + 1)
.map(number => {
return (
<PageLink key={number} number={number} to={`${pathname}?${makeSearch(number)}`}>
{formatMessage(
{ id: 'components.pagination.go-to', defaultMessage: 'Go to page {page}' },
{ page: number }
)}
</PageLink>
);
});
return (
<PaginationCompo activePage={activePage} pageCount={pageCount}>
<PreviousLink to={`${pathname}?${previousSearch}`}>
{formatMessage({
id: 'components.pagination.go-to-previous',
defaultMessage: 'Go to previous page',
})}
</PreviousLink>
{links}
<NextLink to={`${pathname}?${nextSearch}`}>
{formatMessage({
id: 'components.pagination.go-to-next',
defaultMessage: 'Go to next page',
})}
</NextLink>
</PaginationCompo>
);
}
let firstLinksToCreate = [];
let lastLinks = [];
let lastLinksToCreate = [];

View File

@ -0,0 +1,559 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Pagination /> should display the dots correctly 1`] = `
.c6 {
font-weight: 400;
font-size: 0.75rem;
line-height: 1.33;
color: #32324d;
}
.c11 {
font-weight: 500;
font-size: 0.75rem;
line-height: 1.33;
color: #32324d;
}
.c0 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c4 {
border: 0;
-webkit-clip: rect(0 0 0 0);
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.c1 > * + * {
margin-left: 4px;
}
.c7 {
line-height: revert;
}
.c2 {
padding: 12px;
border-radius: 4px;
-webkit-text-decoration: none;
text-decoration: none;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.c9 {
padding: 12px;
border-radius: 4px;
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
-webkit-text-decoration: none;
text-decoration: none;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.c5 {
color: #32324d;
}
.c5:hover {
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
}
.c10 {
color: #271fe0;
background: #ffffff;
}
.c10:hover {
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
}
.c3 {
font-size: 0.7rem;
}
.c3 svg path {
fill: #666687;
}
.c3:focus svg path,
.c3:hover svg path {
fill: #4a4a6a;
}
.c8 {
color: #32324d;
}
<nav
aria-label="pagination"
class=""
>
<ul
class="c0 c1"
>
<li>
<a
aria-current="page"
aria-disabled="false"
class="c2 c3 active"
href="/test?page=4&pageSize=10&sort=firstname"
>
<div
class="c4"
>
Go to previous page
</div>
<svg
aria-hidden="true"
fill="none"
height="1em"
viewBox="0 0 10 16"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9.88 14.12L3.773 8 9.88 1.88 8 0 0 8l8 8 1.88-1.88z"
fill="#32324D"
/>
</svg>
</a>
</li>
<li>
<a
aria-current="page"
class="c2 c5 active"
href="/test?page=1&pageSize=10&sort=firstname"
>
<div
class="c4"
>
Go to page 1
</div>
<span
aria-hidden="true"
class="c6 c7"
>
1
</span>
</a>
</li>
<li>
<div
class="c2 c8"
>
<div
class="c4"
>
And 4 other links
</div>
<span
aria-hidden="true"
class="c6 c7"
>
</span>
</div>
</li>
<li>
<a
aria-current="page"
class="c2 c5 active"
href="/test?page=4&pageSize=10&sort=firstname"
>
<div
class="c4"
>
Go to page 4
</div>
<span
aria-hidden="true"
class="c6 c7"
>
4
</span>
</a>
</li>
<li>
<a
aria-current="page"
class="c9 c10 active"
href="/test?page=5&pageSize=10&sort=firstname"
>
<div
class="c4"
>
Go to page 5
</div>
<span
aria-hidden="true"
class="c11 c7"
>
5
</span>
</a>
</li>
<li>
<a
aria-current="page"
class="c2 c5 active"
href="/test?page=6&pageSize=10&sort=firstname"
>
<div
class="c4"
>
Go to page 6
</div>
<span
aria-hidden="true"
class="c6 c7"
>
6
</span>
</a>
</li>
<li>
<div
class="c2 c8"
>
<div
class="c4"
>
And 8 other links
</div>
<span
aria-hidden="true"
class="c6 c7"
>
</span>
</div>
</li>
<li>
<a
aria-current="page"
class="c2 c5 active"
href="/test?page=10&pageSize=10&sort=firstname"
>
<div
class="c4"
>
Go to page 10
</div>
<span
aria-hidden="true"
class="c6 c7"
>
10
</span>
</a>
</li>
<li>
<a
aria-current="page"
aria-disabled="false"
class="c2 c3 active"
href="/test?page=6&pageSize=10&sort=firstname"
>
<div
class="c4"
>
Go to next page
</div>
<svg
aria-hidden="true"
fill="none"
height="1em"
viewBox="0 0 10 16"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0 1.88L6.107 8 0 14.12 1.88 16l8-8-8-8L0 1.88z"
fill="#32324D"
/>
</svg>
</a>
</li>
</ul>
</nav>
`;
exports[`<Pagination /> should work when the pageCount is inferior or equal to 4 1`] = `
.c7 {
font-weight: 500;
font-size: 0.75rem;
line-height: 1.33;
color: #32324d;
}
.c10 {
font-weight: 400;
font-size: 0.75rem;
line-height: 1.33;
color: #32324d;
}
.c0 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c4 {
border: 0;
-webkit-clip: rect(0 0 0 0);
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.c1 > * + * {
margin-left: 4px;
}
.c8 {
line-height: revert;
}
.c2 {
padding: 12px;
border-radius: 4px;
-webkit-text-decoration: none;
text-decoration: none;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.c5 {
padding: 12px;
border-radius: 4px;
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
-webkit-text-decoration: none;
text-decoration: none;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.c6 {
color: #271fe0;
background: #ffffff;
}
.c6:hover {
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
}
.c9 {
color: #32324d;
}
.c9:hover {
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
}
.c3 {
font-size: 0.7rem;
pointer-events: none;
}
.c3 svg path {
fill: #c0c0cf;
}
.c3:focus svg path,
.c3:hover svg path {
fill: #c0c0cf;
}
.c11 {
font-size: 0.7rem;
}
.c11 svg path {
fill: #666687;
}
.c11:focus svg path,
.c11:hover svg path {
fill: #4a4a6a;
}
<nav
aria-label="pagination"
class=""
>
<ul
class="c0 c1"
>
<li>
<a
aria-current="page"
aria-disabled="true"
class="c2 c3 active"
href="/test"
tabindex="-1"
>
<div
class="c4"
>
Go to previous page
</div>
<svg
aria-hidden="true"
fill="none"
height="1em"
viewBox="0 0 10 16"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9.88 14.12L3.773 8 9.88 1.88 8 0 0 8l8 8 1.88-1.88z"
fill="#32324D"
/>
</svg>
</a>
</li>
<li>
<a
aria-current="page"
class="c5 c6 active"
href="/test?page=1&pageSize=10&sort=firstname"
>
<div
class="c4"
>
Go to page 1
</div>
<span
aria-hidden="true"
class="c7 c8"
>
1
</span>
</a>
</li>
<li>
<a
aria-current="page"
class="c2 c9 active"
href="/test?page=2&pageSize=10&sort=firstname"
>
<div
class="c4"
>
Go to page 2
</div>
<span
aria-hidden="true"
class="c10 c8"
>
2
</span>
</a>
</li>
<li>
<a
aria-current="page"
class="c2 c9 active"
href="/test?page=3&pageSize=10&sort=firstname"
>
<div
class="c4"
>
Go to page 3
</div>
<span
aria-hidden="true"
class="c10 c8"
>
3
</span>
</a>
</li>
<li>
<a
aria-current="page"
class="c2 c9 active"
href="/test?page=4&pageSize=10&sort=firstname"
>
<div
class="c4"
>
Go to page 4
</div>
<span
aria-hidden="true"
class="c10 c8"
>
4
</span>
</a>
</li>
<li>
<a
aria-current="page"
aria-disabled="false"
class="c2 c11 active"
href="/test?page=2&pageSize=10&sort=firstname"
>
<div
class="c4"
>
Go to next page
</div>
<svg
aria-hidden="true"
fill="none"
height="1em"
viewBox="0 0 10 16"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0 1.88L6.107 8 0 14.12 1.88 16l8-8-8-8L0 1.88z"
fill="#32324D"
/>
</svg>
</a>
</li>
</ul>
</nav>
`;

View File

@ -0,0 +1,301 @@
/**
*
* Tests for Pagination
*
*/
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { IntlProvider } from 'react-intl';
import { Router } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import { ThemeProvider, lightTheme } from '@strapi/parts';
import Pagination from '../index';
const messages = {
en: {
'components.pagination.go-to': 'Go to page {page}',
'components.pagination.go-to-previous': 'Go to previous page',
'components.pagination.remaining-links': 'And {number} other links',
'components.pagination.go-to-next': 'Go to next page',
},
};
const makeApp = (history, pageCount) => (
<Router history={history}>
<ThemeProvider theme={lightTheme}>
<IntlProvider locale="en" messages={messages} textComponent="span">
<Pagination pagination={{ pageCount }} />
</IntlProvider>
</ThemeProvider>
</Router>
);
describe('<Pagination />', () => {
it('renders and matches the snapshot', () => {
const history = createMemoryHistory();
const {
container: { firstChild },
} = render(makeApp(history, 1));
expect(firstChild).toMatchInlineSnapshot(`
.c7 {
font-weight: 500;
font-size: 0.75rem;
line-height: 1.33;
color: #32324d;
}
.c0 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c4 {
border: 0;
-webkit-clip: rect(0 0 0 0);
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.c1 > * + * {
margin-left: 4px;
}
.c8 {
line-height: revert;
}
.c2 {
padding: 12px;
border-radius: 4px;
-webkit-text-decoration: none;
text-decoration: none;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.c5 {
padding: 12px;
border-radius: 4px;
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
-webkit-text-decoration: none;
text-decoration: none;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.c6 {
color: #271fe0;
background: #ffffff;
}
.c6:hover {
box-shadow: 0px 1px 4px rgba(33,33,52,0.1);
}
.c3 {
font-size: 0.7rem;
pointer-events: none;
}
.c3 svg path {
fill: #c0c0cf;
}
.c3:focus svg path,
.c3:hover svg path {
fill: #c0c0cf;
}
<nav
aria-label="pagination"
class=""
>
<ul
class="c0 c1"
>
<li>
<a
aria-current="page"
aria-disabled="true"
class="c2 c3 active"
href="/"
tabindex="-1"
>
<div
class="c4"
>
Go to previous page
</div>
<svg
aria-hidden="true"
fill="none"
height="1em"
viewBox="0 0 10 16"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9.88 14.12L3.773 8 9.88 1.88 8 0 0 8l8 8 1.88-1.88z"
fill="#32324D"
/>
</svg>
</a>
</li>
<li>
<a
aria-current="page"
class="c5 c6 active"
href="/?page=1"
>
<div
class="c4"
>
Go to page 1
</div>
<span
aria-hidden="true"
class="c7 c8"
>
1
</span>
</a>
</li>
<li>
<a
aria-current="page"
aria-disabled="true"
class="c2 c3 active"
href="/"
tabindex="-1"
>
<div
class="c4"
>
Go to next page
</div>
<svg
aria-hidden="true"
fill="none"
height="1em"
viewBox="0 0 10 16"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0 1.88L6.107 8 0 14.12 1.88 16l8-8-8-8L0 1.88z"
fill="#32324D"
/>
</svg>
</a>
</li>
</ul>
</nav>
`);
});
it('should display 3 links when the active page is 1 and the pageCount is greater than 5', () => {
const history = createMemoryHistory();
render(makeApp(history, 10));
expect(screen.getByText('Go to page 1')).toBeInTheDocument();
expect(screen.getByText('Go to page 2')).toBeInTheDocument();
expect(screen.queryByText('Go to page 3')).not.toBeInTheDocument();
expect(screen.getByText('And 8 other links')).toBeInTheDocument();
expect(screen.getByText('Go to page 10')).toBeInTheDocument();
});
it('should change the page correctly', async () => {
const history = createMemoryHistory();
history.push({ pathname: '/test', search: 'page=3&pageSize=10&sort=firstname' });
render(makeApp(history, 10));
expect(screen.getByText('Go to page 1')).toBeInTheDocument();
expect(screen.getByText('Go to page 2')).toBeInTheDocument();
expect(screen.queryByText('Go to page 3')).toBeInTheDocument();
expect(screen.queryByText('Go to page 4')).toBeInTheDocument();
expect(screen.queryByText('Go to page 5')).not.toBeInTheDocument();
expect(screen.getByText('And 6 other links')).toBeInTheDocument();
expect(screen.getByText('Go to page 10')).toBeInTheDocument();
fireEvent.click(screen.getByText('Go to page 4'));
await waitFor(() => {
expect(history.location.pathname).toEqual('/test');
expect(history.location.search).toEqual('?page=4&pageSize=10&sort=firstname');
expect(screen.queryByText('Go to page 5')).toBeInTheDocument();
});
});
it('should display the dots correctly', () => {
const history = createMemoryHistory();
history.push({ pathname: '/test', search: 'page=5&pageSize=10&sort=firstname' });
const {
container: { firstChild },
} = render(makeApp(history, 10));
expect(firstChild).toMatchSnapshot();
});
it('should work when the pageCount is inferior or equal to 4', async () => {
const history = createMemoryHistory();
history.push({ pathname: '/test', search: 'page=1&pageSize=10&sort=firstname' });
const {
container: { firstChild },
} = render(makeApp(history, 4));
expect(firstChild).toMatchSnapshot();
fireEvent.click(screen.getByText('Go to page 2'));
await waitFor(() => {
expect(history.location.pathname).toEqual('/test');
expect(history.location.search).toEqual('?page=2&pageSize=10&sort=firstname');
expect(screen.getByText('Go to page 1')).toBeInTheDocument();
expect(screen.getByText('Go to page 2')).toBeInTheDocument();
expect(screen.queryByText('Go to page 3')).toBeInTheDocument();
expect(screen.queryByText('Go to page 4')).toBeInTheDocument();
});
fireEvent.click(screen.getByText('Go to page 3'));
await waitFor(() => {
expect(history.location.pathname).toEqual('/test');
expect(history.location.search).toEqual('?page=3&pageSize=10&sort=firstname');
expect(screen.getByText('Go to page 1')).toBeInTheDocument();
expect(screen.getByText('Go to page 2')).toBeInTheDocument();
expect(screen.queryByText('Go to page 3')).toBeInTheDocument();
expect(screen.queryByText('Go to page 4')).toBeInTheDocument();
});
fireEvent.click(screen.getByText('Go to page 4'));
await waitFor(() => {
expect(history.location.pathname).toEqual('/test');
expect(history.location.search).toEqual('?page=4&pageSize=10&sort=firstname');
expect(screen.getByText('Go to page 1')).toBeInTheDocument();
expect(screen.getByText('Go to page 2')).toBeInTheDocument();
expect(screen.queryByText('Go to page 3')).toBeInTheDocument();
expect(screen.queryByText('Go to page 4')).toBeInTheDocument();
});
});
});

View File

@ -195,6 +195,8 @@ export { default as SettingsPageTitle } from './components/SettingsPageTitle';
export { default as Search } from './components/Search';
export { default as Status } from './components/Status';
export { default as Form } from './components/Form';
export { default as Pagination } from './components/Pagination';
export { default as PageSize } from './components/PageSize';
// New icons
export { default as SortIcon } from './icons/SortIcon';