diff --git a/docs/development/release-preparation-0.15.8.md b/docs/development/release-preparation-0.15.8.md index 63879d72..afbc4a94 100644 --- a/docs/development/release-preparation-0.15.8.md +++ b/docs/development/release-preparation-0.15.8.md @@ -39,3 +39,13 @@ MainImageToolSession、ImageGenerationService、真实 SQLite 会话协作。 中英文 FEATURES、Desktop 与 Agent 双语说明必须与上述实现边界一致。 只暂存必要发布文件,保留工作区用户文件;双远端核验候选和标签一致。 公开验证包括六平台 Desktop、三平台 Agent 签名目录、GitHub/OSS 同步及 Latest 分离。 + +## 首轮 CI 修正 + +`20317c2`:Agent CI `36960575058` 成功;Desktop `36960575157` 为 +5620 通过、59 跳过、4 失败,构建未执行。 +Obsidian 专项 IPC fixture 未安装浏览器服务,显式关闭无关浏览器能力; +MCP 列表断言纳入新增图像卡片的数量和名称;覆盖层原生点击先将控件居中, +避免磨砂顶栏覆盖 `nearest` 保留在顶部的控件,并补充命中遮挡诊断。 +保留所有业务、覆盖层和原生交互断言,不改变产品默认值、关闭沙箱或跳过测试。 +这些修正由新候选 CI 验证。 diff --git a/src/main/ipc.test.ts b/src/main/ipc.test.ts index 884db0c6..520d8909 100644 --- a/src/main/ipc.test.ts +++ b/src/main/ipc.test.ts @@ -9319,6 +9319,8 @@ describe('registerIpcHandlers agent terminal state', () => { { isAvailable: () => true, encrypt: (value) => Buffer.from(value), decrypt: (value) => value.toString() } ) const settings = { vaultPath: join(root, 'Saved Vault') } + // This harness exercises Obsidian grants and does not install a browser service. + await capabilities.setBuiltinMcpServerEnabled('builtin-browser', false) await capabilities.updateObsidianSettings(settings) if (enabled) await capabilities.setBuiltinMcpServerEnabled('obsidian', true) if (!assigned) await capabilities.setBuiltinMcpServerAssignments('obsidian', ['continue']) diff --git a/src/renderer/src/SettingsPanel.test.tsx b/src/renderer/src/SettingsPanel.test.tsx index b5924630..9585f656 100644 --- a/src/renderer/src/SettingsPanel.test.tsx +++ b/src/renderer/src/SettingsPanel.test.tsx @@ -6042,10 +6042,14 @@ describe('SettingsPanel runtime files', () => { screen.getAllByRole('button', { name: /^(?:展开|收起)服务器 /u }) - ).toHaveLength(builtinMcpServers.length) - for (const server of builtinMcpServers) { + ).toHaveLength(builtinMcpServers.length + 1) + const serverNames = [ + ...builtinMcpServers.map(server => server.name), + '图片生成与编辑' + ] + for (const serverName of serverNames) { expect(screen.getByRole('button', { - name: name => name === `展开服务器 ${server.name}` || name === `收起服务器 ${server.name}` + name: name => name === `展开服务器 ${serverName}` || name === `收起服务器 ${serverName}` })).toBeInTheDocument() } expect( diff --git a/tests/support/overlay-paths-main.ts b/tests/support/overlay-paths-main.ts index c9de5e57..3cd4e5ee 100644 --- a/tests/support/overlay-paths-main.ts +++ b/tests/support/overlay-paths-main.ts @@ -71,10 +71,11 @@ app.whenReady().then(async () => { } const click = async (selector: string): Promise => { await wait(`!!document.querySelector(${JSON.stringify(selector)})`) - await js(`document.querySelector(${JSON.stringify(selector)}).scrollIntoView({block:'nearest'})`) + // The frosted header overlays the top of the chat viewport; nearest may leave a control underneath it. + await js(`document.querySelector(${JSON.stringify(selector)}).scrollIntoView({block:'center'})`) await settle() - const p = await js<{ x: number; y: number; hit: boolean }>(`(()=>{const e=document.querySelector(${JSON.stringify(selector)}),r=e.getBoundingClientRect(),x=Math.round(r.x+r.width/2),y=Math.round(r.y+r.height/2);return {x,y,hit:e.contains(document.elementFromPoint(x,y))}})()`) - assert(p.hit, `Occluded ${selector}`) + const p = await js<{ x: number; y: number; hit: boolean; cover?: string }>(`(()=>{const e=document.querySelector(${JSON.stringify(selector)}),r=e.getBoundingClientRect(),x=Math.round(r.x+r.width/2),y=Math.round(r.y+r.height/2),cover=document.elementFromPoint(x,y);return {x,y,hit:e.contains(cover),cover:cover?.outerHTML.slice(0,500)}})()`) + assert(p.hit, `Occluded ${selector}: ${JSON.stringify(p)}`) win.focus() win.webContents.sendInputEvent({ type: 'mouseDown', x: p.x, y: p.y, button: 'left', clickCount: 1 }) win.webContents.sendInputEvent({ type: 'mouseUp', x: p.x, y: p.y, button: 'left', clickCount: 1 })