@@ -76,6 +76,28 @@ describe('<Cascader />', () => {
7676 expect ( container . firstChild ) . toHaveClass ( 'ty-cascader_disabled' ) ;
7777 } ) ;
7878
79+ it ( 'should clear the selected value when allowClear is clicked' , ( ) => {
80+ const onChange = jest . fn ( ) ;
81+ const { container, queryByText } = render (
82+ < Cascader
83+ options = { options }
84+ defaultValue = { [ 'zhejiang' , 'hangzhou' , 'xihu' ] }
85+ allowClear
86+ onChange = { onChange }
87+ />
88+ ) ;
89+
90+ const clearButton = container . querySelector ( '.ty-cascader__clear' ) as HTMLButtonElement ;
91+
92+ expect ( clearButton ) . toHaveAttribute ( 'aria-label' , 'Clear selection' ) ;
93+ expect ( clearButton . querySelector ( 'svg' ) ) . toBeTruthy ( ) ;
94+
95+ fireEvent . click ( clearButton ) ;
96+
97+ expect ( onChange ) . toHaveBeenCalledWith ( [ ] , [ ] ) ;
98+ expect ( queryByText ( 'Zhejiang / Hangzhou / West Lake' ) ) . not . toBeInTheDocument ( ) ;
99+ } ) ;
100+
79101 it ( 'should close on outside click' , async ( ) => {
80102 const { container } = render (
81103 < div >
@@ -102,6 +124,85 @@ describe('<Cascader />', () => {
102124 expect ( getByText ( 'Zhejiang / Hangzhou / West Lake' ) ) . toBeInTheDocument ( ) ;
103125 } ) ;
104126
127+ it ( 'should update value on parent selection when changeOnSelect is enabled' , ( ) => {
128+ const onChange = jest . fn ( ) ;
129+ const { container, getByText } = render (
130+ < Cascader options = { options } changeOnSelect onChange = { onChange } />
131+ ) ;
132+
133+ const selector = container . querySelector ( '.ty-cascader__selector' ) ;
134+ fireEvent . click ( selector ! ) ;
135+ fireEvent . click ( getByText ( 'Zhejiang' ) ) ;
136+
137+ expect ( onChange ) . toHaveBeenCalledWith (
138+ [ 'zhejiang' ] ,
139+ [ expect . objectContaining ( { value : 'zhejiang' , label : 'Zhejiang' } ) ]
140+ ) ;
141+ expect ( container . querySelector ( '.ty-cascader__display' ) ) . toHaveTextContent ( 'Zhejiang' ) ;
142+ expect ( document . body . querySelector ( '.ty-cascader__dropdown' ) ) . toBeTruthy ( ) ;
143+ expect ( getByText ( 'Hangzhou' ) ) . toBeInTheDocument ( ) ;
144+ } ) ;
145+
146+ it ( 'should keep the full path after selecting a child in controlled changeOnSelect mode' , ( ) => {
147+ const ChangeOnSelectControlledDemo = ( ) => {
148+ const [ value , setValue ] = React . useState < ( string | number ) [ ] > ( [ ] ) ;
149+
150+ return (
151+ < Cascader
152+ options = { options }
153+ value = { value }
154+ onChange = { ( nextValue ) => setValue ( nextValue ) }
155+ changeOnSelect
156+ placeholder = "Select any level"
157+ />
158+ ) ;
159+ } ;
160+
161+ const { container, getByText } = render ( < ChangeOnSelectControlledDemo /> ) ;
162+
163+ const selector = container . querySelector ( '.ty-cascader__selector' ) ;
164+ fireEvent . click ( selector ! ) ;
165+ fireEvent . click ( getByText ( 'Zhejiang' ) ) ;
166+ fireEvent . click ( getByText ( 'Hangzhou' ) ) ;
167+ fireEvent . click ( getByText ( 'West Lake' ) ) ;
168+
169+ expect ( container . querySelector ( '.ty-cascader__display' ) ) . toHaveTextContent (
170+ 'Zhejiang / Hangzhou / West Lake'
171+ ) ;
172+ } ) ;
173+
174+ it ( 'should preserve parent path when selecting a child after reopening in controlled changeOnSelect mode' , ( ) => {
175+ const ChangeOnSelectControlledDemo = ( ) => {
176+ const [ value , setValue ] = React . useState < ( string | number ) [ ] > ( [ ] ) ;
177+
178+ return (
179+ < div >
180+ < Cascader
181+ options = { options }
182+ value = { value }
183+ onChange = { ( nextValue ) => setValue ( nextValue ) }
184+ changeOnSelect
185+ placeholder = "Select any level"
186+ />
187+ < button > Outside</ button >
188+ </ div >
189+ ) ;
190+ } ;
191+
192+ const { container, getByText } = render ( < ChangeOnSelectControlledDemo /> ) ;
193+
194+ const selector = container . querySelector ( '.ty-cascader__selector' ) ;
195+ fireEvent . click ( selector ! ) ;
196+ fireEvent . click ( getByText ( 'Jiangsu' ) ) ;
197+ fireEvent . click ( getByText ( 'Outside' ) ) ;
198+ fireEvent . click ( selector ! ) ;
199+ fireEvent . click ( getByText ( 'Nanjing' ) ) ;
200+
201+ expect ( container . querySelector ( '.ty-cascader__display' ) ) . toHaveTextContent (
202+ 'Jiangsu / Nanjing'
203+ ) ;
204+ } ) ;
205+
105206 it ( 'should respect the configured popup container' , ( ) => {
106207 const popupContainer = document . createElement ( 'div' ) ;
107208 document . body . appendChild ( popupContainer ) ;
0 commit comments