Merge branch 'codex/20260831-consolidate-plugin-navigation-3d9a6c71-consolidate-plugin-navigation'

This commit is contained in:
inman
2026-09-01 11:46:24 +08:00
15 changed files with 415 additions and 100 deletions

View File

@@ -36,7 +36,7 @@ describe('Plugin Marketplace pages', () => {
onSearch={onSearch} onSelect={vi.fn()} onAcquire={onAcquire}
/></MemoryRouter>);
expect(screen.getByRole('heading', { name: '插件中心' })).toHaveClass('text-balance');
expect(screen.getByRole('heading', { name: '发现插件' })).toHaveClass('text-balance');
expect(screen.getByText('部分能力包含,部分按 Token Point 用量计费')).toBeVisible();
expect(screen.getByText('1')).toHaveClass('tabular-nums');
fireEvent.change(screen.getByRole('searchbox', { name: '搜索插件' }), { target: { value: '笔记' } });
@@ -92,7 +92,9 @@ describe('My Plugins', () => {
expect(onRemove).toHaveBeenCalledWith('makelore.notes');
fireEvent.click(screen.getByRole('button', { name: '重新免费获取旧插件' }));
expect(onReacquire).toHaveBeenCalledWith('makelore.removed');
expect(screen.getAllByRole('link', { name: '启用到项目' }).length).toBeGreaterThan(0);
const projectLinks = screen.getAllByRole('link', { name: '启用到项目' });
expect(projectLinks.length).toBeGreaterThan(0);
expect(projectLinks[0]).toHaveAttribute('href', '/project-config?resource=plugins&pluginTab=project');
expect(screen.getAllByRole('link', { name: '分配给伙伴' }).length).toBeGreaterThan(0);
expect(screen.getByText('运行已暂停')).toBeVisible();
expect(screen.getByText('已退役,移除后不可重新获取')).toBeVisible();
@@ -129,6 +131,18 @@ describe('My Plugins', () => {
expect(screen.getByRole('link', { name: '分配给伙伴' })).toBeVisible();
});
it('renders as the account/device tab inside project plugin services', () => {
render(<MemoryRouter><MyPluginsView
embedded library={{ ...library, items: [] }} installations={{}} state="ready"
pending={{}} onRefresh={vi.fn()} onInstall={vi.fn()} onUpdate={vi.fn()}
onInstallBeta={vi.fn()} onUninstall={vi.fn()} onRemove={vi.fn()} onReacquire={vi.fn()}
/></MemoryRouter>);
expect(screen.getByRole('heading', { name: '我的插件', level: 2 })).toBeVisible();
expect(screen.getByTestId('my-plugins-page').tagName).toBe('SECTION');
expect(screen.getByRole('link', { name: '浏览插件' })).toHaveAttribute('href', '/project-config?resource=plugins&pluginTab=discover');
});
it('updates an installed Beta package only through the explicit Beta action', () => {
const onUpdate = vi.fn();
const onInstallBeta = vi.fn();

View File

@@ -0,0 +1,47 @@
import { useState } from 'react';
import { fireEvent, render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { describe, expect, it, vi } from 'vitest';
import { PluginServices } from '@/components/plugins/PluginServices';
import { getPluginServiceTab, type PluginServiceTab } from '@/lib/plugin-services';
vi.mock('@/pages/PluginMarketplace', () => ({
PluginMarketplaceCatalog: () => <div>发现插件内容</div>,
}));
vi.mock('@/pages/MyPlugins', () => ({
MyPlugins: () => <div>我的插件内容</div>,
}));
vi.mock('@/pages/ProjectPlugins', () => ({
ProjectPlugins: () => <div>项目启用内容</div>,
}));
function Harness() {
const [value, setValue] = useState<PluginServiceTab>('project');
return <PluginServices
value={value}
onValueChange={setValue}
onProjectPluginsChanged={vi.fn()}
onManageAgents={vi.fn()}
onResolveIdentity={vi.fn()}
/>;
}
describe('PluginServices', () => {
it('keeps discovery, account/device management, and project enablement in one surface', () => {
render(<MemoryRouter><Harness /></MemoryRouter>);
expect(screen.getByRole('tab', { name: '项目启用' })).toHaveAttribute('aria-selected', 'true');
expect(screen.getByText('项目启用内容')).toBeVisible();
fireEvent.mouseDown(screen.getByRole('tab', { name: '发现插件' }), { button: 0, ctrlKey: false });
expect(screen.getByText('发现插件内容')).toBeVisible();
fireEvent.mouseDown(screen.getByRole('tab', { name: '我的插件' }), { button: 0, ctrlKey: false });
expect(screen.getByText('我的插件内容')).toBeVisible();
});
it('defaults invalid and missing deep-link values to project enablement', () => {
expect(getPluginServiceTab(null)).toBe('project');
expect(getPluginServiceTab('unknown')).toBe('project');
expect(getPluginServiceTab('discover')).toBe('discover');
expect(getPluginServiceTab('mine')).toBe('mine');
});
});

View File

@@ -92,4 +92,14 @@ describe('Project Plugin Center', () => {
fireEvent.click(screen.getByRole('button', { name: '从项目禁用保留插件 makelore.removed' }));
expect(onSetEnabled).toHaveBeenCalledWith('makelore.removed', false);
});
it('embeds project enablement in configuration and returns to Agent assignment explicitly', () => {
const onManageAgents = vi.fn();
render(<MemoryRouter><ProjectPluginsView embedded projectName="Demo" projection={projection()} dataService={null} pending={{}} agentNames={{}} onRefresh={vi.fn()} onSetEnabled={vi.fn()} onConfigure={vi.fn()} onReset={vi.fn()} onRemoveCollection={vi.fn()} onRemoveProject={vi.fn()} onManageAgents={onManageAgents} /></MemoryRouter>);
expect(screen.getByTestId('project-plugins-page').tagName).toBe('SECTION');
expect(screen.queryByRole('heading', { name: '项目插件' })).not.toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: '分配给伙伴' }));
expect(onManageAgents).toHaveBeenCalledTimes(1);
});
});