@@ -6,6 +6,8 @@ import { isCancel, settings } from '../../src/utils/index.js';
66import { MockReadable } from '../mock-readable.js' ;
77import { MockWritable } from '../mock-writable.js' ;
88
9+ const waitForTick = ( ) => new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) ) ;
10+
911describe ( 'Prompt' , ( ) => {
1012 let input : MockReadable ;
1113 let output : MockWritable ;
@@ -396,4 +398,79 @@ describe('Prompt', () => {
396398 expect ( instance . error ) . to . equal ( 'must be "valid" (was "invalid")' ) ;
397399 } ) ;
398400 } ) ;
401+
402+ test ( 'validates value with async validation' , async ( ) => {
403+ const instance = new Prompt < string > ( {
404+ input,
405+ output,
406+ render : ( ) => 'foo' ,
407+ validate : async ( value ) => {
408+ await waitForTick ( ) ;
409+ return value === 'valid' ? undefined : 'Invalid value' ;
410+ } ,
411+ } ) ;
412+ instance . prompt ( ) ;
413+
414+ instance . value = 'invalid' ;
415+ input . emit ( 'keypress' , '' , { name : 'return' } ) ;
416+
417+ expect ( instance . state ) . to . equal ( 'validating' ) ;
418+ await waitForTick ( ) ; // Wait for the validation to complete
419+ expect ( instance . state ) . to . equal ( 'error' ) ;
420+ expect ( instance . error ) . to . equal ( 'Invalid value' ) ;
421+ } ) ;
422+
423+ test ( 'accepts valid value with async validation' , async ( ) => {
424+ const instance = new Prompt < string > ( {
425+ input,
426+ output,
427+ render : ( ) => 'foo' ,
428+ validate : async ( value ) => {
429+ await waitForTick ( ) ;
430+ return value === 'valid' ? undefined : 'Invalid value' ;
431+ } ,
432+ } ) ;
433+ instance . prompt ( ) ;
434+
435+ instance . value = 'valid' ;
436+ input . emit ( 'keypress' , '' , { name : 'return' } ) ;
437+
438+ expect ( instance . state ) . to . equal ( 'validating' ) ;
439+ await waitForTick ( ) ; // Wait for the validation to complete
440+ expect ( instance . state ) . to . equal ( 'submit' ) ;
441+ expect ( instance . error ) . to . equal ( '' ) ;
442+ } ) ;
443+
444+ test ( 'ignores keypresses while async validation is pending' , async ( ) => {
445+ const eventSpy = vi . fn ( ) ;
446+ let resolveValidation : ( problem : string | undefined ) => void ;
447+ const validation = new Promise < string | undefined > ( ( resolve ) => {
448+ resolveValidation = resolve ;
449+ } ) ;
450+ const instance = new Prompt < string > ( {
451+ input,
452+ output,
453+ render : ( ) => 'foo' ,
454+ validate : ( ) => validation ,
455+ } ) ;
456+ const resultPromise = instance . prompt ( ) ;
457+
458+ instance . value = 'valid' ;
459+ input . emit ( 'keypress' , '' , { name : 'return' } ) ;
460+
461+ expect ( instance . state ) . to . equal ( 'validating' ) ;
462+
463+ instance . on ( 'key' , eventSpy ) ;
464+ input . emit ( 'keypress' , 'z' , { name : 'z' } ) ;
465+ input . emit ( 'keypress' , '\x03' , { name : 'c' } ) ;
466+
467+ expect ( eventSpy ) . not . toHaveBeenCalled ( ) ;
468+ expect ( instance . state ) . to . equal ( 'validating' ) ;
469+
470+ resolveValidation ! ( undefined ) ;
471+ await resultPromise ;
472+
473+ expect ( instance . state ) . to . equal ( 'submit' ) ;
474+ expect ( instance . error ) . to . equal ( '' ) ;
475+ } ) ;
399476} ) ;
0 commit comments