import { render , screen , waitFor } from '@testing-library/react' ; import userEvent from '@testing-library/user-event' ; import { BrowserRouter as Router } from 'react-router-dom' ; import { mocked } from 'ts-jest/utils' ; import API from '../../../../../../api' ; import { ErrorKind } from '../../../../../../types' ; import alertDispatcher from '../../../../../../utils/alertDispatcher' ; import PackagesSection from '../index' ; jest . mock ( '../../../../../../api' ) ; jest . mock ( '../../../../../../utils/alertDispatcher' ) ; const getMockSubscriptions = ( fixtureId ) => { return require ( `./__fixtures__/index/${ fixtureId }.json` ) ; } ; const mockOnAuthError = jest . fn ( ) ; const scrollIntoViewMock = jest . fn ( ) ; window . HTMLElement . prototype . scrollIntoView = scrollIntoViewMock ; const defaultProps = { onAuthError : mockOnAuthError , } ; describe ( 'PackagesSection' , ( ) => { afterEach ( ( ) => { jest . resetAllMocks ( ) ; } ) ; it ( 'creates snapshot' , async ( ) => { const mockSubscriptions = getMockSubscriptions ( '1' ) ; mocked ( API ) . getUserSubscriptions . mockResolvedValue ( mockSubscriptions ) ; const { asFragment } = render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 1 ) ; expect ( asFragment ( ) ) . toMatchSnapshot ( ) ; } ) ; } ) ; describe ( 'Render' , ( ) => { it ( 'renders component' , async ( ) => { const mockSubscriptions = getMockSubscriptions ( '2' ) ; mocked ( API ) . getUserSubscriptions . mockResolvedValue ( mockSubscriptions ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; expect ( screen . getByText ( 'Packages' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Kind' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Package' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Publisher' ) ) . toBeInTheDocument ( ) ; expect ( screen . getAllByTestId ( 'packageLink' ) ) . toHaveLength ( 8 ) ; expect ( screen . getAllByTestId ( 'packageCardLink' ) ) . toHaveLength ( 8 ) ; expect ( screen . getAllByTestId ( 'userLink' ) ) . toHaveLength ( 1 ) ; expect ( screen . getAllByTestId ( 'orgLink' ) ) . toHaveLength ( 7 ) ; expect ( screen . getAllByTestId ( 'repoLink' ) ) . toHaveLength ( 8 ) ; } ) ; it ( 'opens Add subscription modal' , async ( ) => { const mockSubscriptions = getMockSubscriptions ( '2' ) ; mocked ( API ) . getUserSubscriptions . mockResolvedValue ( mockSubscriptions ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; const modal = screen . getByRole ( 'dialog' ) ; expect ( modal ) . toBeInTheDocument ( ) ; expect ( modal ) . not . toHaveClass ( 'active' ) ; const btn = screen . getByRole ( 'button' , { name : 'Open subscription modal' } ) ; expect ( btn ) . toBeInTheDocument ( ) ; userEvent . click ( btn ) ; expect ( await screen . findByRole ( 'dialog' ) ) . toHaveClass ( 'active' ) ; } ) ; } ) ; describe ( 'Packages' , ( ) => { it ( 'renders 8 packages' , async ( ) => { const mockSubscriptions = getMockSubscriptions ( '3' ) ; mocked ( API ) . getUserSubscriptions . mockResolvedValue ( mockSubscriptions ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( screen . getAllByTestId ( 'subsTableCell' ) ) . toHaveLength ( 8 ) ; expect ( screen . getAllByRole ( 'listitem' ) ) . toHaveLength ( 8 ) ; } ) ; } ) ; it ( 'does not display list when no packages' , async ( ) => { const mockSubscriptions = getMockSubscriptions ( '4' ) ; mocked ( API ) . getUserSubscriptions . mockResolvedValue ( mockSubscriptions ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; expect ( screen . queryByTestId ( 'packagesList' ) ) . toBeNull ( ) ; } ) ; it ( 'calls alertDispatcher when getUserSubscriptions call fails with not Unauthorized error' , async ( ) => { mocked ( API ) . getUserSubscriptions . mockRejectedValue ( { kind : ErrorKind . Other } ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( alertDispatcher . postAlert ) . toHaveBeenCalledWith ( { type : 'danger' , message : 'An error occurred getting your subscriptions, please try again later.' , } ) ; } ) ; } ) ; it ( 'calls history push to load login modal when user is not signed in' , async ( ) => { mocked ( API ) . getUserSubscriptions . mockRejectedValue ( { kind : ErrorKind . Unauthorized , } ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => expect ( mockOnAuthError ) . toHaveBeenCalledTimes ( 1 ) ) ; } ) ; } ) ; it ( 'loads first page when not subscriptions after deleting one' , async ( ) => { const mockSubscriptions = getMockSubscriptions ( '11' ) ; mocked ( API ) . deleteSubscription . mockResolvedValue ( '' ) ; mocked ( API ) . getUserSubscriptions . mockResolvedValue ( mockSubscriptions ) . mockResolvedValueOnce ( mockSubscriptions ) . mockResolvedValueOnce ( mockSubscriptions ) . mockResolvedValueOnce ( { items : [ ] , paginationTotalCount : '12' , } ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 1 ) ; expect ( API . getUserSubscriptions ) . toHaveBeenCalledWith ( { limit : 10 , offset : 0 } ) ; } ) ; const nextBtn = screen . getAllByRole ( 'button' , { name : 'Open page 2' } ) ; userEvent . click ( nextBtn [ 1 ] ) ; await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 2 ) ; expect ( API . getUserSubscriptions ) . toHaveBeenCalledWith ( { limit : 10 , offset : 10 } ) ; } ) ; const input = screen . getByTestId ( `${ mockSubscriptions . items [ 0 ] . name }_newRelease_input` ) ; userEvent . click ( input ) ; await waitFor ( ( ) => { expect ( API . deleteSubscription ) . toHaveBeenCalledTimes ( 1 ) ; expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 4 ) ; expect ( API . getUserSubscriptions ) . toHaveBeenCalledWith ( { limit : 10 , offset : 10 } ) ; expect ( API . getUserSubscriptions ) . toHaveBeenCalledWith ( { limit : 10 , offset : 0 } ) ; } ) ; } ) ; describe ( 'to change subscription' , ( ) => { it ( 'to inactivate New release notification' , async ( ) => { const mockSubscriptions = getMockSubscriptions ( '5' ) ; mocked ( API ) . getUserSubscriptions . mockResolvedValue ( mockSubscriptions ) ; mocked ( API ) . deleteSubscription . mockResolvedValue ( '' ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; const checkbox = screen . getByTestId ( `${ mockSubscriptions . items [ 0 ] . name }_newRelease_input` ) as HTMLInputElement ; expect ( checkbox ) . toBeInTheDocument ( ) ; expect ( checkbox ) . toBeChecked ( ) ; userEvent . click ( checkbox ) ; await waitFor ( ( ) => { expect ( API . deleteSubscription ) . toHaveBeenCalledTimes ( 1 ) ; expect ( API . deleteSubscription ) . toHaveBeenCalledWith ( mockSubscriptions . items [ 0 ] . packageId , 0 ) ; } ) ; await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 2 ) ; } ) ; } ) ; } ) ; describe ( 'when change subscription fails' , ( ) => { it ( 'generic error' , async ( ) => { const mockSubscriptions = getMockSubscriptions ( '6' ) ; mocked ( API ) . getUserSubscriptions . mockResolvedValue ( mockSubscriptions ) ; mocked ( API ) . deleteSubscription . mockRejectedValue ( { kind : ErrorKind . Other } ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; const checkbox = screen . getByTestId ( `${ mockSubscriptions . items [ 0 ] . name }_newRelease_input` ) ; expect ( checkbox ) . toBeInTheDocument ( ) ; userEvent . click ( checkbox ) ; await waitFor ( ( ) => { expect ( screen . queryByTestId ( `${ mockSubscriptions . items [ 0 ] . name }_newRelease_input` ) ) . toBeNull ( ) ; } ) ; expect ( API . deleteSubscription ) . toHaveBeenCalledTimes ( 1 ) ; expect ( API . deleteSubscription ) . toHaveBeenCalledWith ( mockSubscriptions . items [ 0 ] . packageId , 0 ) ; expect ( alertDispatcher . postAlert ) . toHaveBeenCalledWith ( { type : 'danger' , message : `An error occurred unsubscribing from new releases notification for ${ mockSubscriptions . items [ 0 ] . name } package, please try again later.` , } ) ; await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 2 ) ; } ) ; expect ( await screen . findByTestId ( `${ mockSubscriptions . items [ 0 ] . name }_newRelease_input` ) ) . toBeInTheDocument ( ) ; } ) ; it ( 'UnauthorizedError' , async ( ) => { const mockSubscriptions = getMockSubscriptions ( '6' ) ; mocked ( API ) . getUserSubscriptions . mockResolvedValue ( mockSubscriptions ) ; mocked ( API ) . deleteSubscription . mockRejectedValue ( { kind : ErrorKind . Unauthorized , } ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; const checkbox = screen . getByTestId ( `${ mockSubscriptions . items [ 1 ] . name }_newRelease_input` ) ; userEvent . click ( checkbox ) ; await waitFor ( ( ) => { expect ( screen . queryByTestId ( `${ mockSubscriptions . items [ 1 ] . name }_newRelease_input` ) ) . toBeNull ( ) ; } ) ; await waitFor ( ( ) => { expect ( API . deleteSubscription ) . toHaveBeenCalledTimes ( 1 ) ; expect ( API . deleteSubscription ) . toHaveBeenCalledWith ( mockSubscriptions . items [ 1 ] . packageId , 0 ) ; } ) ; await waitFor ( ( ) => { expect ( mockOnAuthError ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; } ) ; } ) ; describe ( 'click links' , ( ) => { it ( 'on package link click' , async ( ) => { const mockSubscriptions = getMockSubscriptions ( '7' ) ; mocked ( API ) . getUserSubscriptions . mockResolvedValue ( mockSubscriptions ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; const links = screen . queryAllByTestId ( 'packageLink' ) ; expect ( links ) . toHaveLength ( 8 ) ; userEvent . click ( links [ 0 ] ) ; expect ( window . location . pathname ) . toBe ( '/packages/helm/stable/airflow' ) ; } ) ; it ( 'on user link click' , async ( ) => { const mockSubscriptions = getMockSubscriptions ( '8' ) ; mocked ( API ) . getUserSubscriptions . mockResolvedValue ( mockSubscriptions ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; const links = screen . queryAllByTestId ( 'userLink' ) ; expect ( links ) . toHaveLength ( 1 ) ; userEvent . click ( links [ 0 ] ) ; expect ( window . location . pathname ) . toBe ( '/packages/search' ) ; expect ( window . location . search ) . toBe ( '?user=jsmith&sort=relevance&page=1' ) ; } ) ; it ( 'on org link click' , async ( ) => { const mockSubscriptions = getMockSubscriptions ( '9' ) ; mocked ( API ) . getUserSubscriptions . mockResolvedValue ( mockSubscriptions ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; const links = screen . queryAllByTestId ( 'orgLink' ) ; expect ( links ) . toHaveLength ( 8 ) ; userEvent . click ( links [ 0 ] ) ; expect ( window . location . pathname ) . toBe ( '/packages/search' ) ; expect ( window . location . search ) . toBe ( '?org=helm&sort=relevance&page=1' ) ; } ) ; it ( 'on repo link click' , async ( ) => { const mockSubscriptions = getMockSubscriptions ( '10' ) ; mocked ( API ) . getUserSubscriptions . mockResolvedValue ( mockSubscriptions ) ; render ( < Router > < PackagesSection { ... defaultProps } / > < /Router>); await waitFor ( ( ) => { expect ( API . getUserSubscriptions ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; const links = screen . queryAllByTestId ( 'repoLink' ) ; expect ( links ) . toHaveLength ( 8 ) ; userEvent . click ( links [ 0 ] ) ; expect ( window . location . pathname ) . toBe ( '/packages/search' ) ; expect ( window . location . search ) . toBe ( '?repo=stable&sort=relevance&page=1' ) ; } ) ; } ) ; } ) ;