firebase / firebase/firebase-js-sdk

Firestore v10 Operations Hang Indefinitely in Jest JSDOM Environment

Open
#7,808 3 comments 6 reactions 1 assignee Claimed by @milaGGL View on GitHub
api: firestore needs-attention question
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.