Files
kashilo/tests/helpers.test.js

158 lines
4.3 KiB
JavaScript
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.
/**
* Tests for js/utils/helpers.js
*/
import { test, describe, assertEquals, assertTrue } from './test-runner.js'
import { escapeHTML, formatPrice, formatRelativeTime, debounce, truncate } from '../js/utils/helpers.js'
describe('escapeHTML', () => {
test('escapes < and >', () => {
assertEquals(escapeHTML('<script>'), '&lt;script&gt;')
})
test('escapes quotes', () => {
assertEquals(escapeHTML('"hello"'), '&quot;hello&quot;')
})
test('escapes ampersand', () => {
assertEquals(escapeHTML('a & b'), 'a &amp; b')
})
test('escapes single quotes', () => {
assertEquals(escapeHTML("it's"), "it&#039;s")
})
test('handles null', () => {
assertEquals(escapeHTML(null), '')
})
test('handles undefined', () => {
assertEquals(escapeHTML(undefined), '')
})
test('handles numbers by converting to string', () => {
assertEquals(escapeHTML(123), '123')
})
test('handles complex XSS attempt', () => {
const xss = '<img src="x" onerror="alert(1)">'
assertTrue(!escapeHTML(xss).includes('<'))
})
})
describe('formatPrice', () => {
test('formats EUR correctly', () => {
assertEquals(formatPrice(99.5, 'EUR'), '€ 99.50')
})
test('formats USD correctly', () => {
assertEquals(formatPrice(99.5, 'USD'), '$ 99.50')
})
test('formats CHF correctly', () => {
assertEquals(formatPrice(99.5, 'CHF'), 'CHF 99.50')
})
test('formats XMR with 4 decimals', () => {
assertEquals(formatPrice(0.5, 'XMR'), '0.5000 ɱ')
})
test('handles null price', () => {
assertEquals(formatPrice(null, 'EUR'), '')
})
test('handles undefined price', () => {
assertEquals(formatPrice(undefined, 'EUR'), '')
})
test('defaults to EUR', () => {
assertEquals(formatPrice(10), '€ 10.00')
})
test('handles unknown currency', () => {
assertEquals(formatPrice(10, 'GBP'), 'GBP 10.00')
})
})
describe('formatRelativeTime', () => {
test('formats seconds ago', () => {
const date = new Date(Date.now() - 30000) // 30 seconds ago
const result = formatRelativeTime(date, 'en')
assertTrue(result.includes('second'))
})
test('formats minutes ago', () => {
const date = new Date(Date.now() - 5 * 60000) // 5 minutes ago
const result = formatRelativeTime(date, 'en')
assertTrue(result.includes('minute'))
})
test('formats hours ago', () => {
const date = new Date(Date.now() - 2 * 3600000) // 2 hours ago
const result = formatRelativeTime(date, 'en')
assertTrue(result.includes('hour'))
})
test('formats days ago', () => {
const date = new Date(Date.now() - 3 * 86400000) // 3 days ago
const result = formatRelativeTime(date, 'en')
assertTrue(result.includes('day'))
})
test('accepts string date', () => {
const date = new Date(Date.now() - 60000).toISOString()
const result = formatRelativeTime(date, 'en')
assertTrue(result.includes('minute'))
})
test('respects locale de', () => {
const date = new Date(Date.now() - 60000)
const result = formatRelativeTime(date, 'de')
assertTrue(result.includes('Minute'))
})
})
describe('truncate', () => {
test('truncates long strings', () => {
assertEquals(truncate('Hello World', 6), 'Hello…')
})
test('does not truncate short strings', () => {
assertEquals(truncate('Hi', 10), 'Hi')
})
test('handles exact length', () => {
assertEquals(truncate('Hello', 5), 'Hello')
})
test('handles null', () => {
assertEquals(truncate(null, 10), null)
})
test('handles empty string', () => {
assertEquals(truncate('', 10), '')
})
test('uses default maxLength of 100', () => {
const long = 'a'.repeat(150)
const result = truncate(long)
assertEquals(result.length, 100)
assertTrue(result.endsWith('…'))
})
})
describe('debounce', () => {
test('returns a function', () => {
const fn = debounce(() => {})
assertEquals(typeof fn, 'function')
})
test('delays execution', (done) => {
let called = false
const fn = debounce(() => { called = true }, 50)
fn()
assertEquals(called, false)
})
})