Skip to content

Commit

Permalink
feat(Pagination): Add pageHref and onPageClick props
Browse files Browse the repository at this point in the history
  • Loading branch information
allyssonsantos committed Apr 4, 2019
1 parent a64bfec commit 3f704a7
Show file tree
Hide file tree
Showing 11 changed files with 727 additions and 1,225 deletions.
121 changes: 77 additions & 44 deletions components/Pagination/Pagination.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import pagination from './utils/pagination';
const Wrapper = styled.nav`
align-items: center;
display: flex;
justify-content: center;
padding: 16px !important;
`;

Expand All @@ -22,48 +23,77 @@ const Pagination = ({
activePageAriaLabel,
nextButtonText,
pageAriaLabel,
pageHref,
prevButtonText,
onClick,
onPageClick,
totalPages,
...props
}) => (
<Wrapper aria-label={ariaLabel} {...props}>
<ActionButton
aria-disabled={activePage === 1}
disabled={activePage === 1}
onClick={() => onClick(activePage - 1)}
>
{prevButtonText}
</ActionButton>
{pagination({ totalPages, activePage }).map((page, index) => {
if (page === '...') {
return <Dots key={generateDotsKey(index)} />;
}

return (
<Page
aria-current={activePage === page ? 'page' : false}
aria-label={`${
activePage === page ? `${activePageAriaLabel}, ` : ''
}${pageAriaLabel} ${page}`}
key={page}
active={activePage === page}
onClick={() => onClick(page)}
>
{page}
</Page>
);
})}

<ActionButton
aria-disabled={activePage === totalPages}
disabled={activePage === totalPages}
onClick={() => onClick(activePage + 1)}
>
{nextButtonText}
</ActionButton>
</Wrapper>
);
}) => {
const handlePageClick = page => e => {
if (!onPageClick) {
return undefined;
}

e.preventDefault();

if (page <= 0 || page > totalPages) {
return false;
}

return onPageClick(page);
};

const handleHref = page => {
if (!pageHref || onPageClick || page <= 0 || page > totalPages) {
return undefined;
}

return pageHref(page);
};

return (
<Wrapper aria-label={ariaLabel} {...props}>
<ActionButton
aria-disabled={activePage === 1}
disabled={activePage === 1}
onClick={handlePageClick(activePage - 1)}
href={handleHref(activePage - 1)}
>
{prevButtonText}
</ActionButton>

{pagination({ totalPages, activePage }).map((page, index) => {
if (page === '...') {
return <Dots key={generateDotsKey(index)} />;
}

return (
<Page
aria-current={activePage === page ? 'page' : false}
aria-label={`${
activePage === page ? `${activePageAriaLabel}, ` : ''
}${pageAriaLabel} ${page}`}
key={page}
active={activePage === page}
onClick={handlePageClick(page)}
href={handleHref(page)}
>
{page}
</Page>
);
})}

<ActionButton
aria-disabled={activePage === totalPages}
disabled={activePage === totalPages}
onClick={handlePageClick(activePage + 1)}
href={handleHref(activePage + 1)}
>
{nextButtonText}
</ActionButton>
</Wrapper>
);
};

Pagination.propTypes = {
/** Set the aria-label html attribute to the root element of pagination */
Expand All @@ -74,14 +104,16 @@ Pagination.propTypes = {
activePageAriaLabel: PropTypes.string,
/** Set the number of pages to be displayed. */
totalPages: PropTypes.number.isRequired,
/** Next page button text */
/** Set next page button text */
nextButtonText: PropTypes.string,
/** Page number button aria-label html attribute */
/** Page number button aria-label html attribute. */
pageAriaLabel: PropTypes.string,
/** Previous page button text */
/** Set the page anchor element href value. */
pageHref: PropTypes.func,
/** Set previous page button text. */
prevButtonText: PropTypes.string,
/** Function to be called when prev, next or page button is clicked, it receives the next page number as an argument. */
onClick: PropTypes.func,
onPageClick: PropTypes.func,
};

Pagination.defaultProps = {
Expand All @@ -90,8 +122,9 @@ Pagination.defaultProps = {
activePageAriaLabel: 'Current Page',
nextButtonText: 'Next',
pageAriaLabel: 'Page',
pageHref: undefined,
prevButtonText: 'Previous',
onClick: nextPage => {}, // eslint-disable-line
onPageClick: undefined, // eslint-disable-line
};

export default Pagination;
80 changes: 57 additions & 23 deletions components/Pagination/Pagination.unit.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,87 +56,121 @@ describe('<Pagination />', () => {
});
});

