app.spec.tsx 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. // @vitest-environment jsdom
  2. /**
  3. * buildRenderApp on SlotTestRuntime: the fail-loud sessions precondition, the
  4. * one ctx-level renderSlot('root') call, and the document-title projection
  5. * arms over the real slot stack.
  6. */
  7. import { afterEach, describe, expect, it } from 'vitest'
  8. import { cleanup, render } from '@testing-library/react'
  9. import { Context } from 'cordis'
  10. import { SlotTestRuntime } from '@deepseek-ai/dsh-client-test-runtime'
  11. import type { SessionId } from '@deepseek-ai/dsh-client-runtime/client'
  12. import { buildRenderApp } from '@deepseek-ai/dsh-client-web/src/app.tsx'
  13. let runtime: SlotTestRuntime | undefined
  14. afterEach(async () => {
  15. cleanup()
  16. await runtime?.dispose()
  17. runtime = undefined
  18. document.title = ''
  19. })
  20. async function bench() {
  21. runtime = await SlotTestRuntime.create()
  22. await runtime.root.declare({}, () => <div data-testid="frame" />)
  23. return { runtime, renderApp: buildRenderApp({ ctx: runtime.ctx }) }
  24. }
  25. describe('buildRenderApp', () => {
  26. it('fails loud when the sessions service is unavailable', () => {
  27. expect(() => buildRenderApp({ ctx: new Context() })).toThrow('sessions service unavailable')
  28. })
  29. it('renders the root slot tree through the one ctx-level renderSlot call', async () => {
  30. const b = await bench()
  31. const view = render(<>{b.renderApp()}</>)
  32. expect(view.getByTestId('frame')).toBeTruthy()
  33. })
  34. it('projects the current session durable title and falls back to the product title', async () => {
  35. document.title = 'Product'
  36. const b = await bench()
  37. render(<>{b.renderApp()}</>)
  38. // No current session: the product title stands.
  39. expect(document.title).toBe('Product')
  40. await b.runtime.sessions.add({ id: 's1', summary: { title: 'First' } })
  41. expect(document.title).toBe('First — Product')
  42. await b.runtime.sessions.setCurrent(undefined)
  43. expect(document.title).toBe('Product')
  44. // A session without a durable title keeps the product title.
  45. await b.runtime.sessions.add({ id: 's2' })
  46. expect(document.title).toBe('Product')
  47. })
  48. it('a current id without a list row falls back (selection/list arbitration transient)', async () => {
  49. document.title = 'Product'
  50. const b = await bench()
  51. await b.runtime.sessions.add({ id: 's1', summary: { title: 'First' } })
  52. render(<>{b.renderApp()}</>)
  53. expect(document.title).toBe('First — Product')
  54. b.runtime.sessions.list.update((draft) => { draft.current = 'ghost' as SessionId })
  55. await b.runtime.flush()
  56. expect(document.title).toBe('Product')
  57. })
  58. })