UNPKG

react-paginate

Version:

A ReactJS component that creates a pagination.

1,528 lines (1,375 loc) 69.3 kB
/** * @jest-environment jsdom */ /* eslint-disable react/no-find-dom-node */ import React from 'react'; import ReactDOM from 'react-dom'; jest.dontMock('./../react_components/PaginationBoxView'); jest.dontMock('./../react_components/PageView'); jest.dontMock('./../react_components/BreakView'); import PaginationBoxView from '../react_components/PaginationBoxView'; // TODO Migrate to React Testing Library. // -> ReactDOM.findDOMNode won't work with function components. // https://testing-library.com/docs/react-testing-library/intro // with jest-dom // https://github.com/testing-library/jest-dom import ReactTestUtils from 'react-dom/test-utils'; const DEFAULT_PAGE_COUNT = 10; describe('Test rendering', () => { it('should render a pagination component', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} /> ); expect(ReactDOM.findDOMNode(pagination).nodeName).toEqual('UL'); ReactTestUtils.scryRenderedComponentsWithType( pagination, PaginationBoxView ); expect( ReactDOM.findDOMNode(pagination).querySelector('li:first-child a') .textContent ).toBe('Previous'); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('1'); expect( ReactDOM.findDOMNode(pagination).querySelector('li:last-child a') .textContent ).toBe('Next'); const pages = ReactDOM.findDOMNode(pagination).querySelectorAll('li'); // 3 * 2 margins + 1 break label + previous & next buttons == 9: expect(pages.length).toEqual(9); }); it('test rendering only active page item', function () { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={0} pageRangeDisplayed={0} marginPagesDisplayed={0} breakLabel={null} /> ); const pageItems = ReactDOM.findDOMNode(pagination).querySelectorAll('li'); // Prev, selected page, next expect(pageItems.length).toBe(3); }); }); describe('Page count is zero', () => { it('should render Previous / Next if page count is zero (default / when renderOnZeroPageCount is undefined)', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={0} pageRangeDisplayed={0} marginPagesDisplayed={0} breakLabel={null} /> ); const pageItems = ReactDOM.findDOMNode(pagination).querySelectorAll('li'); // Prev page, next expect(pageItems.length).toBe(2); }); it('should render nothing if page count is zero when renderOnZeroPageCount is null', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={0} pageRangeDisplayed={0} marginPagesDisplayed={0} breakLabel={null} renderOnZeroPageCount={null} /> ); expect(ReactDOM.findDOMNode(pagination)).toBeNull(); }); it('should render provided Component if page count is zero when renderOnZeroPageCount is not null', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={0} pageRangeDisplayed={0} marginPagesDisplayed={0} breakLabel={null} renderOnZeroPageCount={() => <h2>Nothing</h2>} /> ); expect(ReactDOM.findDOMNode(pagination).textContent).toBe('Nothing'); }); }); describe('Page count checks', () => { it('should trigger a warning when a float is provided', () => { const consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation(); const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={2.5} pageRangeDisplayed={0} marginPagesDisplayed={0} breakLabel={null} /> ); const pageItems = ReactDOM.findDOMNode(pagination).querySelectorAll('li'); // Prev page, next expect(pageItems.length).toBe(4); expect(console.warn).toHaveBeenCalledTimes(1); expect(console.warn).toHaveBeenLastCalledWith( '(react-paginate): The pageCount prop value provided is not an integer (2.5). Did you forget a Math.ceil()?' ); consoleWarnMock.mockRestore(); }); it('should trigger a warning when the initialPage provided is greater than the maximum page index (from pageCount)', () => { const consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation(); ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={10} initialPage={10} /> ); expect(console.warn).toHaveBeenCalledTimes(1); expect(console.warn).toHaveBeenLastCalledWith( '(react-paginate): The initialPage prop provided is greater than the maximum page index from pageCount prop (10 > 9).' ); consoleWarnMock.mockRestore(); }); it('should trigger a warning when the forcePage provided is greater than the maximum page index (from pageCount)', () => { const consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation(); ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={9} forcePage={9} /> ); expect(console.warn).toHaveBeenCalledTimes(1); expect(console.warn).toHaveBeenLastCalledWith( '(react-paginate): The forcePage prop provided is greater than the maximum page index from pageCount prop (9 > 8).' ); consoleWarnMock.mockRestore(); }); // TODO Warning on prop change. }); describe('Test clicks', () => { it('test clicks on previous and next buttons', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} /> ); let elmts = ReactTestUtils.scryRenderedDOMComponentsWithTag( pagination, 'a' ); let previous = elmts[0]; let next = elmts[elmts.length - 1]; ReactTestUtils.Simulate.click(next); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('2'); ReactTestUtils.Simulate.click(previous); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('1'); }); it('test click on a page item', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} /> ); ReactTestUtils.findRenderedComponentWithType(pagination, PaginationBoxView); const pageItem = ReactDOM.findDOMNode(pagination).querySelector('li:nth-child(3) a'); ReactTestUtils.Simulate.click(pageItem); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('2'); }); it('test click on the left break view', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView initialPage={0} pageCount={22} marginPagesDisplayed={2} pageRangeDisplayed={5} /> ); // The selected page is before the left break const rightBreakView = ReactDOM.findDOMNode(pagination).querySelector('.break a'); ReactTestUtils.Simulate.click(rightBreakView); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('6'); const rightBreakView2 = ReactDOM.findDOMNode(pagination).querySelector('.break a'); ReactTestUtils.Simulate.click(rightBreakView2); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('11'); // The selected page is after the left break const leftBreakView2 = ReactDOM.findDOMNode(pagination).querySelectorAll('.break a')[0]; ReactTestUtils.Simulate.click(leftBreakView2); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('6'); }); it('test click on the right break view', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView initialPage={10} pageCount={20} marginPagesDisplayed={2} pageRangeDisplayed={5} /> ); // The selected page is before the right break const rightBreak1 = ReactDOM.findDOMNode(pagination).querySelectorAll('.break a')[1]; ReactTestUtils.Simulate.click(rightBreak1); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('16'); // The selected page is after the right break const rightBreak2 = ReactDOM.findDOMNode(pagination).querySelector('.break a'); ReactTestUtils.Simulate.click(rightBreak2); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('11'); }); }); describe('Test custom event listener', () => { it('test custom listener on previous and next buttons', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} eventListener="onMouseOver" /> ); let elmts = ReactTestUtils.scryRenderedDOMComponentsWithTag( pagination, 'a' ); let previous = elmts[0]; let next = elmts[elmts.length - 1]; ReactTestUtils.Simulate.mouseOver(next); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('2'); ReactTestUtils.Simulate.mouseOver(previous); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('1'); }); it('test custom listener on a page item', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} eventListener="onMouseOver" /> ); ReactTestUtils.findRenderedComponentWithType(pagination, PaginationBoxView); const pageItem = ReactDOM.findDOMNode(pagination).querySelector('li:nth-child(3) a'); ReactTestUtils.Simulate.mouseOver(pageItem); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('2'); }); it('test custom listener on the left break view', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView initialPage={0} pageCount={20} marginPagesDisplayed={2} pageRangeDisplayed={5} eventListener="onMouseOver" /> ); // The selected page is before the left break const rightBreakView = ReactDOM.findDOMNode(pagination).querySelector('.break a'); ReactTestUtils.Simulate.mouseOver(rightBreakView); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('6'); const rightBreakView2 = ReactDOM.findDOMNode(pagination).querySelector('.break a'); ReactTestUtils.Simulate.mouseOver(rightBreakView2); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('11'); // The selected page is after the left break const leftBreakView2 = ReactDOM.findDOMNode(pagination).querySelectorAll('.break a')[0]; ReactTestUtils.Simulate.mouseOver(leftBreakView2); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').textContent ).toBe('6'); }); }); describe('Test pagination behaviour', () => { it('should display 2 elements to the left, 1 break element and 2 elements to the right', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView initialPage={0} pageCount={20} pageRangeDisplayed={2} marginPagesDisplayed={1} /> ); const previousElement = ReactDOM.findDOMNode(pagination).querySelector('li:first-child'); const nextElement = ReactDOM.findDOMNode(pagination).querySelector('li:last-child'); let leftElements = []; let rightElements = []; let breakElements = []; let breakElementReached = false; const elements = ReactDOM.findDOMNode(pagination).querySelectorAll( 'li:not(.previous):not(.next)' ); elements.forEach((element) => { if (breakElementReached === false && element.className !== 'break') { leftElements.push(element); } else if ( breakElementReached === true && element.className !== 'break' ) { rightElements.push(element); } else { breakElements.push(element); breakElementReached = true; } }); expect(previousElement.className).toBe('previous disabled'); expect(nextElement.className).toBe('next'); expect(leftElements.length).toBe(2); expect(rightElements.length).toBe(1); expect(breakElements.length).toBe(1); }); it('should display 5 elements to the left, 1 break element and 2 elements to the right', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView initialPage={0} pageCount={20} marginPagesDisplayed={2} pageRangeDisplayed={5} /> ); const previousElement = ReactDOM.findDOMNode(pagination).querySelector('li:first-child'); const nextElement = ReactDOM.findDOMNode(pagination).querySelector('li:last-child'); let leftElements = []; let rightElements = []; let breakElements = []; let breakElementReached = false; const elements = ReactDOM.findDOMNode(pagination).querySelectorAll( 'li:not(.previous):not(.next)' ); elements.forEach((element) => { if (breakElementReached === false && element.className !== 'break') { leftElements.push(element); } else if ( breakElementReached === true && element.className !== 'break' ) { rightElements.push(element); } else { breakElements.push(element); breakElementReached = true; } }); expect(previousElement.className).toBe('previous disabled'); expect(nextElement.className).toBe('next'); expect(leftElements.length).toBe(5); expect(rightElements.length).toBe(2); expect(breakElements.length).toBe(1); }); it('should display 7 elements to the left, 1 break element and 2 elements to the right', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView initialPage={4} pageCount={20} marginPagesDisplayed={2} pageRangeDisplayed={5} /> ); const previousElement = ReactDOM.findDOMNode(pagination).querySelector('li:first-child'); const nextElement = ReactDOM.findDOMNode(pagination).querySelector('li:last-child'); let leftElements = []; let rightElements = []; let breakElements = []; let breakElementReached = false; const elements = ReactDOM.findDOMNode(pagination).querySelectorAll( 'li:not(.previous):not(.next)' ); elements.forEach((element) => { if (breakElementReached === false && element.className !== 'break') { leftElements.push(element); } else if ( breakElementReached === true && element.className !== 'break' ) { rightElements.push(element); } else { breakElements.push(element); breakElementReached = true; } }); expect(previousElement.className).toBe('previous'); expect(nextElement.className).toBe('next'); expect(leftElements.length).toBe(7); expect(rightElements.length).toBe(2); expect(breakElements.length).toBe(1); }); it('should display 2 elements to the left, 5 elements in the middle, 2 elements to the right and 2 break elements', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView initialPage={7} pageCount={20} marginPagesDisplayed={2} pageRangeDisplayed={5} /> ); const previousElement = ReactDOM.findDOMNode(pagination).querySelector('li:first-child'); const nextElement = ReactDOM.findDOMNode(pagination).querySelector('li:last-child'); let leftElements = []; let middleElements = []; let rightElements = []; let breakElements = []; let leftBreakElementReached = false; let rightBreakElementReached = false; const elements = ReactDOM.findDOMNode(pagination).querySelectorAll( 'li:not(.previous):not(.next)' ); elements.forEach((element) => { if ( leftBreakElementReached === false && rightBreakElementReached === false && element.className !== 'break' ) { leftElements.push(element); } else if ( leftBreakElementReached === true && rightBreakElementReached === false && element.className !== 'break' ) { middleElements.push(element); } else if ( leftBreakElementReached === true && rightBreakElementReached === true && element.className !== 'break' ) { rightElements.push(element); } else if (breakElements.length === 0 && element.className === 'break') { breakElements.push(element); leftBreakElementReached = true; } else if (breakElements.length === 1 && element.className === 'break') { breakElements.push(element); rightBreakElementReached = true; } }); expect(previousElement.className).toBe('previous'); expect(nextElement.className).toBe('next'); expect(leftElements.length).toBe(2); expect(middleElements.length).toBe(5); expect(rightElements.length).toBe(2); expect(breakElements.length).toBe(2); }); it('should display 2 elements to the left, 1 break element and 7 elements to the right', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView initialPage={15} pageCount={20} marginPagesDisplayed={2} pageRangeDisplayed={5} /> ); const previousElement = ReactDOM.findDOMNode(pagination).querySelector('li:first-child'); const nextElement = ReactDOM.findDOMNode(pagination).querySelector('li:last-child'); let leftElements = []; let rightElements = []; let breakElements = []; let breakElementReached = false; const elements = ReactDOM.findDOMNode(pagination).querySelectorAll( 'li:not(.previous):not(.next)' ); elements.forEach((element) => { if (breakElementReached === false && element.className !== 'break') { leftElements.push(element); } else if ( breakElementReached === true && element.className !== 'break' ) { rightElements.push(element); } else { breakElements.push(element); breakElementReached = true; } }); expect(previousElement.className).toBe('previous'); expect(nextElement.className).toBe('next'); expect(leftElements.length).toBe(2); expect(rightElements.length).toBe(7); expect(breakElements.length).toBe(1); }); it('should display 2 elements to the left, 1 break element and 6 elements to the right', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView initialPage={16} pageCount={20} marginPagesDisplayed={2} pageRangeDisplayed={5} /> ); const previousElement = ReactDOM.findDOMNode(pagination).querySelector('li:first-child'); const nextElement = ReactDOM.findDOMNode(pagination).querySelector('li:last-child'); let leftElements = []; let rightElements = []; let breakElements = []; let breakElementReached = false; const elements = ReactDOM.findDOMNode(pagination).querySelectorAll( 'li:not(.previous):not(.next)' ); elements.forEach((element) => { if (breakElementReached === false && element.className !== 'break') { leftElements.push(element); } else if ( breakElementReached === true && element.className !== 'break' ) { rightElements.push(element); } else { breakElements.push(element); breakElementReached = true; } }); expect(previousElement.className).toBe('previous'); expect(nextElement.className).toBe('next'); expect(leftElements.length).toBe(2); expect(rightElements.length).toBe(6); expect(breakElements.length).toBe(1); }); // 1 2 3 4 5 6 7 ... 9 10 // | it('should not display a break containing only one page', () => { // should display 10 elements, 0 break element const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView initialPage={5} pageCount={10} marginPagesDisplayed={2} pageRangeDisplayed={5} /> ); const previousElement = ReactDOM.findDOMNode(pagination).querySelector('li:first-child'); const nextElement = ReactDOM.findDOMNode(pagination).querySelector('li:last-child'); let leftElements = []; let rightElements = []; let breakElements = []; let breakElementReached = false; const elements = ReactDOM.findDOMNode(pagination).querySelectorAll( 'li:not(.previous):not(.next)' ); elements.forEach((element) => { if (breakElementReached === false && element.className !== 'break') { leftElements.push(element); } else if ( breakElementReached === true && element.className !== 'break' ) { rightElements.push(element); } else { breakElements.push(element); breakElementReached = true; } }); expect(previousElement.className).toBe('previous'); expect(nextElement.className).toBe('next'); expect(leftElements.length).toBe(10); expect(rightElements.length).toBe(0); expect(breakElements.length).toBe(0); }); it('should use ariaLabelBuilder for rendering aria-labels if ariaLabelBuilder is specified', function () { const linkedPagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView initialPage={1} pageCount={3} pageRangeDisplayed={2} marginPagesDisplayed={2} ariaLabelBuilder={(page, selected) => selected ? 'Current page' : 'Goto page ' + page } /> ); expect( ReactDOM.findDOMNode(linkedPagination) .querySelector('li:nth-last-child(2) a') .getAttribute('aria-label') ).toBe('Goto page 3'); expect( ReactDOM.findDOMNode(linkedPagination) .querySelector('li:nth-child(2) a') .getAttribute('aria-label') ).toBe('Goto page 1'); expect( ReactDOM.findDOMNode(linkedPagination) .querySelector('.selected a') .getAttribute('aria-label') ).toBe('Current page'); }); it('test ariaLabelBuilder works with extraAriaContext', function () { const consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation(); const linkedPagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView initialPage={1} pageCount={3} pageRangeDisplayed={2} marginPagesDisplayed={2} ariaLabelBuilder={(page, selected) => selected ? 'Current page' : 'Goto page ' + page } extraAriaContext="foobar" /> ); expect( ReactDOM.findDOMNode(linkedPagination) .querySelector('li:nth-last-child(2) a') .getAttribute('aria-label') ).toBe('Goto page 3 foobar'); expect( ReactDOM.findDOMNode(linkedPagination) .querySelector('li:nth-child(2) a') .getAttribute('aria-label') ).toBe('Goto page 1 foobar'); expect( ReactDOM.findDOMNode(linkedPagination) .querySelector('.selected a') .getAttribute('aria-label') ).toBe('Current page'); expect(console.warn).toHaveBeenCalledTimes(1); expect(console.warn).toHaveBeenLastCalledWith( 'DEPRECATED (react-paginate): The extraAriaContext prop is deprecated. You should now use the ariaLabelBuilder instead.' ); consoleWarnMock.mockRestore(); }); }); describe('Test default props', () => { describe('default previousLabel/nextLabel', () => { it('should use the default previousLabel/nextLabel', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('li:first-child a') .textContent ).toBe('Previous'); expect( ReactDOM.findDOMNode(pagination).querySelector('li:last-child a') .textContent ).toBe('Next'); }); }); describe('default breakLabel/breakClassName/breakLinkClassName', () => { it('should use the default breakLabel/breakClassName/breakLinkClassName', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('li.break').textContent ).toBe('...'); expect(ReactDOM.findDOMNode(pagination).querySelector('.break')).not.toBe( null ); expect( ReactDOM.findDOMNode(pagination).querySelector('.break a').className ).toBe(''); }); }); describe('default onPageChange', () => { it('should not call any onPageChange callback if not defined but it should go to the next page', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} /> ); const nextItem = ReactDOM.findDOMNode(pagination).querySelector('li:last-child a'); ReactTestUtils.Simulate.click(nextItem); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a') .textContent ).toBe('2'); }); }); describe('default initialPage/forcePage', () => { it('should use the default initial selected page (0)', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a') .textContent ).toBe('1'); }); }); describe('default disableInitialCallback', () => { it('should call the onPageChange callback when disableInitialCallback is set to false/undefined', () => { const myOnPageChangeMethod = jest.fn(); ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={5} onPageChange={myOnPageChangeMethod} /> ); expect(myOnPageChangeMethod).toHaveBeenCalledWith({ selected: 5 }); }); }); describe('default containerClassName', () => { it('should not use any classname on the container by default', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} /> ); expect(ReactDOM.findDOMNode(pagination).className).toEqual(''); }); }); describe('default pageClassName/activeClassName', () => { it('should not use any classname on page items and a default activeClassName', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} previousClassName="prev" nextClassName="next" /> ); const pageItem = ReactDOM.findDOMNode(pagination).querySelector('li:nth-child(3) a'); ReactTestUtils.Simulate.click(pageItem); expect( ReactDOM.findDOMNode(pagination).querySelector( 'li:not(.selected):not(.prev):not(.next)' ).className ).toBe(''); expect( ReactDOM.findDOMNode(pagination).querySelector('li:nth-child(3)') .className ).toBe('selected'); }); }); describe('default pageLinkClassName/activeLinkClassName', () => { it('should not use any classname on selected links by default', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} previousClassName="prev" nextClassName="next" /> ); expect( ReactDOM.findDOMNode(pagination).querySelector( 'li:not(.selected):not(.prev):not(.next) a' ).className ).toBe(''); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').className ).toBe(''); }); }); describe('default previousClassName/nextClassName', () => { it('should use the default previousClassName/nextClassName', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={2} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('li:first-child') .className ).toBe('previous'); expect( ReactDOM.findDOMNode(pagination).querySelector('li:last-child') .className ).toBe('next'); }); }); describe('default previousLinkClassName/nextLinkClassName/disabledLinkClassName', () => { it('should not use any classname on previous/next links by default', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={2} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('li:first-child a') .className ).toBe(''); expect( ReactDOM.findDOMNode(pagination).querySelector('li:last-child a') .className ).toBe(''); }); }); describe('default disabledClassName', () => { it('should use the default disabledClassName', function () { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView initialPage={0} pageCount={1} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('li:first-child') .className ).toBe('previous disabled'); expect( ReactDOM.findDOMNode(pagination).querySelector('li:last-child') .className ).toBe('next disabled'); }); }); describe('default hrefBuilder', () => { it('should not render href attributes on page items if hrefBuilder is not defined', function () { const linkedPagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} /> ); expect( ReactDOM.findDOMNode(linkedPagination) .querySelector('li:last-child a') .hasAttribute('href') ).toBe(false); expect( ReactDOM.findDOMNode(linkedPagination) .querySelector('li:first-child a') .hasAttribute('href') ).toBe(false); expect( ReactDOM.findDOMNode(linkedPagination) .querySelector('.selected a') .hasAttribute('href') ).toBe(false); }); }); describe('default extraAriaContext', () => { it('should use the default extraAriaContext', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} previousClassName="prev" nextClassName="next" /> ); expect( ReactDOM.findDOMNode(pagination) .querySelector('li:not(.selected):not(.prev):not(.next) a') .getAttribute('aria-label') ).toBe('Page 2'); expect( ReactDOM.findDOMNode(pagination) .querySelector('.selected a') .getAttribute('aria-label') ).toBe('Page 1 is your current page'); }); }); describe('default tabindex', () => { it('should set the tabindex to 0 on all controls', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={0} /> ); expect( ReactDOM.findDOMNode(pagination) .querySelector('li:nth-child(3) a') .getAttribute('tabindex') ).toBe('0'); expect( ReactDOM.findDOMNode(pagination) .querySelector('.selected a') .getAttribute('tabindex') ).toBe('-1'); expect( ReactDOM.findDOMNode(pagination) .querySelector('li:first-child a') .getAttribute('tabindex') ).toBe('-1'); expect( ReactDOM.findDOMNode(pagination) .querySelector('li:last-child a') .getAttribute('tabindex') ).toBe('0'); }); }); }); describe('Test custom props', () => { describe('previousLabel/nextLabel', () => { it('should use the previousLabel prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} previousLabel={'Custom previous label'} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('li:first-child a') .textContent ).toBe('Custom previous label'); }); it('should use the nextLabel prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} nextLabel={'Custom next label'} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('li:last-child a') .textContent ).toBe('Custom next label'); }); }); describe('breakLabel/breakClassName/breakLinkClassName', () => { it('should use the breakLabel string prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} breakLabel={'...'} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('li.break').firstChild .nodeType ).toBe(Node.ELEMENT_NODE); expect( ReactDOM.findDOMNode(pagination).querySelector('li.break').firstChild .nodeName ).toBe('A'); expect( ReactDOM.findDOMNode(pagination).querySelector('li.break').firstChild .textContent ).toBe('...'); }); it('should use the breakLabel node prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} breakLabel={<span>...</span>} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('li.break a').firstChild .nodeName ).toBe('SPAN'); expect( ReactDOM.findDOMNode(pagination).querySelector('li.break a').lastChild .textContent ).toBe('...'); }); it('should use the breakClassName prop when defined', function () { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} breakClassName={'break-me'} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('.break-me') ).not.toBe(null); }); it('should use the breakLinkClassName prop when defined', function () { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} breakLinkClassName={'break-link'} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('.break-link') ).not.toBe(null); }); }); describe('onPageChange', () => { it('should use the onPageChange prop when defined', () => { const myOnPageChangeMethod = jest.fn(); const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} onPageChange={myOnPageChangeMethod} /> ); const nextItem = ReactDOM.findDOMNode(pagination).querySelector('li:last-child a'); ReactTestUtils.Simulate.click(nextItem); expect(myOnPageChangeMethod).toHaveBeenCalledWith({ selected: 1 }); }); }); describe('onPageActive', () => { it('should use the onPageActive prop when defined', () => { const myOnPageActiveMethod = jest.fn(); const myOnPageChangeMethod = jest.fn(); const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} onPageActive={myOnPageActiveMethod} onPageChange={myOnPageChangeMethod} /> ); const activeItem = ReactDOM.findDOMNode(pagination).querySelector('.selected a'); ReactTestUtils.Simulate.click(activeItem); expect(myOnPageActiveMethod).toHaveBeenCalledWith({ selected: 0 }); expect(myOnPageChangeMethod).not.toHaveBeenCalled(); }); }); describe('initialPage', () => { it('should use the initialPage prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={2} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a') .textContent ).toBe('3'); }); }); describe('forcePage', () => { it('should use the forcePage prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} forcePage={2} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a') .textContent ).toBe('3'); }); it('should update forcePage and hence selected page when forcePage value is changed', () => { const node = document.createElement('div'); // TODO Fix this test: use mounted component (requires enzyme?) and change prop on it. let pagination = React.createRef(); ReactDOM.render( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} ref={pagination} forcePage={2} />, node, () => { expect( ReactDOM.findDOMNode(pagination.current).querySelector( '.selected a' ).textContent ).toBe('3'); } ); pagination = React.createRef(); ReactDOM.render( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} ref={pagination} forcePage={3} />, node, () => { expect( ReactDOM.findDOMNode(pagination.current).querySelector( '.selected a' ).textContent ).toBe('3'); } ); }); it('should report a warning when using both initialPage and forcePage props', () => { const consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation(); const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={3} forcePage={2} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a') .textContent ).toBe('4'); expect(console.warn).toHaveBeenCalledTimes(1); expect(console.warn).toHaveBeenLastCalledWith( '(react-paginate): Both initialPage (3) and forcePage (2) props are provided, which is discouraged.' + ' Use exclusively forcePage prop for a controlled component.\n' + 'See https://reactjs.org/docs/forms.html#controlled-components' ); consoleWarnMock.mockRestore(); }); it('(observation) is not totally controlled when forcePage is provided', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} forcePage={2} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a') .textContent ).toBe('3'); const pageItem = ReactDOM.findDOMNode(pagination).querySelector('li:nth-child(3) a'); ReactTestUtils.Simulate.click(pageItem); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a') .textContent ).toBe('2'); }); it('(observation) is not totally controlled when forcePage is provided, even when it is 0', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} forcePage={0} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a') .textContent ).toBe('1'); const pageItem = ReactDOM.findDOMNode(pagination).querySelector('li:nth-child(3) a'); ReactTestUtils.Simulate.click(pageItem); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a') .textContent ).toBe('2'); }); }); describe('disableInitialCallback', () => { it('should not call the onPageChange callback when disableInitialCallback is set to true', () => { const myOnPageChangeMethod = jest.fn(); ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={5} disableInitialCallback={true} onPageChange={myOnPageChangeMethod} /> ); expect(myOnPageChangeMethod).not.toHaveBeenCalled(); }); }); describe('containerClassName', () => { it('should use the containerClassName prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} containerClassName="my-pagination" /> ); expect(ReactDOM.findDOMNode(pagination).className).toEqual( 'my-pagination' ); }); it('should use the className prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} className="my-pagination" /> ); expect(ReactDOM.findDOMNode(pagination).className).toEqual( 'my-pagination' ); }); it('should use the className prop in priority from containerClassName', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} className="my-pagination" containerClassName="another" /> ); expect(ReactDOM.findDOMNode(pagination).className).toEqual( 'my-pagination' ); }); }); describe('pageClassName/activeClassName', () => { it('should use the pageClassName prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} pageClassName={'page-item'} previousClassName="prev" nextClassName="next" /> ); const pageItem = ReactDOM.findDOMNode(pagination).querySelector('li:nth-child(3) a'); ReactTestUtils.Simulate.click(pageItem); expect( ReactDOM.findDOMNode(pagination).querySelector( 'li:not(.selected):not(.prev):not(.next)' ).className ).toBe('page-item'); expect( ReactDOM.findDOMNode(pagination).querySelector('li:nth-child(3)') .className ).toBe('page-item selected'); }); it('should use the activeClassName prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} activeClassName="active-page-item" previousClassName="prev" nextClassName="next" /> ); const pageItem = ReactDOM.findDOMNode(pagination).querySelector('li:nth-child(3) a'); ReactTestUtils.Simulate.click(pageItem); expect( ReactDOM.findDOMNode(pagination).querySelector('li:nth-child(3)') .className ).toBe('active-page-item'); }); it('should use the activeClassName prop without overriding the defined pageClassName', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} pageClassName="page-item" activeClassName="active-page-item" previousClassName="prev" nextClassName="next" /> ); const pageItem = ReactDOM.findDOMNode(pagination).querySelector('li:nth-child(3) a'); ReactTestUtils.Simulate.click(pageItem); expect( ReactDOM.findDOMNode(pagination).querySelector( 'li:not(.selected):not(.prev):not(.next)' ).className ).toBe('page-item'); expect( ReactDOM.findDOMNode(pagination).querySelector('li:nth-child(3)') .className ).toBe('page-item active-page-item'); }); }); describe('pageLinkClassName/activeLinkClassName', () => { it('should use the pageLinkClassName prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} pageLinkClassName="page-item-link" previousClassName="prev" nextClassName="next" /> ); expect( ReactDOM.findDOMNode(pagination).querySelector( 'li:not(.selected):not(.prev):not(.next) a' ).className ).toBe('page-item-link'); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').className ).toBe('page-item-link'); }); it('should use the activeLinkClassName prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView activeLinkClassName="active-page-item-link" pageCount={5} /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').className ).toBe('active-page-item-link'); }); it('should use the activeLinkClassName prop without overriding the defined pageLinkClassName', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} pageLinkClassName="page-item-link" activeLinkClassName="active-page-item-link" previousClassName="prev" nextClassName="next" /> ); expect( ReactDOM.findDOMNode(pagination).querySelector( 'li:not(.selected):not(.prev):not(.next) a' ).className ).toBe('page-item-link'); expect( ReactDOM.findDOMNode(pagination).querySelector('.selected a').className ).toBe('page-item-link active-page-item-link'); }); }); describe('previousClassName/nextClassName', () => { it('should use the previousClassName prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={2} previousClassName="custom-previous-classname" /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('li:first-child') .className ).toBe('custom-previous-classname'); }); it('should use the nextClassName prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={2} nextClassName="custom-next-classname" /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('li:last-child') .className ).toBe('custom-next-classname'); }); }); describe('previousLinkClassName/nextLinkClassName/disabledLinkClassName', () => { it('should use the previousLinkClassName prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={2} previousLinkClassName="custom-previous-link-classname" /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('li:first-child a') .className ).toBe('custom-previous-link-classname'); }); it('should use the nextLinkClassName prop when defined', () => { const pagination = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={2} nextLinkClassName="custom-next-link-classname" /> ); expect( ReactDOM.findDOMNode(pagination).querySelector('li:last-child a') .className ).toBe('custom-next-link-classname'); }); it('should use the disabledLinkClassName prop when defined', () => { const paginationFirst = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={0} disabledLinkClassName="custom-disabled-link-classname" /> ); expect( ReactDOM.findDOMNode(paginationFirst).querySelector('li:first-child a') .className ).toBe(' custom-disabled-link-classname'); expect( ReactDOM.findDOMNode(paginationFirst).querySelector('li:last-child a') .className ).toBe(''); const paginationLast = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} initialPage={9} disabledLinkClassName="custom-disabled-link-classname" /> ); expect( ReactDOM.findDOMNode(paginationLast).querySelector('li:first-child a') .className ).toBe(''); expect( ReactDOM.findDOMNode(paginationLast).querySelector('li:last-child a') .className ).toBe(' custom-disabled-link-classname'); }); it('should combines the previousLinkClassName and disabledLinkClassName props', () => { const paginationFirst = ReactTestUtils.renderIntoDocument( <PaginationBoxView pageCount={DEFAULT_PAGE_COUNT} i