chore: some tests for configuration components (#29653)

Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
This commit is contained in:
Joel
2025-12-15 21:18:58 +08:00
committed by GitHub
parent 7fb68b62b8
commit 23f75a1185
5 changed files with 209 additions and 2 deletions

View File

@@ -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()
})
})
})

View File

@@ -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)
})
})
})

View File

@@ -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('&lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;')
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')
})
})
})

View File

@@ -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)
})
})
})

View File

@@ -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>
)