// @vitest-environment jsdom import { describe, it, expect, vi, beforeEach } from 'vitest'; import '@testing-library/jest-dom/vitest'; import { render, screen, fireEvent, cleanup, waitFor } from '@testing-library/react'; import React from 'react'; const { mockListRevisions, mockRestoreRevision } = vi.hoisted(() => ({ mockListRevisions: vi.fn(), mockRestoreRevision: vi.fn() })); vi.mock('../../src/renderer/inbox/api.js', () => ({ inboxApi: { listRevisions: mockListRevisions, restoreRevision: mockRestoreRevision } })); import { RevisionHistoryModal } from '../../src/renderer/inbox/components/RevisionHistoryModal'; describe('RevisionHistoryModal', () => { beforeEach(() => { vi.clearAllMocks(); cleanup(); mockListRevisions.mockResolvedValue([ { revId: 3, noteId: 'a', rawText: 'v3', editedAt: '2026-05-11T00:00:00Z', editedBy: 'user' }, { revId: 2, noteId: 'a', rawText: 'v2', editedAt: '2026-05-10T00:00:00Z', editedBy: 'user' }, { revId: 1, noteId: 'a', rawText: 'v1', editedAt: '2026-05-01T00:00:00Z', editedBy: 'capture' } ]); mockRestoreRevision.mockResolvedValue({ ok: true }); }); it('open 시 listRevisions 호출 + 목록 표시 (capture/user 라벨)', async () => { render( {}} onRestored={() => {}} />); await waitFor(() => { expect(screen.getByText('v3')).toBeInTheDocument(); expect(screen.getByText('v2')).toBeInTheDocument(); expect(screen.getByText('v1')).toBeInTheDocument(); }); expect(screen.getByText(/캡처/)).toBeInTheDocument(); expect(screen.getAllByText(/사용자/).length).toBeGreaterThanOrEqual(1); }); it('회수 클릭 → confirm OK → restoreRevision + onRestored 호출 + onClose', async () => { const onRestored = vi.fn(); const onClose = vi.fn(); const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(true); render(); await waitFor(() => screen.getByText('v1')); const buttons = screen.getAllByRole('button', { name: /회수/ }); // last button = oldest (v1) const lastButton = buttons[buttons.length - 1]; if (lastButton === undefined) throw new Error('no 회수 button'); fireEvent.click(lastButton); await waitFor(() => { expect(mockRestoreRevision).toHaveBeenCalledWith('a', 1); }); expect(onRestored).toHaveBeenCalledWith('v1'); expect(onClose).toHaveBeenCalled(); confirmSpy.mockRestore(); }); });