* feat(web): boot past failed optional client plugins The Web client boot audit now follows Host startup strictness. An inactive entry on the global required list (module system, Session transport, renderer, application frame, Session view, and sidebar) still rejects startup and the report marks the required entries. Other inactive entries produce one console warning and the application mounts without them. The boot page no longer draws a failed entry before the audit decides. * fix(web): audit boot entries whose creation rejects and name activation errors ClientEntries.start() now logs a row whose Loader creation rejects, such as a module that exports no plugin, and leaves it inactive for the boot audit, as the Host Loader group does. The audit awaits only failed fibers to report their recorded activation error. Notes, READMEs, and the Web client subsystem page describe the browser boot audit; tests cover invalid exports, carrier presentation of optional failures, and required names absent from the boot graph. * test(web): fail test carriers and e2e on inactive client entries The product boot only warns about inactive entries outside its required list, but tests must still surface every plugin that fails. TestClient and createClientTest now require every roster entry to activate unless a case passes allowInactiveEntries. The watchConsole tripwire, the real-host smoke, and the assembled jsdom boot treat a web boot warning as a failure with no opt-out. Docs: the Web README names Session control, notes that an entry without a fiber is reported as an import failure like the Host audit's "failed to import", and the startup strictness note lists the browser tests.
6.1 KiB
apps/web 浏览器 e2e
English | 中文
这些测试在进程内启动真实的 web 组合,并用真实浏览器通过真实 HTTP 驱动它。Chromium 运行整个 lane;模型与推理强度选择场景 还在 WebKit 中运行,以覆盖原生鼠标焦点行为。会话回放恢复还在 WebKit 中运行,共用 fresh-round-trip 的录制和预期输出,不改写这些文件。该用例覆盖输出中刷新、完成后刷新和重新打开 Session。该 lane 的运行机制——模式、fixture(测试前置数据)、golden,以及与 dsh web 之间刻意保留的组合差异——记录在 scaffold.ts 和 浏览器 e2e Agent Note 中。
安装工作区依赖后,在仓库根目录安装浏览器及其系统依赖:
pnpm --filter @deepseek-ai/dsh-web-frontend exec playwright install --with-deps chromium webkit
在 Linux 上,--with-deps 会通过系统包管理器安装依赖。持久化 CI VM 必须通过镜像维护提供这些依赖,CI 只安装浏览器程序,遵循故障切换手册的要求。
普通场景以没有已登记 Workspace 或 Session、但持久化标记记录默认 Workspace 已被删除的状态启动,使显式文件夹选择场景自行决定 cwd。launchWebScaffold({ firstUse: true }) 保留初始化资格,供启动场景使用。
当天消息的 golden 使用共享的 WEB_FIXTURE_TIME:预置会话将它传为 createdAt,并通过 pinBrowserClock 固定浏览器日期;提交实时消息的场景还使用 pinHostClock,在清理后恢复。固定后的时钟随真实耗时前进,保留原生定时器,因此跨午夜不会改变场景的日期标签。
每个场景都要求整个客户端组合全部激活。产品启动只对必需名单外的未激活 entry 告警,但 watchConsole 绊线、真实 Host 冒烟与组装 jsdom 启动把 web boot: warning 视为失败。没有任何场景选项放宽这一点:产品组合中出现未激活插件就是需要修复的缺陷。
完成状态观察
依赖状态的用例使用 Workspace、接纳、附件和模型流屏障,区分可见中间状态与已完成操作。模型选择器的持久化断言等待默认设置保存完成,不以菜单关闭作为完成信号。详情关闭等待框架过渡结束;归档验证为 seed Session 设置显式标题,并跨重载跟踪该身份。CI 测试可靠性工作流负责这些同步规则。
空闲提交交接对 Host 帧和浏览器中的消息归位的等待使用 scaffold 的 30 秒 Turn 完成预算。Vitest 负责 scaffold 清理,使 replay 消耗检查错误不会覆盖场景中失败的断言。
插件管理器和 HMR 生命周期场景中的开关为 Host 的 profile 写入与 store 随后的 inventory 读取预留 PLUGIN_TOGGLE_SETTLE_MS(10 秒),这两步完成后才会重新发布 aria-checked;链路的实测值记录在该常量的 JSDoc 中。
显式滚动使用 support.ts 的 scrollIntoView:旧元素脱离 DOM 时重新解析 locator,并在同一个浏览器任务中检查连接状态、执行原生滚动。各场景保留滚动后的可见性与几何断言。
问答输入框的缩放断言等待 CSS 滚动时间线更新,使溢出、裁剪遮罩与展开按钮的可见性一致。
侧栏窗格关闭后的快照在捕获前将指针移出控件,并等待悬停提示关闭。键盘焦点保持在窗格上。
同源窗口终端用例等待 UI 触发的 Host 关闭操作完成后,再检查进程终止。它还检查第一个窗口的进程、保存的绑定以及重载后的布局。
这些是 Host 面的测试
它们在根 tsconfig.host.json 中做类型检查,而不在 Client aggregate 中,因为它们直接读取 Host 服务:ctx.connection、Host 侧 SessionStore 与 ctx.sessionProjectionCache。运行时驱动浏览器并不使一个文件成为 Client 程序的一部分——两个 face 在相同的键上以不同服务合并 Cordis Context,因此单个程序无法同时看见两者。把这些文件挪进 Client aggregate 会让每一处 Host 服务访问都无法编译。
新增场景要在同一次改动里登记到两份工程清单:根 tsconfig.host.json 的 include,以及 Client aggregate apps/web/tsconfig.json 的 exclude。该工程包含整个 tests 目录,漏登记 exclude 的文件会按 Client 代码编译,pnpm run typecheck 的 Client compiler 关卡会一直以 Host 服务错误失败,直到它被列入。
不要在此 import @deepseek-ai/dsh-client-*
import 一个 Client 包——无论值还是类型——都会把它的 TypeScript 工程及其引用的工程拉进 Host 构建图。生成的 Remote 声明在包编译之前就绪,但这并不使 Host 与 Client 的 Cordis Context 声明兼容。保留这些测试的 Host face 归属,只使用下文明确的 built-client harness 例外。
当某个场景需要 Client 持有的常量或纯函数时,改为在此处镜像一份,并紧挨着一条注释掉的 import 点明源模块。这样漂移会表现为选择器未命中或镜像值陈旧——是响亮的失败,绝不会是静默通过。scaffold.ts 按此规则镜像 welcome-notice 的 namespace、确认字段、版本和被断言的中文文案。
built-client harness 是例外。assembled-boot.ts import AppWebEntry、boot manifest(元数据清单)类型与 RemoteMock;assembled-remote.ts import Client test runtime 的默认响应与 RemoteMock。这些包是显式的工程引用,用于通过测试持有的 carrier 启动真实 shell。chat 场景仍在 support.ts 中镜像 conversationContextKey,而不 import 其 Client owner。
没有任何机制强制这条规则;靠 review 守住它。