Ripas55
Ripas55

Reputation: 943

Can't write firestore tests because of: FIRESTORE (9.6.1) INTERNAL ASSERTION FAILED: Unexpected state

Is testing possible with firebase firestore? I have been following testing tutorial and test that work for others are not working for me.

My component code Works in the client, so I'm very confused why I'm getting this error.

I have only found information regarding testing security rules in firebase, but nothing about firestore, does that mean that its the only thing that we can test?

this is the error that I get:

    FIRESTORE (9.6.1) INTERNAL ASSERTION FAILED: Unexpected state

      at fail (node_modules/@firebase/firestore/src/util/assert.ts:40:9)
      at hardAssert (node_modules/@firebase/firestore/src/util/assert.ts:54:5)
      at fromBytes (node_modules/@firebase/firestore/src/remote/serializer.ts:252:5)
      at fromWatchChange (node_modules/@firebase/firestore/src/remote/serializer.ts:475:25)
      at PersistentListenStream.onMessage (node_modules/@firebase/firestore/src/remote/persistent_stream.ts:642:25)
      at node_modules/@firebase/firestore/src/remote/persistent_stream.ts:517:21
      at node_modules/@firebase/firestore/src/remote/persistent_stream.ts:570:18
      at node_modules/@firebase/firestore/src/util/async_queue_impl.ts:135:7
      at node_modules/@firebase/firestore/src/util/async_queue_impl.ts:186:14

● if the user is fetched, the name is shown

    Unable to find an element with the text: /James/i. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

My component code:

function Hellopage() {
  const [userData, setUserData] = useState();

  const getData = async () => {
    const docRef = doc(firestore, "users", "pW5CizOJOpXezr5lGGshDmKdVzZ2");
    const docSnap = await getDoc(docRef);
    if (docSnap.exists()) {
      setUserData(docSnap.data());
    } else {
      // doc.data() will be undefined in this case
      console.log("No such document!");
    }
  };

  useEffect(() => {
    getData();
  }, []);

  return (
    <div>
      <div>{userData?.name}</div>
    </div>
  );
}

export default Hellopage;

My Test :

test("if the user is fetched, the name is shown", async () => {
  const result = render(<HelloPage />);

  expect(await result.findByText(/James/i)).toBeInTheDocument();
});

Upvotes: 3

Views: 2931

Answers (2)

gouder hicham
gouder hicham

Reputation: 133

just rerun the development server and the problem will go away

Upvotes: 0

chantey
chantey

Reputation: 5837

This is an issue with the jsdom test environment. The environment should be switched back to the default node when using firestore. If you're relying on jsdom for other tests, the simplest way to do this may be with a docblock at the top of your file:

/**
 * @jest-environment node
 */

EDIT - Seperation and Mocking

You may run into issues with this particular test because react and firebase have been tightly coupled, react needs jsdom and firebase needs node. This can be solved by either using an actual DOM based testing environment like cypress, or testing firebase seperately from react by extracting the function and using mocks. The second approach is better because it means not hitting a database when testing ui:

//firebaseService.ts

const getData = async()=>{
    const docRef = doc(firestore, "users", "pW5CizOJOpXezr5lGGshDmKdVzZ2");
    const docSnap = await getDoc(docRef);
    if (docSnap.exists()) {
      return docSnap.data();
    } else {
      console.log("No such document!");
    }
}

//Hellopage.tsx

function Hellopage({getData}) {
  const [userData, setUserData] = useState();
  useEffect(() => {
    getData()
      .then(data=> data && setUserData(data))
  }, []);

  return (
    <div>
      <div>{userData?.name}</div>
    </div>
  );
}

//Hellopage.test.tsx

const mockGetData = ()=>
  ({name:"foo"})

test('hello page renders text', () => {
  const component = renderer.create(<Hellopage getData={mockGetData}/>)
  ...
})

//firebaseService.test.ts

test('firebase service gets user data', async () => {
  const data = await getData()
  ...
})

Upvotes: 6

Related Questions