test: add unit tests for base components (#32818)

Co-authored-by: CodingOnStar <hanxujiang@dify.com>
This commit is contained in:
Coding On Star
2026-03-02 11:40:43 +08:00
committed by GitHub
parent 8cc775d9f2
commit 335b500aea
401 changed files with 820 additions and 819 deletions

View File

@ -0,0 +1,49 @@
import { fireEvent, render, screen } from '@testing-library/react'
import AddButton from '../add-button'
describe('AddButton', () => {
describe('Rendering', () => {
it('should render without crashing', () => {
const { container } = render(<AddButton onClick={vi.fn()} />)
expect(container.firstChild).toBeInTheDocument()
})
it('should render an add icon', () => {
render(<AddButton onClick={vi.fn()} />)
const iconSpan = screen.getByTestId('add-button').querySelector('span')
expect(iconSpan).toBeInTheDocument()
})
})
describe('Props', () => {
it('should apply custom className', () => {
const { container } = render(<AddButton onClick={vi.fn()} className="my-custom" />)
expect(container.firstChild).toHaveClass('my-custom')
})
it('should retain base classes when custom className is applied', () => {
const { container } = render(<AddButton onClick={vi.fn()} className="my-custom" />)
expect(container.firstChild).toHaveClass('cursor-pointer')
expect(container.firstChild).toHaveClass('rounded-md')
expect(container.firstChild).toHaveClass('select-none')
})
})
describe('User Interactions', () => {
it('should call onClick when clicked', () => {
const onClick = vi.fn()
const { container } = render(<AddButton onClick={onClick} />)
fireEvent.click(container.firstChild!)
expect(onClick).toHaveBeenCalledTimes(1)
})
it('should call onClick multiple times on repeated clicks', () => {
const onClick = vi.fn()
const { container } = render(<AddButton onClick={onClick} />)
fireEvent.click(container.firstChild!)
fireEvent.click(container.firstChild!)
fireEvent.click(container.firstChild!)
expect(onClick).toHaveBeenCalledTimes(3)
})
})
})

View File

@ -0,0 +1,110 @@
import { cleanup, fireEvent, render } from '@testing-library/react'
import * as React from 'react'
import Button from '../index'
afterEach(cleanup)
// https://testing-library.com/docs/queries/about
describe('Button', () => {
describe('Button text', () => {
it('Button text should be same as children', async () => {
const { getByRole, container } = render(<Button>Click me</Button>)
expect(getByRole('button').textContent).toBe('Click me')
expect(container.querySelector('button')?.textContent).toBe('Click me')
})
})
describe('Button loading', () => {
it('Loading button text should include same as children', async () => {
const { getByRole } = render(<Button loading>Click me</Button>)
expect(getByRole('button').textContent?.includes('Loading')).toBe(true)
})
it('Not loading button text should include same as children', async () => {
const { getByRole } = render(<Button loading={false}>Click me</Button>)
expect(getByRole('button').textContent?.includes('Loading')).toBe(false)
})
it('Loading button should have loading classname', async () => {
const animClassName = 'anim-breath'
const { getByRole } = render(<Button loading spinnerClassName={animClassName}>Click me</Button>)
expect(getByRole('button').getElementsByClassName('animate-spin')[0]?.className).toContain(animClassName)
})
})
describe('Button style', () => {
it('Button should have default variant', async () => {
const { getByRole } = render(<Button>Click me</Button>)
expect(getByRole('button').className).toContain('btn-secondary')
})
it('Button should have primary variant', async () => {
const { getByRole } = render(<Button variant="primary">Click me</Button>)
expect(getByRole('button').className).toContain('btn-primary')
})
it('Button should have warning variant', async () => {
const { getByRole } = render(<Button variant="warning">Click me</Button>)
expect(getByRole('button').className).toContain('btn-warning')
})
it('Button should have secondary variant', async () => {
const { getByRole } = render(<Button variant="secondary">Click me</Button>)
expect(getByRole('button').className).toContain('btn-secondary')
})
it('Button should have secondary-accent variant', async () => {
const { getByRole } = render(<Button variant="secondary-accent">Click me</Button>)
expect(getByRole('button').className).toContain('btn-secondary-accent')
})
it('Button should have ghost variant', async () => {
const { getByRole } = render(<Button variant="ghost">Click me</Button>)
expect(getByRole('button').className).toContain('btn-ghost')
})
it('Button should have ghost-accent variant', async () => {
const { getByRole } = render(<Button variant="ghost-accent">Click me</Button>)
expect(getByRole('button').className).toContain('btn-ghost-accent')
})
it('Button disabled should have disabled variant', async () => {
const { getByRole } = render(<Button disabled>Click me</Button>)
expect(getByRole('button').className).toContain('btn-disabled')
})
})
describe('Button size', () => {
it('Button should have default size', async () => {
const { getByRole } = render(<Button>Click me</Button>)
expect(getByRole('button').className).toContain('btn-medium')
})
it('Button should have small size', async () => {
const { getByRole } = render(<Button size="small">Click me</Button>)
expect(getByRole('button').className).toContain('btn-small')
})
it('Button should have medium size', async () => {
const { getByRole } = render(<Button size="medium">Click me</Button>)
expect(getByRole('button').className).toContain('btn-medium')
})
it('Button should have large size', async () => {
const { getByRole } = render(<Button size="large">Click me</Button>)
expect(getByRole('button').className).toContain('btn-large')
})
})
describe('Button destructive', () => {
it('Button should have destructive classname', async () => {
const { getByRole } = render(<Button destructive>Click me</Button>)
expect(getByRole('button').className).toContain('btn-destructive')
})
})
describe('Button events', () => {
it('onClick should been call after clicked', async () => {
const onClick = vi.fn()
const { getByRole } = render(<Button onClick={onClick}>Click me</Button>)
fireEvent.click(getByRole('button'))
expect(onClick).toHaveBeenCalled()
})
})
})

View File

@ -0,0 +1,52 @@
import { fireEvent, render, screen } from '@testing-library/react'
import SyncButton from '../sync-button'
describe('SyncButton', () => {
describe('Rendering', () => {
it('should render without crashing', () => {
const { container } = render(<SyncButton onClick={vi.fn()} />)
expect(container.firstChild).toBeInTheDocument()
})
it('should render a refresh icon', () => {
render(<SyncButton onClick={vi.fn()} />)
const iconSpan = screen.getByTestId('sync-button').querySelector('span')
expect(iconSpan).toBeInTheDocument()
})
})
describe('Props', () => {
it('should apply custom className', () => {
render(<SyncButton onClick={vi.fn()} className="my-custom" />)
const clickableDiv = screen.getByTestId('sync-button')
expect(clickableDiv).toHaveClass('my-custom')
})
it('should retain base classes when custom className is applied', () => {
render(<SyncButton onClick={vi.fn()} className="my-custom" />)
const clickableDiv = screen.getByTestId('sync-button')
expect(clickableDiv).toHaveClass('rounded-md')
expect(clickableDiv).toHaveClass('select-none')
})
})
describe('User Interactions', () => {
it('should call onClick when clicked', () => {
const onClick = vi.fn()
render(<SyncButton onClick={onClick} />)
const clickableDiv = screen.getByTestId('sync-button')
fireEvent.click(clickableDiv)
expect(onClick).toHaveBeenCalledTimes(1)
})
it('should call onClick multiple times on repeated clicks', () => {
const onClick = vi.fn()
render(<SyncButton onClick={onClick} />)
const clickableDiv = screen.getByTestId('sync-button')
fireEvent.click(clickableDiv)
fireEvent.click(clickableDiv)
fireEvent.click(clickableDiv)
expect(onClick).toHaveBeenCalledTimes(3)
})
})
})