Files
wehub-resource-sync 070959e133
landing-page-staging / Deploy landing page to staging (push) Has been skipped
landing-page-ci / Validate landing page (push) Failing after 4s
visual-baseline / Capture visual baselines (push) Has been cancelled
bake-plugin-previews / Bake plugin previews (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:00:47 +08:00

103 lines
3.2 KiB
TypeScript

// @vitest-environment jsdom
import { cleanup, fireEvent, render, screen } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { CustomSelect } from '../../src/components/CustomSelect';
afterEach(() => cleanup());
describe('CustomSelect', () => {
it('renders the selected label and chooses an option from the portal menu', () => {
const onChange = vi.fn();
render(
<CustomSelect
ariaLabel="Model"
value="gpt-image-2"
options={[
{ value: 'gpt-image-2', label: 'GPT Image 2' },
{ value: 'seedance', label: 'Seedance' },
]}
onChange={onChange}
/>,
);
const trigger = screen.getByRole('combobox', { name: 'Model: GPT Image 2' });
expect(trigger.getAttribute('aria-expanded')).toBe('false');
fireEvent.click(trigger);
expect(trigger.getAttribute('aria-expanded')).toBe('true');
fireEvent.click(screen.getByRole('option', { name: /Seedance/ }));
expect(onChange).toHaveBeenCalledWith('seedance');
});
it('skips disabled options and supports keyboard selection', () => {
const onChange = vi.fn();
render(
<CustomSelect
ariaLabel="Provider"
value="openai"
options={[
{ value: 'openai', label: 'OpenAI' },
{ value: 'disabled', label: 'Disabled', disabled: true },
{ value: 'custom', label: 'Custom' },
]}
onChange={onChange}
/>,
);
const trigger = screen.getByRole('combobox', { name: 'Provider: OpenAI' });
fireEvent.keyDown(trigger, { key: 'ArrowDown' });
fireEvent.keyDown(trigger, { key: 'ArrowDown' });
expect(trigger.getAttribute('aria-activedescendant')).toBe(
screen.getByRole('option', { name: /Custom/ }).id,
);
expect(trigger.getAttribute('aria-activedescendant')).not.toBe(
screen.getByRole('option', { name: /Disabled/ }).id,
);
fireEvent.keyDown(trigger, { key: 'Enter' });
expect(onChange).toHaveBeenCalledWith('custom');
expect(onChange).not.toHaveBeenCalledWith('disabled');
});
it('keeps keyboard navigation active state across parent rerenders with fresh options', () => {
const onChange = vi.fn();
const options = () => [
{ value: 'first', label: 'First' },
{ value: 'second', label: 'Second' },
{ value: 'third', label: 'Third' },
];
const { rerender } = render(
<CustomSelect
ariaLabel="Template"
value="first"
options={options()}
onChange={onChange}
/>,
);
const trigger = screen.getByRole('combobox', { name: 'Template: First' });
fireEvent.keyDown(trigger, { key: 'ArrowDown' });
fireEvent.keyDown(trigger, { key: 'ArrowDown' });
expect(trigger.getAttribute('aria-activedescendant')).toBe(
screen.getByRole('option', { name: /Second/ }).id,
);
rerender(
<CustomSelect
ariaLabel="Template"
value="first"
options={options()}
onChange={onChange}
/>,
);
const rerenderedTrigger = screen.getByRole('combobox', { name: 'Template: First' });
expect(rerenderedTrigger.getAttribute('aria-activedescendant')).toBe(
screen.getByRole('option', { name: /Second/ }).id,
);
});
});