From 65a21390debe0dd04871417a363a9d87a29339e6 Mon Sep 17 00:00:00 2001 From: mesalogo Date: Mon, 28 Sep 2026 04:22:13 +0800 Subject: [PATCH] test: retain created knowledge bindings across polling Model persisted library state in the external-binding fixture instead of returning pre-creation data to background refreshes. Keep all selected and excluded library assertions, without assuming the last snapshot request belongs to the new library. Windows App: 300 passed; complete frozen Linux suite: 5371 passed, 51 skipped. Typecheck, lint and bilingual notes validation passed. --- docs/development/release-preparation-0.15.0.md | 10 ++++++++++ src/renderer/src/App.test.tsx | 16 +++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/development/release-preparation-0.15.0.md b/docs/development/release-preparation-0.15.0.md index 7f41a4df..31ff3524 100644 --- a/docs/development/release-preparation-0.15.0.md +++ b/docs/development/release-preparation-0.15.0.md @@ -185,6 +185,16 @@ Agent 产品源码及 Runtime 锁未因这四项改变,Agent Windows 原生 Runtime 聚焦用例、类型检查和 lint 通过。 提交仅追加本段记录;仍须等待修正候选的主分支 CI 和生产构建。 +`706726b` 的桌面 [CI 36345672365](https://github.com/mesalogo/goodbuddy/actions/runs/36345672365) +已通过上述采集与 Runtime 用例,但另一个外部知识库测试失败: +5,370 通过、51 跳过、1 失败,生产构建未执行。 +该 fixture 只在查询新库 ID 时返回包含已创建库的快照,普通轮询会返回创建前数据; +同时错误地要求最后一次请求必须属于新库,忽略后台轮询。 +改为模拟已持久化的库列表,等待新库请求发生,保留原库与新增库选中、被排除库未选中的 +全部界面断言,不修改产品代码。Windows 完整 App 300 项通过,类型、lint 和说明校验通过。 +冻结 tree `42a92450ad7d9ebc50167c7946bff53cff2889e6` 的 Linux 全量为 +**5,371 通过、51 跳过、0 失败**,耗时 748.67 秒。 + ## 数据、兼容与验收边界 Desktop schema 48 新增魔法笔记会话来源元数据。升级前应备份完整用户数据, diff --git a/src/renderer/src/App.test.tsx b/src/renderer/src/App.test.tsx index ea37b17d..8759d241 100644 --- a/src/renderer/src/App.test.tsx +++ b/src/renderer/src/App.test.tsx @@ -7391,13 +7391,18 @@ describe("App", () => { const created = { ...existing, id: '33333333-3333-4333-8333-333333333333', name: 'Remote handbook', external: { knowledgeBaseId: '33333333-3333-4333-8333-333333333333', instanceId: instance.id, provider: 'dify' as const, remoteKnowledgeBaseId: 'remote-1', remoteName: 'Remote handbook', commonConfig: { resultLimit: 6, requestTimeoutMs: 15000, maxSnippetCharacters: 4000 }, providerConfig: { provider: 'dify' as const, useDatasetDefaults: true as const }, lastVerifiedAt: '2026-09-12' } }; const initial = { libraries: [existing, excluded], selectedLibraryId: existing.id, sources: [], documents: [], graphNodes: [], graphRelations: [], evidence: [] }; const updated = { ...initial, libraries: [...initial.libraries, created], selectedLibraryId: created.id }; - vi.mocked(api.knowledge.getSnapshot).mockImplementation(async (libraryId) => - libraryId === created.id ? updated : initial - ); + let persistedSnapshot = initial; + vi.mocked(api.knowledge.getSnapshot).mockImplementation(async (libraryId) => ({ + ...persistedSnapshot, + selectedLibraryId: libraryId ?? persistedSnapshot.selectedLibraryId, + })); vi.mocked(api.knowledge.externalInstancesList).mockResolvedValue([instance]); vi.mocked(api.knowledge.externalCatalogList).mockResolvedValueOnce({ items: [{ id: 'remote-1', name: 'Remote handbook' }], hasMore: false }); vi.mocked(api.knowledge.externalCatalogGet).mockResolvedValueOnce({ id: 'remote-1', name: 'Remote handbook' }); - vi.mocked(api.knowledge.externalBindingsCreate).mockResolvedValueOnce(updated); + vi.mocked(api.knowledge.externalBindingsCreate).mockImplementationOnce(async () => { + persistedSnapshot = updated; + return updated; + }); vi.mocked(api.conversations.list).mockResolvedValueOnce([{ id: '44444444-4444-4444-8444-444444444444', projectId, title: 'External scope test', updatedAt: 200, messages: [], knowledgeLibraryIds: [existing.id] }]); render(); await screen.findByRole('button', { name: /^External scope test/u }); @@ -7412,7 +7417,8 @@ describe("App", () => { await waitFor(() => expect(screen.getByRole('button', { name: '添加知识库' })).toBeEnabled()); fireEvent.click(screen.getByRole('button', { name: '添加知识库' })); await screen.findByRole('heading', { name: 'Remote handbook' }, { timeout: 5_000 }); - await waitFor(() => expect(api.knowledge.getSnapshot).toHaveBeenLastCalledWith(created.id)); + // Polling can also refresh another selection; every snapshot must retain the created binding. + await waitFor(() => expect(api.knowledge.getSnapshot).toHaveBeenCalledWith(created.id)); fireEvent.click(screen.getByRole('button', { name: /^External scope test/u })); openComposerOptions(); fireEvent.click(await screen.findByRole('button', { name: '选择知识库,本次已启用 2 个' }));