fix(knowledge): separate creation management and selection
This commit is contained in:
1 parent
a589a864d7
commit
8e0e52f30e
11 files changed
+223
-112
No files matched your search
@@ -179,20 +179,50 @@ async function expectNoClipping(page: Page) {
|
||||
});
|
||||
expect(clipped).toEqual([]);
|
||||
}
|
||||
async function expectKnowledgeLayout(page: Page, width: number) {
|
||||
const layout = page.locator('.agent-knowledge-workspace');
|
||||
const upload = await layout.locator('.agent-knowledge-upload').boundingBox();
|
||||
const selection = await layout.locator('.agent-knowledge-selection').boundingBox();
|
||||
expect(upload).not.toBeNull(); expect(selection).not.toBeNull();
|
||||
if (width >= 1024) {
|
||||
expect(upload!.x + upload!.width).toBeLessThanOrEqual(selection!.x + 1);
|
||||
expect(Math.abs(upload!.y - selection!.y)).toBeLessThanOrEqual(1);
|
||||
async function expectKnowledgeLayout(page: Page) {
|
||||
const knowledge = page.getByTestId('cloud-agent-editor').getByRole('group', { name: '知识库', exact: true });
|
||||
const creation = knowledge.getByRole('region', { name: '上传自己的文件', exact: true });
|
||||
const management = knowledge.getByRole('region', { name: '查看我的知识库', exact: true });
|
||||
const selection = knowledge.getByRole('region', { name: '选择知识库', exact: true });
|
||||
await expect(creation.getByRole('button', { name: '新建知识库', exact: true })).toBeVisible();
|
||||
await expect(creation.getByRole('combobox', { name: '管理的知识库', exact: true })).toHaveCount(0);
|
||||
await expect(creation.getByRole('button', { name: '从电脑上传', exact: true })).toHaveCount(0);
|
||||
await expect(management.getByRole('combobox', { name: '管理的知识库', exact: true })).toBeVisible();
|
||||
await expect(management.getByRole('button', { name: '从电脑上传', exact: true })).toBeVisible();
|
||||
await expect(management.getByRole('button', { name: '新建知识库', exact: true })).toHaveCount(0);
|
||||
await expect(selection.getByRole('combobox', { name: '选择知识库', exact: true })).toBeVisible();
|
||||
await expect(knowledge.getByText('添加到我的知识库', { exact: true })).toHaveCount(0);
|
||||
await expect(knowledge.getByText('选择或新建自己的知识库,再从电脑上传资料。选用会加入右侧配置,保存并应用后生效。', { exact: true })).toHaveCount(0);
|
||||
const creationBounds = await creation.boundingBox();
|
||||
const managementBounds = await management.boundingBox();
|
||||
const selectionBounds = await selection.boundingBox();
|
||||
const ownedBounds = await knowledge.locator('.agent-knowledge-owned-workspace').boundingBox();
|
||||
expect(creationBounds).not.toBeNull(); expect(managementBounds).not.toBeNull(); expect(selectionBounds).not.toBeNull();
|
||||
expect(ownedBounds).not.toBeNull();
|
||||
if (ownedBounds!.width > 620) {
|
||||
expect(creationBounds!.x + creationBounds!.width).toBeLessThanOrEqual(managementBounds!.x + 1);
|
||||
expect(Math.abs(creationBounds!.y - managementBounds!.y)).toBeLessThanOrEqual(1);
|
||||
expect(selectionBounds!.y).toBeGreaterThanOrEqual(Math.max(creationBounds!.y + creationBounds!.height, managementBounds!.y + managementBounds!.height));
|
||||
expect(Math.abs(selectionBounds!.x + selectionBounds!.width - managementBounds!.x - managementBounds!.width)).toBeLessThanOrEqual(1);
|
||||
} else {
|
||||
expect(upload!.y + upload!.height).toBeLessThanOrEqual(selection!.y + 1);
|
||||
expect(Math.abs(upload!.x - selection!.x)).toBeLessThanOrEqual(1);
|
||||
expect(creationBounds!.y + creationBounds!.height).toBeLessThanOrEqual(managementBounds!.y + 1);
|
||||
expect(managementBounds!.y + managementBounds!.height).toBeLessThanOrEqual(selectionBounds!.y + 1);
|
||||
expect(Math.abs(creationBounds!.x - managementBounds!.x)).toBeLessThanOrEqual(1);
|
||||
expect(Math.abs(creationBounds!.width - managementBounds!.width)).toBeLessThanOrEqual(1);
|
||||
expect(Math.abs(creationBounds!.width - selectionBounds!.width)).toBeLessThanOrEqual(1);
|
||||
}
|
||||
expect(Math.abs(creationBounds!.x - selectionBounds!.x)).toBeLessThanOrEqual(1);
|
||||
await expectNoClipping(page);
|
||||
}
|
||||
async function screenshotKnowledge(page: Page, name: string) {
|
||||
const viewport = page.viewportSize()!;
|
||||
const knowledge = page.getByTestId('cloud-agent-editor').getByRole('group', { name: '知识库', exact: true });
|
||||
const bounds = await knowledge.boundingBox();
|
||||
// Fit this scrollable card in the viewport so screenshots show every panel.
|
||||
await page.setViewportSize({ width: viewport.width, height: Math.ceil(bounds!.height + 260) });
|
||||
await knowledge.screenshot({ path: test.info().outputPath(name), animations: 'disabled' });
|
||||
await page.setViewportSize(viewport);
|
||||
}
|
||||
|
||||
for (const width of [375, 1440]) {
|
||||
test(`multiple shared/personal choices stay draft-only and survive save/reopen at ${width}px`, async ({ page }) => {
|
||||
@@ -215,7 +245,7 @@ for (const width of [375, 1440]) {
|
||||
const management = knowledge.getByRole('combobox', { name: '管理的知识库', exact: true });
|
||||
await expect(management.locator('option[value="kb_fixturescience"], option[value="kb_fixturereading"]')).toHaveCount(0);
|
||||
await expect(knowledge.getByRole('button', { name: '从电脑上传', exact: true })).toBeDisabled();
|
||||
await expectKnowledgeLayout(page, width); await page.screenshot({ path: test.info().outputPath(`knowledge-shared-${width}.png`), animations: 'disabled' });
|
||||
await expectKnowledgeLayout(page); await screenshotKnowledge(page, `knowledge-shared-${width}.png`);
|
||||
await editor.getByRole('button', { name: '保存草稿', exact: true }).click();
|
||||
await expect(editor.getByRole('button', { name: '已保存', exact: true })).toBeVisible();
|
||||
expect((await calls(page)).filter(call => call.method === 'PATCH').map(call => (call.input?.configuration as { knowledges: string[] }).knowledges))
|
||||
@@ -223,36 +253,53 @@ for (const width of [375, 1440]) {
|
||||
await page.reload(); const reopened = await openKnowledge(page);
|
||||
await expect(reopened.knowledge.getByRole('list', { name: '已选知识库', exact: true }).getByRole('listitem')).toHaveCount(3);
|
||||
await expectNoClipping(page);
|
||||
if (width === 1440) {
|
||||
for (const intermediateWidth of [768, 1024]) {
|
||||
await page.setViewportSize({ width: intermediateWidth, height: 850 });
|
||||
await expectKnowledgeLayout(page);
|
||||
await screenshotKnowledge(page, `knowledge-shared-${intermediateWidth}.png`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test(`own library creation and explicit upload process a document to ready at ${width}px`, async ({ page }) => {
|
||||
test(`own library browsing and creation stay unbound while computer upload processes a document at ${width}px`, async ({ page }) => {
|
||||
await page.setViewportSize({ width, height: 850 }); await installFixture(page); await page.goto(baseUrl);
|
||||
const { editor, knowledge } = await openKnowledge(page);
|
||||
await knowledge.getByRole('combobox', { name: '选择知识库', exact: true }).selectOption('kb_fixturescience');
|
||||
const selection = knowledge.getByRole('region', { name: '选择知识库', exact: true });
|
||||
const choose = selection.getByRole('combobox', { name: '选择知识库', exact: true });
|
||||
const selected = selection.getByRole('list', { name: '已选知识库', exact: true });
|
||||
await choose.selectOption('kb_fixturescience');
|
||||
await expect(knowledge.getByRole('heading', { name: '上传自己的文件', exact: true })).toBeVisible();
|
||||
expect((await calls(page)).filter(call => call.path.endsWith('/knowledge/pick') || ['createKnowledge', 'processKnowledge'].includes(String(call.input?.operation)))).toEqual([]);
|
||||
const upload = knowledge.getByRole('button', { name: '从电脑上传', exact: true });
|
||||
const create = knowledge.getByRole('button', { name: '新建知识库', exact: true });
|
||||
const creation = knowledge.getByRole('region', { name: '上传自己的文件', exact: true });
|
||||
const management = knowledge.getByRole('region', { name: '查看我的知识库', exact: true });
|
||||
const manager = management.getByRole('combobox', { name: '管理的知识库', exact: true });
|
||||
const upload = management.getByRole('button', { name: '从电脑上传', exact: true });
|
||||
const create = creation.getByRole('button', { name: '新建知识库', exact: true });
|
||||
await expect(upload).toBeDisabled();
|
||||
const uploadBounds = await upload.boundingBox();
|
||||
const createBounds = await create.boundingBox();
|
||||
expect(uploadBounds).not.toBeNull(); expect(createBounds).not.toBeNull();
|
||||
expect(createBounds!.y).toBeGreaterThan(uploadBounds!.y + uploadBounds!.height);
|
||||
await create.click();
|
||||
await knowledge.getByRole('textbox', { name: '知识库名称', exact: true }).fill('我的春天资料');
|
||||
await knowledge.getByRole('combobox', { name: '向量模型', exact: true }).selectOption('fixture-embedding');
|
||||
await knowledge.getByRole('button', { name: '创建并选用', exact: true }).click();
|
||||
await expect(knowledge.getByRole('combobox', { name: '管理的知识库', exact: true })).toHaveValue('kb_fixturecreated');
|
||||
await expect(knowledge.getByRole('list', { name: '已选知识库', exact: true })).toContainText('我的春天资料');
|
||||
await expectKnowledgeLayout(page);
|
||||
await manager.selectOption('kb_fixturepersonal');
|
||||
await expect(upload).toBeEnabled();
|
||||
const selectedUploadBounds = await upload.boundingBox();
|
||||
const selectedCreateBounds = await create.boundingBox();
|
||||
expect(selectedUploadBounds).not.toBeNull(); expect(selectedCreateBounds).not.toBeNull();
|
||||
expect(selectedCreateBounds!.y).toBeGreaterThan(selectedUploadBounds!.y + selectedUploadBounds!.height);
|
||||
await expect(selected.getByRole('listitem')).toHaveCount(1);
|
||||
await expect(selected).not.toContainText('我的观察记录');
|
||||
await manager.selectOption('');
|
||||
await expect(upload).toBeDisabled();
|
||||
await create.click();
|
||||
await creation.getByRole('textbox', { name: '知识库名称', exact: true }).fill('我的春天资料');
|
||||
await creation.getByRole('combobox', { name: '向量模型', exact: true }).selectOption('fixture-embedding');
|
||||
await expectKnowledgeLayout(page);
|
||||
await creation.getByRole('button', { name: '创建知识库', exact: true }).click();
|
||||
await expect(manager).toHaveValue('kb_fixturecreated');
|
||||
await expect(selected.getByRole('listitem')).toHaveCount(1);
|
||||
await expect(selected).not.toContainText('我的春天资料');
|
||||
await expect(upload).toBeEnabled();
|
||||
await manager.selectOption('kb_fixturepersonal');
|
||||
await manager.selectOption('kb_fixturecreated');
|
||||
await expect(selected.getByRole('listitem')).toHaveCount(1);
|
||||
await expect(knowledge.getByRole('button', { name: '从聊天选择文件', exact: true })).toHaveCount(0);
|
||||
expect((await calls(page)).filter(call => call.path.endsWith('/knowledge/pick') || call.input?.operation === 'processKnowledge')).toEqual([]);
|
||||
await knowledge.getByRole('button', { name: '从电脑上传', exact: true }).click();
|
||||
const document = knowledge.getByRole('article', { name: '春天观察记录.md', exact: true });
|
||||
await upload.click();
|
||||
const document = management.getByRole('article', { name: '春天观察记录.md', exact: true });
|
||||
await expect(document.getByText('等待处理', { exact: true })).toBeVisible();
|
||||
const mutations = (await calls(page)).filter(call => call.path.endsWith('/knowledge/pick') || call.input?.operation === 'processKnowledge');
|
||||
expect(mutations).toHaveLength(2);
|
||||
@@ -265,8 +312,12 @@ for (const width of [375, 1440]) {
|
||||
});
|
||||
await expect(document.getByText('可用于回答', { exact: true })).toBeVisible({ timeout: 12_000 });
|
||||
await expect(document.getByText('2 KB · 6 段可检索内容', { exact: true })).toBeVisible();
|
||||
await expect(selected.getByRole('listitem')).toHaveCount(1);
|
||||
await choose.selectOption('kb_fixturecreated');
|
||||
await expect(selected.getByRole('listitem')).toHaveCount(2);
|
||||
await expect(selected).toContainText('我的春天资料');
|
||||
await document.scrollIntoViewIfNeeded();
|
||||
await expectKnowledgeLayout(page, width); await page.screenshot({ path: test.info().outputPath(`knowledge-upload-ready-${width}.png`), animations: 'disabled' });
|
||||
await expectKnowledgeLayout(page); await screenshotKnowledge(page, `knowledge-upload-ready-${width}.png`);
|
||||
// Document mutations never implicitly save the Agent draft.
|
||||
expect((await calls(page)).filter(call => call.method === 'PATCH')).toEqual([]);
|
||||
await editor.getByRole('button', { name: '保存草稿', exact: true }).click();
|
||||
@@ -295,7 +346,8 @@ test('cancelled and failed uploads preserve shared choices and the personal draf
|
||||
await expect(knowledge.getByRole('alert')).toContainText('上传服务暂不可用');
|
||||
await expect(knowledge.getByRole('combobox', { name: '管理的知识库', exact: true })).toHaveValue('kb_fixturepersonal');
|
||||
await expect(knowledge.getByRole('list', { name: '已选知识库', exact: true })).toContainText('科学知识');
|
||||
await expect(knowledge.getByRole('list', { name: '已选知识库', exact: true })).toContainText('我的观察记录');
|
||||
await expect(knowledge.getByRole('list', { name: '已选知识库', exact: true })).not.toContainText('我的观察记录');
|
||||
await expect(knowledge.getByRole('list', { name: '已选知识库', exact: true }).getByRole('listitem')).toHaveCount(1);
|
||||
// An uncertain upload response keeps its retry attached to the same library.
|
||||
await expect(knowledge.getByRole('combobox', { name: '管理的知识库', exact: true })).toBeDisabled();
|
||||
await expect(knowledge.getByRole('button', { name: '新建知识库', exact: true })).toBeDisabled();
|
||||
|
||||
Reference in new issue
Block a user