Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for onSnapshot #63

Closed
HauptmannEck opened this issue Feb 10, 2021 · 5 comments · Fixed by #65
Closed

Add support for onSnapshot #63

HauptmannEck opened this issue Feb 10, 2021 · 5 comments · Fixed by #65

Comments

@HauptmannEck
Copy link

Summary

Firestore has .onSnapshot() which is an alternative to .get() on a collection. It is used to get realtime updates from the DB. This is currently not handled by this mock.

Basic example

        firestore
            .collection( Collections.history )
            .onSnapshot( ( snapshot ) => {
                setHistory(snapshot.docs.map(doc => doc.data() as IHistory));
            } );

Motivation

My code uses quite a few of these to sync my UI with the DB, so to test them I need to be able to mock them and this library is the best option to mock Firebase.
To mock this we should be able to use the same logic as the .get() instead of as a Promise returning the query results as a function callback.

@sbatson5
Copy link
Owner

Thanks for pointing this out. It's not an API i've used.

Digging into firestore's docs, it looks like it's a bit more complicated than the get call on a collection.
https://firebase.google.com/docs/reference/js/firebase.firestore.CollectionReference#onsnapshot

🤔 That seems a little inconsistent with some of their documented use-cases

db.collection("cities").doc("SF")
    .onSnapshot({
        // Listen for document metadata changes
        includeMetadataChanges: true
    }, (doc) => {
        // ...
    });

Or

db.collection("cities").where("state", "==", "CA")
    .onSnapshot((querySnapshot) => {
        var cities = [];
        querySnapshot.forEach((doc) => {
            cities.push(doc.data().name);
        });
        console.log("Current cities in CA: ", cities.join(", "));
    });

Sometimes they refer to the object returned as a doc but other times as a QuerySnapshot which is an instance of a QuerySnapShot object.

I'm assuming that it depends on whether you are fetching one versus multiple records. We should be able to get this to work with our current buildQuerySnapShot helper (props to @AverageHelper for building it 🙌 ).

This was mostly me thinking out loud, but all this is to say that I will try to build this out but it seems to be a bit more complicated than just returning the same results as get. I want to make sure we add support for the other things that a snapshot can do, in case someone else uses this and it doesn't work as expected.

Any tips are welcome

@HauptmannEck
Copy link
Author

Thanks for taking a look!
Yeah I have not used the optional observer or options parameters of the onSnapshot method, so I don't have much insight into them and have no idea how widly used they are. I have only used the basic pattern:

onSnapshot ( onNext :  ( snapshot/doc :  QuerySnapshot/Document < T > ) => void)

Like the .get().then(...) pattern the onNext callback returns a single doc for DocumentReference.onSnapshot() and QuerySnapshot for the CollectionReference.onSnapshot()

@sbatson5
Copy link
Owner

@HauptmannEck Can you see if your tests pass with #65 in your repo?

@HauptmannEck
Copy link
Author

@sbatson5 The tests I had built now work with that branch, and I get the expected output.

@sbatson5
Copy link
Owner

Versions 0.8.0 was released with this update!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants