// @vitest-environment jsdom import { cleanup, fireEvent, render, screen } from '@testing-library/react'; import { useState } from 'react'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { PluginPanelHost } from '../src/features/plugins/PluginPanelHost'; import { readAgcPluginPanel } from '../src/services/pluginHost'; vi.mock('../src/services/pluginHost', () => ({ readAgcPluginPanel: vi.fn() })); const panel = { id: 'summary', title: '项目摘要', entry: './panel.html', placement: null, }; function Harness() { const [open, setOpen] = useState(true); return open ? ( setOpen(false)} /> ) : null; } describe('plugin panel mounting', () => { afterEach(() => { cleanup(); vi.clearAllMocks(); }); it('loads registered HTML into an isolated frame and removes it on close', async () => { vi.mocked(readAgcPluginPanel).mockResolvedValue({ panel, html: '

项目摘要

', }); render(); const frame = await screen.findByTitle('项目摘要'); expect(readAgcPluginPanel).toHaveBeenCalledWith( 'installed-plugin', 'summary', ); expect(frame.getAttribute('sandbox')).toBe('allow-scripts'); expect(frame.getAttribute('srcdoc')).toContain("default-src 'none'"); expect(frame.getAttribute('srcdoc')).toContain('

项目摘要

'); fireEvent.click(screen.getByRole('button', { name: '关闭 项目摘要' })); expect(screen.queryByTitle('项目摘要')).toBeNull(); }); it('shows a safe error when the host rejects panel access', async () => { vi.mocked(readAgcPluginPanel).mockRejectedValue(new Error('private path')); render(); expect((await screen.findByRole('alert')).textContent).toBe( '插件面板加载失败', ); expect(document.body.textContent).not.toContain('private path'); expect(screen.queryByTitle('项目摘要')).toBeNull(); }); });