mirror of
https://github.com/labring/FastGPT.git
synced 2025-12-26 04:32:50 +00:00
* fix(api): 修复二级路由下的页面判断逻辑 在请求错误处理中,添加基础URL前缀以正确判断当前是否为外部链接页面。 * perf: use global var * remove invalid code * feat: response limit;perf: copy avatar image;perf: markdown parse (#5719) * feat: response limit * remove placeholder * perf: copy avatar image * perf: markdown parse * fix: child app cannot show cite * doc * fix: node template bugs (#5727) * add dataset search count track (#5721) * add dataset search count track * remove pro * change to track * remove unused * fix * perf: track code --------- Co-authored-by: archer <545436317@qq.com> * http response limit * deploy doc * fix: test * doc * remove invalid code * remove invalid code --------- Co-authored-by: 戴盛利 <1639499287@qq.com> Co-authored-by: heheer <heheer@sealos.io>
154 lines
4.7 KiB
TypeScript
154 lines
4.7 KiB
TypeScript
import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|
import {
|
|
maxQuantityMap,
|
|
checkMaxQuantity,
|
|
requestFinish,
|
|
checkRes,
|
|
responseError
|
|
} from '../../../../src/web/common/api/request';
|
|
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
|
import { TOKEN_ERROR_CODE } from '@fastgpt/global/common/error/errorCode';
|
|
|
|
// Mock all required dependencies
|
|
vi.mock('@fastgpt/web/common/system/utils', () => ({
|
|
getWebReqUrl: vi.fn().mockReturnValue('http://test.com'),
|
|
subRoute: '/test-route' // Add subRoute mock
|
|
}));
|
|
|
|
vi.mock('@/web/support/user/auth', () => ({
|
|
clearToken: vi.fn()
|
|
}));
|
|
|
|
vi.mock('../system/useSystemStore', () => ({
|
|
useSystemStore: {
|
|
getState: vi.fn().mockReturnValue({
|
|
setNotSufficientModalType: vi.fn()
|
|
})
|
|
}
|
|
}));
|
|
|
|
vi.mock('@fastgpt/web/i18n/utils', () => ({
|
|
i18nT: vi.fn().mockReturnValue('Unauthorized token')
|
|
}));
|
|
|
|
// Mock window.location
|
|
const mockLocation = {
|
|
pathname: '/test',
|
|
replace: vi.fn(),
|
|
search: ''
|
|
};
|
|
|
|
vi.stubGlobal('window', {
|
|
location: mockLocation
|
|
});
|
|
|
|
describe('request utils', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
Object.keys(maxQuantityMap).forEach((key) => delete maxQuantityMap[key]);
|
|
mockLocation.pathname = '/test';
|
|
});
|
|
|
|
describe('checkMaxQuantity', () => {
|
|
it('should return empty object when maxQuantity is not set', () => {
|
|
const result = checkMaxQuantity({ url: 'test', maxQuantity: undefined });
|
|
expect(result).toEqual({});
|
|
});
|
|
|
|
it('should handle first request', () => {
|
|
const result = checkMaxQuantity({ url: 'test', maxQuantity: 2 });
|
|
expect(result.id).toBeDefined();
|
|
expect(result.abortSignal).toBeDefined();
|
|
expect(maxQuantityMap['test']?.length).toBe(1);
|
|
});
|
|
|
|
it('should cancel oldest request when maxQuantity exceeded', () => {
|
|
const result1 = checkMaxQuantity({ url: 'test', maxQuantity: 2 });
|
|
const result2 = checkMaxQuantity({ url: 'test', maxQuantity: 2 });
|
|
const result3 = checkMaxQuantity({ url: 'test', maxQuantity: 2 });
|
|
|
|
expect(maxQuantityMap['test']?.length).toBe(2);
|
|
expect(maxQuantityMap['test']?.find((item) => item.id === result1.id)).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('requestFinish', () => {
|
|
it('should remove finished request', () => {
|
|
const { id } = checkMaxQuantity({ url: 'test', maxQuantity: 2 });
|
|
requestFinish({ signId: id, url: 'test' });
|
|
expect(maxQuantityMap['test']).toBeUndefined();
|
|
});
|
|
|
|
it('should handle non-existent request', () => {
|
|
requestFinish({ signId: 'non-existent', url: 'test' });
|
|
expect(maxQuantityMap['test']).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('checkRes', () => {
|
|
it('should return data for successful response', () => {
|
|
const response = { code: 200, data: 'test data', message: 'success' };
|
|
expect(checkRes(response)).toBe('test data');
|
|
});
|
|
|
|
it('should reject for error response', async () => {
|
|
const response = { code: 400, data: null, message: 'error' };
|
|
await expect(checkRes(response)).rejects.toEqual(response);
|
|
});
|
|
|
|
it('should reject for undefined response', async () => {
|
|
await expect(checkRes(undefined)).rejects.toBe('服务器异常');
|
|
});
|
|
});
|
|
|
|
describe('responseError', () => {
|
|
it('should handle token error for non-outlink page', async () => {
|
|
mockLocation.pathname = '/dashboard';
|
|
const err = {
|
|
response: {
|
|
data: {
|
|
code: Object.values(TOKEN_ERROR_CODE)[0]
|
|
}
|
|
}
|
|
};
|
|
await expect(responseError(err)).rejects.toEqual({
|
|
code: Object.values(TOKEN_ERROR_CODE)[0]
|
|
});
|
|
});
|
|
|
|
it('should handle token error for outlink page', async () => {
|
|
mockLocation.pathname = '/test-route/chat/share';
|
|
const err = {
|
|
response: {
|
|
data: {
|
|
code: Object.values(TOKEN_ERROR_CODE)[0]
|
|
}
|
|
}
|
|
};
|
|
await expect(responseError(err)).rejects.toEqual({
|
|
code: Object.values(TOKEN_ERROR_CODE)[0]
|
|
});
|
|
});
|
|
|
|
it('should handle team error', async () => {
|
|
const err = { response: { data: { statusText: TeamErrEnum.aiPointsNotEnough } } };
|
|
await expect(responseError(err)).rejects.toEqual({
|
|
statusText: TeamErrEnum.aiPointsNotEnough
|
|
});
|
|
});
|
|
|
|
it('should handle string error', async () => {
|
|
await expect(responseError('error message')).rejects.toEqual({ message: 'error message' });
|
|
});
|
|
|
|
it('should handle undefined error', async () => {
|
|
await expect(responseError(undefined)).rejects.toEqual({ message: '未知错误' });
|
|
});
|
|
|
|
it('should handle string data error', async () => {
|
|
const err = { response: { data: 'error string' } };
|
|
await expect(responseError(err)).rejects.toBe('error string');
|
|
});
|
|
});
|
|
});
|