imccyu před 2 měsíci
rodič
revize
e874e80012

+ 1 - 0
packages/api/gateway/src/client/index.ts

@@ -119,6 +119,7 @@ class ClientRemoteService extends Service implements TypeRTClientRemote {
       listeners.push(subscription)
       return () => {
         const at = listeners.indexOf(subscription)
+        /* v8 ignore next -- listener */
         if (at >= 0) listeners.splice(at, 1)
       }
     }, `api-gateway.client.$on(${JSON.stringify(event)})`)

+ 5 - 1
packages/client/ui-settings/src/client/index.ts

@@ -25,8 +25,12 @@ export const inject = []
 
 /**
  * Provide the settings-namespace scope service.
+ *
+ * `Service` registers itself under its own name from its constructor, so the
+ * class mounts as a plugin; a second `ctx.provide` for the same name would
+ * throw.
  * @param ctx - client root context.
  */
 export function apply(ctx: ClientContext): void {
-  ctx.provide('settingsScope', new SettingsScopeService(ctx))
+  ctx.plugin(SettingsScopeService)
 }

+ 29 - 0
packages/client/ui-settings/tests/plugin.spec.ts

@@ -0,0 +1,29 @@
+/**
+ * The settings domain base plugin's own mounting behavior: it stands up
+ * `ctx.settingsScope` for every feature that owns a preference row, and the
+ * service retires with its fiber.
+ */
+import { Context } from '@deepseek-ai/cordis'
+import { describe, expect, it } from 'vitest'
+import { apply, inject, SettingsScopeService } from '../src/client/index.ts'
+
+/** Boot the browser half over a bare root context; it injects nothing. */
+function bench() {
+  const ctx = new Context()
+  return { ctx, fiber: ctx.plugin({ inject: [...inject], apply }) }
+}
+
+describe('settings domain base plugin', () => {
+  it('mounts the scope service under settingsScope', async () => {
+    const { ctx, fiber } = bench()
+    await fiber.await()
+    expect(ctx.get('settingsScope')).toBeInstanceOf(SettingsScopeService)
+  })
+
+  it('fiber disposal retires the service', async () => {
+    const { ctx, fiber } = bench()
+    await fiber.await()
+    await fiber.dispose()
+    expect(ctx.get('settingsScope')).toBeUndefined()
+  })
+})