Files
sofarr/tests/frontend/utils/format.test.js
T
gronod 3e6af1bff2
Licence Check / Licence compatibility and copyright header verification (push) Successful in 38s
CI / Security audit (push) Successful in 53s
CI / Tests & coverage (push) Successful in 1m9s
Build and Push Docker Image / build (push) Failing after 32s
Add frontend unit tests with Vitest + jsdom
- Create tests/frontend/utils/format.test.js with 24 tests for formatting utilities
- Create tests/frontend/ui/downloads.test.js with 10 tests for DOM rendering functions
- Update vitest.config.js to support jsdom environment for frontend tests
- All 34 tests pass and cover edge cases (null, zero, large numbers, DOM structure)
2026-05-21 00:07:41 +01:00

128 lines
3.5 KiB
JavaScript

// Copyright (c) 2026 Gordon Bolton. MIT License.
/**
* @vitest-environment jsdom
* Tests for client/src/utils/format.js
*
* Verifies formatting utilities for sizes, speeds, dates, and HTML escaping.
* These are pure functions that handle edge cases like null, zero, and large numbers.
*/
import { formatSize, formatSpeed, formatDate, formatTimeAgo, escapeHtml } from '../../../client/src/utils/format.js';
describe('formatSize', () => {
it('returns N/A for null/undefined', () => {
expect(formatSize(null)).toBe('N/A');
expect(formatSize(undefined)).toBe('N/A');
});
it('returns string as-is when already formatted', () => {
expect(formatSize('21.5 GB')).toBe('21.5 GB');
});
it('formats bytes correctly', () => {
expect(formatSize(512)).toBe('512 B');
});
it('formats kilobytes correctly', () => {
expect(formatSize(1024)).toBe('1 KB');
});
it('formats megabytes correctly', () => {
expect(formatSize(1024 * 1024)).toBe('1 MB');
});
it('formats gigabytes correctly', () => {
expect(formatSize(1024 * 1024 * 1024)).toBe('1 GB');
});
it('handles zero', () => {
expect(formatSize(0)).toBe('N/A');
});
});
describe('formatSpeed', () => {
it('returns 0 B/s for zero', () => {
expect(formatSpeed(0)).toBe('0 B/s');
});
it('returns 0 B/s for null/undefined', () => {
expect(formatSpeed(null)).toBe('0 B/s');
expect(formatSpeed(undefined)).toBe('0 B/s');
});
it('formats bytes per second correctly', () => {
expect(formatSpeed(512)).toBe('512.00 B/s');
});
it('formats kilobytes per second correctly', () => {
expect(formatSpeed(1024)).toBe('1.00 KB/s');
});
it('formats megabytes per second correctly', () => {
expect(formatSpeed(1024 * 1024)).toBe('1.00 MB/s');
});
it('handles large numbers', () => {
expect(formatSpeed(1024 * 1024 * 1024)).toBe('1.00 GB/s');
});
});
describe('formatDate', () => {
it('returns N/A for null/undefined', () => {
expect(formatDate(null)).toBe('N/A');
expect(formatDate(undefined)).toBe('N/A');
});
it('formats valid date string', () => {
const dateStr = '2024-01-15T10:30:00Z';
const result = formatDate(dateStr);
expect(result).toBeTruthy();
expect(result).not.toBe('N/A');
});
});
describe('formatTimeAgo', () => {
it('returns Never for null/undefined', () => {
expect(formatTimeAgo(null)).toBe('Never');
expect(formatTimeAgo(undefined)).toBe('Never');
});
it('returns seconds ago for recent timestamps', () => {
const now = Date.now();
expect(formatTimeAgo(now - 30000)).toBe('30s ago');
});
it('returns minutes ago for older timestamps', () => {
const now = Date.now();
expect(formatTimeAgo(now - 60000 * 5)).toBe('5m ago');
});
it('returns hours ago for hours-old timestamps', () => {
const now = Date.now();
expect(formatTimeAgo(now - 60000 * 60 * 3)).toBe('3h ago');
});
it('returns days ago for day-old timestamps', () => {
const now = Date.now();
expect(formatTimeAgo(now - 60000 * 60 * 24 * 2)).toBe('2d ago');
});
});
describe('escapeHtml', () => {
it('escapes HTML special characters', () => {
expect(escapeHtml('<script>alert("xss")</script>')).toBe('&lt;script&gt;alert("xss")&lt;/script&gt;');
});
it('escapes quotes', () => {
expect(escapeHtml('"test"')).toBe('"test"');
});
it('handles empty string', () => {
expect(escapeHtml('')).toBe('');
});
it('handles normal text without special chars', () => {
expect(escapeHtml('normal text')).toBe('normal text');
});
});