Skip to content
This repository has been archived by the owner on Mar 23, 2023. It is now read-only.

Commit

Permalink
refactor: filter options in the select dropdown (#2963)
Browse files Browse the repository at this point in the history
  • Loading branch information
brenopolanski authored Oct 16, 2020
1 parent 0bbf07f commit b774cc8
Show file tree
Hide file tree
Showing 20 changed files with 3,223 additions and 2,272 deletions.
20 changes: 10 additions & 10 deletions src/app/__snapshots__/App.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ exports[`App should close splash screen if not demo 1`] = `
class="Toastify"
/>
<div
class="sc-fznLxA kCDRyF"
class="sc-fznyYp ePFTkY"
data-testid="RouterView__wrapper"
>
<div
Expand Down Expand Up @@ -137,7 +137,7 @@ exports[`App should render mock 1`] = `
class="Toastify"
/>
<div
class="sc-fznLxA kCDRyF"
class="sc-fznyYp ePFTkY"
data-testid="RouterView__wrapper"
>
<div
Expand Down Expand Up @@ -257,7 +257,7 @@ exports[`App should render mock 1`] = `
data-testid="profile-card__user--name"
>
<span
class="sc-fzoydu eoIiNI"
class="sc-fzqMAW dOgzZx"
>
John Doe
</span>
Expand Down Expand Up @@ -349,7 +349,7 @@ exports[`App should render mock 1`] = `
data-testid="profile-card__user--name"
>
<span
class="sc-fzoydu eoIiNI"
class="sc-fzqMAW dOgzZx"
>
Jane Doe
</span>
Expand Down Expand Up @@ -451,7 +451,7 @@ exports[`App should render splash screen 1`] = `
class="Toastify"
/>
<div
class="sc-fznLxA kCDRyF"
class="sc-fznyYp ePFTkY"
data-testid="RouterView__wrapper"
>
<div
Expand Down Expand Up @@ -571,7 +571,7 @@ exports[`App should render splash screen 1`] = `
data-testid="profile-card__user--name"
>
<span
class="sc-fzoydu eoIiNI"
class="sc-fzqMAW dOgzZx"
>
John Doe
</span>
Expand Down Expand Up @@ -663,7 +663,7 @@ exports[`App should render splash screen 1`] = `
data-testid="profile-card__user--name"
>
<span
class="sc-fzoydu eoIiNI"
class="sc-fzqMAW dOgzZx"
>
Jane Doe
</span>
Expand Down Expand Up @@ -842,7 +842,7 @@ exports[`App should render welcome screen after splash screen 1`] = `
class="Toastify"
/>
<div
class="sc-fznLxA kCDRyF"
class="sc-fznyYp ePFTkY"
data-testid="RouterView__wrapper"
>
<div
Expand Down Expand Up @@ -962,7 +962,7 @@ exports[`App should render welcome screen after splash screen 1`] = `
data-testid="profile-card__user--name"
>
<span
class="sc-fzoydu eoIiNI"
class="sc-fzqMAW dOgzZx"
>
John Doe
</span>
Expand Down Expand Up @@ -1054,7 +1054,7 @@ exports[`App should render welcome screen after splash screen 1`] = `
data-testid="profile-card__user--name"
>
<span
class="sc-fzoydu eoIiNI"
class="sc-fzqMAW dOgzZx"
>
Jane Doe
</span>
Expand Down
10 changes: 6 additions & 4 deletions src/app/components/SelectDropdown/SelectDropdown.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,18 @@ export const Dropdown = () => {
value: "3",
},
];

return (
<div className="max-w-xs space-y-4">
<Select placeholder="Select option" options={options} />
<Select placeholder="Invalid" isInvalid options={options} />
<Select placeholder="Disabled" disabled options={options} />
<Select options={options} placeholder="Select option" />
<Select options={options} placeholder="Invalid" isInvalid />
<Select options={options} placeholder="Disabled" disabled />

<div className="mt-4">With default value</div>
<Select placeholder="Disabled" options={options} defaultValue="3" />

<div className="mt-4">With default value (disabled)</div>
<Select placeholder="Disabled" disabled options={options} defaultValue="3" />
<Select options={options} defaultValue="3" placeholder="Disabled" disabled />
</div>
);
};
212 changes: 191 additions & 21 deletions src/app/components/SelectDropdown/SelectDropdown.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { act } from "@testing-library/react-hooks";
import React from "react";
import { fireEvent, render } from "testing-library";
import { fireEvent, render, waitFor } from "testing-library";

