Merge branch 'codex/20260907-project-config-plugin-panel-c84e71a2-project-config-plugin-panel'

# Conflicts:
#	README.md
This commit is contained in:
inman
2026-09-07 14:59:14 +08:00
16 changed files with 583 additions and 709 deletions

View File

@@ -93,17 +93,20 @@ test.describe('Unified plugin workspace', () => {
await expect(page.getByTestId('project-plugins-sheet')).toBeVisible();
await expect(page.getByTestId('plugins-page')).toBeVisible();
await expect(page).toHaveURL(/\/project-config\/plugins\?scope=all/);
await expect(page.getByTestId('plugins-page').getByText('尚未获取')).toBeVisible();
await expect(page.getByText('为你的智能体添加插件,拓展更多能力。')).toBeVisible();
await expect(page.getByRole('button', { name: /刷新/ })).toHaveCount(0);
await expect(page.getByRole('searchbox')).toHaveCount(0);
await expect(page.getByRole('combobox')).toHaveCount(0);
await expect(page.getByRole('button', { name: '添加灵感笔记' })).toBeVisible();
await page.getByRole('button', { name: '查看灵感笔记详情' }).click();
await expect(page.getByRole('dialog', { name: '灵感笔记' })).toContainText('详细介绍');
await page.getByRole('button', { name: '免费获取灵感笔记' }).click();
await expect(page.getByRole('button', { name: '从账号移除灵感笔记' })).toBeVisible();
await expect(page.getByRole('dialog', { name: '灵感笔记' })).not.toContainText('读取项目名称');
await page.getByRole('button', { name: '添加灵感笔记' }).click();
await expect(page.getByRole('button', { name: '从插件库移除灵感笔记' })).toBeVisible();
await page.getByRole('button', { name: '关闭插件详情' }).click();
await page.getByRole('combobox', { name: '状态', exact: true }).selectOption('mine');
await expect(page).toHaveURL(/state=mine/);
await expect(page.getByRole('heading', { name: '灵感笔记' })).toBeVisible();
await expect(page.getByText('不适用项目启用')).toBeVisible();
await expect(page.getByRole('button', { name: '安装灵感笔记' })).toBeVisible();
const requests = await app.evaluate(() => (
(globalThis as typeof globalThis & { __pluginsE2E?: { requests: string[] } }).__pluginsE2E?.requests ?? []
));
@@ -157,17 +160,21 @@ test.describe('Unified plugin workspace', () => {
await expect(page.getByTestId('project-configuration-empty-state')).toBeVisible();
await expect(page.getByTestId('project-plugins-sheet')).toBeVisible();
await expect(page.getByTestId('plugins-page')).toBeVisible();
await expect(page.getByRole('alert')).toContainText('官方目录刷新失败');
await expect(page.getByRole('alert')).toContainText('官方目录加载失败');
await expect(page.getByRole('heading', { name: 'Local Search' })).toBeVisible();
await expect(page.getByText('本机全局已启用')).toBeVisible();
await expect(page.getByText(/仅通过对话安装/)).toBeVisible();
await expect(page.getByRole('button', { name: 'Local Search:已安装' })).toBeDisabled();
await expect(page.getByRole('button', { name: /刷新/ })).toHaveCount(0);
await expect(page.getByRole('searchbox')).toHaveCount(0);
await expect(page.getByRole('combobox')).toHaveCount(0);
await expect(page.getByRole('textbox', { name: /包|路径|source/i })).toHaveCount(0);
await page.getByRole('button', { name: '查看Local Search详情' }).click();
await expect(page.getByText(/完整桌面权限/)).toBeVisible();
await page.getByRole('button', { name: '本机全局停用Local Search' }).click();
await expect(page.getByRole('button', { name: '本机全局启用Local Search' })).toBeVisible();
await page.getByRole('button', { name: '本机全局启用Local Search' }).click();
await expect(page.getByRole('button', { name: '本机全局停用Local Search' })).toBeVisible();
await expect(page.getByText('为智能体提供可在本机使用的扩展能力。')).toBeVisible();
await expect(page.getByText(/完整桌面权限/)).toHaveCount(0);
await expect(page.getByText(/Pi extension|Skill 脚本/)).toHaveCount(0);
await page.getByRole('button', { name: '停用Local Search' }).click();
await expect(page.getByRole('button', { name: '启用Local Search' })).toBeVisible();
await page.getByRole('button', { name: '启用Local Search' }).click();
await expect(page.getByRole('button', { name: '停用Local Search' })).toBeVisible();
const requests = await app.evaluate(() => (
(globalThis as typeof globalThis & { __pluginsE2E?: { requests: string[] } }).__pluginsE2E?.requests ?? []
@@ -291,24 +298,23 @@ test.describe('Unified plugin workspace', () => {
await expect.poll(async () => app.evaluate(() => (
(globalThis as typeof globalThis & { __pluginsE2E?: { requests: string[] } }).__pluginsE2E?.requests ?? []
))).toContain('GET /api/coding/plugin-marketplace/library');
const bundledCard = page.getByRole('heading', { name: '游戏资源生成' }).locator('..');
await expect(bundledCard).toContainText('账号已获取');
await expect(page.getByRole('button', { name: '游戏资源生成:随应用提供' })).toBeDisabled();
await page.getByRole('button', { name: '查看开发数据服务详情' }).click();
await expect(page.getByText('当前状态没有可执行操作。')).toBeVisible();
await expect(page.getByText('当前无需进行其他操作。')).toBeVisible();
await page.getByRole('button', { name: '关闭插件详情' }).click();
await page.getByRole('button', { name: '查看游戏资源生成详情' }).click();
await expect(page.getByRole('button', { name: '从账号移除游戏资源生成' })).toBeVisible();
await expect(page.getByRole('button', { name: /下载.*游戏资源生成|删除.*游戏资源生成.*官方设备包/ })).toHaveCount(0);
await page.getByRole('button', { name: '从账号移除游戏资源生成' }).click();
await page.getByRole('button', { name: '确认从账号移除' }).click();
await expect(page.getByRole('button', { name: '从插件库移除游戏资源生成' })).toBeVisible();
await expect(page.getByRole('button', { name: /安装.*游戏资源生成|从本机卸载.*游戏资源生成/ })).toHaveCount(0);
await page.getByRole('button', { name: '从插件库移除游戏资源生成' }).click();
await page.getByRole('button', { name: '确认移除' }).click();
await page.getByRole('button', { name: '关闭插件详情' }).click();
await page.getByRole('button', { name: '查看Local Tool详情' }).click();
await expect(page.getByRole('button', { name: '本机全局停用Local Tool' })).toBeVisible();
await expect(page.getByRole('button', { name: /账号.*Local Tool|下载.*Local Tool/ })).toHaveCount(0);
await page.getByRole('button', { name: '本机全局停用Local Tool' }).click();
await expect(page.getByRole('button', { name: '停用Local Tool' })).toBeVisible();
await expect(page.getByRole('button', { name: /插件库.*Local Tool|安装.*Local Tool/ })).toHaveCount(0);
await page.getByRole('button', { name: '停用Local Tool' }).click();
const requests = await app.evaluate(() => (
(globalThis as typeof globalThis & { __pluginsE2E?: { requests: string[] } }).__pluginsE2E?.requests ?? []

View File

@@ -48,18 +48,40 @@ test.describe('Project configuration skills', () => {
expect(actionBarBottomGap).toBeLessThan(40);
await expect(page.getByRole('button', { name: '创建智能体' })).toBeVisible();
const resourceCardGeometry = await page.getByTestId('project-resource-row').locator(':scope > button').evaluateAll((cards) => cards.map((card) => {
const rect = card.getBoundingClientRect();
return { left: rect.left, top: rect.top, width: rect.width };
}));
expect(resourceCardGeometry).toHaveLength(4);
expect(Math.max(...resourceCardGeometry.map(({ top }) => top)) - Math.min(...resourceCardGeometry.map(({ top }) => top))).toBeLessThanOrEqual(1);
expect(resourceCardGeometry.every(({ width }) => width > 0)).toBe(true);
expect(resourceCardGeometry.map(({ left }) => left)).toEqual([...resourceCardGeometry.map(({ left }) => left)].sort((a, b) => a - b));
const drawerWidths: number[] = [];
for (const [resourceId, title] of [
['resource-card-models', '可用模型'],
['resource-card-knowledge', '知识文件'],
['resource-card-skills', '可用技能'],
['resource-card-knowledge', '知识文件'],
['resource-card-plugins', '插件'],
] as const) {
await page.getByTestId(resourceId).click();
const drawer = page.getByRole('dialog', { name: title });
await expect(drawer).toBeVisible();
const drawerBox = await drawer.boundingBox();
if (!drawerBox) throw new Error(`未能读取 ${title} 抽屉的布局区域`);
drawerWidths.push(drawerBox.width);
if (resourceId === 'resource-card-models') {
await expect(drawer.getByRole('combobox')).toHaveCount(0);
await expect(drawer.locator('[data-testid="project-model-list"], [data-testid="project-model-empty-state"]')).toHaveCount(1);
}
if (resourceId === 'resource-card-plugins') {
await expect(page.getByTestId('project-plugins-sheet')).toBeVisible();
await expect(drawer.getByTestId('plugins-page')).toBeVisible();
await expect(drawer.getByText('为你的智能体添加插件,拓展更多能力。')).toBeVisible();
await expect(drawer.getByRole('button', { name: /刷新/ })).toHaveCount(0);
await expect(drawer.getByRole('searchbox')).toHaveCount(0);
await expect(drawer.getByRole('combobox')).toHaveCount(0);
}
const closeButton = drawer.getByRole('button', { name: '关闭' });
const closeGeometry = await closeButton.evaluate((button) => {
const icon = button.querySelector('svg');
@@ -81,6 +103,8 @@ test.describe('Project configuration skills', () => {
await closeButton.locator('svg').click();
await expect(page.getByRole('dialog', { name: title })).toHaveCount(0);
}
expect(Math.max(...drawerWidths) - Math.min(...drawerWidths)).toBeLessThanOrEqual(1);
expect(Math.max(...drawerWidths)).toBeLessThanOrEqual(430);
const now = new Date().toISOString();
await mkdir(path.join(parentPath, '.makelore'), { recursive: true });

View File

@@ -103,10 +103,11 @@ test.describe('Unified project plugin workspace', () => {
includeHidden: true,
})).toBeAttached();
await page.getByRole('button', { name: '查看开发数据服务详情' }).click();
await expect(page.getByText('按平台包含,不按单次插件调用扣点。')).toBeVisible();
await expect(page.getByRole('heading', { name: '生效范围' })).toBeVisible();
await expect(page.getByText(/启用当前项目后.*无需单独分配/)).toBeVisible();
await expect(page.getByRole('button', { name: '分配开发数据服务给伙伴' })).toHaveCount(0);
const pluginDialog = page.getByRole('dialog', { name: '开发数据服务' });
await expect(pluginDialog).toContainText('为当前项目提供数据。');
await expect(pluginDialog).not.toContainText('Token Point');
await expect(pluginDialog).not.toContainText('data-service.control');
await expect(page.getByRole('button', { name: '将开发数据服务分配给智能体' })).toHaveCount(0);
const localProjectId = await app.evaluate(() => (
(globalThis as typeof globalThis & { __projectPluginE2E?: { localProjectId: string } }).__projectPluginE2E?.localProjectId
));
@@ -114,15 +115,15 @@ test.describe('Unified project plugin workspace', () => {
await expect(page.getByText(localProjectId as string)).toHaveCount(0);
await expect(page.getByText('11111111-1111-4111-8111-111111111111')).toHaveCount(0);
await page.getByRole('button', { name: '启用开发数据服务到当前项目' }).click();
await expect(page.getByRole('button', { name: '从当前项目禁用开发数据服务' })).toBeVisible();
await expect(page.getByText('插件专属设置')).toBeVisible();
await page.getByRole('button', { name: '将开发数据服务添加到项目' }).click();
await expect(page.getByRole('button', { name: '从项目移除开发数据服务' })).toBeVisible();
await expect(page.getByText('使用设置')).toBeVisible();
await expect(page.getByRole('button', { name: '创建开发数据空间' })).toBeDisabled();
await page.getByRole('button', { name: '从当前项目禁用开发数据服务' }).click();
await expect(page.getByRole('alertdialog')).toContainText('从当前项目禁用开发数据服务');
await page.getByRole('button', { name: '确认从当前项目禁用' }).click();
await expect(page.getByRole('button', { name: '启用开发数据服务到当前项目' })).toBeVisible();
await page.getByRole('button', { name: '从项目移除开发数据服务' }).click();
await expect(page.getByRole('alertdialog')).toContainText('从当前项目移除开发数据服务');
await page.getByRole('button', { name: '确认从项目移除' }).click();
await expect(page.getByRole('button', { name: '将开发数据服务添加到项目' })).toBeVisible();
const state = await app.evaluate(() => (
(globalThis as typeof globalThis & {