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() } 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')) })