How to use firestore emulator from client

10,205

Solution 1

Ok i found how to do it :

1) launch the functions emulator locally:

set GOOGLE_APPLICATION_CREDENTIALS=./privatekey.json && firebase serve --only functions

2) then client side:

if (process.env.NODE_ENV === 'development') {
    firebase.functions().useFunctionsEmulator('http://localhost:5001')
}

Solution 2

Install the testing lib

npm i -D @firebase/testing

Setup and start the emulator in another terminal:

firebase setup:emulators:firestore

firebase serve --only firestore

Setup the tests

const firebase = require("@firebase/testing");

// Helper function to setup test db
function authedApp(auth) {
  return firebase
    .initializeTestApp({ projectId: FIRESTORE_PROJECT_ID, auth })
    .firestore();
}

// Setup methods
beforeEach(async () => {
  // Clear the database between tests
  await firebase.clearFirestoreData({ projectId: FIRESTORE_PROJECT_ID });
});

// Clean up apps between tests.
afterEach(async () => {
  await Promise.all(firebase.apps().map(app => app.delete()));
});

Run the tests

it("should retrieve correct item", async () => {
  // Init test db
  const db = authedApp(null);

  // Manually add item to collection
  const ref = await db.collection(COLLECTION_NAME).add({name: 'test item'});

  // Fetch item by id 
  const resp = await db.collection(COLLECTION_NAME).doc(ref.id).get();

  // test the output
  expect(resp).toBeDefined();
  expect(resp).toEqual(expect.objectContaining({name: 'test item'}));
});

Of course your particular setup and circumstances will differ, but this at least should give you a general idea. More info: https://firebase.google.com/docs/rules/unit-tests

Note from 'Test your Cloud Firestore Security Rules'

Data written to the Cloud Firestore emulator is held in memory until the emulator is stopped. If the emulator is run continuously, this may have an impact on test isolation. To ensure that data written in one test is not read in another, either explicitly clear your data with clearFirestoreData, or assign a different project ID for each independent test: when you call firebase.initializeAdminApp or firebase.initializeTestApp, append a user ID, timestamp, or random integer to the projectID.

Edit: I wrote a blog post a while back, which goes into more detail about the subject.

Solution 3

I had the same problem too. I found the following example, which looks like its still work in progress:

https://github.com/firebase/quickstart-nodejs/tree/master/firestore-emulator/browser-quickstart

They didn't use @firebase/testing directly in their example. When I did try to embed @firebase/testing in my webpack code, it tries to connect via grpc, which attempts to do fs.existsSync, which doesn't exist in webpack browser context. They prefer to enable the functionality via WebChannel instead.

Some caveats as of Nov 2019:

  • You might see errors in the console connecting to localhost:8080 with the X-Goog-API. I am not sure what is that for.
  • You might get the following error: @firebase/firestore: Firestore (6.3.5): Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds.

Despite having those errors, my functions were still able to connect to the local firestore.

Versions I had at time I was testing:

  • firebase-js-sdk 6.3.1
  • firebase-tools 7.3.1

Update 11/18:

  • I raised an issue within quickstart-nodejs github and it seems I just needed to use the latest versions of everything.

Versions:

  • firebase-js-sdk v7.4.0
  • firebase-tools v7.8.0

Solution 4

Okay, this is trivial... In your firestore cient config you should have provided the host, not the origin for firestore (the protocol is set using the ssl parameter):

firebase.firestore().settings({
    host: 'localhost:8080',
    ssl: false
})

At least this solved it for me when I had the exact same error.

Just FYI to anyone who's reading this - if you run into problems with the firestore client, you can use debug level logging, just set firebase.firestore.setLogLevel('debug'). Had the OP done that, he might have noticed that firebase is accessing firestore at http://http://localhost:8080/...

Share:
10,205

Related videos on Youtube

Anthony JEAMME
Author by

Anthony JEAMME

Master's Degree in Web Intelligence Independent Web Developer with copywriting & webdesign skills

Updated on June 04, 2022

Comments

  • Anthony JEAMME
    Anthony JEAMME almost 2 years

    I want to test locally my firebase functions. These functions make firestore queries.

    So i start the emulator firebase emulators:start and in my client i use firebase.functions().useFunctionsEmulator('http://localhost:5001').

    My functions work well when i call them in my client. I can read/write data inside the firestore emulator.

    The problem :

    I want to read the firestore emulator data directly inside my client, like :

    firebase.firestore().collection('tests').get().then(tests => {
        console.log( tests.docs.map(test=>test.map) )
    })
    

    but i can't find how to set the firestore emulator inside my client.

    here what i tried:

    1) Firestore setting

    firebase.firestore().settings({
        host:'http://localhost:8080',
        ssl:false
    })
    

    result :

    i get @firebase/firestore: Firestore (6.3.5): Could not reach Cloud Firestore backend. Backend didn't respond within 10 seconds. inside my client console.

    The http request returns 'Not found'

    2) Set the emulator url inside my firebaseConfig

    var firebaseConfig = {
        // ...
        databaseURL: "http://localhost:8080",
        // ...
    }
    
    firebase.initializeApp(firebaseConfig)
    
    

    in this case, the remote server (https://firestore.googleapis.com..) is requested.

    So i want to setup one of these two cases :

    1) Using the remote firestore inside my functions emulators

    OR

    2) Using the local firestore emulator inside my client code.

    Anyone has already done this ?

  • ThdK
    ThdK over 4 years
    Will there be real data written in the firestore db using this method?
  • ThdK
    ThdK over 4 years
    Never mind, found the answer in the docs and I've added it to your answer.
  • Antonio Ooi
    Antonio Ooi almost 4 years
    Then what about the Firestore Emulator and the test data? You go straight to the production server for the database?
  • BorisD
    BorisD over 2 years
    This is it with firebase-admin ^9.2.0 Thank you