Files
k88936 964290c641
Project CI / Native shell tests (push) Successful in 21m3s
Project CI / Repository checks (push) Successful in 2m37s
Project CI / Frontend tests (push) Successful in 2m41s
Project CI / Backend tests (push) Successful in 7m2s
优化错误报告 (#286)
样式

before:
![shotmd-1788605870.jpg](/attachments/0470de00-944f-466e-a339-cf9e6cc0b780)
![shotmd-1788605755.jpg](/attachments/3e7be68e-31c5-41ba-9f8b-6dc98ec08868)

after:
![shotmd-1788607435.jpg](/attachments/165c878e-5c1c-4517-b7d5-74ce97a1a99b)
![shotmd-1788608364.jpg](/attachments/4dd20baf-879c-4aa8-ab51-bcc588d48dbc)

逻辑:
每次打开报告modal会再次查询队列中的错误
<video src="attachments/6d9d9bd7-5b7b-4a05-a7c3-ca64b6fb77f3" title="2026-09-05 19-46-02.mp4" controls></video>

---------

Co-authored-by: 段舒康 <kdletters@qq.com>
Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/286
Reviewed-by: 段舒康 <kdletters@qq.com>
Co-authored-by: 王德宇 <kvtodev@outlook.com>
Co-committed-by: 王德宇 <kvtodev@outlook.com>
2026-09-07 15:17:21 +08:00

99 lines
2.6 KiB
TypeScript

/** @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 ? <div data-testid="error-report-dialog" /> : 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(<ErrorReportNotice />);
expect(await screen.findByText('发现问题')).toBeTruthy();
expect(mockState.getPending).toHaveBeenCalledTimes(1);
});
it('收到唤醒后重新查询权威快照', async () => {
mockState.getPending
.mockResolvedValueOnce([])
.mockResolvedValueOnce([event]);
render(<ErrorReportNotice />);
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(<ErrorReportNotice />);
await screen.findByText('发现问题');
fireEvent.click(screen.getByRole('button', { name: '查看并报告' }));
expect(await screen.findByTestId('error-report-dialog')).toBeTruthy();
expect(dialogState.fallbackEvents).toEqual([event]);
});
});