import { render, screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { afterEach, describe, expect, it, vi } from 'vitest' import { AutoDetectImageKeySection } from '../../src/renderer/src/features/settings/image-decryption/AutoDetectImageKeySection' import { ImageDecryptStatus } from '../../src/renderer/src/features/settings/image-decryption/ImageDecryptStatus' import { ImageTestSection } from '../../src/renderer/src/features/settings/image-decryption/ImageTestSection' import { initialImageDecryptionState } from '../../src/renderer/src/features/settings/image-decryption/imageDecryptionReducer' import type { ImageBatchTestState } from '../../src/renderer/src/features/settings/image-decryption/types' import type { ImageDecryptionStatus } from '../../src/shared/image-decryption' const emptyBatchTest: ImageBatchTestState = { running: false, stopRequested: false, elapsedMs: 0, items: [] } const imageStatus: ImageDecryptionStatus = { configured: true, saved: true, encryptionAvailable: true, source: 'secure-storage', resourceRoot: '/fixture/images', platform: 'darwin', autoDetectSupported: true, wechatRunning: true, accountIdentified: true, cacheState: 'normal', decoder: { installed: true, available: true, source: 'bundled', selected: false }, resources: { imageIndex: { state: 'available', detail: '正常' }, imageDirectory: { state: 'available', detail: '正常' }, thumbnail: { state: 'available', detail: '正常' }, original: { state: 'available', detail: '正常' }, sticker: { state: 'available', detail: '正常' }, video: { state: 'available', detail: '正常' } } } afterEach(() => { vi.restoreAllMocks() }) describe('ImageTestSection', () => { it('uses shared buttons for status validation and automatic key actions', async () => { const user = userEvent.setup() const onValidate = vi.fn() const onDetect = vi.fn() const onSave = vi.fn() const configuredState = { ...initialImageDecryptionState, config: { success: true, configured: true, saved: true, encryptionAvailable: true, source: 'secure-storage' as const, resourceRoot: '/fixture/images' }, status: imageStatus } const { rerender } = render( ) const validate = screen.getByRole('button', { name: '重新验证' }) expect(validate).not.toHaveClass('database-key-secondary') await user.click(validate) expect(onValidate).toHaveBeenCalledOnce() rerender( ) const detect = screen.getByRole('button', { name: '开始自动获取' }) const save = screen.getByRole('button', { name: '保存图片密钥' }) expect(detect).not.toHaveClass('database-key-secondary') expect(save).not.toHaveClass('database-key-primary') await user.click(detect) await user.click(save) expect(onDetect).toHaveBeenCalledOnce() expect(onSave).toHaveBeenCalledOnce() }) it('keeps automatic detection disabled while scanning', () => { render( ) expect(screen.getByRole('button', { name: '扫描中…' })).toBeDisabled() }) it('keeps the file step successful when decryption fails and copies diagnostics', async () => { const onCopyLog = vi.fn() render( ) expect(screen.getByText('找到图片文件').closest('li')).toHaveClass('image-step-ok') expect(screen.getByText('解密成功').closest('li')).toHaveClass('image-step-fail') expect(screen.getByText('图片可以读取').closest('li')).toHaveClass('image-step-skipped') expect(screen.getByText('仅当前会话的单次测试日志')).toHaveAttribute( 'title', expect.stringContaining('不包含批量测试结果') ) await userEvent.click(screen.getByRole('button', { name: '复制日志' })) expect(onCopyLog).toHaveBeenCalledOnce() }) it('disables log copying before a test result exists', () => { render( ) expect(screen.getByRole('button', { name: '复制日志' })).toBeDisabled() }) it('filters groups and contacts before starting a batch test', async () => { const onBatchTest = vi.fn() const onSelect = vi.fn() vi.spyOn(window, 'confirm').mockReturnValue(true) render( ) await userEvent.click(screen.getByRole('radio', { name: '群聊 1' })) expect(screen.getByRole('radio', { name: '群聊 1' })).toBeChecked() await userEvent.click(screen.getByRole('combobox', { name: '选择会话' })) expect(screen.getByRole('option', { name: '测试群聊' })).toBeInTheDocument() expect(screen.queryByRole('option', { name: '测试联系人' })).not.toBeInTheDocument() await userEvent.click(screen.getByRole('option', { name: '测试群聊' })) expect(onSelect).toHaveBeenCalledWith('group-md5') await userEvent.click(screen.getByRole('button', { name: '测试筛选结果(1)' })) expect(window.confirm).toHaveBeenCalledWith(expect.stringContaining('测试 1 个会话')) expect(onBatchTest).toHaveBeenCalledWith([ expect.objectContaining({ md5: 'group-md5', type: 'group' }) ]) }) it('shows per-conversation batch result and elapsed time', () => { render( ) expect(screen.getByText('成功群聊')).toBeInTheDocument() expect(screen.getByText('没有图片的联系人')).toBeInTheDocument() expect(screen.getByText('成功 1')).toBeInTheDocument() expect(screen.getByText('无图片 1')).toBeInTheDocument() expect(screen.getByText(/2\/2 · 已耗时 1\.3 秒/)).toBeInTheDocument() }) })