123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- // mounted makes store to reinitiate on each test
- import { mounted } from '#tests/support/components/mounted.ts'
- import { mockAccount } from '#tests/support/mock-account.ts'
- import { nextTick } from 'vue'
- import { useAppTheme } from '../theme.ts'
- const haveUserPreference = (theme: string | undefined) => {
- mockAccount({
- preferences: {
- theme,
- },
- })
- }
- const haveDOMTheme = (theme: string | undefined) => {
- const root = document.querySelector(':root') as HTMLElement
- if (!theme) {
- root.removeAttribute('data-theme')
- } else {
- root.dataset.theme = theme
- }
- }
- const getDOMTheme = () => {
- const root = document.querySelector(':root') as HTMLElement
- return root.dataset.theme
- }
- const addEventListener = vi.fn()
- const haveMediaTheme = (theme: string) => {
- window.matchMedia = (rule) =>
- ({
- matches: !!(rule === '(prefers-color-scheme: dark)' && theme === 'dark'),
- addEventListener,
- }) as any
- }
- describe('theme is initiated correctly', () => {
- beforeEach(() => {
- haveDOMTheme(undefined)
- haveMediaTheme('light')
- })
- describe("when user doesn't have a preference", () => {
- beforeEach(() => {
- haveUserPreference(undefined)
- })
- it('when DOM is present, takes from DOM', () => {
- haveMediaTheme('light')
- haveDOMTheme('dark')
- const appTheme = mounted(() => useAppTheme())
- expect(appTheme.theme).toBe('dark')
- expect(getDOMTheme()).toBe('dark')
- })
- it('when DOM is not present, takes from media if light', () => {
- haveMediaTheme('light')
- haveDOMTheme(undefined)
- const appTheme = mounted(() => useAppTheme())
- expect(appTheme.theme).toBe('light')
- expect(getDOMTheme()).toBe('light')
- })
- it('when DOM is not present, takes from media if dark', () => {
- haveMediaTheme('dark')
- haveDOMTheme(undefined)
- const appTheme = mounted(() => useAppTheme())
- expect(appTheme.theme).toBe('dark')
- expect(getDOMTheme()).toBe('dark')
- })
- it('when media changes, update theme', async () => {
- haveMediaTheme('dark')
- const appTheme = mounted(() => useAppTheme())
- expect(appTheme.theme).toBe('dark')
- expect(getDOMTheme()).toBe('dark')
- haveMediaTheme('light')
- addEventListener.mock.calls[0][1]()
- expect(appTheme.theme).toBe('light')
- expect(getDOMTheme()).toBe('light')
- })
- })
- describe('when user has a preference', () => {
- it('when user has dark theme enabled, but DOM and media are light, takes from user preference', () => {
- haveUserPreference('dark')
- haveMediaTheme('light')
- haveDOMTheme('light')
- const appTheme = mounted(() => useAppTheme())
- expect(appTheme.theme).toBe('dark')
- expect(getDOMTheme()).toBe('dark')
- })
- it('when user has light theme enabled, but DOM and media are dark, takes from user preference', () => {
- haveUserPreference('light')
- haveMediaTheme('dark')
- haveDOMTheme('dark')
- const appTheme = mounted(() => useAppTheme())
- expect(appTheme.theme).toBe('light')
- expect(getDOMTheme()).toBe('light')
- })
- it('updates theme when account is changed', async () => {
- haveUserPreference('light')
- const appTheme = mounted(() => useAppTheme())
- expect(appTheme.theme).toBe('light')
- expect(getDOMTheme()).toBe('light')
- haveUserPreference('dark')
- await nextTick()
- expect(appTheme.theme).toBe('dark')
- expect(getDOMTheme()).toBe('dark')
- })
- it('can toggle them from the outside', () => {
- haveUserPreference('light')
- const appTheme = mounted(() => useAppTheme())
- expect(appTheme.theme).toBe('light')
- expect(getDOMTheme()).toBe('light')
- appTheme.toggleTheme(false)
- expect(appTheme.theme).toBe('dark')
- expect(getDOMTheme()).toBe('dark')
- })
- it("changes in media don't affect theme", async () => {
- haveUserPreference('dark')
- haveMediaTheme('dark')
- const appTheme = mounted(() => useAppTheme())
- expect(appTheme.theme).toBe('dark')
- expect(getDOMTheme()).toBe('dark')
- haveMediaTheme('light')
- addEventListener.mock.calls[0][1]()
- expect(appTheme.theme).toBe('dark')
- expect(getDOMTheme()).toBe('dark')
- })
- // TODO: when saveTheme implements API call
- it.todo('stored the new value in user preferences when theme is toggled')
- })
- })
|