UNPKG

@lobehub/chat

Version:

Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.

195 lines (155 loc) 5.19 kB
import { renderHook } from '@testing-library/react'; import { uniq } from 'lodash-es'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { HOTKEYS_REGISTRATION } from '@/const/hotkeys'; import { HotkeyEnum, HotkeyScopeEnum } from '@/types/hotkey'; import { useHotkeyById } from './useHotkeyById'; // Mock dependencies vi.mock('lodash-es', async (importOriginal) => { const actual: any = await importOriginal(); return { ...actual, uniq: vi.fn((arr) => [...new Set(arr)]), }; }); // Mock react-hotkeys-hook const mockRef = { current: document.createElement('div') }; const mockUseHotkeys = vi.fn(() => mockRef); vi.mock('react-hotkeys-hook', () => ({ // @ts-ignore useHotkeys: (...args: any[]) => mockUseHotkeys(...args), })); // Mock store and environment let isMobileValue = false; const mockHotkey = 'mod+k'; vi.mock('@/store/serverConfig', () => ({ useServerConfigStore: (selector: (state: any) => any) => selector({ isMobile: isMobileValue }), })); vi.mock('@/store/user', () => ({ useUserStore: (selector: any) => selector(), })); vi.mock('@/store/user/selectors', () => ({ settingsSelectors: { getHotkeyById: () => () => mockHotkey, }, })); vi.mock('@/utils/env', () => ({ isDev: false, })); describe('useHotkeyById', () => { const mockCallback = vi.fn(); beforeEach(() => { vi.clearAllMocks(); isMobileValue = false; }); it('should register hotkey with correct parameters', () => { const { result } = renderHook(() => useHotkeyById(HotkeyEnum.Search, mockCallback)); // 验证 useHotkeys 被调用,但不检查具体函数引用 expect(mockUseHotkeys).toHaveBeenCalled(); // 获取实际调用参数 const callArgs: any = mockUseHotkeys.mock.calls[0]; // 验证第一个参数是正确的热键 expect(callArgs[0]).toBe(mockHotkey); // 验证第二个参数是函数 expect(typeof callArgs[1]).toBe('function'); // 验证第三个参数包含预期的属性 expect(callArgs[2]).toMatchObject({ enableOnFormTags: true, preventDefault: true, scopes: [HotkeyEnum.Search, HotkeyScopeEnum.Global], }); // 验证第四个参数是 undefined expect(callArgs[3]).toBeUndefined(); // 验证返回值 expect(result.current).toEqual({ id: HotkeyEnum.Search, ref: mockRef, }); }); it('should disable hotkey on mobile devices', () => { // Set as mobile isMobileValue = true; renderHook(() => useHotkeyById(HotkeyEnum.Search, mockCallback, { enabled: true })); expect(mockUseHotkeys).toHaveBeenCalledWith( mockHotkey, expect.any(Function), expect.objectContaining({ enabled: false, // Should be disabled on mobile }), undefined, ); }); it('should handle options parameter correctly', () => { const options = { enabled: true, scopes: ['customScope'], }; renderHook(() => useHotkeyById(HotkeyEnum.Search, mockCallback, options)); expect(mockUseHotkeys).toHaveBeenCalledWith( mockHotkey, expect.any(Function), expect.objectContaining({ enabled: true, scopes: expect.arrayContaining([HotkeyEnum.Search, HotkeyScopeEnum.Global, 'customScope']), }), undefined, ); expect(uniq).toHaveBeenCalled(); }); it('should handle dependencies parameter correctly', () => { const deps = [1, 2, 3]; renderHook(() => useHotkeyById(HotkeyEnum.Search, mockCallback, deps)); expect(mockUseHotkeys).toHaveBeenCalledWith( mockHotkey, expect.any(Function), expect.any(Object), deps, ); }); it('should handle both options and dependencies correctly', () => { const options = { enabled: true }; const deps = [1, 2, 3]; renderHook(() => useHotkeyById(HotkeyEnum.Search, mockCallback, options, deps)); expect(mockUseHotkeys).toHaveBeenCalledWith( mockHotkey, expect.any(Function), expect.objectContaining({ enabled: true, }), deps, ); }); it('should combine scopes from registration and options', () => { const testHotkeyId = HotkeyEnum.ToggleLeftPanel; const registrationItem = HOTKEYS_REGISTRATION.find((item) => item.id === testHotkeyId); const options = { scopes: ['customScope'], }; renderHook(() => useHotkeyById(testHotkeyId, mockCallback, options)); expect(mockUseHotkeys).toHaveBeenCalledWith( mockHotkey, expect.any(Function), expect.objectContaining({ scopes: expect.arrayContaining([ testHotkeyId, ...(registrationItem?.scopes || []), 'customScope', ]), }), undefined, ); }); it('should handle case when no registration item is found', () => { // Using a non-existent ID to test this case const nonExistentId = 'nonExistentId' as any; renderHook(() => useHotkeyById(nonExistentId, mockCallback)); expect(mockUseHotkeys).toHaveBeenCalledWith( mockHotkey, expect.any(Function), expect.objectContaining({ scopes: expect.arrayContaining([nonExistentId]), }), undefined, ); }); });