@@ -2,6 +2,16 @@ import { expect } from '@playwright/test';
22import type { Locator } from '@playwright/test' ;
33import { configs , test } from '@utils/test/playwright' ;
44
5+ /**
6+ * Simulates an autofill event in an input element with the given value
7+ */
8+ async function simulateAutofill ( input : any , value : string ) {
9+ await input . evaluate ( ( input : any , value : string ) => {
10+ ( input as HTMLInputElement ) . value = value ;
11+ input . dispatchEvent ( new Event ( 'input' , { bubbles : true } ) ) ;
12+ } , value ) ;
13+ }
14+
515/**
616 * Simulates a paste event in an input element with the given value
717 */
@@ -334,7 +344,10 @@ configs({ modes: ['ios'] }).forEach(({ title, config }) => {
334344 const firstInput = page . locator ( 'ion-input-otp input' ) . first ( ) ;
335345 await firstInput . focus ( ) ;
336346
337- await page . keyboard . type ( 'أبجد123' ) ;
347+ // We need to type the numbers separately because the browser
348+ // does not properly handle the script text when mixed with numbers
349+ await page . keyboard . type ( '123' ) ;
350+ await page . keyboard . type ( 'أبجد' ) ;
338351
339352 // Because Arabic is a right-to-left script, JavaScript's handling of RTL text
340353 // causes the array values to be reversed while input boxes maintain LTR order.
@@ -431,6 +444,87 @@ configs({ modes: ['ios'] }).forEach(({ title, config }) => {
431444 } ) ;
432445 } ) ;
433446
447+ test . describe ( title ( 'input-otp: autofill functionality' ) , ( ) => {
448+ test ( 'should handle autofill correctly' , async ( { page } ) => {
449+ await page . setContent ( `<ion-input-otp>Description</ion-input-otp>` , config ) ;
450+
451+ const firstInput = page . locator ( 'ion-input-otp input' ) . first ( ) ;
452+ await firstInput . focus ( ) ;
453+
454+ await simulateAutofill ( firstInput , '1234' ) ;
455+
456+ const inputOtp = page . locator ( 'ion-input-otp' ) ;
457+ await verifyInputValues ( inputOtp , [ '1' , '2' , '3' , '4' ] ) ;
458+
459+ const lastInput = page . locator ( 'ion-input-otp input' ) . last ( ) ;
460+ await expect ( lastInput ) . toBeFocused ( ) ;
461+ } ) ;
462+
463+ test ( 'should handle autofill correctly when it exceeds the length' , async ( { page } ) => {
464+ await page . setContent ( `<ion-input-otp>Description</ion-input-otp>` , config ) ;
465+
466+ const firstInput = page . locator ( 'ion-input-otp input' ) . first ( ) ;
467+ await firstInput . focus ( ) ;
468+
469+ await simulateAutofill ( firstInput , '123456' ) ;
470+
471+ const inputOtp = page . locator ( 'ion-input-otp' ) ;
472+ await verifyInputValues ( inputOtp , [ '1' , '2' , '3' , '4' ] ) ;
473+
474+ const lastInput = page . locator ( 'ion-input-otp input' ) . last ( ) ;
475+ await expect ( lastInput ) . toBeFocused ( ) ;
476+ } ) ;
477+
478+ test ( 'should handle autofill correctly when it is less than the length' , async ( { page } ) => {
479+ await page . setContent ( `<ion-input-otp>Description</ion-input-otp>` , config ) ;
480+
481+ const firstInput = page . locator ( 'ion-input-otp input' ) . first ( ) ;
482+ await firstInput . focus ( ) ;
483+
484+ await simulateAutofill ( firstInput , '12' ) ;
485+
486+ const inputOtp = page . locator ( 'ion-input-otp' ) ;
487+ await verifyInputValues ( inputOtp , [ '1' , '2' , '' , '' ] ) ;
488+
489+ const thirdInput = page . locator ( 'ion-input-otp input' ) . nth ( 2 ) ;
490+ await expect ( thirdInput ) . toBeFocused ( ) ;
491+ } ) ;
492+
493+ test ( 'should handle autofill correctly when using autofill after typing 1 character' , async ( { page } ) => {
494+ await page . setContent ( `<ion-input-otp>Description</ion-input-otp>` , config ) ;
495+
496+ const firstInput = page . locator ( 'ion-input-otp input' ) . first ( ) ;
497+ await firstInput . focus ( ) ;
498+
499+ await page . keyboard . type ( '9' ) ;
500+
501+ const secondInput = page . locator ( 'ion-input-otp input' ) . nth ( 1 ) ;
502+ await secondInput . focus ( ) ;
503+
504+ await simulateAutofill ( secondInput , '1234' ) ;
505+
506+ const inputOtp = page . locator ( 'ion-input-otp' ) ;
507+ await verifyInputValues ( inputOtp , [ '1' , '2' , '3' , '4' ] ) ;
508+
509+ const lastInput = page . locator ( 'ion-input-otp input' ) . last ( ) ;
510+ await expect ( lastInput ) . toBeFocused ( ) ;
511+ } ) ;
512+
513+ test ( 'should handle autofill correctly when autofill value contains invalid characters' , async ( { page } ) => {
514+ await page . setContent ( `<ion-input-otp pattern="[a-zA-Z]">Description</ion-input-otp>` , config ) ;
515+
516+ const firstInput = page . locator ( 'ion-input-otp input' ) . first ( ) ;
517+ await firstInput . focus ( ) ;
518+
519+ await simulateAutofill ( firstInput , '1234' ) ;
520+
521+ const inputOtp = page . locator ( 'ion-input-otp' ) ;
522+ await verifyInputValues ( inputOtp , [ '' , '' , '' , '' ] ) ;
523+
524+ await expect ( firstInput ) . toBeFocused ( ) ;
525+ } ) ;
526+ } ) ;
527+
434528 test . describe ( title ( 'input-otp: focus functionality' ) , ( ) => {
435529 test ( 'should focus the first input box when tabbed to' , async ( { page } ) => {
436530 await page . setContent ( `<ion-input-otp>Description</ion-input-otp>` , config ) ;
@@ -614,6 +708,18 @@ configs({ modes: ['ios'] }).forEach(({ title, config }) => {
614708
615709 await verifyInputValues ( inputOtp , [ '1' , '2' , '3' , '4' ] ) ;
616710 } ) ;
711+
712+ test ( 'should paste mixed language text into all input boxes' , async ( { page } ) => {
713+ await page . setContent ( `<ion-input-otp type="text" length="6">Description</ion-input-otp>` , config ) ;
714+
715+ const firstInput = page . locator ( 'ion-input-otp input' ) . first ( ) ;
716+ await firstInput . focus ( ) ;
717+ await simulatePaste ( firstInput , 'أبجد123' ) ;
718+
719+ const inputOtp = page . locator ( 'ion-input-otp' ) ;
720+
721+ await verifyInputValues ( inputOtp , [ 'أ' , 'ب' , 'ج' , 'د' , '1' , '2' ] ) ;
722+ } ) ;
617723 } ) ;
618724} ) ;
619725
0 commit comments