如何使用 react-testing-library 测试锚点的 href

jay*_*pee 50 anchor href reactjs jestjs react-testing-library

我正在尝试测试我的锚标签。一旦我点击它,我想看看它是否window.location.href是我所期望的。

我尝试渲染锚点,单击它,然后进行测试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/");
});
Run Code Online (Sandbox Code Playgroud)

我期待测试通过,但 window.location.href 只是"http://localhost/"意味着它没有因任何原因得到更新。我什至尝试用 包装我的期望await wait,但这也不起作用。我找不到关于使用react-testing-library. 也许有比我正在做的更好的方法来测试它们。???

Gio*_*Gpx 98

Jest 使用 jsdom 来运行它的测试。jsdom 正在模拟浏览器,但它有一些限制。这些限制之一是您无法更改位置。如果你想测试你的链接是否有效,我建议检查href你的属性<a>

expect(screen.getByText('Click Me').closest('a')).toHaveAttribute('href', 'https://www.test.com/')
Run Code Online (Sandbox Code Playgroud)

  • 这不如下面 Dominic 的答案那么好,因为搜索 `closest('a')`,它有点脱离了 React-testing-library 的精神(“你的测试越类似于你的测试方式”)使用软件,他们给你的信心就越大”)我认为。`getByRole('link')` 更符合库的精神,因为不需要这样的搜索。即使图书馆的精神本身就值得怀疑,哈哈。请注意,我没有投反对票 - 只是说...... (5认同)
  • 我遇到了同样的问题并添加 import "@testing-library/jest-dom/extend-expect"; 到文件顶部修复了问题 (3认同)
  • 我得到 `TypeError: getByText(...).closest is not a function` 有什么想法吗? (2认同)
  • 我猜 `getByText` 在您的情况下找不到任何内容 (2认同)

小智 22

我找到了一个可以帮助其他人的解决方案。该<a>元素被linkReact 测试库视为一个角色。这应该有效:

expect(screen.getByRole('link')).toHaveAttribute('href', 'https://www.test.com');
Run Code Online (Sandbox Code Playgroud)

  • 这可能是最好的答案,因为 RTL 文档中表示按角色查询在查询方面具有最高优先级。[关于查询](https://testing-library.com/docs/queries/about) (5认同)

小智 19

您可以简单地使用它:

expect(getByText("Click Me").href).toBe("https://www.test.com/")
Run Code Online (Sandbox Code Playgroud)


小智 8

简单又容易。

尝试这个

  it('should be a link that have href value to "/login"', () => {
    render(<SigningInLink />);
    const link = screen.getByRole('link', { name: /log in/i });
    expect(link.getAttribute('href')).toBe('/login');
  });
Run Code Online (Sandbox Code Playgroud)


cru*_*lab 6

也许在这种情况下它是经过公开设计的。但您也可以使用 data-testid 属性。这保证您获得 a 标签。我认为这对于更复杂的组件是有好处的。

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');
   
});
Run Code Online (Sandbox Code Playgroud)


Adn*_*ikh 6

这就是我使用的:

const linkToTest = screen.getByRole("link", { name: /link to test/i })
// I used regex here as a value of name property which ignores casing

expect(linkToTest.getAttribute("href")).toMatchInlineSnapshot();
Run Code Online (Sandbox Code Playgroud)

然后运行测试,括号toMatchInlineSnapshot中将填充代码中的值。

这样做的好处是不对其进行硬编码,并且维护起来会更容易。

例如:它将像这样填充:

expect(linkToTest.getAttribute("href")).toMatchInlineSnapshot(`"link/to/somewhere"`);
Run Code Online (Sandbox Code Playgroud)

下次,假设您将此链接更改为代码库中的其他内容,运行程序会询问您是否要更新,按下u后它将被更新。(请注意,您需要检查此更新是否正确)。

在Jest Docs上了解有关内联快照的更多信息


Con*_*tin 5

如果您正在使用screen哪种应该是首选方式,由 RTL 作者:

const linkEl = screen.getByRole('link', { name: 'Click Me' });

expect(linkEl).toHaveAttribute('href', '...')
Run Code Online (Sandbox Code Playgroud)

类似,没有屏幕(名称可以是字符串或正则表达式):

const linkEl = getByRole('link', { name: 'Click Me' }); 
Run Code Online (Sandbox Code Playgroud)


Sum*_*umi 5

您可能在一个页面上有多个要检查的链接。我发现这些建议非常有用。我做了什么来调整它以检查同一页面上的 5 个链接 -

  1. 使用最佳实践的方法查询页面上的链接screen()- 更可靠
  2. 断言链接在页面上
  3. 将链接分配给变量
  4. 链接上的调用事件
  5. 确保 urltoHaveAttribute方法而不是使用 window 对象进行导航 - 在与虚拟 DOM 进行反应时,如果您尝试导航到另一个页面,则链接将定向到 http://localhost/link 而不是测试重定向
test('should navigate to url1 when link is clicked', () => {

const componentName = render(<Component/>)

const url1 = getByText("https://www.test.com/")
expect(ur1).toBeInTheDocument()
screen.userEvent.click(url1);
expect(url1).toHaveAttribute('href', 'https://www.test.com/')

});
Run Code Online (Sandbox Code Playgroud)