Jest/Enzyme:功能组件中的模拟函数

时间:2021-02-05 11:00:55

标签: reactjs jestjs enzyme

我在 React 中有一个函数式组件。这是代码

import React, { useState, Fragment } from "react";
import { makeStyles } from "@material-ui/core/styles";
import "./K8sIPCalculator.css";
import { initialState, checkBoxLabel } from "./FormMetaData";
import { checkPositiveInteger } from "./FormDataValidation";

const useStyles = makeStyles((theme) => ({
  // Styles
}));

const K8sIPCalculator = (props) => {
  const classes = useStyles();
  let intialStateCopy = JSON.parse(JSON.stringify(initialState));
  const [data, setData] = useState(intialStateCopy);

  const handleCheckBox = (path, value) => {
    const newData = { ...data };
    if (path === "nodes" || path === "pods") {
      if (!checkPositiveInteger(value)) {
        newData[path].value = value;
        newData[path].helperText = "It should be a positive integer!";
      } else {
        newData[path].value = value;
        newData[path].helperText = "";
      }
    } else newData[path] = value;
    setData(newData);
  };

  const calculate = () => {
           // Does some calculation and update data state
  };

  const onSubmit = () => {
    if (data.nodes.helperText !== "" || data.pods.helperText !== "") {
      alert("Data is not correct");
      return;
    }
    calculate();
  };

  const onReset = () => {
    intialStateCopy = JSON.parse(JSON.stringify(initialState));
    setData(intialStateCopy);
  };

  return (
    <Fragment>
      <h2 className="name">K8s IP Calculator</h2>
      <form className={classes.formRoot}>
        <Accordion
          defaultExpanded={true}
          classes={{ expanded: classes.expanded }}
        >
          <AccordionSummary
            expandIcon={<ExpandMoreIcon />}
            id="accordion1"
            className={classes.summary}
          >
            <Typography className={classes.heading}>Results</Typography>
          </AccordionSummary>
          <AccordionDetails className="container">
            <InputLabel className={classes.label}>
              Total useable IPs required:
            </InputLabel>
            <TextField
              disabled
              className={classes.textDisabledInput}
              id="ips-required-output"
              variant="outlined"
              value={data.total}
            />
            <InputLabel className={classes.label} htmlFor="subnet-size-output">
              Subnet Size required:
            </InputLabel>
            <TextField
              disabled
              className={classes.textDisabledInput}
              id="subnet-size-output"
              variant="outlined"
              value={data.subnet_size}
            />
          </AccordionDetails>
        </Accordion>
        <br />
        <Accordion
          defaultExpanded={true}
          classes={{ expanded: classes.expanded }}
        >
          <AccordionSummary
            expandIcon={<ExpandMoreIcon />}
            id="accordion2"
            className={classes.summary}
          >
            <Typography className={classes.heading}>K8s Details</Typography>
          </AccordionSummary>
          <AccordionDetails className="container">
            <InputLabel className={classes.label}>Nodes:</InputLabel>
            <TextField
              size="small"
              type="number"
              onChange={(e) => handleCheckBox("nodes", e.target.value)}
              className={classes.textInput}
              id="nodes-input"
              variant="outlined"
              value={data.nodes.value}
              helperText={data.nodes.helperText}
            />
            <InputLabel className={classes.label} htmlFor="pods-input">
              Pods:
            </InputLabel>
            <TextField
              size="small"
              type="number"
              onChange={(e) => handleCheckBox("pods", e.target.value)}
              className={classes.textInput}
              id="pods-input"
              variant="outlined"
              value={data.pods.value}
              helperText={data.pods.helperText}
            />
            <div id="nodes-error"></div>
          </AccordionDetails>
        </Accordion>
        <div className="button-container">
          <Button
            id="reset-button"
            className="button"
            variant="outlined"
            color="primary"
            size="small"
            onClick={onReset}
            startIcon={<UndoIcon />}
          >
            Reset
          </Button>
          <Button
            id="submit-button"
            className="button"
            variant="contained"
            color="primary"
            size="small"
            startIcon={<SaveIcon />}
            onClick={onSubmit}
          >
            Submit
          </Button>
        </div>
      </form>
    </Fragment>
  );
};

export default K8sIPCalculator;


事情,我正在尝试测试,

  1. 当输入改变时,我想检查handleCheckBox函数是否被调用
  2. 当提交按钮被调用时,我想检查计算函数是否被调用
  3. 如何调用 setData 函数通过 Jest/Enzyme 更新数据

我试过这样的事情

const spy = jest.spyOn(K8sIPCalculator, "calculate");

但是我得到了

Cannot spy the calculate property because it is not a function; undefined given instead

PS:我可以在调用提交后断言数据更改。但我想检查是否调用了计算函数。

    const submit = wrapper.find("button#submit-button");
    submit.simulate("click");

    expect(wrapper.find("input#ips-required-output").props().value).toEqual(35);
    expect(wrapper.find("input#subnet-size-output").props().value).toEqual(
      "/26"
    );

0 个答案:

没有答案