firebasegoogle-cloud-firestorecypresswebapp2firebase-tools

can't use cypress to test app using using firestore local emulator


I have a app built with vue and firebase/firestore. I use the firebase emulator to local development and am trying to integrate my dev workflow with cypress. But i get a error in cypress that do not occur if i access the app from browser.

Firebase CLI version is 7.9.0 and Cypress version is "^3.8.0"

My npm scripts to load everything are below:

"start": "firebase emulators:exec --only firestore \"npm run dev:appandtest\"",
"dev:appandtest": "concurrently -n \"app,test\" -c \"bgYellow.black,bgWhite.black\" \"npm:dev:app\" \"npm:dev:test\"",
"dev:app": "webpack-dev-server --config build/webpack.dev.js",
"dev:test": "npx cypress open", 

The local server runs on port 9000 and the firebase emulator on port 8080.

After things are running, if i access the app from a normal browser everything is fine as this screen shows.

normal

enter image description here

Then i tried to run a basic cypress test with this code

    describe('The Home Page', function () {
      it('successfully loads', function () {
        cy.visit('/');
      });
    });

And i got the errors messages below:

    [2019-12-14T15:29:24.725Z]  @firebase/firestore: Firestore (6.6.2): Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds.
    This typically indicates that your device does not have a healthy Internet connection at the moment. The client will operate in offline mode until it is able to successfully connect to the backend.

    error.ts:166 Uncaught (in promise) FirebaseError: Failed to get document because the client is offline.
        at new FirestoreError (http://localhost:9000/bundle.js:11739:149)
        at Object.next (http://localhost:9000/bundle.js:16734:8)
        at next (http://localhost:9000/bundle.js:16725:4704)
        at http://localhost:9000/bundle.js:16430:411

I took a screenshot also: buggy

enter image description here

I tried to research answers but wasn't able to find one. Thanks in advance for any help.


Solution

  • The solution to this problem, at least for now, is to enable experimentalForceLongPolling, like this:

    // NOTE: do NOT put this in production.
    firebase.firestore().settings({ experimentalForceLongPolling: true })
    

    Important: this is an experimental feature and you should put it in some conditional checks with environment variables. You should not use this in production environment.

    The reason for this is best described here:

    The default behavior of Firestore's web SDK is to make use of WebChannel's streaming mode. The client makes what looks like an XHR, but then the server will hold the response open for 60 seconds and send as many server-initiated responses as it can during that time window.

    The experimentalForLongPolling option forces the server to send only a single response per request.

    And here:

    That is the same workaround we are using in cypress. I think the underlying problem is that Cypress is intercepting all network traffic so it can monitor and sometimes mock. However, the webchannel protocol used by firestore has multiple replies over the same http request. The Cypress code cannot handle this and will only forward the first reply and ignore the rest.