Skip to content

Commit

Permalink
Create sagas to handle resolve/reject actions fix #29
Browse files Browse the repository at this point in the history
  • Loading branch information
diegohaz committed Dec 15, 2016
1 parent ee6b53f commit c3a90f7
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 53 deletions.
18 changes: 6 additions & 12 deletions src/store/post/sagas.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,36 @@ import { take, put, call, fork } from 'redux-saga/effects'
import { postList, postCreate, POST_LIST_REQUEST, POST_CREATE_REQUEST } from './actions'
import api from 'services/api'

const fn = () => true

export function* createPost (newData, resolve = fn, reject = fn) {
export function* createPost (newData) {
try {
const { data } = yield call(api.post, '/posts', { id: 1, ...newData })
resolve(data)
yield put(postCreate.success(data))
} catch (e) {
reject(e)
yield put(postCreate.failure(e))
}
}

export function* listPosts (limit, resolve = fn, reject = fn) {
export function* listPosts (limit) {
try {
const params = { _limit: limit }
const { data } = yield call(api.get, '/posts', { params })
resolve(data)
yield put(postList.success(data))
} catch (e) {
reject(e)
yield put(postList.failure(e))
}
}

export function* watchPostCreateRequest () {
while (true) {
const { data, resolve, reject } = yield take(POST_CREATE_REQUEST)
yield call(createPost, data, resolve, reject)
const { data } = yield take(POST_CREATE_REQUEST)
yield call(createPost, data)
}
}

export function* watchPostListRequest () {
while (true) {
const { limit, resolve, reject } = yield take(POST_LIST_REQUEST)
yield call(listPosts, limit, resolve, reject)
const { limit } = yield take(POST_LIST_REQUEST)
yield call(listPosts, limit)
}
}

Expand Down
43 changes: 2 additions & 41 deletions src/store/post/sagas.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,6 @@ import * as actions from './actions'
import api from 'services/api'
import saga, * as sagas from './sagas'

const resolve = jest.fn()
const reject = jest.fn()

beforeEach(() => {
jest.resetAllMocks()
})

describe('createPost', () => {
const data = { id: 1, title: 'test' }

Expand All @@ -19,27 +12,11 @@ describe('createPost', () => {
expect(generator.next({ data }).value).toEqual(put(actions.postCreate.success(data)))
})

it('calls success and resolve', () => {
const generator = sagas.createPost(data, resolve)
expect(generator.next().value).toEqual(call(api.post, '/posts', data))
expect(resolve).not.toBeCalled()
expect(generator.next({ data }).value).toEqual(put(actions.postCreate.success(data)))
expect(resolve).toHaveBeenCalledWith(data)
})

it('calls failure', () => {
const generator = sagas.createPost(data)
expect(generator.next().value).toEqual(call(api.post, '/posts', data))
expect(generator.throw('test').value).toEqual(put(actions.postCreate.failure('test')))
})

it('calls failure and reject', () => {
const generator = sagas.createPost(data, resolve, reject)
expect(generator.next().value).toEqual(call(api.post, '/posts', data))
expect(reject).not.toBeCalled()
expect(generator.throw('test').value).toEqual(put(actions.postCreate.failure('test')))
expect(reject).toHaveBeenCalledWith('test')
})
})

describe('listPosts', () => {
Expand All @@ -51,38 +28,22 @@ describe('listPosts', () => {
expect(generator.next({ data }).value).toEqual(put(actions.postList.success(data)))
})

it('calls success and resolve', () => {
const generator = sagas.listPosts(1, resolve)
expect(generator.next().value).toEqual(call(api.get, '/posts', { params: { _limit: 1 } }))
expect(resolve).not.toBeCalled()
expect(generator.next({ data }).value).toEqual(put(actions.postList.success(data)))
expect(resolve).toHaveBeenCalledWith(data)
})

it('calls failure', () => {
const generator = sagas.listPosts(1)
expect(generator.next().value).toEqual(call(api.get, '/posts', { params: { _limit: 1 } }))
expect(generator.throw('test').value).toEqual(put(actions.postList.failure('test')))
})

it('calls failure and reject', () => {
const generator = sagas.listPosts(1, resolve, reject)
expect(generator.next().value).toEqual(call(api.get, '/posts', { params: { _limit: 1 } }))
expect(reject).not.toBeCalled()
expect(generator.throw('test').value).toEqual(put(actions.postList.failure('test')))
expect(reject).toHaveBeenCalledWith('test')
})
})

test('watchPostCreateRequest', () => {
const payload = { data: 1, resolve, reject }
const payload = { data: 1 }
const generator = sagas.watchPostCreateRequest()
expect(generator.next().value).toEqual(take(actions.POST_CREATE_REQUEST))
expect(generator.next(payload).value).toEqual(call(sagas.createPost, ...Object.values(payload)))
})

test('watchPostListRequest', () => {
const payload = { limit: 1, resolve, reject }
const payload = { limit: 1 }
const generator = sagas.watchPostListRequest()
expect(generator.next().value).toEqual(take(actions.POST_LIST_REQUEST))
expect(generator.next(payload).value).toEqual(call(sagas.listPosts, ...Object.values(payload)))
Expand Down
36 changes: 36 additions & 0 deletions src/store/status/sagas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { fork, take } from 'redux-saga/effects'

export function* watchResolveReject () {
const resolvers = {}
const rejecters = {}
while (true) {
const { type, resolve, reject, ...rest } = yield take('*')
let [ suffix, ...prefix ] = type.split('_').reverse()
prefix = prefix.reverse().join('_')
yield { prefix, suffix }

switch (suffix) {
case 'REQUEST':
resolvers[prefix] = resolve
rejecters[prefix] = reject
break
case 'SUCCESS':
if (resolvers[prefix]) {
resolvers[prefix](rest)
delete resolvers[prefix]
}
break
case 'FAILURE':
if (rejecters[prefix]) {
rejecters[prefix](rest)
delete rejecters[prefix]
}
}

yield { resolvers, rejecters }
}
}

export default function* () {
yield fork(watchResolveReject)
}
52 changes: 52 additions & 0 deletions src/store/status/sagas.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { take, fork } from 'redux-saga/effects'
import saga, * as sagas from './sagas'

const resolve = jest.fn()
const reject = jest.fn()

test('watchResolveReject', () => {
const generator = sagas.watchResolveReject()

const requestAction = { type: 'SOMETHING_REQUEST', resolve, reject }
expect(generator.next().value).toEqual(take('*'))
expect(generator.next(requestAction).value).toEqual({ prefix: 'SOMETHING', suffix: 'REQUEST' })
expect(generator.next().value).toEqual({
resolvers: { SOMETHING: resolve },
rejecters: { SOMETHING: reject }
})
expect(resolve).not.toBeCalled()
expect(reject).not.toBeCalled()

const successAction = { type: 'SOMETHING_SUCCESS', data: 1 }
for (let i = 0; i < 2; i++) {
expect(generator.next().value).toEqual(take('*'))
expect(generator.next(successAction).value).toEqual({ prefix: 'SOMETHING', suffix: 'SUCCESS' })
expect(generator.next().value).toEqual({
resolvers: {},
rejecters: { SOMETHING: reject }
})
}
expect(resolve).toHaveBeenCalledTimes(1)
expect(resolve).toBeCalledWith({ data: 1 })
expect(reject).not.toBeCalled()

resolve.mockClear()

const failureAction = { type: 'SOMETHING_FAILURE', error: 1 }
for (let i = 0; i < 2; i++) {
expect(generator.next().value).toEqual(take('*'))
expect(generator.next(failureAction).value).toEqual({ prefix: 'SOMETHING', suffix: 'FAILURE' })
expect(generator.next().value).toEqual({
resolvers: {},
rejecters: {}
})
}
expect(resolve).not.toBeCalled()
expect(reject).toHaveBeenCalledTimes(1)
expect(reject).toBeCalledWith({ error: 1 })
})

test('saga', () => {
const generator = saga()
expect(generator.next().value).toEqual(fork(sagas.watchResolveReject))
})

0 comments on commit c3a90f7

Please sign in to comment.