test(web-shell): add extensions-manager visual scenario - #6997
Conversation
Add a full-page Extensions manager scenario to the web-shell visual
suite, proving a manager PAGE (not just a transcript or dialog) is
reachable in the mock-daemon harness and captured in both themes.
- Make the mocked workspace extensions scenario-driven: empty by
default (mirroring skills/settings/tools), so a scenario can seed
sample extensions via createWebShellDaemonScenario({ extensions }).
- Mock the two endpoints the manager fires on mount so the captured
page renders without a spurious error banner:
GET /workspace/extensions/operations (idle poll) and
POST /workspace/extensions/check-updates (no updates available).
- Seed three extensions (enabled/disabled, marketplace/local, with
varied capability counts) so the manager renders real cards.
|
Thanks for the PR! Template looks good ✓ Problem: The visual-preview suite was missing a full-page manager scenario — only transcripts, dialogs, and the sidebar were covered. This is a real gap: manager pages are the most likely to regress silently on layout or data-shape changes. The PR addresses it by adding the first manager-page scenario (Extensions manager). Not a bug fix — test-infrastructure hardening with clear motivation. Direction: Aligned. Extends the visual-preview suite (#6880, #6963, #6964). The mock daemon needed two new routes ( Size: Not applicable — both files are under Approach: Scope feels right. Two files, focused changes. The mock daemon refactor (moving extensions data into the scenario object instead of computing it at request time) is a clean simplification that makes the data scenario-driven like skills/settings/tools. No scope creep. Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ 问题:视觉预览套件缺少整页管理器场景——目前只覆盖了对话记录、弹窗和侧边栏。这是一个真实缺口:管理器页面最容易在布局或数据结构变更中悄悄回归。本 PR 新增第一个管理器页面场景(扩展管理器)来解决这个问题。不是 bug 修复——而是有明确动机的测试基础设施加固。 方向:对齐。延续视觉预览套件(#6880、#6963、#6964)。mock daemon 需要两个新路由( 规模:不适用——两个文件均位于 方案:范围合理。两个文件,改动聚焦。mock daemon 重构(将扩展数据移入场景对象而非在请求时计算)是一次简洁的简化,使数据像 skills/settings/tools 一样由场景驱动。无范围蔓延。 进入代码审查 🔍 — Qwen Code · qwen3.7-max Reviewed at |
🖼️ web-shell visual previewRendered against a mock daemon (no real backend): the PR base vs this PR head Screenshots · before / afterFull-resolution recordings (.webm) are attached to the workflow run. — Qwen Code · web-shell visuals |
Code ReviewClean diff — follows the established patterns in the mock daemon and visual suite.
No correctness bugs, no security issues, no AGENTS.md violations. Code is straightforward and minimal. Test Results (CI)No local All 21 visual scenarios pass in both themes, including the new extensions-manager pair. No regression in existing scenarios. Additional CI: Test (ubuntu-latest) passed (10m38s), web-shell E2E Smoke passed (4m50s). 中文说明代码审查干净的 diff——遵循 mock daemon 和视觉套件中的既有模式。
无正确性 bug、无安全问题、无 AGENTS.md 违规。代码简洁且最小化。 测试结果(CI)本地无 所有 21 个视觉场景在两种主题下均通过,包括新增的扩展管理器场景对。现有场景无回归。 其他 CI:Test (ubuntu-latest) 通过(10m38s),web-shell E2E Smoke 通过(4m50s)。 — Qwen Code · qwen3.7-max Reviewed at |
|
Confidence: 5/5 — clean across every stage, no reservations. This is a textbook test-infrastructure PR: it fills a real gap in the visual suite (no manager-page capture existed), follows every established pattern in the mock daemon and screenshots spec, and the CI confirms all 21 scenarios pass in both themes. The scope is minimal — two e2e files, no production code — and the one shared edit (adding 中文说明信心度:5/5 — 各阶段均干净,无保留意见。 这是一个教科书般的测试基础设施 PR:填补了视觉套件中的真实缺口(此前没有管理器页面的截图捕获),遵循 mock daemon 和截图规范中的每一个既有模式,CI 确认所有 21 个场景在两种主题下均通过。范围最小化——两个 e2e 文件,无生产代码——唯一的共享改动(在场景类型中添加 — Qwen Code · qwen3.7-max Reviewed at |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline. Not reviewed: chunk 1 — no agent reported covering these; nobody read them.
— qwen3.7-max via Qwen Code /review
Address review feedback on the extensions-manager visual scenario:
- Gate the scenario on the page heading (a stable `heading` role) and
assert the seeded card via its `button` role, instead of a bare
getByText('Context7') that a card-heading refactor or a toast/sidebar
match could break.
- Wire the /operations and /check-updates mock routes through the
scenario (new extensionOperations / extensionUpdateCheck fields with
idle defaults) so a future test can preview an in-flight install or a
pending update, matching how every other workspace route delegates to
the scenario rather than returning a hardcoded inline object.
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline.
— qwen3.7-max via Qwen Code /review
Address review: inline the trivial `workspaceExtensions()` pass-through at its one call site (`await json(route, scenario.extensions)`) and drop the function. This matches how the other full-object scenario fields (providers/skills/settings) are served directly, rather than the synthesizing helpers (workspaceTools/workspaceMcp) that build a fresh object each call.
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline. Not reviewed: chunk 1 — no agent reported covering these; nobody read them.
— qwen3.7-max via Qwen Code /review
Address review: the scenario seeds a disabled/local extension but only asserted the enabled one, so a regression that hides `isActive: false` or local-source rows would pass here and only differ in the (visually reviewed) screenshot. Also assert the "Local Notes" card is visible.
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Not reviewed: chunk 1 — no agent reported covering these; nobody read them.
— qwen3.7-max via Qwen Code /review
|
@qwen-code /triage |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
yiliang114
left a comment
There was a problem hiding this comment.
Solid addition. The synthesizer → pass-through conversion for extensions aligns with how providers/skills/settings already work, and the two new mock endpoints (/operations, /check-updates) close the gap that would have painted an error banner on the capture.
Good call on the structural locators (heading + button roles) and asserting both the enabled marketplace card and the disabled local-source card — that catches regressions that would otherwise only show up as a pixel diff.
One non-blocking note: the three capabilities objects in the seed share ~80% of their shape. Could be extracted into a small factory (e.g. mockCapabilities({ mcpServerCount: 1, hasSettings: true })) if more extension scenarios land later. Not worth blocking on — matches how other scenarios inline their fixtures.
LGTM.



What this PR does
Adds a full-page Extensions manager scenario to the web-shell visual suite. The scenario opens the
/extensionsfull-page manager in the mock-daemon harness, seeds a few extensions, and captures it in both dark and light themes — proving a manager page (not just a transcript or dialog) is reachable and renderable in the harness.To make the captured page clean, it also fills two small gaps in the mock daemon: the manager fires
GET /workspace/extensions/operationsandPOST /workspace/extensions/check-updateson mount, which the mock did not recognize, so they fell through to the (absent) real daemon and painted an error banner across the capture. The mock now serves both as idle / no-op responses, and the mocked extensions list is scenario-driven — empty by default (mirroringskills/settings/tools) so a scenario can seed sample rows without perturbing the other scenarios.Why it's needed
The visual-preview suite so far captured transcripts, dialogs, and the sidebar, but no full-page manager view — the surface most likely to regress silently on layout or data-shape changes. This adds the first manager-page scenario, so the before/after preview bot surfaces changes to the Extensions manager (cards, badges, empty/populated states) on any PR that touches it. It also hardens the mock daemon's extensions surface so future manager scenarios (MCP, tools, providers) can be added the same way.
Reviewer Test Plan
How to verify
Expected:
2 passed(dark + light). The capturedextensions-manager-<theme>.pngshows the "Manage Extensions" page with three cards (Context7 / Playwright enabled, Local Notes disabled) and no error banner.tsconfig.json, so scope atsc --noEmittoclient/e2e/**— clean.npx eslinton the two changed files — clean.npm run test:e2e:visuals):21 passed, no regression in the other scenarios (the mock's default extensions list stays empty, matchingmain).Evidence (Before & After)
New scenario — there is no "before" capture (the view did not exist). After:
The web-shell visuals bot also triggers on this PR (it touches
packages/web-shell/client/**) and will post a live preview of the same scenario as a NEW view.Tested on
Verified locally on macOS; Windows/Linux left to CI (the visuals job runs on Linux).
Environment (optional)
npm run devweb-shell dev server + Playwright (chromium), driven byplaywright.visuals.config.ts.Risk & Scope
client/e2e/). The one shared edit is the mock daemon adding a requiredextensionsfield to the scenario type — safe because the factory is the only constructor (no direct literal construction anywhere) and it defaults to an empty list, so existing scenarios are unchanged.Linked Issues
None. Follows the visual-preview suite (#6880) and the before/after engine (#6963); extends the feature-scenario set added in #6964.
中文说明
这个 PR 做了什么
为 web-shell 视觉套件新增一个整页的 扩展管理器(Extensions manager) 场景。该场景在 mock-daemon 测试环境中打开
/extensions整页管理器,注入若干扩展,并在深色与浅色两种主题下截图——证明在该测试环境中可以到达并渲染一个管理器页面(而不仅仅是对话记录或弹窗)。为了让截图干净,本 PR 还补齐了 mock daemon 的两个缺口:管理器在挂载时会请求
GET /workspace/extensions/operations和POST /workspace/extensions/check-updates,而 mock 未识别这两个路径,导致请求穿透到(并不存在的)真实 daemon 并在截图上渲染出一条错误条。现在 mock 将两者作为空闲 / 无操作响应返回;同时把 mock 的扩展列表改为由场景驱动——默认为空(与skills/settings/tools一致),使场景可以注入示例行而不影响其他场景。为什么需要它
到目前为止,视觉预览套件覆盖了对话记录、弹窗和侧边栏,但没有任何整页管理器视图——而这恰恰是最容易在布局或数据结构变更中悄悄回归的界面。本 PR 新增第一个管理器页面场景,这样 before/after 预览机器人就能在任何改动扩展管理器的 PR 上呈现其变化(卡片、徽章、空/非空状态)。它同时加固了 mock daemon 的扩展接口面,便于后续以相同方式新增管理器场景(MCP、工具、供应商)。
复现测试计划
如何验证
预期:
2 passed(深色 + 浅色)。截图extensions-manager-<theme>.png显示 "Manage Extensions" 页面,含三张卡片(Context7 / Playwright 启用,Local Notes 停用),且没有错误条。tsconfig.json排除,因此需将tsc --noEmit单独限定到client/e2e/**——通过。npx eslint——通过。npm run test:e2e:visuals):21 passed,其他场景无回归(mock 的默认扩展列表保持为空,与main一致)。证据(Before & After)
新场景——没有 "before" 截图(该视图此前不存在)。After:见上方深色 / 浅色两图。
web-shell 视觉机器人也会在本 PR 上触发(因为改动了
packages/web-shell/client/**),并会将同一场景作为 NEW 视图发布实时预览。测试平台
仅在本地 macOS 验证;Windows/Linux 交由 CI(视觉任务在 Linux 上运行)。
风险与范围
client/e2e/下)。唯一的共享改动是 mock daemon 在场景类型上新增了必填的extensions字段——安全,因为工厂函数是唯一构造入口(代码中没有任何直接的字面量构造),且默认为空列表,因此现有场景不受影响。关联 Issue
无。延续视觉预览套件(#6880)与 before/after 引擎(#6963);扩展了 #6964 新增的功能场景集合。