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

Posted

技术标签:

【中文标题】如何使用 react-testing-library 测试锚的 href【英文标题】:How to test anchor's href with react-testing-library 【发布时间】:2020-01-09 15:12:30 【问题描述】:

我正在尝试测试我的锚标记。一旦我点击它,我想看看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/");
);

我希望测试能够通过,但 window.location.href 只是 "http://localhost/",这意味着无论出于何种原因它都不会更新。我什至尝试用await wait 包装我的期望,但这也不起作用。我找不到太多关于使用react-testing-library 测试锚点的信息。也许有比我正在做的更好的方法来测试它们。 ????‍♂️

【问题讨论】:

【参考方案1】:

这是我用的:

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();

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

这样的好处是不用硬编码,维护起来会更容易。

例如:它会这样填充:

expect(linkToTest.getAttribute("href")).toMatchInlineSnapshot(`"link/to/somewhere"`);

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

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

【讨论】:

【参考方案2】:

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

    使用screen()方法最佳实践查询页面上的链接-更可靠 断言链接在页面上 将链接分配给变量 链接上的调用事件 确保使用 url toHaveAttribute 方法而不是使用窗口对象导航 - 与虚拟 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/')

);

【讨论】:

【参考方案3】:

简单易行。

试试这个

  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');
  );

【讨论】:

【参考方案4】:

如果您使用的是screen,这应该是 RTL 作者的首选方式:

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

expect(linkEl).toHaveAttribute('href', '...')

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

const linkEl = getByRole('link',  name: 'Click Me' ); 

【讨论】:

【参考方案5】:

在这种情况下,它可能是公开设计的。但您也可以使用 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');
   
);

【讨论】:

【参考方案6】:

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

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

【讨论】:

这可能是最好的答案,因为在 RTL 文档中它说按角色查询在查询方面具有最高优先级。 About Queries【参考方案7】:

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

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

【讨论】:

我得到TypeError: getByText(...).closest is not a function 任何想法? 我猜getByText 在你的情况下找不到任何东西 我只需要添加 screen: expect(screen.getByText('Click Me').closest('a')).toHaveAttribute('href', 'https://www.test.com/') 并像魅力一样工作。 我遇到了同样的问题并添加了 import "@testing-library/jest-dom/extend-expect";到文件顶部修复了问题 这不如下面多米尼克的答案,因为搜索closest('a'),它有点超出了react-testing-library的精神(“你的测试越像你的软件的使用方式,他们能给你的信心就越大") imo。 getByRole('link') 更符合图书馆的精神,因为不需要这样的搜索。即使图书馆的精神本身就是有问题的,哈哈。请注意,我没有投反对票 - 只是说...【参考方案8】:

您可以简单地使用它:

expect(getByText("Click Me").href).toBe("https://www.test.com/")

【讨论】:

这并不能防止有一个 prop href 但没有 的开发错误。考虑动态组件,例如,呈现为链接的按钮。当然,这没有任何意义,但要强制测试失败,您需要验证属性 href 是否正在链接元素中使用。 你需要引用 screen ,但即使这样做你也会得到一个类型错误,因为:TS2339: Property 'href' does not exist on type 'htmlElement' 在反应中,这会将/link 转换为http://localhost/link,从而导致测试失败。使用toHaveAttribute 可以正常工作。

以上是关于如何使用 react-testing-library 测试锚的 href的主要内容,如果未能解决你的问题,请参考以下文章

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]

如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?

如何使用laravel保存所有行数据每个行名或相等

如何使用 Math.Net 连接矩阵。如何使用 Math.Net 调用特定的行或列?

WSARecv 如何使用 lpOverlapped?如何手动发出事件信号?