mount.client.spec.ts 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. // @vitest-environment jsdom
  2. import { Context } from '@deepseek-ai/cordis'
  3. import { describe, expect, it, vi } from 'vitest'
  4. import { mountClient } from '../src/mount.ts'
  5. /** Provide a fake `uiRenderer` from its own plugin fiber so it can be replaced. */
  6. function provideRenderer(ctx: Context, mount: (container: HTMLElement) => () => void) {
  7. return ctx.plugin({ apply: (scope: Context) => { scope.reflect.provide('uiRenderer', { mount }) } })
  8. }
  9. describe('mountClient', () => {
  10. it('mounts into the container and unmounts when the tree is disposed', async () => {
  11. const ctx = new Context()
  12. const unmount = vi.fn()
  13. const mount = vi.fn((_container: HTMLElement) => unmount)
  14. provideRenderer(ctx, mount)
  15. const container = document.createElement('div')
  16. await mountClient(ctx, container)
  17. expect(mount).toHaveBeenCalledExactlyOnceWith(container)
  18. expect(unmount).not.toHaveBeenCalled()
  19. await ctx.fiber.dispose()
  20. expect(unmount).toHaveBeenCalledOnce()
  21. })
  22. it('remounts when uiRenderer is replaced', async () => {
  23. const ctx = new Context()
  24. const container = document.createElement('div')
  25. const first = { unmount: vi.fn(), mount: vi.fn(() => first.unmount) }
  26. const second = { unmount: vi.fn(), mount: vi.fn(() => second.unmount) }
  27. await mountClient(ctx, container)
  28. expect(first.mount).not.toHaveBeenCalled()
  29. const renderer = provideRenderer(ctx, first.mount)
  30. await vi.waitFor(() => { expect(first.mount).toHaveBeenCalledExactlyOnceWith(container) })
  31. await renderer.dispose()
  32. expect(first.unmount).toHaveBeenCalledOnce()
  33. provideRenderer(ctx, second.mount)
  34. await vi.waitFor(() => { expect(second.mount).toHaveBeenCalledExactlyOnceWith(container) })
  35. await ctx.fiber.dispose()
  36. expect(second.unmount).toHaveBeenCalledOnce()
  37. })
  38. })