mirror of https://github.com/langgenius/dify.git
112 lines
3.9 KiB
TypeScript
112 lines
3.9 KiB
TypeScript
import { render, screen } from '@testing-library/react'
|
|
import { Avatar } from '../index'
|
|
|
|
describe('Avatar', () => {
|
|
describe('Rendering', () => {
|
|
it('should keep the fallback visible when avatar URL is provided before image load', () => {
|
|
render(<Avatar name="John Doe" avatar="https://example.com/avatar.jpg" />)
|
|
|
|
expect(screen.getByText('J')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should render fallback with uppercase initial when avatar is null', () => {
|
|
render(<Avatar name="alice" avatar={null} />)
|
|
|
|
expect(screen.queryByRole('img')).not.toBeInTheDocument()
|
|
expect(screen.getByText('A')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should render the fallback when avatar is provided', () => {
|
|
render(<Avatar name="John" avatar="https://example.com/avatar.jpg" />)
|
|
|
|
expect(screen.getByText('J')).toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('Size variants', () => {
|
|
it.each([
|
|
{ size: 'xxs' as const, expectedClass: 'size-4' },
|
|
{ size: 'xs' as const, expectedClass: 'size-5' },
|
|
{ size: 'sm' as const, expectedClass: 'size-6' },
|
|
{ size: 'md' as const, expectedClass: 'size-8' },
|
|
{ size: 'lg' as const, expectedClass: 'size-9' },
|
|
{ size: 'xl' as const, expectedClass: 'size-10' },
|
|
{ size: '2xl' as const, expectedClass: 'size-12' },
|
|
{ size: '3xl' as const, expectedClass: 'size-16' },
|
|
])('should apply $expectedClass for size="$size"', ({ size, expectedClass }) => {
|
|
const { container } = render(<Avatar name="Test" avatar={null} size={size} />)
|
|
|
|
const root = container.firstElementChild as HTMLElement
|
|
expect(root).toHaveClass(expectedClass)
|
|
})
|
|
|
|
it('should default to md size when size is not specified', () => {
|
|
const { container } = render(<Avatar name="Test" avatar={null} />)
|
|
|
|
const root = container.firstElementChild as HTMLElement
|
|
expect(root).toHaveClass('size-8')
|
|
})
|
|
})
|
|
|
|
describe('className prop', () => {
|
|
it('should merge className with avatar variant classes on root', () => {
|
|
const { container } = render(
|
|
<Avatar name="Test" avatar={null} className="custom-class" />,
|
|
)
|
|
|
|
const root = container.firstElementChild as HTMLElement
|
|
expect(root).toHaveClass('custom-class')
|
|
expect(root).toHaveClass('rounded-full', 'bg-primary-600')
|
|
})
|
|
})
|
|
|
|
describe('Edge Cases', () => {
|
|
it('should handle empty string name gracefully', () => {
|
|
const { container } = render(<Avatar name="" avatar={null} />)
|
|
|
|
const fallback = container.querySelector('.text-white') as HTMLElement
|
|
expect(fallback).toBeInTheDocument()
|
|
expect(fallback.textContent).toBe('')
|
|
})
|
|
|
|
it.each([
|
|
{ name: '中文名', expected: '中', label: 'Chinese characters' },
|
|
{ name: '123User', expected: '1', label: 'number' },
|
|
])('should display first character when name starts with $label', ({ name, expected }) => {
|
|
render(<Avatar name={name} avatar={null} />)
|
|
|
|
expect(screen.getByText(expected)).toBeInTheDocument()
|
|
})
|
|
|
|
it('should handle empty string avatar as falsy value', () => {
|
|
render(<Avatar name="Test" avatar={'' as string | null} />)
|
|
|
|
expect(screen.queryByRole('img')).not.toBeInTheDocument()
|
|
expect(screen.getByText('T')).toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('onLoadingStatusChange', () => {
|
|
it('should render the fallback when avatar and onLoadingStatusChange are provided', () => {
|
|
render(
|
|
<Avatar
|
|
name="John"
|
|
avatar="https://example.com/avatar.jpg"
|
|
onLoadingStatusChange={vi.fn()}
|
|
/>,
|
|
)
|
|
|
|
expect(screen.getByText('J')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should not render image when avatar is null even with onLoadingStatusChange', () => {
|
|
const onStatusChange = vi.fn()
|
|
render(
|
|
<Avatar name="John" avatar={null} onLoadingStatusChange={onStatusChange} />,
|
|
)
|
|
|
|
expect(screen.queryByRole('img')).not.toBeInTheDocument()
|
|
})
|
|
})
|
|
})
|