plugin.client.spec.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { Context } from '@deepseek-ai/cordis'
  2. import { describe, expect, it, vi } from 'vitest'
  3. import { TestRemote } from '@deepseek-ai/dsh-client-test-runtime'
  4. import { apply, inject } from '../src/client/index.ts'
  5. import { SettingsSchemaService } from '../src/client/schema.ts'
  6. import { SettingsScopeBinder } from '../src/client/settings-scope.ts'
  7. import { apply as hostApply } from '../src/index.ts'
  8. function bench() {
  9. const describeCall = vi.fn((scope?: string) => Promise.resolve({
  10. ok: true,
  11. value: { writable: true, hasDocument: true, namespaces: [], ...scope === undefined ? { scopes: [] } : { scope, scopes: [scope] } },
  12. }))
  13. const ctx = new Context()
  14. const remote = new TestRemote(ctx, { settings: { describe: describeCall } })
  15. return { ctx, describeCall, remote, fiber: ctx.plugin({ inject: [...inject], apply }) }
  16. }
  17. describe('settings domain base plugin', () => {
  18. it('keeps the host Loader entry inert', () => {
  19. expect(hostApply).not.toThrow()
  20. })
  21. it('mounts the scope service under settingsScope and reads once eagerly', async () => {
  22. const { ctx, describeCall, fiber } = bench()
  23. await fiber.await()
  24. expect(ctx.get('settingsScope')).toBeInstanceOf(SettingsScopeBinder)
  25. expect(ctx.get('settingsSchema')).toBeInstanceOf(SettingsSchemaService)
  26. await vi.waitFor(() => { expect(describeCall).toHaveBeenCalledTimes(1) })
  27. })
  28. it('refreshes the mirror on document commits and connection resets, once each', async () => {
  29. const { ctx, describeCall, remote, fiber } = bench()
  30. await fiber.await()
  31. await vi.waitFor(() => { expect(describeCall).toHaveBeenCalledTimes(1) })
  32. remote.emit('settings/document-updated', ['ui-test', 0])
  33. await vi.waitFor(() => { expect(describeCall).toHaveBeenCalledTimes(2) })
  34. ctx.emit('connection/reset')
  35. await vi.waitFor(() => { expect(describeCall).toHaveBeenCalledTimes(3) })
  36. })
  37. it('routes a scoped commit to the scope\'s mirror and a global commit to every mirror', async () => {
  38. const { ctx, describeCall, remote, fiber } = bench()
  39. await fiber.await()
  40. await vi.waitFor(() => { expect(describeCall).toHaveBeenCalledTimes(1) })
  41. // A scoped commit before any scoped bind touches nothing: no mirror exists for it.
  42. remote.emit('settings/document-updated', ['ui-test', 0, 'preset/research'])
  43. await Promise.resolve()
  44. expect(describeCall).toHaveBeenCalledTimes(1)
  45. ctx.settingsScope.describe('preset/research')
  46. remote.emit('settings/document-updated', ['ui-test', 1, 'preset/research'])
  47. await vi.waitFor(() => { expect(describeCall).toHaveBeenCalledTimes(2) })
  48. expect(describeCall.mock.calls[1]).toEqual(['preset/research'])
  49. // A global commit reaches the scoped instance too: it inherits the global section.
  50. remote.emit('settings/document-updated', ['ui-test', 2])
  51. await vi.waitFor(() => { expect(describeCall).toHaveBeenCalledTimes(4) })
  52. expect(describeCall.mock.calls.slice(2).map(call => call[0])).toEqual([undefined, 'preset/research'])
  53. ctx.emit('connection/reset')
  54. await vi.waitFor(() => { expect(describeCall).toHaveBeenCalledTimes(6) })
  55. await fiber.dispose()
  56. })
  57. it('fiber disposal retires the service and its invalidation subscriptions', async () => {
  58. const { ctx, describeCall, remote, fiber } = bench()
  59. await fiber.await()
  60. await vi.waitFor(() => { expect(describeCall).toHaveBeenCalledTimes(1) })
  61. await fiber.dispose()
  62. expect(ctx.get('settingsScope')).toBeUndefined()
  63. expect(ctx.get('settingsSchema')).toBeUndefined()
  64. remote.emit('settings/document-updated', ['ui-test', 0])
  65. ctx.emit('connection/reset')
  66. await Promise.resolve()
  67. expect(describeCall).toHaveBeenCalledTimes(1)
  68. })
  69. })