使用 Firebase Auth 模拟器以编程方式创建用户
Create a user programatically using Firebase Auth emulator
我正在尝试使用 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>
更新jsdom版本16.5.2
这个新版本现在支持 access-control-allow-headers 的通配符,因此对于使用 Create React App 创建的项目,更新到这个版本或将其用作解决方案可以解决问题。
jsdom 16.5.2之前版本的解决方法
错误是由 jsdom 抛出的,因为它不支持 access-control-allow-headers 的通配符,但 firebase 使用通配符(参见 issue for jsdom and this pull request related to firebase). There are two open pull requests to fix this issue: https://github.com/jsdom/jsdom/pull/3073 and https://github.com/jsdom/jsdom/pull/2867.
可以通过手动更改 node_modules
文件夹中的相关代码或在 package.json
:
中使用 fork 作为依赖项来解决此问题
"jsdom": "silviot/jsdom#fix/allow-headers"
如果 jsdom
不是直接依赖项,那么您可以将以下内容添加到顶层的 package.json
:
"resolutions": {
"jsdom": "silviot/jsdom#fix/allow-headers"
}
如果使用分叉,jsdom
文件夹中会缺少一些自动生成的文件。这些可以通过文件夹中的 运行 npm install
或 yarn install
生成。要自动执行此操作,您可以将 prepare
脚本添加到 package.json
:
"scripts": {
"prepare": "cd node_modules/jsdom && yarn"
},
我在 firebase 身份验证模拟器中以编程方式创建用户时也遇到了问题。
而不是使用
https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]
您必须使用以下格式:
http://localhost:9099/identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]
然后给一个JSON这样的body,打post
{
"email": "test@test.com",
"password": "test12"
}
瞧!您的模拟器中有一个用户。将它与 fetch 或 axios 结合起来,你就可以为你的模拟器播种用户。如果您需要添加自定义声明或其他信息,请在创建用户时触发的函数模拟器中创建函数。
functions.auth.user().onCreate
我正在尝试使用 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>
更新jsdom版本16.5.2
这个新版本现在支持 access-control-allow-headers 的通配符,因此对于使用 Create React App 创建的项目,更新到这个版本或将其用作解决方案可以解决问题。
jsdom 16.5.2之前版本的解决方法
错误是由 jsdom 抛出的,因为它不支持 access-control-allow-headers 的通配符,但 firebase 使用通配符(参见 issue for jsdom and this pull request related to firebase). There are two open pull requests to fix this issue: https://github.com/jsdom/jsdom/pull/3073 and https://github.com/jsdom/jsdom/pull/2867.
可以通过手动更改 node_modules
文件夹中的相关代码或在 package.json
:
"jsdom": "silviot/jsdom#fix/allow-headers"
如果 jsdom
不是直接依赖项,那么您可以将以下内容添加到顶层的 package.json
:
"resolutions": {
"jsdom": "silviot/jsdom#fix/allow-headers"
}
如果使用分叉,jsdom
文件夹中会缺少一些自动生成的文件。这些可以通过文件夹中的 运行 npm install
或 yarn install
生成。要自动执行此操作,您可以将 prepare
脚本添加到 package.json
:
"scripts": {
"prepare": "cd node_modules/jsdom && yarn"
},
我在 firebase 身份验证模拟器中以编程方式创建用户时也遇到了问题。
而不是使用
https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]
您必须使用以下格式:
http://localhost:9099/identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]
然后给一个JSON这样的body,打post
{
"email": "test@test.com",
"password": "test12"
}
瞧!您的模拟器中有一个用户。将它与 fetch 或 axios 结合起来,你就可以为你的模拟器播种用户。如果您需要添加自定义声明或其他信息,请在创建用户时触发的函数模拟器中创建函数。
functions.auth.user().onCreate