Parcourir la source

Align client boot import failure test with reverted Loader

turtle1999 il y a 2 semaines
Parent
commit
0e6505454e

+ 2 - 2
packages/client/web/README.i18n.yaml

@@ -2,5 +2,5 @@
 # side as of the last confirmed-consistent state. Both languages carry equal authority;
 # after editing either side, bring the other along and re-record with:
 #   pnpm run verify-translation-pairing --write packages/client/web/README.md
-README.md: 6bc0c4f241d1afb28825cadc19f89b7f54d4b637
-README.zh.md: e2d7ab81e82f1b5b1b93b95e4ed117a80f897a8e
+README.md: 7bdcec9e2a964b746cbd808497f9222e2b4150fa
+README.zh.md: a7243e52a7bababebb75a0ee9f4e22a99fa83337

+ 1 - 1
packages/client/web/README.md

@@ -35,7 +35,7 @@ Boot runs in two stages: the module stage adopts the parser-loaded bootstrap bat
 
 ### The boot page
 
-The boot page uses plain DOM and local CSS, so bundle and plugin-activation failures remain visible: it shows one spinner node whose CSS arc grows as entries activate, and reports per-entry status. The spinner and its animation phase persist until the full UI replaces the boot page. A plugin that fails import or activation is reported by name with the reason (missing service, import error, or state) instead of a blank page.
+The boot page uses plain DOM and local CSS, so bundle and plugin-activation failures remain visible: it shows one spinner node whose CSS arc grows as entries activate, and reports per-entry status. The spinner and its animation phase persist until the full UI replaces the boot page. A plugin that fails import or activation is reported by name with the reason (missing service, import failure, or state) instead of a blank page. The console contains the original import error.
 
 ### The shared module table
 

+ 1 - 1
packages/client/web/README.zh.md

@@ -35,7 +35,7 @@ kind: "package-library"
 
 ### 启动页
 
-启动页只使用原生 DOM 与本地 CSS,因此 bundle 与插件激活失败保持可见:它显示一个 spinner 节点,其 CSS 圆弧随 entry 激活而增长,并逐 entry 报告状态。spinner 及其动画相位会一直保留,直到完整 UI 替换启动页。导入或激活失败的插件会按名称报告并给出原因(缺失服务、导入错误或状态),而不是白屏。
+启动页只使用原生 DOM 与本地 CSS,因此 bundle 与插件激活失败保持可见:它显示一个 spinner 节点,其 CSS 圆弧随 entry 激活而增长,并逐 entry 报告状态。spinner 及其动画相位会一直保留,直到完整 UI 替换启动页。导入或激活失败的插件会按名称报告并给出原因(缺失服务、导入失败或状态),而不是白屏。控制台包含原始导入错误。
 
 ### 共享模块表
 

+ 2 - 2
packages/client/web/src/boot-client.ts

@@ -27,8 +27,8 @@ export interface ClientBootOptions {
 /**
  * Compose the client: `ctx.plugin(Loader)`, `loader.internal = modules`, one
  * `loader.create({ name })` per manifest row, `loader.await()`, then
- * {@link assertEntriesActive}. A row whose module cannot be imported rejects
- * `loader.create`, so that import error propagates from here as-is.
+ * {@link assertEntriesActive}. A row whose module cannot be imported is marked
+ * failed; the Loader logs its import error and the audit rejects startup.
  * @param options - context, module system, manifest, optional progress sink.
  * @returns resolves after every entry is active; rejects with the audit report otherwise.
  */

+ 9 - 5
packages/client/web/tests/boot-client.client.spec.ts

@@ -4,7 +4,7 @@ import {
   createClientModuleSystem, parseBootManifest,
   type ClientBundleRegistration, type ClientModuleLoader, type ClientModuleLoaderTarget, type WebBootEntry, type WebBootGraph,
 } from '@deepseek-ai/dsh-client-modules/client'
-import { describe, expect, it } from 'vitest'
+import { describe, expect, it, onTestFinished, vi } from 'vitest'
 import { assertEntriesActive, bootClient, type EntryStateLabel } from '../src/boot-client.ts'
 import { FIBER_STATE } from '../src/loader-status.ts'
 
@@ -77,17 +77,21 @@ describe('bootClient', () => {
     await ctx.fiber.dispose()
   })
 
-  it('surfaces the Loader import error for a row that is neither seeded nor a graph row', async () => {
+  it('reports and logs an import failure for a row that is neither seeded nor a graph row', async () => {
     const { modules } = modulesOf(graphOf(['seeded']), { seeded: { apply: () => {} } })
     const manifest = parseBootManifest(graphOf(['ghost']))
     const ctx = new Context()
+    onTestFinished(() => ctx.fiber.dispose())
+    const error = vi.spyOn(ctx.logger, 'error').mockImplementation(() => {})
+    onTestFinished(() => { error.mockRestore() })
     const sink = stateSink()
 
     await expect(bootClient({ ctx, modules, manifest, onEntryState: sink.onEntryState })).rejects.toThrow(
-      /failed to import loader entry \S+ \(ghost\): client-modules: cannot resolve/,
+      'web boot: 1 entry did not activate\nghost: import failed (see console for the import error)',
     )
-    expect(sink.states.get('ghost')).toEqual(['loading'])
-    await ctx.fiber.dispose()
+    expect(sink.states.get('ghost')).toEqual(['loading', 'failed'])
+    expect(error).toHaveBeenCalledOnce()
+    expect(error.mock.calls[0]?.[0]).toHaveProperty('message', expect.stringContaining('client-modules: cannot resolve'))
   })
 })