test: expand coverage 53 → 135 (+82 tests)
Аудит тестов выявил критические пробелы в покрытии. Расширили существующие файлы и добавили два новых: Новые файлы: - src/main/validate.test.ts (59) — security-boundary IPC layer вообще не имел тестов. Покрывает NaN/Infinity, range edge cases, тип- сабверсии, partial-patch semantics, quietHours regex+dedup. Фиксирует контракт «strict для required, lenient для optional defaults» (input принимает enabled:'yes' → true, patch строгий). - src/renderer/src/lib/icon-choices.test.ts (3) — SAMPLE_EXERCISES.icon ⊆ ICON_CHOICES (иначе fallback-Activity на первом запуске). Расширения: - format.test.ts: NaN/Infinity guard, EN-локаль. - history.test.ts: DST-safe инвариант (unique keys, monotonic), plannedRepsToday, future-dated entries, mixed actions. - i18n.test.ts: dict parity RU↔EN (с правильным skip для RU-only *_few CLDR-категории), regex-injection в var-значениях, weekday.short.* parity. Рефакторинг: - ICON_CHOICES вынесен в src/renderer/src/lib/icon-choices.ts (без JSX) — теперь whitelist импортируется из любого слоя без React-зависимости. icon.tsx реэкспортирует для обратной совместимости.
This commit is contained in:
@@ -33,6 +33,29 @@ describe('formatCountdown', () => {
|
||||
expect(formatCountdown(999)).toBe('0с')
|
||||
expect(formatCountdown(500)).toBe('0с')
|
||||
})
|
||||
|
||||
// Guard added in v0.5.2 — electron-updater и scheduler могут передать
|
||||
// NaN/Infinity на ранних событиях. Должны вернуть «сейчас», не «NaNс».
|
||||
it('returns "сейчас" for NaN and Infinity (defensive guard)', () => {
|
||||
expect(formatCountdown(NaN)).toBe('сейчас')
|
||||
expect(formatCountdown(Infinity)).toBe('сейчас')
|
||||
expect(formatCountdown(-Infinity)).toBe('сейчас')
|
||||
})
|
||||
|
||||
describe('english locale', () => {
|
||||
it('renders sub-minute with "s"', () => {
|
||||
expect(formatCountdown(45_000, 'en')).toBe('45s')
|
||||
})
|
||||
it('renders minutes+seconds with "m"/"s"', () => {
|
||||
expect(formatCountdown(65_000, 'en')).toBe('1m 05s')
|
||||
})
|
||||
it('renders hours+minutes with "h"/"m"', () => {
|
||||
expect(formatCountdown(3_660_000, 'en')).toBe('1h 01m')
|
||||
})
|
||||
it('returns "now" for zero', () => {
|
||||
expect(formatCountdown(0, 'en')).toBe('now')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('formatInterval', () => {
|
||||
@@ -53,4 +76,10 @@ describe('formatInterval', () => {
|
||||
expect(formatInterval(90)).toBe('1 ч 30 мин')
|
||||
expect(formatInterval(125)).toBe('2 ч 5 мин')
|
||||
})
|
||||
|
||||
it('english locale', () => {
|
||||
expect(formatInterval(30, 'en')).toBe('30 min')
|
||||
expect(formatInterval(60, 'en')).toBe('1 h')
|
||||
expect(formatInterval(90, 'en')).toBe('1 h 30 min')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user