Files
floci-ui/packages/frontend/src/components/Route53RecordsPanel.test.tsx
T
2026-10-24 13:07:57 -04:00

95 lines
4.7 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 {beforeEach, expect, test, vi} from 'vitest'
import {Route53RecordsPanel} from './Route53RecordsPanel'
import type {CloudResource} from '@/types/resource'
const api = vi.hoisted(() => ({
deleteFlatItem: vi.fn(),
getCloudResource: vi.fn(),
listFlatItems: vi.fn(),
putFlatItem: vi.fn(),
}))
vi.mock('@/api/cloudProxyClient', () => api)
vi.mock('@/lib/accountStore', () => ({useAccountId: () => '000000000000'}))
const zone: CloudResource = {
id: 'ZG9PAE0M9KRWJ4F', name: 'example.test', cloud: 'aws', service: 'dns', type: 'hosted-zone',
region: null, createdAt: null, metadata: {visibility: 'public', recordCount: 3},
}
function item(id: string, body: Record<string, unknown>) {
return {id, collectionId: null, timestamp: null, metadata: {}, body: {ttl: 300, values: [], alias: null, setIdentifier: null, managed: false, editable: true, ...body}}
}
const records = [
item('example.test|NS', {name: 'example.test', type: 'NS', ttl: 172800, values: ['ns-1.awsdns-01.org.'], managed: true}),
item('www.example.test|A', {name: 'www.example.test', type: 'A', values: ['10.0.0.1']}),
item('example.test|TXT', {name: 'example.test', type: 'TXT', values: ['"v=spf1 -all"']}),
item('cdn.example.test|A', {name: 'cdn.example.test', type: 'A', ttl: null, alias: {dnsName: 'd111.cloudfront.net', hostedZoneId: 'Z2'}, editable: false}),
]
function renderPanel() {
const client = new QueryClient({defaultOptions: {queries: {retry: false}}})
return render(<QueryClientProvider client={client}><Route53RecordsPanel resource={zone} runtimeReachable/></QueryClientProvider>)
}
beforeEach(() => {
vi.clearAllMocks()
api.getCloudResource.mockResolvedValue({...zone, metadata: {...zone.metadata, nameServers: ['ns-1.awsdns-01.org', 'ns-2.awsdns-02.net']}})
api.listFlatItems.mockResolvedValue({items: records, nextCursor: null})
api.putFlatItem.mockImplementation(async (_cloud, _service, _zone, body) => item('x', {name: `${body.name}.example.test`, type: body.type}))
api.deleteFlatItem.mockResolvedValue(undefined)
})
test('shows the name servers and records, keeping the zone defaults read-only', async () => {
renderPanel()
expect(await screen.findByText('ns-2.awsdns-02.net')).toBeInTheDocument()
expect(await screen.findByText('10.0.0.1')).toBeInTheDocument()
expect(screen.getByText('Alias → d111.cloudfront.net')).toBeInTheDocument()
expect(screen.getByText('zone default')).toBeInTheDocument()
expect(screen.queryByRole('button', {name: 'Delete NS example.test'})).not.toBeInTheDocument()
expect(screen.queryByRole('button', {name: 'Edit A cdn.example.test'})).not.toBeInTheDocument()
expect(screen.getByRole('button', {name: 'Delete A cdn.example.test'})).toBeInTheDocument()
})
test('creates a record from a name inside the zone', async () => {
const user = userEvent.setup()
renderPanel()
const form = await screen.findByRole('form', {name: 'Create record'})
await user.type(within(form).getByLabelText(/Record name/), 'api')
await user.selectOptions(within(form).getByLabelText('Type'), 'CNAME')
await user.clear(within(form).getByLabelText(/TTL/))
await user.type(within(form).getByLabelText(/TTL/), '60')
await user.type(within(form).getByLabelText(/Values/), 'app.example.net')
await user.click(within(form).getByRole('button', {name: 'Create record'}))
expect(api.putFlatItem).toHaveBeenCalledWith('aws', 'dns', zone.id, {name: 'api', type: 'CNAME', ttl: 60, values: ['app.example.net']})
expect(await screen.findByText(/Created CNAME api.example.test/)).toBeInTheDocument()
})
test('edits a record with its name and type fixed, showing TXT text without quotes', async () => {
const user = userEvent.setup()
renderPanel()
await user.click(await screen.findByRole('button', {name: 'Edit TXT example.test'}))
const form = screen.getByRole('form', {name: 'Edit record'})
expect(within(form).getByLabelText(/Record name/)).toHaveValue('@')
expect(within(form).getByLabelText(/Record name/)).toBeDisabled()
expect(within(form).getByLabelText('Type')).toBeDisabled()
expect(within(form).getByLabelText(/Values/)).toHaveValue('v=spf1 -all')
})
test('deletes a record by its name and type', async () => {
const user = userEvent.setup()
renderPanel()
await user.click(await screen.findByRole('button', {name: 'Delete A www.example.test'}))
expect(api.deleteFlatItem).toHaveBeenCalledWith('aws', 'dns', zone.id, 'www.example.test|A')
expect(await screen.findByText('Deleted A www.example.test.')).toBeInTheDocument()
})