'Mocha: Nested describe() structure fails to register tests when using firebase rules testing library (SDK 9)

I have a Typescript Mocha setup that I'm using to test my Firestore rules. It uses the latest version of the @firebase/rules-unit-testing library that is part of the Version 9 Firebase SDK.

It also uses the latest Firestore client library that has the newer API that is tree-shakable.

My problem is that Mocha doesn't seem to be able to recognise tests in my nested describe() structure AFTER I call the initializeTestEnvironment() promise.

If you see the output you will see only two tests get executed.

package.json

{
  "name": "blocks",
  "version": "1.0.0",
  "description": "A new Flutter project.",
  "main": "index.js",
  "private": true,
  "scripts": {
    "setup": "firebase setup:emulators:firestore",
    "test": "firebase emulators:exec --only firestore \"mocha firestore.rules.spec.ts\""
  },
  "devDependencies": {
    "@firebase/rules-unit-testing": "^2.0.2",
    "@types/mocha": "^8.2.2",
    "firebase-tools": "^10.7.1",
    "chai": "^4.3.4",
    "mocha": "^9.2.2",
    "ts-node": "^9.1.1",
    "typescript": "^4.2.4"
  },
  "mocha": {
    "recursive": true,
    "reporter": "nyan",
    "require": "ts-node/register",
    "watch-extensions": "ts"
  },
  "prettier": {
    "trailingComma": "es5",
    "tabWidth": 2,
    "semi": false,
    "singleQuote": true
  }
}

tsconfig.json

{
  "compilerOptions": {
    "esModuleInterop": true,
    "importHelpers": true,
    "module": "commonjs",
    "target": "es2019",
    "types": [
      "node"
    ]
  }
}

firestore.rules.spec.ts

import { before, beforeEach, after } from 'mocha'
import { readFileSync } from 'fs'
import {
  assertFails,
  assertSucceeds,
  initializeTestEnvironment,
} from '@firebase/rules-unit-testing'
import { doc, setDoc, getDoc, updateDoc, deleteDoc } from 'firebase/firestore'

const PROJECT_ID = 'blocks-firestore-rules-testing'

describe('A test that should get run', async () => {
  it('should pass', async () => {
    return true
  })
})

describe('Firestore rules', async () => {
  it('should pass also', async () => {
    return true
  })

  const testEnv = await initializeTestEnvironment({
    projectId: PROJECT_ID,
    firestore: {
      rules: readFileSync('firestore.rules', 'utf-8'),
    },
  })

  beforeEach(async () => {
    testEnv.cleanup()
    await testEnv.clearFirestore()
  })

  after(async () => {
    testEnv.cleanup()
    await testEnv.clearFirestore()
  })

  const uid = 'normal-user'
  const user = testEnv.authenticatedContext(uid)
  const userRef = doc(user.firestore(), `users/${uid}/`)
  const dummyUserDoc = { displayName: 'John Smith' }

  it('ensures can create their own user document', async () => {
    await assertSucceeds(setDoc(userRef, dummyUserDoc))
  })

  it('ensures they can read their user document', async () => {
    testEnv.withSecurityRulesDisabled(async () => {
      setDoc(userRef, dummyUserDoc)
    })
    await assertSucceeds(getDoc(userRef))
  })

  it('ensures they can update their user document', async () => {
    testEnv.withSecurityRulesDisabled(async () => {
      setDoc(userRef, dummyUserDoc)
    })
    await assertSucceeds(updateDoc(userRef, { foo: 'baz' }))
  })

  it('ensures cannot delete their user document', async () => {
    testEnv.withSecurityRulesDisabled(async () => {
      setDoc(userRef, dummyUserDoc)
    })
    await assertFails(deleteDoc(userRef))
  })
})

Command line output:

➜  blocks git:(main) ✗ npm test

> [email protected] test
> firebase emulators:exec --only firestore "mocha firestore.rules.spec.ts"

i  emulators: Starting emulators: firestore
i  firestore: Firestore Emulator logging to firestore-debug.log
i  Running script: mocha firestore.rules.spec.ts
 2   -_-_,------,
 0   -_-_|   /\_/\
 0   -_-^|__( ^ .^)
     -_-  ""  ""

  2 passing (2ms)

✔  Script exited successfully (code 0)
i  emulators: Shutting down emulators.
i  firestore: Stopping Firestore Emulator
i  hub: Stopping emulator hub


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source