Files
creator-hub/web/src/features/operations/AuditPage.test.jsx
T

63 lines
3.5 KiB
React

import { afterEach, describe, expect, it, vi } from 'vitest'
import { cleanup, fireEvent, render, screen, waitFor, within } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { TestDataProvider } from '../../test/providerCompat.jsx'
import { MemoryRouter } from '../../test/routerCompat.jsx'
import { AuditPage, auditCSV } from './AuditPage'
afterEach(() => { cleanup(); vi.restoreAllMocks() })
const httpQuery = () => new QueryClient({ defaultOptions: { queries: { retry: false } } })
function renderAudit(dataProvider, initialEntry = '/audit?task_id=task-a') {
return render(
<QueryClientProvider client={httpQuery()}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter initialEntries={[initialEntry]}><AuditPage /></MemoryRouter>
</TestDataProvider>
</QueryClientProvider>,
)
}
describe('AuditPage', () => {
it('deep-links safe correlation fields and exposes no mutation or secret details', async () => {
const dataProvider = {
getList: vi.fn().mockResolvedValue({ data: [{
id: 7, event_type: 'task_verified', account_id: 'account-a', task_id: 'task-a', attempt_id: 'attempt-a',
browser_env_alias: 'env-a', network_exit_id: 'exit-a', binding_version: 4, reason_code: 'manual_verification_recorded',
details: { token: 'must-not-render' }, created_at: '2026-08-30T00:00:00Z',
}], total: 1 }),
getOne: vi.fn(), getMany: vi.fn(), getManyReference: vi.fn(), create: vi.fn(), update: vi.fn(), updateMany: vi.fn(), delete: vi.fn(), deleteMany: vi.fn(),
}
renderAudit(dataProvider)
expect((await screen.findAllByRole('link', { name: 'task-a' })).length).toBeGreaterThan(0)
expect(screen.getAllByRole('link', { name: 'account-a' })[0].getAttribute('href')).toBe('/accounts/account-a')
expect(screen.getAllByRole('link', { name: 'attempt-a' })[0].getAttribute('href')).toBe('/attempts/attempt-a')
expect(screen.getAllByRole('link', { name: 'env-a' })[0].getAttribute('href')).toBe('/browsers/env-a')
expect(screen.getAllByRole('link', { name: 'exit-a' })[0].getAttribute('href')).toBe('/network-exits/exit-a')
expect(screen.queryByText('must-not-render')).toBeNull()
expect(screen.queryByRole('button', { name: /编辑|删除/ })).toBeNull()
})
it('exports only allowlisted correlation columns and requests the next page', async () => {
const event = {
id: 7, event_type: 'task_verified', task_id: 'task-a', attempt_id: 'attempt-a', browser_env_alias: 'env-a', network_exit_id: 'exit-a',
details: { api_key: 'api-secret', private_key: 'private-secret', credential_key: 'credential-secret', authorization_header: 'auth-secret', proxy_url: 'proxy-secret' },
created_at: '2026-08-30T00:00:00Z',
}
const csv = auditCSV([event])
expect(csv).toContain('attempt-a')
for (const secret of ['api-secret', 'private-secret', 'credential-secret', 'auth-secret', 'proxy-secret']) expect(csv).not.toContain(secret)
const getList = vi.fn().mockImplementation(() => Promise.resolve({ data: [{ ...event, id: 7 }], total: 26 }))
const dataProvider = {
getList, getOne: vi.fn(), getMany: vi.fn(), getManyReference: vi.fn(), create: vi.fn(), update: vi.fn(), updateMany: vi.fn(), delete: vi.fn(), deleteMany: vi.fn(),
}
renderAudit(dataProvider, '/audit')
fireEvent.click(await screen.findByRole('button', { name: '下一页' }))
await waitFor(() => expect(getList.mock.calls.some(([{ pagination }]) => (pagination?.currentPage || pagination?.page) === 2)).toBe(true))
})
})