2023-06-07 11:54:50 +08:00
import React from 'react' ;
2024-04-08 14:04:08 +08:00
import type { SingleValueType } from 'rc-cascader/lib/Cascader' ;
2024-04-12 17:30:32 +08:00
import type { DefaultOptionType } from '..' ;
2017-02-26 16:48:42 +08:00
import Cascader from '..' ;
2024-04-08 14:04:08 +08:00
import { resetWarned } from '../../_util/warning' ;
2021-08-31 15:51:02 +08:00
import excludeAllWarning from '../../../tests/shared/excludeWarning' ;
2017-11-19 01:41:40 +08:00
import focusTest from '../../../tests/shared/focusTest' ;
2019-08-26 22:53:20 +08:00
import mountTest from '../../../tests/shared/mountTest' ;
2020-01-02 19:10:16 +08:00
import rtlTest from '../../../tests/shared/rtlTest' ;
2022-07-26 22:27:42 +08:00
import { fireEvent , render } from '../../../tests/utils' ;
2023-06-07 11:54:50 +08:00
import ConfigProvider from '../../config-provider' ;
2021-08-31 15:51:02 +08:00
2022-03-26 00:17:34 +08:00
const { SHOW_CHILD , SHOW_PARENT } = Cascader ;
2022-09-02 15:05:21 +08:00
function toggleOpen ( container : ReturnType < typeof render > [ 'container' ] ) {
fireEvent . mouseDown ( container . querySelector ( '.ant-select-selector' ) ! ) ;
2021-08-31 15:51:02 +08:00
}
2022-09-02 15:05:21 +08:00
function isOpen ( container : ReturnType < typeof render > [ 'container' ] ) {
return container . querySelector ( '.ant-cascader' ) ? . className . includes ( 'ant-select-open' ) ;
2021-08-31 15:51:02 +08:00
}
2022-09-02 15:05:21 +08:00
function getDropdown ( container : ReturnType < typeof render > [ 'container' ] ) {
2022-07-26 22:27:42 +08:00
return container . querySelector ( '.ant-select-dropdown' ) ;
2021-08-31 15:51:02 +08:00
}
2022-09-02 15:05:21 +08:00
function clickOption (
container : ReturnType < typeof render > [ 'container' ] ,
menuIndex : number ,
itemIndex : number ,
type = 'click' ,
) {
2022-07-26 22:27:42 +08:00
const menu = container . querySelectorAll ( 'ul.ant-cascader-menu' ) [ menuIndex ] ;
const itemList = menu . querySelectorAll ( 'li.ant-cascader-menu-item' ) ;
2022-09-02 15:05:21 +08:00
fireEvent ? . [ type as keyof typeof fireEvent ] ? . ( itemList [ itemIndex ] ) ;
2021-08-31 15:51:02 +08:00
}
2017-02-26 16:48:42 +08:00
2018-12-07 16:17:45 +08:00
const options = [
{
value : 'zhejiang' ,
label : 'Zhejiang' ,
children : [
{
value : 'hangzhou' ,
label : 'Hangzhou' ,
children : [
{
value : 'xihu' ,
label : 'West Lake' ,
} ,
] ,
} ,
] ,
} ,
{
value : 'jiangsu' ,
label : 'Jiangsu' ,
children : [
{
value : 'nanjing' ,
label : 'Nanjing' ,
children : [
{
value : 'zhonghuamen' ,
label : 'Zhong Hua Men' ,
} ,
] ,
} ,
] ,
} ,
] ;
2017-02-26 16:48:42 +08:00
2024-04-12 17:30:32 +08:00
function filter < OptionType extends DefaultOptionType = DefaultOptionType > (
2022-09-02 15:05:21 +08:00
inputValue : string ,
path : OptionType [ ] ,
) : boolean {
2024-04-12 17:30:32 +08:00
return path . some ( ( option ) = >
option . label ? . toString ( ) . toLowerCase ( ) . includes ( inputValue . toLowerCase ( ) ) ,
) ;
2018-05-25 19:31:34 +08:00
}
2017-02-26 16:48:42 +08:00
describe ( 'Cascader' , ( ) = > {
2021-08-31 15:51:02 +08:00
excludeAllWarning ( ) ;
focusTest ( Cascader , { refFocus : true } ) ;
2019-08-26 22:53:20 +08:00
mountTest ( Cascader ) ;
2020-01-02 19:10:16 +08:00
rtlTest ( Cascader ) ;
2017-11-19 01:41:40 +08:00
2017-02-26 16:48:42 +08:00
it ( 'popup correctly when panel is hidden' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render ( < Cascader options = { options } / > ) ;
expect ( isOpen ( container ) ) . toBeFalsy ( ) ;
2017-02-26 16:48:42 +08:00
} ) ;
it ( 'popup correctly when panel is open' , ( ) = > {
2023-06-07 21:59:21 +08:00
const onPopupVisibleChange = jest . fn ( ) ;
2022-07-26 22:27:42 +08:00
const { container } = render (
2018-12-07 16:17:45 +08:00
< Cascader options = { options } onPopupVisibleChange = { onPopupVisibleChange } / > ,
2017-02-26 16:48:42 +08:00
) ;
2022-07-26 22:27:42 +08:00
toggleOpen ( container ) ;
expect ( isOpen ( container ) ) . toBeTruthy ( ) ;
2018-05-25 19:31:34 +08:00
expect ( onPopupVisibleChange ) . toHaveBeenCalledWith ( true ) ;
2017-02-26 16:48:42 +08:00
} ) ;
2018-03-23 19:19:29 +08:00
it ( 'support controlled mode' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { rerender , asFragment } = render ( < Cascader options = { options } / > ) ;
rerender ( < Cascader options = { options } value = { [ 'zhejiang' , 'hangzhou' , 'xihu' ] } / > ) ;
expect ( asFragment ( ) . firstChild ) . toMatchSnapshot ( ) ;
2018-03-23 19:19:29 +08:00
} ) ;
2017-02-26 16:48:42 +08:00
it ( 'popup correctly with defaultValue' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render (
< Cascader options = { options } defaultValue = { [ 'zhejiang' , 'hangzhou' ] } / > ,
) ;
toggleOpen ( container ) ;
expect ( getDropdown ( container ) ) . toMatchSnapshot ( ) ;
2017-02-26 16:48:42 +08:00
} ) ;
2018-05-25 19:31:34 +08:00
it ( 'should support popupVisible' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container , rerender } = render (
< Cascader options = { options } defaultValue = { [ 'zhejiang' , 'hangzhou' ] } / > ,
) ;
expect ( isOpen ( container ) ) . toBeFalsy ( ) ;
rerender ( < Cascader options = { options } defaultValue = { [ 'zhejiang' , 'hangzhou' ] } popupVisible / > ) ;
expect ( isOpen ( container ) ) . toBeTruthy ( ) ;
2018-05-25 19:31:34 +08:00
} ) ;
2017-02-26 16:48:42 +08:00
it ( 'can be selected' , ( ) = > {
2023-06-07 21:59:21 +08:00
const onChange = jest . fn ( ) ;
2023-04-18 11:35:07 +08:00
const { container } = render ( < Cascader open options = { options } onChange = { onChange } / > ) ;
2021-08-31 15:51:02 +08:00
2022-07-26 22:27:42 +08:00
clickOption ( container , 0 , 0 ) ;
expect ( getDropdown ( container ) ) . toMatchSnapshot ( ) ;
2021-08-31 15:51:02 +08:00
2022-07-26 22:27:42 +08:00
clickOption ( container , 1 , 0 ) ;
expect ( getDropdown ( container ) ) . toMatchSnapshot ( ) ;
2021-08-31 15:51:02 +08:00
2022-07-26 22:27:42 +08:00
clickOption ( container , 2 , 0 ) ;
expect ( getDropdown ( container ) ) . toMatchSnapshot ( ) ;
2021-08-31 15:51:02 +08:00
expect ( onChange ) . toHaveBeenCalledTimes ( 1 ) ;
2018-05-25 19:31:34 +08:00
expect ( onChange ) . toHaveBeenCalledWith ( [ 'zhejiang' , 'hangzhou' , 'xihu' ] , expect . anything ( ) ) ;
2017-02-26 16:48:42 +08:00
} ) ;
2017-03-28 13:51:58 +08:00
it ( 'backspace should work with `Cascader[showSearch]`' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render ( < Cascader options = { options } showSearch / > ) ;
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : '123' } } ) ;
2022-07-26 22:27:42 +08:00
expect ( isOpen ( container ) ) . toBeTruthy ( ) ;
2021-08-31 15:51:02 +08:00
2022-09-02 15:05:21 +08:00
fireEvent . keyDown ( container . querySelector ( 'input' ) ! , { key : 'Backspace' , keyCode : 8 } ) ;
2022-07-26 22:27:42 +08:00
expect ( isOpen ( container ) ) . toBeTruthy ( ) ;
2021-08-31 15:51:02 +08:00
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : '' } } ) ;
2022-07-26 22:27:42 +08:00
expect ( isOpen ( container ) ) . toBeTruthy ( ) ;
2021-08-31 15:51:02 +08:00
2022-09-02 15:05:21 +08:00
fireEvent . keyDown ( container . querySelector ( 'input' ) ! , { key : 'Backspace' , keyCode : 8 } ) ;
2022-07-26 22:27:42 +08:00
expect ( isOpen ( container ) ) . toBeFalsy ( ) ;
2017-03-28 13:51:58 +08:00
} ) ;
2018-05-25 19:31:34 +08:00
it ( 'should highlight keyword and filter when search in Cascader' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render ( < Cascader options = { options } showSearch = { { filter } } / > ) ;
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : 'z' } } ) ;
2022-07-26 22:27:42 +08:00
// React 18 with testing lib will have additional space. We have to compare innerHTML. Sad.
2022-09-02 15:05:21 +08:00
expect ( getDropdown ( container ) ? . innerHTML ) . toMatchSnapshot ( ) ;
2018-05-25 19:31:34 +08:00
} ) ;
2020-01-07 13:41:41 +08:00
it ( 'should highlight keyword and filter when search in Cascader with same field name of label and value' , ( ) = > {
const customOptions = [
{
name : 'Zhejiang' ,
children : [
{
name : 'Hangzhou' ,
children : [
{
name : 'West Lake' ,
} ,
{
name : 'Xia Sha' ,
disabled : true ,
} ,
] ,
} ,
] ,
} ,
] ;
2024-04-12 17:30:32 +08:00
function customFilter < OptionType extends DefaultOptionType = DefaultOptionType > (
2022-09-02 15:05:21 +08:00
inputValue : string ,
path : OptionType [ ] ,
) : boolean {
2022-11-19 13:47:33 +08:00
return path . some ( ( option ) = > option . name . toLowerCase ( ) . includes ( inputValue . toLowerCase ( ) ) ) ;
2020-01-07 13:41:41 +08:00
}
2022-07-26 22:27:42 +08:00
const { container } = render (
2020-01-07 13:41:41 +08:00
< Cascader
options = { customOptions }
fieldNames = { { label : 'name' , value : 'name' } }
showSearch = { { filter : customFilter } }
/ > ,
) ;
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : 'z' } } ) ;
2022-07-26 22:27:42 +08:00
// React 18 with testing lib will have additional space. We have to compare innerHTML. Sad.
2022-09-02 15:05:21 +08:00
expect ( getDropdown ( container ) ? . innerHTML ) . toMatchSnapshot ( ) ;
2020-01-07 13:41:41 +08:00
} ) ;
2018-05-25 19:31:34 +08:00
it ( 'should render not found content' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render ( < Cascader options = { options } showSearch = { { filter } } / > ) ;
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , {
2022-07-26 22:27:42 +08:00
target : { value : '__notfoundkeyword__' } ,
} ) ;
expect ( getDropdown ( container ) ) . toMatchSnapshot ( ) ;
2018-05-25 19:31:34 +08:00
} ) ;
2021-08-31 15:51:02 +08:00
it ( 'should support to clear selection' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render (
< Cascader options = { options } defaultValue = { [ 'zhejiang' , 'hangzhou' ] } / > ,
) ;
2022-09-02 15:05:21 +08:00
expect ( container . querySelector ( '.ant-select-selection-item' ) ? . textContent ) . toEqual (
2022-07-26 22:27:42 +08:00
'Zhejiang / Hangzhou' ,
) ;
2022-09-02 15:05:21 +08:00
fireEvent . mouseDown ( container . querySelector ( '.ant-select-clear' ) ! ) ;
2022-07-26 22:27:42 +08:00
expect ( container . querySelector ( '.ant-select-selection-item' ) ) . toBeFalsy ( ) ;
2018-05-25 19:31:34 +08:00
} ) ;
it ( 'should clear search input when clear selection' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render (
2018-12-07 16:17:45 +08:00
< Cascader options = { options } defaultValue = { [ 'zhejiang' , 'hangzhou' ] } showSearch / > ,
2018-05-25 19:31:34 +08:00
) ;
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : 'xxx' } } ) ;
fireEvent . mouseDown ( container . querySelector ( '.ant-select-clear' ) ! ) ;
expect ( container . querySelector ( 'input' ) ? . value ) . toEqual ( '' ) ;
2018-05-25 19:31:34 +08:00
} ) ;
it ( 'should change filtered item when options are changed' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container , rerender } = render ( < Cascader options = { options } showSearch = { { filter } } / > ) ;
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : 'a' } } ) ;
2022-07-26 22:27:42 +08:00
expect ( container . querySelectorAll ( '.ant-cascader-menu-item' ) . length ) . toBe ( 2 ) ;
rerender ( < Cascader options = { [ options [ 0 ] ] } showSearch = { { filter } } / > ) ;
expect ( container . querySelectorAll ( '.ant-cascader-menu-item' ) . length ) . toBe ( 1 ) ;
2018-05-25 19:31:34 +08:00
} ) ;
2018-07-28 13:29:39 +08:00
2020-03-19 15:31:14 +08:00
it ( 'should select item immediately when searching and pressing down arrow key' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render ( < Cascader options = { options } showSearch = { { filter } } / > ) ;
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : 'a' } } ) ;
2022-07-26 22:27:42 +08:00
expect ( container . querySelectorAll ( '.ant-cascader-menu-item' ) . length ) . toBe ( 2 ) ;
expect ( container . querySelectorAll ( '.ant-cascader-menu-item-active' ) . length ) . toBe ( 0 ) ;
2022-09-02 15:05:21 +08:00
fireEvent . keyDown ( container . querySelector ( 'input' ) ! , { key : 'Down' , keyCode : 40 } ) ;
2022-07-26 22:27:42 +08:00
expect ( container . querySelectorAll ( '.ant-cascader-menu-item-active' ) . length ) . toBe ( 1 ) ;
2020-03-19 15:31:14 +08:00
} ) ;
2018-07-28 13:29:39 +08:00
it ( 'can use fieldNames' , ( ) = > {
2022-09-30 16:59:29 +08:00
const customOptions = [
2018-12-07 16:17:45 +08:00
{
code : 'zhejiang' ,
name : 'Zhejiang' ,
items : [
{
code : 'hangzhou' ,
name : 'Hangzhou' ,
items : [
{
code : 'xihu' ,
name : 'West Lake' ,
} ,
] ,
} ,
] ,
} ,
{
code : 'jiangsu' ,
name : 'Jiangsu' ,
items : [
{
code : 'nanjing' ,
name : 'Nanjing' ,
items : [
{
code : 'zhonghuamen' ,
name : 'Zhong Hua Men' ,
} ,
] ,
} ,
] ,
} ,
] ;
2021-08-31 15:51:02 +08:00
2023-06-07 21:59:21 +08:00
const onChange = jest . fn ( ) ;
2021-08-31 15:51:02 +08:00
2022-07-26 22:27:42 +08:00
const { container } = render (
2018-11-06 12:36:03 +08:00
< Cascader
2022-09-30 16:59:29 +08:00
options = { customOptions }
2021-08-31 15:51:02 +08:00
onChange = { onChange }
2018-11-06 12:36:03 +08:00
fieldNames = { {
children : 'items' ,
label : 'name' ,
value : 'code' ,
} }
2021-08-31 15:51:02 +08:00
open
2018-12-07 16:17:45 +08:00
/ > ,
2018-11-06 12:36:03 +08:00
) ;
2021-08-31 15:51:02 +08:00
2022-07-26 22:27:42 +08:00
clickOption ( container , 0 , 0 ) ;
clickOption ( container , 1 , 0 ) ;
clickOption ( container , 2 , 0 ) ;
2022-09-02 15:05:21 +08:00
expect ( container . querySelector ( '.ant-select-selection-item' ) ? . textContent ) . toEqual (
2021-08-31 15:51:02 +08:00
'Zhejiang / Hangzhou / West Lake' ,
) ;
expect ( onChange ) . toHaveBeenCalledWith ( [ 'zhejiang' , 'hangzhou' , 'xihu' ] , expect . anything ( ) ) ;
2018-11-06 12:36:03 +08:00
} ) ;
2019-07-09 16:29:42 +08:00
it ( 'should show not found content when options.length is 0' , ( ) = > {
2022-09-30 16:59:29 +08:00
const { container } = render ( < Cascader options = { [ ] } / > ) ;
2022-07-26 22:27:42 +08:00
toggleOpen ( container ) ;
expect ( getDropdown ( container ) ) . toMatchSnapshot ( ) ;
2019-07-09 16:29:42 +08:00
} ) ;
2021-08-31 15:51:02 +08:00
it ( 'not found content should be disabled' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render ( < Cascader options = { [ ] } open / > ) ;
expect ( container . querySelectorAll ( '.ant-cascader-menu-item-disabled' ) . length ) . toBe ( 1 ) ;
2020-11-30 11:31:22 +08:00
} ) ;
2018-11-26 11:29:16 +08:00
describe ( 'limit filtered item count' , ( ) = > {
2023-06-07 21:59:21 +08:00
const errorSpy = jest . spyOn ( console , 'error' ) . mockImplementation ( ( ) = > { } ) ;
2018-11-26 11:29:16 +08:00
afterAll ( ( ) = > {
errorSpy . mockRestore ( ) ;
} ) ;
it ( 'limit with positive number' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render (
< Cascader options = { options } showSearch = { { filter , limit : 1 } } / > ,
) ;
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : 'a' } } ) ;
2022-07-26 22:27:42 +08:00
expect ( container . querySelectorAll ( '.ant-cascader-menu-item' ) ) . toHaveLength ( 1 ) ;
2018-11-26 11:29:16 +08:00
} ) ;
it ( 'not limit' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render (
< Cascader options = { options } showSearch = { { filter , limit : false } } / > ,
) ;
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : 'a' } } ) ;
2022-07-26 22:27:42 +08:00
expect ( container . querySelectorAll ( '.ant-cascader-menu-item' ) ) . toHaveLength ( 2 ) ;
2018-11-26 11:29:16 +08:00
} ) ;
it ( 'negative limit' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render (
< Cascader options = { options } showSearch = { { filter , limit : - 1 } } / > ,
) ;
2022-09-02 15:05:21 +08:00
fireEvent . click ( container . querySelector ( 'input' ) ! ) ;
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : 'a' } } ) ;
2022-07-26 22:27:42 +08:00
expect ( container . querySelectorAll ( '.ant-cascader-menu-item' ) ) . toHaveLength ( 2 ) ;
2018-11-26 11:29:16 +08:00
} ) ;
} ) ;
2019-07-08 10:57:34 +08:00
2021-08-31 15:51:02 +08:00
// FIXME: Move to `rc-tree-select` instead
2023-06-07 21:59:21 +08:00
// eslint-disable-next-line jest/no-disabled-tests
2021-10-12 13:14:26 +08:00
it . skip ( 'should warning if not find `value` in `options`' , ( ) = > {
2023-06-07 21:59:21 +08:00
const errorSpy = jest . spyOn ( console , 'error' ) . mockImplementation ( ( ) = > { } ) ;
2022-07-26 22:27:42 +08:00
render ( < Cascader options = { [ { label : 'a' , value : 'a' , children : [ { label : 'b' } ] } ] } / > ) ;
2021-10-12 13:14:26 +08:00
expect ( errorSpy ) . toHaveBeenCalledWith (
'Warning: [antd: Cascader] Not found `value` in `options`.' ,
) ;
errorSpy . mockRestore ( ) ;
} ) ;
2019-07-20 12:20:00 +08:00
// https://github.com/ant-design/ant-design/issues/17690
it ( 'should not breaks when children is null' , ( ) = > {
const optionsWithChildrenNull = [
{
value : 'zhejiang' ,
label : 'Zhejiang' ,
children : [
{
value : 'hangzhou' ,
label : 'Hangzhou' ,
2024-04-12 17:30:32 +08:00
children : null as any ,
2019-07-20 12:20:00 +08:00
} ,
] ,
} ,
] ;
expect ( ( ) = > {
2022-07-26 22:27:42 +08:00
render ( < Cascader options = { optionsWithChildrenNull } / > ) ;
2019-07-20 12:20:00 +08:00
} ) . not . toThrow ( ) ;
} ) ;
2019-08-17 22:29:02 +08:00
2019-10-15 19:23:26 +08:00
it ( 'placeholder works correctly' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container , rerender } = render ( < Cascader options = { [ ] } / > ) ;
2022-09-02 15:05:21 +08:00
expect ( container . querySelector ( '.ant-select-selection-placeholder' ) ? . textContent ) . toEqual ( '' ) ;
2019-10-15 19:23:26 +08:00
const customPlaceholder = 'Custom placeholder' ;
2022-07-26 22:27:42 +08:00
rerender ( < Cascader options = { [ ] } placeholder = { customPlaceholder } / > ) ;
2022-09-02 15:05:21 +08:00
expect ( container . querySelector ( '.ant-select-selection-placeholder' ) ? . textContent ) . toEqual (
2022-07-26 22:27:42 +08:00
customPlaceholder ,
) ;
2019-10-15 19:23:26 +08:00
} ) ;
2020-03-20 15:48:44 +08:00
2022-07-26 22:27:42 +08:00
it ( 'placement work correctly' , async ( ) = > {
2022-09-30 16:59:29 +08:00
const customOptions = [
2022-01-20 16:54:47 +08:00
{
value : 'zhejiang' ,
label : 'Zhejiang' ,
children : [
{
value : 'hangzhou' ,
label : 'Hangzhou' ,
} ,
] ,
} ,
] ;
2022-09-30 16:59:29 +08:00
const { container } = render ( < Cascader options = { customOptions } placement = "topRight" / > ) ;
2022-07-26 22:27:42 +08:00
toggleOpen ( container ) ;
2023-06-07 21:59:21 +08:00
// Inject in tests/__mocks__/rc-trigger.js
expect ( ( global as any ) ? . triggerProps . popupPlacement ) . toEqual ( 'topRight' ) ;
2022-01-20 16:54:47 +08:00
} ) ;
2020-01-02 19:10:16 +08:00
it ( 'popup correctly with defaultValue RTL' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { asFragment } = render (
2020-01-02 19:10:16 +08:00
< ConfigProvider direction = "rtl" >
2021-08-31 15:51:02 +08:00
< Cascader options = { options } defaultValue = { [ 'zhejiang' , 'hangzhou' ] } open / >
2020-01-02 19:10:16 +08:00
< / ConfigProvider > ,
) ;
2022-07-26 22:27:42 +08:00
expect ( asFragment ( ) . firstChild ) . toMatchSnapshot ( ) ;
2020-01-02 19:10:16 +08:00
} ) ;
2020-03-20 15:48:44 +08:00
2020-01-02 19:10:16 +08:00
it ( 'can be selected in RTL direction' , ( ) = > {
const options2 = [
{
value : 'zhejiang' ,
label : 'Zhejiang' ,
children : [
{
value : 'hangzhou' ,
label : 'Hangzhou' ,
children : [
{
value : 'xihu' ,
label : 'West Lake' ,
} ,
] ,
} ,
] ,
} ,
{
value : 'jiangsu' ,
label : 'Jiangsu' ,
children : [
{
value : 'nanjing' ,
label : 'Nanjing' ,
children : [
{
value : 'zhonghuamen' ,
label : 'Zhong Hua Men' ,
} ,
] ,
} ,
] ,
} ,
] ;
2023-06-07 21:59:21 +08:00
const onChange = jest . fn ( ) ;
2022-07-26 22:27:42 +08:00
const { container } = render (
2020-01-02 19:10:16 +08:00
< ConfigProvider direction = "rtl" >
< Cascader
options = { options2 }
defaultValue = { [ 'zhejiang' , 'hangzhou' ] }
onChange = { onChange }
popupPlacement = "bottomRight"
2023-04-18 11:35:07 +08:00
open
2020-01-02 19:10:16 +08:00
/ >
< / ConfigProvider > ,
) ;
2022-07-26 22:27:42 +08:00
clickOption ( container , 0 , 0 ) ;
expect ( getDropdown ( container ) ) . toMatchSnapshot ( ) ;
2021-08-31 15:51:02 +08:00
2022-07-26 22:27:42 +08:00
clickOption ( container , 1 , 0 ) ;
expect ( getDropdown ( container ) ) . toMatchSnapshot ( ) ;
2021-08-31 15:51:02 +08:00
2022-07-26 22:27:42 +08:00
clickOption ( container , 2 , 0 ) ;
expect ( getDropdown ( container ) ) . toMatchSnapshot ( ) ;
2021-08-31 15:51:02 +08:00
expect ( onChange ) . toHaveBeenCalledTimes ( 1 ) ;
2020-01-02 19:10:16 +08:00
expect ( onChange ) . toHaveBeenCalledWith ( [ 'zhejiang' , 'hangzhou' , 'xihu' ] , expect . anything ( ) ) ;
} ) ;
2020-05-12 10:34:24 +08:00
it ( 'defaultValue works correctly when no match options' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render (
< Cascader options = { options } defaultValue = { [ 'options1' , 'options2' ] } / > ,
) ;
2022-09-02 15:05:21 +08:00
expect ( container . querySelector ( '.ant-select-selection-item' ) ? . textContent ) . toEqual (
2022-07-26 22:27:42 +08:00
'options1 / options2' ,
) ;
2020-05-12 10:34:24 +08:00
} ) ;
2020-05-24 23:52:25 +08:00
it ( 'can be selected when showSearch' , ( ) = > {
2023-06-07 21:59:21 +08:00
const onChange = jest . fn ( ) ;
2022-07-26 22:27:42 +08:00
const { container } = render ( < Cascader options = { options } onChange = { onChange } showSearch / > ) ;
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : 'Zh' } } ) ;
2022-07-26 22:27:42 +08:00
expect ( container . querySelectorAll ( '.ant-cascader-menu' ) . length ) . toBe ( 1 ) ;
clickOption ( container , 0 , 0 ) ;
2020-05-24 23:52:25 +08:00
expect ( onChange ) . toHaveBeenCalledWith ( [ 'zhejiang' , 'hangzhou' , 'xihu' ] , expect . anything ( ) ) ;
} ) ;
2020-08-19 10:43:54 +08:00
it ( 'options should open after press esc and then search' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render ( < Cascader options = { options } showSearch / > ) ;
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : 'jin' } } ) ;
2022-07-26 22:27:42 +08:00
expect ( isOpen ( container ) ) . toBeTruthy ( ) ;
2022-09-02 15:05:21 +08:00
fireEvent . keyDown ( container . querySelector ( 'input' ) ! , { key : 'Esc' , keyCode : 27 } ) ;
2022-07-26 22:27:42 +08:00
expect ( isOpen ( container ) ) . toBeFalsy ( ) ;
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : 'jin' } } ) ;
2022-07-26 22:27:42 +08:00
expect ( isOpen ( container ) ) . toBeTruthy ( ) ;
2020-08-19 10:43:54 +08:00
} ) ;
2020-09-04 10:59:10 +08:00
it ( 'onChange works correctly when the label of fieldNames is the same as value' , ( ) = > {
2023-06-07 21:59:21 +08:00
const onChange = jest . fn ( ) ;
2024-04-12 17:30:32 +08:00
const sameNames = { label : 'label' , value : 'label' } as const ;
2022-07-26 22:27:42 +08:00
const { container } = render (
2020-09-04 10:59:10 +08:00
< Cascader options = { options } onChange = { onChange } showSearch fieldNames = { sameNames } / > ,
) ;
2022-09-02 15:05:21 +08:00
fireEvent . change ( container . querySelector ( 'input' ) ! , { target : { value : 'est' } } ) ;
2022-07-26 22:27:42 +08:00
clickOption ( container , 0 , 0 ) ;
2020-09-04 10:59:10 +08:00
expect ( onChange ) . toHaveBeenCalledWith ( [ 'Zhejiang' , 'Hangzhou' , 'West Lake' ] , expect . anything ( ) ) ;
} ) ;
2021-09-13 15:59:57 +08:00
2022-01-21 11:49:07 +08:00
it ( 'rtl should work well with placement' , ( ) = > {
2022-07-26 22:27:42 +08:00
const { container } = render ( < Cascader options = { options } direction = "rtl" / > ) ;
toggleOpen ( container ) ;
2022-01-21 11:49:07 +08:00
2023-06-07 21:59:21 +08:00
// Inject in tests/__mocks__/rc-trigger.js
expect ( ( global as any ) . triggerProps . popupPlacement ) . toEqual ( 'bottomRight' ) ;
2020-09-04 10:59:10 +08:00
} ) ;
2021-09-13 15:59:57 +08:00
2021-11-30 17:26:51 +08:00
describe ( 'legacy props' , ( ) = > {
2022-09-08 14:33:11 +08:00
it ( 'popupPlacement' , ( ) = > {
2022-08-21 15:32:49 +08:00
render ( < Cascader open popupPlacement = "bottomLeft" / > ) ;
2023-06-07 21:59:21 +08:00
// Inject in tests/__mocks__/rc-trigger.js
2022-09-02 15:05:21 +08:00
expect ( ( global as any ) . triggerProps . popupPlacement ) . toEqual ( 'bottomLeft' ) ;
2021-11-30 17:26:51 +08:00
} ) ;
2022-09-08 14:33:11 +08:00
it ( 'legacy dropdownClassName' , ( ) = > {
resetWarned ( ) ;
2023-06-07 21:59:21 +08:00
const errSpy = jest . spyOn ( console , 'error' ) . mockImplementation ( ( ) = > { } ) ;
2022-09-08 14:33:11 +08:00
const { container } = render ( < Cascader dropdownClassName = "legacy" open / > ) ;
expect ( errSpy ) . toHaveBeenCalledWith (
'Warning: [antd: Cascader] `dropdownClassName` is deprecated. Please use `popupClassName` instead.' ,
) ;
expect ( container . querySelector ( '.legacy' ) ) . toBeTruthy ( ) ;
errSpy . mockRestore ( ) ;
} ) ;
2022-03-26 00:17:34 +08:00
it ( 'should support showCheckedStrategy child' , ( ) = > {
const multipleOptions = [
{
value : 'zhejiang' ,
label : 'Zhejiang' ,
children : [
{
value : 'hangzhou' ,
label : 'Hangzhou' ,
children : [
{
value : 'xihu' ,
label : 'West Lake' ,
} ,
{
value : 'donghu' ,
label : 'East Lake' ,
} ,
] ,
} ,
] ,
} ,
{
value : 'jiangsu' ,
label : 'Jiangsu' ,
children : [
{
value : 'nanjing' ,
label : 'Nanjing' ,
children : [
{
value : 'zhonghuamen' ,
label : 'Zhong Hua Men' ,
} ,
] ,
} ,
] ,
} ,
] ;
2022-09-02 15:05:21 +08:00
let selectedValue : SingleValueType [ ] ;
const onChange = function onChange ( value : SingleValueType [ ] ) {
2022-03-26 00:17:34 +08:00
selectedValue = value ;
} ;
2022-07-26 22:27:42 +08:00
const { container , asFragment } = render (
2022-03-26 00:17:34 +08:00
< Cascader
options = { multipleOptions }
onChange = { onChange }
multiple
showCheckedStrategy = { SHOW_CHILD }
/ > ,
) ;
2022-07-26 22:27:42 +08:00
toggleOpen ( container ) ;
expect ( asFragment ( ) . firstChild ) . toMatchSnapshot ( ) ;
2022-03-26 00:17:34 +08:00
2022-07-26 22:27:42 +08:00
clickOption ( container , 0 , 0 ) ;
clickOption ( container , 1 , 0 ) ;
clickOption ( container , 2 , 0 ) ;
clickOption ( container , 2 , 1 ) ;
2022-09-02 15:05:21 +08:00
expect ( selectedValue ! [ 0 ] . join ( ',' ) ) . toBe ( 'zhejiang,hangzhou,xihu' ) ;
expect ( selectedValue ! [ 1 ] . join ( ',' ) ) . toBe ( 'zhejiang,hangzhou,donghu' ) ;
expect ( selectedValue ! . join ( ',' ) ) . toBe ( 'zhejiang,hangzhou,xihu,zhejiang,hangzhou,donghu' ) ;
2022-03-26 00:17:34 +08:00
} ) ;
it ( 'should support showCheckedStrategy parent' , ( ) = > {
const multipleOptions = [
{
value : 'zhejiang' ,
label : 'Zhejiang' ,
children : [
{
value : 'hangzhou' ,
label : 'Hangzhou' ,
children : [
{
value : 'xihu' ,
label : 'West Lake' ,
} ,
{
value : 'donghu' ,
label : 'East Lake' ,
} ,
] ,
} ,
] ,
} ,
{
value : 'jiangsu' ,
label : 'Jiangsu' ,
children : [
{
value : 'nanjing' ,
label : 'Nanjing' ,
children : [
{
value : 'zhonghuamen' ,
label : 'Zhong Hua Men' ,
} ,
] ,
} ,
] ,
} ,
] ;
2022-09-02 15:05:21 +08:00
let selectedValue : SingleValueType [ ] ;
const onChange = function onChange ( value : SingleValueType [ ] ) {
2022-03-26 00:17:34 +08:00
selectedValue = value ;
} ;
2022-07-26 22:27:42 +08:00
const { container , asFragment } = render (
2022-03-26 00:17:34 +08:00
< Cascader
options = { multipleOptions }
onChange = { onChange }
multiple
showCheckedStrategy = { SHOW_PARENT }
/ > ,
) ;
2022-07-26 22:27:42 +08:00
toggleOpen ( container ) ;
expect ( asFragment ( ) . firstChild ) . toMatchSnapshot ( ) ;
clickOption ( container , 0 , 0 ) ;
clickOption ( container , 1 , 0 ) ;
clickOption ( container , 2 , 0 ) ;
clickOption ( container , 2 , 1 ) ;
2022-03-26 00:17:34 +08:00
2022-09-02 15:05:21 +08:00
expect ( selectedValue ! . length ) . toBe ( 1 ) ;
expect ( selectedValue ! . join ( ',' ) ) . toBe ( 'zhejiang' ) ;
2022-03-26 00:17:34 +08:00
} ) ;
2021-09-13 15:59:57 +08:00
} ) ;
2023-05-12 11:53:51 +08:00
it ( 'should be correct expression with disableCheckbox' , ( ) = > {
const { container } = render (
< Cascader
multiple
options = { [
{
label : '台湾' ,
value : 'tw' ,
children : [
{
label : '福建' ,
value : 'fj' ,
disableCheckbox : true ,
} ,
{
label : '兰州' ,
value : 'lz' ,
} ,
{ label : '北京' , value : 'bj' } ,
] ,
} ,
] }
/ > ,
) ;
fireEvent . mouseDown ( container . querySelector ( '.ant-select-selector' ) ! ) ;
// disabled className
fireEvent . click ( container . querySelector ( '.ant-cascader-menu-item' ) ! ) ;
expect ( container . querySelectorAll ( '.ant-cascader-checkbox-disabled' ) ) . toHaveLength ( 1 ) ;
// Check all children except disableCheckbox When the parent checkbox is checked
expect ( container . querySelectorAll ( '.ant-cascader-checkbox' ) ) . toHaveLength ( 4 ) ;
fireEvent . click ( container . querySelector ( '.ant-cascader-checkbox' ) ! ) ;
expect ( container . querySelectorAll ( '.ant-cascader-checkbox-checked' ) ) . toHaveLength ( 3 ) ;
} ) ;
2023-07-19 20:27:09 +08:00
it ( 'deprecate showArrow' , ( ) = > {
resetWarned ( ) ;
const errSpy = jest . spyOn ( console , 'error' ) . mockImplementation ( ( ) = > { } ) ;
const { container } = render ( < Cascader showArrow / > ) ;
expect ( errSpy ) . toHaveBeenCalledWith (
'Warning: [antd: Cascader] `showArrow` is deprecated which will be removed in next major version. It will be a default behavior, you can hide it by setting `suffixIcon` to null.' ,
) ;
expect ( container . querySelector ( '.ant-select-show-arrow' ) ) . toBeTruthy ( ) ;
errSpy . mockRestore ( ) ;
} ) ;
2017-02-26 16:48:42 +08:00
} ) ;