@@ -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,26 +574,11 @@ 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 ,
517580 } ) ;
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- }
581+ } ) ;
529582 await Updates . next ( ) ;
530583
531584 // Simulate potential click following pointerup; should be suppressed
@@ -539,21 +592,9 @@ describe('vwc-dial-pad', () => {
539592 element . disabled = true ;
540593 await Updates . next ( ) ;
541594 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- }
595+ withFakeTimers ( ( ) => {
596+ simulatePointerLongPress ( btn , { duration : 600 } ) ;
597+ } ) ;
557598 await Updates . next ( ) ;
558599 expect ( getTextField ( element ) . value ) . toEqual ( '' ) ;
559600 } ) ;
@@ -562,28 +603,20 @@ describe('vwc-dial-pad', () => {
562603 element . pattern = '^\\+?[0-9#*]*$' ;
563604 await Updates . next ( ) ;
564605 const btn = getZeroButton ( element ) ;
565- vi . useFakeTimers ( ) ;
566- try {
567- const pointerDown = createPointerEvent ( 'pointerdown' , {
568- bubbles : true ,
606+ withFakeTimers ( ( ) => {
607+ simulatePointerLongPress ( btn , {
608+ duration : 300 ,
609+ onLeave : ( ) => {
610+ // Leave before long press completes
611+ btn . dispatchEvent (
612+ createPointerEvent ( 'pointerleave' , {
613+ bubbles : true ,
614+ } )
615+ ) ;
616+ } ,
569617 } ) ;
570- Object . defineProperty ( pointerDown , 'currentTarget' , {
571- value : btn ,
572- writable : true ,
573- } ) ;
574- btn . dispatchEvent ( pointerDown ) ;
575618 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- }
619+ } ) ;
587620 await Updates . next ( ) ;
588621 expect ( getTextField ( element ) . value ) . toEqual ( '' ) ;
589622 } ) ;
@@ -833,4 +866,30 @@ describe('vwc-dial-pad', () => {
833866 expect ( element . _errorAnnouncement ) . toBe ( '' ) ;
834867 } ) ;
835868 } ) ;
869+
870+ describe ( 'keyboard events' , function ( ) {
871+ it ( 'should add "+" when long pressing Space in input field' , async ( ) => {
872+ element . pattern = '^\\+?[0-9#*]*$' ;
873+ await Updates . next ( ) ;
874+ const inputEl = getInput ( element ) ;
875+ withFakeTimers ( ( ) => {
876+ simulateKeyboardLongPress ( inputEl , { pressDuration : 650 } ) ;
877+ } ) ;
878+ await Updates . next ( ) ;
879+
880+ expect ( getTextField ( element ) . value ) . toEqual ( '+' ) ;
881+ } ) ;
882+
883+ it ( 'should add space when short pressing Space in input field' , async ( ) => {
884+ element . pattern = '^\\+?[0-9#*]*$' ;
885+ await Updates . next ( ) ;
886+ const inputEl = getInput ( element ) ;
887+ withFakeTimers ( ( ) => {
888+ simulateKeyboardLongPress ( inputEl , { pressDuration : 300 } ) ;
889+ } ) ;
890+ await Updates . next ( ) ;
891+
892+ expect ( getTextField ( element ) . value ) . toEqual ( ' ' ) ;
893+ } ) ;
894+ } ) ;
836895} ) ;
0 commit comments