test(web): cover passthrough props in base ui wrappers

This commit is contained in:
yyh
2026-03-02 20:18:30 +08:00
parent ceb8c8bf1e
commit 74f96d54ca
3 changed files with 125 additions and 2 deletions

View File

@ -179,6 +179,32 @@ describe('dropdown-menu wrapper', () => {
expect(popup).toHaveClass('content-popup-custom')
expect(screen.getByText('custom content')).toBeInTheDocument()
})
it('should forward positioner and popup passthrough props when passthrough props are provided', () => {
// Arrange
// Act
render(
<DropdownMenuContent
positionerProps={{
'aria-label': 'dropdown content positioner',
}}
popupProps={{
'role': 'menu',
'aria-label': 'dropdown content popup',
}}
>
<span>passthrough content</span>
</DropdownMenuContent>,
)
// Assert
const positioner = screen.getByTestId('menu-positioner')
const popup = screen.getByTestId('menu-popup')
expect(positioner).toHaveAttribute('aria-label', 'dropdown content positioner')
expect(popup).toHaveAttribute('role', 'menu')
expect(popup).toHaveAttribute('aria-label', 'dropdown content popup')
})
})
describe('DropdownMenuSubContent', () => {
@ -236,6 +262,32 @@ describe('dropdown-menu wrapper', () => {
expect(positioner).toHaveClass('sub-positioner-custom')
expect(popup).toHaveClass('sub-popup-custom')
})
it('should forward passthrough props for sub-content positioner and popup when passthrough props are provided', () => {
// Arrange
// Act
render(
<DropdownMenuSubContent
positionerProps={{
'aria-label': 'dropdown sub positioner',
}}
popupProps={{
'role': 'menu',
'aria-label': 'dropdown sub popup',
}}
>
<span>passthrough sub content</span>
</DropdownMenuSubContent>,
)
// Assert
const positioner = screen.getByTestId('menu-positioner')
const popup = screen.getByTestId('menu-popup')
expect(positioner).toHaveAttribute('aria-label', 'dropdown sub positioner')
expect(popup).toHaveAttribute('role', 'menu')
expect(popup).toHaveAttribute('aria-label', 'dropdown sub popup')
})
})
describe('DropdownMenuSubTrigger', () => {

View File

@ -17,6 +17,7 @@ type PositionerMockProps = ComponentPropsWithoutRef<'div'> & {
const positionerPropsSpy = vi.fn<(props: PositionerMockProps) => void>()
const popupClassNameSpy = vi.fn<(className: string | undefined) => void>()
const popupPropsSpy = vi.fn<(props: ComponentPropsWithoutRef<'div'>) => void>()
const parsePlacementMock = vi.fn<(placement: Placement) => ParsedPlacement>()
vi.mock('@base-ui/react/popover', () => {
@ -53,10 +54,11 @@ vi.mock('@base-ui/react/popover', () => {
)
}
const Popup = ({ children, className }: ComponentPropsWithoutRef<'div'>) => {
const Popup = ({ children, className, ...props }: ComponentPropsWithoutRef<'div'>) => {
popupClassNameSpy(className)
popupPropsSpy({ className, ...props })
return (
<div data-testid="mock-popup" className={className}>
<div data-testid="mock-popup" className={className} {...props}>
{children}
</div>
)
@ -168,6 +170,43 @@ describe('PopoverContent', () => {
})
})
describe('Passthrough props', () => {
it('should forward positionerProps and popupProps when passthrough props are provided', () => {
// Arrange
render(
<PopoverContent
positionerProps={{
'aria-label': 'popover positioner',
}}
popupProps={{
'role': 'dialog',
'aria-label': 'popover content',
}}
>
<span>Popover body</span>
</PopoverContent>,
)
// Act
const popup = screen.getByTestId('mock-popup')
// Assert
expect(positionerPropsSpy).toHaveBeenCalledWith(
expect.objectContaining({
'aria-label': 'popover positioner',
}),
)
expect(popupPropsSpy).toHaveBeenCalledWith(
expect.objectContaining({
'role': 'dialog',
'aria-label': 'popover content',
}),
)
expect(popup).toHaveAttribute('role', 'dialog')
expect(popup).toHaveAttribute('aria-label', 'popover content')
})
})
describe('Children rendering', () => {
it('should render children inside Popup', () => {
// Arrange

View File

@ -219,6 +219,38 @@ describe('Select wrappers', () => {
expect(screen.getByTestId('base-select-list')).toHaveClass('max-h-80', 'custom-list')
})
it('should forward passthrough props to positioner popup and list when passthrough props are provided', () => {
// Arrange & Act
render(
<SelectContent
positionerProps={{
'aria-label': 'select positioner',
}}
popupProps={{
'role': 'dialog',
'aria-label': 'select popup',
}}
listProps={{
'role': 'listbox',
'aria-label': 'select list',
}}
>
<div>Option A</div>
</SelectContent>,
)
// Assert
const positioner = screen.getByTestId('base-select-positioner')
const popup = screen.getByTestId('base-select-popup')
const list = screen.getByTestId('base-select-list')
expect(positioner).toHaveAttribute('aria-label', 'select positioner')
expect(popup).toHaveAttribute('role', 'dialog')
expect(popup).toHaveAttribute('aria-label', 'select popup')
expect(list).toHaveAttribute('role', 'listbox')
expect(list).toHaveAttribute('aria-label', 'select list')
})
it('should render children inside list when children are provided', () => {
// Arrange & Act
render(