/**
* Unit tests for CallEventRow — enterprise chat renderer for phone
* calls. Covers the three-state UX:
*
* - Collapsed default, clickable label, hidden action cluster
* - Expanded after click, transcript visible, Collapse link exposed
* - Resume handler wired, Resume action visible when provided
*
* jsdom caveat: group-hover CSS is not actually evaluated, so the
* hover-reveal is tested by asserting the hover CSS class is present
* on the action cluster, rather than by simulating mouseenter.
*/
import React from 'react'
import { describe, it, expect, vi } from 'vitest'
import { render, screen, fireEvent } from '@testing-library/react'
import CallEventRow from './CallEventRow'
const SAMPLE_TRANSCRIPT = [
{ who: 'user' as const, text: 'hello how are you going' },
{ who: 'assistant' as const, text: 'I am well, thank you.' },
]
describe('CallEventRow', () => {
it('renders the collapsed divider with duration + time summary', () => {
render()
expect(screen.getByRole('region', { name: /call/i })).toBeTruthy()
expect(screen.getByText(/26s/)).toBeTruthy()
})
it('hides the transcript body in the default collapsed state', () => {
render()
expect(screen.queryByText(/hello how are you going/)).toBeNull()
})
it('expands the transcript when the label button is clicked', () => {
render()
const expandBtn = screen.getByRole('button', { name: /expand call row/i })
fireEvent.click(expandBtn)
expect(screen.getByText(/hello how are you going/)).toBeTruthy()
expect(screen.getByText(/I am well, thank you\./)).toBeTruthy()
})
it('uses personaName as the label column for assistant lines', () => {
render(
,
)
// User label + persona label both appear in the expanded body.
expect(screen.getByText('You')).toBeTruthy()
expect(screen.getByText('Secretary')).toBeTruthy()
})
it('strips markdown image syntax from transcript lines', () => {
render(
,
)
// Stripped text has the middle removed; renders as "hello there".
expect(screen.getByText(/^hello\s+there$/)).toBeTruthy()
})
it('hides the Transcript / Collapse affordance when transcript is empty', () => {
render()
expect(screen.queryByText(/Transcript/i)).toBeNull()
expect(screen.queryByText(/Collapse/i)).toBeNull()
})
it('renders Resume link only when onResume is provided', () => {
const { rerender } = render()
expect(screen.queryByRole('button', { name: /resume call/i })).toBeNull()
const onResume = vi.fn()
rerender()
expect(screen.getByRole('button', { name: /resume call/i })).toBeTruthy()
})
it('fires onResume when Resume is clicked, does not expand/collapse', () => {
const onResume = vi.fn()
render(
,
)
// Transcript stays hidden since we clicked Resume, not the label.
fireEvent.click(screen.getByRole('button', { name: /resume call/i }))
expect(onResume).toHaveBeenCalledTimes(1)
expect(screen.queryByText(/hello how are you going/)).toBeNull()
})
it('renders with defaultExpanded=true showing transcript immediately', () => {
render(
,
)
expect(screen.getByText(/hello how are you going/)).toBeTruthy()
})
it('formats durations as Ns / Nm / Nm Ss', () => {
const { rerender } = render()
expect(screen.getByText(/42s/)).toBeTruthy()
rerender()
expect(screen.getByText(/3m/)).toBeTruthy()
rerender()
expect(screen.getByText(/3m 12s/)).toBeTruthy()
})
})