Skip to content

Commit c40ce71

Browse files
MichaelGoberlingMichael Goberling
andauthored
feat: allow flags to have false value in when (#557)
* fix: allow flags to have false value in when * test: false value in when failure case Co-authored-by: Michael Goberling <[email protected]>
1 parent aadcde9 commit c40ce71

File tree

2 files changed

+86
-4
lines changed

2 files changed

+86
-4
lines changed

src/parser/validate.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export async function validate(parse: {
8282

8383
function getPresentFlags(flags: Record<string, unknown>): string[] {
8484
return Object.keys(flags).reduce((acc, key) => {
85-
if (flags[key]) acc.push(key)
85+
if (flags[key] !== undefined) acc.push(key)
8686
return acc
8787
}, [] as string[])
8888
}
@@ -113,7 +113,7 @@ export async function validate(parse: {
113113
continue
114114
if (parse.output.metadata.flags && parse.output.metadata.flags[name]?.setFromDefault)
115115
continue
116-
if (parse.output.flags[flag]) {
116+
if (parse.output.flags[flag] !== undefined) {
117117
return {...base, status: 'failed', reason: `--${flag}=${parse.output.flags[flag]} cannot also be provided when using --${name}`}
118118
}
119119
}
@@ -126,7 +126,7 @@ export async function validate(parse: {
126126
const resolved = await resolveFlags(flags)
127127
const keys = getPresentFlags(resolved)
128128
for (const flag of keys) {
129-
if (flag !== name && parse.output.flags[flag]) {
129+
if (flag !== name && parse.output.flags[flag] !== undefined) {
130130
return {...base, status: 'failed', reason: `--${flag} cannot also be provided when using --${name}`}
131131
}
132132
}
@@ -137,7 +137,7 @@ export async function validate(parse: {
137137
async function validateDependsOn(name: string, flags: FlagRelationship[]): Promise<Validation> {
138138
const base = {name, validationFn: 'validateDependsOn'}
139139
const resolved = await resolveFlags(flags)
140-
const foundAll = Object.values(resolved).every(Boolean)
140+
const foundAll = Object.values(resolved).every(val => val !== undefined)
141141
if (!foundAll) {
142142
const formattedFlags = Object.keys(resolved).map(f => `--${f}`).join(', ')
143143
return {...base, status: 'failed', reason: `All of the following must be provided when using --${name}: ${formattedFlags}`}

test/parser/validate.test.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,88 @@ describe('validate', () => {
748748
})
749749
})
750750

751+
it('should pass if the specified flags whose when property resolves to true, flag has a false value', async () => {
752+
const input = {
753+
argv: [],
754+
flags: {
755+
cookies: {input: [], name: 'cookies'},
756+
sprinkles: {input: [], name: 'sprinkles'},
757+
dessert: {
758+
input: [],
759+
name: 'dessert',
760+
relationships: [
761+
{
762+
type: 'all',
763+
flags: [
764+
'sprinkles',
765+
{name: 'cookies', when: async () => Promise.resolve(true)},
766+
],
767+
},
768+
],
769+
},
770+
},
771+
args: [],
772+
strict: true,
773+
context: {},
774+
'--': true,
775+
}
776+
777+
const output = {
778+
args: {},
779+
argv: [],
780+
flags: {sprinkles: true, dessert: 'ice-cream', cookies: false},
781+
raw: [
782+
{type: 'flag', flag: 'sprinkles', input: true},
783+
{type: 'flag', flag: 'dessert', input: 'ice-cream'},
784+
{type: 'flag', flag: 'cookies', input: false},
785+
],
786+
metadata: {},
787+
}
788+
789+
// @ts-expect-error
790+
await validate({input, output})
791+
})
792+
793+
it('should fail if the specified flags whose when property resolves to true in exclusive, flag has a false value', async () => {
794+
const input = {
795+
argv: [],
796+
flags: {
797+
cookies: {input: [], name: 'cookies'},
798+
sprinkles: {input: [], name: 'sprinkles'},
799+
dessert: {
800+
input: [],
801+
name: 'dessert',
802+
exclusive: [{name: 'cookies', when: async () => Promise.resolve(true)}],
803+
},
804+
},
805+
args: [],
806+
strict: true,
807+
context: {},
808+
'--': true,
809+
}
810+
811+
const output = {
812+
args: {},
813+
argv: [],
814+
flags: {sprinkles: true, dessert: 'ice-cream', cookies: false},
815+
raw: [
816+
{type: 'flag', flag: 'sprinkles', input: true},
817+
{type: 'flag', flag: 'dessert', input: 'ice-cream'},
818+
{type: 'flag', flag: 'cookies', input: false},
819+
],
820+
metadata: {},
821+
}
822+
823+
try {
824+
// @ts-expect-error
825+
await validate({input, output})
826+
assert.fail('should have thrown')
827+
} catch (error) {
828+
const err = error as CLIError
829+
expect(err.message).to.include('--cookies=false cannot also be provided when using --dessert')
830+
}
831+
})
832+
751833
describe('mixed', () => {
752834
const input = {
753835
argv: [],

0 commit comments

Comments
 (0)