/** * 格式化工具函数测试 */ import { describe, it, expect, vi, beforeEach } from 'vitest' import { formatDate, formatDateTime, formatTime, formatRelativeTime, formatFileSize, formatNumber, formatCurrency, maskPhone, maskEmail, truncateText } from '@/utils/format' describe('format utils', () => { beforeEach(() => { // 重置时间相关的模拟 vi.useFakeTimers() vi.setSystemTime(new Date('2024-01-15 12:00:00')) }) afterEach(() => { vi.useRealTimers() }) describe('formatDate', () => { it('should format timestamp to date string', () => { const timestamp = new Date('2024-01-15').getTime() expect(formatDate(timestamp)).toBe('2024-01-15') }) it('should format Date object to date string', () => { const date = new Date('2024-01-15') expect(formatDate(date)).toBe('2024-01-15') }) it('should use custom format', () => { const timestamp = new Date('2024-01-15').getTime() expect(formatDate(timestamp, 'MM/DD/YYYY')).toBe('01/15/2024') }) }) describe('formatDateTime', () => { it('should format timestamp to datetime string', () => { const timestamp = new Date('2024-01-15 12:30:45').getTime() expect(formatDateTime(timestamp)).toBe('2024-01-15 12:30:45') }) it('should use custom format', () => { const timestamp = new Date('2024-01-15 12:30:45').getTime() expect(formatDateTime(timestamp, 'YYYY年MM月DD日 HH:mm')).toBe('2024年01月15日 12:30') }) }) describe('formatTime', () => { it('should format timestamp to time string', () => { const timestamp = new Date('2024-01-15 12:30:45').getTime() expect(formatTime(timestamp)).toBe('12:30:45') }) it('should use custom format', () => { const timestamp = new Date('2024-01-15 12:30:45').getTime() expect(formatTime(timestamp, 'HH:mm')).toBe('12:30') }) }) describe('formatRelativeTime', () => { it('should return "刚刚" for very recent time', () => { const timestamp = Date.now() - 1000 // 1秒前 expect(formatRelativeTime(timestamp)).toBe('刚刚') }) it('should return minutes ago', () => { const timestamp = Date.now() - 5 * 60 * 1000 // 5分钟前 expect(formatRelativeTime(timestamp)).toBe('5分钟前') }) it('should return hours ago', () => { const timestamp = Date.now() - 2 * 60 * 60 * 1000 // 2小时前 expect(formatRelativeTime(timestamp)).toBe('2小时前') }) it('should return days ago', () => { const timestamp = Date.now() - 3 * 24 * 60 * 60 * 1000 // 3天前 expect(formatRelativeTime(timestamp)).toBe('3天前') }) it('should return formatted date for old time', () => { const timestamp = Date.now() - 10 * 24 * 60 * 60 * 1000 // 10天前 expect(formatRelativeTime(timestamp)).toMatch(/\d{4}-\d{2}-\d{2}/) }) }) describe('formatFileSize', () => { it('should format bytes', () => { expect(formatFileSize(512)).toBe('512 B') }) it('should format KB', () => { expect(formatFileSize(1024)).toBe('1.0 KB') expect(formatFileSize(1536)).toBe('1.5 KB') }) it('should format MB', () => { expect(formatFileSize(1024 * 1024)).toBe('1.0 MB') expect(formatFileSize(1024 * 1024 * 2.5)).toBe('2.5 MB') }) it('should format GB', () => { expect(formatFileSize(1024 * 1024 * 1024)).toBe('1.0 GB') }) it('should handle zero size', () => { expect(formatFileSize(0)).toBe('0 B') }) it('should handle negative size', () => { expect(formatFileSize(-1024)).toBe('0 B') }) }) describe('formatNumber', () => { it('should format number with default options', () => { expect(formatNumber(1234.567)).toBe('1,234.567') }) it('should format number with custom decimal places', () => { expect(formatNumber(1234.567, { decimals: 2 })).toBe('1,234.57') }) it('should format number without separator', () => { expect(formatNumber(1234.567, { separator: false })).toBe('1234.567') }) it('should handle zero', () => { expect(formatNumber(0)).toBe('0') }) it('should handle negative numbers', () => { expect(formatNumber(-1234.567)).toBe('-1,234.567') }) }) describe('formatCurrency', () => { it('should format currency with default options', () => { expect(formatCurrency(1234.56)).toBe('¥1,234.56') }) it('should format currency with custom symbol', () => { expect(formatCurrency(1234.56, { symbol: '$' })).toBe('$1,234.56') }) it('should format currency with custom decimal places', () => { expect(formatCurrency(1234.567, { decimals: 3 })).toBe('¥1,234.567') }) }) describe('maskPhone', () => { it('should mask phone number', () => { expect(maskPhone('13812345678')).toBe('138****5678') }) it('should handle short phone number', () => { expect(maskPhone('12345')).toBe('12345') }) it('should handle empty phone number', () => { expect(maskPhone('')).toBe('') }) it('should handle null/undefined', () => { expect(maskPhone(null)).toBe('') expect(maskPhone(undefined)).toBe('') }) }) describe('maskEmail', () => { it('should mask email address', () => { expect(maskEmail('test@example.com')).toBe('t***@example.com') }) it('should handle short email', () => { expect(maskEmail('a@b.c')).toBe('a***@b.c') }) it('should handle invalid email', () => { expect(maskEmail('invalid-email')).toBe('invalid-email') }) it('should handle empty email', () => { expect(maskEmail('')).toBe('') }) }) describe('truncateText', () => { it('should truncate long text', () => { const text = 'This is a very long text that should be truncated' expect(truncateText(text, 20)).toBe('This is a very long...') }) it('should not truncate short text', () => { const text = 'Short text' expect(truncateText(text, 20)).toBe('Short text') }) it('should use custom suffix', () => { const text = 'This is a very long text' expect(truncateText(text, 10, '---')).toBe('This is a---') }) it('should handle empty text', () => { expect(truncateText('', 10)).toBe('') }) it('should handle zero length', () => { expect(truncateText('Hello', 0)).toBe('...') }) }) })