PlatformWebhooksEndpointDetails.test.tsx141 lines · main
| 1 | import { render, screen, waitFor } from '@testing-library/react' |
| 2 | import userEvent from '@testing-library/user-event' |
| 3 | import type { ComponentProps } from 'react' |
| 4 | import { describe, expect, it, vi } from 'vitest' |
| 5 | |
| 6 | import { PLATFORM_WEBHOOKS_MOCK_DATA } from './PlatformWebhooks.mock' |
| 7 | import { PlatformWebhooksEndpointDetails } from './PlatformWebhooksEndpointDetails' |
| 8 | |
| 9 | vi.mock('@/components/ui/DataTable/DataTableColumn/DataTableColumnStatusCode', () => ({ |
| 10 | DataTableColumnStatusCode: ({ value }: { value: number }) => <span>{value}</span>, |
| 11 | })) |
| 12 | |
| 13 | vi.mock('@/components/ui/ButtonTooltip', () => ({ |
| 14 | ButtonTooltip: ({ |
| 15 | icon, |
| 16 | children, |
| 17 | size: _size, |
| 18 | tooltip: _tooltip, |
| 19 | type: _type, |
| 20 | ...props |
| 21 | }: any) => ( |
| 22 | <button type="button" {...props}> |
| 23 | {icon} |
| 24 | {children} |
| 25 | </button> |
| 26 | ), |
| 27 | })) |
| 28 | |
| 29 | vi.mock('ui-patterns', async () => { |
| 30 | const actual = await vi.importActual<typeof import('ui-patterns')>('ui-patterns') |
| 31 | |
| 32 | return { |
| 33 | ...actual, |
| 34 | TimestampInfo: ({ utcTimestamp, className }: { utcTimestamp: string; className?: string }) => ( |
| 35 | <span className={className}>{utcTimestamp}</span> |
| 36 | ), |
| 37 | } |
| 38 | }) |
| 39 | |
| 40 | describe('PlatformWebhooksEndpointDetails', () => { |
| 41 | const selectedEndpoint = PLATFORM_WEBHOOKS_MOCK_DATA.organization.endpoints[0] |
| 42 | const allDeliveries = PLATFORM_WEBHOOKS_MOCK_DATA.organization.deliveries.filter( |
| 43 | (delivery) => delivery.endpointId === selectedEndpoint.id |
| 44 | ) |
| 45 | |
| 46 | const renderComponent = ( |
| 47 | props?: Partial<ComponentProps<typeof PlatformWebhooksEndpointDetails>> |
| 48 | ) => |
| 49 | render( |
| 50 | <PlatformWebhooksEndpointDetails |
| 51 | deliverySearch="" |
| 52 | filteredDeliveries={allDeliveries} |
| 53 | selectedEndpoint={selectedEndpoint} |
| 54 | onDeliverySearchChange={vi.fn()} |
| 55 | onOpenDelivery={vi.fn()} |
| 56 | onRetryDelivery={vi.fn()} |
| 57 | {...props} |
| 58 | /> |
| 59 | ) |
| 60 | |
| 61 | it('renders paginated deliveries with previous and next controls', async () => { |
| 62 | const user = userEvent.setup() |
| 63 | |
| 64 | renderComponent() |
| 65 | |
| 66 | expect(screen.getByText('Showing 1 to 5 of 12 deliveries')).toBeInTheDocument() |
| 67 | expect(screen.queryByText('organization.member_removed')).not.toBeInTheDocument() |
| 68 | |
| 69 | await user.click(screen.getByLabelText('Next page')) |
| 70 | |
| 71 | expect(screen.getByText('Showing 6 to 10 of 12 deliveries')).toBeInTheDocument() |
| 72 | expect(screen.getByText('organization.member_removed')).toBeInTheDocument() |
| 73 | |
| 74 | await user.click(screen.getByLabelText('Previous page')) |
| 75 | |
| 76 | expect(screen.getByText('Showing 1 to 5 of 12 deliveries')).toBeInTheDocument() |
| 77 | expect(screen.queryByText('organization.member_removed')).not.toBeInTheDocument() |
| 78 | }) |
| 79 | |
| 80 | it('sorts deliveries by event type from the header', async () => { |
| 81 | const user = userEvent.setup() |
| 82 | |
| 83 | renderComponent() |
| 84 | |
| 85 | await user.click(screen.getByRole('button', { name: 'Event type' })) |
| 86 | |
| 87 | expect(screen.getAllByRole('row')[1]).toHaveTextContent('organization.member_invited') |
| 88 | |
| 89 | await user.click(screen.getByRole('button', { name: 'Event type' })) |
| 90 | |
| 91 | expect(screen.getAllByRole('row')[1]).toHaveTextContent('project.updated') |
| 92 | }) |
| 93 | |
| 94 | it('resets to the first page when the delivery search changes', async () => { |
| 95 | const user = userEvent.setup() |
| 96 | const projectDeliveries = allDeliveries.filter((delivery) => |
| 97 | delivery.eventType.includes('project') |
| 98 | ) |
| 99 | const { rerender } = renderComponent() |
| 100 | |
| 101 | await user.click(screen.getByLabelText('Next page')) |
| 102 | expect(screen.getByText('Showing 6 to 10 of 12 deliveries')).toBeInTheDocument() |
| 103 | |
| 104 | rerender( |
| 105 | <PlatformWebhooksEndpointDetails |
| 106 | deliverySearch="project" |
| 107 | filteredDeliveries={projectDeliveries} |
| 108 | selectedEndpoint={selectedEndpoint} |
| 109 | onDeliverySearchChange={vi.fn()} |
| 110 | onOpenDelivery={vi.fn()} |
| 111 | onRetryDelivery={vi.fn()} |
| 112 | /> |
| 113 | ) |
| 114 | |
| 115 | await waitFor(() => { |
| 116 | expect(screen.getByText('Showing 1 to 5 of 8 deliveries')).toBeInTheDocument() |
| 117 | }) |
| 118 | }) |
| 119 | |
| 120 | it('retries a failed delivery without opening the delivery row', async () => { |
| 121 | const user = userEvent.setup() |
| 122 | const onOpenDelivery = vi.fn() |
| 123 | const onRetryDelivery = vi.fn() |
| 124 | |
| 125 | renderComponent({ onOpenDelivery, onRetryDelivery }) |
| 126 | |
| 127 | await user.click(screen.getByLabelText('Retry org-delivery-2')) |
| 128 | |
| 129 | expect(onRetryDelivery).toHaveBeenCalledWith('org-delivery-2') |
| 130 | expect(onOpenDelivery).not.toHaveBeenCalled() |
| 131 | }) |
| 132 | |
| 133 | it('renders a zero response code instead of the placeholder', () => { |
| 134 | renderComponent({ |
| 135 | filteredDeliveries: [{ ...allDeliveries[0], id: 'org-delivery-zero', responseCode: 0 }], |
| 136 | }) |
| 137 | |
| 138 | expect(screen.getByText('0')).toBeInTheDocument() |
| 139 | expect(screen.queryByText('–')).not.toBeInTheDocument() |
| 140 | }) |
| 141 | }) |