| @@ -0,0 +1,90 @@ | |||
| import { renderHook } from '@testing-library/react' | |||
| import { useLanguage } from './hooks' | |||
| import { useContext } from 'use-context-selector' | |||
| import { after } from 'node:test' | |||
| jest.mock('swr', () => ({ | |||
| __esModule: true, | |||
| default: jest.fn(), // mock useSWR | |||
| useSWRConfig: jest.fn(), | |||
| })) | |||
| // mock use-context-selector | |||
| jest.mock('use-context-selector', () => ({ | |||
| useContext: jest.fn(), | |||
| })) | |||
| // mock service/common functions | |||
| jest.mock('@/service/common', () => ({ | |||
| fetchDefaultModal: jest.fn(), | |||
| fetchModelList: jest.fn(), | |||
| fetchModelProviderCredentials: jest.fn(), | |||
| fetchModelProviders: jest.fn(), | |||
| getPayUrl: jest.fn(), | |||
| })) | |||
| // mock context hooks | |||
| jest.mock('@/context/i18n', () => ({ | |||
| __esModule: true, | |||
| default: jest.fn(), | |||
| })) | |||
| jest.mock('@/context/provider-context', () => ({ | |||
| useProviderContext: jest.fn(), | |||
| })) | |||
| jest.mock('@/context/modal-context', () => ({ | |||
| useModalContextSelector: jest.fn(), | |||
| })) | |||
| jest.mock('@/context/event-emitter', () => ({ | |||
| useEventEmitterContextContext: jest.fn(), | |||
| })) | |||
| // mock plugins | |||
| jest.mock('@/app/components/plugins/marketplace/hooks', () => ({ | |||
| useMarketplacePlugins: jest.fn(), | |||
| })) | |||
| jest.mock('@/app/components/plugins/marketplace/utils', () => ({ | |||
| getMarketplacePluginsByCollectionId: jest.fn(), | |||
| })) | |||
| jest.mock('./provider-added-card', () => { | |||
| // eslint-disable-next-line no-labels, ts/no-unused-expressions | |||
| UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST: [] | |||
| }) | |||
| after(() => { | |||
| jest.resetModules() | |||
| jest.clearAllMocks() | |||
| }) | |||
| describe('useLanguage', () => { | |||
| it('should replace hyphen with underscore in locale', () => { | |||
| (useContext as jest.Mock).mockReturnValue({ | |||
| locale: 'en-US', | |||
| }) | |||
| const { result } = renderHook(() => useLanguage()) | |||
| expect(result.current).toBe('en_US') | |||
| }) | |||
| it('should return locale as is if no hyphen exists', () => { | |||
| (useContext as jest.Mock).mockReturnValue({ | |||
| locale: 'enUS', | |||
| }) | |||
| const { result } = renderHook(() => useLanguage()) | |||
| expect(result.current).toBe('enUS') | |||
| }) | |||
| it('should handle multiple hyphens', () => { | |||
| // Mock the I18n context return value | |||
| (useContext as jest.Mock).mockReturnValue({ | |||
| locale: 'zh-Hans-CN', | |||
| }) | |||
| const { result } = renderHook(() => useLanguage()) | |||
| expect(result.current).toBe('zh_Hans-CN') | |||
| }) | |||
| }) | |||
| @@ -0,0 +1,93 @@ | |||
| import { act, renderHook } from '@testing-library/react' | |||
| import useBreakpoints, { MediaType } from './use-breakpoints' | |||
| describe('useBreakpoints', () => { | |||
| const originalInnerWidth = window.innerWidth | |||
| // Mock the window resize event | |||
| const fireResize = (width: number) => { | |||
| window.innerWidth = width | |||
| act(() => { | |||
| window.dispatchEvent(new Event('resize')) | |||
| }) | |||
| } | |||
| // Restore the original innerWidth after tests | |||
| afterAll(() => { | |||
| window.innerWidth = originalInnerWidth | |||
| }) | |||
| it('should return mobile for width <= 640px', () => { | |||
| // Mock window.innerWidth for mobile | |||
| Object.defineProperty(window, 'innerWidth', { | |||
| writable: true, | |||
| configurable: true, | |||
| value: 640, | |||
| }) | |||
| const { result } = renderHook(() => useBreakpoints()) | |||
| expect(result.current).toBe(MediaType.mobile) | |||
| }) | |||
| it('should return tablet for width > 640px and <= 768px', () => { | |||
| // Mock window.innerWidth for tablet | |||
| Object.defineProperty(window, 'innerWidth', { | |||
| writable: true, | |||
| configurable: true, | |||
| value: 768, | |||
| }) | |||
| const { result } = renderHook(() => useBreakpoints()) | |||
| expect(result.current).toBe(MediaType.tablet) | |||
| }) | |||
| it('should return pc for width > 768px', () => { | |||
| // Mock window.innerWidth for pc | |||
| Object.defineProperty(window, 'innerWidth', { | |||
| writable: true, | |||
| configurable: true, | |||
| value: 1024, | |||
| }) | |||
| const { result } = renderHook(() => useBreakpoints()) | |||
| expect(result.current).toBe(MediaType.pc) | |||
| }) | |||
| it('should update media type when window resizes', () => { | |||
| // Start with desktop | |||
| Object.defineProperty(window, 'innerWidth', { | |||
| writable: true, | |||
| configurable: true, | |||
| value: 1024, | |||
| }) | |||
| const { result } = renderHook(() => useBreakpoints()) | |||
| expect(result.current).toBe(MediaType.pc) | |||
| // Resize to tablet | |||
| fireResize(768) | |||
| expect(result.current).toBe(MediaType.tablet) | |||
| // Resize to mobile | |||
| fireResize(600) | |||
| expect(result.current).toBe(MediaType.mobile) | |||
| }) | |||
| it('should clean up event listeners on unmount', () => { | |||
| // Spy on addEventListener and removeEventListener | |||
| const addEventListenerSpy = jest.spyOn(window, 'addEventListener') | |||
| const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener') | |||
| const { unmount } = renderHook(() => useBreakpoints()) | |||
| // Unmount should trigger cleanup | |||
| unmount() | |||
| expect(addEventListenerSpy).toHaveBeenCalledWith('resize', expect.any(Function)) | |||
| expect(removeEventListenerSpy).toHaveBeenCalledWith('resize', expect.any(Function)) | |||
| // Clean up spies | |||
| addEventListenerSpy.mockRestore() | |||
| removeEventListenerSpy.mockRestore() | |||
| }) | |||
| }) | |||
| @@ -98,7 +98,7 @@ const config: Config = { | |||
| // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module | |||
| moduleNameMapper: { | |||
| '^@/components/(.*)$': '<rootDir>/components/$1', | |||
| '^@/(.*)$': '<rootDir>/$1', | |||
| '^lodash-es$': 'lodash', | |||
| }, | |||
| @@ -133,7 +133,7 @@ const config: Config = { | |||
| // restoreMocks: false, | |||
| // The root directory that Jest should scan for tests and modules within | |||
| // rootDir: undefined, | |||
| rootDir: './', | |||
| // A list of paths to directories that Jest should use to search for files in | |||
| // roots: [ | |||