It's good to be able to test one's Security Rules, locally. The Firestore emulator and the @firebase/testing package provide means for this.
However, when running tests and if the access is allowed, the underlying data actually changes. This is normal from an implementation aspect, since the assertFails and assertSucceeds are only thin wrappers around the promise from Firebase client.
The problem with changing underlying data is that it makes the test setup stateful. It becomes way harder to reason what should pass and what not. Also, this presents a different mental model to the online Security Rules Playground, where allowed rule access does not change the data.
If we agree that immutability of data is good when testing Security Rules, there are two ways to approach that.
1. Cloaking
I've implemented an immutability facade in the project I'm working on. It's based on storing the document being targeted, and restoring it if write access is allowed. There are mutexes involved, in case multiple tests would access the same document at the same time.
This approach is a bit complex, but hidden from the tests themselves. It helped me reason about my Security Tests and to get them to pass.
The problem is that my current mutexes don't go far enough. Jest runs each suite in a separate JavaScript context and therefore I would need to mutex across all of those.
2. Foundation
The @firebase/testing module could help one reach the above, by providing means to make a certain connection to Firestore "dry-run". It would act as normal, on the protocol level, but if allowed, a transaction would not change the data within the Firestore emulator.
This would be beautiful. It would mean that one can build an immutable Security Rules testing structure, and I would not need to think, how to mutex-guard tests running in separate Jest contexts.
Suggestion
My current approach is to open a discussion about this, both with fellow developers and Firebase authors. If we see joint value in the immutable approach, we could make a roadmap on how to reach there.
Environment
Problem
It's good to be able to test one's Security Rules, locally. The Firestore emulator and the
@firebase/testing
package provide means for this.However, when running tests and if the access is allowed, the underlying data actually changes. This is normal from an implementation aspect, since the
assertFails
andassertSucceeds
are only thin wrappers around the promise from Firebase client.The problem with changing underlying data is that it makes the test setup stateful. It becomes way harder to reason what should pass and what not. Also, this presents a different mental model to the online Security Rules Playground, where allowed rule access does not change the data.
If we agree that immutability of data is good when testing Security Rules, there are two ways to approach that.
1. Cloaking
I've implemented an immutability facade in the project I'm working on. It's based on storing the document being targeted, and restoring it if write access is allowed. There are mutexes involved, in case multiple tests would access the same document at the same time.
This approach is a bit complex, but hidden from the tests themselves. It helped me reason about my Security Tests and to get them to pass.
The problem is that my current mutexes don't go far enough. Jest runs each suite in a separate JavaScript context and therefore I would need to mutex across all of those.
2. Foundation
The
@firebase/testing
module could help one reach the above, by providing means to make a certain connection to Firestore "dry-run". It would act as normal, on the protocol level, but if allowed, a transaction would not change the data within the Firestore emulator.This would be beautiful. It would mean that one can build an immutable Security Rules testing structure, and I would not need to think, how to mutex-guard tests running in separate Jest contexts.
Suggestion
My current approach is to open a discussion about this, both with fellow developers and Firebase authors. If we see joint value in the immutable approach, we could make a roadmap on how to reach there.