import { act , render , screen , waitFor } from '@testing-library/react' ; import userEvent from '@testing-library/user-event' ; import { mocked } from 'ts-jest/utils' ; import API from '../../api' ; import { Organization } from '../../types' ; import { prepareQueryString } from '../../utils/prepareQueryString' ; import OrganizationInfo from './OrganizationInfo' ; jest . mock ( '../../api' ) ; const defaultProps = { organizationName : 'orgname' , visibleLegend : false , } ; const mockHistoryPush = jest . fn ( ) ; jest . mock ( 'react-router-dom' , ( ) => ( { ... ( jest . requireActual ( 'react-router-dom' ) as { } ) , useHistory : ( ) => ( { push : mockHistoryPush , } ) , } ) ) ; const getMockOrganization = ( fixtureId ) : Organization => { return require ( `./__fixtures__/OrganizationInfo/${ fixtureId }.json` ) as Organization ; } ; describe ( 'OrganizationInfo' , ( ) => { afterEach ( ( ) => { jest . resetAllMocks ( ) ; } ) ; it ( 'creates snapshot' , ( ) => { const { asFragment } = render ( < OrganizationInfo { ... defaultProps } / > ) ; expect ( asFragment ( ) ) . toMatchSnapshot ( ) ; } ) ; it ( 'renders proper content' , ( ) => { render ( < OrganizationInfo { ... defaultProps } / > ) ; expect ( screen . getByText ( defaultProps . organizationName ) ) . toBeInTheDocument ( ) ; expect ( screen . getByLabelText ( 'Organization info' ) ) . toBeInTheDocument ( ) ; } ) ; it ( 'calls history push to click org link' , async ( ) => { render ( < OrganizationInfo { ... defaultProps } / > ) ; userEvent . click ( screen . getByLabelText ( 'Organization info' ) ) ; await waitFor ( ( ) => expect ( mockHistoryPush ) . toHaveBeenCalledTimes ( 1 ) ) ; expect ( mockHistoryPush ) . toHaveBeenCalledWith ( { pathname : '/packages/search' , search : prepareQueryString ( { pageNumber : 1 , filters : { org : [ defaultProps . organizationName ] , } , } ) , } ) ; } ) ; it ( 'displays org info to enter on link and hides on leave' , async ( ) => { jest . useFakeTimers ( ) ; const mockOrganization = getMockOrganization ( '1' ) ; mocked ( API ) . getOrganization . mockResolvedValue ( mockOrganization ) ; render ( < OrganizationInfo { ... defaultProps } / > ) ; userEvent . hover ( screen . getByLabelText ( 'Organization info' ) ) ; await waitFor ( ( ) => { expect ( API . getOrganization ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; expect ( screen . getByRole ( 'button' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByAltText ( mockOrganization . displayName ! ) ) . toBeInTheDocument ( ) ; expect ( screen . getByAltText ( mockOrganization . displayName ! ) ) . toHaveProperty ( 'src' , `http://localhost/image/${ mockOrganization . logoImageId ! }` ) ; expect ( screen . getByText ( mockOrganization . description ! ) ) . toBeInTheDocument ( ) ; act ( ( ) => { jest . advanceTimersByTime ( 100 ) ; } ) ; expect ( await screen . findByRole ( 'complementary' ) ) . toHaveClass ( 'show' ) ; userEvent . unhover ( screen . getByLabelText ( 'Organization info' ) ) ; act ( ( ) => { jest . advanceTimersByTime ( 50 ) ; } ) ; expect ( await screen . findByRole ( 'complementary' ) ) . not . toHaveClass ( 'show' ) ; jest . useRealTimers ( ) ; } ) ; it ( 'hides org info to leave org dropdown' , async ( ) => { jest . useFakeTimers ( ) ; const mockOrganization = getMockOrganization ( '1' ) ; mocked ( API ) . getOrganization . mockResolvedValue ( mockOrganization ) ; render ( < OrganizationInfo { ... defaultProps } / > ) ; userEvent . hover ( screen . getByLabelText ( 'Organization info' ) ) ; await waitFor ( ( ) => { expect ( API . getOrganization ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; userEvent . hover ( screen . getByRole ( 'complementary' ) ) ; userEvent . unhover ( screen . getByLabelText ( 'Organization info' ) ) ; act ( ( ) => { jest . advanceTimersByTime ( 100 ) ; } ) ; expect ( await screen . findByRole ( 'complementary' ) ) . toHaveClass ( 'show' ) ; userEvent . unhover ( screen . getByRole ( 'complementary' ) ) ; act ( ( ) => { jest . advanceTimersByTime ( 50 ) ; } ) ; expect ( await screen . findByRole ( 'complementary' ) ) . not . toHaveClass ( 'show' ) ; jest . useRealTimers ( ) ; } ) ; it ( 'does not render dropdown content when api call fails' , async ( ) => { mocked ( API ) . getOrganization . mockRejectedValue ( '' ) ; render ( < OrganizationInfo { ... defaultProps } / > ) ; userEvent . hover ( screen . getByLabelText ( 'Organization info' ) ) ; await waitFor ( ( ) => { expect ( API . getOrganization ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; expect ( await screen . findByRole ( 'complementary' ) ) . toBeEmptyDOMElement ( ) ; } ) ; it ( 'does not call getOrganization if user is over link less than 100ms' , async ( ) => { jest . useFakeTimers ( ) ; const mockOrganization = getMockOrganization ( '1' ) ; mocked ( API ) . getOrganization . mockResolvedValue ( mockOrganization ) ; render ( < OrganizationInfo { ... defaultProps } / > ) ; userEvent . hover ( screen . getByLabelText ( 'Organization info' ) ) ; act ( ( ) => { jest . advanceTimersByTime ( 50 ) ; } ) ; userEvent . unhover ( screen . getByLabelText ( 'Organization info' ) ) ; await waitFor ( ( ) => { expect ( API . getOrganization ) . toHaveBeenCalledTimes ( 0 ) ; } ) ; userEvent . hover ( screen . getByLabelText ( 'Organization info' ) ) ; act ( ( ) => { jest . advanceTimersByTime ( 150 ) ; } ) ; userEvent . unhover ( screen . getByLabelText ( 'Organization info' ) ) ; await waitFor ( ( ) => { expect ( API . getOrganization ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; jest . useRealTimers ( ) ; } ) ; } ) ;