5e1b39db03
Раньше для записей с 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).
70 lines
2.5 KiB
TypeScript
70 lines
2.5 KiB
TypeScript
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')
|
||
})
|
||
})
|