Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Firestore incompatible with Create React App / Jest / JSDOM #344

Closed
matt-kinton opened this issue Mar 6, 2021 · 6 comments
Closed

Firestore incompatible with Create React App / Jest / JSDOM #344

matt-kinton opened this issue Mar 6, 2021 · 6 comments

Comments

@matt-kinton
Copy link

matt-kinton commented Mar 6, 2021

Version info

React: 17

Firebase: 8.2.10

ReactFire: 3.0.0-rc.0

Test case

import React from "react";
import { render, screen, waitFor } from "@testing-library/react";
import "firebase/auth";
import "firebase/firestore";
import {
  FirebaseAppProvider,
  useFirestore,
  useFirestoreDocData,
} from "reactfire";

function TestComponent() {
  const userRef = useFirestore().collection("users").doc("test");

  const { data: user, status } = useFirestoreDocData<any>(userRef);

  if (status !== "success") return <></>;

  return <>testing</>;
}

test("renders user", async () => {
  render(
    <FirebaseAppProvider
      firebaseConfig={config}
    >
      <TestComponent />
    </FirebaseAppProvider>
  );

  await waitFor(() => expect(screen.getByText("testing")).toBeInTheDocument());

  screen.debug();
});

Steps to reproduce

  1. Use a standard create-react-app template
  2. Setup a test similar to the one above
  3. Run it

Expected behavior

Test should pass

Actual behavior

Error: Uncaught [TypeError: this.timerId.unref is not a function]
        at reportException (C:\Users\Matt\Dev\reactfire-test\node_modules\jsdom\lib\jsdom\living\helpers\runtime-script-errors.js:62:24)
        at Timeout.task [as _onTimeout] (C:\Users\Matt\Dev\reactfire-test\node_modules\jsdom\lib\jsdom\browser\Window.js:396:9)
        at listOnTimeout (internal/timers.js:554:17)
        at processTimers (internal/timers.js:497:7) TypeError: this.timerId.unref is not a function
        at BackoffTimeout.unref (C:\Users\Matt\Dev\reactfire-test\node_modules\@grpc\grpc-js\src\backoff-timeout.ts:117:18)
        at new ResolvingLoadBalancer (C:\Users\Matt\Dev\reactfire-test\node_modules\@grpc\grpc-js\src\resolving-load-balancer.ts:199:25)
        at new ChannelImplementation (C:\Users\Matt\Dev\reactfire-test\node_modules\@grpc\grpc-js\src\channel.ts:242:34)
        at new Client (C:\Users\Matt\Dev\reactfire-test\node_modules\@grpc\grpc-js\src\client.ts:146:30)
        at new ServiceClientImpl (C:\Users\Matt\Dev\reactfire-test\node_modules\@grpc\grpc-js\src\make-client.ts:128:3)
        at GrpcConnection.Object.<anonymous>.GrpcConnection.ensureActiveStub (C:\Users\Matt\Dev\reactfire-test\node_modules\@firebase\firestore\src\platform\node\grpc_connection.ts:90:25)
        at GrpcConnection.Object.<anonymous>.GrpcConnection.openStream (C:\Users\Matt\Dev\reactfire-test\node_modules\@firebase\firestore\src\platform\node\grpc_connection.ts:175:23) 
        at PersistentListenStream.Object.<anonymous>.PersistentListenStream.startRpc (C:\Users\Matt\Dev\reactfire-test\node_modules\@firebase\firestore\src\remote\persistent_stream.ts:571:28)
        at PersistentListenStream.Object.<anonymous>.PersistentStream.startStream (C:\Users\Matt\Dev\reactfire-test\node_modules\@firebase\firestore\src\remote\persistent_stream.ts:443:24)
        at call (C:\Users\Matt\Dev\reactfire-test\node_modules\@firebase\firestore\src\remote\persistent_stream.ts:420:16)
        at call (C:\Users\Matt\Dev\reactfire-test\node_modules\@firebase\node_modules\google-closure-library\closure\goog\promise\promise.js:826:22)
        at goog.Promise.invokeCallback_ (C:\Users\Matt\Dev\reactfire-test\node_modules\@firebase\node_modules\google-closure-library\closure\goog\promise\promise.js:1166:5)
        at executeCallback_ (C:\Users\Matt\Dev\reactfire-test\node_modules\@firebase\node_modules\google-closure-library\closure\goog\promise\promise.js:1140:5)
        at D.call [as gc] (C:\Users\Matt\Dev\reactfire-test\node_modules\@firebase\node_modules\google-closure-library\closure\goog\promise\promise.js:1111:5)
        at xc (C:\Users\Matt\Dev\reactfire-test\node_modules\@firebase\node_modules\google-closure-library\closure\goog\async\run.js:124:7)
        at processTicksAndRejections (internal/process/task_queues.js:93:5)

      at console.error (node_modules/@testing-library/react/dist/act-compat.js:53:34)
      at VirtualConsole.<anonymous> (node_modules/jsdom/lib/jsdom/virtual-console.js:29:45)
      at reportException (node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:28)
      at Timeout.task [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:396:9)

