70 lines
3.0 KiB
TypeScript
70 lines
3.0 KiB
TypeScript
import { describe, it, expect, vi } from 'vitest'
|
|
import { render, screen, fireEvent } from '@testing-library/react'
|
|
import { MicCapture } from '../components/MicCapture'
|
|
import type { MicStatus } from '../types'
|
|
|
|
const defaultProps = {
|
|
status: 'idle' as MicStatus,
|
|
error: null as string | null,
|
|
onStart: vi.fn(),
|
|
onStop: vi.fn(),
|
|
}
|
|
|
|
describe('MicCapture', () => {
|
|
it('renders "Start Listening" button with Mic icon in idle state', () => {
|
|
render(<MicCapture {...defaultProps} />)
|
|
expect(screen.getByRole('button', { name: /start listening/i })).toBeInTheDocument()
|
|
const svg = screen.getByRole('button', { name: /start listening/i }).querySelector('svg')
|
|
expect(svg).toBeInTheDocument()
|
|
})
|
|
|
|
it('does not render compatibility warning in idle state', () => {
|
|
render(<MicCapture {...defaultProps} />)
|
|
expect(screen.queryByText(/chrome\/edge/i)).not.toBeInTheDocument()
|
|
expect(screen.queryByText(/firefox/i)).not.toBeInTheDocument()
|
|
})
|
|
|
|
it('calls onStart when Start Listening button is clicked', () => {
|
|
const onStart = vi.fn()
|
|
render(<MicCapture {...defaultProps} onStart={onStart} />)
|
|
fireEvent.click(screen.getByRole('button', { name: /start listening/i }))
|
|
expect(onStart).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('renders "Waiting for microphone permission..." with spinner in requesting state', () => {
|
|
render(<MicCapture {...defaultProps} status="requesting" />)
|
|
expect(screen.getByText(/waiting for microphone permission/i)).toBeInTheDocument()
|
|
const spinner = document.querySelector('.animate-spin')
|
|
expect(spinner).toBeInTheDocument()
|
|
})
|
|
|
|
it('renders "Stop Listening" button, pulsing green dot, and "Listening..." in listening state', () => {
|
|
render(<MicCapture {...defaultProps} status="listening" />)
|
|
expect(screen.getByRole('button', { name: /stop listening/i })).toBeInTheDocument()
|
|
expect(screen.getByText('Listening...')).toBeInTheDocument()
|
|
const dot = document.querySelector('.animate-pulse')
|
|
expect(dot).toBeInTheDocument()
|
|
})
|
|
|
|
it('renders "Stopping..." disabled button in stopping state', () => {
|
|
render(<MicCapture {...defaultProps} status="stopping" />)
|
|
const btn = screen.getByRole('button', { name: /stopping/i })
|
|
expect(btn).toBeDisabled()
|
|
})
|
|
|
|
it('renders error message in red box and "Try Again" button in error state', () => {
|
|
render(<MicCapture {...defaultProps} status="error" error="Mic not found" />)
|
|
expect(screen.getByText('Mic not found')).toBeInTheDocument()
|
|
const redBox = screen.getByText('Mic not found').closest('[class*="red"]')
|
|
expect(redBox).toBeInTheDocument()
|
|
expect(screen.getByRole('button', { name: /try again/i })).toBeInTheDocument()
|
|
})
|
|
|
|
it('calls onStart when "Try Again" is clicked in error state', () => {
|
|
const onStart = vi.fn()
|
|
render(<MicCapture {...defaultProps} status="error" error="fail" onStart={onStart} />)
|
|
fireEvent.click(screen.getByRole('button', { name: /try again/i }))
|
|
expect(onStart).toHaveBeenCalledTimes(1)
|
|
})
|
|
})
|