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

How to test anchor's href with 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/");
});

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

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

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

您可以简单地使用它:

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

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

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

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

如果您正在使用 screen,RTL 作者认为这应该是首选方式:

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

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

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

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

简单易行。

试试这个

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

您可能有几个 link 要检查一个页面。我发现这些建议非常有用。我做了什么使它适应检查同一页上的 5 links -

  1. screen()方法最佳实践在页面上查询link-更可靠
  2. 断言 link 在页面上
  3. 将link分配给一个变量
  4. 在 link
  5. 上调用事件
  6. 确保 url toHaveAttribute 方法而不是使用 window 对象导航 - 在与虚拟 DOM 的反应中,如果您尝试导航到另一个页面link 指向 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/')

});

这是我用的:

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"`);

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

Jest Docs

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

这对我有用:


expect(screen.getByText('Click Me').closest('a')?.href).toEqual('https://test.com');

这是我所做的,使用 testing-library/react

对我有用
import { render, screen } from '@testing-library/react';
import {HomeFeature} from '../Components/HomeFeature.tsx';

let imp_content = [
    {
        title: "Next.js",
        link: "https://nextjs.org/",
    },
    {
        title: "React",
        link: "https://reactjs.org/",
    },
    {
        title: "Firebase",
        link: "https://firebase.google.com/",
    },
    {
        title: "Tailwind",
        link: "https://tailwindcss.com/",
    },
    {
        title: "TypeScript",
        link: "https://www.typescriptlang.org/",
    },
    {
        title: "Jest.js",
        link: "https://jestjs.io/",
    },
    {
        title: "testing-library/react",
        link: "https://testing-library.com/",
    }
];

imp_content.map((content) => {
    test(`${content.title} contains ${content.link}`, () => {
        render(<HomeFeature />);
        expect(screen.getByText(content.title).closest('a')).toHaveAttribute('href', content.link);
    })
})