Some checks failed
ci / 정본·보안·린트·타입·테스트 (push) Failing after 50s
ci / 워크스페이스 빌드 검증 (push) Has been skipped
ci / Supabase Edge Functions + Cloudflare Worker (push) Successful in 20s
ci / .NET API 서버 테스트 (push) Successful in 12s
deploy-site / deploy (push) Successful in 39s
ci / 모바일 린트·타입·Jest (push) Failing after 3h10m31s
90 lines
3.1 KiB
TypeScript
90 lines
3.1 KiB
TypeScript
import React from 'react'
|
|
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
|
|
|
|
const mockSubmitAiContentReport = jest.fn()
|
|
const mockClose = jest.fn()
|
|
|
|
jest.mock('@d3ro/i18n', () => ({
|
|
useI18n: () => ({ t: (key: string, params?: Record<string, string>) => (
|
|
params?.id === undefined ? key : `${key}:${params.id}`
|
|
) }),
|
|
}))
|
|
jest.mock('../src/lib/preferences-context', () => {
|
|
const { d3roNativeDarkPalette } = jest.requireActual('@d3ro/ui-native') as typeof import('@d3ro/ui-native')
|
|
return {
|
|
useMobilePreferences: () => ({ palette: d3roNativeDarkPalette }),
|
|
}
|
|
})
|
|
jest.mock('../src/lib/random-id', () => ({
|
|
createUuidV4: () => '22222222-2222-4222-8222-222222222222',
|
|
}))
|
|
jest.mock('../src/features/reporting/content-report-service', () => {
|
|
const actual = jest.requireActual('../src/features/reporting/content-report-service')
|
|
return {
|
|
...actual,
|
|
submitAiContentReport: (...args: unknown[]) => mockSubmitAiContentReport(...args),
|
|
}
|
|
})
|
|
|
|
import ContentReportSheet from '../src/components/ContentReportSheet'
|
|
|
|
async function renderSheet(): Promise<ReactTestRenderer> {
|
|
let renderer: ReactTestRenderer
|
|
await act(async () => {
|
|
renderer = create(
|
|
<ContentReportSheet
|
|
visible
|
|
accessToken="access-token"
|
|
target={{
|
|
sourceType: 'talk_response',
|
|
generationId: '11111111-1111-4111-8111-111111111111',
|
|
snapshot: 'unsafe AI output',
|
|
}}
|
|
onRequestClose={mockClose}
|
|
/>,
|
|
)
|
|
await Promise.resolve()
|
|
})
|
|
return renderer!
|
|
}
|
|
|
|
describe('ContentReportSheet', () => {
|
|
beforeEach(() => {
|
|
mockClose.mockReset()
|
|
mockSubmitAiContentReport.mockReset().mockResolvedValue({
|
|
reportId: '33333333-3333-4333-8333-333333333333',
|
|
status: 'submitted',
|
|
idempotent: false,
|
|
createdAt: '2026-08-24T08:00:00.000Z',
|
|
})
|
|
})
|
|
|
|
it('requires a reason, submits only the selected output, and shows an in-app receipt', async () => {
|
|
const renderer = await renderSheet()
|
|
const submitBeforeReason = renderer.root.findByProps({ testID: 'content-report-submit' })
|
|
expect(submitBeforeReason.props.disabled).toBe(true)
|
|
|
|
await act(async () => {
|
|
renderer.root.findByProps({ testID: 'content-report-reason-privacy' }).props.onPress()
|
|
renderer.root.findByProps({ testID: 'content-report-comment' }).props.onChangeText('name exposed')
|
|
})
|
|
await act(async () => {
|
|
renderer.root.findByProps({ testID: 'content-report-submit' }).props.onPress()
|
|
await Promise.resolve()
|
|
await Promise.resolve()
|
|
})
|
|
|
|
expect(mockSubmitAiContentReport).toHaveBeenCalledWith({
|
|
accessToken: 'access-token',
|
|
idempotencyKey: '22222222-2222-4222-8222-222222222222',
|
|
generationId: '11111111-1111-4111-8111-111111111111',
|
|
sourceType: 'talk_response',
|
|
reason: 'privacy',
|
|
comment: 'name exposed',
|
|
snapshot: 'unsafe AI output',
|
|
})
|
|
expect(renderer.root.findByProps({ testID: 'content-report-success' })).toBeTruthy()
|
|
expect(renderer.root.findByProps({ testID: 'content-report-receipt' })).toBeTruthy()
|
|
expect(mockClose).not.toHaveBeenCalled()
|
|
})
|
|
})
|