redux-toolbelt-saga
Advanced tools
Comparing version 1.0.10 to 2.0.0
@@ -10,17 +10,21 @@ 'use strict'; | ||
var _marked3 = /*#__PURE__*/regeneratorRuntime.mark(getArgs); | ||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } | ||
/** | ||
* @param {AsyncActionCreator} asyncActionCreator | ||
* @param {function} fn | ||
* @param {...*} [args] | ||
* @param options? = {mapArgs?, args?}) | ||
* | ||
* @returns {Function} | ||
*/ | ||
function makeAsyncSaga(asyncActionCreator, fn) { | ||
for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { | ||
args[_key - 2] = arguments[_key]; | ||
} | ||
var _marked = /*#__PURE__*/regeneratorRuntime.mark(exec), | ||
_marked2 = /*#__PURE__*/regeneratorRuntime.mark(waitFor); | ||
function exec() { | ||
var result; | ||
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
function exec(action) { | ||
var args, result; | ||
return regeneratorRuntime.wrap(function exec$(_context) { | ||
@@ -30,22 +34,36 @@ while (1) { | ||
case 0: | ||
_context.prev = 0; | ||
_context.next = 3; | ||
return _effects.call.apply(undefined, [fn].concat(args)); | ||
_context.next = 2; | ||
return getArgs(action, options); | ||
case 3: | ||
case 2: | ||
args = _context.sent; | ||
if (Array.isArray(args)) { | ||
_context.next = 5; | ||
break; | ||
} | ||
throw new Error('makeAsyncSaga expected an array of args, instead got: ' + args); | ||
case 5: | ||
_context.prev = 5; | ||
_context.next = 8; | ||
return _effects.call.apply(undefined, [fn].concat(_toConsumableArray(args))); | ||
case 8: | ||
result = _context.sent; | ||
_context.next = 6; | ||
_context.next = 11; | ||
return (0, _effects.put)(asyncActionCreator.success(result)); | ||
case 6: | ||
_context.next = 12; | ||
case 11: | ||
_context.next = 17; | ||
break; | ||
case 8: | ||
_context.prev = 8; | ||
_context.t0 = _context['catch'](0); | ||
_context.next = 12; | ||
case 13: | ||
_context.prev = 13; | ||
_context.t0 = _context['catch'](5); | ||
_context.next = 17; | ||
return (0, _effects.put)(asyncActionCreator.failure(_context.t0)); | ||
case 12: | ||
case 17: | ||
case 'end': | ||
@@ -55,3 +73,3 @@ return _context.stop(); | ||
} | ||
}, _marked, this, [[0, 8]]); | ||
}, _marked, this, [[5, 13]]); | ||
} | ||
@@ -76,2 +94,45 @@ | ||
return waitFor; | ||
} | ||
function getArgs(action, options) { | ||
return regeneratorRuntime.wrap(function getArgs$(_context3) { | ||
while (1) { | ||
switch (_context3.prev = _context3.next) { | ||
case 0: | ||
if (!options.mapArgs) { | ||
_context3.next = 4; | ||
break; | ||
} | ||
_context3.next = 3; | ||
return options.mapArgs(action); | ||
case 3: | ||
return _context3.abrupt('return', _context3.sent); | ||
case 4: | ||
if (!options.args) { | ||
_context3.next = 6; | ||
break; | ||
} | ||
return _context3.abrupt('return', options.args); | ||
case 6: | ||
if (!action.payload) { | ||
_context3.next = 8; | ||
break; | ||
} | ||
return _context3.abrupt('return', [action.payload]); | ||
case 8: | ||
return _context3.abrupt('return', []); | ||
case 9: | ||
case 'end': | ||
return _context3.stop(); | ||
} | ||
} | ||
}, _marked3, this); | ||
} |
{ | ||
"name": "redux-toolbelt-saga", | ||
"version": "1.0.10", | ||
"version": "2.0.0", | ||
"description": "Saga helpers for redux-toolbelt", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -50,4 +50,2 @@ # redux-toolbelt-saga | ||
Other arguments are passed to the function when it is run. | ||
```js | ||
@@ -57,5 +55,31 @@ const fetchTodos = makeAsyncActionCreator('FETCH_TODOS') | ||
// Returns promise | ||
const fetchTodosFromServer = () => {/*...*/} | ||
const fetchTodosFromServer = ({id, url}, debug = false) => {/*...*/} | ||
const saga = makeAsyncSaga(fetchTodos, fetchTodosFromServer) | ||
//... | ||
dispatch(fetchTodos({id: 100, url: 'http://google.com'})) | ||
``` | ||
By default, the payload of the action is what passed to the function as it's argument. | ||
You have two ways of changing it, using `options`: | ||
```js | ||
const options = { | ||
// pass specific arguments | ||
args: [{id, url}], | ||
// OR | ||
// map the action to arguments using a regular or a generator function | ||
mapArgs: function* mapArgs(action){ | ||
const {todosId} = action.payload | ||
const url = yield select(urlSelector) | ||
return [{id: todosId, url}, true] | ||
} | ||
} | ||
const saga = makeAsyncSaga(fetchTodos, fetchTodosFromServer, options) | ||
``` |
@@ -6,6 +6,14 @@ import { call, put, takeLatest } from 'redux-saga/effects' | ||
* @param {function} fn | ||
* @param {...*} [args] | ||
* @param options? = {mapArgs?, args?}) | ||
* | ||
* @returns {Function} | ||
*/ | ||
export default function makeAsyncSaga(asyncActionCreator, fn, ...args){ | ||
function* exec(){ | ||
export default function makeAsyncSaga(asyncActionCreator, fn, options = {}){ | ||
function* exec(action){ | ||
const args = yield getArgs(action, options) | ||
if(!Array.isArray(args)){ | ||
throw new Error(`makeAsyncSaga expected an array of args, instead got: ${args}`) | ||
} | ||
try { | ||
@@ -26,1 +34,18 @@ const result = yield call(fn, ...args) | ||
} | ||
function* getArgs(action, options){ | ||
if (options.mapArgs){ | ||
return yield options.mapArgs(action) | ||
} | ||
if (options.args){ | ||
return options.args | ||
} | ||
if (action.payload){ | ||
return [action.payload] | ||
} | ||
return [] | ||
} |
import 'babel-polyfill' | ||
import {makeAsyncActionCreator} from '../../redux-toolbelt/src' | ||
import {makeAsyncSaga} from '../src' | ||
import { makeAsyncActionCreator } from '../../redux-toolbelt/src' | ||
import { makeAsyncSaga } from '../src' | ||
import { select } from 'redux-saga/effects' | ||
import createSagaMiddleware from 'redux-saga' | ||
import configureMockStore from 'redux-mock-store' | ||
function createStoreForTest(mySaga) { | ||
function createStoreForTest(mySaga, initialState = {}) { | ||
const sagaMiddleware = createSagaMiddleware() | ||
const mockStore = configureMockStore([sagaMiddleware]) | ||
const store = mockStore() | ||
const store = mockStore(initialState) | ||
sagaMiddleware.run(mySaga) | ||
@@ -17,47 +19,128 @@ return store | ||
function mockRequest({shouldReject = false} = {}){ | ||
return Promise.resolve().then(() => { | ||
if(shouldReject){ | ||
throw 'some error' | ||
function mockRequest(...args){ | ||
return new Promise((resolve, reject) => { | ||
if(args[0] === 'fail'){ | ||
reject('failed!') | ||
} | ||
return { 'dummy': 'object' } | ||
else{ | ||
resolve(args) | ||
} | ||
}) | ||
} | ||
test('saga dispatches success actions for a successful request', done => { | ||
describe('saga dispatches success actions for a successful request', () => { | ||
test('with no args', done => { | ||
const requestActionCreator = makeAsyncActionCreator('REQUEST') | ||
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest) | ||
const requestActionCreator = makeAsyncActionCreator('REQUEST') | ||
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest) | ||
const store = createStoreForTest(mySaga) | ||
store.dispatch(requestActionCreator()) | ||
const store = createStoreForTest(mySaga) | ||
store.dispatch(requestActionCreator()) | ||
setImmediate(() => { | ||
const actualActions = store.getActions() | ||
expect(actualActions).toEqual([ | ||
requestActionCreator(), | ||
requestActionCreator.success([]), | ||
]) | ||
done() | ||
}) | ||
}) | ||
setTimeout(() => { | ||
expect(store.getActions()).toEqual([ | ||
requestActionCreator(), | ||
requestActionCreator.success({ 'dummy': 'object' }), | ||
]) | ||
test('with args', done => { | ||
const requestActionCreator = makeAsyncActionCreator('REQUEST') | ||
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest) | ||
done() | ||
const store = createStoreForTest(mySaga) | ||
store.dispatch(requestActionCreator('some-arg')) | ||
setImmediate(() => { | ||
const actualActions = store.getActions() | ||
expect(actualActions).toEqual([ | ||
requestActionCreator('some-arg'), | ||
requestActionCreator.success(['some-arg']), | ||
]) | ||
done() | ||
}) | ||
}) | ||
test('with pre-set args', done => { | ||
const requestActionCreator = makeAsyncActionCreator('REQUEST') | ||
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest, { | ||
args: ['preset-arg'], | ||
}) | ||
const store = createStoreForTest(mySaga) | ||
store.dispatch(requestActionCreator('some-arg')) | ||
setImmediate(() => { | ||
const actualActions = store.getActions() | ||
expect(actualActions).toEqual([ | ||
requestActionCreator('some-arg'), | ||
requestActionCreator.success(['preset-arg']), | ||
]) | ||
done() | ||
}) | ||
}) | ||
test('with simple args mapping', done => { | ||
const requestActionCreator = makeAsyncActionCreator('REQUEST') | ||
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest, { | ||
mapArgs: () => ['mapped-arg'], | ||
}) | ||
const store = createStoreForTest(mySaga) | ||
store.dispatch(requestActionCreator('some-arg')) | ||
setImmediate(() => { | ||
const actualActions = store.getActions() | ||
expect(actualActions).toEqual([ | ||
requestActionCreator('some-arg'), | ||
requestActionCreator.success(['mapped-arg']), | ||
]) | ||
done() | ||
}) | ||
}) | ||
test('with complex args mapping', done => { | ||
const initialState = { | ||
arg0: 'arg0', | ||
} | ||
const requestActionCreator = makeAsyncActionCreator('REQUEST') | ||
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest, { | ||
mapArgs: function* (action){ | ||
const state = yield select() | ||
return [state.arg0, action.payload.arg1] | ||
}, | ||
}) | ||
const store = createStoreForTest(mySaga, initialState) | ||
store.dispatch(requestActionCreator({arg1: 'arg1'})) | ||
setImmediate(() => { | ||
const actualActions = store.getActions() | ||
expect(actualActions).toEqual([ | ||
requestActionCreator({arg1: 'arg1'}), | ||
requestActionCreator.success(['arg0', 'arg1']), | ||
]) | ||
done() | ||
}) | ||
}) | ||
}) | ||
test('saga dispatches failure actions for a successful request', done => { | ||
test('saga dispatches failure actions for a failed request', done => { | ||
const requestActionCreator = makeAsyncActionCreator('REQUEST') | ||
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest, {shouldReject: true}) | ||
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest) | ||
const store = createStoreForTest(mySaga) | ||
store.dispatch(requestActionCreator()) | ||
store.dispatch(requestActionCreator('fail')) | ||
setTimeout(() => { | ||
expect(store.getActions()).toEqual([ | ||
requestActionCreator(), | ||
requestActionCreator.failure('some error'), | ||
setImmediate(() => { | ||
const actualActions = store.getActions() | ||
expect(actualActions).toEqual([ | ||
requestActionCreator('fail'), | ||
requestActionCreator.failure('failed!'), | ||
]) | ||
done() | ||
}) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
12979
9
275
84
1