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

Unable to execute tests with Cypress using Firebase Emulator - Application accesses Production Firestore Service #4917

Closed
sceee opened this issue May 17, 2021 · 2 comments
Labels
api: firestore testing-sdk testing with emulator

Comments

@sceee
Copy link

sceee commented May 17, 2021

[REQUIRED] Describe your environment

  • Operating System version: Windows 10 20H2
  • Browser version: Chrome 90 (Cypress)
  • Firebase SDK version: v8.6.1
  • Firebase Product: firestore (auth and functions seem to work)

[REQUIRED] Describe the problem

I cannot get the Firestore emulator to work when executing my application under test with Cypress.
It seems, the Firestore production service is always contacted instead of the Firestore emulator.

Other emulators (auth & functions) seem to be working correctly and get contacted by the app.

The strange thing here is that the application works with the emulators if using the regular Chrome instead of the Cypress-started one.
So if executing Cypress tests but opening the application's Url (http://localhost:8080) manually in a (separate) tab in a regular Chrome, in the Cypress-started Chrome, Firestore is contacted in production. But in the regular ("manual") started Chrome, the application contacts to the Firestore emulator and the app works as expected.

Steps to reproduce:

  1. Have an application that uses Authentication and Firestore and that is set up to use the Firebase emulators locally:
    const isTestRun = window.Cypress
    if (location.hostname === 'localhost' || isTestRun) {
      auth.useEmulator('http://localhost:5003')
      firestore.useEmulator('localhost', 5002)
      functions.useEmulator('localhost', 5001)

      if (isTestRun) {
        // Set LongPolling to make Firestore work at all with Cypress
        firestore.settings({ experimentalAutoDetectLongPolling: true })
        firebase.firestore.setLogLevel('debug')
      }
    }
  1. Have a cypress test that authenticates and afterwards, accesses a restricted document for the signed in user
  2. In parallel to the executed Cypress test (or after it failed), navigate to http://localhost:8080 (app Url) in a regular Chrome tab and manually execute the same action (login)

Within Cypress, Chrome's Dev-Tools show the following permission denied error:
image
...which actually makes sense, as there is no user in the production database and obviously, this access should then fail.
The corresponding request to Firestore from Chrome's dev-tools network tab was:

https://firestore.googleapis.com/google.firestore.v1.Firestore/Listen/channel?database=projects%2................

Whereas the request to Authentication went correctly to the Auth emulator:

http://localhost:5003/www.googleapis.com/identitytoolkit/v3/relyingparty/getAccountInfo?..........

Now, when accessing the app in a regular Chrome (still Cypress runs in the background and "serves" the app), signing in and looking at the network tab, the requests go to:

http://localhost:5002/google.firestore.v1.Firestore/Listen/channel?database=projects%2F......................

So what happens here seems to be that

  • Authentication requests go correctly to the Auth emulator
  • Firestore requests falsely go to the Firestore production service

Now, I had a feeling that experimentalAutoDetectLongPolling: true has an effect here.
So if I omit setting experimentalAutoDetectLongPolling: true, the requests to Firestore seem to go correctly to the emulator:

http://localhost:5002/google.firestore.v1.Firestore/Listen/channel?database=projects%2F.....................

...but fail because of #1674 / cypress-io/cypress#2374 (comment) with

@firebase/firestore: Firestore (8.5.0): 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.

Actually I put the experimentalAutoDetectLongPolling in there because of this comment cypress-io/cypress#2374 (comment) (I also tried experimentalForLongPolling first).

So it seems:

  • experimentalAutoDetectLongPolling: true / experimentalForLongPolling: true causes Firestore requests to always go to Firestore production when the app is executed via Cypress, even if firestore.useEmulator('localhost', 5002) is used

It feels this bug makes it currently impossible to test Firebase applications using Firestore under Cypress using Firebase emulator.
Is there any way to resolve this?

Relevant Code:

See above.

@looptheloop88 looptheloop88 added the testing-sdk testing with emulator label May 17, 2021
@looptheloop88
Copy link

looptheloop88 commented May 17, 2021

Hi @sceee, you should be using the useEmulator() after the firestore.settings({ experimentalAutoDetectLongPolling: true }). The settings() reverts the useEmulator(). This is the reason why your app is trying to use the project instance and not the emulator.

We are exploring potential solutions to improve or optimize this feature by adding warnings that settings() should be written first before the useEmulator(), but we don't have any details or timelines to share.

@sceee
Copy link
Author

sceee commented May 18, 2021

Ah, I missed that @looptheloop88 . Thanks for your help! That's tricky.

@firebase firebase locked and limited conversation to collaborators Jun 17, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api: firestore testing-sdk testing with emulator
Projects
None yet
Development

No branches or pull requests

4 participants