@@ -47,6 +47,91 @@ describe('vwc-dial-pad', () => {
4747 return activeEl ;
4848 }
4949
50+ function withFakeTimers ( callback : ( ) => void ) {
51+ vi . useFakeTimers ( ) ;
52+ try {
53+ callback ( ) ;
54+ } finally {
55+ vi . useRealTimers ( ) ;
56+ }
57+ }
58+
59+ function createPointerEvent (
60+ type : string ,
61+ options : EventInit = { }
62+ ) : PointerEvent {
63+ // Create a mock PointerEvent for test environment
64+ const event = new Event ( type , options ) as PointerEvent ;
65+ Object . defineProperty ( event , 'pointerType' , {
66+ value : 'mouse' ,
67+ writable : true ,
68+ } ) ;
69+ Object . defineProperty ( event , 'pointerId' , {
70+ value : 1 ,
71+ writable : true ,
72+ } ) ;
73+ return event ;
74+ }
75+
76+ function simulatePointerLongPress (
77+ button : HTMLElement ,
78+ options : {
79+ duration ?: number ;
80+ onComplete ?: ( ) => void ;
81+ onLeave ?: ( ) => void ;
82+ } = { }
83+ ) {
84+ const { duration = 600 , onComplete, onLeave } = options ;
85+ const pointerDown = createPointerEvent ( 'pointerdown' , {
86+ bubbles : true ,
87+ } ) ;
88+ const pointerUp = createPointerEvent ( 'pointerup' , {
89+ bubbles : true ,
90+ } ) ;
91+
92+ Object . defineProperty ( pointerDown , 'currentTarget' , {
93+ value : button ,
94+ writable : true ,
95+ } ) ;
96+ button . dispatchEvent ( pointerDown ) ;
97+ vi . advanceTimersByTime ( duration ) ;
98+
99+ if ( onLeave ) {
100+ onLeave ( ) ;
101+ }
102+ button . dispatchEvent ( pointerUp ) ;
103+
104+ if ( onComplete ) {
105+ onComplete ( ) ;
106+ }
107+ vi . runAllTimers ( ) ;
108+ }
109+
110+ function simulateKeyboardLongPress (
111+ input : HTMLInputElement ,
112+ options : {
113+ pressDuration ?: number ;
114+ releaseAfter ?: number ;
115+ } = { }
116+ ) {
117+ const { pressDuration = 650 , releaseAfter : providedReleaseAfter } = options ;
118+ const releaseAfter =
119+ providedReleaseAfter !== undefined ? providedReleaseAfter : pressDuration ;
120+ const keyDown = new KeyboardEvent ( 'keydown' , {
121+ key : ' ' ,
122+ bubbles : true ,
123+ repeat : false ,
124+ } ) ;
125+ input . dispatchEvent ( keyDown ) ;
126+ vi . advanceTimersByTime ( releaseAfter ) ;
127+ const keyUp = new KeyboardEvent ( 'keyup' , {
128+ key : ' ' ,
129+ bubbles : true ,
130+ } ) ;
131+ input . dispatchEvent ( keyUp ) ;
132+ vi . runAllTimers ( ) ;
133+ }
134+
50135 beforeEach ( async ( ) => {
51136 element = ( await fixture (
52137 `<${ COMPONENT_TAG } ></${ COMPONENT_TAG } >`
@@ -479,23 +564,6 @@ describe('vwc-dial-pad', () => {
479564 return getDigitButtons ( component ) [ 10 ] as Button ;
480565 }
481566
482- function createPointerEvent (
483- type : string ,
484- options : EventInit = { }
485- ) : PointerEvent {
486- // Create a mock PointerEvent for test environment
487- const event = new Event ( type , options ) as PointerEvent ;
488- Object . defineProperty ( event , 'pointerType' , {
489- value : 'mouse' ,
490- writable : true ,
491- } ) ;
492- Object . defineProperty ( event , 'pointerId' , {
493- value : 1 ,
494- writable : true ,
495- } ) ;
496- return event ;
497- }
498-
499567 it ( 'should add "0" when tapping 0' , async ( ) => {
500568 getZeroButton ( element ) . click ( ) ;
501569 await Updates . next ( ) ;
@@ -506,30 +574,16 @@ describe('vwc-dial-pad', () => {
506574 element . pattern = '^\\+?[0-9#*]*$' ;
507575 await Updates . next ( ) ;
508576 const btn = getZeroButton ( element ) ;
509- vi . useFakeTimers ( ) ;
510- try {
511- const pointerDown = createPointerEvent ( 'pointerdown' , {
512- bubbles : true ,
513- } ) ;
514- Object . defineProperty ( pointerDown , 'currentTarget' , {
515- value : btn ,
516- writable : true ,
577+ withFakeTimers ( ( ) => {
578+ simulatePointerLongPress ( btn , {
579+ duration : 600 ,
580+ onComplete : ( ) => {
581+ btn . dispatchEvent ( new MouseEvent ( 'click' , { bubbles : true } ) ) ;
582+ } ,
517583 } ) ;
518- btn . dispatchEvent ( pointerDown ) ;
519- vi . advanceTimersByTime ( 600 ) ;
520- btn . dispatchEvent (
521- createPointerEvent ( 'pointerup' , {
522- bubbles : true ,
523- } )
524- ) ;
525- vi . runAllTimers ( ) ;
526- } finally {
527- vi . useRealTimers ( ) ;
528- }
584+ } ) ;
529585 await Updates . next ( ) ;
530586
531- // Simulate potential click following pointerup; should be suppressed
532- btn . dispatchEvent ( new MouseEvent ( 'click' , { bubbles : true } ) ) ;
533587 await Updates . next ( ) ;
534588 expect ( getTextField ( element ) . value ) . toEqual ( '+' ) ;
535589 } ) ;
@@ -539,21 +593,9 @@ describe('vwc-dial-pad', () => {
539593 element . disabled = true ;
540594 await Updates . next ( ) ;
541595 const btn = getZeroButton ( element ) ;
542- vi . useFakeTimers ( ) ;
543- try {
544- const pointerDown = createPointerEvent ( 'pointerdown' , {
545- bubbles : true ,
546- } ) ;
547- Object . defineProperty ( pointerDown , 'currentTarget' , {
548- value : btn ,
549- writable : true ,
550- } ) ;
551- btn . dispatchEvent ( pointerDown ) ;
552- vi . advanceTimersByTime ( 600 ) ;
553- vi . runAllTimers ( ) ;
554- } finally {
555- vi . useRealTimers ( ) ;
556- }
596+ withFakeTimers ( ( ) => {
597+ simulatePointerLongPress ( btn , { duration : 600 } ) ;
598+ } ) ;
557599 await Updates . next ( ) ;
558600 expect ( getTextField ( element ) . value ) . toEqual ( '' ) ;
559601 } ) ;
@@ -562,28 +604,20 @@ describe('vwc-dial-pad', () => {
562604 element . pattern = '^\\+?[0-9#*]*$' ;
563605 await Updates . next ( ) ;
564606 const btn = getZeroButton ( element ) ;
565- vi . useFakeTimers ( ) ;
566- try {
567- const pointerDown = createPointerEvent ( 'pointerdown' , {
568- bubbles : true ,
607+ withFakeTimers ( ( ) => {
608+ simulatePointerLongPress ( btn , {
609+ duration : 300 ,
610+ onLeave : ( ) => {
611+ // Leave before long press completes
612+ btn . dispatchEvent (
613+ createPointerEvent ( 'pointerleave' , {
614+ bubbles : true ,
615+ } )
616+ ) ;
617+ } ,
569618 } ) ;
570- Object . defineProperty ( pointerDown , 'currentTarget' , {
571- value : btn ,
572- writable : true ,
573- } ) ;
574- btn . dispatchEvent ( pointerDown ) ;
575619 vi . advanceTimersByTime ( 300 ) ;
576- // Leave before long press completes
577- btn . dispatchEvent (
578- createPointerEvent ( 'pointerleave' , {
579- bubbles : true ,
580- } )
581- ) ;
582- vi . advanceTimersByTime ( 300 ) ;
583- vi . runAllTimers ( ) ;
584- } finally {
585- vi . useRealTimers ( ) ;
586- }
620+ } ) ;
587621 await Updates . next ( ) ;
588622 expect ( getTextField ( element ) . value ) . toEqual ( '' ) ;
589623 } ) ;
@@ -833,4 +867,30 @@ describe('vwc-dial-pad', () => {
833867 expect ( element . _errorAnnouncement ) . toBe ( '' ) ;
834868 } ) ;
835869 } ) ;
870+
871+ describe ( 'keyboard events' , function ( ) {
872+ it ( 'should add "+" when long pressing Space in input field' , async ( ) => {
873+ element . pattern = '^\\+?[0-9#*]*$' ;
874+ await Updates . next ( ) ;
875+ const inputEl = getInput ( element ) ;
876+ withFakeTimers ( ( ) => {
877+ simulateKeyboardLongPress ( inputEl , { pressDuration : 650 } ) ;
878+ } ) ;
879+ await Updates . next ( ) ;
880+
881+ expect ( getTextField ( element ) . value ) . toEqual ( '+' ) ;
882+ } ) ;
883+
884+ it ( 'should add space when short pressing Space in input field' , async ( ) => {
885+ element . pattern = '^\\+?[0-9#*]*$' ;
886+ await Updates . next ( ) ;
887+ const inputEl = getInput ( element ) ;
888+ withFakeTimers ( ( ) => {
889+ simulateKeyboardLongPress ( inputEl , { pressDuration : 300 } ) ;
890+ } ) ;
891+ await Updates . next ( ) ;
892+
893+ expect ( getTextField ( element ) . value ) . toEqual ( ' ' ) ;
894+ } ) ;
895+ } ) ;
836896} ) ;
0 commit comments