import * as React from 'react'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import kebabCase from 'lodash/kebabCase'; import { Collection } from '../Collection'; import { Flex } from '../../Flex'; import { Text } from '../../Text'; import { ComponentClassNames, ComponentText } from '../../shared/constants'; import { ComponentPropsToStylePropsMap } from '../../types'; const emojis = [ { title: 'LOL', emoji: '🤣', }, { title: 'Thumbs up', emoji: '👍', }, { title: 'Face palm', emoji: '🤦‍♂️', }, ]; const visitNewZealand = [ { title: 'Fiordland National Park', description: 'This national park includes the famous fjords of Milford, Dusky and Doubtful Sounds.', }, { title: 'Bay of Islands, North Island', description: 'Three hours north of Auckland, this area features over 144 islands to explore.', }, { title: 'Queenstown, South Island', description: null, }, ]; const getElementByClassName = ( element: HTMLElement, className: string ) => element.querySelector(`.${className}`); describe('Collection component', () => { const testList = 'testList'; it('should render a Search box when isSearchable is true', async () => { render( {(item, index) => (
{item.emoji}
)}
); const collection = await screen.findByTestId('testList'); const search = getElementByClassName( collection, ComponentClassNames.CollectionSearch ); expect(search).not.toBe(null); }); it('should render pagination when isPaginated is true', async () => { render( {(item, index) => (
{item.emoji}
)}
); const collection = await screen.findByTestId(testList); const pagination = getElementByClassName( collection, ComponentClassNames.CollectionPagination ); expect(pagination).not.toBe(null); }); it('should render Flex when rendering list collection items', async () => { render( {(item, index) => (
{item.emoji}
)}
); const collection = await screen.findByTestId(testList); const items = getElementByClassName( collection, ComponentClassNames.CollectionItems ); expect( items?.style.getPropertyValue( kebabCase(ComponentPropsToStylePropsMap.direction) ) ).toBe('column'); expect(items?.children[0].getAttribute('aria-label')).toBe('LOL'); }); it('should not throw when items is not an array', () => { expect(() => render( // @ts-expect-error // it's expected that items will cause TS error since the type doesn't allow null {(item, index) =>
} ) ).not.toThrowError(TypeError); }); it('can apply a custom className', async () => { render( {(item, index) => (
{item.emoji}
)}
); const collection = await screen.findByTestId(testList); expect(collection.classList.contains('custom-collection')).toBe(true); }); it('can render arbitrary attributes to items container', async () => { render( {(item, index) => (
{item.emoji}
)}
); const collection = await screen.findByTestId(testList); const items = getElementByClassName( collection, ComponentClassNames.CollectionItems ); expect(items?.dataset['demo']).toBe('true'); }); it('should not break the search functionality when items contain null values', async () => { render( {(item, index) => (
{item.description}
)}
); const searchInput = await screen.findByRole('textbox'); const text = 'Yosemite National Park'; userEvent.type(searchInput, text); expect(searchInput).toHaveValue(text); }); it('should be able to customize search field label', async () => { const searchLabel = 'Search emojis'; render( {(item, index) => (
{item.emoji}
)}
); const searchControl = await screen.findByLabelText(searchLabel); expect(searchControl).toBeDefined(); }); it('should render default text when no results are found from search', async () => { render( {(item, index) => (
{item.emoji}
)}
); const searchInput = await screen.findByRole('textbox'); const searchText = 'qwerty12345'; userEvent.type(searchInput, searchText); const noResults = await screen.findByText( ComponentText.Collection.searchNoResultsFound ); expect(noResults).toBeDefined(); }); it('should render custom ReactNode using searchNoResultsFound prop', async () => { const customText = 'Nothing found, please try again'; render( {customText} } > {(item, index) => (
{item.emoji}
)}
); const searchInput = await screen.findByRole('textbox'); const searchText = 'qwerty12345'; userEvent.type(searchInput, searchText); const noResults = await screen.findByText(customText); expect(noResults).toBeDefined(); }); });