test(quick-261016-0fm): theme switch, language switcher and footer offset
- theme: light and dark ignore prefers-color-scheme, choices and guard - i18n: ?locale= only with a preference, availableLocales from meta - usePreferences: cache validation, cycle order and PUT bodies, revert with a danger toast, profile apply, setLocale save, cache and reload - rail theme button, user menu language group, --shell-offset and the form save bar offset; fixture strings and resetState theme reset
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { beforeEach, describe, expect, it } from 'vitest'
|
||||
import {
|
||||
availableLocales,
|
||||
currentLocale,
|
||||
interpolate,
|
||||
loadStrings,
|
||||
@@ -9,7 +10,7 @@ import {
|
||||
t,
|
||||
tc,
|
||||
} from '../../src/app/i18n'
|
||||
import { API, mockApi, requestsTo } from '../helpers'
|
||||
import { API, mockApi, queryOf, requestsTo } from '../helpers'
|
||||
import { langFixture } from '../fixtures/typed'
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -128,6 +129,29 @@ describe('loadStrings', () => {
|
||||
expect(currentLocale.value).toBe('en')
|
||||
})
|
||||
|
||||
it('sends the preferred locale as ?locale= and keeps meta.locales', async () => {
|
||||
const calls = mockApi({
|
||||
[`GET ${API}/lang`]: { body: { data: {}, meta: { locale: 'en', locales: ['en', 'pl'] } } },
|
||||
})
|
||||
await loadStrings('en')
|
||||
const [request] = requestsTo(calls, 'GET', `${API}/lang`)
|
||||
expect(queryOf(request!).get('locale')).toBe('en')
|
||||
expect(availableLocales.value).toEqual(['en', 'pl'])
|
||||
expect(currentLocale.value).toBe('en')
|
||||
})
|
||||
|
||||
it('sends no locale without a preference and follows a shorter meta.locales', async () => {
|
||||
const calls = mockApi({
|
||||
[`GET ${API}/lang`]: { body: { data: {}, meta: { locale: 'pl', locales: ['pl'] } } },
|
||||
})
|
||||
await loadStrings()
|
||||
await loadStrings('')
|
||||
for (const request of requestsTo(calls, 'GET', `${API}/lang`)) {
|
||||
expect(queryOf(request).has('locale')).toBe(false)
|
||||
}
|
||||
expect(availableLocales.value).toEqual(['pl'])
|
||||
})
|
||||
|
||||
it('keeps the current strings when the bundle cannot be loaded', async () => {
|
||||
mockApi({ [`GET ${API}/lang`]: { status: 500, body: { error: { code: 'server', message: 'x', details: {} } } } })
|
||||
await loadStrings()
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { applyColorScheme, DARK_QUERY } from '../../src/app/theme'
|
||||
import { applyColorScheme, DARK_QUERY, isThemeChoice, THEME_CHOICES } from '../../src/app/theme'
|
||||
import { fakeMedia } from '../helpers'
|
||||
|
||||
afterEach(() => {
|
||||
document.documentElement.classList.remove('dark')
|
||||
})
|
||||
|
||||
describe('applyColorScheme (A6: system preference only)', () => {
|
||||
describe('applyColorScheme', () => {
|
||||
it('sets .dark from prefers-color-scheme and follows changes until unsubscribed', () => {
|
||||
const media = fakeMedia({ [DARK_QUERY]: true })
|
||||
const stop = applyColorScheme()
|
||||
@@ -31,4 +31,41 @@ describe('applyColorScheme (A6: system preference only)', () => {
|
||||
expect(document.documentElement.classList.contains('dark')).toBe(false)
|
||||
expect(stop()).toBeUndefined()
|
||||
})
|
||||
|
||||
it('light never sets .dark and ignores the media query', () => {
|
||||
const media = fakeMedia({ [DARK_QUERY]: true })
|
||||
document.documentElement.classList.add('dark')
|
||||
const stop = applyColorScheme(window, 'light')
|
||||
expect(document.documentElement.classList.contains('dark')).toBe(false)
|
||||
expect(media.listeners(DARK_QUERY)).toBe(0)
|
||||
media.change(DARK_QUERY, true)
|
||||
expect(document.documentElement.classList.contains('dark')).toBe(false)
|
||||
expect(stop()).toBeUndefined()
|
||||
})
|
||||
|
||||
it('dark always sets .dark and ignores the media query', () => {
|
||||
const media = fakeMedia({ [DARK_QUERY]: false })
|
||||
const stop = applyColorScheme(window, 'dark')
|
||||
expect(document.documentElement.classList.contains('dark')).toBe(true)
|
||||
expect(media.listeners(DARK_QUERY)).toBe(0)
|
||||
media.change(DARK_QUERY, false)
|
||||
expect(document.documentElement.classList.contains('dark')).toBe(true)
|
||||
stop()
|
||||
})
|
||||
|
||||
it('dark works without matchMedia', () => {
|
||||
const win = { document } as unknown as Window
|
||||
applyColorScheme(win, 'dark')
|
||||
expect(document.documentElement.classList.contains('dark')).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('theme choices', () => {
|
||||
it('lists system, light and dark in cycle order and guards values', () => {
|
||||
expect(THEME_CHOICES).toEqual(['system', 'light', 'dark'])
|
||||
expect(isThemeChoice('dark')).toBe(true)
|
||||
expect(isThemeChoice('blue')).toBe(false)
|
||||
expect(isThemeChoice(null)).toBe(false)
|
||||
expect(isThemeChoice(1)).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user