forked from wangziqi/gongxue-base
Squash merge PR #23. Included changes: - complete occupancy check-in required fields/default payload - improve responsive admin management pages - fix attendance edge cases and attendance period config - refine wallet/finance-related workflow handling Checks: - npm run typecheck -w apps/admin - npm run typecheck -w apps/server
108 lines
3.8 KiB
TypeScript
108 lines
3.8 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import {
|
|
shouldAutoSwapBaseUrl,
|
|
formatDateTime,
|
|
sourceLabel,
|
|
sourceColor,
|
|
PROVIDER_DEFAULTS,
|
|
extractErrorMessage,
|
|
} from './helpers';
|
|
|
|
describe('AiConfig helpers', () => {
|
|
describe('shouldAutoSwapBaseUrl', () => {
|
|
it('swaps to default on first provider selection', () => {
|
|
const result = shouldAutoSwapBaseUrl('DEEPSEEK', '', null);
|
|
expect(result.shouldSwap).toBe(true);
|
|
expect(result.baseUrl).toBe(PROVIDER_DEFAULTS.DEEPSEEK);
|
|
});
|
|
|
|
it('swaps when current baseUrl matches previous provider default', () => {
|
|
const result = shouldAutoSwapBaseUrl('DEEPSEEK', 'https://api.openai.com/v1', 'OPENAI');
|
|
expect(result.shouldSwap).toBe(true);
|
|
expect(result.baseUrl).toBe(PROVIDER_DEFAULTS.DEEPSEEK);
|
|
});
|
|
|
|
it('swaps when current baseUrl is empty', () => {
|
|
const result = shouldAutoSwapBaseUrl('DEEPSEEK', '', 'OPENAI');
|
|
expect(result.shouldSwap).toBe(true);
|
|
});
|
|
|
|
it('keeps custom baseUrl unchanged', () => {
|
|
const result = shouldAutoSwapBaseUrl('OPENAI', 'https://custom.api.com/v1', 'DEEPSEEK');
|
|
expect(result.shouldSwap).toBe(false);
|
|
expect(result.baseUrl).toBe('https://custom.api.com/v1');
|
|
});
|
|
});
|
|
|
|
describe('formatDateTime', () => {
|
|
it('returns hyphen for null', () => {
|
|
expect(formatDateTime(null)).toBe('-');
|
|
});
|
|
|
|
it('returns Chinese locale string for ISO date', () => {
|
|
expect(formatDateTime('2024-01-15T10:30:00Z')).toContain('2024');
|
|
});
|
|
});
|
|
|
|
describe('sourceLabel', () => {
|
|
it('returns Chinese labels', () => {
|
|
expect(sourceLabel('database')).toBe('数据库');
|
|
expect(sourceLabel('environment')).toBe('环境变量');
|
|
expect(sourceLabel('none')).toBe('未配置');
|
|
});
|
|
});
|
|
|
|
describe('sourceColor', () => {
|
|
it('returns correct colors', () => {
|
|
expect(sourceColor('database')).toBe('green');
|
|
expect(sourceColor('environment')).toBe('blue');
|
|
expect(sourceColor('none')).toBe('default');
|
|
});
|
|
});
|
|
|
|
describe('extractErrorMessage', () => {
|
|
it('extracts message from server error response (interceptor unwraps to { message })', () => {
|
|
// The Axios interceptor at api/index.ts does Promise.reject(err.response?.data || err).
|
|
// For server errors, the rejection value is err.response.data — typically { message: '...' }.
|
|
const err = { message: 'API出错' };
|
|
expect(extractErrorMessage(err)).toBe('API出错');
|
|
});
|
|
|
|
it('falls back to message property', () => {
|
|
const err = { message: 'Network error' };
|
|
expect(extractErrorMessage(err)).toBe('Network error');
|
|
});
|
|
|
|
it('falls back to default on unknown type', () => {
|
|
expect(extractErrorMessage('unknown string')).toBe('操作失败');
|
|
expect(extractErrorMessage(null)).toBe('操作失败');
|
|
expect(extractErrorMessage(undefined)).toBe('操作失败');
|
|
});
|
|
|
|
it('sanitizes: newlines replaced with spaces', () => {
|
|
const err = { message: 'line1\nline2\r\nline3' };
|
|
expect(extractErrorMessage(err)).toBe('line1 line2 line3');
|
|
});
|
|
|
|
it('sanitizes: message > 120 chars truncated with ellipsis', () => {
|
|
const long = 'x'.repeat(200);
|
|
const err = { message: long };
|
|
const result = extractErrorMessage(err);
|
|
expect(result).toHaveLength(121); // 120 + '…' (1 char)
|
|
expect(result.endsWith('\u2026')).toBe(true);
|
|
});
|
|
|
|
it('sanitizes: empty trimmed message falls back', () => {
|
|
const err = { message: ' ' };
|
|
expect(extractErrorMessage(err)).toBe('操作失败');
|
|
});
|
|
|
|
it('sanitizes: plain object message property sanitized', () => {
|
|
const err = {
|
|
message: ' some \n\nerror \r\nmessage ',
|
|
};
|
|
expect(extractErrorMessage(err)).toBe('some error message');
|
|
});
|
|
});
|
|
});
|