import { Select } from "./SelectDropdown";

Expand Down Expand Up @@ -57,12 +57,12 @@ describe("SelectDropdown", () => {

it("should toggle select list options", () => {
const options = [{ label: "Option 1", value: "1" }];
const { getByTestId } = render(<Select options={options} defaultValue="3" />);
const { getByTestId } = render(<Select options={options} />);

const toggle = getByTestId("select-list__toggle-button");
const selectDropdown = getByTestId("SelectDropdownInput__input");

act(() => {
fireEvent.click(toggle);
fireEvent.change(selectDropdown, { target: { value: "Opt" } });
});

const firstOption = getByTestId("select-list__toggle-option-0");
Expand All @@ -75,12 +75,12 @@ describe("SelectDropdown", () => {

it("should select option", () => {
const options = [{ label: "Option 1", value: "1" }];
const { getByTestId } = render(<Select options={options} defaultValue="3" />);
const { getByTestId } = render(<Select options={options} />);

const toggle = getByTestId("select-list__toggle-button");
const selectDropdown = getByTestId("SelectDropdownInput__input");

act(() => {
fireEvent.click(toggle);
fireEvent.change(selectDropdown, { target: { value: "Opt" } });
});

const firstOption = getByTestId("select-list__toggle-option-0");
Expand All @@ -95,36 +95,40 @@ describe("SelectDropdown", () => {

it("should highlight option", () => {
const options = [{ label: "Option 1", value: "1" }];
const { getByTestId } = render(<Select options={options} defaultValue="3" />);
const { getByTestId } = render(<Select options={options} />);

const toggle = getByTestId("select-list__toggle-button");
const selectDropdown = getByTestId("SelectDropdownInput__input");

act(() => {
fireEvent.click(toggle);
fireEvent.change(selectDropdown, { target: { value: "Opt" } });
});

const firstOption = getByTestId("select-list__toggle-option-0");
expect(firstOption).toBeTruthy();

act(() => {
fireEvent.mouseOver(firstOption);
fireEvent.keyDown(selectDropdown, { key: "Tab", code: 9 });
});

act(() => {
fireEvent.keyDown(toggle, { key: "ArrowDown", code: 40 });
});
const firstOption = getByTestId("select-list__toggle-option-0");
expect(firstOption).toBeTruthy();

expect(firstOption).toHaveClass("is-highlighted");
});

it("should select options with arrow keys", () => {
const options = [{ label: "Option 1", value: "1" }];
const { getByTestId } = render(<Select options={options} defaultValue="3" />);
const { getByTestId } = render(<Select options={options} />);

const toggle = getByTestId("select-list__toggle-button");
const selectDropdown = getByTestId("SelectDropdownInput__input");

act(() => {
fireEvent.click(toggle);
fireEvent.change(selectDropdown, { target: { value: "Opt" } });
});

act(() => {
fireEvent.keyDown(selectDropdown, { key: "Tab", code: 9 });
});

act(() => {
fireEvent.keyDown(selectDropdown, { key: "Backspace", code: 8 });
});

const firstOption = getByTestId("select-list__toggle-option-0");
Expand All @@ -135,7 +139,7 @@ describe("SelectDropdown", () => {
});

act(() => {
fireEvent.keyDown(toggle, { key: "ArrowDown", code: 40 });
fireEvent.keyDown(selectDropdown, { key: "ArrowDown", code: 40 });
});

expect(firstOption).toHaveClass("is-highlighted");
Expand All @@ -146,4 +150,170 @@ describe("SelectDropdown", () => {

expect(getByTestId("select-list__input")).toHaveValue("1");
});

it("should show typeahead when typing has found at least one match", () => {
const { getByTestId } = render(<Select options={options} />);
const selectDropdown = getByTestId("SelectDropdownInput__input");

act(() => {
fireEvent.change(selectDropdown, { target: { value: "Opt" } });
});

expect(getByTestId("SelectDropdownInput__typeahead")).toHaveTextContent("Option 1");
});

it("should select first matching option with enter", () => {
const { getByTestId } = render(<Select options={options} />);
const selectDropdown = getByTestId("SelectDropdownInput__input");

act(() => {
fireEvent.change(selectDropdown, { target: { value: "Opt" } });
});

act(() => {
fireEvent.keyDown(selectDropdown, { key: "Enter", code: 13 });
});

expect(getByTestId("select-list__input")).toHaveValue("1");
});

it("should select first matching option with tab", () => {
const { getByTestId } = render(<Select options={options} />);
const selectDropdown = getByTestId("SelectDropdownInput__input");

act(() => {
fireEvent.change(selectDropdown, { target: { value: "Opt" } });
});

act(() => {
fireEvent.keyDown(selectDropdown, { key: "Tab", code: 9 });
});

expect(getByTestId("select-list__input")).toHaveValue("1");
});

it("should not select non-matching option after key input and tab", () => {
const { getByTestId } = render(<Select options={options} />);
const selectDropdown = getByTestId("SelectDropdownInput__input");

act(() => {
fireEvent.change(selectDropdown, { target: { value: "Optt" } });
});

act(() => {
fireEvent.keyDown(selectDropdown, { key: "Tab", code: 9 });
});

expect(getByTestId("select-list__input")).toHaveValue("");
});

it("should not select first matched option after random key enter", () => {
const { getByTestId } = render(<Select options={options} />);
const selectDropdown = getByTestId("SelectDropdownInput__input");

act(() => {
fireEvent.change(selectDropdown, { target: { value: "Opt" } });
});

act(() => {
fireEvent.keyDown(selectDropdown, { key: "A", code: 65 });
});

expect(getByTestId("select-list__input")).toHaveValue("");
});

it("should clear selection when changing input", () => {
const { getByTestId } = render(<Select options={options} />);
const selectDropdown = getByTestId("SelectDropdownInput__input");

act(() => {
fireEvent.change(selectDropdown, { target: { value: "Opt" } });
});

act(() => {
fireEvent.keyDown(selectDropdown, { key: "Enter", code: 13 });
});

expect(getByTestId("select-list__input")).toHaveValue("1");

act(() => {
fireEvent.change(selectDropdown, { target: { value: "test" } });
});

act(() => {
fireEvent.keyDown(selectDropdown, { key: "A", code: 65 });
});
act(() => {
fireEvent.keyDown(selectDropdown, { key: "B", code: 65 });
});

expect(getByTestId("select-list__input")).toHaveValue("");
});

it("should select match on blur if available", async () => {
const { getByTestId } = render(<Select options={options} />);
const selectDropdown = getByTestId("SelectDropdownInput__input");

act(() => {
fireEvent.change(selectDropdown, { target: { value: "Opt" } });
});

act(() => {
fireEvent.blur(selectDropdown);
});

await waitFor(() => expect(selectDropdown).toHaveValue("Option 1"));
});

it("should clear input on blur if there is no match", async () => {
const { getByTestId } = render(<Select options={options} />);
const selectDropdown = getByTestId("SelectDropdownInput__input");

act(() => {
fireEvent.change(selectDropdown, { target: { value: "Foobar" } });
});

act(() => {
fireEvent.blur(selectDropdown);
});

await waitFor(() => expect(selectDropdown).toHaveValue(""));
});

it("should not clear input on blur if selected", () => {
const { getByTestId } = render(<Select options={options} />);
const selectDropdown = getByTestId("SelectDropdownInput__input");

act(() => {
fireEvent.change(selectDropdown, { target: { value: "Opt" } });
});

act(() => {
fireEvent.keyDown(selectDropdown, { key: "Enter", code: 13 });
});

expect(selectDropdown).toHaveValue("Option 1");

act(() => {
fireEvent.blur(selectDropdown);
});

expect(selectDropdown).toHaveValue("Option 1");
});

it("should select an option by clicking on it", async () => {
const { getByTestId } = render(<Select options={options} />);

act(() => {
fireEvent.focus(getByTestId("SelectDropdownInput__input"));
});

await waitFor(() => expect(getByTestId("select-list__toggle-option-0")).toBeTruthy());

act(() => {
fireEvent.mouseDown(getByTestId("select-list__toggle-option-0"));
});

expect(getByTestId("select-list__input")).toHaveValue("1");
});
});
Loading

0 comments on commit b774cc8

Please sign in to comment.