I've also raised issues elsewhere. I believe the problem is that Jest is loading Node dependencies and not the browser ones. I would be happy to find a workaround that lets me keep using create-react-app if the issues cant be fixed.

firebase/firebase-js-sdk#4552
facebook/create-react-app#10626

@alexmcmanus
Copy link

I ran into a series of issues trying to get CRA/Jests tests working with reactfire and the emulators, and ultimately gave up. I couldn't even get the Firestore tests copied out of reactfire working in my project. It would be really helpful if the documentation could provide guidance (or even better, a working example) of how to get a CRA/Jest/Emulator test setup working for components and hooks. My Firestore rule tests work nicely with @firebase/rules-unit-testing, it's just the React tests that I couldn't get to work.

@matt-kinton
Copy link
Author

I've raised a bunch of issues and come to the conclusion that at the moment it's not really possible/simple at the moment unfortunately. I'm currently in the process of coming up with add decent mocking solution.

@cd-a
Copy link

cd-a commented Mar 21, 2021

I'm running tests with the above configuration without issues. Here's what i do

package.json: (ignore craco, that's just for less support, you can use react-scripts here)

"test": "firebase emulators:exec --project xxx \"CI=true craco test --env=./src/test/customTestEnvironment.js  --coverage --colors\"",

Then, the customTestEnvironment.js

/* eslint-disable @typescript-eslint/no-empty-function */
// __test-utils__/custom-jest-environment.js
// Stolen from: https://github.com/ipfs/jest-environment-aegir/blob/master/src/index.js
// Overcomes error from jest internals.. this thing: https://github.com/facebook/jest/issues/6248
'use strict';

// eslint-disable-next-line @typescript-eslint/no-var-requires
const NodeEnvironment = require('jest-environment-jsdom');

class MyEnvironment extends NodeEnvironment {
  constructor(config) {
    super(
      Object.assign({}, config, {
        globals: Object.assign({}, config.globals, {
          Uint32Array: Uint32Array,
          Uint8Array: Uint8Array,
          ArrayBuffer: ArrayBuffer,
        }),
      }),
    );
  }

  async setup() {}

  async teardown() {}
}

module.exports = MyEnvironment;

@jhuleatt
Copy link
Collaborator

jhuleatt commented Apr 7, 2021

Hi @Mattinton, now that firebase/firebase-js-sdk#4552 is fixed, is this still an issue?

@matt-kinton
Copy link
Author

Hey @jhuleatt, things are working now with the fix from @dahmc. Maybe this should be documented somewhere or raised as a new issue as it seems to come and go.. Either way I think you can probably close this?

@jhuleatt
Copy link
Collaborator

Thanks for confirming it is working now. Hopefully it won't pop up again now that the root issue, grpc/grpc-node#1708, is now resolved.

@FirebaseExtended FirebaseExtended locked and limited conversation to collaborators May 30, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants