简体   繁体   中英

Test useRef onError Fn, with React-Testing-Library and Jest

I have this simple fallbackImage Component:

export interface ImageProps {
  srcImage: string;
  classNames?: string;
  fallbackImage?: FallbackImages;
}

const Image = ({
  srcImage,
  classNames,
  fallbackImage = FallbackImages.FALLBACK
}: ImageProps) => {
  const imgToSourceFrom = srcImage;
  const imgToFallbackTo = fallbackImage;

  const imageRef = useRef(null);
  const whenImageIsMissing = () => {
    imageRef.current.src = imgToFallbackTo;
    imageRef.current.onerror = () => {};
  };

  return (
    <img ref={imageRef} src={imgToSourceFrom} className={classNames} onError={whenImageIsMissing} />
  );
};

export default Image;

It works perfectly. I have test running for it with Jest and React-Testing-Library . I have tested all but one scenario. This one:

  const whenImageIsMissing = () => {
    imageRef.current.src = imgToFallbackTo;
    imageRef.current.onerror = () => {}; // This line.
  };

This line basically prevents an infinite Loop in case both images are missing

The Problem: I want to test that my onerror function has been called exactly one time. Which I am really stuck on how to do it. Here is the test...

      const { container } = render(<Image srcImage={undefined} fallbackImage={undefined} />);

      const assertion = container.querySelector('img').onerror;

      fireEvent.error(container.firstElementChild);

      console.log(container.firstElementChild);
      expect(container.firstElementChild.ref.current.onerror).toHaveBeenCalledTimes(1);
      // This though has no reference to a real value. Is an example of what I want to get at.

The Question: How to access the ref callback function and check how many times has my function been called?

Any ideas on this. I am at a loss, I tried mocking refs , I tried mocking and spying on the component. I tried using act and async/await, in case it was called after. I really need some help on this..

You should check if your function is called or not, that's called testing implementation details, rather you should check if your img element have correct src.

Even you should add some alt and user getByAltText to select image element

const { getByAltText } = render(<Image srcImage={undefined} fallbackImage={undefined} />);
const imageElement = getByAltText('Image Alt');
fireEvent.error(imageElement);
expect(imageElement.src).toEqual(imgToFallbackTo);

You have 2 options:

Add a callback to your props that will be called when whenImageIsMissing is called:

export interface ImageProps {
  srcImage: string;
  classNames?: string;
  fallbackImage?: FallbackImages;
  onImageMissing?:();
}

const Image = ({
  srcImage,
  classNames,
  onImageMissing,
  fallbackImage = FallbackImages.FALLBACK
}: ImageProps) => {
  const imgToSourceFrom = srcImage;
  const imgToFallbackTo = fallbackImage;

  const imageRef = useRef(null);
  const whenImageIsMissing = () => {
    imageRef.current.src = imgToFallbackTo;
    imageRef.current.onerror = () => {};
    if (onImageMissing) onImageMissing();
  };

  return (
    <img ref={imageRef} src={imgToSourceFrom} className={classNames} onError={whenImageIsMissing} />
  );
};

and then insert jest.fn in your test and check how many times it was called.

The other option is to take the implementation of whenImageIsMissing and put it inside image.util file and then use jest.spy to get number of calls. Since you are using a function component there is no way to access this function directly.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM