import { QueryClient } from '@tanstack/react-query'
import { act, fireEvent, screen, waitFor } from '@testing-library/react'
import type { components } from 'api-types'
import { HttpResponse } from 'msw'
import { Button } from 'ui'
import { describe, expect, test, vi } from 'vitest'
import { PipelineStatePill } from './PipelineStatePill'
import { UpdateVersionModal } from './UpdateVersionModal'
import { replicationKeys } from '@/data/replication/keys'
import {
useReplicationPipelineStatusQuery,
type ReplicationPipelineStatusResponse,
} from '@/data/replication/pipeline-status-query'
import type { Pipeline } from '@/data/replication/pipelines-query'
import {
PipelineRequestStatusProvider,
usePipelineRequestStatus,
} from '@/state/replication-pipeline-request-status'
import { customRender } from '@/tests/lib/custom-render'
import { addAPIMock } from '@/tests/lib/msw'
const pipeline: Pipeline = {
id: 9,
tenant_id: 'test',
source_id: 1,
source_name: 'main',
destination_id: 1,
destination_name: 'Analytics',
replicator_id: 1,
config: { publication_name: 'analytics' },
}
const StatusView = () => {
const { data, error, isPending, isError, isSuccess } = useReplicationPipelineStatusQuery({
projectRef: 'default',
pipelineId: 9,
})
const { getRequestStatus, isRequestPending } = usePipelineRequestStatus()
return (
<>
>
)
}
describe('pipeline version updates', () => {
test.each([
{
status: 'started',
initialLabel: 'Running',
confirmLabel: 'Update and restart',
pendingLabel: 'Stopping',
},
{
status: 'stopped',
initialLabel: 'Stopped',
confirmLabel: 'Update version',
pendingLabel: 'Stopped',
},
{
status: 'unknown',
initialLabel: 'Unknown',
confirmLabel: 'Update version',
pendingLabel: 'Unknown',
},
] as const)(
'honors the backend lifecycle for $status',
async ({ status, initialLabel, confirmLabel, pendingLabel }) => {
const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } })
const onClose = vi.fn()
const updates: unknown[] = []
let complete = () => {}
const response = new Promise((resolve) => {
complete = resolve
})
addAPIMock({
method: 'get',
path: '/platform/replication/:ref/pipelines/:pipeline_id/status',
response: () =>
HttpResponse.json({
pipeline_id: 9,
status: { name: status },
}),
})
addAPIMock({
method: 'get',
path: '/platform/replication/:ref/pipelines/:pipeline_id/version',
response: () =>
HttpResponse.json({
pipeline_id: 9,
version: { id: 1, name: 'v1' },
new_version: { id: 2, name: 'v2' },
}),
})
addAPIMock({
method: 'post',
path: '/platform/replication/:ref/pipelines/:pipeline_id/version',
response: async ({ request }) => {
updates.push(await request.json())
await response
return HttpResponse.json>({})
},
})
customRender(
,
{ queryClient }
)
await screen.findByText(initialLabel)
await screen.findByText('v2')
fireEvent.click(screen.getByRole('button', { name: confirmLabel }))
expect(screen.getByText(pendingLabel)).toBeInTheDocument()
expect(screen.getByText('Another action').closest('button')).toBeDisabled()
await act(async () => {
await queryClient.invalidateQueries(
{ queryKey: replicationKeys.pipelinesStatus('default', 9) },
{ cancelRefetch: false }
)
})
expect(screen.getByText(pendingLabel)).toBeInTheDocument()
expect(screen.getByText('Another action').closest('button')).toBeDisabled()
await act(async () => {
complete()
})
await waitFor(() => expect(onClose).toHaveBeenCalledOnce())
expect(screen.getByText('Another action').closest('button')).toBeEnabled()
// There are deliberately no start/stop/restart handlers: the update endpoint owns this.
expect(updates).toEqual([{ version_id: 2 }])
}
)
})