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 { AppCtx } from '../../../../context/AppCtx' ; import { ErrorKind , Webhook } from '../../../../types' ; import alertDispatcher from '../../../../utils/alertDispatcher' ; import WebhookCard from './Card' ; jest . mock ( '../../../../api' ) ; jest . mock ( '../../../../utils/alertDispatcher' ) ; const getmockWebhook = ( fixtureId ) : Webhook => { return require ( `./__fixtures__/Card/${ fixtureId }.json` ) as Webhook ; } ; const mockOnEdition = jest . fn ( ) ; const mockOnDeletion = jest . fn ( ) ; const mockOnAuthError = jest . fn ( ) ; const defaultProps = { onEdition : mockOnEdition , onDeletion : mockOnDeletion , onAuthError : mockOnAuthError , } ; const mockUserCtx = { user : { alias : 'userAlias' , email : 'jsmith@email.com' , passwordSet : true } , prefs : { controlPanel : { } , search : { limit : 60 } , theme : { configured : 'light' , effective : 'light' , } , notifications : { lastDisplayedTime : null , enabled : true , displayed : [ ] , } , } , } ; const mockOrgCtx = { user : { alias : 'userAlias' , email : 'jsmith@email.com' , passwordSet : true } , prefs : { controlPanel : { selectedOrg : 'test' } , search : { limit : 60 } , theme : { configured : 'light' , effective : 'light' , } , notifications : { lastDisplayedTime : null , enabled : true , displayed : [ ] , } , } , } ; describe ( 'WebhookCard' , ( ) => { afterEach ( ( ) => { jest . resetAllMocks ( ) ; } ) ; it ( 'creates snapshot' , ( ) => { const mockWebhook = getmockWebhook ( '1' ) ; const { asFragment } = render ( < AppCtx . Provider value = { { ctx : mockUserCtx , dispatch : jest . fn ( ) } } > < Router > < WebhookCard { ... defaultProps } webhook = { mockWebhook } / > < /Router> < /AppCtx.Provider>); expect ( asFragment ( ) ) . toMatchSnapshot ( ) ; } ) ; describe ( 'Render' , ( ) => { it ( 'renders active component' , ( ) => { const mockWebhook = getmockWebhook ( '2' ) ; render ( < AppCtx . Provider value = { { ctx : mockUserCtx , dispatch : jest . fn ( ) } } > < Router > < WebhookCard { ... defaultProps } webhook = { mockWebhook } / > < /Router> < /AppCtx.Provider>); expect ( screen . getByText ( mockWebhook . name ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( mockWebhook . url ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( mockWebhook . description ! ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Active' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Edit' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'Delete' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByRole ( 'button' , { name : 'Open deletion webhook modal' } ) ) . toBeInTheDocument ( ) ; } ) ; it ( 'renders inactive component' , ( ) => { const mockWebhook = getmockWebhook ( '3' ) ; render ( < AppCtx . Provider value = { { ctx : mockUserCtx , dispatch : jest . fn ( ) } } > < Router > < WebhookCard { ... defaultProps } webhook = { mockWebhook } / > < /Router> < /AppCtx.Provider>); expect ( screen . getByText ( 'Inactive' ) ) . toBeInTheDocument ( ) ; expect ( screen . queryByText ( 'Active' ) ) . toBeNull ( ) ; } ) ; it ( 'opens Edit form' , ( ) => { const mockWebhook = getmockWebhook ( '4' ) ; render ( < AppCtx . Provider value = { { ctx : mockUserCtx , dispatch : jest . fn ( ) } } > < Router > < WebhookCard { ... defaultProps } webhook = { mockWebhook } / > < /Router> < /AppCtx.Provider>); const btn = screen . getByRole ( 'button' , { name : 'Edit webhook' } ) ; expect ( btn ) . toHaveTextContent ( 'Edit' ) ; userEvent . click ( btn ) ; expect ( mockOnEdition ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; } ) ; describe ( 'on webhook deletion' , ( ) => { it ( 'when is successful' , async ( ) => { mocked ( API ) . deleteWebhook . mockResolvedValue ( null ) ; const mockWebhook = getmockWebhook ( '5' ) ; render ( < AppCtx . Provider value = { { ctx : mockUserCtx , dispatch : jest . fn ( ) } } > < Router > < WebhookCard { ... defaultProps } webhook = { mockWebhook } / > < /Router> < /AppCtx.Provider>); const modal = screen . queryByRole ( 'dialog' ) ; expect ( modal ) . toBeNull ( ) ; const btn = screen . getByRole ( 'button' , { name : 'Open deletion webhook modal' } ) ; userEvent . click ( btn ) ; expect ( screen . getByRole ( 'dialog' ) ) . toHaveClass ( 'active' ) ; expect ( screen . getByText ( 'Are you sure you want to delete this webhook?' ) ) . toBeInTheDocument ( ) ; const deleteBtn = screen . getByRole ( 'button' , { name : 'Delete webhook' } ) ; expect ( deleteBtn ) . toBeInTheDocument ( ) ; userEvent . click ( deleteBtn ) ; await waitFor ( ( ) => { expect ( API . deleteWebhook ) . toHaveBeenCalledTimes ( 1 ) ; expect ( API . deleteWebhook ) . toHaveBeenCalledWith ( mockWebhook . webhookId , undefined ) ; } ) ; expect ( mockOnDeletion ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; it ( 'when context is org' , async ( ) => { mocked ( API ) . deleteWebhook . mockResolvedValue ( null ) ; const mockWebhook = getmockWebhook ( '6' ) ; render ( < AppCtx . Provider value = { { ctx : mockOrgCtx , dispatch : jest . fn ( ) } } > < Router > < WebhookCard { ... defaultProps } webhook = { mockWebhook } / > < /Router> < /AppCtx.Provider>); const modal = screen . queryByRole ( 'dialog' ) ; expect ( modal ) . toBeNull ( ) ; const btn = screen . getByRole ( 'button' , { name : 'Open deletion webhook modal' } ) ; userEvent . click ( btn ) ; expect ( screen . getByRole ( 'dialog' ) ) . toHaveClass ( 'active' ) ; const deleteBtn = screen . getByRole ( 'button' , { name : 'Delete webhook' } ) ; userEvent . click ( deleteBtn ) ; await waitFor ( ( ) => { expect ( API . deleteWebhook ) . toHaveBeenCalledTimes ( 1 ) ; expect ( API . deleteWebhook ) . toHaveBeenCalledWith ( mockWebhook . webhookId , 'test' ) ; } ) ; expect ( mockOnDeletion ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; describe ( 'when fails' , ( ) => { it ( 'on UnauthorizedError' , async ( ) => { mocked ( API ) . deleteWebhook . mockRejectedValue ( { kind : ErrorKind . Unauthorized , } ) ; const mockWebhook = getmockWebhook ( '7' ) ; render ( < AppCtx . Provider value = { { ctx : mockUserCtx , dispatch : jest . fn ( ) } } > < Router > < WebhookCard { ... defaultProps } webhook = { mockWebhook } / > < /Router> < /AppCtx.Provider>); const btn = screen . getByRole ( 'button' , { name : 'Open deletion webhook modal' } ) ; userEvent . click ( btn ) ; const deleteBtn = screen . getByRole ( 'button' , { name : 'Delete webhook' } ) ; userEvent . click ( deleteBtn ) ; await waitFor ( ( ) => { expect ( API . deleteWebhook ) . toHaveBeenCalledTimes ( 1 ) ; expect ( API . deleteWebhook ) . toHaveBeenCalledWith ( mockWebhook . webhookId , undefined ) ; } ) ; expect ( mockOnAuthError ) . toHaveBeenCalledTimes ( 1 ) ; } ) ; it ( 'default error' , async ( ) => { mocked ( API ) . deleteWebhook . mockRejectedValue ( { kind : ErrorKind . Other } ) ; const mockWebhook = getmockWebhook ( '8' ) ; render ( < AppCtx . Provider value = { { ctx : mockUserCtx , dispatch : jest . fn ( ) } } > < Router > < WebhookCard { ... defaultProps } webhook = { mockWebhook } / > < /Router> < /AppCtx.Provider>); const btn = screen . getByRole ( 'button' , { name : 'Open deletion webhook modal' } ) ; userEvent . click ( btn ) ; const deleteBtn = screen . getByRole ( 'button' , { name : 'Delete webhook' } ) ; userEvent . click ( deleteBtn ) ; await waitFor ( ( ) => { expect ( API . deleteWebhook ) . toHaveBeenCalledTimes ( 1 ) ; expect ( API . deleteWebhook ) . toHaveBeenCalledWith ( mockWebhook . webhookId , undefined ) ; } ) ; expect ( alertDispatcher . postAlert ) . toHaveBeenCalledTimes ( 1 ) ; expect ( alertDispatcher . postAlert ) . toHaveBeenCalledWith ( { type : 'danger' , message : 'An error occurred deleting the webhook, please try again later.' , } ) ; } ) ; } ) ; } ) ; describe ( 'last notifications' , ( ) => { it ( 'renders button' , ( ) => { const mockWebhook = getmockWebhook ( '9' ) ; render ( < AppCtx . Provider value = { { ctx : mockUserCtx , dispatch : jest . fn ( ) } } > < Router > < WebhookCard { ... defaultProps } webhook = { mockWebhook } / > < /Router> < /AppCtx.Provider>); expect ( screen . getByText ( 'Show last notifications' ) ) . toBeInTheDocument ( ) ; expect ( screen . queryByTestId ( 'lastNotifAlert' ) ) . toBeNull ( ) ; } ) ; it ( 'renders button with exclamation icon' , ( ) => { const mockWebhook = getmockWebhook ( '10' ) ; render ( < AppCtx . Provider value = { { ctx : mockUserCtx , dispatch : jest . fn ( ) } } > < Router > < WebhookCard { ... defaultProps } webhook = { mockWebhook } / > < /Router> < /AppCtx.Provider>); expect ( screen . getByText ( 'Show last notifications' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByTestId ( 'lastNotifAlert' ) ) . toBeInTheDocument ( ) ; } ) ; it ( 'does not render button' , ( ) => { const mockWebhook = getmockWebhook ( '11' ) ; render ( < AppCtx . Provider value = { { ctx : mockUserCtx , dispatch : jest . fn ( ) } } > < Router > < WebhookCard { ... defaultProps } webhook = { mockWebhook } / > < /Router> < /AppCtx.Provider>); expect ( screen . queryByText ( 'Show last notifications' ) ) . toBeNull ( ) ; expect ( screen . queryByTestId ( 'lastNotifAlert' ) ) . toBeNull ( ) ; } ) ; } ) ; describe ( 'no packages' , ( ) => { it ( 'renders label' , async ( ) => { const mockWebhook = getmockWebhook ( '12' ) ; render ( < AppCtx . Provider value = { { ctx : mockUserCtx , dispatch : jest . fn ( ) } } > < Router > < WebhookCard { ... defaultProps } webhook = { mockWebhook } / > < /Router> < /AppCtx.Provider>); expect ( screen . getByText ( 'No packages' ) ) . toBeInTheDocument ( ) ; const badge = screen . getByTestId ( 'elementWithTooltip' ) ; expect ( badge ) . toBeInTheDocument ( ) ; userEvent . hover ( badge ) ; expect ( await screen . findByRole ( 'tooltip' ) ) . toBeInTheDocument ( ) ; expect ( screen . getByText ( 'This webhook is not associated to any packages.' ) ) . toBeInTheDocument ( ) ; } ) ; } ) ; } ) ;