import '@testing-library/jest-dom/vitest' import React from 'react' import { afterEach, describe, expect, it, vi } from 'vitest' import { cleanup, fireEvent, render, screen } from '@testing-library/react' import { Avatar } from './Avatar' import { DropdownMenu } from './DropdownMenu' import { IntegrationStatusCard } from './IntegrationStatusCard' import { UserMenu } from './UserMenu' afterEach(cleanup) describe('Avatar', () => { it('uses name initials as fallback and exposes a default accessible label', () => { render() expect(screen.getByRole('img', { name: '홍길동' })).toHaveTextContent('홍') expect(screen.getByLabelText('online')).toBeInTheDocument() }) it('falls back to initials when the profile image fails to load', () => { render() const image = screen.getByRole('img', { name: 'Jane Doe' }) fireEvent.error(image) expect(screen.getByRole('img', { name: 'Jane Doe' })).toHaveTextContent('J') }) }) describe('DropdownMenu', () => { it('opens from the trigger and closes on outside click', () => { render(
계정}> 프로필
) fireEvent.click(screen.getByRole('button', { name: '계정' })) expect(screen.getByRole('menu')).toBeInTheDocument() fireEvent.mouseDown(screen.getByRole('button', { name: '외부' })) expect(screen.queryByRole('menu')).not.toBeInTheDocument() }) it('skips disabled items during keyboard navigation and returns focus to trigger after selection', () => { const onSelect = vi.fn() render( 액션}> 비활성 로그아웃 ) const trigger = screen.getByRole('button', { name: '액션' }) fireEvent.click(trigger) fireEvent.keyDown(screen.getByRole('menu'), { key: 'ArrowDown' }) fireEvent.keyDown(screen.getByRole('menu'), { key: 'Enter' }) expect(onSelect).toHaveBeenCalledTimes(1) expect(screen.queryByRole('menu')).not.toBeInTheDocument() expect(trigger).toHaveFocus() }) it('opens from the trigger with ArrowDown and focuses the first enabled item', () => { render( 더보기}> 비활성 첫 액션 ) const trigger = screen.getByRole('button', { name: '더보기' }) fireEvent.keyDown(trigger, { key: 'ArrowDown' }) expect(screen.getByRole('menuitem', { name: '첫 액션' })).toHaveFocus() }) }) describe('UserMenu', () => { it('renders truncated user identity and calls account actions from the dropdown', () => { const onSettingsClick = vi.fn() const onLogout = vi.fn() render( ) expect(screen.getByText('홍길동')).toBeInTheDocument() expect(screen.getByText('very.long.email.address@example-company.com')).toBeInTheDocument() fireEvent.click(screen.getByRole('button', { name: /계정 메뉴/ })) fireEvent.click(screen.getByRole('menuitem', { name: /계정 설정/ })) expect(onSettingsClick).toHaveBeenCalledTimes(1) fireEvent.click(screen.getByRole('button', { name: /계정 메뉴/ })) fireEvent.click(screen.getByRole('menuitem', { name: /로그아웃/ })) expect(onLogout).toHaveBeenCalledTimes(1) }) }) describe('IntegrationStatusCard', () => { it('renders status metadata and invokes configured actions', () => { const reconnect = vi.fn() const disconnect = vi.fn() render( 마지막 동기화 2분 전} primaryAction={{ label: '다시 연결', onClick: reconnect }} secondaryAction={{ label: '연결 해제', onClick: disconnect, tone: 'danger' }} /> ) expect(screen.getByText('다시 연결 필요')).toBeInTheDocument() expect(screen.getByText('마지막 동기화 2분 전')).toBeInTheDocument() fireEvent.click(screen.getByRole('button', { name: '다시 연결' })) fireEvent.click(screen.getByRole('button', { name: '연결 해제' })) expect(reconnect).toHaveBeenCalledTimes(1) expect(disconnect).toHaveBeenCalledTimes(1) }) })