2021/10/04追記: rules-unit-testingのバージョンがアップして使い方が変わりました。紹介記事を書いているのでよければこちらもご覧ください。
https://zenn.dev/moga/articles/firebase-rules-unit-testing-v2
---追記終わり
2020年8月20日にFirebase SDKの7.19.0がリリースされました。このバージョンではTestingSDKに以下のアップデートが入りました。
@firebase/testing
のいわば後継として、新たに@firebase/rules-unit-testing
がリリースされました。名前が変更されて、何のためのパッケージなのかわかりやすくなりました。対応PRは、引用RTでmonoさんが教えてくださったこちらになります。
https://t.co/SmfbOhJNTf が対応プルリクで、そこにこの変更に至った議論のリンクが載ってたけど中の人しかアクセスできなかった( ´・‿・`) https://t.co/KrKn1FrBJR
— mono (@_mono) August 22, 2020
軽く目を通してみると、このリリースに至った経緯はGooglerしか見ることができませんでした。しかし、破壊的変更が発生するにも関わらずこのリリースを行ったことを考えると、今後はこの新しいTestingSDKを使っていくほうがよいでしょう。
違い
ReleaseNoteに記載されているとおりですが、以下の違いがあります。
- インターフェースは互換性がある
-
assertFails()
の挙動が変わる- いままではassertFailsの引数に渡したPromiseがrejectされればfailとしていたようだが、今回からFirestoreのrulesに弾かれたときに発生する
PERMISSION_DENIED
のときのみfailとするようになる。これにより、より正確なrulesのテストになる。
- いままではassertFailsの引数に渡したPromiseがrejectされればfailとしていたようだが、今回からFirestoreのrulesに弾かれたときに発生する
-
initializeAdminApp()
がfirebase-admin
依存になる- 今までは
firebase-admin
を模倣したインスタンスを返していたが、新しいパッケージではfirebase-admin
を使ってインスタンスを返すようになる
- 今までは
対応
@firebase/rules-unit-testing
をインストールします。すでに@firebase/testing
を使っている場合は、不要になるのでアンインストールしておきましょう。
$ npm uninstall @firebase/testing
$ npm i -D @firebase/rules-unit-testing
import文を書き換えます。
- import * as firebase from '@firebase/testing'
+ import * as firebase from '@firebase/rules-unit-testing'
書き換えが完了したら一度テストを実行してみるとよいでしょう。テストの書き方によってはいくつかFAILしているかもしれません。それは、set
メソッドでTimestamp
やFieldValue
がinvalid object
とかinvalid data
というエラーの場合は下記が原因です。
client用Firestoreとadmin用Firestoreは別物
下記のようにする必要があります。
import * as firebase from '@firebase/rules-unit-testing'
import * as admin from 'firebase-admin'
const projectId = 'sample'
const databaseName = 'test'
const clientFirestore = firebase.initializeTestApp({ projectId, databaseName }).firestore()
const adminFirestore = firebase.initializeAdminApp({ projectId, databaseName }).firestore()
const clientUserRef = clientFirestore.collection('users').doc()
const adminUserRef = adminFirestore.collection('users').doc()
// OK: Client用のFirestoreには@firebase/rules-unit-testingから生成したFieldValueを渡さなければならない
clientUserRef.set({ createdAt: firebase.firestore.FieldValue.serverTimestamp() })
// NG: Client用のFirestoreにfirebase-adminから生成したFieldValueを渡すとエラーになる
clientUserRef.set({ createdAt: admin.firestore.FieldValue.serverTimestamp() })
// OK: Admin用のFirestoreにはfirebase-adminから生成したFieldValueを渡さなければならない
adminUserRef.set({ createdAt: admin.firestore.FieldValue.serverTimestamp() })
// NG: Admin用のFirestoreに@firebase/rules-unit-testingから生成したFieldValueを渡すとエラーになる
adminUserRef.set({ createdAt: firebase.firestore.FieldValue.serverTimestamp() })
ようするにFirestoreに渡す値はパッケージが一致している必要があるということです。これが一致していないとエラーになります。実際、私が担当しているプロダクトのTestingSDKを差し替えるとこれに起因するエラーがいくつか発生していました。(いままでは、逆に、admin用のFirestoreにfirebase-adminから生成したTimestampを渡すとエラーになっていたと思う)
おわりに
何か間違っている点などありましたらコメントいただけると幸いです。また、Firebaseに関する発信をTwitterとYoutubeでおこなっているので、よければ見てください。
追記
この記事を書いたことがきっかけで、実際に@firebase/rules-unit-testing
を試してくれた人がいて、そのおかげでfirebase-js-sdk
にコントリビューターになれました!SDKで怪しい挙動があったらGithubに行ってコードを読んでみるといいかもしれません。
firebase-js-sdkにPR送ってたんだけどマージされた🎉 🎉はじめて大きいOSSにPR送ったけどめちゃくちゃうれしい〜〜〜普段愛用しているOSSにContributeできるとこんなにうれしいんだな…https://t.co/yw6ekCH2Z9 pic.twitter.com/jI4W79Iyd3
— moga🍳 (@_mogaming) August 26, 2020