(react) add ref to Select

We encountered a use-case where we needed to blur the select programatically
but the component wasn't offering any way to do that.
This commit is contained in:
Nathan Vasse
2023-10-03 17:02:23 +02:00
committed by NathanVss
parent d647a77c58
commit 1c7a114b6e
12 changed files with 869 additions and 474 deletions

View File

@@ -1,10 +1,10 @@
import userEvent from "@testing-library/user-event";
import { render, screen, waitFor } from "@testing-library/react";
import React, { FormEvent, useState } from "react";
import React, { createRef, FormEvent, useState } from "react";
import { expect } from "vitest";
import { within } from "@testing-library/dom";
import { CunninghamProvider } from ":/components/Provider";
import { Select } from ":/components/Forms/Select/index";
import { Select, SelectHandle } from ":/components/Forms/Select/index";
import {
expectMenuToBeClosed,
expectMenuToBeOpen,
@@ -785,6 +785,55 @@ describe("<Select multi={true} />", () => {
);
expectSelectedOptions(["Paris"]);
});
it("blurs from ref", async () => {
const ref = createRef<SelectHandle>();
render(
<CunninghamProvider>
<Select
label="City"
options={[
{
label: "Paris",
value: "paris",
},
{
label: "Panama",
value: "panama",
},
{
label: "London",
value: "london",
},
]}
multi={true}
ref={ref}
/>
</CunninghamProvider>,
);
const input = screen.getByRole("combobox", {
name: "City",
});
const menu: HTMLDivElement = screen.getByRole("listbox", {
name: "City",
});
const user = userEvent.setup();
// Make sure the select is not focused.
expect(document.activeElement?.className).toEqual("");
// Focus the select.
await user.click(input);
expectMenuToBeOpen(menu);
expect(document.activeElement?.className).toContain("c__button");
// Blur the select.
ref.current?.blur();
// Make sure the select is blured.
await waitFor(() => expectMenuToBeClosed(menu));
expect(document.activeElement?.className).toEqual("");
});
});
describe("Searchable", async () => {
@@ -1343,5 +1392,55 @@ describe("<Select multi={true} />", () => {
screen.getByText("No options available");
});
it("blurs from ref", async () => {
const ref = createRef<SelectHandle>();
render(
<CunninghamProvider>
<Select
label="City"
options={[
{
label: "Paris",
value: "paris",
},
{
label: "Panama",
value: "panama",
},
{
label: "London",
value: "london",
},
]}
multi={true}
searchable={true}
ref={ref}
/>
</CunninghamProvider>,
);
const input = screen.getByRole("combobox", {
name: "City",
});
const menu: HTMLDivElement = screen.getByRole("listbox", {
name: "City",
});
const user = userEvent.setup();
// Make sure the select is not focused.
expect(document.activeElement?.tagName).toEqual("BODY");
// Focus the select by focusing input.
await user.click(input);
expectMenuToBeOpen(menu);
expect(document.activeElement?.tagName).toEqual("INPUT");
// Blur the select.
ref.current?.blur();
// Make sure the select is blured.
await waitFor(() => expectMenuToBeClosed(menu));
expect(document.activeElement?.tagName).toEqual("BODY");
});
});
});