redux-waitfor-middleware
Version:
Lightweight Redux middleware to assert on actions being dispatched
168 lines (147 loc) • 5.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = createWaitForMiddleware;
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
function createWaitForMiddleware(verbose) {
var _this = this;
if (verbose) {
console.log('WaitForMiddleware - created'); // eslint-disable-line no-console
}
/**
* Array of actions recorded by the middleware since the last clean() :
*/
var records = [];
/**
* List of Promises resolvers that are called each time an action is dispatched :
*/
var waitedQueue = [];
/**
* Keep track of emitted promises so we can give them an id and find them in the waited list :
* @type {number}
*/
var emittedPromises = 0;
/**
* Remove a specific resolver from the waited queue :
* @param id int
*/
var removeResolver = function removeResolver(id) {
waitedQueue.splice(waitedQueue.findIndex(function (resolver) {
return resolver.id = id;
}), 1);
};
/**
* Match an array of actions against the list of recorded actions
* If any of the required actions is not found, will return null
*/
var findRecorded = function findRecorded(actions) {
// Find records in the history matching the waited actions :
var matches = [];
actions.forEach(function (actionType) {
var c = records.find(function (record) {
return record.type && record.type === actionType;
});
if (c) matches.push(c);
});
// Checking every waited action was matched :
if (actions.every(function (type) {
return matches.find(function (match) {
return match.type === type;
});
})) {
return matches;
}
return null;
};
/**
* Redux middleware function :
*/
var middleware = function middleware() {
return function (next) {
return function (action) {
if (verbose) {
console.log('WaitForMiddleware - Received action : ' + action.type); // eslint-disable-line no-console
}
records.push(action);
waitedQueue.forEach(function (waited) {
waited.resolver();
});
return next(action);
};
};
};
/**
* Clear the recorded actions array AND the waited actions queue :
*/
middleware.clean = function () {
records = [];
waitedQueue = [];
};
/**
* Clear the recorded actions array AND the waited actions queue :
*/
middleware.getRecordedActions = function () {
return _this.records;
};
/**
* Method exposed to allow waiting for a set of actions to be received.
* Its returned Promise :
* - resolves with the actions received (including payloads) if the required actions are found within timeout
* - rejects otherwise (timeout elapsed && actions not found)
* @param actions Array<string> Types of the waited actions
* @param timeout int Timeout before failing in ms
* @returns {Promise}
*/
middleware.waitFor = function () {
var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(actions) {
var timeout = arguments.length <= 1 || arguments[1] === undefined ? 2000 : arguments[1];
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
emittedPromises++;
return _context.abrupt('return', new Promise(function (resolve, reject) {
// Match recorded actions with those we are waiting for :
var matches = findRecorded(actions);
// Resolving if the actions have all happened already :
if (matches) {
// XXX .length ?
resolve(actions);
} else {
(function () {
// Setting timeout for rejection :
setTimeout(function () {
reject(new Error('Redux Recorder : One of the following actions was not dispatched before specified timeout was elapsed\n[' + actions.toString() + ']'));
}, timeout);
// Keeping track of the resolver's id to be able to remove it when it succeeds
var id = emittedPromises;
var resolver = function resolver() {
var resolverMatches = findRecorded(actions);
if (resolverMatches) {
// XXX .length ?
removeResolver(id);
resolve(resolverMatches); // Resolving with the received actions
}
};
// Pushing the resolver for this waiter in the queue read by the middleware :
waitedQueue.push({
resolver: resolver,
id: id
});
})();
}
}));
case 2:
case 'end':
return _context.stop();
}
}
}, _callee, _this);
}));
return function (_x, _x2) {
return _ref.apply(this, arguments);
};
}();
return middleware;
}