Skip to content

Commit 497abe9

Browse files
authored
chore: add storybook stories for combobox component (#16451)
1 parent a546a85 commit 497abe9

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import { expect, screen, userEvent, waitFor, within } from "@storybook/test";
3+
import { useState } from "react";
4+
import { Combobox } from "./Combobox";
5+
6+
const options = ["Option 1", "Option 2", "Option 3", "Another Option"];
7+
8+
const ComboboxWithHooks = () => {
9+
const [value, setValue] = useState("");
10+
const [open, setOpen] = useState(false);
11+
const [inputValue, setInputValue] = useState("");
12+
13+
return (
14+
<Combobox
15+
value={value}
16+
options={options}
17+
placeholder="Select option"
18+
open={open}
19+
onOpenChange={setOpen}
20+
inputValue={inputValue}
21+
onInputChange={setInputValue}
22+
onSelect={setValue}
23+
onKeyDown={(e) => {
24+
if (e.key === "Enter" && inputValue && !options.includes(inputValue)) {
25+
setValue(inputValue);
26+
setInputValue("");
27+
setOpen(false);
28+
}
29+
}}
30+
/>
31+
);
32+
};
33+
34+
const meta: Meta<typeof Combobox> = {
35+
title: "components/Combobox",
36+
component: Combobox,
37+
};
38+
39+
export default meta;
40+
type Story = StoryObj<typeof Combobox>;
41+
42+
export const Default: Story = {
43+
render: () => <ComboboxWithHooks />,
44+
};
45+
46+
export const OpenCombobox: Story = {
47+
render: () => <ComboboxWithHooks />,
48+
play: async ({ canvasElement }) => {
49+
const canvas = within(canvasElement);
50+
await userEvent.click(canvas.getByRole("button"));
51+
52+
await waitFor(() => expect(screen.getByRole("dialog")).toBeInTheDocument());
53+
},
54+
};
55+
56+
export const SelectOption: Story = {
57+
render: () => <ComboboxWithHooks />,
58+
play: async ({ canvasElement }) => {
59+
const canvas = within(canvasElement);
60+
await userEvent.click(canvas.getByRole("button"));
61+
await userEvent.click(screen.getByText("Option 1"));
62+
63+
await waitFor(() =>
64+
expect(canvas.getByRole("button")).toHaveTextContent("Option 1"),
65+
);
66+
},
67+
};
68+
69+
export const SearchAndFilter: Story = {
70+
render: () => <ComboboxWithHooks />,
71+
play: async ({ canvasElement }) => {
72+
const canvas = within(canvasElement);
73+
await userEvent.click(canvas.getByRole("button"));
74+
await userEvent.type(screen.getByRole("combobox"), "Another");
75+
await userEvent.click(
76+
screen.getByRole("option", { name: "Another Option" }),
77+
);
78+
79+
await waitFor(() => {
80+
expect(
81+
screen.getByRole("option", { name: "Another Option" }),
82+
).toBeInTheDocument();
83+
expect(
84+
screen.queryByRole("option", { name: "Option 1" }),
85+
).not.toBeInTheDocument();
86+
});
87+
},
88+
};
89+
90+
export const EnterCustomValue: Story = {
91+
render: () => <ComboboxWithHooks />,
92+
play: async ({ canvasElement }) => {
93+
const canvas = within(canvasElement);
94+
await userEvent.click(canvas.getByRole("button"));
95+
await userEvent.type(screen.getByRole("combobox"), "Custom Value{enter}");
96+
97+
await waitFor(() =>
98+
expect(canvas.getByRole("button")).toHaveTextContent("Custom Value"),
99+
);
100+
},
101+
};
102+
103+
export const NoResults: Story = {
104+
render: () => <ComboboxWithHooks />,
105+
play: async ({ canvasElement }) => {
106+
const canvas = within(canvasElement);
107+
await userEvent.click(canvas.getByRole("button"));
108+
await userEvent.type(screen.getByRole("combobox"), "xyz");
109+
110+
await waitFor(() => {
111+
expect(screen.getByText("No results found")).toBeInTheDocument();
112+
expect(screen.getByText("Enter custom value")).toBeInTheDocument();
113+
});
114+
},
115+
};
116+
117+
export const ClearSelectedOption: Story = {
118+
render: () => <ComboboxWithHooks />,
119+
play: async ({ canvasElement }) => {
120+
const canvas = within(canvasElement);
121+
122+
await userEvent.click(canvas.getByRole("button"));
123+
// First select an option
124+
await userEvent.click(screen.getByRole("option", { name: "Option 1" }));
125+
// Then clear it by selecting it again
126+
await userEvent.click(screen.getByRole("option", { name: "Option 1" }));
127+
128+
await waitFor(() =>
129+
expect(canvas.getByRole("button")).toHaveTextContent("Select option"),
130+
);
131+
},
132+
};

0 commit comments

Comments
 (0)