Skip to content

Commit ba0dad8

Browse files
committed
wip: commit progress on useClipboard test
1 parent eb8b552 commit ba0dad8

File tree

1 file changed

+38
-17
lines changed

1 file changed

+38
-17
lines changed

site/src/hooks/useClipboard.test.ts

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import { act, renderHook } from "@testing-library/react";
44
/*
55
Normally, you could call userEvent.setup to enable clipboard mocking, but
66
userEvent doesn't expose a teardown function. It also modifies the global
7-
clipboard, so enabling just one userEvent session will make a mock clipboard
8-
exist for all other tests, even though you didn't tell them to set up a
9-
session. The mock also assumes that the clipboard API will always be
10-
available, which is not true on HTTP-only connections
7+
scope for the whole test file, so enabling just one userEvent session will
8+
make a mock clipboard exist for all other tests, even though you didn't tell
9+
them to set up a session. The mock also assumes that the clipboard API will
10+
always be available, which is not true on HTTP-only connections
1111
1212
Since these tests need to split hairs and differentiate between HTTP and HTTPS
1313
connections, setting up a single userEvent is disastrous. It will make all the
@@ -16,7 +16,9 @@ import { act, renderHook } from "@testing-library/react";
1616
*/
1717
type MockClipboard = Readonly<
1818
Clipboard & {
19-
resetText: () => void;
19+
getMockText: () => string;
20+
setMockText: (newText: string) => void;
21+
resetMockText: () => void;
2022
setIsSecureContext: (newContext: boolean) => void;
2123
}
2224
>;
@@ -42,7 +44,12 @@ function makeMockClipboard(): MockClipboard {
4244

4345
mockClipboardValue = newText;
4446
},
45-
resetText: () => {
47+
48+
getMockText: () => mockClipboardValue,
49+
setMockText: (newText) => {
50+
mockClipboardValue = newText;
51+
},
52+
resetMockText: () => {
4653
mockClipboardValue = "";
4754
},
4855
setIsSecureContext: (newContext) => {
@@ -60,18 +67,34 @@ function makeMockClipboard(): MockClipboard {
6067
const mockClipboard = makeMockClipboard();
6168

6269
beforeAll(() => {
70+
jest.useFakeTimers();
71+
6372
const originalNavigator = window.navigator;
6473
jest.spyOn(window, "navigator", "get").mockImplementation(() => ({
6574
...originalNavigator,
6675
clipboard: mockClipboard,
6776
}));
6877

69-
jest.spyOn(document, "hasFocus").mockImplementation(() => true);
70-
jest.useFakeTimers();
78+
// Not the biggest fan of exposing implementation details like this, but
79+
// making any kind of mock for execCommand is really gnarly in general
80+
global.document.execCommand = jest.fn(() => {
81+
const dummyInput = document.querySelector("input[data-testid=dummy]");
82+
const inputIsFocused =
83+
dummyInput instanceof HTMLInputElement &&
84+
document.activeElement === dummyInput;
85+
86+
let copySuccessful = false;
87+
if (inputIsFocused) {
88+
mockClipboard.setMockText(dummyInput.value);
89+
copySuccessful = true;
90+
}
91+
92+
return copySuccessful;
93+
});
7194
});
7295

7396
afterEach(() => {
74-
mockClipboard.resetText();
97+
mockClipboard.resetMockText();
7598
});
7699

77100
afterAll(() => {
@@ -87,17 +110,15 @@ function renderUseClipboard(textToCopy: string) {
87110
);
88111
}
89112

90-
type UseClipboardTestResult = ReturnType<typeof renderUseClipboard>["result"];
91-
92113
async function assertClipboardTextUpdate(
93-
result: UseClipboardTestResult,
114+
result: ReturnType<typeof renderUseClipboard>["result"],
94115
textToCheck: string,
95116
): Promise<void> {
96117
await act(() => result.current.copyToClipboard());
97118
expect(result.current.showCopiedSuccess).toBe(true);
98119

99-
const clipboardText = await window.navigator.clipboard.readText();
100-
expect(textToCheck).toEqual(clipboardText);
120+
const clipboardText = mockClipboard.getMockText();
121+
expect(clipboardText).toEqual(textToCheck);
101122
}
102123

103124
function scheduleTests(isHttps: boolean) {
@@ -127,7 +148,7 @@ describe(useClipboard.name, () => {
127148
scheduleTests(false);
128149
});
129150

130-
describe("HTTPS connections", () => {
131-
scheduleTests(true);
132-
});
151+
// describe("HTTPS connections", () => {
152+
// scheduleTests(true);
153+
// });
133154
});

0 commit comments

Comments
 (0)