Skip to content

Commit f939c81

Browse files
committed
Migrate to using @testing-library/user-event
Removes redundant `act` calls as well.
1 parent e70973f commit f939c81

File tree

5 files changed

+298
-108
lines changed

5 files changed

+298
-108
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ const { getByRole, getByLabelText } = render(
8080
expect(getByRole("form")).toHaveFormValues({ food: "" });
8181

8282
// start typing to trigger the `loadOptions`
83-
fireEvent.change(getByLabelText("Food"), { target: { value: "Choc" } });
83+
userEvent.type(getByLabelText("Food"), "Choc");
8484
await selectEvent.select(getByLabelText("Food"), "Chocolate");
8585
expect(getByRole("form")).toHaveFormValues({
8686
food: ["chocolate"],

package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636
},
3737
"homepage": "https://github.com/romgain/react-select-event#readme",
3838
"dependencies": {
39-
"@testing-library/dom": ">=7"
39+
"@testing-library/dom": ">=7",
40+
"@testing-library/user-event": ">=14"
4041
},
4142
"devDependencies": {
4243
"@babel/core": "^7.4.5",
@@ -46,14 +47,14 @@
4647
"@babel/preset-react": "^7.0.0",
4748
"@babel/preset-typescript": "^7.3.3",
4849
"@testing-library/jest-dom": "^5.0.1",
49-
"@testing-library/react": "^12.1.5",
50+
"@testing-library/react": "^14.0.0",
5051
"@types/jest": "^29.1.2",
51-
"@types/react": "^17.0.47",
52+
"@types/react": "^18.2.6",
5253
"@types/react-select": "^5.0.1",
5354
"jest": "^27.0.4",
5455
"prettier": "^2.0.2",
55-
"react": "^17.0.2",
56-
"react-dom": "^17.0.2",
56+
"react": "^18.2.0",
57+
"react-dom": "^18.2.0",
5758
"react-select": "^5.0.0",
5859
"rimraf": "^3.0.0",
5960
"rollup": "^2.0.3",

src/__tests__/select-event.test.tsx

Lines changed: 230 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import "@testing-library/jest-dom/extend-expect";
22

3-
import { fireEvent, render } from "@testing-library/react";
3+
import { render } from "@testing-library/react";
4+
import userEvent from "@testing-library/user-event";
45

56
import React from "react";
67
import Select from "react-select";
@@ -56,27 +57,55 @@ const renderForm = (select: React.ReactNode) => {
5657
};
5758

5859
describe("The openMenu event helper", () => {
59-
it("opens the menu", () => {
60+
it("opens the menu", async () => {
6061
const { getByLabelText, queryByText } = renderForm(
6162
<Select {...defaultProps} />
6263
);
6364
// option is not yet visible
6465
expect(queryByText("Chocolate")).toBeNull();
65-
selectEvent.openMenu(getByLabelText("Food"));
66+
await selectEvent.openMenu(getByLabelText("Food"));
6667
// option can now be seen because menu is open
6768
expect(queryByText("Chocolate")).toBeInTheDocument();
6869
});
6970

7071
it("does not prevent selecting options", async () => {
7172
const { form, input, getByText } = renderForm(<Select {...defaultProps} />);
72-
selectEvent.openMenu(input);
73+
await selectEvent.openMenu(input);
7374
expect(getByText("Chocolate")).toBeInTheDocument();
7475
expect(getByText("Vanilla")).toBeInTheDocument();
7576
expect(getByText("Strawberry")).toBeInTheDocument();
7677
expect(getByText("Mango")).toBeInTheDocument();
7778
await selectEvent.select(input, "Strawberry");
7879
expect(form).toHaveFormValues({ food: "strawberry" });
7980
});
81+
82+
it("allows passing custom userEvent option", async () => {
83+
const user = userEvent.setup();
84+
jest.spyOn(user, "click");
85+
jest.spyOn(user, "type");
86+
87+
const { input } = renderForm(<Select {...defaultProps} />);
88+
89+
await selectEvent.openMenu(input, { user });
90+
91+
expect(user.click).toHaveBeenCalledWith(input);
92+
expect(user.type).toHaveBeenCalledWith(input, "{ArrowDown}");
93+
});
94+
95+
it("allows passing custom userEvent option with setup", async () => {
96+
const user = userEvent.setup();
97+
jest.spyOn(user, "click");
98+
jest.spyOn(user, "type");
99+
100+
const userSelectEvent = selectEvent.setup(user);
101+
102+
const { input } = renderForm(<Select {...defaultProps} />);
103+
104+
await userSelectEvent.openMenu(input);
105+
106+
expect(user.click).toHaveBeenCalledWith(input);
107+
expect(user.type).toHaveBeenCalledWith(input, "{ArrowDown}");
108+
});
80109
});
81110

82111
describe("The select event helpers", () => {
@@ -240,6 +269,7 @@ describe("The select event helpers", () => {
240269
});
241270

242271
it("selects an option in an async input", async () => {
272+
const user = userEvent.setup();
243273
const loadOptions = (_: string, callback: Callback) =>
244274
setTimeout(() => callback(OPTIONS), 100);
245275
const { form, input } = renderForm(
@@ -248,7 +278,7 @@ describe("The select event helpers", () => {
248278
expect(form).toHaveFormValues({ food: "" });
249279

250280
// start typing to trigger the `loadOptions`
251-
fireEvent.change(input, { target: { value: "Choc" } });
281+
await user.type(input, "Choc");
252282
await selectEvent.select(input, "Chocolate");
253283
expect(form).toHaveFormValues({ food: "chocolate" });
254284
});
@@ -344,6 +374,42 @@ describe("The select event helpers", () => {
344374
expect(form).toHaveFormValues({ food: "vanilla" });
345375
});
346376

377+
it("allows passing custom userEvent option", async () => {
378+
const user = userEvent.setup();
379+
jest.spyOn(user, "click");
380+
jest.spyOn(user, "type");
381+
382+
const { input } = renderForm(<Select {...defaultProps} />);
383+
384+
await selectEvent.select(input, "Chocolate", { user });
385+
386+
// Open the dropdown
387+
expect(user.type).toHaveBeenCalledWith(input, "{ArrowDown}");
388+
expect(user.click).toHaveBeenNthCalledWith(1, input);
389+
390+
// Difficult to get correct element here but it's fine as long as we get an element
391+
expect(user.click).toHaveBeenNthCalledWith(2, expect.any(HTMLDivElement));
392+
});
393+
394+
it("allows passing custom userEvent option with setup", async () => {
395+
const user = userEvent.setup();
396+
jest.spyOn(user, "click");
397+
jest.spyOn(user, "type");
398+
399+
const userSelectEvent = selectEvent.setup(user);
400+
401+
const { input } = renderForm(<Select {...defaultProps} />);
402+
403+
await userSelectEvent.select(input, "Chocolate");
404+
405+
// Open the dropdown
406+
expect(user.type).toHaveBeenCalledWith(input, "{ArrowDown}");
407+
expect(user.click).toHaveBeenNthCalledWith(1, input);
408+
409+
// Difficult to get correct element here but it's fine as long as we get an element
410+
expect(user.click).toHaveBeenNthCalledWith(2, expect.any(HTMLDivElement));
411+
});
412+
347413
describe("when asynchronously generating the list of options", () => {
348414
// from https://github.com/JedWatson/react-select/blob/v3.0.0/docs/examples/CreatableAdvanced.js
349415
// mixed with Async Creatable Example from https://react-select.com/creatable
@@ -416,6 +482,56 @@ describe("The select event helpers", () => {
416482

417483
expect(form).toHaveFormValues({ food: "papaya" });
418484
});
485+
486+
it("allows passing custom userEvent option", async () => {
487+
const user = userEvent.setup();
488+
jest.spyOn(user, "click");
489+
jest.spyOn(user, "type");
490+
491+
const { input } = renderForm(<CreatableAdvanced {...defaultProps} />);
492+
493+
await selectEvent.create(input, "papaya", { user });
494+
495+
// Open the dropdown
496+
expect(user.click).toHaveBeenNthCalledWith(1, input);
497+
expect(user.type).toHaveBeenCalledWith(input, "{ArrowDown}");
498+
499+
// Create option
500+
expect(user.type).toHaveBeenNthCalledWith(2, input, "papaya");
501+
502+
// Open dropdown again
503+
expect(user.click).toHaveBeenNthCalledWith(2, input);
504+
505+
// Select the new option
506+
// Difficult to get correct element here but it's fine as long as we get an element
507+
expect(user.click).toHaveBeenNthCalledWith(3, expect.any(HTMLDivElement));
508+
});
509+
510+
it("allows passing custom userEvent option with setup", async () => {
511+
const user = userEvent.setup();
512+
jest.spyOn(user, "click");
513+
jest.spyOn(user, "type");
514+
515+
const userSelectEvent = selectEvent.setup(user);
516+
517+
const { input } = renderForm(<CreatableAdvanced {...defaultProps} />);
518+
519+
await userSelectEvent.create(input, "papaya");
520+
521+
// Open the dropdown
522+
expect(user.click).toHaveBeenNthCalledWith(1, input);
523+
expect(user.type).toHaveBeenCalledWith(input, "{ArrowDown}");
524+
525+
// Create option
526+
expect(user.type).toHaveBeenNthCalledWith(2, input, "papaya");
527+
528+
// Open dropdown again
529+
expect(user.click).toHaveBeenNthCalledWith(2, input);
530+
531+
// Select the new option
532+
// Difficult to get correct element here but it's fine as long as we get an element
533+
expect(user.click).toHaveBeenNthCalledWith(3, expect.any(HTMLDivElement));
534+
});
419535
});
420536

421537
describe("when rendering the dropdown in a portal", () => {
@@ -452,39 +568,119 @@ describe("The select event helpers", () => {
452568
await selectEvent.create(input, "papaya", { container: document.body });
453569
expect(form).toHaveFormValues({ food: "papaya" });
454570
});
571+
});
572+
});
455573

456-
it("clears the first item in a multi-select dropdown", async () => {
457-
const { form, input } = renderForm(
458-
<Creatable
459-
{...defaultProps}
460-
isMulti
461-
defaultValue={[OPTIONS[0], OPTIONS[1], OPTIONS[2]]}
462-
menuPortalTarget={document.body}
463-
/>
464-
);
465-
expect(form).toHaveFormValues({
466-
food: ["chocolate", "vanilla", "strawberry"],
467-
});
468-
469-
await selectEvent.clearFirst(input);
470-
expect(form).toHaveFormValues({ food: ["vanilla", "strawberry"] });
574+
describe("clearFirst", () => {
575+
it("clears the first item in a multi-select dropdown", async () => {
576+
const { form, input } = renderForm(
577+
<Creatable
578+
{...defaultProps}
579+
isMulti
580+
defaultValue={[OPTIONS[0], OPTIONS[1], OPTIONS[2]]}
581+
menuPortalTarget={document.body}
582+
/>
583+
);
584+
expect(form).toHaveFormValues({
585+
food: ["chocolate", "vanilla", "strawberry"],
471586
});
472587

473-
it("clears all items", async () => {
474-
const { form, input } = renderForm(
475-
<Creatable
476-
{...defaultProps}
477-
isMulti
478-
defaultValue={[OPTIONS[0], OPTIONS[1], OPTIONS[2]]}
479-
menuPortalTarget={document.body}
480-
/>
481-
);
482-
expect(form).toHaveFormValues({
483-
food: ["chocolate", "vanilla", "strawberry"],
484-
});
588+
await selectEvent.clearFirst(input);
589+
expect(form).toHaveFormValues({ food: ["vanilla", "strawberry"] });
590+
});
485591

486-
await selectEvent.clearAll(input);
487-
expect(form).toHaveFormValues({ food: "" });
592+
it("allows passing custom userEvent option", async () => {
593+
const user = userEvent.setup();
594+
jest.spyOn(user, "click");
595+
596+
const { input } = renderForm(
597+
<Creatable
598+
{...defaultProps}
599+
isMulti
600+
defaultValue={[OPTIONS[0], OPTIONS[1], OPTIONS[2]]}
601+
menuPortalTarget={document.body}
602+
/>
603+
);
604+
605+
await selectEvent.clearFirst(input, { user });
606+
607+
expect(user.click).toHaveBeenCalledWith(expect.any(SVGSVGElement));
608+
});
609+
610+
it("allows passing custom userEvent option with setup", async () => {
611+
const user = userEvent.setup();
612+
jest.spyOn(user, "click");
613+
614+
const userSelectEvent = selectEvent.setup(user);
615+
616+
const { input } = renderForm(
617+
<Creatable
618+
{...defaultProps}
619+
isMulti
620+
defaultValue={[OPTIONS[0], OPTIONS[1], OPTIONS[2]]}
621+
menuPortalTarget={document.body}
622+
/>
623+
);
624+
625+
await userSelectEvent.clearFirst(input);
626+
627+
expect(user.click).toHaveBeenCalledWith(expect.any(SVGSVGElement));
628+
});
629+
});
630+
631+
describe("clearAll", () => {
632+
it("clears all items", async () => {
633+
const { form, input } = renderForm(
634+
<Creatable
635+
{...defaultProps}
636+
isMulti
637+
defaultValue={[OPTIONS[0], OPTIONS[1], OPTIONS[2]]}
638+
menuPortalTarget={document.body}
639+
/>
640+
);
641+
expect(form).toHaveFormValues({
642+
food: ["chocolate", "vanilla", "strawberry"],
488643
});
644+
645+
await selectEvent.clearAll(input);
646+
expect(form).toHaveFormValues({ food: "" });
647+
});
648+
649+
it("allows passing custom userEvent option", async () => {
650+
const user = userEvent.setup();
651+
jest.spyOn(user, "click");
652+
653+
const { input } = renderForm(
654+
<Creatable
655+
{...defaultProps}
656+
isMulti
657+
defaultValue={[OPTIONS[0], OPTIONS[1], OPTIONS[2]]}
658+
menuPortalTarget={document.body}
659+
/>
660+
);
661+
662+
await selectEvent.clearAll(input, { user });
663+
664+
expect(user.click).toHaveBeenCalledWith(expect.any(SVGSVGElement));
665+
});
666+
667+
it("allows passing custom userEvent option with setup", async () => {
668+
const user = userEvent.setup();
669+
jest.spyOn(user, "click");
670+
671+
const userSelectEvent = selectEvent.setup(user);
672+
673+
const { input } = renderForm(
674+
<Creatable
675+
{...defaultProps}
676+
isMulti
677+
defaultValue={[OPTIONS[0], OPTIONS[1], OPTIONS[2]]}
678+
menuPortalTarget={document.body}
679+
/>
680+
);
681+
682+
await userSelectEvent.clearAll(input);
683+
684+
expect(user.click).toHaveBeenCalledWith(expect.any(SVGSVGElement));
489685
});
490686
});

src/act-compat.ts

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)