Home > Net >  How do I write this test for complete coverage?
How do I write this test for complete coverage?

Time:12-31

I am new to React development and am studying testing with Jest and React Testing Library (RTL).

But I'm having difficulty doing the complete coverage of the component below:

import {
  CustomCardActions,
  CustomCardHeader,
} from '@Custom/react';
import React from 'react';
import {
  PortalAccessButton,
  PortalAccessContext,
  PortalAccessInternalCard,
  PortalAccessTitle,
} from './styles';

interface PortalAccessCard {
  children: React.ReactNode
  buttonText: string;
  hrefLink: string;
}

export const redirectToUrl = (hrefLink: string) => {
  window.open(hrefLink, '_self');
};

const PortalAccessCard = (props: PortalAccessCard) => {
  const { children, buttonText, hrefLink } = props;

  return (
    <PortalAccessContext inverse>
      <PortalAccessInternalCard>

        <CustomCardHeader>
          <PortalAccessTitle variant="heading-4">
            {children}
          </PortalAccessTitle>
        </CustomCardHeader>

        <CustomCardActions>
          <PortalAccessButton onCustomClick={() => redirectToUrl(hrefLink)}>
            {buttonText}
          </PortalAccessButton>
        </CustomCardActions>

      </PortalAccessInternalCard>
    </PortalAccessContext>
  );
};

export default React.memo(PortalAccessCard);

There are two details here:

1- I exported the "redirectToUrl" method to be able to test it. I can't say if there's a better way out, but maybe the second question solves this one.

2- When I check the coverage report it says that this part () => redirectToUrl(hrefLink) has not been tested, but it is basically the pointer to the method I exported above.

My test looks like this:

import { render, RenderResult } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import PortalAccessCard from '.';
import * as PortalAccessCardComponent from '.';

describe('PortalAccessCard', () => {
  let renderResult: RenderResult;
  const hrefLink = '#';

  beforeEach(() => {
    renderResult = render(
      <PortalAccessCard
        buttonText="Texto do botão"
        hrefLink={hrefLink}
      >
        Texto interno PortalAccessCard.
      </PortalAccessCard>,
    );
  });

  it('should call onCustomClick and redirectToUrl', async () => {
    window.open = jest.fn();
    jest.spyOn(PortalAccessCardComponent, 'redirectToUrl');
    const onCustomClick = jest.fn(() => PortalAccessCardComponent.redirectToUrl(hrefLink));

    const CustomButtonElement = renderResult.container.getElementsByTagName('Custom-button')[0];
    CustomButtonElement.onclick = onCustomClick;

    await userEvent.click(CustomButtonElement);
    expect(onCustomClick).toBeCalledTimes(1);
    expect(PortalAccessCardComponent.redirectToUrl).toBeCalledTimes(1);
  });
});

What can I do to make the test call of the onCustomClick event call the redirectToUrl method so that Jest understands that this snippet has been tested?

CodePudding user response:

Not sure which exactly line is not covered... Though, toBeCalledTimes is a sign of bad test expectation, so try to append to the very bottom line:

    expect(PortalAccessCardComponent.redirectToUrl).toBeCalledWith(hrefLink);

CodePudding user response:

It's better to test for the side effect you want (opening a window). redirectToUrl is an implementation detail. I think you're making this much harder than it needs to be.

Spy on window.open, click the item, check the spy. I think that's all you need.

jest.spyOn(window, 'open')

const CustomButtonElement = renderResult.container.getElementsByTagName('Custom-button')[0];
await userEvent.click(CustomButtonElement);
// or maybe: getByRole('something...').click()

expect(window.open).toHaveBeenCallWith('#', '_self')
  • Related