Skip to content

Instantly share code, notes, and snippets.

@cbilgili
Created December 27, 2016 08:59
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cbilgili/40762c565c2053a29b8193c56f07da2a to your computer and use it in GitHub Desktop.
Save cbilgili/40762c565c2053a29b8193c56f07da2a to your computer and use it in GitHub Desktop.
Redux CRUD Saga (redux-saga)
import { takeLatest } from 'redux-saga'
import { call, put } from 'redux-saga/effects'
import fetch from 'isomorphic-fetch'
import * as actions from './modules/grid'
import * as api from '../lib/api'
export function* fetchGrids(action) {
try {
const grids = yield call(api.GET, 'grids')
yield put(actions.fetchGridsSuccess(grids))
} catch (error) {
yield put(actions.fetchGridsFail(error))
}
}
export function* createGrid(action) {
try {
const grid = yield call(api.POST, 'grids', { grid: action.payload })
yield put(actions.createGridSuccess(grid))
yield put(actions.closeSubview())
} catch (error) {
yield put(actions.createGridFail(error))
}
}
export function* updateGrid(action) {
try {
const grid = yield call(api.PUT, `grids/${action.payload.id}`, { grid: action.payload })
yield put(actions.updateGridSuccess(grid))
yield put(actions.closeSubview())
} catch (error) {
yield put(actions.updateGridFail(error))
}
}
export function* deleteGrid(action) {
try {
yield call(api.DELETE, `grids/${action.payload}`)
yield put(actions.deleteGridSuccess(action.payload))
} catch (error) {
yield put(actions.deleteGridFail(error))
}
}
export function* watchFetchGrids() {
yield* takeLatest(actions.FETCH_GRIDS, fetchGrids)
}
export function* watchCreateGrid() {
yield* takeLatest(actions.CREATE_GRID, createGrid)
}
export function* watchUpdateGrid() {
yield* takeLatest(actions.UPDATE_GRID, updateGrid)
}
export function* watchDeleteGrid() {
yield* takeLatest(actions.DELETE_GRID, deleteGrid)
}
import 'babel-polyfill'
import { expect } from 'chai'
import { takeLatest } from 'redux-saga'
import { put, call } from 'redux-saga/effects'
import * as sagas from './sagas'
import * as api from '../lib/api'
import * as actions from './modules/grid'
// Since put() and call() return plain objects, we can reuse the same
// functions in our test code. And to test the logic of incrementAsync,
// we simply iterate over the generator and do deepEqual tests on its values.
describe('(Saga) Grids', () => {
describe('GET: Fetch Grids', () => {
it('should watch the FETCH_GRIDS action', () => {
const generator = sagas.watchFetchGrids()
expect(generator.next().value)
.to.eql(takeLatest(actions.FETCH_GRIDS, sagas.deleteGrid).next().value)
})
it('should fetch grids', () => {
const generator = sagas.fetchGrids()
expect(generator.next().value)
.to.eql(call(api.GET, 'grids'))
// fake response
const grids = []
expect(generator.next(grids).value)
.to.eql(put(actions.fetchGridsSuccess(grids)))
})
it('should return an error if fetching fails', () => {
const generator = sagas.fetchGrids()
expect(generator.next().value)
.to.eql(call(api.GET, 'grids'))
// fake response
const error = {}
expect(generator.throw(error).value)
.to.eql(put(actions.fetchGridsFail(error)))
})
})
describe('POST: Create Grids', () => {
it('should create grid', () => {
const grid = {}
const action = { payload: grid }
const generator = sagas.createGrid(action)
expect(generator.next().value)
.to.eql(call(api.POST, 'grids', { grid }))
const gridResponse = {}
expect(generator.next(gridResponse).value)
.to.eql(put(actions.createGridSuccess(gridResponse)))
expect(generator.next(gridResponse).value)
.to.eql(put(actions.closeSubview()))
})
it('should return an error if creating fails', () => {
const grid = {}
const action = { payload: grid }
const generator = sagas.createGrid(action)
expect(generator.next().value)
.to.eql(call(api.POST, 'grids', { grid }))
// fake response
const error = {}
expect(generator.throw(error).value)
.to.eql(put(actions.createGridFail(error)))
})
})
describe('PUT: Update Grids', () => {
it('should update grid', () => {
const grid = { id: 1 }
const action = { payload: grid }
const generator = sagas.updateGrid(action)
expect(generator.next().value)
.to.eql(call(api.PUT, `grids/${action.payload.id}`, { grid: action.payload }))
const gridResponse = grid
expect(generator.next(gridResponse).value)
.to.eql(put(actions.updateGridSuccess(gridResponse)))
expect(generator.next(gridResponse).value)
.to.eql(put(actions.closeSubview()))
})
it('should return an error if creating fails', () => {
const grid = { id: 1 }
const action = { payload: grid }
const generator = sagas.updateGrid(action)
expect(generator.next().value)
.to.eql(call(api.PUT, `grids/${action.payload.id}`, { grid: action.payload }))
// fake response
const error = {}
expect(generator.throw(error).value)
.to.eql(put(actions.updateGridFail(error)))
})
})
describe('DELETE: Delete Grids', () => {
it('should watch the DELETE_GRID action', () => {
const generator = sagas.watchDeleteGrid()
expect(generator.next().value)
.to.eql(takeLatest(actions.DELETE_GRID, sagas.deleteGrid).next().value)
})
it('should delete grid', () => {
const gridId = 1
const action = { payload: gridId }
const generator = sagas.deleteGrid(action)
expect(generator.next().value)
.to.eql(call(api.DELETE, `grids/${action.payload}`))
const response = {}
expect(generator.next().value)
.to.eql(put(actions.deleteGridSuccess(action.payload, response)))
})
it('should return an error if creating fails', () => {
const gridId = 1
const action = { payload: gridId }
const generator = sagas.deleteGrid(action)
expect(generator.next().value)
.to.eql(call(api.DELETE, `grids/${action.payload}`))
// fake response
const error = {}
expect(generator.throw(error).value)
.to.eql(put(actions.deleteGridFail(error)))
})
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment