Skip to content

Commit 3e92792

Browse files
authored
fix(prompt): fix validation and return type of object option values for checkbox and seleect prompt (#718)
1 parent f81e895 commit 3e92792

File tree

4 files changed

+44
-5
lines changed

4 files changed

+44
-5
lines changed

prompt/checkbox.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { KeyCode } from "@cliffy/keycode";
2+
import { equal } from "@std/assert/equal";
23
import { WidenType } from "./_utils.ts";
34
import { brightBlue, dim, green, red } from "@std/fmt/colors";
45
import { Figures, getFiguresByKeys } from "./_figures.ts";
@@ -24,7 +25,7 @@ export interface CheckboxOptions<TValue>
2425
keys?: CheckboxKeys;
2526
/** An array of child options. */
2627
options: Array<
27-
| Extract<TValue, string | number>
28+
// | Extract<TValue, string | number>
2829
| Extract<WidenType<TValue>, string | number>
2930
| CheckboxOption<TValue>
3031
| CheckboxOptionGroup<TValue>
@@ -460,7 +461,7 @@ export class Checkbox<TValue> extends GenericList<
460461
const isValidValue = Array.isArray(value) &&
461462
value.every((val) =>
462463
options.findIndex((option: CheckboxOptionSettings<TValue>) =>
463-
option.value === val
464+
equal(option.value, val)
464465
) !== -1
465466
);
466467

prompt/select.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
} from "./_generic_list.ts";
1616
import { GenericPrompt } from "./_generic_prompt.ts";
1717
import { getFiguresByKeys } from "./_figures.ts";
18+
import { equal } from "@std/assert/equal";
1819

1920
/** Select prompt options. */
2021
export interface SelectOptions<TValue>
@@ -23,7 +24,7 @@ export interface SelectOptions<TValue>
2324
keys?: SelectKeys;
2425
/** An array of child options. */
2526
options: Array<
26-
| Extract<TValue, string | number>
27+
// | Extract<TValue, string | number>
2728
| Extract<WidenType<TValue>, string | number>
2829
| SelectOption<TValue>
2930
| SelectOptionGroup<TValue>
@@ -158,7 +159,7 @@ export class Select<TValue> extends GenericList<
158159
*
159160
* @param value Input value.
160161
*/
161-
public static inject(value: string): void {
162+
public static inject<TValue>(value: TValue): void {
162163
GenericPrompt.inject(value);
163164
}
164165

@@ -238,7 +239,7 @@ export class Select<TValue> extends GenericList<
238239
protected validate(value: TValue): boolean | string {
239240
return this.options.findIndex((
240241
option: SelectOptionSettings<TValue> | SelectOptionGroupSettings<TValue>,
241-
) => isOption(option) && option.value === value) !== -1;
242+
) => isOption(option) && equal(option.value, value)) !== -1;
242243
}
243244

244245
/**

prompt/test/checkbox_test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { assertEquals, assertRejects } from "@std/assert";
22
import { bold, red } from "@std/fmt/colors";
3+
import { assertType, IsExact } from "@std/testing/types";
34
import { Checkbox } from "../checkbox.ts";
45

56
Deno.test("prompt checkbox: valid value", async () => {
@@ -17,9 +18,27 @@ Deno.test("prompt checkbox: empty value", async () => {
1718
message: "message",
1819
options: [{ value: "value1" }, { value: "value2" }, "value3"],
1920
});
21+
2022
assertEquals(result, []);
2123
});
2224

25+
Deno.test("prompt checkbox: object value", async () => {
26+
Checkbox.inject([{ id: 1, name: "foo" }]);
27+
28+
const books = [
29+
{ id: 1, name: "foo" },
30+
{ id: 2, name: "bar" },
31+
];
32+
33+
const result = await Checkbox.prompt({
34+
message: "please select a book",
35+
options: books.map((x) => ({ name: x.name, value: x })),
36+
});
37+
38+
assertEquals(result, [{ id: 1, name: "foo" }]);
39+
assertType<IsExact<typeof result, Array<{ id: number; name: string }>>>(true);
40+
});
41+
2342
Deno.test("prompt checkbox: invalid value", async () => {
2443
await assertRejects(
2544
async () => {

prompt/test/select_test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { assertEquals, assertRejects } from "@std/assert";
22
import { bold, red } from "@std/fmt/colors";
3+
import { assertType, IsExact } from "@std/testing/types";
34
import { Select } from "../select.ts";
45

56
Deno.test("prompt select: value", async () => {
@@ -12,6 +13,23 @@ Deno.test("prompt select: value", async () => {
1213
assertEquals(result, "value2");
1314
});
1415

16+
Deno.test("prompt select: object value", async () => {
17+
Select.inject({ id: 1, name: "foo" });
18+
19+
const books = [
20+
{ id: 1, name: "foo" },
21+
{ id: 2, name: "bar" },
22+
];
23+
24+
const result = await Select.prompt({
25+
message: "please select a book",
26+
options: books.map((x) => ({ name: x.name, value: x })),
27+
});
28+
29+
assertEquals(result, { id: 1, name: "foo" });
30+
assertType<IsExact<typeof result, { id: number; name: string }>>(true);
31+
});
32+
1533
Deno.test("prompt select: empty value", async () => {
1634
await assertRejects(
1735
async () => {

0 commit comments

Comments
 (0)