host.spec.ts 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. import { Context } from '@deepseek-ai/cordis'
  2. import { describe, expect, it } from 'vitest'
  3. import type { HttpServerService } from '@deepseek-ai/dsh-host-webserver'
  4. import { Settings, settingsNamespace, type SettingsNamespace } from '@deepseek-ai/dsh-settings'
  5. import {
  6. DEFAULT_PREFERENCE, THEME_SETTINGS_NAMESPACE, apply,
  7. } from '@deepseek-ai/dsh-client-ui-theme'
  8. class MemorySettings extends Settings {
  9. readonly writable = true
  10. protected load(): Promise<Record<string, unknown>> { return Promise.resolve({}) }
  11. protected persist(_ns: SettingsNamespace, _section: Record<string, unknown>): Promise<void> {
  12. return Promise.resolve()
  13. }
  14. }
  15. describe('ui-theme host', () => {
  16. it('registers, validates, and disposes the durable theme namespace with its fiber', async () => {
  17. const ctx = new Context()
  18. await ctx.plugin(MemorySettings).await()
  19. const fiber = ctx.plugin({ apply })
  20. await fiber.await()
  21. const ns = settingsNamespace(THEME_SETTINGS_NAMESPACE)
  22. expect(ctx.settings.get(ns)).toEqual({ preference: DEFAULT_PREFERENCE })
  23. await ctx.settings.update(ns, { preference: 'dark' })
  24. expect(ctx.settings.get(ns)).toEqual({ preference: 'dark' })
  25. await expect(ctx.settings.update(ns, { preference: 'sepia' })).rejects.toThrow()
  26. await fiber.dispose()
  27. expect(ctx.settings.describe().map(row => row.ns)).not.toContain(ns)
  28. })
  29. it('renders the current durable preference and disposes the index transform', async () => {
  30. const ctx = new Context()
  31. await ctx.plugin(MemorySettings).await()
  32. let transform: ((html: string) => string) | undefined
  33. let disposed = false
  34. ctx.provide('httpServer', {
  35. tapIndex: (next: (html: string) => string) => {
  36. transform = next
  37. return () => { disposed = true }
  38. },
  39. } as HttpServerService)
  40. const fiber = ctx.plugin({ apply })
  41. await fiber.await()
  42. expect(transform?.('<body></body>')).toContain('const preference = "system"')
  43. await ctx.settings.update(settingsNamespace(THEME_SETTINGS_NAMESPACE), { preference: 'dark' })
  44. expect(transform?.('<body></body>')).toContain('const preference = "dark"')
  45. await fiber.dispose()
  46. expect(disposed).toBe(true)
  47. expect(transform?.('<body></body>')).toContain('const preference = "system"')
  48. })
  49. it('uses the system preference when only an HTTP server exists', async () => {
  50. const ctx = new Context()
  51. let transform: ((html: string) => string) | undefined
  52. ctx.provide('httpServer', {
  53. tapIndex: (next: (html: string) => string) => {
  54. transform = next
  55. return () => undefined
  56. },
  57. } as HttpServerService)
  58. await ctx.plugin({ apply }).await()
  59. expect(transform?.('<body></body>')).toContain('const preference = "system"')
  60. })
  61. })