/** * config.ts 配置解析模块单元测试 */ import { describe, it, expect } from 'vitest'; import { parseConfig } from '../src/config'; const validConfig = { integrateId: '123', requestDomain: 'https://api.example.com', }; describe('parseConfig - 必传参数校验', () => { it('缺少 integrateId 返回 null', () => { expect(parseConfig({ requestDomain: 'https://api.example.com' } as never)).toBeNull(); }); it('integrateId 为空字符串返回 null', () => { expect(parseConfig({ integrateId: '', requestDomain: 'https://api.example.com' })).toBeNull(); }); it('缺少 requestDomain 返回 null', () => { expect(parseConfig({ integrateId: '123' } as never)).toBeNull(); }); it('requestDomain 不是合法 URL 返回 null', () => { expect(parseConfig({ integrateId: '123', requestDomain: 'not-a-url' })).toBeNull(); }); it('合法配置正常解析', () => { const result = parseConfig(validConfig); expect(result).not.toBeNull(); expect(result!.integrateId).toBe('123'); expect(result!.requestDomain).toBe('https://api.example.com'); }); it('数字 integrateId 转为字符串', () => { const result = parseConfig({ integrateId: 42, requestDomain: 'https://api.example.com' }); expect(result!.integrateId).toBe('42'); }); }); describe('parseConfig - 默认值填充', () => { it('width 默认 500', () => { const result = parseConfig(validConfig); expect(result!.width).toBe(500); }); it('height 默认 520', () => { const result = parseConfig(validConfig); expect(result!.height).toBe(520); }); it('height 最小值 400', () => { const result = parseConfig({ ...validConfig, height: 100 }); expect(result!.height).toBe(400); }); it('title 默认 "AI 智能助手"', () => { const result = parseConfig(validConfig); expect(result!.title).toBe('AI 智能助手'); }); it('theme 默认 light', () => { const result = parseConfig(validConfig); expect(result!.theme).toBe('light'); }); it('theme dark 正常解析', () => { const result = parseConfig({ ...validConfig, theme: 'dark' }); expect(result!.theme).toBe('dark'); }); it('streaming 默认 true', () => { const result = parseConfig(validConfig); expect(result!.streaming).toBe(true); }); it('debug 默认 true', () => { const result = parseConfig(validConfig); expect(result!.debug).toBe(true); }); it('sound 默认 false', () => { const result = parseConfig(validConfig); expect(result!.sound).toBe(false); }); it('notification 默认 false', () => { const result = parseConfig(validConfig); expect(result!.notification).toBe(false); }); it('quickReplies 默认空数组', () => { const result = parseConfig(validConfig); expect(result!.quickReplies).toEqual([]); }); it('quickReplies 过滤空字符串', () => { const result = parseConfig({ ...validConfig, quickReplies: ['你好', '', ' ', '世界'] }); expect(result!.quickReplies).toEqual(['你好', '世界']); }); it('requestDomain 去除末尾斜杠', () => { const result = parseConfig({ ...validConfig, requestDomain: 'https://api.example.com///' }); expect(result!.requestDomain).toBe('https://api.example.com'); }); it('position 仅接受两个合法值', () => { expect(parseConfig({ ...validConfig, position: 'left-bottom' })!.position).toBe('left-bottom'); expect(parseConfig({ ...validConfig, position: 'right-bottom' })!.position).toBe('right-bottom'); expect(parseConfig({ ...validConfig, position: 'top' as never })!.position).toBe('right-bottom'); }); }); describe('parseConfig - 回调函数', () => { it('onError 回调正常保留', () => { const onError = () => {}; const result = parseConfig({ ...validConfig, onError }); expect(result!.onError).toBe(onError); }); it('非函数的 onError 被忽略', () => { const result = parseConfig({ ...validConfig, onError: 'not-a-function' as never }); expect(result!.onError).toBeUndefined(); }); it('onReady / onMessage 回调正常保留', () => { const onReady = () => {}; const onMessage = () => {}; const result = parseConfig({ ...validConfig, onReady, onMessage }); expect(result!.onReady).toBe(onReady); expect(result!.onMessage).toBe(onMessage); }); }); describe('parseConfig - 鉴权参数(token / expiresIn / getToken / tokenStrategy / tokenUrl)', () => { it('合法的 token 与 expiresIn 正常保留', () => { const result = parseConfig({ ...validConfig, token: ' eyJhbGci ', expiresIn: 7200 }); expect(result!.token).toBe('eyJhbGci'); // 去除首尾空白 expect(result!.expiresIn).toBe(7200); }); it('token 非字符串时忽略', () => { const result = parseConfig({ ...validConfig, token: 123 as never }); expect(result!.token).toBeUndefined(); }); it('token 为空白串时忽略', () => { const result = parseConfig({ ...validConfig, token: ' ' }); expect(result!.token).toBeUndefined(); }); it('expiresIn 非正数或非数字时忽略', () => { expect(parseConfig({ ...validConfig, expiresIn: 0 })!.expiresIn).toBeUndefined(); expect(parseConfig({ ...validConfig, expiresIn: -5 })!.expiresIn).toBeUndefined(); expect(parseConfig({ ...validConfig, expiresIn: '7200' as never })!.expiresIn).toBeUndefined(); }); it('getToken 非函数时忽略', () => { const result = parseConfig({ ...validConfig, getToken: 'not-a-function' as never }); expect(result!.getToken).toBeUndefined(); }); it('tokenStrategy 默认 expiry', () => { expect(parseConfig(validConfig)!.tokenStrategy).toBe('expiry'); }); it('tokenStrategy 接受 always,非法值回退 expiry', () => { expect(parseConfig({ ...validConfig, tokenStrategy: 'always' })!.tokenStrategy).toBe('always'); expect(parseConfig({ ...validConfig, tokenStrategy: 'everyRequest' as never })!.tokenStrategy).toBe('expiry'); }); it('tokenUrl 去空白保留,非法值忽略', () => { expect(parseConfig({ ...validConfig, tokenUrl: ' /api/sdk-token ' })!.tokenUrl).toBe('/api/sdk-token'); expect(parseConfig({ ...validConfig, tokenUrl: ' ' })!.tokenUrl).toBeUndefined(); expect(parseConfig({ ...validConfig, tokenUrl: 42 as never })!.tokenUrl).toBeUndefined(); }); it('getToken 与 tokenUrl 同时配置时 getToken 优先,tokenUrl 被忽略', () => { const getToken = async () => 'token'; const result = parseConfig({ ...validConfig, getToken, tokenUrl: '/api/sdk-token' }); expect(result!.getToken).toBe(getToken); expect(result!.tokenUrl).toBeUndefined(); }); });