Search code examples
javascriptfirebase-realtime-databasefirebase-securityfirebase-tools

Using Firebase DB Emulators, how to clear database between tests and avoid PERMISSION_DENIED?


I'm following this guide to setup firebase emulators to test my realtime database security rules: https://firebase.google.com/docs/emulator-suite/connect_rtdb#clear_your_database_between_tests

At "Clear your database between tests", it suggests doing:

firebase.database().ref().set(null);

However, my security rules prevent my app from doing so.

Here's my code:


import * as firebase from '@firebase/testing';
import fs from 'fs';

const app = firebase.initializeTestApp({
  databaseName: 'myDb',
  auth: {
    uid: 'myuid',
  },
});

describe('test', () => {
  beforeEach(async () => {
    await firebase.loadDatabaseRules({
      databaseName: 'mydb',
      rules: fs.readFileSync('database.rules.json', 'utf8'),
    });
    
    await app.database().ref().set(null) // This line throws a permission denied error
  });

  afterAll(async () => {
    await Promise.all(firebase.apps().map((app) => app.delete()));
  });

  it('test', async (done) => {
    // ... //
  });
}

How can I reset my database between my tests?


Solution

  • Found a solution here

    I need to use

    firebase.initializeAdminApp({ databaseName: "myDb" });
    

    to create an app that is authenticated as an admin. I can then reset the database between each test:

      const app = firebase.initializeTestApp({
        databaseName: 'myDb',
        auth: {
          uid: 'myuid',
        },
      });
      const adminApp = firebase.initializeAdminApp({ databaseName: "myDb" });
      let backup;
    
      beforeEach(async () => {
        await firebase.loadDatabaseRules({
          databaseName: 'myDb',
          rules: fs.readFileSync('database.rules.json', 'utf8'),
        });
        await adminApp
          .database()
          .ref('/')
          .once('value')
          .then((v) => {
            backup = v.val();
          })
      });
    
      afterEach(async ()=>{
        await adminApp.database().ref('/').set(backup);
      })