firebase / firebase/firebase-js-sdk
Firestore v10 Operations Hang Indefinitely in Jest JSDOM Environment
- Dominant language
- TypeScript
- Stars
- 5.1k
- Forks
- 1k
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 37
Description
### Operating System
MacOS Sonoma 14.1.1
### Browser Version
n/a
### Firebase SDK Version
10.6.0
### Firebase SDK Product:
Firestore
### Describe your project's tooling
For simplicity's sake, I just have some functions that are supposed to be used by our client-side apps (browser) that reads and writes from/to Firestore and I want to test them with `jest` and the firestore emulator.
So the only tooling necessary to reproduce is:
- `jest@29` for the testing
- `jest-environment-jsdom@29` for mocking the env as a browser
- `firebase-tools@12` for starting the firestore emulator
### Describe the problem
When I set the testing environment to use `jsdom`, every read/write call to Firestore hangs indefinitely until the timeout is reached. There is no error message. If the testing environment is set to `node`, the calls work as expected.
For what it's worth, I'm refactoring my codebase from `v8` to `v10` and the testing environment was working as expected by doing the workaround described in this previous issue: https://github.com/firebase/firebase-js-sdk/issues/3096#issuecomment-637584185
[Repro Repository](https://github.com/kaisermann/repro-firebase-v10-jest-jsdom)
I tried debugging this for a bit and cloned the js-SDK locally and linked with my project. The furthest that I manage to go is that the [`watchStream` never responds](https://github.com/firebase/firebase-js-sdk/blob/e9ff107eedbb9ec695ddc35e45bdd62734735674/packages/firestore/src/remote/remote_store.ts#L442), nor is the current online state set to `Offline`. It seems that when the env is set to JSDOM, the tracked online state is kept at `Unknown`. Which in turn causes the [`shouldRaiseInitialEvent` to never be `true`](https://github.com/firebase/firebase-js-sdk/blob/e9ff107eedbb9ec695ddc35e45bdd62734735674/packages/firestore/src/core/event_manager.ts#L348). (I might have gotten this wrong, I'm new to the codebase).
---
FWIW, I did find some StackOverflow unanswered questions related to this behavior:
- https://stackoverflow.com/questions/77076936/my-jest-test-hangs-when-i-try-to-reach-the-firebase-emulator-i-have-running
- https://stackoverflow.com/questions/76401143/jest-testing-stuck-at-setdoc-forever-firestore/76716071#76716071
Sorry if this is unrelated to this codebase, feel free to close it if it's the case.
edit:
I found [this comment](https://github.com/firebase/firebase-js-sdk/issues/5667#issuecomment-952079600) on an old issue and adding `useFetchStreams` makes the issue go away, even though it's not documented and exposed in the typings anymore.
### Steps and code to reproduce issue
With repro:
1. Clone the repository: [Repro Repository](https://github.com/kaisermann/repro-firebase-v10-jest-jsdom)
2. Install dependencies: npm install
3. Run tests: npm emulate-and-test
---
Manually:
1. Write a test suite connecting to the firestore emulator and read/write something from it:
```ts
const { initializeApp } = require("firebase/app");
const {
connectFirestoreEmulator,
doc,
initializeFirestore,
getDoc,
setDoc,
} = require("firebase/firestore");
const testApp = initializeApp({
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
projectId: "some-project-id",
});
const testFirestore = initializeFirestore(testApp, {
ignoreUndefinedProperties: true,
});
connectFirestoreEmulator(testFirestore, "127.0.0.1", 5001);
test("hangs forever", async () => {
const ref = doc(testFirestore, "users", "alice");
// hangs forever
await setDoc(ref, { age: 29 });
// would also hang forever
console.log((await getDoc(ref)).data());
expect(true).toBe(true);
});
```
2. Configure `jest` to use `jsdom` as the testing environment:
```js
/** @type {import('jest').Config} */
module.exports = {
// If the following line is commented, the repro test passes
// If the following line is uncommented, the repro test hangs forever
testEnvironment: 'jest-environment-jsdom',
};
```
3. Run the emulator and tests: `firebase emulators:exec --only firestore \"jest\"`
Contributor guide
Assessment
This issue has not been assessed yet.