3

I was trying out the new Firebase Emulators UI announced on May 21, 2020. In the Firebase Docs, I noticed that there is a CLI command that allows us to run a script file:

firebase emulators:exec scriptpath

Run the script at scriptpath after starting emulators for the Firebase products configured in firebase.json. Emulator processes will automatically stop when the script has finished running.

Although the docs does not mention what kind of script file it should be, I presume it could be either a test script or a workable JavaScript file that be executed standalone with node filename.js without any errors. This makes sense because I can actually run an initial JS file that pre-populate some test data to the Firestore Emulator for further testing.

But since I've previously started the emulators, I have to open a new instance of command window to run the firebase emulators:exec command. Unfortunately, I hit the following errors:

D:\Firebase\my-project>firebase emulators:exec setup-db.js
i  emulators: Starting emulators: functions, firestore, database, hosting, pubsub
!  hub: emulator hub unable to start on port 4400, starting on 4401 instead.
!  emulators: It seems that you are running multiple instances of the emulator suite for project my-project-id. This may result in unexpected behavior.
i  emulators: Shutting down emulators.
i  hub: Stopping emulator hub
!  functions: Port 5001 is not open on localhost, could not start Functions Emulator.
!  functions: To select a different host/port, specify that host/port in a firebase.json config file:
      {
        // ...
        "emulators": {
          "functions": {
            "host": "HOST",
            "port": "PORT"
          }
        }
      }
i  emulators: Shutting down emulators.

Error: Could not start Functions Emulator, port taken.

Take note of this line:

! emulators: It seems that you are running multiple instances of the emulator suite for project my-project-id. This may result in unexpected behavior.

So, how can I run the firebase emulators:exec AFTER the emulators start as mentioned in the Firebase Docs and, can I run the JS file for the said purpose? Thanks in advance!

UPDATE:

If I run just the firebase emulators:exec setup-imtp-db.js without prior running the firebase emulators:start command, I ran into the following errors:

enter image description here

Note that the setup-imtp-db.js does not contain any Cloud Functions code but just a standalone JS file that populates data from another JSON file into Firestore via Admin SDK. I'm using Node.js 12.14.0 and firebase-tools 8.4.0.

Antonio Ooi
  • 1,601
  • 1
  • 18
  • 32
  • If the Firebase CLI isn't working the way you expect, I suggest posting an issue on its GitHub. https://github.com/firebase/firebase-tools – Doug Stevenson May 23 '20 at 16:14
  • I've been there before, but I don't understand their Contributing Guidelines, so might as well post it here. It's ok if nobody can answer, I can use other alternatives just to avoid our functional and integrated testing from costing too much on Google Cloud. – Antonio Ooi May 24 '20 at 01:27

2 Answers2

3

According to Firebase CLI Github README.md:

emulators:exec Start the local Firebase emulators, run a test script, then shut down the emulators.

So the scriptpath parameter isn't really meant to run a JavaScript file that pre-populates data on Firestore Emulator (and presents on its Emulator UI) for the purpose of UI Functional Test or Integrated Test. The emulators:exec will immediately shut down the emulators after finish executing the test script.

As @Doug Stevenson suggested in the comment, if a proper error handling is expected from the emulators or a new feature is required, a request or bug report can be posted on Github for firebase-tools.

Antonio Ooi
  • 1,601
  • 1
  • 18
  • 32
  • Could you give an alternative? Some kind of way to run a script to populate the database with data? – joshpetit Dec 29 '21 at 21:04
  • You can [try this](https://firebase.google.com/docs/emulator-suite/install_and_configure#export_and_import_emulator_data). But for the 1st time, you need to populate the data to Firestore Emulator, either manually or programmatically. Then subsequently, you can import the data using the exported data as shown in the given link. – Antonio Ooi Dec 30 '21 at 10:17
  • Thanks for the reply! I found another way however, if I sent the process.env['EACH_EMULATOR_IM_USING'] then I can run scripts against the emulator with the admin sdk. I use that in conjunciton with importing and exporting. – joshpetit Dec 30 '21 at 11:45
  • @joshpetit if you remember, can you elaborate on what you mean with sending the `process.env['EACH_EMULATOR_IM_USING']`? I found a workaround for this problem which I described in another answer here, but I'd be interested in running standalone scripts against the emulator as well. – Thor Galle Feb 09 '23 at 12:26
  • Yea, @ThorGalle. So I create a .env file in the root firebase directory with the key value pairs for `FIRESTORE_EMULATOR_HOST FIREBASE_AUTH_EMULATOR_HOST FIREBASE_STORAGE_EMULATOR_HOST ` (the respective values are 0.0.0.0:8080, 9099, and 9099). I then use dotenv to apply those variables to the envionrment, I have some more config in the script file that I think is unnecessary, but if that doesn't work for you I can post this as a full answer. – joshpetit Feb 10 '23 at 15:46
0

While the emulators:exec command is clearly not meant for seeding a database while continuing (manual) testing, as explained in the accepted answer, I did accomplish something of the kind.

I successfully prevented my emulators:exec-invoked database seeding script from exiting with the following method:

// db-seeder.js
const admin = require('firebase-admin');
const app = admin.initializeApp({
  projectId: 'demo-test'
});
const db = admin.firestore(app);

...

// Prevents the seed Node.js process from exiting,
// which in turn prevents the emulators from exiting.
process.stdin.resume();

Along with the --ui switch, this gives an experience comparable to running emulators:start, but then with a seeded database:

firebase --project demo-test emulators:exec --ui db-seeder.js

I had to use this method because I was getting credential problems when trying to seed the database with a standalone script, see details here on dev.to.

Thor Galle
  • 68
  • 7