如何模拟 window.gapi.load() React + Jest

How to mock window.gapi.load() React + Jest

Angular有一个问题可以回答这个问题,Vuejs 有一个没有任何答案的问题。我试图找到一种方法来在我的测试中模拟 window.gapi.load() 函数。我是 React 测试的新手,这是我目前所拥有的:

it('should render the App component without crashing', function () {
  const component = renderer.create(
    shallow(
      <Root>
        <App/>
      </Root>
    )
  )

  let tree = component.toJSON()
  expect(tree).toMatchSnapshot()
})

我已经尝试了一个基本的 beforeEach 调用来尝试加载它或其他东西,但这也没有用。这是组件中的代码:

const App = () => {
  const { isSignedIn } = useSelector(state => state.auth)

  const renderApp = () => {
    if (isSignedIn) {
      return <Home/>
    } else {
      return (
          <div className='app'>
            <h1 id='logo'>netTube</h1>
            <GoogleAuth/>
          </div>
      )
    }
  }

  return (
      <>
        { renderApp() }
      </>
  )
}

以及 GoogleAuth 组件中的调用:

// GoogleAuth.jsx

componentDidMount() {
    window.gapi.load('client:auth2', () => {
      window.gapi.client.init({
        clientId: process.env.REACT_APP_GOOGLE_CLIENT_ID,
        scope: 'email'
      }).then(() => {
        this.auth = window.gapi.auth2.getAuthInstance()
        this.onAuthChange(this.auth.isSignedIn.get())
        this.auth.isSignedIn.listen(this.onAuthChange)
      })
    })
  }

如果您还有什么想让我补充的,请尽管询问。抱歉,如果没有足够的信息,正如我所说,我对 React 测试非常陌生。谢谢!

您可以模拟您的组件使用的每个 gapi 调用。 (尽管使用浅渲染,您的 componentDidMount 可能不会 运行。)

类似于:

window.gapi = {};
window.gapi.auth2.getAuthInstance = () => {isSignedIn : {get : () => true, listen : f => f()}};
window.gapi.client.init = (v) => true;
window.gapi.load = (a, f) => f();

作为 it 的第一行(或者在 before/beforeEach 函数中更好)

这就是我在 Jest 中为 window.gapi.auth2.getAuthInstance 模拟数据的方式。你也可以这样做。

示例:

import React from "react";
import { render, unmountComponentAtNode } from "react-dom";
import { act } from "react-dom/test-utils";
import {BrowserRouter} from 'react-router-dom';

import Home from "../routes/Home";

let container = null;
beforeEach(() => {
    // setup a DOM element as a render target

    let profileObj = {
        getEmail: () => 'testUser@gmail.edu',
        getImageUrl: () => 'www.example.com/stem.jpg',
        getName : () => 'NON STEM user'
    }

    let getBasicProfileFun = { getBasicProfile: () => profileObj }

    let authInstanceObj = { 'currentUser': { get: () => getBasicProfileFun } }
    window.gapi = { 'auth2': "d" };
    window.gapi.auth2 = { getAuthInstance: () => authInstanceObj }

    container = document.createElement("div");
    document.body.appendChild(container);
});

afterEach(() => {
    // cleanup on exiting
    unmountComponentAtNode(container);
    container.remove();
    container = null;
});

it("renders with or without a name", () => {
    act(() => {
        render(<BrowserRouter><Home /></BrowserRouter>, container);
    });
    // console.log(container)
    expect(container.textContent).toBe(' PairStudytestUser@gmail.eduWelcome to Pair StudySelect your field of study and join a roomStemNon-StemJoin Room');
});

对 Tom 和 Hector 的回答进行了一些扩展,我添加了一个 JWT 令牌,它似乎在 Jest 中工作,用于模拟登录和退出 gapi.auth2 的基础知识:

window.gapi = {auth2: {}, client: {}};
window.gapi.auth2.getAuthInstance = () => {return new function() {
  this.isSignedIn = new function() {
    this.signedIn = false;
    this.get = () => this.signedIn;
    this.listen = (f) => f();
  };
  this.signIn = () => Promise.resolve(this.isSignedIn.signedIn = true);
  this.signOut = () => Promise.resolve(this.isSignedIn.signedIn = false);
  this.currentUser = new function() {
    this.get = () => new function() {
      this.getId = () => "XYZ";
      this.getAuthResponse = () => new function() {
        this.id_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
      };
      this.getBasicProfile = () => new function() {
        this.getName = () => "Mr Test";
        this.getEmail = () => "test@email.com";
        this.getImageUrl = () => "http://email.com/image";
      };
    };
  };
};}
window.gapi.auth2.init = () => {return Promise.resolve({});}
window.gapi.client.init = (v) => true;
window.gapi.load = (a, f) => f();