import React from 'react'; import { getByText, waitFor } from '@testing-library/dom'; import { render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { axe } from 'jest-axe'; import { consoleOnce } from '@leafygreen-ui/lib'; import { DEFAULT_LGID_ROOT, getLgIds } from '../getLgIds'; import PaginationItemsPerPage from '.'; let offsetParentSpy: jest.SpyInstance; beforeAll(() => { offsetParentSpy = jest.spyOn(HTMLElement.prototype, 'offsetParent', 'get'); offsetParentSpy.mockImplementation(function (this: HTMLElement) { return this.parentElement; }); }); afterAll(() => { offsetParentSpy.mockRestore(); }); afterEach(() => { jest.clearAllMocks(); }); describe('PaginationItemsPerPage', () => { describe('a11y', () => { test('does not have basic accessibility issues', async () => { const { container } = render( , ); const results = await axe(container); expect(results).toHaveNoViolations(); }); }); describe('rendering', () => { test('renders select when onItemsPerPageOptionChange is provided', () => { const { getByTestId, getByText } = render( , ); expect(getByText('Items per page:')).toBeInTheDocument(); expect( getByTestId('leafygreen-ui-select-menubutton'), ).toBeInTheDocument(); }); test('does not render select when onItemsPerPageOptionChange is undefined', () => { const { queryByTestId, queryByText } = render( , ); expect(queryByText('Items per page:')).not.toBeInTheDocument(); expect( queryByTestId('leafygreen-ui-select-menubutton'), ).not.toBeInTheDocument(); }); test('renders default options when itemsPerPageOptions is not provided', async () => { const { getByTestId, queryByRole } = render( , ); const selectButton = getByTestId('leafygreen-ui-select-menubutton'); userEvent.click(selectButton); const listbox = await waitFor(() => { const listbox = queryByRole('listbox'); expect(listbox).toBeVisible(); return listbox as HTMLElement; }); // Default options from constants expect(getByText(listbox, '10')).toBeInTheDocument(); expect(getByText(listbox, '25')).toBeInTheDocument(); expect(getByText(listbox, '50')).toBeInTheDocument(); }); test('renders custom itemsPerPageOptions', async () => { const { getByTestId, queryByRole } = render( , ); const selectButton = getByTestId('leafygreen-ui-select-menubutton'); userEvent.click(selectButton); const listbox = await waitFor(() => { const listbox = queryByRole('listbox'); expect(listbox).toBeVisible(); return listbox as HTMLElement; }); expect(getByText(listbox, '5')).toBeInTheDocument(); expect(getByText(listbox, '15')).toBeInTheDocument(); expect(getByText(listbox, '30')).toBeInTheDocument(); }); }); describe('validation', () => { let consoleOnceSpy: jest.SpyInstance; beforeEach(() => { consoleOnceSpy = jest .spyOn(consoleOnce, 'error') .mockImplementation(() => {}); }); afterEach(() => { consoleOnceSpy.mockRestore(); }); test('console errors when itemsPerPage is not a valid option', () => { render( , ); expect(consoleOnceSpy).toHaveBeenCalledWith( `Value of the 'itemsPerPage' prop is not a valid option specified in 'itemsPerPageOptions'.`, ); }); test('does not console error when itemsPerPage is a valid option', () => { render( , ); expect(consoleOnceSpy).not.toHaveBeenCalled(); }); }); describe('select functionality', () => { test('calls onItemsPerPageOptionChange when option is selected', async () => { const onItemsPerPageOptionChange = jest.fn(); const { getByTestId, queryByRole } = render( , ); const selectButton = getByTestId('leafygreen-ui-select-menubutton'); userEvent.click(selectButton); const listbox = await waitFor(() => { const listbox = queryByRole('listbox'); expect(listbox).toBeVisible(); return listbox as HTMLElement; }); const option25 = getByText(listbox, '25'); userEvent.click(option25); await waitFor(() => { expect(onItemsPerPageOptionChange).toHaveBeenCalledWith( '25', expect.anything(), ); }); }); test('displays current itemsPerPage value in select', () => { const { getByTestId } = render( , ); const selectButton = getByTestId('leafygreen-ui-select-menubutton'); expect(selectButton).toHaveTextContent('25'); }); }); describe('id prop', () => { test('generates unique ids with custom id prefix', () => { const { getByText } = render( , ); const label = getByText('Items per page:'); expect(label).toHaveAttribute( 'id', expect.stringContaining('custom-pagination'), ); }); }); describe('lgid props', () => { const defaultLgIds = getLgIds(); test('renders default lgid values when data-lgid is not provided', () => { const { getByTestId } = render( , ); expect(getByTestId(defaultLgIds.pageSize)).toBeInTheDocument(); }); test('renders default data-lgid attribute when data-lgid is not provided', () => { const { getByTestId } = render( , ); expect(getByTestId(defaultLgIds.pageSize)).toHaveAttribute( 'data-lgid', `${DEFAULT_LGID_ROOT}-page_size`, ); }); test('renders custom lgid value when data-lgid is provided', () => { const customLgId = 'lg-my-pagination'; const customLgIds = getLgIds(customLgId); const { getByTestId } = render( , ); expect(getByTestId(customLgIds.pageSize)).toBeInTheDocument(); }); test('renders custom data-lgid attribute when data-lgid is provided', () => { const customLgId = 'lg-my-pagination'; const customLgIds = getLgIds(customLgId); const { getByTestId } = render( , ); expect(getByTestId(customLgIds.pageSize)).toHaveAttribute( 'data-lgid', `${customLgId}-page_size`, ); }); }); });