import React from 'react'
import { describe, expect, it } from 'vitest'
import { renderWithProviders, screen } from '../../test/utils'
import { Avatar } from '.'
describe('Avatar', () => {
const emojiFontSize = (size: number) => {
renderWithProviders()
return screen.getByText(/\p{Emoji}/u)
}
it('scales the emoji with small (<32px) avatars so it does not overpower them', () => {
expect(emojiFontSize(18)).toHaveStyle({ fontSize: '8px', lineHeight: '1' })
})
it('scales up proportionally as small avatars grow', () => {
expect(emojiFontSize(20)).toHaveStyle({ fontSize: '9px' })
})
it('stays continuous with the fixed 14px step at the 32px boundary', () => {
// 31 * 0.45 rounds to 14, matching the >=32px fixed size.
expect(emojiFontSize(31)).toHaveStyle({ fontSize: '14px' })
})
it('keeps fixed emoji sizes for larger avatars', () => {
expect(emojiFontSize(40)).toHaveStyle({ fontSize: '14px' })
})
it.each([
[32, '14px'],
[55, '14px'],
[56, '18px'],
[119, '18px'],
[120, '36px'],
])(
'uses the exact fixed font size at the %spx boundary',
(size, fontSize) => {
expect(emojiFontSize(size)).toHaveStyle({ fontSize })
}
)
it('does not show a star by default but shows one when starred', () => {
const defaultAvatar = renderWithProviders(
)
expect(defaultAvatar.container.querySelector('svg')).not.toBeInTheDocument()
const starredAvatar = renderWithProviders(
)
expect(starredAvatar.container.querySelector('svg')).toBeInTheDocument()
})
it('uses a squircle by default and a circle when explicitly requested', () => {
const squircleAvatar = renderWithProviders(
)
const squircleElements = squircleAvatar.container.querySelectorAll(
'[style*="border-radius"]'
)
expect(squircleElements).toHaveLength(3)
squircleElements.forEach((element) =>
expect(element).toHaveStyle({ borderRadius: '1rem' })
)
const circleAvatar = renderWithProviders(
)
const circleElements = circleAvatar.container.querySelectorAll(
'[style*="border-radius"]'
)
expect(circleElements).toHaveLength(3)
circleElements.forEach((element) =>
expect(element).toHaveStyle({ borderRadius: '50%' })
)
})
it('only applies the AI ring when dmAgentEnabled is true', () => {
const defaultAvatar = renderWithProviders(
)
expect(
defaultAvatar.container.querySelector('[data-testid="avatar-ring"]')
).not.toHaveStyle({
borderWidth: '2px',
borderStyle: 'solid',
})
const enabledAvatar = renderWithProviders(
)
expect(
enabledAvatar.container.querySelector('[data-testid="avatar-ring"]')
).toHaveStyle({
borderWidth: '2px',
borderStyle: 'solid',
borderColor: 'var(--AI-Gradient, #7F22FE)',
boxShadow: 'inset 0 1px 2px 0 rgba(255, 255, 255, 0.5)',
})
const smallEnabledAvatar = renderWithProviders(
)
expect(
smallEnabledAvatar.container.querySelector('[data-testid="avatar-ring"]')
).toHaveStyle({ borderWidth: '1px' })
})
it('renders an image instead of the emoji fallback when image is provided', () => {
const fallbackAvatar = renderWithProviders()
expect(
fallbackAvatar.container.querySelector('img')
).not.toBeInTheDocument()
expect(fallbackAvatar.container).toHaveTextContent('🍎')
expect(
fallbackAvatar.container.querySelector('.avatar-fallback')
).toHaveClass(
'avatar-fallback',
'flex',
'h-full',
'w-full',
'items-center',
'justify-center',
'font-semibold',
'select-none',
'transition-colors'
)
const imageAvatar = renderWithProviders(
)
expect(imageAvatar.container.querySelector('img')).toHaveAttribute(
'src',
'https://example.com/avatar.png'
)
expect(imageAvatar.container).not.toHaveTextContent('🍎')
})
it('applies the fallback background color and forwards custom classes', () => {
const { container } = renderWithProviders(
)
const root = container.firstElementChild
const ring = container.querySelector('[data-testid="avatar-ring"]')
expect(root).toHaveClass('relative', 'flex-shrink-0', 'custom-avatar')
expect(ring).toHaveClass('h-full', 'w-full', 'bg-transparent')
expect(root).toHaveStyle({
backgroundColor: '#FFD1DD',
width: '40px',
height: '40px',
})
})
})