@@ -442,6 +442,67 @@ configs({ modes: ['ios'] }).forEach(({ title, config }) => {
442442
443443 await verifyInputValues ( inputOtp , [ '1' , '9' , '3' , '' ] ) ;
444444 } ) ;
445+
446+ test ( 'should replace the last value when typing one more than the length' , async ( { page } ) => {
447+ await page . setContent ( `<ion-input-otp>Description</ion-input-otp>` , config ) ;
448+
449+ const inputOtp = page . locator ( 'ion-input-otp' ) ;
450+ const firstInput = inputOtp . locator ( 'input' ) . first ( ) ;
451+ await firstInput . focus ( ) ;
452+
453+ await page . keyboard . type ( '12345' ) ;
454+
455+ await verifyInputValues ( inputOtp , [ '1' , '2' , '3' , '5' ] ) ;
456+ } ) ;
457+
458+ test ( 'should replace the last value when typing one more than the length and the type is text' , async ( {
459+ page,
460+ } , testInfo ) => {
461+ testInfo . annotations . push ( {
462+ type : 'issue' ,
463+ description : 'https://github.com/ionic-team/ionic-framework/issues/30459' ,
464+ } ) ;
465+
466+ await page . setContent ( `<ion-input-otp type="text">Description</ion-input-otp>` , config ) ;
467+
468+ const inputOtp = page . locator ( 'ion-input-otp' ) ;
469+ const firstInput = inputOtp . locator ( 'input' ) . first ( ) ;
470+ await firstInput . focus ( ) ;
471+
472+ await page . keyboard . type ( 'abcde' ) ;
473+
474+ await verifyInputValues ( inputOtp , [ 'a' , 'b' , 'c' , 'e' ] ) ;
475+ } ) ;
476+
477+ test ( 'should not insert or shift when typing an invalid character before a number' , async ( { page } ) => {
478+ await page . setContent ( `<ion-input-otp value="12">Description</ion-input-otp>` , config ) ;
479+
480+ const inputOtp = page . locator ( 'ion-input-otp' ) ;
481+ const firstInput = inputOtp . locator ( 'input' ) . first ( ) ;
482+ await firstInput . focus ( ) ;
483+
484+ // Move cursor to the start of the first input
485+ await firstInput . evaluate ( ( el : HTMLInputElement ) => el . setSelectionRange ( 0 , 0 ) ) ;
486+
487+ await page . keyboard . type ( 'w' ) ;
488+
489+ await verifyInputValues ( inputOtp , [ '1' , '2' , '' , '' ] ) ;
490+ } ) ;
491+
492+ test ( 'should not insert or shift when typing an invalid character after a number' , async ( { page } ) => {
493+ await page . setContent ( `<ion-input-otp value="12">Description</ion-input-otp>` , config ) ;
494+
495+ const inputOtp = page . locator ( 'ion-input-otp' ) ;
496+ const firstInput = inputOtp . locator ( 'input' ) . first ( ) ;
497+ await firstInput . focus ( ) ;
498+
499+ // Move cursor to the end of the first input
500+ await firstInput . evaluate ( ( el : HTMLInputElement ) => el . setSelectionRange ( 1 , 1 ) ) ;
501+
502+ await page . keyboard . type ( 'w' ) ;
503+
504+ await verifyInputValues ( inputOtp , [ '1' , '2' , '' , '' ] ) ;
505+ } ) ;
445506 } ) ;
446507
447508 test . describe ( title ( 'input-otp: autofill functionality' ) , ( ) => {
@@ -460,6 +521,53 @@ configs({ modes: ['ios'] }).forEach(({ title, config }) => {
460521 await expect ( lastInput ) . toBeFocused ( ) ;
461522 } ) ;
462523
524+ test ( 'should handle autofill correctly when all characters are the same' , async ( { page } ) => {
525+ await page . setContent ( `<ion-input-otp>Description</ion-input-otp>` , config ) ;
526+
527+ const firstInput = page . locator ( 'ion-input-otp input' ) . first ( ) ;
528+ await firstInput . focus ( ) ;
529+
530+ await simulateAutofill ( firstInput , '1111' ) ;
531+
532+ const inputOtp = page . locator ( 'ion-input-otp' ) ;
533+ await verifyInputValues ( inputOtp , [ '1' , '1' , '1' , '1' ] ) ;
534+
535+ const lastInput = page . locator ( 'ion-input-otp input' ) . last ( ) ;
536+ await expect ( lastInput ) . toBeFocused ( ) ;
537+ } ) ;
538+
539+ test ( 'should handle autofill correctly when length is 2' , async ( { page } ) => {
540+ await page . setContent ( `<ion-input-otp length="2">Description</ion-input-otp>` , config ) ;
541+
542+ const firstInput = page . locator ( 'ion-input-otp input' ) . first ( ) ;
543+ await firstInput . focus ( ) ;
544+
545+ await simulateAutofill ( firstInput , '12' ) ;
546+
547+ const inputOtp = page . locator ( 'ion-input-otp' ) ;
548+ await verifyInputValues ( inputOtp , [ '1' , '2' ] ) ;
549+
550+ const lastInput = page . locator ( 'ion-input-otp input' ) . last ( ) ;
551+ await expect ( lastInput ) . toBeFocused ( ) ;
552+ } ) ;
553+
554+ test ( 'should handle autofill correctly when length is 2 after typing 1 character' , async ( { page } ) => {
555+ await page . setContent ( `<ion-input-otp length="2">Description</ion-input-otp>` , config ) ;
556+
557+ await page . keyboard . type ( '1' ) ;
558+
559+ const secondInput = page . locator ( 'ion-input-otp input' ) . nth ( 1 ) ;
560+ await secondInput . focus ( ) ;
561+
562+ await simulateAutofill ( secondInput , '22' ) ;
563+
564+ const inputOtp = page . locator ( 'ion-input-otp' ) ;
565+ await verifyInputValues ( inputOtp , [ '2' , '2' ] ) ;
566+
567+ const lastInput = page . locator ( 'ion-input-otp input' ) . last ( ) ;
568+ await expect ( lastInput ) . toBeFocused ( ) ;
569+ } ) ;
570+
463571 test ( 'should handle autofill correctly when it exceeds the length' , async ( { page } ) => {
464572 await page . setContent ( `<ion-input-otp>Description</ion-input-otp>` , config ) ;
465573
0 commit comments