Files
floci-ui/packages/frontend/src/components/EventBridgeRulePanel.test.tsx
T
2026-09-25 18:18:33 -04:00

82 lines
5.1 KiB
TypeScript

import {QueryClient, QueryClientProvider} from '@tanstack/react-query'
import {render, screen, waitFor} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import {expect, test, vi} from 'vitest'
import {EventBridgeRulePanel} from './EventBridgeRulePanel'
import type {CloudResource} from '@/types/resource'
const apiMocks = vi.hoisted(() => ({
createEventBridgeRule: vi.fn(),
deleteEventBridgeRule: vi.fn(),
listCloudResources: vi.fn(),
listEventBridgeRules: vi.fn(),
}))
vi.mock('@/api/cloudProxyClient', () => apiMocks)
const eventBus: CloudResource = {id: 'event-bus:orders', name: 'orders', cloud: 'aws', service: 'events', type: 'event-bus', region: null, createdAt: null, metadata: {}}
const lambda: CloudResource = {id: 'worker', name: 'worker', cloud: 'aws', service: 'serverless', type: 'lambda', region: null, createdAt: null, metadata: {arn: 'arn:aws:lambda:us-east-1:000000000000:function:worker'}}
const topic: CloudResource = {id: 'orders-topic', name: 'orders-topic', cloud: 'aws', service: 'notifications', type: 'topic', region: null, createdAt: null, metadata: {arn: 'arn:aws:sns:us-east-1:000000000000:orders-topic'}}
function renderPanel() {
const queryClient = new QueryClient({defaultOptions: {queries: {retry: false}}})
render(<QueryClientProvider client={queryClient}><EventBridgeRulePanel cloud="aws" resource={eventBus} runtimeReachable/></QueryClientProvider>)
}
test('creates a scheduled EventBridge rule with the selected resource ARN', async () => {
apiMocks.listCloudResources.mockImplementation((_: string, service: string) => Promise.resolve(service === 'serverless' ? [lambda] : []))
apiMocks.listEventBridgeRules.mockResolvedValue([])
apiMocks.createEventBridgeRule.mockResolvedValue({name: 'hourly-report'})
const user = userEvent.setup()
renderPanel()
await screen.findByRole('option', {name: 'worker'})
await user.type(screen.getByLabelText(/rule name/i), 'hourly-report')
await user.selectOptions(screen.getByLabelText(/target resource/i), String(lambda.metadata.arn))
expect(screen.getByText(/No Lambda, SQS queue, SNS topic, or Step Functions resources will be created/i)).toBeVisible()
await user.click(screen.getByRole('button', {name: 'Create rule'}))
await waitFor(() => expect(apiMocks.createEventBridgeRule).toHaveBeenCalledWith('aws', 'event-bus:orders', {
name: 'hourly-report', scheduleExpression: 'rate(5 minutes)', state: 'ENABLED', targets: [{id: 'worker', arn: lambda.metadata.arn}],
}))
})
test('creates an EventBridge rule with a selected SNS topic target', async () => {
apiMocks.listCloudResources.mockImplementation((_: string, service: string) => Promise.resolve(service === 'notifications' ? [topic] : []))
apiMocks.listEventBridgeRules.mockResolvedValue([])
apiMocks.createEventBridgeRule.mockResolvedValue({name: 'topic-notifications'})
const user = userEvent.setup()
renderPanel()
await screen.findByRole('option', {name: 'orders-topic'})
await user.selectOptions(screen.getByLabelText(/target service/i), 'sns')
await user.type(screen.getByLabelText(/rule name/i), 'topic-notifications')
await user.selectOptions(screen.getByLabelText(/target resource/i), String(topic.metadata.arn))
await user.click(screen.getByRole('button', {name: 'Create rule'}))
await waitFor(() => expect(apiMocks.createEventBridgeRule).toHaveBeenCalledWith('aws', eventBus.id, {
name: 'topic-notifications', scheduleExpression: 'rate(5 minutes)', state: 'ENABLED', targets: [{id: 'orders-topic', arn: topic.metadata.arn}],
}))
})
test('creates an event-pattern rule and confirms before deletion', async () => {
apiMocks.listCloudResources.mockImplementation((_: string, service: string) => Promise.resolve(service === 'serverless' ? [lambda] : []))
apiMocks.listEventBridgeRules.mockResolvedValue([{name: 'billing-events', busName: 'orders', busId: eventBus.id, arn: null, eventPattern: '{"source":["billing"]}', state: 'DISABLED', targets: [{id: 'worker', arn: String(lambda.metadata.arn)}]}])
apiMocks.createEventBridgeRule.mockResolvedValue({name: 'billing-events'})
apiMocks.deleteEventBridgeRule.mockResolvedValue(undefined)
const user = userEvent.setup()
renderPanel()
await user.click(screen.getByLabelText(/mode/i))
await user.selectOptions(screen.getByLabelText(/mode/i), 'event-pattern')
await user.type(screen.getByLabelText(/rule name/i), 'billing-events')
await user.selectOptions(screen.getByLabelText(/target resource/i), String(lambda.metadata.arn))
await user.click(screen.getByRole('button', {name: 'Create rule'}))
await waitFor(() => expect(apiMocks.createEventBridgeRule).toHaveBeenCalledWith('aws', eventBus.id, expect.objectContaining({eventPattern: '{\n "source": ["orders"]\n}'})))
await user.click(await screen.findByRole('button', {name: 'Delete rule billing-events'}))
expect(screen.getByText('Delete rule?')).toBeVisible()
await user.click(screen.getByRole('button', {name: 'Delete'}))
await waitFor(() => expect(apiMocks.deleteEventBridgeRule).toHaveBeenCalledWith('aws', eventBus.id, 'billing-events'))
})