Skip to content

Commit 9ec87e6

Browse files
committed
fix: nicer error messages for duration min/max violations
1 parent 56d3d79 commit 9ec87e6

File tree

3 files changed

+81
-4
lines changed

3 files changed

+81
-4
lines changed

messages/messages.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ The value must be an integer.
7474

7575
The value must be between %s and %s (inclusive).
7676

77+
# errors.DurationBoundsMin
78+
79+
The value must be at least %s.
80+
81+
# errors.DurationBoundsMax
82+
83+
The value must be no more than %s.
84+
7785
# warning.prefix
7886

7987
Warning:

src/flags/duration.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,14 @@ const validate = (input: string, config: DurationFlagConfig): Duration => {
6161
throw messages.createError('errors.InvalidDuration');
6262
}
6363

64-
if (min && parsedInput < min) {
65-
throw messages.createError('errors.DurationBounds', [min, max]);
66-
}
67-
if (max && parsedInput > max) {
64+
if (min && max && (parsedInput < min || parsedInput > max)) {
6865
throw messages.createError('errors.DurationBounds', [min, max]);
66+
} else if (min && parsedInput < min) {
67+
throw messages.createError('errors.DurationBoundsMin', [min]);
68+
} else if (max && parsedInput > max) {
69+
throw messages.createError('errors.DurationBoundsMax', [max]);
6970
}
71+
7072
return toDuration(parsedInput, unit);
7173
};
7274

test/unit/flags/duration.test.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,71 @@ describe('duration flag', () => {
122122
});
123123
});
124124
});
125+
126+
describe('validation with min not max', () => {
127+
const min = 1;
128+
const buildProps = {
129+
flags: {
130+
wait: durationFlag({
131+
min,
132+
unit: 'minutes',
133+
description: 'test',
134+
char: 'w',
135+
}),
136+
},
137+
};
138+
it('passes', async () => {
139+
const out = await Parser.parse(['--wait=10'], buildProps);
140+
expect(out.flags.wait?.quantity).to.equal(10);
141+
});
142+
it('min passes', async () => {
143+
const out = await Parser.parse([`--wait=${min}`], buildProps);
144+
expect(out.flags.wait?.quantity).to.equal(min);
145+
});
146+
describe('failures', () => {
147+
it('below min fails', async () => {
148+
try {
149+
const out = await Parser.parse([`--wait=${min - 1}`], buildProps);
150+
151+
throw new Error(`Should have thrown an error ${JSON.stringify(out)}`);
152+
} catch (err) {
153+
const error = err as Error;
154+
expect(error.message).to.include(messages.getMessage('errors.DurationBoundsMin', [min]));
155+
}
156+
});
157+
});
158+
});
159+
160+
describe('validation with max not min', () => {
161+
const max = 60;
162+
const buildProps = {
163+
flags: {
164+
wait: durationFlag({
165+
max,
166+
unit: 'minutes',
167+
description: 'test',
168+
char: 'w',
169+
}),
170+
},
171+
};
172+
it('passes', async () => {
173+
const out = await Parser.parse(['--wait=10'], buildProps);
174+
expect(out.flags.wait?.quantity).to.equal(10);
175+
});
176+
it('max passes', async () => {
177+
const out = await Parser.parse([`--wait=${max}`], buildProps);
178+
expect(out.flags.wait?.quantity).to.equal(max);
179+
});
180+
describe('failures', () => {
181+
it('above max fails', async () => {
182+
try {
183+
const out = await Parser.parse([`--wait=${max + 1}`], buildProps);
184+
throw new Error(`Should have thrown an error ${JSON.stringify(out)}`);
185+
} catch (err) {
186+
const error = err as Error;
187+
expect(error.message).to.include(messages.getMessage('errors.DurationBoundsMax', [max]));
188+
}
189+
});
190+
});
191+
});
125192
});

0 commit comments

Comments
 (0)