mirror of
https://github.com/langgenius/dify.git
synced 2025-12-19 17:27:16 -05:00
chore: some tests for configuration components (#29653)
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import GroupName from './index'
|
||||
|
||||
describe('GroupName', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('Rendering', () => {
|
||||
it('should render name when provided', () => {
|
||||
// Arrange
|
||||
const title = 'Inputs'
|
||||
|
||||
// Act
|
||||
render(<GroupName name={title} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText(title)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,76 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import OperationBtn from './index'
|
||||
|
||||
jest.mock('react-i18next', () => ({
|
||||
useTranslation: () => ({
|
||||
t: (key: string) => key,
|
||||
}),
|
||||
}))
|
||||
|
||||
jest.mock('@remixicon/react', () => ({
|
||||
RiAddLine: (props: { className?: string }) => (
|
||||
<svg data-testid='add-icon' className={props.className} />
|
||||
),
|
||||
RiEditLine: (props: { className?: string }) => (
|
||||
<svg data-testid='edit-icon' className={props.className} />
|
||||
),
|
||||
}))
|
||||
|
||||
describe('OperationBtn', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
// Rendering icons and translation labels
|
||||
describe('Rendering', () => {
|
||||
it('should render passed custom class when provided', () => {
|
||||
// Arrange
|
||||
const customClass = 'custom-class'
|
||||
|
||||
// Act
|
||||
render(<OperationBtn type='add' className={customClass} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('common.operation.add').parentElement).toHaveClass(customClass)
|
||||
})
|
||||
it('should render add icon when type is add', () => {
|
||||
// Arrange
|
||||
const onClick = jest.fn()
|
||||
|
||||
// Act
|
||||
render(<OperationBtn type='add' onClick={onClick} className='custom-class' />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('add-icon')).toBeInTheDocument()
|
||||
expect(screen.getByText('common.operation.add')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render edit icon when provided', () => {
|
||||
// Arrange
|
||||
const actionName = 'Rename'
|
||||
|
||||
// Act
|
||||
render(<OperationBtn type='edit' actionName={actionName} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('edit-icon')).toBeInTheDocument()
|
||||
expect(screen.queryByTestId('add-icon')).toBeNull()
|
||||
expect(screen.getByText(actionName)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// Click handling
|
||||
describe('Interactions', () => {
|
||||
it('should execute click handler when button is clicked', () => {
|
||||
// Arrange
|
||||
const onClick = jest.fn()
|
||||
render(<OperationBtn type='add' onClick={onClick} />)
|
||||
|
||||
// Act
|
||||
fireEvent.click(screen.getByText('common.operation.add'))
|
||||
|
||||
// Assert
|
||||
expect(onClick).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,62 @@
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import VarHighlight, { varHighlightHTML } from './index'
|
||||
|
||||
describe('VarHighlight', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
// Rendering highlighted variable tags
|
||||
describe('Rendering', () => {
|
||||
it('should render braces around the variable name with default styles', () => {
|
||||
// Arrange
|
||||
const props = { name: 'userInput' }
|
||||
|
||||
// Act
|
||||
const { container } = render(<VarHighlight {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('userInput')).toBeInTheDocument()
|
||||
expect(screen.getAllByText('{{')[0]).toBeInTheDocument()
|
||||
expect(screen.getAllByText('}}')[0]).toBeInTheDocument()
|
||||
expect(container.firstChild).toHaveClass('item')
|
||||
})
|
||||
|
||||
it('should apply custom class names when provided', () => {
|
||||
// Arrange
|
||||
const props = { name: 'custom', className: 'mt-2' }
|
||||
|
||||
// Act
|
||||
const { container } = render(<VarHighlight {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(container.firstChild).toHaveClass('mt-2')
|
||||
})
|
||||
})
|
||||
|
||||
// Escaping HTML via helper
|
||||
describe('varHighlightHTML', () => {
|
||||
it('should escape dangerous characters before returning HTML string', () => {
|
||||
// Arrange
|
||||
const props = { name: '<script>alert(\'xss\')</script>' }
|
||||
|
||||
// Act
|
||||
const html = varHighlightHTML(props)
|
||||
|
||||
// Assert
|
||||
expect(html).toContain('<script>alert('xss')</script>')
|
||||
expect(html).not.toContain('<script>')
|
||||
})
|
||||
|
||||
it('should include custom class names in the wrapper element', () => {
|
||||
// Arrange
|
||||
const props = { name: 'data', className: 'text-primary' }
|
||||
|
||||
// Act
|
||||
const html = varHighlightHTML(props)
|
||||
|
||||
// Assert
|
||||
expect(html).toContain('class="item text-primary')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,48 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import ContrlBtnGroup from './index'
|
||||
|
||||
jest.mock('react-i18next', () => ({
|
||||
useTranslation: () => ({
|
||||
t: (key: string) => key,
|
||||
}),
|
||||
}))
|
||||
|
||||
describe('ContrlBtnGroup', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
// Rendering fixed action buttons
|
||||
describe('Rendering', () => {
|
||||
it('should render buttons when rendered', () => {
|
||||
// Arrange
|
||||
const onSave = jest.fn()
|
||||
const onReset = jest.fn()
|
||||
|
||||
// Act
|
||||
render(<ContrlBtnGroup onSave={onSave} onReset={onReset} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('apply-btn')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('reset-btn')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// Handling click interactions
|
||||
describe('Interactions', () => {
|
||||
it('should invoke callbacks when buttons are clicked', () => {
|
||||
// Arrange
|
||||
const onSave = jest.fn()
|
||||
const onReset = jest.fn()
|
||||
render(<ContrlBtnGroup onSave={onSave} onReset={onReset} />)
|
||||
|
||||
// Act
|
||||
fireEvent.click(screen.getByTestId('apply-btn'))
|
||||
fireEvent.click(screen.getByTestId('reset-btn'))
|
||||
|
||||
// Assert
|
||||
expect(onSave).toHaveBeenCalledTimes(1)
|
||||
expect(onReset).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -15,8 +15,8 @@ const ContrlBtnGroup: FC<IContrlBtnGroupProps> = ({ onSave, onReset }) => {
|
||||
return (
|
||||
<div className="fixed bottom-0 left-[224px] h-[64px] w-[519px]">
|
||||
<div className={`${s.ctrlBtn} flex h-full items-center gap-2 bg-white pl-4`}>
|
||||
<Button variant='primary' onClick={onSave}>{t('appDebug.operation.applyConfig')}</Button>
|
||||
<Button onClick={onReset}>{t('appDebug.operation.resetConfig')}</Button>
|
||||
<Button variant='primary' onClick={onSave} data-testid="apply-btn">{t('appDebug.operation.applyConfig')}</Button>
|
||||
<Button onClick={onReset} data-testid="reset-btn">{t('appDebug.operation.resetConfig')}</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user