describe('onClick prop', () => {
describe('onPageClick prop', () => {
describe('Page button', () => {
it('should call onClick when button is clicked', () => {
const onClickMock = jest.fn();
it('should call onPageClick when button is clicked', () => {
const onPageClickMock = jest.fn();
const wrapper = shallow(
<Pagination totalPages={10} onClick={onClickMock} />,
<Pagination totalPages={10} onPageClick={onPageClickMock} />,
);

const page = wrapper.find('Page');
page.at(0).simulate('click');
page.at(0).simulate('click', { preventDefault: () => {} });

expect(onClickMock).toHaveBeenCalled();
expect(onPageClickMock).toHaveBeenCalled();
});

it('should receive clicked page as onClick parameter when button is clicked', () => {
const onClickMock = jest.fn();
const onPageClickMock = jest.fn();
const wrapper = mount(
<Pagination totalPages={10} activePage={2} onClick={onClickMock} />,
<Pagination
totalPages={10}
activePage={2}
onPageClick={onPageClickMock}
/>,
);

wrapper
.find('Page')
.at(2)
.simulate('click');

expect(onClickMock).toHaveBeenCalledWith(3);
expect(onPageClickMock).toHaveBeenCalledWith(3);
});
});

describe('Action buttons', () => {
it('should call onClick when previous button is clicked', () => {
const onClickMock = jest.fn();
const onPageClickMock = jest.fn();
const wrapper = shallow(
<Pagination totalPages={10} onClick={onClickMock} />,
<Pagination
totalPages={10}
activePage={2}
onPageClick={onPageClickMock}
/>,
);

const page = wrapper.find('ActionButton');
page.at(0).simulate('click');
page.at(0).simulate('click', { preventDefault: () => {} });

expect(onClickMock).toHaveBeenCalled();
expect(onPageClickMock).toHaveBeenCalled();
});

it('should call onClick when next button is clicked', () => {
const onClickMock = jest.fn();
const onPageClickMock = jest.fn();
const wrapper = shallow(
<Pagination totalPages={10} onClick={onClickMock} />,
<Pagination totalPages={10} onPageClick={onPageClickMock} />,
);

const page = wrapper.find('ActionButton');
page.at(1).simulate('click');
page.at(1).simulate('click', { preventDefault: () => {} });

expect(onClickMock).toHaveBeenCalled();
expect(onPageClickMock).toHaveBeenCalled();
});

it('should receive previous page as onClick parameter when previous button is clicked', () => {
const onClickMock = jest.fn();
const onPageClickMock = jest.fn();
const wrapper = mount(
<Pagination totalPages={10} activePage={2} onClick={onClickMock} />,
<Pagination
totalPages={10}
activePage={2}
onPageClick={onPageClickMock}
/>,
);

wrapper
.find('ActionButton')
.at(0)
.simulate('click');

expect(onClickMock).toHaveBeenCalledWith(1);
expect(onPageClickMock).toHaveBeenCalledWith(1);
});

it('should receive next page as onClick parameter when next button is clicked', () => {
const onClickMock = jest.fn();
const onPageClickMock = jest.fn();
const wrapper = mount(
<Pagination totalPages={10} activePage={2} onClick={onClickMock} />,
<Pagination
totalPages={10}
activePage={2}
onPageClick={onPageClickMock}
/>,
);

wrapper
.find('ActionButton')
.at(1)
.simulate('click');

expect(onClickMock).toHaveBeenCalledWith(3);
expect(onPageClickMock).toHaveBeenCalledWith(3);
});
});
});

describe('Page href prop', () => {
it('should set href value with correct value', () => {
const wrapper = mount(
<Pagination
totalPages={10}
activePage={2}
pageHref={page => `/?page=${page}`}
/>,
);
expect(
wrapper
.find('Page')
.at(0)
.prop('href'),
).toBe('/?page=1');
});
});
});
Loading

0 comments on commit 3f704a7

Please sign in to comment.