@@ -81,7 +81,7 @@ describe('DateField Component', () => {
8181 expect ( inputs [ 2 ] ! . value ) . toBe ( '2023' ) ;
8282 } ) ;
8383
84- test ( 'backspace clears previous field when empty ' , ( ) => {
84+ test ( 'backspace deletes one character; moves to previous field when caret at start ' , ( ) => {
8585 const handleChange = jest . fn ( ) ;
8686 const { container } = render (
8787 < Controlled
@@ -98,28 +98,93 @@ describe('DateField Component', () => {
9898 fireEvent . click ( labelNode ! ) ;
9999 } ) ;
100100 const inputs = Array . from ( container . querySelectorAll ( 'input' ) ) ;
101+ const month = inputs [ 0 ] ! ;
102+ const day = inputs [ 1 ] ! ;
103+ const year = inputs [ 2 ] ! ;
101104
102- // Focus last input and clear it with backspace until it moves to previous
103- act ( ( ) => {
104- inputs [ 2 ] ! . focus ( ) ;
105- fireEvent . keyDown ( inputs [ 2 ] ! , { key : 'Backspace' } ) ; // Clears year
106- } ) ;
105+ // Initial assertions
106+ expect ( month . value ) . toBe ( '08' ) ;
107+ expect ( day . value ) . toBe ( '20' ) ;
108+ expect ( year . value ) . toBe ( '2023' ) ;
109+
110+ const deleteLastChar = ( input : HTMLInputElement ) => {
111+ const current = input . value ;
112+ const next = current . slice ( 0 , - 1 ) ;
113+ act ( ( ) => {
114+ fireEvent . keyDown ( input , { key : 'Backspace' } ) ;
115+ // Simulate browser applying new value (Backspace default behavior)
116+ fireEvent . input ( input , { target : { value : next } } ) ;
117+ } ) ;
118+ } ;
119+
120+ // Delete year digits one by one
121+ year . focus ( ) ;
122+ deleteLastChar ( year ) ; // 2023 -> 202
123+ expect ( handleChange ) . toHaveBeenLastCalledWith ( '08/20/202' ) ;
124+ deleteLastChar ( year ) ; // 202 -> 20
125+ expect ( handleChange ) . toHaveBeenLastCalledWith ( '08/20/20' ) ;
126+ deleteLastChar ( year ) ; // 20 -> 2
127+ expect ( handleChange ) . toHaveBeenLastCalledWith ( '08/20/2' ) ;
128+ deleteLastChar ( year ) ; // 2 -> '' (becomes 08/20/)
107129 expect ( handleChange ) . toHaveBeenLastCalledWith ( '08/20/' ) ;
108130
109- // Now last input is empty, backspace again should move to previous and clear day
131+ // Current (year) empty; Backspace now should move to previous (day) and delete its last char
110132 act ( ( ) => {
111- fireEvent . keyDown ( inputs [ 2 ] ! , { key : 'Backspace' } ) ;
133+ fireEvent . keyDown ( year , { key : 'Backspace' } ) ;
112134 } ) ;
135+ expect ( handleChange ) . toHaveBeenLastCalledWith ( '08/2/' ) ;
136+ expect ( document . activeElement ) . toBe ( day ) ;
137+
138+ // Delete remaining day digit via single-char deletion
139+ deleteLastChar ( day ) ; // 2 -> '' => 08//
113140 expect ( handleChange ) . toHaveBeenLastCalledWith ( '08//' ) ;
114141
115- // Finally clear the month field so that all parts empty => '' (not '//' )
142+ // Backspace on empty day moves to month and deletes one char (08 -> 0 )
116143 act ( ( ) => {
117- inputs [ 0 ] ! . focus ( ) ;
118- fireEvent . keyDown ( inputs [ 0 ] ! , { key : 'Backspace' } ) ;
144+ fireEvent . keyDown ( day , { key : 'Backspace' } ) ;
119145 } ) ;
146+ expect ( handleChange ) . toHaveBeenLastCalledWith ( '0//' ) ;
147+ expect ( document . activeElement ) . toBe ( month ) ;
148+
149+ // Delete last month digit
150+ deleteLastChar ( month ) ; // 0 -> '' => all empty -> '' (not '//')
120151 expect ( handleChange ) . toHaveBeenLastCalledWith ( '' ) ;
121- const emittedValuesAfterFullClear = handleChange . mock . calls . map ( ( call ) => call [ 0 ] ) ;
122- expect ( emittedValuesAfterFullClear . includes ( '//' ) ) . toBe ( false ) ;
152+
153+ const emittedValues = handleChange . mock . calls . map ( ( call ) => call [ 0 ] ) ;
154+ // Ensure no final dangling '//' value
155+ expect ( emittedValues . filter ( ( value ) => value === '//' ) ) . toHaveLength ( 0 ) ;
156+ } ) ;
157+
158+ test ( 'backspace at start of non-empty field moves to previous and deletes last char there' , ( ) => {
159+ const handleChange = jest . fn ( ) ;
160+ const { container } = render (
161+ < Controlled
162+ dateFormat = { SupportedDateFormat . US }
163+ value = "08/20/2023"
164+ label = "Date of birth"
165+ onChange = { handleChange }
166+ />
167+ ) ;
168+ const labelNode = Array . from ( container . querySelectorAll ( '*' ) ) . find (
169+ ( element ) => element . textContent === 'Date of birth'
170+ ) ;
171+ act ( ( ) => {
172+ fireEvent . click ( labelNode ! ) ;
173+ } ) ;
174+ const inputs = Array . from ( container . querySelectorAll ( 'input' ) ) ;
175+ const day = inputs [ 1 ] ! ; // Value '20'
176+ const month = inputs [ 0 ] ! ; // Value '08'
177+ // Place caret at start of day input
178+ act ( ( ) => {
179+ day . focus ( ) ;
180+ // Simulate caret at start
181+ day . setSelectionRange ( 0 , 0 ) ;
182+ fireEvent . keyDown ( day , { key : 'Backspace' } ) ;
183+ } ) ;
184+ // Should have deleted last char of month (08 -> 0) keeping day intact
185+ expect ( handleChange ) . toHaveBeenLastCalledWith ( '0/20/2023' ) ;
186+ expect ( month . value ) . toBe ( '0' ) ;
187+ expect ( day . value ) . toBe ( '20' ) ;
123188 } ) ;
124189
125190 test ( 'paste distributes digits across inputs' , ( ) => {
0 commit comments