fix(agents): make editor settings peer tabs

This commit is contained in:
2026-09-15 14:50:06 +08:00
parent 80e52496d2
commit 868ab54be6
5 changed files with 163 additions and 18 deletions

View File

@@ -117,7 +117,29 @@ test('personal cloud Agent creation, draft save and leave protection in Electron
await page.getByRole('button', { name: '保存并开始试用', exact: true }).click();
await expect(page.getByRole('button', { name: '已保存', exact: true })).toBeVisible();
await expect(page.getByTestId('titlebar-page-title')).toHaveText('智能体工作区');
await page.getByRole('button', { name: '高级设置', exact: true }).click();
const requirementsTab = page.getByRole('tab', { name: '我的要求', exact: true });
const advancedTab = page.getByRole('tab', { name: '高级设置', exact: true });
await expect(requirementsTab).toHaveAttribute('aria-selected', 'true');
await expect(page.getByRole('navigation', { name: '配置分类' })).toHaveCount(0);
await requirementsTab.focus();
await requirementsTab.press('ArrowRight');
await expect(advancedTab).toBeFocused();
await expect(advancedTab).toHaveAttribute('aria-selected', 'true');
await expect(page.getByRole('tabpanel', { name: '高级设置' })).toBeVisible();
await expect(page.getByLabel('特别要求')).toBeHidden();
await expect(page.getByRole('button', { name: '能力', exact: true })).toHaveAttribute('aria-current', 'page');
await advancedTab.click();
await expect(advancedTab).toHaveAttribute('aria-selected', 'true');
await page.screenshot({ path: testInfo.outputPath('cloud-agent-advanced-tab.png') });
const configurationScroll = page.getByRole('tabpanel').locator('.agent-config-scroll');
await configurationScroll.evaluate(el => { el.scrollTop = el.scrollHeight; });
await expect.poll(() => configurationScroll.evaluate(el => el.scrollTop)).toBeGreaterThan(0);
await requirementsTab.click();
await expect.poll(() => configurationScroll.evaluate(el => el.scrollTop)).toBe(0);
await expect(page.getByLabel('用途', { exact: true })).toBeInViewport();
await page.screenshot({ path: testInfo.outputPath('cloud-agent-requirements-tab.png') });
await advancedTab.click();
await expect.poll(() => configurationScroll.evaluate(el => el.scrollTop)).toBe(0);
await page.getByRole('button', { name: '知识', exact: true }).click();
await page.getByText('管理我的知识文档', { exact: true }).click();
const knowledgeDescription = page.getByText(/上传到知识库的文档可供/);
@@ -131,6 +153,12 @@ test('personal cloud Agent creation, draft save and leave protection in Electron
await expect(page.getByText(/Yuxi 后台/)).toContainText('服务地址和 API Key');
await expect(page.getByText(/Works Square 运营后台|one-api/)).toHaveCount(0);
await page.getByLabel('知识库名称', { exact: true }).fill('我的创作资料');
await requirementsTab.click();
await expect(page.getByRole('navigation', { name: '配置分类' })).toHaveCount(0);
await expect(page.getByLabel('特别要求')).toHaveValue('使用简洁自然的中文。先理解我的目的,再协助梳理结构。');
await advancedTab.click();
await expect(page.getByRole('button', { name: '知识', exact: true })).toHaveAttribute('aria-current', 'page');
await expect(page.getByLabel('知识库名称', { exact: true })).toHaveValue('我的创作资料');
await page.screenshot({ path: testInfo.outputPath('knowledge-empty.png') });
await page.getByRole('button', { name: '刷新知识库与模型', exact: true }).click();
await page.getByLabel('向量模型', { exact: true }).selectOption('fixture:test-embedding');
@@ -152,7 +180,7 @@ test('personal cloud Agent creation, draft save and leave protection in Electron
await document.scrollIntoViewIfNeeded();
expect(await document.evaluate(el => el.scrollWidth - el.clientWidth)).toBeLessThanOrEqual(1);
await page.screenshot({ path: testInfo.outputPath('knowledge-ready.png') });
await page.getByRole('button', { name: '我的要求', exact: true }).click();
await page.getByRole('tab', { name: '我的要求', exact: true }).click();
const preview = page.getByRole('region', { name: '草稿预览', exact: true });
await preview.getByRole('button', { name: '保存并重新试用', exact: true }).click();
await expect(preview.getByText('当前试用 · 修订 3')).toBeVisible();
@@ -225,10 +253,17 @@ test('personal cloud Agent creation, draft save and leave protection in Electron
await page.getByTestId('ai-module-option-cloud_agents').click();
await expect(page.getByTestId('cloud-agent-editor')).toBeVisible();
await expect(page.getByLabel('特别要求')).toHaveValue('使用简洁自然的中文。先理解我的目的,再协助梳理结构。补充具体例子。');
await page.getByRole('button', { name: '高级设置', exact: true }).click();
await page.getByRole('tab', { name: '高级设置', exact: true }).click();
await page.getByRole('button', { name: '限制', exact: true }).click();
await page.getByLabel('每次任务上限(词元点数)').fill('2.50');
await page.getByLabel('每日上限(词元点数)').fill('10.00');
await advancedTab.press('ArrowLeft');
await expect(requirementsTab).toBeFocused();
await expect(requirementsTab).toHaveAttribute('aria-selected', 'true');
await expect(page.getByLabel('每日上限(词元点数)')).toBeHidden();
await requirementsTab.press('ArrowRight');
await expect(page.getByRole('button', { name: '限制', exact: true })).toHaveAttribute('aria-current', 'page');
await expect(page.getByLabel('每日上限(词元点数)')).toHaveValue('10.00');
await page.getByRole('button', { name: '保存费用上限' }).click();
await expect(page.getByRole('button', { name: '保存费用上限' })).toBeDisabled();
await page.getByRole('button', { name: '使用与分享', exact: true }).click();

View File

@@ -308,6 +308,51 @@ it('keeps unsent preview text when configuration changes and waits before switch
});
it('switches peer editor tabs while retaining the advanced category and unfinished form inputs', async () => {
api.list.mockResolvedValue({ agents: [{ ...draft, configuration: { ...EMPTY_CLOUD_CONFIGURATION, model: 'test-model' } }], next_cursor: null });
open();
fireEvent.click(await screen.findByRole('button', { name: /写作搭档/ }));
await waitFor(() => expect(screen.getByLabelText('消息')).toBeEnabled());
const requirements = screen.getByRole('tab', { name: '我的要求', exact: true });
const advanced = screen.getByRole('tab', { name: '高级设置', exact: true });
expect(requirements).toHaveAttribute('aria-selected', 'true');
expect(advanced).toHaveAttribute('aria-selected', 'false');
expect(screen.getByRole('tabpanel', { name: '我的要求' })).toBeVisible();
expect(screen.queryByRole('navigation', { name: '配置分类' })).not.toBeInTheDocument();
const instructions = screen.getByLabelText('特别要求');
const preview = screen.getByLabelText('消息');
fireEvent.change(instructions, { target: { value: '没有保存的要求' } });
fireEvent.change(preview, { target: { value: '没有发送的问题' } });
fireEvent.mouseDown(advanced, { button: 0, ctrlKey: false });
expect(advanced).toHaveAttribute('aria-selected', 'true');
expect(requirements).toHaveAttribute('aria-selected', 'false');
expect(screen.getByRole('tabpanel', { name: '高级设置' })).toBeVisible();
expect(instructions).not.toBeVisible();
expect(screen.getByRole('button', { name: '能力', exact: true })).toHaveAttribute('aria-current', 'page');
fireEvent.click(screen.getByRole('button', { name: '限制', exact: true }));
const budgetInput = screen.getByLabelText('每日上限(词元点数)');
await waitFor(() => expect(budgetInput).toBeEnabled());
fireEvent.change(budgetInput, { target: { value: '12.50' } });
fireEvent.mouseDown(advanced, { button: 0, ctrlKey: false });
expect(screen.getByRole('button', { name: '限制', exact: true })).toHaveAttribute('aria-current', 'page');
expect(budgetInput).toBeVisible();
fireEvent.mouseDown(requirements, { button: 0, ctrlKey: false });
expect(screen.queryByRole('navigation', { name: '配置分类' })).not.toBeInTheDocument();
expect(budgetInput).not.toBeVisible();
expect(screen.getByLabelText('特别要求')).toBe(instructions);
expect(instructions).toHaveValue('没有保存的要求');
fireEvent.mouseDown(advanced, { button: 0, ctrlKey: false });
expect(screen.getByRole('button', { name: '限制', exact: true })).toHaveAttribute('aria-current', 'page');
expect(screen.getByLabelText('每日上限(词元点数)')).toBe(budgetInput);
expect(budgetInput).toHaveValue(12.5);
expect(screen.getByLabelText('消息')).toBe(preview);
expect(preview).toHaveValue('没有发送的问题');
expect(api.save).not.toHaveBeenCalled();
expect(api.call.mock.calls.some(([operation]) => ['saveBudget', 'preview', 'submit'].includes(operation))).toBe(false);
});
it('keeps preview text across mode switches and saves a budget independently of the draft', async () => {
const configured = { ...draft, configuration: { ...EMPTY_CLOUD_CONFIGURATION, model: 'test-model' } };
api.list.mockResolvedValue({ agents: [configured], next_cursor: null });
@@ -322,13 +367,13 @@ it('keeps preview text across mode switches and saves a budget independently of
fireEvent.click(screen.getByRole('button', { name: '编辑', exact: true }));
expect(screen.getByLabelText('消息')).toHaveValue('待发送的问题');
expect(screen.getByLabelText('特别要求')).toHaveValue('未保存的指令');
fireEvent.click(screen.getByRole('button', { name: '高级设置' }));
fireEvent.mouseDown(screen.getByRole('tab', { name: '高级设置' }), { button: 0, ctrlKey: false });
fireEvent.click(screen.getByRole('button', { name: '限制', exact: true }));
fireEvent.change(screen.getByLabelText('每日上限(词元点数)'), { target: { value: '12' } });
fireEvent.click(screen.getByRole('button', { name: '保存费用上限' }));
await waitFor(() => expect(api.call).toHaveBeenCalledWith('saveBudget', expect.objectContaining({ daily_limit_points: '12' })));
expect(api.save).not.toHaveBeenCalled();
fireEvent.click(screen.getByRole('button', { name: '我的要求', exact: true }));
fireEvent.mouseDown(screen.getByRole('tab', { name: '我的要求', exact: true }), { button: 0, ctrlKey: false });
expect(screen.getByLabelText('特别要求')).toHaveValue('未保存的指令');
expect(screen.getByLabelText('消息')).toHaveValue('待发送的问题');
});
@@ -343,7 +388,7 @@ it('keeps an existing preview when the saved draft clears its model selection',
await waitFor(() => expect(screen.getByLabelText('消息')).toBeEnabled());
const prompt = screen.getByLabelText('消息');
fireEvent.change(prompt, { target: { value: '还没有发送' } });
fireEvent.click(screen.getByRole('button', { name: '高级设置' }));
fireEvent.mouseDown(screen.getByRole('tab', { name: '高级设置' }), { button: 0, ctrlKey: false });
fireEvent.click(screen.getByRole('button', { name: '能力', exact: true }));
fireEvent.change(screen.getByLabelText('模型'), { target: { value: '' } });
fireEvent.click(screen.getByRole('button', { name: '保存草稿' }));
@@ -364,11 +409,14 @@ it('searches capabilities while retaining existing selections outside the result
api.save.mockImplementation(async (_slug, input) => ({ ...configured, ...input, draft_revision: 2 }));
open();
fireEvent.click(await screen.findByRole('button', { name: /写作搭档/ }));
fireEvent.click(screen.getByRole('button', { name: '高级设置' }));
fireEvent.mouseDown(screen.getByRole('tab', { name: '高级设置' }), { button: 0, ctrlKey: false });
fireEvent.click(screen.getByRole('button', { name: '能力', exact: true }));
expect(await screen.findByRole('checkbox', { name: /missing-tool/ })).toBeChecked();
fireEvent.click(screen.getByRole('button', { name: '选择工具', exact: true }));
fireEvent.change(screen.getByLabelText('搜索工具'), { target: { value: '资料' } });
fireEvent.mouseDown(screen.getByRole('tab', { name: '我的要求' }), { button: 0, ctrlKey: false });
fireEvent.mouseDown(screen.getByRole('tab', { name: '高级设置' }), { button: 0, ctrlKey: false });
expect(screen.getByLabelText('搜索工具')).toHaveValue('资料');
expect(screen.queryByRole('checkbox', { name: '当前时间' })).not.toBeInTheDocument();
fireEvent.click(screen.getByRole('checkbox', { name: /资料搜索/ }));
fireEvent.click(screen.getByRole('button', { name: '完成选择' }));