Skip to content

Commit d19b4bd

Browse files
authored
Bump node to 14.x and fix-up tests for shouldFocusAfterRender (#919)
* Add test for unmount * fix shouldFocusAfterRender unit test * update yarn.lock * update node to 14.x
1 parent bdd1446 commit d19b4bd

File tree

6 files changed

+1492
-2306
lines changed

6 files changed

+1492
-2306
lines changed

.github/workflows/npm.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ jobs:
1818
- uses: actions/checkout@v2
1919
- name: Prepare repository
2020
run: git fetch --unshallow --tags
21-
- name: Use Node.js 12.x
21+
- name: Use Node.js 14.x
2222
uses: actions/setup-node@v1
2323
with:
24-
node-version: 12.x
24+
node-version: 14.x
2525
- name: Cache node modules
2626
uses: actions/cache@v1
2727
with:

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v13.6.0
1+
v14.18.1

src/__snapshots__/command-palette.test.js.snap

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ exports[`Command List renders a command 1`] = `
186186
style="position: absolute; opacity: 0;"
187187
tabindex="0"
188188
/>
189+
<div
190+
class="ReactModalPortal"
191+
/>
189192
<div
190193
class="ReactModalPortal"
191194
>
@@ -3798,6 +3801,9 @@ exports[`Command List renders a command 1`] = `
37983801
style="position: absolute; opacity: 0;"
37993802
tabindex="0"
38003803
/>
3804+
<div
3805+
class="ReactModalPortal"
3806+
/>
38013807
<div
38023808
class="ReactModalPortal"
38033809
>
@@ -8026,6 +8032,9 @@ exports[`Opening the palette displays the suggestion list 1`] = `
80268032
style="position: absolute; opacity: 0;"
80278033
tabindex="0"
80288034
/>
8035+
<div
8036+
class="ReactModalPortal"
8037+
/>
80298038
<div
80308039
class="ReactModalPortal"
80318040
>
@@ -9915,6 +9924,9 @@ exports[`Opening the palette displays the suggestion list 1`] = `
99159924
style="position: absolute; opacity: 0;"
99169925
tabindex="0"
99179926
/>
9927+
<div
9928+
class="ReactModalPortal"
9929+
/>
99189930
<div
99199931
class="ReactModalPortal"
99209932
>
@@ -14167,6 +14179,9 @@ exports[`props.reactModalParentSelector should render render reat-modal in the t
1416714179
style="position: absolute; opacity: 0;"
1416814180
tabindex="0"
1416914181
/>
14182+
<div
14183+
class="ReactModalPortal"
14184+
/>
1417014185
<div
1417114186
class="ReactModalPortal"
1417214187
>
@@ -15846,6 +15861,9 @@ exports[`props.reactModalParentSelector should render render reat-modal in the t
1584615861
style="position: absolute; opacity: 0;"
1584715862
tabindex="0"
1584815863
/>
15864+
<div
15865+
class="ReactModalPortal"
15866+
/>
1584915867
<div
1585015868
class="ReactModalPortal"
1585115869
>
@@ -17871,6 +17889,9 @@ exports[`props.renderCommand should render a custom command component 1`] = `
1787117889
style="position: absolute; opacity: 0;"
1787217890
tabindex="0"
1787317891
/>
17892+
<div
17893+
class="ReactModalPortal"
17894+
/>
1787417895
<div
1787517896
class="ReactModalPortal"
1787617897
>
@@ -18517,6 +18538,9 @@ exports[`props.renderCommand should render a custom command component 1`] = `
1851718538
style="position: absolute; opacity: 0;"
1851818539
tabindex="0"
1851918540
/>
18541+
<div
18542+
class="ReactModalPortal"
18543+
/>
1852018544
<div
1852118545
class="ReactModalPortal"
1852218546
>
@@ -19509,6 +19533,9 @@ exports[`props.theme should render a custom theme 1`] = `
1950919533
style="position: absolute; opacity: 0;"
1951019534
tabindex="0"
1951119535
/>
19536+
<div
19537+
class="ReactModalPortal"
19538+
/>
1951219539
<div
1951319540
class="ReactModalPortal"
1951419541
>
@@ -20406,6 +20433,9 @@ exports[`props.theme should render a custom theme 1`] = `
2040620433
style="position: absolute; opacity: 0;"
2040720434
tabindex="0"
2040820435
/>
20436+
<div
20437+
class="ReactModalPortal"
20438+
/>
2040920439
<div
2041020440
class="ReactModalPortal"
2041120441
>

src/command-palette.shouldFocusAfterRender.test.js

Lines changed: 63 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
no-new:0 */
66

77
import React from "react";
8-
import { mount } from "enzyme";
98
import CommandPalette from "./command-palette";
109
import mockCommands from "./__mocks__/commands";
11-
10+
import { render, screen, waitFor, waitForElementToBeRemoved, fireEvent } from '@testing-library/react'
11+
import userEvent from '@testing-library/user-event'
12+
import '@testing-library/jest-dom'
1213

1314
// We have to put this in a separate file. Otherwise, the document.activeElement
1415
// will be reseted by other test suite to null which we can't easily
@@ -17,65 +18,70 @@ describe("props.shouldReturnFocusAfterClose", () => {
1718
beforeEach(() => {
1819
global.document.body.innerHTML = "";
1920
});
20-
afterEach(() => {
21-
global.document.body.innerHTML = "";
22-
});
2321

24-
it.skip("should return to focused element after close if true", async () => {
25-
const focusedElement = global.document.createElement("button");
26-
focusedElement.setAttribute("id", "button");
27-
const focusedElement2 = global.document.createElement("button");
22+
it("should return to focused element after close if true", async () => {
23+
// Given shouldReturnFocusAfterClose = true then focus should return
24+
// to the focused element when the command palette is close. We'll setup
25+
// two buttons and force focus to move from the the originally focused button
26+
// to the nextfocused button while the palette is open. Upon closing the palette
27+
// focus will be returned to the originally focused button
28+
2829
const body = global.document.querySelector("body");
29-
body.appendChild(focusedElement);
30-
body.appendChild(focusedElement2);
31-
focusedElement.focus();
32-
expect(global.document.activeElement).toBe(
33-
global.document.querySelector("#button")
34-
);
35-
const commandPalette = mount(
36-
<CommandPalette commands={mockCommands} shouldReturnFocusAfterClose open />
37-
);
38-
expect(global.document.activeElement).toBe(
39-
global.document.querySelector("input")
40-
);
41-
expect(commandPalette.state("showModal")).toEqual(true);
42-
expect(global.document.activeElement).toBe(
43-
global.document.querySelector("input")
44-
);
45-
// Change focus during command palette open
46-
focusedElement2.focus();
47-
expect(global.document.activeElement).toBe(focusedElement2);
48-
commandPalette.instance().handleCloseModal();
49-
await new Promise((r) => setTimeout(r, 50));
50-
expect(global.document.activeElement).toBe(
51-
global.document.querySelector("#button")
52-
);
30+
const originallyFocusedElement = global.document.createElement("button");
31+
const nextFocusedElement = global.document.createElement("button");
32+
originallyFocusedElement.setAttribute("data-testid", "originallyFocusedButton");
33+
body.appendChild(originallyFocusedElement);
34+
body.appendChild(nextFocusedElement);
35+
36+
originallyFocusedElement.focus();
37+
expect(originallyFocusedElement).toHaveFocus();
38+
const commandPalette = render(<CommandPalette commands={mockCommands} shouldReturnFocusAfterClose open />);
39+
const input = screen.getByPlaceholderText("Type a command");
40+
await waitFor(() => {expect(input).toHaveFocus()});
41+
42+
// Change focus while command palette is open
43+
nextFocusedElement.focus();
44+
await waitFor(() => {expect(nextFocusedElement).toHaveFocus()});
45+
46+
// Close the command palette
47+
userEvent.click(input);
48+
userEvent.keyboard('{esc}');
49+
fireEvent.keyDown(input, { key: 'Escape', code: 'Escape' })
50+
await waitForElementToBeRemoved(() => screen.getByLabelText("Command Palette"));
51+
52+
await waitFor(() => { expect(originallyFocusedElement).toHaveFocus() });
5353
});
5454

55-
it.skip("should not return to focused element after close if false", async () => {
56-
const focusedElement = global.document.createElement("button");
57-
focusedElement.setAttribute("id", "button");
55+
it("should not return to focused element after close if false", async () => {
56+
// Given shouldReturnFocusAfterClose = true then focus should return
57+
// to the focused element when the command palette is close. We'll setup
58+
// two buttons and force focus to move from the the originally focused button
59+
// to the nextfocused button while the palette is open. Upon closing the palette
60+
// focus will be returned to the originally focused button
61+
5862
const body = global.document.querySelector("body");
59-
body.appendChild(focusedElement);
60-
focusedElement.focus();
61-
expect(global.document.activeElement).toBe(
62-
global.document.querySelector("#button")
63-
);
64-
const commandPalette = mount(
65-
<CommandPalette
66-
commands={mockCommands}
67-
shouldReturnFocusAfterClose={false}
68-
/>
69-
);
70-
commandPalette.instance().handleOpenModal();
71-
expect(global.document.activeElement).toBe(
72-
global.document.querySelector("input")
73-
);
74-
expect(commandPalette.state("showModal")).toEqual(true);
75-
commandPalette.instance().handleCloseModal();
76-
await new Promise((r) => setTimeout(r, 50));
77-
expect(global.document.activeElement).toBe(
78-
global.document.querySelector("body")
79-
);
63+
const originallyFocusedElement = global.document.createElement("button");
64+
const nextFocusedElement = global.document.createElement("button");
65+
originallyFocusedElement.setAttribute("data-testid", "originallyFocusedButton");
66+
body.appendChild(originallyFocusedElement);
67+
body.appendChild(nextFocusedElement);
68+
69+
originallyFocusedElement.focus();
70+
expect(originallyFocusedElement).toHaveFocus();
71+
const commandPalette = render(<CommandPalette commands={mockCommands} shouldReturnFocusAfterClose={false} open />);
72+
const input = screen.getByPlaceholderText("Type a command");
73+
await waitFor(() => {expect(input).toHaveFocus()});
74+
75+
// Change focus while command palette is open
76+
nextFocusedElement.focus();
77+
await waitFor(() => {expect(nextFocusedElement).toHaveFocus()});
78+
79+
// Close the command palette
80+
userEvent.click(input);
81+
userEvent.keyboard('{esc}');
82+
fireEvent.keyDown(input, { key: 'Escape', code: 'Escape' })
83+
await waitForElementToBeRemoved(() => screen.getByLabelText("Command Palette"));
84+
85+
await waitFor(() => { expect(global.document.body).toHaveFocus() });
8086
});
8187
});

src/command-palette.test.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,20 @@ import sampleAtomCommand from "./examples/sampleAtomCommand";
1515
import sampleChromeCommand from "./examples/sampleChromeCommand";
1616
import chromeTheme from "./themes/chrome-theme";
1717
import { clickDown, clickUp, clickEnter } from "./test-helpers";
18-
import { waitFor, render, screen, fireEvent, unmount } from '@testing-library/react'
18+
import { render, screen, fireEvent } from '@testing-library/react'
1919
import '@testing-library/jest-dom'
20-
import { getByPlaceholderText, prettyDOM } from '@testing-library/dom'
2120
import userEvent from '@testing-library/user-event'
2221

22+
describe("Umounting the palette", () => {
23+
it("should not leave elements in the DOM", () => {
24+
const { commandPalette, unmount } = render(<CommandPalette commands={mockCommands} open />);
25+
const input = screen.getByPlaceholderText('Type a command');
26+
expect(input).toBeInTheDocument();
27+
unmount();
28+
expect(input).not.toBeInTheDocument();
29+
})
30+
});
31+
2332
describe("Loading indicator", () => {
2433
it("should display the spinner by default", () => {
2534
const wrapper = mount(<CommandPalette commands={mockCommands} open />);
@@ -614,16 +623,6 @@ describe("Opening the palette", () => {
614623
});
615624
});
616625

617-
describe.skip("Umounting the palette", () => {
618-
it("should not leave elements in the DOM", () => {
619-
const { commandPalette, unmount } = render(<CommandPalette commands={mockCommands} open />);
620-
const input = screen.getByPlaceholderText('Type a command');
621-
expect(input).toBeInTheDocument();
622-
unmount();
623-
expect(input).not.toBeInTheDocument();
624-
})
625-
});
626-
627626
describe("Closing the palette", () => {
628627
beforeEach(() => {
629628
jest.clearAllMocks();
@@ -637,6 +636,7 @@ describe("Closing the palette", () => {
637636
fireEvent.keyDown(input, { key: 'Escape', code: 'Escape' })
638637
const firstSuggestion = screen.queryAllByText('Start All Data Imports')[0];
639638
expect(firstSuggestion).toBeInTheDocument();
639+
// TODO: assert that the command palette is not visible
640640
});
641641

642642
it("should close the wrapper when clicked outside", () => {

0 commit comments

Comments
 (0)