【问题标题】:Create a user programatically using Firebase Auth emulator使用 Firebase Auth 模拟器以编程方式创建用户
【发布时间】:2021-04-04 10:50:19
【问题描述】:

我正在尝试使用 Firebase Auth 模拟器编写笑话测试并继续收到以下 CORS 错误。

console.error
    Error: Headers X-Client-Version forbidden
        at dispatchError (/Users/me/my-project/node_modules/jsdom/lib/jsdom/living/xhr/xhr-utils.js:62:19)
        at validCORSPreflightHeaders (/Users/me/my-project/node_modules/jsdom/lib/jsdom/living/xhr/xhr-utils.js:99:5)
        at Request.<anonymous> (/Users/me/my-project/node_modules/jsdom/lib/jsdom/living/xhr/xhr-utils.js:367:12)
        at Request.emit (events.js:315:20)
        at Request.onRequestResponse (/Users/me/my-project/node_modules/request/request.js:1059:10)
        at ClientRequest.emit (events.js:315:20)
        at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:641:27)
        at HTTPParser.parserOnHeadersComplete (_http_common.js:126:17)
        at Socket.socketOnData (_http_client.js:509:22)
        at Socket.emit (events.js:315:20) undefined

测试很简单:

import { renderHook, act } from "@testing-library/react-hooks"
import faker from "faker"
import { useAuth, FirebaseProvider, firebase } from "./index"


const wrapper = ({ firebase, children }) => {
  return <FirebaseProvider firebase={firebase}>{children}</FirebaseProvider>
}

const createUser = ({ email = faker.internet.email(), password = faker.internet.password({ length: 6 }) } = {}) => {
  return firebase
    .auth()
    .createUserWithEmailAndPassword(email, password)
    .then(user => user)
}

const signUserIn = ({ email, password } = {}) => {
  return firebase
    .auth()
    .signInWithEmailAndPassword(email, password)
    .then(user => user)
}

describe("useAuth", () => {
  it("will return the user", async () => {
    const { result } = renderHook(() => useAuth(), { wrapper, initialProps: { firebase } })
    const email = faker.internet.email()
    const password = faker.internet.password()
    await act(async () => {
      const user = await createUser({ email, password }) // this fails
      await signUserIn({ email, password }) //and so does this
    })
    expect(result.user).toEqual({ email, password })
  })
})

作为参考,索引文件:

const FirebaseProvider = ({ children, firebase }) => {
  const firestore = firebase.firestore()
  const auth = firebase.auth()

  if (useEmulator()) {
    firestore.useEmulator("localhost", 8080)
    auth.useEmulator("http://localhost:9099/")
  }

  const value = { firestore, auth }

  return <FirebaseContext.Provider value={value}>{children}</FirebaseContext.Provider>
}

const throwError = hook => {
  throw new Error(`${hook} must be used within a FirebaseProvider`)
}

const useAuth = () => {
  const context = useContext(FirebaseContext)
  if (context === undefined) throwError("useAuth")

  const [user, setUser] = useState()

  useEffect(() => {
    const cleanup = context.auth.onAuthStateChanged(authUser => {
      authUser ? setUser(authUser) : setUser(null)
    })
    return () => cleanup()
  })

  return { ...context.auth, user }
}

我尝试使用实际模拟器使用的 REST 端点(如下),但它以相同的方式出错。

http://localhost:9099/identitytoolkit.googleapis.com/v1/projects/<my-project>/accounts

在使用 jest 时有没有办法让它运行?或者我是否需要使用模拟器 UI 创建帐户、导出它们并在运行测试时重新导入?

我发现我可以使用下面的 REST 端点在测试中创建一个用户,但是它绕过了模拟器并创建了一个真正的用户。

https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=<api-key>

【问题讨论】:

    标签: firebase firebase-authentication jestjs jsdom firebase-tools


    【解决方案1】:

    更新jsdom版本16.5.2

    这个新版本现在支持 access-control-allow-headers 的通配符,因此更新到这个版本或使用它作为解决方案,对于使用 Create React App 创建的项目,可以解决问题。

    jsdom 16.5.2 之前的解决方案

    这个错误是由 jsdom 抛出的,因为它不支持 access-control-allow-headers 的通配符,但是 firebase 使用了通配符(参见这个issue for jsdom 和这个pull request related to firebase)。有两个开放的拉取请求来解决这个问题:https://github.com/jsdom/jsdom/pull/3073https://github.com/jsdom/jsdom/pull/2867

    可以通过手动更改 node_modules 文件夹中的相关代码或使用 fork 作为 package.json 中的依赖项来解决此问题:

    "jsdom": "silviot/jsdom#fix/allow-headers"
    

    如果jsdom 不是直接依赖项,那么您可以将以下内容添加到顶层的package.json

    "resolutions": {
      "jsdom": "silviot/jsdom#fix/allow-headers"
    }
    

    如果使用 fork,jsdom 文件夹中会缺少一些自动生成的文件。这些可以通过在文件夹中运行npm installyarn install 来生成。要自动执行此操作,您可以将 prepare 脚本添加到 package.json

    "scripts": {
      "prepare": "cd node_modules/jsdom && yarn"
    },
    

    【讨论】:

    • 我已经尝试了这些建议,它们都导致Cannot find module './jsdom/living/generated/utils.js' 错误的相同结果。我已经清除了 jest 缓存并删除了我的 node_modules。
    • 在修复此问题的同时,是否有任何已知的解决方法可以在测试中使用 Firebase Auth 模拟器?我在网上找不到任何东西。
    • node_modules/jsdom 文件夹中运行yarn 之前,我遇到了同样的错误。输出为: $ yarn convert-idl && yarn generate-js-globals yarn run v1.22.5 $ node ./scripts/webidl/convert.js 2.97s 完成。 yarn run v1.22.5 $ node ./scripts/generate-js-globals.js 之后出现/jsdom/living/generated 文件夹。除了你的问题,我在网上也找不到任何东西。
    • 啊,是的,这行得通!完成这些步骤以使其正常工作有点烦人...希望所需的依赖项将很快更新以更好地支持他。
    【解决方案2】:

    我在 firebase auth 模拟器中以编程方式创建用户时也遇到了问题。

    而不是使用

    https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]
    

    您必须使用以下格式:

    http://localhost:9099/identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]
    

    然后给出一个这样的 JSON 正文,然后点击 post

    {
    "email": "test@test.com",
    "password": "test12"
    }
    

    瞧!您的模拟器中有一个用户。将此与 fetch 或 axios 结合使用,您可以为您的模拟器播种用户。如果您需要添加自定义声明或其他信息,请在创建用户时触发的函数模拟器中创建函数。

    functions.auth.user().onCreate
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多