project-nomad/admin/inertia/lib/util.test.ts

103 lines
3.3 KiB
TypeScript

// @vitest-environment jsdom
import { describe, it, expect, vi, beforeEach } from 'vitest'
import {
setGlobalNotificationCallback,
capitalizeFirstLetter,
formatBytes,
generateRandomString,
generateUUID,
extractFileName,
catchInternal
} from './util'
describe('util', () => {
describe('capitalizeFirstLetter', () => {
it('should capitalize the first letter of a string', () => {
expect(capitalizeFirstLetter('nomad')).toBe('Nomad')
expect(capitalizeFirstLetter('PROJECT')).toBe('PROJECT')
})
it('should handle empty or null values safely', () => {
expect(capitalizeFirstLetter('')).toBe('')
expect(capitalizeFirstLetter(null)).toBe('')
expect(capitalizeFirstLetter(undefined)).toBe('')
})
})
describe('formatBytes', () => {
it('should format bytes into human readable sizes', () => {
expect(formatBytes(0)).toBe('0 Bytes')
expect(formatBytes(1024)).toBe('1 KB')
expect(formatBytes(1048576)).toBe('1 MB')
})
it('should respect decimal places', () => {
expect(formatBytes(1500, 2)).toBe('1.46 KB')
expect(formatBytes(1500, 0)).toBe('1 KB')
})
})
describe('generateRandomString', () => {
it('should generate a string of the exact specified length', () => {
expect(generateRandomString(10)).toHaveLength(10)
expect(generateRandomString(0)).toBe('')
})
})
describe('generateUUID', () => {
it('should generate a valid UUID v4 format string', () => {
const uuid = generateUUID()
// Regex UUID
expect(uuid).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)
})
})
describe('extractFileName', () => {
it('should extract filename from unix-style paths', () => {
expect(extractFileName('/storage/zim/wikipedia.zim')).toBe('wikipedia.zim')
})
it('should extract filename from windows-style paths', () => {
expect(extractFileName('C:\\Users\\nomad\\downloads\\map.pmtiles')).toBe('map.pmtiles')
})
it('should return the original string if no path separators exist', () => {
expect(extractFileName('just-a-file.pdf')).toBe('just-a-file.pdf')
})
})
describe('catchInternal', () => {
beforeEach(() => {
vi.restoreAllMocks()
setGlobalNotificationCallback(null as any)
})
it('should return the result of the wrapped function if successful', async () => {
const fn = vi.fn().mockResolvedValue('success data')
const wrapped = catchInternal(fn)
const result = await wrapped()
expect(result).toBe('success data')
expect(fn).toHaveBeenCalled()
})
it('should catch errors, log to console, and trigger global notification', async () => {
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
const notificationMock = vi.fn()
setGlobalNotificationCallback(notificationMock)
const fn = vi.fn().mockRejectedValue(new Error('API Timeout'))
const wrapped = catchInternal(fn)
const result = await wrapped()
expect(result).toBeUndefined()
expect(consoleSpy).toHaveBeenCalledWith('Internal error caught:', expect.any(Error))
expect(notificationMock).toHaveBeenCalledWith({
message: expect.stringContaining('API Timeout'),
type: 'error',
duration: 5000
})
})
})
})