mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-02-07 19:41:12 +08:00
* refactor(CodeEditor): improve props for clarity * refactor: update CodeEditor usage * refactor: change unwrapped to wrapped * fix: CodeViewer unwrap * refactor: simplify code viewer border radius, add comments
191 lines
5.4 KiB
TypeScript
191 lines
5.4 KiB
TypeScript
import { useWrapTool } from '@renderer/components/CodeToolbar/hooks/useWrapTool'
|
|
import { act, renderHook } from '@testing-library/react'
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
// Mock dependencies
|
|
const mocks = vi.hoisted(() => ({
|
|
i18n: {
|
|
t: vi.fn((key: string) => key)
|
|
},
|
|
useToolManager: vi.fn(),
|
|
TOOL_SPECS: {
|
|
wrap: {
|
|
id: 'wrap',
|
|
type: 'quick',
|
|
order: 13
|
|
}
|
|
}
|
|
}))
|
|
|
|
vi.mock('react-i18next', () => ({
|
|
useTranslation: () => ({
|
|
t: mocks.i18n.t
|
|
})
|
|
}))
|
|
|
|
vi.mock('@renderer/components/ActionTools', () => ({
|
|
TOOL_SPECS: mocks.TOOL_SPECS,
|
|
useToolManager: mocks.useToolManager
|
|
}))
|
|
|
|
// Mock useToolManager
|
|
const mockRegisterTool = vi.fn()
|
|
const mockRemoveTool = vi.fn()
|
|
mocks.useToolManager.mockImplementation(() => ({
|
|
registerTool: mockRegisterTool,
|
|
removeTool: mockRemoveTool
|
|
}))
|
|
|
|
vi.mock('lucide-react', () => ({
|
|
Text: () => <div data-testid="text-icon" />,
|
|
WrapText: () => <div data-testid="wrap-text-icon" />
|
|
}))
|
|
|
|
describe('useWrapTool', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
// Helper function to create mock props
|
|
const createMockProps = (overrides: Partial<Parameters<typeof useWrapTool>[0]> = {}) => {
|
|
const defaultProps = {
|
|
enabled: true,
|
|
wrapped: true,
|
|
wrappable: true,
|
|
toggle: vi.fn(),
|
|
setTools: vi.fn()
|
|
}
|
|
|
|
return { ...defaultProps, ...overrides }
|
|
}
|
|
|
|
// Helper function for tool registration assertions
|
|
const expectToolRegistration = (times: number, toolConfig?: object) => {
|
|
expect(mockRegisterTool).toHaveBeenCalledTimes(times)
|
|
if (times > 0 && toolConfig) {
|
|
expect(mockRegisterTool).toHaveBeenCalledWith(expect.objectContaining(toolConfig))
|
|
}
|
|
}
|
|
|
|
describe('tool registration', () => {
|
|
it('should register wrap tool when enabled', () => {
|
|
const props = createMockProps({ enabled: true })
|
|
renderHook(() => useWrapTool(props))
|
|
|
|
expect(mocks.useToolManager).toHaveBeenCalledWith(props.setTools)
|
|
expectToolRegistration(1, {
|
|
id: 'wrap',
|
|
type: 'quick',
|
|
order: 13,
|
|
tooltip: 'code_block.wrap.off',
|
|
onClick: expect.any(Function),
|
|
visible: expect.any(Function)
|
|
})
|
|
})
|
|
|
|
it('should not register tool when disabled', () => {
|
|
const props = createMockProps({ enabled: false })
|
|
renderHook(() => useWrapTool(props))
|
|
|
|
expect(mockRegisterTool).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('should re-register tool when wrapped changes', () => {
|
|
const props = createMockProps({ wrapped: true })
|
|
const { rerender } = renderHook((hookProps) => useWrapTool(hookProps), {
|
|
initialProps: props
|
|
})
|
|
|
|
expect(mockRegisterTool).toHaveBeenCalledTimes(1)
|
|
const firstCall = mockRegisterTool.mock.calls[0][0]
|
|
expect(firstCall.tooltip).toBe('code_block.wrap.off')
|
|
|
|
// Change wrapped to false and rerender
|
|
const newProps = { ...props, wrapped: false }
|
|
rerender(newProps)
|
|
|
|
expect(mockRegisterTool).toHaveBeenCalledTimes(2)
|
|
const secondCall = mockRegisterTool.mock.calls[1][0]
|
|
expect(secondCall.tooltip).toBe('code_block.wrap.on')
|
|
})
|
|
})
|
|
|
|
describe('visibility behavior', () => {
|
|
it('should be visible when wrappable is true', () => {
|
|
const props = createMockProps({ wrappable: true })
|
|
renderHook(() => useWrapTool(props))
|
|
|
|
const registeredTool = mockRegisterTool.mock.calls[0][0]
|
|
expect(registeredTool.visible()).toBe(true)
|
|
})
|
|
|
|
it('should not be visible when wrappable is false', () => {
|
|
const props = createMockProps({ wrappable: false })
|
|
renderHook(() => useWrapTool(props))
|
|
|
|
const registeredTool = mockRegisterTool.mock.calls[0][0]
|
|
expect(registeredTool.visible()).toBe(false)
|
|
})
|
|
|
|
it('should not be visible when wrappable is undefined', () => {
|
|
const props = createMockProps({ wrappable: undefined })
|
|
renderHook(() => useWrapTool(props))
|
|
|
|
const registeredTool = mockRegisterTool.mock.calls[0][0]
|
|
expect(registeredTool.visible()).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('toggle functionality', () => {
|
|
it('should execute toggle function when tool is clicked', () => {
|
|
const mockToggle = vi.fn()
|
|
const props = createMockProps({ toggle: mockToggle })
|
|
renderHook(() => useWrapTool(props))
|
|
|
|
const registeredTool = mockRegisterTool.mock.calls[0][0]
|
|
act(() => {
|
|
registeredTool.onClick()
|
|
})
|
|
|
|
expect(mockToggle).toHaveBeenCalledTimes(1)
|
|
})
|
|
})
|
|
|
|
describe('cleanup', () => {
|
|
it('should remove tool on unmount', () => {
|
|
const props = createMockProps()
|
|
const { unmount } = renderHook(() => useWrapTool(props))
|
|
|
|
unmount()
|
|
|
|
expect(mockRemoveTool).toHaveBeenCalledWith('wrap')
|
|
})
|
|
})
|
|
|
|
describe('edge cases', () => {
|
|
it('should handle missing setTools gracefully', () => {
|
|
const props = createMockProps({ setTools: undefined })
|
|
|
|
expect(() => {
|
|
renderHook(() => useWrapTool(props))
|
|
}).not.toThrow()
|
|
|
|
// Should still call useToolManager (but won't actually register)
|
|
expect(mocks.useToolManager).toHaveBeenCalledWith(undefined)
|
|
})
|
|
|
|
it('should not break when toggle is undefined', () => {
|
|
const props = createMockProps({ toggle: undefined })
|
|
renderHook(() => useWrapTool(props))
|
|
|
|
const registeredTool = mockRegisterTool.mock.calls[0][0]
|
|
|
|
expect(() => {
|
|
act(() => {
|
|
registeredTool.onClick()
|
|
})
|
|
}).not.toThrow()
|
|
})
|
|
})
|
|
})
|