为 React App 开玩笑模拟 Firebase auth signInWithPopUp

Mocking Firebase auth signInWithPopUp with jest for React App

我在测试我的 React 应用程序登录方法时遇到了一些问题。当我在测试中单击登录按钮时,我试图模拟 firebase auth 的 signInWithPopup 方法。

我的登录处理程序在 App.js

import * as firebase from 'firebase/app';
import 'firebase/auth';
import firebaseSetup from './firebaseSetup'
    
const firebaseApp = firebaseSetup.firebaseApp

const firebaseAppAuth = firebaseSetup.firebaseAppAuth

const providers = firebaseSetup.providers 

handleGoogleLogin = () => {
 firebaseAppAuth.signInWithPopup(providers.googleProvider)
    .then(function(result) {
      this.setState({
        token: result.credential.accessToken,
        signedInUser: result.user
      })
    }).catch(function(error) {
      let errorCode = error.code
      let errorMessage = error.message
      let errorEmail = error.email
      let errorCredential = error.credential
    })
}

我的mockFirebase.js

import * as firebase from 'firebase/app'
import firebaseConfig from './firebaseConfig';
import 'firebase/auth'
import App from './App'
import firebaseSetup from './firebaseSetup'

const mockFirebase = jest.fn( (functionName) => {
    console.log('mockFirebase', typeof functionName.providerId)
    switch(functionName.providerId) {
        case 'google.com': {
            console.log('google case')
            return 'result of signInWithPopup'
        }

        default: {
            throw new Error(`Unhandled firebase request: ${url}`)
        }
    }
}) 

beforeAll(() => {
  jest.spyOn(firebaseSetup.firebaseAppAuth, 'signInWithPopup')
})

beforeEach(() => {
  firebaseSetup.firebaseAppAuth.signInWithPopup.mockImplementation(mockFirebase)
})

export default mockFirebase

我的App.test.js

it('Firebase auth triggered when login clicked', async () => {
  render(<App/>)

  const result = fireEvent.click(screen.getByText(/Sign in with Google/i))
  expect(mockFirebase).toBeCalled()
  expect(result).toEqual(
    'result of signInWithPopup'
  )

})

我的测试失败并出现以下错误: 未捕获 [TypeError: firebaseAppAuth.signInWithPopup(...).then 不是函数]

如果我删除 .then 块,测试将在 expect(result).toEqual('result of signInWithPopup') 上失败并出现错误:

预期:“signInWithPopup 的结果” 收到:真实

我不确定为什么 .then 块会导致错误,或者为什么当测试单击登录按钮时我无法在我的结果常量中的 mockFirebase 函数中获得匹配开关案例的 return 结果.

iotype 的建议加上将我的测试结构更改为以下内容解决了这个问题。

it('Firebase auth triggerd when login clicked', async () => {
    fireEvent.click(screen.getByText(/Sign in with Google/i))
    await waitForElementToBeRemoved(() => screen.getByText(/Sign In With Google/i))
    expect(screen.getByText(/Welcome to Writual/i)).toBeInTheDocument()
    
  })
})

我想问题是 signInWithPopup 是一个提供 then 方法的 Promise。因此模拟必须 return 具有相同签名的 Promise。