38

I am trying to test my anchor tag. Once I click it, I want to see if the window.location.href is what I expect.

I've tried to render the anchor, click it, and then test window.location.href:

test('should navigate to ... when link is clicked', () => {
  const { getByText } = render(<a href="https://test.com">Click Me</a>);

  const link = getByText('Click Me');

  fireEvent.click(link);

  expect(window.location.href).toBe("https://www.test.com/");
});

I am expecting the test to pass, but instead the window.location.href is just "http://localhost/" meaning it is not getting updated for whatever reason. I even tried wrapping my expect with await wait, but that didn't work either. I can't find much information about testing anchors with react-testing-library. Maybe there is even a better way to test them than what I am doing. ‍♂️

skyboyer
  • 15,149
  • 4
  • 41
  • 56
jaypee
  • 517
  • 1
  • 5
  • 11

4 Answers4

77

Jest uses jsdom to run its test. jsdom is simulating a browser but it has some limitations. One of these limitations is the fact that you can't change the location. If you want to test that your link works I suggest to check the href attribute of your <a>:

expect(screen.getByText('Click Me').closest('a')).toHaveAttribute('href', 'https://www.test.com/')
Fez Vrasta
  • 11,462
  • 19
  • 73
  • 135
Giorgio Polvara - Gpx
  • 12,268
  • 5
  • 53
  • 55
  • I get `TypeError: getByText(...).closest is not a function` any ideas? – S.. Nov 20 '19 at 11:43
  • 2
    I guess that `getByText` finds nothing in your case – Giorgio Polvara - Gpx Nov 25 '19 at 08:21
  • I just had to add `screen`: `expect(screen.getByText('Click Me').closest('a')).toHaveAttribute('href', 'https://www.test.com/')`and worked like charm. – Jorge Epuñan Oct 01 '20 at 16:08
  • 1
    I had the same problem and adding import "@testing-library/jest-dom/extend-expect"; to the top of the file fixed the problem – Pedro Silva Nov 11 '20 at 16:11
  • This is not as good as the answer from Dominic below, because of the search for `closest('a')`, it falls a bit outside of the spirit of react-testing-library ("The more your tests resemble the way your software is used, the more confidence they can give you") imo. `getByRole('link')` aligns closer with the spirit of the library since no such search is required. Even if the spirit of the library is itself questionable lol. Note, I have not downvoted - just saying... – quickshiftin Feb 26 '21 at 21:47
  • This did not work for me, I have this DOM: `Next Step`, I tried `expect(screen.getByText('Next Step').closest('a')).toHaveAttribute('href', "some-url")`. But got this error: `Expected the element to have attribute: href="some-url" Received: null` – Rahul Sagore Mar 08 '21 at 16:52
17

You can simply use this instead:

expect(getByText("Click Me").href).toBe("https://www.test.com/")
Azametzin
  • 4,342
  • 12
  • 22
  • 38
  • That does not prevent from a development bug where there's a prop href but no . Think in dynamic components, for example, a button that renders as a link. Of course, it wouldn't make sense but to force failure on your tests you need to validate that the property href is being used in a link element. – carlosnufe Aug 20 '20 at 10:11
  • you need to reference to screen , but even doing so you will get a type error because: TS2339: Property 'href' does not exist on type 'HTMLElement' – Boogie Jan 13 '21 at 10:55
  • In react this translates `/link` into `http://localhost/link` which causes the test to fail. Using `toHaveAttribute` works correctly. – James Gentes Mar 19 '21 at 16:39
11

I found a solution that may help others. The <a> element is considered a link role by React Testing Library. This should work:

expect(screen.getByRole('link')).toHaveAttribute('href', 'https://www.test.com');
0

Maybe its overtly engineered in this case. But you can also use data-testid attribute. This guarantees that you are getting the a tag. I think there are benefit to this for more complex components.

test('should navigate to ... when link is clicked', () => {
  const { getByTestId } = render(<a data-testid='link' href="https://test.com">Click Me</a>);

  expect(getByTestId('link')).toHaveAttribute('href', 'https://test.com');
   
});
cruise_lab
  • 409
  • 4
  • 16