|
| 1 | +importtype{ArgsDef,CommandDef}from'citty' |
| 2 | + |
| 3 | +import{describe,expect,it}from'vitest' |
| 4 | + |
| 5 | +import{commands}from'../../src/commands' |
| 6 | +import{cwdArgs}from'../../src/commands/_shared' |
| 7 | +import{findUnknownFlags,suggestFlags}from'../../src/utils/unknown-args' |
| 8 | + |
| 9 | +constargsDef={ |
| 10 | +'cwd': {type: 'string'}, |
| 11 | +'json': {type: 'boolean'}, |
| 12 | +'logLevel': {type: 'string'}, |
| 13 | +'fork': {type: 'boolean'}, |
| 14 | +'https': {type: 'boolean'}, |
| 15 | +'open.url': {type: 'string'}, |
| 16 | +'port': {type: 'string',alias: ['p']}, |
| 17 | +}satisfiesArgsDef |
| 18 | + |
| 19 | +describe('findUnknownFlags',()=>{ |
| 20 | +it('should accept declared flags, aliases and negations',()=>{ |
| 21 | +const{ flags }=findUnknownFlags(argsDef,['--cwd=.','--json','--no-fork','--port','3000','--help','--version']) |
| 22 | +expect(flags).toEqual([]) |
| 23 | +}) |
| 24 | + |
| 25 | +it('should accept a dotted flag declared whole or by its parent',()=>{ |
| 26 | +expect(findUnknownFlags(argsDef,['--open.url=/admin','--https.cert=x','--https.key','y']).flags).toEqual([]) |
| 27 | +}) |
| 28 | + |
| 29 | +it('should report a flag that is not declared',()=>{ |
| 30 | +expect(findUnknownFlags(argsDef,['--strictport']).flags).toEqual(['strictport']) |
| 31 | +}) |
| 32 | + |
| 33 | +it('should report each unknown flag once',()=>{ |
| 34 | +expect(findUnknownFlags(argsDef,['--nope','--nope=1']).flags).toEqual(['nope']) |
| 35 | +}) |
| 36 | + |
| 37 | +it('should ignore short flags and everything after a separator',()=>{ |
| 38 | +expect(findUnknownFlags(argsDef,['-abc','-x','--','--nope']).flags).toEqual([]) |
| 39 | +}) |
| 40 | + |
| 41 | +it('should ignore positionals and a bare separator',()=>{ |
| 42 | +expect(findUnknownFlags(argsDef,['build','./app','--']).flags).toEqual([]) |
| 43 | +}) |
| 44 | +}) |
| 45 | + |
| 46 | +describe('suggestFlags',()=>{ |
| 47 | +it('should suggest the declared flag a misspelling is closest to',async()=>{ |
| 48 | +awaitexpect(suggestFlags(findUnknownFlags(argsDef,['--loglevel','--jsn']))).resolves.toEqual([ |
| 49 | +{flag: '--loglevel',suggestion: '--logLevel'}, |
| 50 | +{flag: '--jsn',suggestion: '--json'}, |
| 51 | +]) |
| 52 | +}) |
| 53 | + |
| 54 | +it('should not invent a suggestion for an unrelated flag',async()=>{ |
| 55 | +awaitexpect(suggestFlags(findUnknownFlags(argsDef,['--xyzzy']))).resolves.toEqual([{flag: '--xyzzy',suggestion: undefined}]) |
| 56 | +}) |
| 57 | +}) |
| 58 | + |
| 59 | +describe('declared command arguments',()=>{ |
| 60 | +it('should never be reported as unknown',async()=>{ |
| 61 | +constreported: Record<string,string[]>={} |
| 62 | + |
| 63 | +for(constnameofObject.keys(commands)){ |
| 64 | +for(const[commandName,def]ofawaitresolveCommands(name)){ |
| 65 | +constargs=awaitresolveLazy((defasCommandDef<any>).args)??{} |
| 66 | +constargv: string[]=[] |
| 67 | +for(const[flag,definition]ofObject.entries(argsasArgsDef)){ |
| 68 | +if((definitionas{type?: string}).type==='positional'){ |
| 69 | +continue |
| 70 | +} |
| 71 | +argv.push(`--${flag}`) |
| 72 | +} |
| 73 | +const{ flags }=findUnknownFlags({ ...cwdArgs, ...args},argv) |
| 74 | +if(flags.length>0){ |
| 75 | +reported[commandName]=flags |
| 76 | +} |
| 77 | +} |
| 78 | +} |
| 79 | + |
| 80 | +expect(reported).toEqual({}) |
| 81 | +}) |
| 82 | +}) |
| 83 | + |
| 84 | +asyncfunctionresolveCommands(name: string): Promise<Array<[string,unknown]>>{ |
| 85 | +constdef=awaitcommands[nameaskeyoftypeofcommands]()asCommandDef<any> |
| 86 | +constsubCommands=awaitresolveLazy(def.subCommands) |
| 87 | +if(!subCommands){ |
| 88 | +return[[name,def]] |
| 89 | +} |
| 90 | +returnPromise.all(Object.entries(subCommands).map(async([subName,subDef])=>[`${name}${subName}`,awaitresolveLazy(subDef)]as[string,unknown])) |
| 91 | +} |
| 92 | + |
| 93 | +functionresolveLazy<T>(value: T|(()=>T|Promise<T>)|undefined): Promise<T|undefined>{ |
| 94 | +returnPromise.resolve(typeofvalue==='function' ? (valueas()=>T|Promise<T>)() : value) |
| 95 | +} |
0 commit comments