12b50f4868
CI / checks (pull_request) Successful in 27m2s
Create pipes from SQS, Kinesis, DynamoDB streams or MSK to Lambda, SQS, SNS, EventBridge buses or Step Functions, with an optional filter, enrichment and input template; start and stop them, see the flow with links to each resource, and send a test message to an SQS source. Sources and targets the runtime's poller cannot deliver between are refused on create.
82 lines
3.9 KiB
TypeScript
82 lines
3.9 KiB
TypeScript
import {QueryClient, QueryClientProvider} from '@tanstack/react-query'
|
|
import {render, screen, within} from '@testing-library/react'
|
|
import userEvent from '@testing-library/user-event'
|
|
import {MemoryRouter} from 'react-router-dom'
|
|
import {beforeEach, expect, test, vi} from 'vitest'
|
|
import {PipePanel} from './PipePanel'
|
|
import type {CloudResource} from '@/types/resource'
|
|
|
|
const api = vi.hoisted(() => ({
|
|
getCloudResource: vi.fn(),
|
|
startCloudResource: vi.fn(),
|
|
stopCloudResource: vi.fn(),
|
|
sendSqsMessage: vi.fn(),
|
|
}))
|
|
|
|
vi.mock('@/api/cloudProxyClient', () => api)
|
|
vi.mock('@/lib/accountStore', () => ({useAccountId: () => '000000000000'}))
|
|
|
|
function pipe(status = 'RUNNING', metadata: Record<string, unknown> = {}): CloudResource {
|
|
return {
|
|
id: 'orders-pipe', name: 'orders-pipe', cloud: 'aws', service: 'pipes', type: 'pipe', region: 'us-east-1', createdAt: null, status,
|
|
metadata: {
|
|
desiredState: status, source: 'arn:aws:sqs:us-east-1:000000000000:pipe-src', sourceName: 'pipe-src (SQS queue)',
|
|
target: 'arn:aws:lambda:us-east-1:000000000000:function:worker', targetName: 'worker (Lambda function)',
|
|
filterPatterns: ['{"body":{"kind":["order"]}}'], batchSize: 5, inputTemplate: '{"id": <$.messageId>}',
|
|
roleArn: 'arn:aws:iam::000000000000:role/pipe-role',
|
|
...metadata,
|
|
},
|
|
}
|
|
}
|
|
|
|
function renderPanel(resource: CloudResource) {
|
|
api.getCloudResource.mockResolvedValue(resource)
|
|
const client = new QueryClient({defaultOptions: {queries: {retry: false}}})
|
|
return render(<MemoryRouter><QueryClientProvider client={client}><PipePanel resource={resource} runtimeReachable/></QueryClientProvider></MemoryRouter>)
|
|
}
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
api.startCloudResource.mockResolvedValue(undefined)
|
|
api.stopCloudResource.mockResolvedValue(undefined)
|
|
api.sendSqsMessage.mockResolvedValue({messageId: 'm-1'})
|
|
})
|
|
|
|
test('shows the flow from source through the filter to the target, linked to each service', async () => {
|
|
renderPanel(pipe())
|
|
|
|
const flow = await screen.findByRole('list', {name: 'Event flow'})
|
|
expect(within(flow).getByRole('link', {name: 'pipe-src (SQS queue)'})).toHaveAttribute('href', '/cloud-explorer/aws/messaging')
|
|
expect(within(flow).getByRole('link', {name: 'worker (Lambda function)'})).toHaveAttribute('href', '/cloud-explorer/aws/serverless')
|
|
expect(within(flow).getByText('{"body":{"kind":["order"]}}')).toBeInTheDocument()
|
|
expect(within(flow).getByText('batches of 5')).toBeInTheDocument()
|
|
expect(within(flow).getByText('{"id": <$.messageId>}')).toBeInTheDocument()
|
|
})
|
|
|
|
test('stops a running pipe', async () => {
|
|
const user = userEvent.setup()
|
|
renderPanel(pipe())
|
|
|
|
await user.click(await screen.findByRole('button', {name: 'Stop'}))
|
|
expect(api.stopCloudResource).toHaveBeenCalledWith('aws', 'pipes', 'orders-pipe')
|
|
expect(await screen.findByText(/Pipe stopped/)).toBeInTheDocument()
|
|
})
|
|
|
|
test('sends a test message to an SQS source queue', async () => {
|
|
const user = userEvent.setup()
|
|
renderPanel(pipe())
|
|
|
|
const form = await screen.findByRole('form', {name: 'Send test message'})
|
|
await user.click(within(form).getByRole('button', {name: 'Send to pipe-src'}))
|
|
expect(api.sendSqsMessage).toHaveBeenCalledWith('aws', 'pipe-src', {messageBody: '{"kind": "order", "id": 1}'})
|
|
expect(await screen.findByText(/Sent message m-1/)).toBeInTheDocument()
|
|
})
|
|
|
|
test('offers no test message for a stream source, and cannot toggle a pipe mid-change', async () => {
|
|
renderPanel(pipe('STARTING', {source: 'arn:aws:kinesis:us-east-1:000000000000:stream/clicks', sourceName: 'clicks (Kinesis stream)', desiredState: 'RUNNING'}))
|
|
|
|
expect(await screen.findByRole('link', {name: 'clicks (Kinesis stream)'})).toBeInTheDocument()
|
|
expect(screen.queryByRole('form', {name: 'Send test message'})).not.toBeInTheDocument()
|
|
expect(screen.getByRole('button', {name: 'Start'})).toBeDisabled()
|
|
})
|