Skip to content

Commit

Permalink
Merge pull request #135 from ted-aux/snapshot-options
Browse files Browse the repository at this point in the history
Add support for SnapshotListenOptions
  • Loading branch information
n6g7 committed Aug 18, 2018
2 parents bf536bd + 960c0b0 commit c32a6b0
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 9 deletions.
8 changes: 6 additions & 2 deletions docs/reference/dev/firestore.md
Expand Up @@ -48,6 +48,10 @@ methods:
required: false
type: A [Buffer](https://redux-saga.js.org/docs/api/#buffer) object
description: Defaults to `buffers.none()`. Optional Buffer object to buffer messages on this channel. If not provided, messages will not buffered on this channel. See [redux-saga documentation](https://redux-saga.js.org/docs/api/#buffers) for more information for what options are available.
- name: snapshotListenOptions
required: false
type: A [SnapshotListenOptions](https://firebase.google.com/docs/reference/js/firebase.firestore.SnapshotListenOptions) object
description: Options to control the circumstances when the channel will emit events.
output: A redux-saga [Channel](https://redux-saga.github.io/redux-saga/docs/advanced/Channels.html) which emits every time the data at `pathOrRef` in firestore changes.
example: |
```js
Expand Down Expand Up @@ -163,7 +167,7 @@ methods:
- name: options
required: true
type: Object
description: "An object to configure how the collection should be synchronised. It must contain at least the `successActionCreator` which must take either a [DocumentSnapshot](https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentSnapshot) or a [QuerySnapshot](https://firebase.google.com/docs/reference/js/firebase.firestore.QuerySnapshot) as argument. The other possible options are `failureActionCreator` which is called on channel errors and `transform` which is an optional transformer function to be applied to the value before it's passed to the action creator. Default to the identity function (`x => x`)."
description: "An object to configure how the collection should be synchronised. It must contain at least the `successActionCreator` which must take either a [DocumentSnapshot](https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentSnapshot) or a [QuerySnapshot](https://firebase.google.com/docs/reference/js/firebase.firestore.QuerySnapshot) as argument. The other possible options are `failureActionCreator` which is called on channel errors, `transform` which is an optional transformer function to be applied to the value before it's passed to the action creator(default to the identity function (`x => x`).) and `snapshotListenOptions` which is an [SnapshotListenOptions](https://firebase.google.com/docs/reference/js/firebase.firestore.SnapshotListenOptions) object to opt into updates when only metadata changes."
output:
example: |
```js
Expand All @@ -190,7 +194,7 @@ methods:
- name: options
required: true
type: Object
description: "An object to configure how the document should be synchronised. It must contain at least the `successActionCreator` which must take either a [DocumentSnapshot](https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentSnapshot) or a [QuerySnapshot](https://firebase.google.com/docs/reference/js/firebase.firestore.QuerySnapshot) as argument. The other possible options are `failureActionCreator` which is called on channel errors and `transform` which is an optional transformer function to be applied to the value before it's passed to the action creator. Default to the identity function (`x => x`)."
description: "An object to configure how the document should be synchronised. It must contain at least the `successActionCreator` which must take either a [DocumentSnapshot](https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentSnapshot) or a [QuerySnapshot](https://firebase.google.com/docs/reference/js/firebase.firestore.QuerySnapshot) as argument. The other possible options are `failureActionCreator` which is called on channel errors, `transform` which is an optional transformer function to be applied to the value before it's passed to the action creator(default to the identity function (`x => x`).) and `snapshotListenOptions` which is an [SnapshotListenOptions](https://firebase.google.com/docs/reference/js/firebase.firestore.SnapshotListenOptions) object to opt into updates when only metadata changes."
output:
example: |
```js
Expand Down
27 changes: 23 additions & 4 deletions src/firestore.js
Expand Up @@ -33,14 +33,21 @@ function* addDocument(collectionRef, data) {
return yield call([collection, collection.add], data)
}

function channel(pathOrRef, type = 'collection', buffer = buffers.none()) {
function channel(
pathOrRef,
type = 'collection',
buffer = buffers.none(),
snapshotListenOptions,
) {
const ref =
type === 'collection'
? getCollectionRef(this, pathOrRef)
: getDocumentRef(this, pathOrRef)

const channel = eventChannel(emit => {
const unsubscribe = ref.onSnapshot(emit)
const unsubscribe = snapshotListenOptions
? ref.onSnapshot(snapshotListenOptions, emit)
: ref.onSnapshot(emit)

// Returns unsubscribe function
return unsubscribe
Expand Down Expand Up @@ -76,12 +83,24 @@ function* updateDocument(documentRef, ...args) {
}

function* syncCollection(pathOrRef, options) {
const channel = yield call(this.firestore.channel, pathOrRef, 'collection')
const channel = yield call(
this.firestore.channel,
pathOrRef,
'collection',
undefined,
options.snapshotListenOptions,
)
yield fork(syncChannel, channel, options)
}

function* syncDocument(pathOrRef, options) {
const channel = yield call(this.firestore.channel, pathOrRef, 'document')
const channel = yield call(
this.firestore.channel,
pathOrRef,
'document',
undefined,
options.snapshotListenOptions,
)
yield fork(syncChannel, channel, options)
}

Expand Down
78 changes: 75 additions & 3 deletions src/firestore.test.js
Expand Up @@ -125,6 +125,24 @@ describe('firestore', () => {

expect(document.onSnapshot.mock.calls.length).toBe(1)
})

it('respects snapshot listen options for collections', () => {
const type = 'collection'
const options = { includeMetadataChanges: true }
firestoreModule.channel.call(context, 'foo', type, undefined, options)

expect(collection.onSnapshot.mock.calls.length).toBe(1)
expect(collection.onSnapshot.mock.calls[0][0]).toBe(options)
})

it('respects snapshot listen options for documents', () => {
const type = 'document'
const options = { includeMetadataChanges: true }
firestoreModule.channel.call(context, 'foo', type, undefined, options)

expect(document.onSnapshot.mock.calls.length).toBe(1)
expect(document.onSnapshot.mock.calls[0][0]).toBe(options)
})
})

describe('deleteDocument(documentRef)', () => {
Expand Down Expand Up @@ -252,7 +270,7 @@ describe('firestore', () => {
const iterator = firestoreModule.syncCollection.call(context, path, options)

expect(iterator.next().value).toEqual(
call(context.firestore.channel, path, 'collection'),
call(context.firestore.channel, path, 'collection', undefined, undefined),
)

const chan = 'eeeerqd'
Expand All @@ -272,7 +290,34 @@ describe('firestore', () => {
const iterator = firestoreModule.syncCollection.call(context, collection, options)

expect(iterator.next().value).toEqual(
call(context.firestore.channel, collection, 'collection'),
call(context.firestore.channel, collection, 'collection', undefined, undefined),
)

const chan = 'eeeerqd'
expect(iterator.next(chan)).toEqual({
done: false,
value: fork(syncChannel, chan, options),
})

expect(iterator.next()).toEqual({
done: true,
value: undefined,
})
})

it('respects snapshot listen options', () => {
const path = 'skddksl'
const options = { snapshotListenOptions: { includeMetadataChanges: true } }
const iterator = firestoreModule.syncCollection.call(context, path, options)

expect(iterator.next().value).toEqual(
call(
context.firestore.channel,
path,
'collection',
undefined,
options.snapshotListenOptions,
),
)

const chan = 'eeeerqd'
Expand All @@ -295,7 +340,34 @@ describe('firestore', () => {
const iterator = firestoreModule.syncDocument.call(context, path, options)

expect(iterator.next().value).toEqual(
call(context.firestore.channel, path, 'document'),
call(context.firestore.channel, path, 'document', undefined, undefined),
)

const chan = 'eeeerqd'
expect(iterator.next(chan)).toEqual({
done: false,
value: fork(syncChannel, chan, options),
})

expect(iterator.next()).toEqual({
done: true,
value: undefined,
})
})

it('respects snapshot listen options', () => {
const path = 'skddksl'
const options = { snapshotListenOptions: { includeMetadataChanges: true } }
const iterator = firestoreModule.syncDocument.call(context, path, options)

expect(iterator.next().value).toEqual(
call(
context.firestore.channel,
path,
'document',
undefined,
options.snapshotListenOptions,
),
)

const chan = 'eeeerqd'
Expand Down

0 comments on commit c32a6b0

Please sign in to comment.