Jest test for a copy to clipboard method using react with typescript
Asked Answered
T

3

6

I am trying to ensure that the right value is copied to the users clipboard when they click a button. This is my copy method. I am using a ref on the input to access the right value.

  protected copyToClipboard() {
   console.log("clicked!");
   const text = this.controls.copyData;

   if (!_.isNil(text)) {
     text.current.focus();
     text.current.select();

     document.execCommand("copy");
     this.setState({copied: true});
   }
 }

For my test:

  test("Ensure right value is copied to clipboard", () => {
    const wrapper = mount(<MyComponent />);

    const copyButton = wrapper.find(".copyBtn");
    copyButton.simulate("click");

    const copyToClipboardSpy = jest.spyOn(document as any, "execCommand");
    wrapper.update();

    expect(copyToClipboardSpy).toHaveBeenCalledWith("copy");
  });

The error I receive when I run the test is TypeError: document.execCommand is not a function which makes sense, but I am unsure how to approach this.

I am relatively new to testing, just to put that out there. I also have read that I may not be able to access the document.execCommand but have struggled to find a good alternative to hijack the test and access the value being copied. I appreciate any advice that can be given on the matter!

Tryma answered 14/5, 2020 at 21:5 Comment(0)
T
16

Posting this in case anyone else was in a similar boat. It's doesn't necessarily check the value yet, but one piece I managed was with the document.execCommand method.

I set up a mock function above the wrapper:

document.execCommand = jest.fn();

With this, the test stopped throwing the TypeError. Then my expectations included checking for the spy to have been called, expect my copy state to have changed to true, and:

expect(document.execCommand).toHaveBeenCalledWith("copy");

Test passes! A possible solution for the value is to see if I can "paste" the value and then check it. Will edit this response if/when I can manage that

Tryma answered 19/5, 2020 at 20:33 Comment(4)
Did you ever figure out how to check the copied value?Attwood
Anyone ever get things to work to place assertions on the value of the clipboard copy and/or to be pasted?Statehood
@suzu94, how to check the copied value?Heather
Well, since you are mocking the ecexCommand("copy") call, the text is not really copied. This just tests that execCommand is called.Natascha
T
6

When you use navigator.clipBoard.writeText instead of using document.exec("copy"), you can refer to this thread for an elegant solution that lets you assert on the content as well.

Tunesmith answered 21/4, 2022 at 9:45 Comment(0)
P
3

Being execCommand no longer an option as it is deprecated (see MDN), you should be using navigator.clipboard.writeText('your copied data');.

To mock navigator.clipboard, you could do the following:

// It's important to keep a copy, so your tests don't bleed
const originalClipboard = navigator.clipboard;

const mockedWriteText = jest.fn();

navigator.clipboard = {
  writeText: mockedWriteText,
};

const copyComponent = await screen.findByTestId('copy-component');
await userEvent.click(copyComponent);

expect(mockedWriteText).toHaveBeenCalledTimes(1);
expect(mockedWriteText).toHaveBeenCalledWith('your copied data');

// Remember to restore the original clipboard
navigator.clipboard = originalClipboard;
jest.resetAllMocks();
  • You can also do Object.assignProperty instead of directly modifying the navigator object.
  • This snippet assumes you are using React Testing Library with User Event.
Pout answered 12/1, 2023 at 14:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.