使用Jest测试组件时,无法从'react-common.cjs.js'中找到模块'react'

时间:2019-11-16 15:54:23

标签: jestjs react-apollo react-testing-library

在测试使用由Apollo Tooling生成的自定义graphql突变挂钩的组件时,我遇到问题。变异挂钩来自一个import * as ApolloReactCommon from "@apollo/react-common";

的graphql.tsx文件

组件:

import React, { ReactNode } from "react";
import {
    ListItem,
    ListItemText,
    ListItemSecondaryAction,
    IconButton,
    Typography
} from "@material-ui/core";
import DeleteIcon from "@material-ui/icons/Delete";

import StyledMaterialList from "./styled-components/StyledList";
import StyledListSubheader from "./styled-components/StyledListSubheader";
import StyledLink from "../../styled-components/CustomLink";
import EmptyListWrapper from "./styled-components/EmptyListWrapper";
import { useDeleteArtistMutation } from "../../../generated/graphql";

interface Props {
    items: any[];
    subheader: string;
    path: string;
    children?: ReactNode;
    onDelete?(error?: any): void;
}

const List = (props: Props) => {
    const { items, subheader, children, path, onDelete } = props;
    const [deleteArtist] = useDeleteArtistMutation();

    if (!items || items.length <= 0) {
        return (
            <EmptyListWrapper>
                <Typography data-testid="emptyListMessage">
                    No {path} added yet
                </Typography>
            </EmptyListWrapper>
        );
    }

    const handleDelete = (artistId: string) => async (
        event: React.MouseEvent<HTMLButtonElement, MouseEvent>
    ) => {
        event.preventDefault();
        try {
            await deleteArtist({
                variables: { id: artistId }
            });
            onDelete && onDelete();
        } catch (error) {
            console.error("Something went wrong", error);
            onDelete && onDelete(error);
        }
    };

    return (
        <StyledMaterialList
            subheader={<StyledListSubheader>{subheader}</StyledListSubheader>}
        >
            {items.map((item: any, index: number) => {
                return (
                    <StyledLink key={item.id} to={`/dashboard/${path}/${item.id}`}>
                        <ListItem button={true}>
                            {children ? children : null}
                            <ListItemText
                                data-testid={`itemText${index}`}
                                primary={item.primaryText}
                                secondary={item.secondaryText}
                            />
                            {onDelete && (
                                <ListItemSecondaryAction>
                                    <IconButton
                                        data-testid={`itemSecondaryAction${index}`}
                                        edge="end"
                                        aria-label={`delete ${subheader}`}
                                        onClick={handleDelete(item.id)}
                                    >
                                        <DeleteIcon />
                                    </IconButton>
                                </ListItemSecondaryAction>
                            )}
                        </ListItem>
                    </StyledLink>
                );
            })}
        </StyledMaterialList>
    );
};

export default List;

import React from "react";
import { render, getByTestId, fireEvent } from "@testing-library/react";

import List from "../List";
import { BrowserRouter } from "react-router-dom";

describe("List", () => {
    const fakeProps: any = {
        items: [
            {
                id: "1",
                primaryText: "More important",
                secondaryText: "less important"
            }
        ],
        subheader: "string",
        onDelete: (id: string) => {},
        path: "something"
    };
    it("should be rendering children if passed", () => {
        const { container } = render(

                <BrowserRouter>
                    <List
                        {...fakeProps}
                        children={<h3 data-testid="childrenTest">Children tested</h3>}
                    />
                </BrowserRouter>

        );

        const children = getByTestId(container, "childrenTest");

        expect(children.textContent).toBe("Children tested");
    });

    it("shoud display message if no items were passed", () => {
        fakeProps.items = [];
        const { container } = render(
            <BrowserRouter>
                <List {...fakeProps} />
            </BrowserRouter>
        );

        const emptyListMessage = getByTestId(container, "emptyListMessage");
        expect(emptyListMessage.textContent).toBe("No something added yet");
    });
});

引发错误:

 Cannot find module 'react' from 'react-common.cjs.js'

    However, Jest was able to find:
        '../../../generated/graphql.tsx'

    You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['web.js', 'js', 'web.ts', 'ts', 'web.tsx', 'tsx', 'json', 'web.jsx', 'jsx', 'node'].

    See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string

    However, Jest was able to find:
        '../List.tsx'

    You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['web.js', 'js', 'web.ts', 'ts', 'web.tsx', 'tsx', 'json', 'web.jsx', 'jsx', 'node'].

最佳配置:

module.exports = {
    roots: ["./src"],
    moduleNameMapper: {
        "^.+\\.(css|less|scss)$": "identity-obj-proxy"
    },
    transform: {
        "^.+\\.jsx?$": require.resolve("babel-jest"),
        "^.+\\.(ts|tsx)?$": "ts-jest"
    },
    testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
    moduleFileExtensions: ["cjs.js", "ts", "tsx", "js", "jsx", "json", "node"]
};

如您所见,添加cjs.js的moduleFileExentions不能解决此问题。

任何帮助将不胜感激!

打包版本:

"@graphql-codegen/cli": "^1.7.0", "ts-jest": "^24.0.2",

0 个答案:

没有答案