💽

Firestoreのセキュリティルールのテストを行う際に処理が終わらずタイムアウトする

2023/05/13に公開

Firestoreのセキュリティルールのテスト導入を行った際にトラブったメモです。

https://firebase.google.com/docs/rules/unit-tests?hl=ja

発生した問題

以下のようなテストを書いてみました。

    test(
      "作成できない",
      async () => {
        await assertFails(
          addDoc(collection(db, "users"), {
            displayName: "NewTestUser",
          })
        )
      }
    )

エミュレーターを起動してテストを実行してみると以下のように失敗しました。

addDocの処理が終わらなくてそのままタイムアウトしています。

> jest firebase/tests/rules/users.test.ts

 FAIL  firebase/tests/rules/users.test.ts (11.328 s)
  users
    ログインしてないとき
      ✕ 作成できない (5013 ms)

  ● users › ログインしてないとき › 作成できない

    thrown: "Exceeded timeout of 5000 ms for a test.
    Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

      24 |     })
      25 |
    > 26 |     test("作成できない", async () => {
         |     ^
      27 |       await assertFails(
      28 |         addDoc(collection(db, "users"), {
      29 |           displayName: "NewTestUser",

解決方法

原因調査は難航したのですが、以下のサイトにある回答が参考になりました。

https://stackoverflow.com/questions/75890427/firestore-rules-tests-always-ends-with-timeout-error

jest.config.jstestEnvironment: jsdomになっているから失敗していました。
デフォルトのtestEnvironment: nodeに変更すればタイムアウトしなくなります。

修正例

ReactやNextJSと共通の環境でテストをしているときは、実行コマンドを分けることで別のConfigを使うのがいいでしょう。

構成は

├── firebase
│   ├── data
│   ├── tests
│   │   ├── helpers
│   │   └── rules
│   ├── .firebaserc
│   ├── firebase.json
│   └── firestore.rules
├── public
└── src
    ├── pages
    │   └── api
    ├── styles
    └── test
        └── pages

のような感じだとします。

NextJS用のテストConfig

jest.config.js
module.exports = {
  roots: ["<rootDir>"],
  testMatch: ["**/*.+(spec|test).+(ts|tsx|js)"],
  testPathIgnorePatterns: ["<rootDir>/firebase/"],
  transform: {
    "^.+\\.(ts|tsx)$": "ts-jest",
  },
  moduleDirectories: ["node_modules"],
  testEnvironment: "jsdom",
}

Firestoreのセキュリティルール用のテストConfig

jest.config.firebase.js
module.exports = {
  roots: ["<rootDir>"],
  testMatch: ["<rootDir>/firebase/**/*.+(spec|test).+(ts|tsx|js)"],
  transform: {
    "^.+\\.(ts|tsx)$": "ts-jest",
  },
  moduleDirectories: ["node_modules"],
  testEnvironment: "node",
}

それぞれの実行コマンド

package.json
  "scripts": {
    "test": "jest",
    "test_firebase": "jest --config jest.config.firebase.js"
  },

Discussion