测试 ReactJS 自定义挂钩以使用 Jest 加载图像

问题描述 投票:0回答:1

我正在尝试测试自定义挂钩的 onload 函数来加载图像,但是当我运行测试时,它会跳过 onload。

挂钩:

import { useEffect, useState } from "react";

const useImage = (src: string) => {
    const [loaded, setLoaded] = useState(false);

    useEffect(() => {
        const image = new Image();
        image.src = src;
        image.onload = () => {
            return setLoaded(true); //can't test it
        };
    }, [src]);

    return { loaded };
};

export default useImage;

测试:

import {
    renderHook,
    waitFor,
} from "@testing-library/react";
import useImage from "./useImage";

describe("useImage", () => {

    it("Loads a data url into an image element", async () => {

        const img = new Image();
        img.src = "foo";

        const { result } = renderHook(() => useImage("foo"));

        await waitFor(() =>
            expect(result.current).toStrictEqual({ loaded: true }) // loaded is always false
        );

    });
});

如何让测试在 useEffect 中运行 onload?我正在使用 Jest 和 Typescript。

reactjs jestjs
1个回答
0
投票

首先,你的

useImage
钩子除了加载图像然后设置状态之外没有做任何事情。如果这仅用于演示目的,那很好,否则,您应该研究一下您想要使用该钩子实现的目标。

关于测试,如果您使用

jest
jsdom
来测试。然后
jsdom
仅在实际加载某些内容时触发加载事件。这意味着使用必须在
src
中使用真实图像并更改一些笑话配置,如下所示:

package.json
中,如果您使用jest.config.js,请参阅官方文档以获取等效内容。

  "jest": {
    "preset": "ts-jest",
    "testEnvironment": "jsdom", // we need this line
    "transform": {
      "node_modules/variables/.+\\.(j|t)sx?$": "ts-jest"
    },
    "testEnvironmentOptions": {
      "resources": "usable" // we need this line
    },
    "transformIgnorePatterns": [
      "node_modules/(?!variables/.*)"
    ]
  },

您还需要安装canvas

 npm i canvas

那么你的测试现在就要通过了。但是,如果您发现安装新依赖项并更改默认测试框架的工作方式有点问题,那么您可以模拟 Image 对象实现,就个人而言,我更喜欢这种方式:

const LOAD_FAILURE_SRC = 'LOAD_FAILURE_SRC';
const LOAD_SUCCESS_SRC = 'LOAD_SUCCESS_SRC';
beforeAll(() => {
    Object.defineProperty(global.Image.prototype, 'src', {
        set(src) {
            if (src === LOAD_FAILURE_SRC) {
                setTimeout(() => this.onerror(new Error('mocked error')));
            } else if (src === LOAD_SUCCESS_SRC) {
                setTimeout(() => this.onload());
            }
        },
    });
});
© www.soinside.com 2019 - 2024. All rights reserved.