/* @vitest-environment jsdom */
import { fireEvent, render, screen } from '@testing-library/react';
import { describe, expect, test, vi } from 'vitest';
import {
Badge,
Button,
Checkbox,
EmptyState,
IconButton,
Label,
Modal,
PlatformActionButton,
PlatformIconButton,
ProgressBar,
SegmentedTabs,
SelectField,
Skeleton,
Status,
Subpanel,
Switch,
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
TextField,
} from './index';
describe('shared UI components', () => {
test('keeps native button semantics and states', () => {
const onClick = vi.fn();
render(
,
);
const button = screen.getByRole('button', { name: '保存' });
expect(button.getAttribute('type')).toBe('button');
fireEvent.click(button);
expect(onClick).toHaveBeenCalledTimes(1);
expect(
(screen.getByRole('button', { name: '稍等' }) as HTMLButtonElement)
.disabled,
).toBe(true);
expect(
screen.getByRole('button', { name: '关闭' }).getAttribute('title'),
).toBe('关闭');
});
test('connects field labels and descriptions to native controls', () => {
render(
,
);
const input = screen.getByLabelText('名称');
expect(input.getAttribute('aria-invalid')).toBe('true');
expect(input.getAttribute('aria-describedby')).toContain('hint');
expect(screen.getByLabelText('描述').tagName).toBe('TEXTAREA');
expect(screen.getByLabelText('主题').tagName).toBe('SELECT');
expect(screen.getByRole('alert').textContent).toContain('名称已存在');
});
test('renders slots, selected tabs and semantic status content', () => {
const onChange = vi.fn();
render(
,
);
expect(screen.getByRole('heading', { name: '设置' })).toBeTruthy();
expect(screen.getByRole('status').textContent).toContain('完成');
expect(screen.getByRole('progressbar').getAttribute('aria-valuenow')).toBe(
'100',
);
expect(
screen.getByRole('tab', { name: 'A' }).getAttribute('aria-selected'),
).toBe('true');
fireEvent.click(screen.getByRole('tab', { name: 'B' }));
expect(onChange).toHaveBeenCalledWith('b');
expect(
screen.getByRole('switch', { name: '启用' }).getAttribute('aria-checked'),
).toBe('true');
});
test('provides semantic label, checkbox, skeleton and table primitives', () => {
render(
,
);
expect(screen.getByLabelText('自动保存')).toHaveProperty('checked', true);
expect(screen.getByLabelText('读取中').getAttribute('data-slot')).toBe(
'skeleton',
);
expect(screen.getByRole('table', { name: '最近项目' })).toBeTruthy();
expect(screen.getByRole('cell', { name: '珊瑚岛' })).toBeTruthy();
});
test('closes modal on escape and backdrop click', () => {
const onClose = vi.fn();
render(
正文
,
);
expect(screen.getByRole('dialog', { name: '确认' })).toBeTruthy();
fireEvent.keyDown(document, { key: 'Escape' });
expect(onClose).toHaveBeenCalledTimes(1);
fireEvent.mouseDown(
document.querySelector('.genarrative-ui-modal__backdrop')!,
);
expect(onClose).toHaveBeenCalledTimes(2);
});
test('can keep modal open when backdrop and escape closing are disabled', () => {
const onClose = vi.fn();
render(
正文
,
);
fireEvent.keyDown(document, { key: 'Escape' });
fireEvent.mouseDown(
document.querySelector('.genarrative-ui-modal__backdrop')!,
);
expect(onClose).not.toHaveBeenCalled();
});
test('keeps platform wrappers generic and supports label/span hosts', () => {
const onClick = vi.fn();
render(
,
);
expect(screen.getByText('上传').closest('label')?.htmlFor).toBe('upload');
const spanButton = screen.getByRole('button', { name: '打开' });
fireEvent.keyDown(spanButton, { key: 'Enter' });
expect(onClick).toHaveBeenCalledTimes(1);
});
});