/** @vitest-environment jsdom */ import { cleanup, fireEvent, render, screen, waitFor, } from '@testing-library/react'; import { afterEach, describe, expect, it, vi } from 'vitest'; const mockState = vi.hoisted(() => ({ getPending: vi.fn(), listeners: [] as Array<() => void>, })); const dialogState = vi.hoisted(() => ({ fallbackEvents: [] as (typeof event)[], })); vi.mock('../src/services/errorReporting', () => ({ getPendingClientErrorEvents: mockState.getPending, subscribeClientErrorEvents: (listener: () => void) => { mockState.listeners.push(listener); return () => { mockState.listeners = mockState.listeners.filter( (item) => item !== listener, ); }; }, })); vi.mock('../src/components/error-report/ErrorReportDialog', () => ({ ErrorReportDialog: ({ fallbackEvents, open, }: { fallbackEvents?: (typeof event)[]; open: boolean; }) => { dialogState.fallbackEvents = fallbackEvents ?? []; return open ?
: null; }, })); import { ErrorReportNotice } from '../src/components/error-report/ErrorReportNotice'; const event = { eventId: 'rust-error-1', fingerprint: 'fingerprint-1', source: 'test', message: '错过 emit 的错误', occurredAt: '1', count: 1, }; describe('ErrorReportNotice', () => { afterEach(() => { cleanup(); mockState.getPending.mockReset(); mockState.listeners = []; }); it('挂载时查询快照,即使错过唤醒事件也能显示通知', async () => { mockState.getPending.mockResolvedValue([event]); render(); expect(await screen.findByText('发现问题')).toBeTruthy(); expect(mockState.getPending).toHaveBeenCalledTimes(1); }); it('收到唤醒后重新查询权威快照', async () => { mockState.getPending .mockResolvedValueOnce([]) .mockResolvedValueOnce([event]); render(); await waitFor(() => expect(mockState.getPending).toHaveBeenCalledTimes(1)); mockState.listeners[0]?.(); expect(await screen.findByText('发现问题')).toBeTruthy(); expect(mockState.getPending).toHaveBeenCalledTimes(2); }); it('打开报告时保留通知快照作为对话框 fallback', async () => { mockState.getPending.mockResolvedValue([event]); render(); await screen.findByText('发现问题'); fireEvent.click(screen.getByRole('button', { name: '查看并报告' })); expect(await screen.findByTestId('error-report-dialog')).toBeTruthy(); expect(dialogState.fallbackEvents).toEqual([event]); }); });