feat(api): add CloudWatch alarms and metric charts to the cloud explorer
CI / checks (pull_request) Successful in 27m29s
CI / checks (pull_request) Successful in 27m29s
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import {QueryClient, QueryClientProvider} from '@tanstack/react-query'
|
||||
import {render, screen, within} from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import {beforeEach, expect, test, vi} from 'vitest'
|
||||
import {CloudWatchAlarmPanel} from './CloudWatchAlarmPanel'
|
||||
import {HttpError} from '@/api/HttpClient'
|
||||
import type {CloudResource} from '@/types/resource'
|
||||
|
||||
const api = vi.hoisted(() => ({
|
||||
getCloudResource: vi.fn(),
|
||||
describeAlarmHistory: vi.fn(),
|
||||
getMetricSeries: vi.fn(),
|
||||
setAlarmState: vi.fn(),
|
||||
setAlarmActionsEnabled: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('@/api/cloudProxyClient', () => api)
|
||||
vi.mock('@/lib/accountStore', () => ({useAccountId: () => '000000000000'}))
|
||||
|
||||
const alarm: CloudResource = {
|
||||
id: 'high-errors', name: 'high-errors', cloud: 'aws', service: 'monitoring', type: 'alarm', region: 'us-east-1', createdAt: null, status: 'ALARM',
|
||||
metadata: {
|
||||
alarmType: 'metric', stateReason: 'Threshold crossed', actionsEnabled: true, alarmActions: ['arn:aws:sns:us-east-1:000000000000:alerts'], okActions: [],
|
||||
namespace: 'App', metricName: 'Errors', dimensions: [], statistic: 'Sum', threshold: 5, condition: 'Errors Sum > 5 for 1 × 5 min',
|
||||
},
|
||||
}
|
||||
|
||||
function renderPanel() {
|
||||
const client = new QueryClient({defaultOptions: {queries: {retry: false}}})
|
||||
return render(<QueryClientProvider client={client}><CloudWatchAlarmPanel resource={alarm} runtimeReachable/></QueryClientProvider>)
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
api.getCloudResource.mockResolvedValue(alarm)
|
||||
api.describeAlarmHistory.mockResolvedValue([{timestamp: null, type: 'StateUpdate', summary: 'Alarm updated from OK to ALARM'}])
|
||||
api.getMetricSeries.mockResolvedValue({label: 'Errors', statistic: 'Sum', periodSeconds: 60, points: [{timestamp: '2026-10-25T10:00:00Z', value: 7}]})
|
||||
api.setAlarmState.mockResolvedValue(undefined)
|
||||
api.setAlarmActionsEnabled.mockResolvedValue(undefined)
|
||||
})
|
||||
|
||||
test('shows the state, its metric with the threshold, the targets and the history', async () => {
|
||||
renderPanel()
|
||||
|
||||
expect(screen.getByText('Threshold crossed')).toBeInTheDocument()
|
||||
expect(await screen.findByText('Threshold 5')).toBeInTheDocument()
|
||||
expect(screen.getByText('arn:aws:sns:us-east-1:000000000000:alerts')).toBeInTheDocument()
|
||||
expect(await screen.findByText('Alarm updated from OK to ALARM')).toBeInTheDocument()
|
||||
expect(api.getMetricSeries).toHaveBeenCalledWith('aws', expect.objectContaining({namespace: 'App', metricName: 'Errors', statistic: 'Sum', rangeMinutes: 180}), expect.anything())
|
||||
})
|
||||
|
||||
test('sets a state to test the actions, and turns the actions off', async () => {
|
||||
const user = userEvent.setup()
|
||||
renderPanel()
|
||||
|
||||
const form = await screen.findByRole('form', {name: 'Set alarm state'})
|
||||
await user.selectOptions(within(form).getByLabelText('State'), 'OK')
|
||||
await user.type(within(form).getByLabelText('Reason'), 'Testing')
|
||||
await user.click(within(form).getByRole('button', {name: 'Set state'}))
|
||||
expect(api.setAlarmState).toHaveBeenCalledWith('aws', 'high-errors', 'OK', 'Testing')
|
||||
expect(await screen.findByText(/Set to OK/)).toBeInTheDocument()
|
||||
|
||||
await user.click(within(form).getByRole('button', {name: 'Turn actions off'}))
|
||||
expect(api.setAlarmActionsEnabled).toHaveBeenCalledWith('aws', 'high-errors', false)
|
||||
})
|
||||
|
||||
test('says when the runtime does not record alarm history, without an error', async () => {
|
||||
api.describeAlarmHistory.mockRejectedValue(new HttpError(501, 'Not Implemented', {code: 'operation_not_implemented', error: 'Operation is not implemented by the selected runtime'}, '/history'))
|
||||
renderPanel()
|
||||
|
||||
expect(await screen.findByText(/does not record alarm history yet/)).toBeInTheDocument()
|
||||
expect(screen.queryByRole('alert')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user