无法建立测试以使用onOnClickOutside自定义钩子

时间:2020-08-09 22:50:02

标签: reactjs jestjs enzyme react-testing-library react-hooks-testing-library

我建立了一个自定义挂钩,我想从中建立测试,但我不知道从哪里开始,我希望您能帮助我解释一些事情:

1。我如何在测试中捕捉鼠标 2.如何使用useRef并将其关联为当前值 如果您可以帮助我并向我展示代码,这将非常有帮助,因为有时我会坐在上面

下面是自定义钩子,我在其中实现了自定义钩子的代码 预先感谢?

unix

这是使用它的组件:

 import { useEffect } from 'react';

function useOnClickOutside(ref, callback) {
  useEffect(
    () => {
      const listener = (event) => {
        // Do nothing if clicking ref's element or descendent elements
        if (!ref.current || ref.current.contains(event.target)) {
          return;
        }

        callback(event);
      };

      document.addEventListener('mousedown', listener);
      document.addEventListener('touchstart', listener);

      return () => {
        document.removeEventListener('mousedown', listener);
        document.removeEventListener('touchstart', listener);
      };
    },
    [ref, callback],
  );
}

export default useOnClickOutside;

2 个答案:

答案 0 :(得分:0)

我为您的案例找到了不错的博客文章。这里有如何测试onClickOutside https://webman.pro/blog/how-to-detect-and-test-click-outside-in-react/的信息 我查看了您的组件,并对它的实际工作方式产生了好奇。)因此,如果您添加了示例代码,我会为您提供更多帮助)

更新 我在您的组件中添加了内容的测试ID) 组件:

import React, { useRef } from "react";
import ReactDOM from "react-dom";
import styles from "./OverlayDialog.module.css";
import useOnClickOutside from "./useOnClickOutside";
const OverlayDialog = (props) => {
  const wrapperRef = useRef(null);

  useOnClickOutside(wrapperRef, () => props.onClose());

  return ReactDOM.createPortal(
    <div className={styles.Dialog}>
      <div className={styles.InnerDialog} tabIndex={1}>
        <div className={styles.DialogCard} tabIndex={-1}>
          <div
            className={props.className ? props.className : styles.DialogContent}
            ref={wrapperRef}
            data-testid="content"
          >
            {props.children}
          </div>
        </div>
      </div>
    </div>,
    document.getElementById("OverlayDialog")
  );
};

export default OverlayDialog;

测试:

import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import OverlayDialog from "./OverlayDialog";

test('renders learn react link', () => {
  const onClose = jest.fn();
  const modalRoot = document.createElement('div');
  modalRoot.setAttribute('id', 'OverlayDialog');
  const body = document.querySelector('body');
  body.appendChild(modalRoot);
  render(
      <OverlayDialog onClose={onClose}>
        content
      </OverlayDialog>
  );
  /*checking that if we click on content nothing happens*/
  expect(screen.queryByTestId('content')).toBeInTheDocument();
  fireEvent(screen.queryByTestId('content'), new MouseEvent('mousedown', {
    bubbles: true,
    cancelable: true,
  }));
  expect(onClose).not.toBeCalled();

  /*checking that if we click outside we'll fire onClose*/
  fireEvent(body, new MouseEvent('mousedown', {
    bubbles: true,
    cancelable: true,
  }));
  expect(onClose).toBeCalled();
});

答案 1 :(得分:0)

单独测试 useOnClickOutside 的示例

import logo from './logo.svg';
import './App.css';
import React, { useState } from "react";


function App() {

  const [newWager, setWager] = useState(0);
  const [userSide, setUserSide] = useState(0);
  const [retrievedSide1, setRetrievedSide1] = useState("1");
  const [retrievedSide2, setRetrievedSide2] = useState("2");

  const wager = async (t) => {
    if(t) { t.preventDefault(); }
    else { console.log('No t') };
    let str = newWager + ' on side ' + userSide;
    wagerComplete(str);
    let form = document.getElementById("submitWagerForm");
    form.reset();
  };

  const wagerComplete = async (wagerstr) => {
    console.log(wagerstr);
    alert(wagerstr);
  };

  const beginRound = async (t) => {
    t.preventDefault();
    // setRetrievedSide1(document.getElementById("side1").value);
    // setRetrievedSide2(document.getElementById("side2").value);
    try{
      // const accounts = await window.ethereum.enable();
      // const account = accounts[0];
      // const gas = await eventWagerContract.methods.beginRound(retrievedSide1, retrievedSide2).estimateGas();
      // const post = await eventWagerContract.methods.beginRound(retrievedSide1, retrievedSide2).send({ from: account, gas });
      alert(retrievedSide1 + ' ' + retrievedSide2);
      wager();
    }
    catch(e)
    {
      alert('Apparently this is the best way to display blockchain errors :/\n\n' + e.message);
    }
    let form = document.getElementById("beginRoundForm");
    form.reset();
  };

  return (
    <div className="App">
      <form className="form" id="submitWagerForm" autocomplete="off" onSubmit={wager}>
          <label>
            Enter your wager and side:
            <br />
            <input
              className="input"
              type="text"
              name="amount"
              placeholder="# of WC"
              onChange={(t) => setWager(t.target.value)}
            />
            <input
              className="input"
              type="text"
              name="side"
              placeholder="1 or 2"
              onChange={(t) => setUserSide(t.target.value)}
            />
          </label>
          <button className="button" type="submit" value="Submit">
            Submit
          </button>
        </form>
        <form className="form" id="beginRoundForm" autocomplete="off" onSubmit={beginRound}>
            <label>
              <input
                className="input"
                type="text"
                name="name"
                id="side1"
                placeholder="Side 1"
                onChange={(t) => setRetrievedSide1(t.target.value)}
              />
              <input
                className="input"
                type="text"
                name="side"
                placeholder="Side 2"
                id="side2"
                onChange={(t) => setRetrievedSide2(t.target.value)}
              />
              <button className="button" type="submit" value="Submit">
                Begin Round
              </button>
            </label>
          </form>
    </div>
  );
}

export default App;