theme-presenter.spec.ts 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. // @vitest-environment jsdom
  2. // ThemePresenter behavior account: the palette attribute follows
  3. // active.colorScheme only, token variables replace the previous apply's set,
  4. // and dispose retracts everything the presenter wrote.
  5. import { beforeEach, describe, expect, it } from 'vitest'
  6. import type { ThemeSnapshot } from '@deepseek-ai/dsh-client-ui-theme/client'
  7. import { DARK_ATTRIBUTE, ThemePresenter } from '@deepseek-ai/dsh-client-ui-layout/src/client/theme-presenter.ts'
  8. function snapshot(colorScheme: 'light' | 'dark', tokens: Record<string, string> = {}): ThemeSnapshot {
  9. // The presenter must key off colorScheme, not the id — keep them distinct.
  10. const active = { id: `${colorScheme}-test`, colorScheme, tokens }
  11. return { preference: colorScheme, active, themes: [active], revision: 1 }
  12. }
  13. beforeEach(() => {
  14. document.body.removeAttribute(DARK_ATTRIBUTE)
  15. document.body.removeAttribute('style')
  16. })
  17. describe('ThemePresenter', () => {
  18. it('light scheme leaves the dark attribute absent', () => {
  19. const presenter = new ThemePresenter()
  20. presenter.apply(snapshot('light'))
  21. expect(document.body.hasAttribute(DARK_ATTRIBUTE)).toBe(false)
  22. })
  23. it('dark scheme sets the attribute; switching back to light removes it', () => {
  24. const presenter = new ThemePresenter()
  25. presenter.apply(snapshot('dark'))
  26. expect(document.body.hasAttribute(DARK_ATTRIBUTE)).toBe(true)
  27. presenter.apply(snapshot('light'))
  28. expect(document.body.hasAttribute(DARK_ATTRIBUTE)).toBe(false)
  29. })
  30. it('applies tokens as inline variables and clears the previous set on theme change', () => {
  31. const presenter = new ThemePresenter()
  32. presenter.apply(snapshot('dark', { '--dsw-alias-bg': '#111', '--dsw-alias-fg': '#eee' }))
  33. expect(document.body.style.getPropertyValue('--dsw-alias-bg')).toBe('#111')
  34. expect(document.body.style.getPropertyValue('--dsw-alias-fg')).toBe('#eee')
  35. presenter.apply(snapshot('light', { '--dsw-alias-bg': '#fff' }))
  36. expect(document.body.style.getPropertyValue('--dsw-alias-bg')).toBe('#fff')
  37. // The old theme's extra variable is gone, not merged.
  38. expect(document.body.style.getPropertyValue('--dsw-alias-fg')).toBe('')
  39. })
  40. it('dispose removes the attribute and every applied variable, sparing foreign inline styles', () => {
  41. document.body.style.setProperty('--foreign', 'kept')
  42. const presenter = new ThemePresenter()
  43. presenter.apply(snapshot('dark', { '--dsw-alias-bg': '#111' }))
  44. presenter.dispose()
  45. expect(document.body.hasAttribute(DARK_ATTRIBUTE)).toBe(false)
  46. expect(document.body.style.getPropertyValue('--dsw-alias-bg')).toBe('')
  47. expect(document.body.style.getPropertyValue('--foreign')).toBe('kept')
  48. })
  49. })