Skip to content

Instantly share code, notes, and snippets.

@lourd
Last active September 19, 2018 03:56
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lourd/2e7572c4664dd342cbacea5660f90f40 to your computer and use it in GitHub Desktop.
Save lourd/2e7572c4664dd342cbacea5660f90f40 to your computer and use it in GitHub Desktop.
Example of making a channel in redux-saga with a firebase source and testing it with jest
import { eventChannel } from 'redux-saga'
function firebaseChannel(firebase, {
eventType = 'value',
returnSnapshot = false,
} = {}) {
return eventChannel(emit => {
const subscription = firebase.on(eventType, snapshot => {
emit(returnSnapshot ? { snapshot } : { value: snapshot.val() })
})
return () => firebase.off(eventType, subscription)
})
}
class FakeFirebase {
constructor() {
this.subs = []
this.count = 0
}
on(type, listener) {
this.subs.push({
type,
listener,
id: this.count++,
})
return this.count
}
off(type, id) {
this.subs = this.subs.filter(sub => sub.id !== id)
}
emit({ type: t, snapshot }) {
this.subs.forEach(({ type, listener }) => {
if (type === t) listener(snapshot)
})
}
}
class FakeSnapshot {
val = jest.fn(() => 42)
}
describe('firebaseChannel', () => {
it('should subscribe to firebase, emit the values into the channel that firebase ' +
'emits, and unsubscribe when the channel is closed', async () => {
const firebase = new FakeFirebase()
const channel = firebaseChannel(firebase)
const taken = new Promise(resolve => channel.take(resolve))
const snapshot = new FakeSnapshot()
firebase.emit({ type: 'value', snapshot })
const value = await taken
expect(value).toEqual({ value: snapshot.val() })
const spy = jest.spyOn(firebase, 'off')
channel.close()
expect(spy).toHaveBeenCalledWith('value', 1)
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment