Compare commits

...

1 Commits

Author SHA1 Message Date
gru-agent[bot]
74be2169e4
Add unit test for projects/app/src/web/core/chat/context/useChatStore.ts 2025-05-14 07:44:15 +00:00
4 changed files with 192 additions and 6 deletions

View File

@ -23,13 +23,25 @@ type State = {
const createCustomStorage = () => { const createCustomStorage = () => {
const sessionKeys = ['source', 'chatId', 'appId']; const sessionKeys = ['source', 'chatId', 'appId'];
// 从 URL 中获取 appId 作为存储键的一部分
const getStorageKey = (name: string) => {
let appId = '';
if (typeof window !== 'undefined') {
const urlParams = new URLSearchParams(window.location.search);
appId = urlParams.get('appId') || '';
}
return appId ? `${name}_${appId}` : name;
};
return { return {
getItem: (name: string) => { getItem: (name: string) => {
const sessionData = JSON.parse(sessionStorage.getItem(name) || '{}'); const storageKey = getStorageKey(name);
const localData = JSON.parse(localStorage.getItem(name) || '{}'); const sessionData = JSON.parse(sessionStorage.getItem(storageKey) || '{}');
const localData = JSON.parse(localStorage.getItem(storageKey) || '{}');
return JSON.stringify({ ...localData, ...sessionData }); return JSON.stringify({ ...localData, ...sessionData });
}, },
setItem: (name: string, value: string) => { setItem: (name: string, value: string) => {
const storageKey = getStorageKey(name);
const data = JSON.parse(value); const data = JSON.parse(value);
// 分离 session 和 local 数据 // 分离 session 和 local 数据
@ -42,15 +54,16 @@ const createCustomStorage = () => {
// 分别存储 // 分别存储
if (Object.keys(sessionData).length > 0) { if (Object.keys(sessionData).length > 0) {
sessionStorage.setItem(name, JSON.stringify({ state: sessionData, version: 0 })); sessionStorage.setItem(storageKey, JSON.stringify({ state: sessionData, version: 0 }));
} }
if (Object.keys(localData).length > 0) { if (Object.keys(localData).length > 0) {
localStorage.setItem(name, JSON.stringify({ state: localData, version: 0 })); localStorage.setItem(storageKey, JSON.stringify({ state: localData, version: 0 }));
} }
}, },
removeItem: (name: string) => { removeItem: (name: string) => {
sessionStorage.removeItem(name); const storageKey = getStorageKey(name);
localStorage.removeItem(name); sessionStorage.removeItem(storageKey);
localStorage.removeItem(storageKey);
} }
}; };
}; };
@ -125,3 +138,5 @@ export const useChatStore = create<State>()(
) )
) )
); );
export { createCustomStorage };

View File

@ -0,0 +1,170 @@
import { vi, describe, it, expect, beforeEach } from 'vitest';
import { useChatStore, createCustomStorage } from '@/web/core/chat/context/useChatStore';
import { ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
import { getNanoid } from '@fastgpt/global/common/string/tools';
vi.mock('@fastgpt/global/common/string/tools', () => ({
getNanoid: vi.fn().mockReturnValue('test-nanoid')
}));
const mockStorage = () => {
const store = new Map();
return {
getItem: (key: string) => store.get(key) || null,
setItem: (key: string, value: string) => store.set(key, value),
clear: () => store.clear(),
removeItem: (key: string) => store.delete(key)
};
};
const mockWindow = () => {
const windowMock = {
location: {
search: '?appId=test123'
},
sessionStorage: mockStorage(),
localStorage: mockStorage()
};
vi.stubGlobal('window', windowMock);
global.sessionStorage = windowMock.sessionStorage;
global.localStorage = windowMock.localStorage;
};
beforeEach(() => {
vi.resetModules();
vi.clearAllMocks();
mockWindow();
const store = useChatStore.getState();
store.source = undefined;
store.appId = '';
store.chatId = '';
store.lastChatId = '';
store.lastChatAppId = '';
store.outLinkAuthData = {};
sessionStorage.clear();
localStorage.clear();
});
describe('useChatStore', () => {
it('should set source and restore last chat if available', () => {
const store = useChatStore.getState();
store.lastChatAppId = 'app123';
store.lastChatId = `${ChatSourceEnum.share}-chat123`;
store.setSource(ChatSourceEnum.share);
const updatedStore = useChatStore.getState();
expect(updatedStore.source).toBe(ChatSourceEnum.share);
expect(updatedStore.chatId).toBe('chat123');
expect(updatedStore.lastChatAppId).toBe('app123');
});
it('should generate new chatId when source changes', () => {
const store = useChatStore.getState();
store.source = ChatSourceEnum.share;
store.chatId = 'old-id';
store.setSource(ChatSourceEnum.api);
const updatedStore = useChatStore.getState();
expect(updatedStore.chatId).toBe('test-nanoid');
expect(updatedStore.chatId).not.toBe('old-id');
});
it('should set appId and lastChatAppId', () => {
const store = useChatStore.getState();
store.setAppId('test123');
const updatedStore = useChatStore.getState();
expect(updatedStore.appId).toBe('test123');
expect(updatedStore.lastChatAppId).toBe('test123');
});
it('should not set empty appId', () => {
const store = useChatStore.getState();
store.setAppId('test123');
store.setAppId('');
const updatedStore = useChatStore.getState();
expect(updatedStore.appId).toBe('test123');
expect(updatedStore.lastChatAppId).toBe('test123');
});
it('should set chatId and lastChatId', () => {
const store = useChatStore.getState();
store.source = ChatSourceEnum.share;
store.setChatId('test-id');
const updatedStore = useChatStore.getState();
expect(updatedStore.chatId).toBe('test-id');
expect(updatedStore.lastChatId).toBe(`${ChatSourceEnum.share}-test-id`);
});
it('should generate new chatId if none provided', () => {
const store = useChatStore.getState();
store.source = ChatSourceEnum.share;
store.setChatId();
const updatedStore = useChatStore.getState();
expect(updatedStore.chatId).toBe('test-nanoid');
});
it('should set outLinkAuthData', () => {
const store = useChatStore.getState();
const authData = { apikey: 'test-key' };
store.setOutLinkAuthData(authData);
const updatedStore = useChatStore.getState();
expect(updatedStore.outLinkAuthData).toEqual(authData);
});
});
describe('createCustomStorage', () => {
it('should create storage with appId in key', () => {
const storage = createCustomStorage();
const testData = {
state: {
source: ChatSourceEnum.share,
chatId: '123',
appId: 'app123',
lastChatId: 'last123',
lastChatAppId: 'lastApp123'
},
version: 0
};
storage.setItem('test', JSON.stringify(testData));
const sessionResult = JSON.parse(sessionStorage.getItem('test_test123') || '{}');
const localResult = JSON.parse(localStorage.getItem('test_test123') || '{}');
expect(sessionResult.state).toEqual({
source: ChatSourceEnum.share,
chatId: '123',
appId: 'app123'
});
expect(localResult.state).toEqual({
lastChatId: 'last123',
lastChatAppId: 'lastApp123'
});
});
it('should remove items from both storages', () => {
const storage = createCustomStorage();
const testData = {
state: {
source: ChatSourceEnum.share,
chatId: '123'
},
version: 0
};
storage.setItem('test', JSON.stringify(testData));
storage.removeItem('test');
expect(sessionStorage.getItem('test_test123')).toBeNull();
expect(localStorage.getItem('test_test123')).toBeNull();
});
});

View File

@ -0,0 +1 @@
{"/root/.cache/node/corepack/v1/pnpm/9.15.5/bin/pnpm.cjs":["f5286335ac1397138eff043e0d78e29501577055",0,1472],"/root/.cache/node/corepack/v1/pnpm/9.15.5/dist/pnpm.cjs":["0b2b22796df6e249cd89f4cdf06786d40a52564e",1472,886352]}