Files
floci-ui/packages/frontend/src/components/RedisDataExplorer.test.tsx
T
2026-10-05 16:03:05 -04:00

72 lines
3.8 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 {RedisDataExplorer} from './RedisDataExplorer'
import type {CloudResource} from '@/types/resource'
const apiMocks = vi.hoisted(() => ({
connectRedis: vi.fn(),
scanRedisKeys: vi.fn(),
getRedisKeyDetails: vi.fn(),
setRedisString: vi.fn(),
deleteRedisKey: vi.fn(),
}))
vi.mock('@/api/elasticacheClient', () => apiMocks)
const cache: CloudResource = {
id: 'orders', name: 'orders', cloud: 'aws', service: 'elasticache', type: 'replication-group',
region: 'us-east-1', createdAt: null, engine: 'redis', metadata: {},
}
function renderExplorer() {
const queryClient = new QueryClient({defaultOptions: {queries: {retry: false}}})
return render(<QueryClientProvider client={queryClient}><RedisDataExplorer resource={cache} runtimeReachable/></QueryClientProvider>)
}
test('connects, scans matching keys, and inspects a typed value', async () => {
apiMocks.connectRedis.mockResolvedValue({ping: 'PONG', target: {engine: 'redis', endpoint: {address: 'redis.local', port: 6379, kind: 'primary'}}})
apiMocks.scanRedisKeys.mockResolvedValue({cursor: '0', keys: ['order:1']})
apiMocks.getRedisKeyDetails.mockResolvedValue({key: 'order:1', type: 'hash', ttlSeconds: 60, value: {status: 'new'}})
const user = userEvent.setup()
renderExplorer()
await user.type(screen.getByLabelText('Redis username'), 'app')
await user.type(screen.getByLabelText('Redis password'), 'secret')
await user.click(screen.getByRole('button', {name: 'Connect and ping'}))
await screen.findByText('redis.local:6379 (primary)')
expect(apiMocks.connectRedis).toHaveBeenCalledWith({resourceId: 'orders', credentials: {username: 'app', password: 'secret'}})
await user.type(screen.getByLabelText('Key match pattern'), 'order:*')
await user.click(screen.getByRole('button', {name: 'Scan keys'}))
expect(await screen.findByText('order:1')).toBeInTheDocument()
expect(apiMocks.scanRedisKeys).toHaveBeenCalledWith({resourceId: 'orders', credentials: {username: 'app', password: 'secret'}, match: 'order:*'})
await user.click(screen.getByRole('button', {name: 'order:1'}))
await screen.findByText('hash · 60s TTL')
expect(screen.getByText(/"status": "new"/)).toBeInTheDocument()
})
test('sets a string with a TTL and deletes the selected key', async () => {
apiMocks.connectRedis.mockResolvedValue({ping: 'PONG', target: {engine: 'valkey', endpoint: {address: 'cache.local', port: 6379, kind: 'configuration'}}})
apiMocks.scanRedisKeys.mockResolvedValue({cursor: '0', keys: ['order:1']})
apiMocks.getRedisKeyDetails.mockResolvedValue({key: 'order:1', type: 'string', ttlSeconds: -1, value: 'pending'})
apiMocks.setRedisString.mockResolvedValue({ok: true})
apiMocks.deleteRedisKey.mockResolvedValue({deleted: true})
const user = userEvent.setup()
renderExplorer()
await user.click(screen.getByRole('button', {name: 'Connect and ping'}))
await user.click(screen.getByRole('button', {name: 'Scan keys'}))
await user.click(await screen.findByRole('button', {name: 'order:1'}))
await user.click(await screen.findByRole('button', {name: 'Delete key'}))
await waitFor(() => expect(apiMocks.deleteRedisKey).toHaveBeenCalledWith({resourceId: 'orders', key: 'order:1'}))
await user.type(screen.getByLabelText('New Redis key'), 'order:2')
await user.type(screen.getByLabelText('New Redis value'), 'created')
await user.type(screen.getByLabelText('TTL seconds'), '30')
await user.click(screen.getByRole('button', {name: 'Set string'}))
await waitFor(() => expect(apiMocks.setRedisString).toHaveBeenCalledWith({resourceId: 'orders', key: 'order:2', value: 'created', ttlSeconds: 30}))
})