import { describe, it, expect } from 'vitest' // Import from the pure modules directly — no electron import chain (L37). import { parseProgress } from '../src/main/lib/formatters' import { fmtBytes, fmtEta } from '../src/shared/format' describe('fmtBytes', () => { it('formats bytes under 1 KB verbatim', () => { expect(fmtBytes(0)).toBe('0 B') expect(fmtBytes(512)).toBe('512 B') expect(fmtBytes(1023)).toBe('1023 B') }) it('switches to KB at 1024', () => { expect(fmtBytes(1024)).toBe('1.0 KB') expect(fmtBytes(1536)).toBe('1.5 KB') }) it('uses one decimal below 100, none above', () => { expect(fmtBytes(99 * 1024)).toBe('99.0 KB') expect(fmtBytes(100 * 1024)).toBe('100 KB') expect(fmtBytes(150 * 1024)).toBe('150 KB') }) it('switches to MB and GB', () => { expect(fmtBytes(1024 * 1024)).toBe('1.0 MB') expect(fmtBytes(1024 * 1024 * 1024)).toBe('1.0 GB') }) }) describe('fmtEta', () => { it('returns undefined for null / undefined input', () => { expect(fmtEta(undefined)).toBeUndefined() expect(fmtEta(null as unknown as number)).toBeUndefined() }) it('formats seconds to M:SS', () => { expect(fmtEta(0)).toBe('0:00') expect(fmtEta(59)).toBe('0:59') expect(fmtEta(60)).toBe('1:00') expect(fmtEta(90)).toBe('1:30') expect(fmtEta(3599)).toBe('59:59') }) it('formats hours to H:MM:SS (L166)', () => { expect(fmtEta(3600)).toBe('1:00:00') expect(fmtEta(3661)).toBe('1:01:01') expect(fmtEta(7260)).toBe('2:01:00') expect(fmtEta(7384)).toBe('2:03:04') }) it('clamps negative input to 0', () => { expect(fmtEta(-10)).toBe('0:00') }) }) describe('parseProgress', () => { const makeRaw = (parts: string[]): string => parts.join('|') it('returns null when there are fewer than 6 fields', () => { expect(parseProgress('')).toBeNull() expect(parseProgress('downloading|100|200|200')).toBeNull() }) it('parses a normal progress line', () => { // status | downloaded | total | totalEst | speed | eta const raw = makeRaw(['downloading', '524288', '1048576', '1048576', '262144', '2']) const p = parseProgress(raw) expect(p).not.toBeNull() expect(p!.progress).toBeCloseTo(0.5) expect(p!.speedBytesPerSec).toBe(262144) expect(p!.etaSeconds).toBe(2) expect(p!.sizeLabel).toBe('1.0 MB') expect(p!.sizeUnknown).toBe(false) }) it('falls back to totalEst when total is NA', () => { const raw = makeRaw(['downloading', '100', 'NA', '1000', '50', '18']) const p = parseProgress(raw) expect(p).not.toBeNull() expect(p!.sizeLabel).toBe('1000 B') expect(p!.sizeUnknown).toBe(false) }) it('marks sizeUnknown when both total and totalEst are NA', () => { const raw = makeRaw(['downloading', '100', 'NA', 'NA', 'NA', 'NA']) const p = parseProgress(raw) expect(p).not.toBeNull() expect(p!.sizeUnknown).toBe(true) expect(p!.etaSeconds).toBeUndefined() expect(p!.speedBytesPerSec).toBeUndefined() }) it('clamps progress to 1.0', () => { const raw = makeRaw(['downloading', '2000', '1000', '1000', '500', '0']) const p = parseProgress(raw) expect(p!.progress).toBe(1) }) it('carries a raw ETA in seconds; the renderer formats it (L166)', () => { const raw = makeRaw(['downloading', '100', '1000', '1000', '10', '3661']) const p = parseProgress(raw) expect(p!.etaSeconds).toBe(3661) expect(fmtEta(p!.etaSeconds)).toBe('1:01:01') }) })