sententiaregum-flux-container
Version:
The flux implementation of the sententiaregum project based on facebook/flux
175 lines (145 loc) • 6.61 kB
JavaScript
/*
* This file is part of the Sententiaregum project.
*
* (c) Maximilian Bosch <maximilian.bosch.27@gmail.com>
* (c) Ben Bieler <benjaminbieler2014@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _invariant = require('invariant');
var _invariant2 = _interopRequireDefault(_invariant);
var _deepEqual = require('deep-equal');
var _deepEqual2 = _interopRequireDefault(_deepEqual);
var _runAction = require('../runAction');
var _runAction2 = _interopRequireDefault(_runAction);
var _Dispatcher = require('../dispatcher/Dispatcher');
var _Dispatcher2 = _interopRequireDefault(_Dispatcher);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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); } }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Builds an error message for failed assertions.
*
* @param {String} kind Which kind of data mismatched.
* @param {*} expected Expected dataset.
* @param {*} actual Actual dataset.
*
* @returns {String} The error message.
*/
function getErrorMessage(kind, expected, actual) {
return 'Can\'t match the expected ' + kind + ' (' + JSON.stringify(expected) + ') with actual ' + kind + ' (' + JSON.stringify(actual) + ')!';
}
/**
* API for testing utility.
*
* @author Maximilian Bosch <maximilian.bosch.27@gmail.com>
*/
exports.default = new (function () {
function _class() {
_classCallCheck(this, _class);
}
_createClass(_class, [{
key: 'clear',
/**
* Clear.
*
* As the dispatcher is an internal API which is stateful, it needs to be ensured that everything will be
* cleared properly before running tests.
*
* @returns {void}
*/
value: function clear() {
_Dispatcher2.default.reset();
}
/**
* Executes an action and returns a function to match the payload.
* This is helpful when unittesting the way how action creators should work.
*
* Example:
*
* describe('TestUtils', () => {
* it('single test', () => {
* TestUtils.executeAction(actionCreator, event, args)(expected);
* });
* });
*
* @param {Function} actionCreator The creator which should be tested.
* @param {String} event The event of the action creator to be tested.
* @param {Array.<*>} args The arguments used in that event.
*
* @returns {Function} The function used assert the result.
*/
}, {
key: 'executeAction',
value: function executeAction(actionCreator, event, args) {
this.clear();
return function (expected) {
var _actionCreator;
var events = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1];
var dispatched = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
var list = {};
events.forEach(function (event) {
return _Dispatcher2.default.addListener(event, function (payload) {
return Object.assign(list, _defineProperty({}, event, payload));
});
});
(_actionCreator = actionCreator())[event].apply(_actionCreator, [function (payload) {
return (0, _invariant2.default)((0, _deepEqual2.default)(payload, expected), getErrorMessage('payload', expected, payload));
}].concat(_toConsumableArray(args)));
if (Object.keys(list).length > 0) {
Object.keys(dispatched).forEach(function (event) {
(0, _invariant2.default)(typeof list[event] !== 'undefined', 'Missing event "' + event + '"!');
(0, _invariant2.default)((0, _deepEqual2.default)(dispatched[event], list[event]), getErrorMessage('payload', dispatched[event], list[event]));
});
}
};
}
/**
* Uses the runAction API to check whether actions and stores interact correctly.
* This sort of integrative tests is helpful when ensuring that the interaction between the components
* behaves as expected.
*
* Example:
*
* describe('TestUtils', () => {
* it('single test', () => {
* TestUtils.executeAction(actionCreator, event, args)(expected, storeToValidate);
* // or
* TestUtils.executeAction(actionCreator, event, args)([expected1, expected2], [store1, store2]);
* });
* });
*
* @param actionCreator
* @param event
* @param args
* @returns {function(*=, *)}
*/
}, {
key: 'executeFullWorkflow',
value: function executeFullWorkflow(actionCreator, event) {
var args = arguments.length <= 2 || arguments[2] === undefined ? [] : arguments[2];
(0, _runAction2.default)(event, actionCreator, args);
return function (expected, stores) {
var compareWithState = function compareWithState(state, expected) {
(0, _invariant2.default)((0, _deepEqual2.default)(expected, state), getErrorMessage('state', expected, state));
};
if (!Array.isArray(stores)) {
compareWithState(stores.getState(), expected);
return;
}
(0, _invariant2.default)(Array.isArray(expected), 'A list of expected values is needed when asserting against multiple stores!');
stores.forEach(function (store, i) {
return compareWithState(store.getState(), expected[i]);
});
};
}
}]);
return _class;
}())();