import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest' import { getDeviceFingerprint, clearDeviceFingerprint, } from './device-fingerprint' describe('device-fingerprint', () => { // 保存原始 navigator const originalNavigator = global.navigator beforeEach(() => { // 清除缓存 clearDeviceFingerprint() vi.clearAllMocks() }) afterEach(() => { clearDeviceFingerprint() global.navigator = originalNavigator }) describe('getDeviceFingerprint', () => { it('should return a device fingerprint object', () => { const fingerprint = getDeviceFingerprint() expect(fingerprint).toBeDefined() expect(fingerprint).toHaveProperty('device_id') expect(fingerprint).toHaveProperty('device_name') expect(fingerprint).toHaveProperty('device_browser') expect(fingerprint).toHaveProperty('device_os') }) it('should return the same fingerprint on multiple calls (singleton)', () => { const fingerprint1 = getDeviceFingerprint() const fingerprint2 = getDeviceFingerprint() expect(fingerprint1).toBe(fingerprint2) expect(fingerprint1.device_id).toBe(fingerprint2.device_id) }) it('should return valid device_id', () => { const fingerprint = getDeviceFingerprint() expect(fingerprint.device_id).toBeTruthy() expect(typeof fingerprint.device_id).toBe('string') expect(fingerprint.device_id.length).toBeGreaterThan(0) }) it('should return valid device_name format', () => { const fingerprint = getDeviceFingerprint() expect(fingerprint.device_name).toBeTruthy() expect(typeof fingerprint.device_name).toBe('string') // device_name 格式: "Browser on OS" expect(fingerprint.device_name).toMatch(/.+\s+on\s+.+/) }) it('should return valid device_browser', () => { const fingerprint = getDeviceFingerprint() expect(fingerprint.device_browser).toBeTruthy() expect(typeof fingerprint.device_browser).toBe('string') }) it('should return valid device_os', () => { const fingerprint = getDeviceFingerprint() expect(fingerprint.device_os).toBeTruthy() expect(typeof fingerprint.device_os).toBe('string') }) }) describe('clearDeviceFingerprint', () => { it('should clear cached fingerprint', () => { // 先获取一次生成缓存 const fingerprint1 = getDeviceFingerprint() // 清除缓存 clearDeviceFingerprint() // 再次获取应该是新的指纹 const fingerprint2 = getDeviceFingerprint() // 两个指纹不应该相同 expect(fingerprint1.device_id).not.toBe(fingerprint2.device_id) }) it('should allow multiple clears without error', () => { clearDeviceFingerprint() clearDeviceFingerprint() clearDeviceFingerprint() // 不应该抛出错误 expect(true).toBe(true) }) }) describe('browser detection', () => { it('should detect browser from user agent', () => { // 注意:实际测试中 navigator.userAgent 是只读的 // 这里主要验证函数能正常工作 const fingerprint = getDeviceFingerprint() expect(fingerprint.device_browser).toBeTruthy() }) }) describe('OS detection', () => { it('should detect OS from user agent', () => { // 类似浏览器检测,验证函数能正常工作 const fingerprint = getDeviceFingerprint() expect(fingerprint.device_os).toBeTruthy() }) }) describe('security considerations', () => { it('should not store fingerprint in localStorage', () => { getDeviceFingerprint() // 设备指纹不应该存储在 localStorage const deviceId = localStorage.getItem('device_id') const fingerprint = localStorage.getItem('device_fingerprint') expect(deviceId).toBeFalsy() // null or undefined expect(fingerprint).toBeFalsy() }) it('should not store fingerprint in sessionStorage', () => { getDeviceFingerprint() // 设备指纹不应该存储在 sessionStorage const deviceId = sessionStorage.getItem('device_id') const fingerprint = sessionStorage.getItem('device_fingerprint') expect(deviceId).toBeFalsy() expect(fingerprint).toBeFalsy() }) }) })