firebase / firebase/firebase-js-sdk

FR: Immutability when testing Firestore Security Rules

Open
#2,895 1 comment 0 reactions 0 assignees View on GitHub
api: firestore feature request
Dominant language
TypeScript
Stars
5.1k
Forks
1k
Avg merge
2d 21h
Merged PRs (30d)
37

Description

### Environment

* Firebase SDK version: 8.0.2
* Firebase Product: firestore

### 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` and `assertSucceeds` are only [thin wrappers](https://github.com/firebase/firebase-js-sdk/blob/5a637389a14c2c6f5f6dd0594df8c73619db87ee/packages/testing/src/api/index.ts#L279-L289) 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](https://github.com/akauppi/GroundLevel-es6-firebase-web). 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.

Contributor guide

Open the contributing guide

Research direction

The issue points to packages/testing/src/api/index.ts, where assertFails and assertSucceeds wrap Firebase client promises. Start by reading those entry points and the Firestore emulator connection behavior; the issue currently calls for discussion and a roadmap, so a concrete implementation and definition of done are not yet specified.

Written by the indexing model from the issue text.

Assessment

Tech stack
firebase, typescript
Domain
databases, security, testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.