Lesson 15 / 25

Testing Rules With the Emulator Suite

Prove allow and deny cases.

Unit tests against the emulator

The Firebase Local Emulator Suite runs Firestore, Auth, Storage, Functions and other emulators locally. The @firebase/rules-unit-testing library loads your rules into the emulator and gives you contexts for an authenticated user, an unauthenticated user, or a context that bypasses rules for seeding data. Wrap operations in assertSucceeds and assertFails and write tests for both: that owners can write and that strangers cannot. Run them in CI with firebase emulators:exec so every rules change is checked. The console's Rules Playground is handy for quick experiments but is not a substitute for tests.

A rules test

TypeScript with a test runner such as Vitest or Jest.

import { readFileSync } from "node:fs";
import {
  initializeTestEnvironment, assertFails, assertSucceeds, RulesTestEnvironment,
} from "@firebase/rules-unit-testing";
import { doc, getDoc, setDoc, serverTimestamp } from "firebase/firestore";

let env: RulesTestEnvironment;

beforeAll(async () => {
  env = await initializeTestEnvironment({
    projectId: "demo-rules-test",
    firestore: { rules: readFileSync("firestore.rules", "utf8") },
  });
});
afterAll(() => env.cleanup());

test("users can create only their own profile", async () => {
  const alice = env.authenticatedContext("alice").firestore();
  await assertSucceeds(setDoc(doc(alice, "profiles/alice"),
    { displayName: "Alice", createdAt: serverTimestamp() }));
  await assertFails(setDoc(doc(alice, "profiles/bob"),
    { displayName: "Not Bob", createdAt: serverTimestamp() }));
});

test("signed-out users cannot read profiles", async () => {
  const anon = env.unauthenticatedContext().firestore();
  await assertFails(getDoc(doc(anon, "profiles/alice")));
});

// shell, not run here:
// firebase emulators:exec --only firestore "npm test"

Use a demo- project id

Project ids starting with demo- tell the emulators that no real project exists, so tests cannot accidentally reach production resources.

Quick check: Which helper asserts that an operation is denied by rules?

  • assertFails
  • assertSucceeds
  • withSecurityRulesDisabled
  • onSnapshot
Answer

assertFails — Test denials as carefully as approvals.