- mlLocale: type predicates, localeRecord, the ML_LOCALE_CHANGE broadcast - MLField: locale switch, whole-map emit, broadcast follow, content-locale - FileCaptionModal: prefill, save via FileRoutes.update, 422 stays, danger toast - ApiTokensPanel and ApiTokenCreateDialog mounted directly next to the app tests
87 lines
2.6 KiB
TypeScript
87 lines
2.6 KiB
TypeScript
// mlLocale (Phase 15): the ML field type predicates, the locale -> text map
|
|
// sent on save and the window event that keeps every ML control on one locale.
|
|
import { afterEach, describe, expect, it } from 'vitest'
|
|
import {
|
|
ML_LOCALE_CHANGE,
|
|
broadcastMLLocale,
|
|
isMLField,
|
|
isMLFieldType,
|
|
localeRecord,
|
|
} from '../../src/components/form/mlLocale'
|
|
|
|
describe('isMLFieldType', () => {
|
|
it('accepts the three ML types', () => {
|
|
expect(isMLFieldType('mltext')).toBe(true)
|
|
expect(isMLFieldType('mltextarea')).toBe(true)
|
|
expect(isMLFieldType('mlmarkdown')).toBe(true)
|
|
})
|
|
|
|
it('refuses plain types and a missing type', () => {
|
|
expect(isMLFieldType('text')).toBe(false)
|
|
expect(isMLFieldType('markdown')).toBe(false)
|
|
expect(isMLFieldType(undefined)).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('isMLField', () => {
|
|
it('accepts a built-in ML type', () => {
|
|
expect(isMLField({ type: 'mltext' })).toBe(true)
|
|
})
|
|
|
|
it('accepts a translatable plugin field with an element', () => {
|
|
expect(isMLField({ type: 'acme-color', element: 'acme-color', translatable: true })).toBe(true)
|
|
})
|
|
|
|
it('refuses a translatable field without an element', () => {
|
|
expect(isMLField({ type: 'acme-color', translatable: true })).toBe(false)
|
|
})
|
|
|
|
it('refuses a plugin field that is not translatable', () => {
|
|
expect(isMLField({ type: 'acme-color', element: 'acme-color' })).toBe(false)
|
|
expect(isMLField({ type: 'acme-color', element: 'acme-color', translatable: false })).toBe(false)
|
|
})
|
|
|
|
it('refuses a missing field', () => {
|
|
expect(isMLField(undefined)).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('localeRecord', () => {
|
|
it('keeps only string values', () => {
|
|
expect(localeRecord({ en: 'Hello', pl: 'Cześć', de: 3, fr: null, es: '' })).toEqual({
|
|
en: 'Hello',
|
|
pl: 'Cześć',
|
|
es: '',
|
|
})
|
|
})
|
|
|
|
it('returns an empty map for null, an array and a string', () => {
|
|
expect(localeRecord(null)).toEqual({})
|
|
expect(localeRecord(undefined)).toEqual({})
|
|
expect(localeRecord(['Hello'])).toEqual({})
|
|
expect(localeRecord('Hello')).toEqual({})
|
|
})
|
|
})
|
|
|
|
describe('broadcastMLLocale', () => {
|
|
const seen: string[] = []
|
|
const listener = (event: Event) => seen.push((event as CustomEvent<string>).detail)
|
|
|
|
afterEach(() => {
|
|
window.removeEventListener(ML_LOCALE_CHANGE, listener)
|
|
seen.length = 0
|
|
})
|
|
|
|
it('dispatches the locale as a window event', () => {
|
|
window.addEventListener(ML_LOCALE_CHANGE, listener)
|
|
broadcastMLLocale('pl')
|
|
expect(seen).toEqual(['pl'])
|
|
})
|
|
|
|
it('dispatches nothing for an empty locale', () => {
|
|
window.addEventListener(ML_LOCALE_CHANGE, listener)
|
|
broadcastMLLocale('')
|
|
expect(seen).toEqual([])
|
|
})
|
|
})
|