Files
mdm-ordinis/ordinis-admin-ui/src/lib/locales.test.ts
T
Zimin A.N. 5e1b39db03 fix(dict): name column в records list — pick localized value, не [object Object]
Раньше для записей с x-localized name (КА, антенна, ground_station,
operator) колонка 'name / code' показывала literal '[object Object]'
потому что String({'ru-RU': 'Канопус', 'en-US': 'Kanopus'}) =
toString() стандартный → '[object Object]'.

Решение:
- Новый shared util lib/locales.ts:
  - pickLocalized(value, defaultLocale) — извлекает строку из i18n
    объекта или plain string. Fallback на first non-empty key
    если defaultLocale не найден.
  - recordDisplayName(data, defaultLocale) — name → code → '—' chain.
- Records list использует recordDisplayName с dict.defaultLocale
  (берётся из DictionaryDetail).
- SchemaDrivenForm дедуплицирован — был свой локальный pickLocalized,
  теперь импортирует из util'ы.

Tests: +13 (76 → 89), unit tests на pickLocalized + recordDisplayName
покрывают все edge cases (plain string, localized object, fallback
chain, null/undefined input).
2026-05-06 21:05:50 +03:00

70 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, test } from 'vitest'
import { pickLocalized, recordDisplayName } from './locales'
describe('pickLocalized', () => {
test('plain string возвращается as-is', () => {
expect(pickLocalized('hello', 'ru-RU')).toBe('hello')
})
test('пустая string → undefined (caller покажет placeholder)', () => {
expect(pickLocalized('', 'ru-RU')).toBeUndefined()
})
test('object с defaultLocale → значение defaultLocale', () => {
expect(
pickLocalized({ 'ru-RU': 'Канопус', 'en-US': 'Kanopus' }, 'ru-RU'),
).toBe('Канопус')
})
test('defaultLocale пустой → fallback на любой non-empty key', () => {
expect(pickLocalized({ 'ru-RU': '', 'en-US': 'Kanopus' }, 'ru-RU')).toBe(
'Kanopus',
)
})
test('defaultLocale отсутствует → fallback на первый non-empty key', () => {
expect(pickLocalized({ 'en-US': 'Kanopus' }, 'ru-RU')).toBe('Kanopus')
})
test('null / undefined / number → undefined', () => {
expect(pickLocalized(null, 'ru-RU')).toBeUndefined()
expect(pickLocalized(undefined, 'ru-RU')).toBeUndefined()
expect(pickLocalized(42, 'ru-RU')).toBeUndefined()
})
test('объект без string значений → undefined', () => {
expect(pickLocalized({ 'ru-RU': { nested: 'oops' } }, 'ru-RU')).toBeUndefined()
})
})
describe('recordDisplayName', () => {
test('localized name → строка локали', () => {
expect(
recordDisplayName({ name: { 'ru-RU': 'Канопус', 'en-US': 'Kanopus' } }, 'ru-RU'),
).toBe('Канопус')
})
test('plain name string', () => {
expect(recordDisplayName({ name: 'Plain' }, 'ru-RU')).toBe('Plain')
})
test('нет name → fallback на code', () => {
expect(recordDisplayName({ code: 'OPERATIONAL' }, 'ru-RU')).toBe('OPERATIONAL')
})
test('нет name+code → em-dash', () => {
expect(recordDisplayName({ other: 'x' }, 'ru-RU')).toBe('—')
})
test('undefined data → em-dash', () => {
expect(recordDisplayName(undefined, 'ru-RU')).toBe('—')
})
test('localized с empty default locale → fallback на code не происходит, берём другую локаль', () => {
// Если name есть в other locale — оно приоритетнее code (name всегда нагляднее).
expect(
recordDisplayName({ name: { 'en-US': 'Eng only' }, code: 'X' }, 'ru-RU'),
).toBe('Eng only')
})
})