11import type { NuxtModule } from '../../../../src/commands/module/_utils'
22
3+ import { stripVTControlCharacters as stripAnsi } from 'node:util'
4+
35import { afterEach , beforeEach , describe , expect , it , vi } from 'vitest'
46
57// Mock std-env before importing the module
@@ -125,7 +127,7 @@ describe('selectModulesAutocomplete', () => {
125127 let capturedOptions : any [ ] = [ ]
126128
127129 mockAutocompleteMultiselect . mockImplementation ( async ( opts : any ) => {
128- capturedOptions = opts . options
130+ capturedOptions = opts . options . call ( { userInput : '' } )
129131 return [ ]
130132 } )
131133
@@ -345,7 +347,7 @@ describe('selectModulesAutocomplete', () => {
345347
346348 let capturedOptions : any [ ] = [ ]
347349 mockAutocompleteMultiselect . mockImplementation ( async ( opts : any ) => {
348- capturedOptions = opts . options
350+ capturedOptions = opts . options . call ( { userInput : '' } )
349351 return [ ]
350352 } )
351353
@@ -357,9 +359,82 @@ describe('selectModulesAutocomplete', () => {
357359
358360 expect ( capturedOptions [ 0 ] ) . toEqual ( {
359361 value : '@nuxt/test' ,
360- label : '@nuxt/test' ,
361- hint : 'A test module' , // trailing period removed
362+ label : expect . stringContaining ( '@nuxt/test' ) ,
363+ } )
364+ // trailing period removed
365+ expect ( stripAnsi ( capturedOptions [ 0 ] . label ) ) . toBe ( '@nuxt/test A test module' )
366+ } )
367+
368+ it ( 'should show a description on every option, not only the focused one' , async ( ) => {
369+ vi . doMock ( 'std-env' , ( ) => ( {
370+ hasTTY : true ,
371+ } ) )
372+
373+ let capturedOptions : any [ ] = [ ]
374+ mockAutocompleteMultiselect . mockImplementation ( async ( opts : any ) => {
375+ capturedOptions = opts . options . call ( { userInput : '' } )
376+ return [ ]
377+ } )
378+
379+ const { selectModulesAutocomplete } = await import ( '../../../../src/commands/module/_autocomplete' )
380+
381+ await selectModulesAutocomplete ( {
382+ modules : [
383+ createMockModule ( { npm : '@nuxt/one' , description : 'First module' } ) ,
384+ createMockModule ( { npm : '@nuxt/two' , description : 'Second module' } ) ,
385+ ] ,
386+ } )
387+
388+ expect ( capturedOptions . map ( ( o : any ) => stripAnsi ( o . label ) ) ) . toEqual ( [
389+ '@nuxt/one First module' ,
390+ '@nuxt/two Second module' ,
391+ ] )
392+ expect ( capturedOptions . every ( ( o : any ) => o . hint === undefined ) ) . toBe ( true )
393+ } )
394+
395+ it ( 'should highlight the matched part of the name as the user types' , async ( ) => {
396+ vi . doMock ( 'std-env' , ( ) => ( {
397+ hasTTY : true ,
398+ } ) )
399+
400+ let capturedOptions : any [ ] = [ ]
401+ mockAutocompleteMultiselect . mockImplementation ( async ( opts : any ) => {
402+ capturedOptions = opts . options . call ( { userInput : 'img' } )
403+ return [ ]
404+ } )
405+
406+ const { selectModulesAutocomplete } = await import ( '../../../../src/commands/module/_autocomplete' )
407+
408+ await selectModulesAutocomplete ( {
409+ modules : [ createMockModule ( { npm : '@nuxt/image' , description : 'Images' } ) ] ,
410+ } )
411+
412+ expect ( capturedOptions [ 0 ] . label ) . not . toBe ( stripAnsi ( capturedOptions [ 0 ] . label ) )
413+ expect ( stripAnsi ( capturedOptions [ 0 ] . label ) ) . toBe ( '@nuxt/image Images' )
414+ } )
415+
416+ it ( 'should truncate descriptions to the terminal width' , async ( ) => {
417+ vi . doMock ( 'std-env' , ( ) => ( {
418+ hasTTY : true ,
419+ } ) )
420+
421+ Object . defineProperty ( process . stdout , 'columns' , { value : 60 , writable : true , configurable : true } )
422+
423+ let capturedOptions : any [ ] = [ ]
424+ mockAutocompleteMultiselect . mockImplementation ( async ( opts : any ) => {
425+ capturedOptions = opts . options . call ( { userInput : '' } )
426+ return [ ]
362427 } )
428+
429+ const { selectModulesAutocomplete } = await import ( '../../../../src/commands/module/_autocomplete' )
430+
431+ await selectModulesAutocomplete ( {
432+ modules : [ createMockModule ( { npm : '@nuxt/test' , description : 'A' . repeat ( 200 ) } ) ] ,
433+ } )
434+
435+ const label = stripAnsi ( capturedOptions [ 0 ] . label )
436+ expect ( label . length ) . toBeLessThanOrEqual ( 60 - 5 )
437+ expect ( label . endsWith ( '…' ) ) . toBe ( true )
363438 } )
364439
365440 it ( 'should set required to false' , async ( ) => {
0 commit comments