import {describe, expect, it, vi, beforeAll} from 'vitest'
import {render, screen, waitFor} from '../../test-utils'
import {Image} from './image'
// Mock URL.revokeObjectURL for jsdom
beforeAll(() => {
URL.revokeObjectURL = vi.fn()
})
// Mock the util functions
vi.mock('../../utils', () => ({
getThumbhashBlobURL: vi.fn((thumbhash?: string) =>
thumbhash ? `blob:http://localhost/${thumbhash}` : undefined
),
getResizedImageUrl: vi.fn((url?: string) => url),
}))
describe('Image', () => {
it('renders with src and alt', () => {
render()
const img = screen.getByRole('img', {name: /test image/i})
expect(img).toBeInTheDocument()
expect(img).toHaveAttribute('src', 'https://example.com/image.jpg')
})
it('renders placeholder when no src provided', () => {
const {container} = render()
// When no src is provided, Image component still renders an img element but without src
const img = container.querySelector('img')
expect(img).toBeInTheDocument()
expect(img).not.toHaveAttribute('src')
})
it('handles onLoad callback', async () => {
const handleLoad = vi.fn()
render(
)
const img = screen.getByRole('img')
// Simulate image loading
img.dispatchEvent(new Event('load'))
await waitFor(() => {
expect(handleLoad).toHaveBeenCalled()
})
})
it('applies custom className', () => {
const {container} = render(
)
const wrapper = container.firstChild as HTMLElement
expect(wrapper).toHaveClass('custom-class')
})
it('applies aspect ratio style', () => {
const {container} = render(
)
const wrapper = container.firstChild as HTMLElement
expect(wrapper.style.aspectRatio).toBe('16/9')
})
it('uses thumbhash as placeholder when provided with fixed aspect ratio', () => {
const {container} = render(
)
// Thumbhash is now rendered as a separate img element (placeholder)
const images = container.querySelectorAll('img')
expect(images).toHaveLength(2) // placeholder + main image
const placeholderImg = images[0]
expect(placeholderImg).toHaveAttribute(
'src',
'blob:http://localhost/testThumbhash'
)
expect(placeholderImg).toHaveAttribute('aria-hidden', 'true')
})
it('renders with natural sizing when aspectRatio is auto', () => {
const {container} = render(
)
const wrapper = container.firstChild as HTMLElement
const img = screen.getByRole('img')
expect(wrapper.tagName).toBe('DIV')
expect(wrapper).toHaveClass('custom-class')
expect(wrapper.style.aspectRatio).toBe('')
expect(img).toHaveClass('w-full', 'h-auto')
expect(img).toHaveAttribute('src', 'https://example.com/image.jpg')
})
it('preserves thumbhash with natural sizing', () => {
const {container} = render(
)
// Thumbhash is now rendered as a separate img element (placeholder)
const images = container.querySelectorAll('img')
expect(images).toHaveLength(2) // placeholder + main image
const placeholderImg = images[0]
expect(placeholderImg).toHaveAttribute(
'src',
'blob:http://localhost/testThumbhash'
)
const mainImg = images[1]
expect(mainImg).toHaveClass('w-full', 'h-auto')
})
it('passes additional props to img element', () => {
render(
)
const img = screen.getByRole('img')
expect(img).toHaveAttribute('loading', 'lazy')
expect(img).toHaveAttribute('data-testid', 'custom-image')
})
})