🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

autodux

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

autodux - npm Package Compare versions

Comparing version

to
5.0.0

.eslintignore

43

.eslintrc.json
{
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"parserOptions": {
"sourceType": "module",
"ecmaVersion": "2017"
},
"rules": {
"indent": [
"error",
2
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true
},
"extends": ["eslint:recommended", "plugin:prettier/recommended"],
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2017
},
"rules": {
"linebreak-style": ["error", "unix"]
}
}

@@ -1,2 +0,2 @@

/*! autodux v4.0.3 by Eric Elliott */
/*! autodux v5.0.0 by Eric Elliott */
import 'core-js/modules/es6.array.reduce-right';

@@ -9,2 +9,3 @@ import 'core-js/modules/es6.regexp.split';

import 'core-js/modules/es6.array.reduce';
import 'core-js/modules/es6.array.some';

@@ -15,2 +16,5 @@ var get = require('lodash/fp/get');

var _require = require("./errors"),
SLICE_VALUE_ERROR = _require.SLICE_VALUE_ERROR;
var id = function id(x) {

@@ -30,2 +34,32 @@ return x;

var isString = function isString(s) {
return typeof s == 'string';
};
var isNumber = function isNumber(n) {
return typeof n == 'number';
};
var isBoolean = function isBoolean(b) {
return typeof b == 'boolean';
};
var isUndefined = function isUndefined(v) {
return typeof v == 'undefined';
};
var isNull = function isNull(v) {
return v === null;
};
var isPrimitive = function isPrimitive(v) {
return [isString, isNumber, isBoolean, isUndefined, isNull].some(function (f) {
return f(v);
});
};
var isEmptyString = function isEmptyString(s) {
return s === '';
};
var selectFunction = selectIf(isFunction);

@@ -83,3 +117,3 @@

return Object.assign({}, state, key ? (_ref = {}, _ref[key] = payload, _ref) : payload);
return !key && isPrimitive(payload) ? payload : Object.assign({}, state, key ? (_ref = {}, _ref[key] = payload, _ref) : payload);
}

@@ -123,13 +157,28 @@ };

var autodux = function autodux(_temp) {
var _ref2 = _temp === void 0 ? {} : _temp,
_ref2$initial = _ref2.initial,
initial = _ref2$initial === void 0 ? '' : _ref2$initial,
_ref2$actions = _ref2.actions,
actions = _ref2$actions === void 0 ? {} : _ref2$actions,
_ref2$selectors = _ref2.selectors,
selectors = _ref2$selectors === void 0 ? {} : _ref2$selectors,
_ref2$slice = _ref2.slice,
slice = _ref2$slice === void 0 ? '' : _ref2$slice;
var isSliceValid = function isSliceValid(slice) {
return isString(slice) && !isEmptyString(slice);
};
var checkOptions = function checkOptions(_ref2) {
var slice = _ref2.slice;
if (!isSliceValid(slice)) {
throw new Error(SLICE_VALUE_ERROR);
}
};
var autodux = function autodux(options) {
if (options === void 0) {
options = {};
}
checkOptions(options);
var _options = options,
_options$initial = _options.initial,
initial = _options$initial === void 0 ? '' : _options$initial,
_options$actions = _options.actions,
actions = _options$actions === void 0 ? {} : _options$actions,
_options$selectors = _options.selectors,
selectors = _options$selectors === void 0 ? {} : _options$selectors,
slice = _options.slice;
var allSelectors = Object.assign({}, createInitSelectors(slice, initial), createSliceSelectors(slice, selectors));

@@ -139,3 +188,3 @@ var allActions = createMappedActions(slice, addDefaultActions(slice, initial, actions));

initial: initial,
reducer: function reducer(state, _temp2) {
reducer: function reducer(state, _temp) {
if (state === void 0) {

@@ -145,3 +194,3 @@ state = initial;

var _ref3 = _temp2 === void 0 ? {} : _temp2,
var _ref3 = _temp === void 0 ? {} : _temp,
type = _ref3.type,

@@ -148,0 +197,0 @@ payload = _ref3.payload;

@@ -1,2 +0,2 @@

/*! autodux v4.0.3 by Eric Elliott */
/*! autodux v5.0.0 by Eric Elliott */
'use strict';

@@ -11,2 +11,3 @@

require('core-js/modules/es6.array.reduce');
require('core-js/modules/es6.array.some');

@@ -17,2 +18,5 @@ var get = require('lodash/fp/get');

var _require = require("./errors"),
SLICE_VALUE_ERROR = _require.SLICE_VALUE_ERROR;
var id = function id(x) {

@@ -32,2 +36,32 @@ return x;

var isString = function isString(s) {
return typeof s == 'string';
};
var isNumber = function isNumber(n) {
return typeof n == 'number';
};
var isBoolean = function isBoolean(b) {
return typeof b == 'boolean';
};
var isUndefined = function isUndefined(v) {
return typeof v == 'undefined';
};
var isNull = function isNull(v) {
return v === null;
};
var isPrimitive = function isPrimitive(v) {
return [isString, isNumber, isBoolean, isUndefined, isNull].some(function (f) {
return f(v);
});
};
var isEmptyString = function isEmptyString(s) {
return s === '';
};
var selectFunction = selectIf(isFunction);

@@ -85,3 +119,3 @@

return Object.assign({}, state, key ? (_ref = {}, _ref[key] = payload, _ref) : payload);
return !key && isPrimitive(payload) ? payload : Object.assign({}, state, key ? (_ref = {}, _ref[key] = payload, _ref) : payload);
}

@@ -125,13 +159,28 @@ };

var autodux = function autodux(_temp) {
var _ref2 = _temp === void 0 ? {} : _temp,
_ref2$initial = _ref2.initial,
initial = _ref2$initial === void 0 ? '' : _ref2$initial,
_ref2$actions = _ref2.actions,
actions = _ref2$actions === void 0 ? {} : _ref2$actions,
_ref2$selectors = _ref2.selectors,
selectors = _ref2$selectors === void 0 ? {} : _ref2$selectors,
_ref2$slice = _ref2.slice,
slice = _ref2$slice === void 0 ? '' : _ref2$slice;
var isSliceValid = function isSliceValid(slice) {
return isString(slice) && !isEmptyString(slice);
};
var checkOptions = function checkOptions(_ref2) {
var slice = _ref2.slice;
if (!isSliceValid(slice)) {
throw new Error(SLICE_VALUE_ERROR);
}
};
var autodux = function autodux(options) {
if (options === void 0) {
options = {};
}
checkOptions(options);
var _options = options,
_options$initial = _options.initial,
initial = _options$initial === void 0 ? '' : _options$initial,
_options$actions = _options.actions,
actions = _options$actions === void 0 ? {} : _options$actions,
_options$selectors = _options.selectors,
selectors = _options$selectors === void 0 ? {} : _options$selectors,
slice = _options.slice;
var allSelectors = Object.assign({}, createInitSelectors(slice, initial), createSliceSelectors(slice, selectors));

@@ -141,3 +190,3 @@ var allActions = createMappedActions(slice, addDefaultActions(slice, initial, actions));

initial: initial,
reducer: function reducer(state, _temp2) {
reducer: function reducer(state, _temp) {
if (state === void 0) {

@@ -147,3 +196,3 @@ state = initial;

var _ref3 = _temp2 === void 0 ? {} : _temp2,
var _ref3 = _temp === void 0 ? {} : _temp,
type = _ref3.type,

@@ -150,0 +199,0 @@ payload = _ref3.payload;

{
"name": "autodux",
"version": "4.0.3",
"version": "5.0.0",
"description": "Automate the Redux boilerplate.",

@@ -9,7 +9,12 @@ "browser": "dist/index.js",

"scripts": {
"lint": "eslint src && echo 'lint finished.'",
"test": "node src/test.js | tap-colorize && npm run -s lint",
"debug": "echo 'open debugger: chrome://inspect' && node --inspect-brk src/test.js",
"watch": "watch 'clear && npm run -s test' src",
"prepare": "npm run test -s && prepublish",
"lint": "eslint . && echo 'Lint finished.'",
"test": "riteway src/test.js | tap-nirvana",
"test-coverage": "nyc npm test",
"test-coverage-ci": "nyc --reporter=text-lcov npm test",
"show-coverage-ci": "nyc report --reporter=text-lcov | coveralls",
"show-coverage-text": "nyc report --reporter=text || echo \"Run 'npm run test-coverage' first.\"",
"show-coverage-html": "open ./coverage/index.html || echo \"Run 'npm run test-coverage' first.\"",
"debug": "echo 'Open debugger in Chrome: \"chrome://inspect\".' && node --inspect-brk src/test.js",
"watch": "watch 'clear && npm -s test' src",
"prepare": "npm run -s lint && npm -s test && prepublish",
"update": "updtr"

@@ -33,7 +38,13 @@ },

"devDependencies": {
"eslint": "5.6.1",
"coveralls": "3.0.2",
"eslint": "5.13.0",
"eslint-config-prettier": "4.0.0",
"eslint-plugin-prettier": "3.0.1",
"husky": "1.3.1",
"lint-staged": "8.1.4",
"nyc": "13.3.0",
"prepublish": "2.2.0",
"riteway": "3.0.0",
"tap-colorize": "1.2.0",
"tape": "4.9.1",
"prettier": "1.16.4",
"riteway": "4.0.1",
"tap-nirvana": "1.1.0",
"updtr": "3.1.0",

@@ -40,0 +51,0 @@ "watch": "1.0.2"

const get = require('lodash/fp/get');
const capitalize = require('lodash/upperFirst');
const { SLICE_VALUE_ERROR } = require('./errors');
const id = x => x;
const selectIf = predicate => x => predicate(x) && x;
const isFunction = f => (typeof f === 'function');
const isFunction = f => typeof f === 'function';
const isString = s => typeof s === 'string';
const isNumber = n => typeof n === 'number';
const isBoolean = b => typeof b === 'boolean';
const isUndefined = v => typeof v === 'undefined';
const isNull = v => v === null;
const isPrimitive = v =>
[isString, isNumber, isBoolean, isUndefined, isNull].some(f => f(v));
const isEmptyString = s => s === '';
const selectFunction = selectIf(isFunction);
// # Selector creation:
const toGetter = s => `get${ capitalize(s) }`;
const toGetter = s => `get${capitalize(s)}`;
const sliceSelector = (slice, fn) => state => fn(state[slice], state);
const createInitSelectors = (slice, initial) => Object.keys(initial).reduce(
(obj, selector) => slice ?
Object.assign(obj, {[toGetter(selector)]: sliceSelector(slice, state => get(selector, state)) }) :
Object.assign(obj, {[toGetter(selector)]: state => get(selector, state) }),
{}
);
const createInitSelectors = (slice, initial) =>
Object.keys(initial).reduce(
(obj, selector) =>
slice
? Object.assign(obj, {
[toGetter(selector)]: sliceSelector(slice, state =>
get(selector, state)
)
})
: Object.assign(obj, {
[toGetter(selector)]: state => get(selector, state)
}),
{}
);
const createSliceSelectors = (slice, selectors) => (
Object.assign(Object.keys(selectors).reduce(
(obj, selector) => slice ?
Object.assign(obj, {[selector]: sliceSelector(slice, selectors[selector]) }) :
Object.assign(obj, {[selector]: selectors[selector] }),
{}
), {
[toGetter(slice)]: sliceSelector(slice, id)
})
);
const createSliceSelectors = (slice, selectors) =>
Object.assign(
Object.keys(selectors).reduce(
(obj, selector) =>
slice
? Object.assign(obj, {
[selector]: sliceSelector(slice, selectors[selector])
})
: Object.assign(obj, { [selector]: selectors[selector] }),
{}
),
{
[toGetter(slice)]: sliceSelector(slice, id)
}
);
// /selector creation
// # Action creation
const getActionName = key => `set${ capitalize(key) }`;
const getActionName = key => `set${capitalize(key)}`;
const createAction = (
slice, action, key,
type = `${ slice }/${ action }`
) => ({
const createAction = (slice, action, key, type = `${slice}/${action}`) => ({
create: Object.assign(payload => payload, { type }),
reducer: (state, payload) => Object.assign({},
state,
(key)
? { [key]: payload }
: payload
)
reducer: (state, payload) =>
!key && isPrimitive(payload)
? payload
: Object.assign({}, state, key ? { [key]: payload } : payload)
});
const getInitialActions = (slice, initial) => (
const getInitialActions = (slice, initial) =>
Object.keys(initial).reduce((o, key) => {

@@ -55,4 +73,3 @@ const action = getActionName(key);

});
}, {})
);
}, {});

@@ -63,3 +80,4 @@ const addDefaultActions = (slice, initial, actions) => {

return Object.assign({},
return Object.assign(
{},
{

@@ -73,25 +91,36 @@ [action]: createAction(slice, action)

const createMappedActions = (slice, actions) => Object.keys(actions).reduce(
(obj, action) => Object.assign({}, obj, {
[action]: Object.assign(
(...args) => ({
type: `${ slice }/${ action }`,
payload: typeof actions[action].create === 'function' ?
actions[action].create(...args) :
args[0]
const createMappedActions = (slice, actions) =>
Object.keys(actions).reduce(
(obj, action) =>
Object.assign({}, obj, {
[action]: Object.assign(
(...args) => ({
type: `${slice}/${action}`,
payload:
typeof actions[action].create === 'function'
? actions[action].create(...args)
: args[0]
}),
{ type: `${slice}/${action}` }
)
}),
{ type: `${ slice }/${ action }` }
)
}),
{}
);
{}
);
// /action creation
const autodux = ({
initial = '',
actions = {},
selectors = {},
slice = ''
} = {}) => {
const allSelectors = Object.assign({},
const isSliceValid = slice => isString(slice) && !isEmptyString(slice);
const checkOptions = ({ slice }) => {
if (!isSliceValid(slice)) {
throw new Error(SLICE_VALUE_ERROR);
}
};
const autodux = (options = {}) => {
checkOptions(options);
const { initial = '', actions = {}, selectors = {}, slice } = options;
const allSelectors = Object.assign(
{},
createInitSelectors(slice, initial),

@@ -101,10 +130,11 @@ createSliceSelectors(slice, selectors)

const allActions = createMappedActions(slice,
const allActions = createMappedActions(
slice,
addDefaultActions(slice, initial, actions)
);
const reducer = (state = initial, {type, payload} = {}) => {
const [ namespace, subType ] = type ?
type.split('/') :
'unknown/unknown'.split('/');
const reducer = (state = initial, { type, payload } = {}) => {
const [namespace, subType] = type
? type.split('/')
: 'unknown/unknown'.split('/');

@@ -119,20 +149,20 @@ const defaultActions = addDefaultActions(slice, initial, {});

const actionReducer = [
get(`${ subType }.reducer`, actions),
get(`${subType}.reducer`, actions),
actions[subType],
get(`${ subType }.reducer`, defaultActions)
get(`${subType}.reducer`, defaultActions)
].reduceRight((f, v) => selectFunction(v) || f);
return (namespace === slice
&& (actions[subType] || defaultActions[subType])
) ?
(actionReducer) ?
actionReducer(state, payload) :
Object.assign({}, state, payload) :
state
;
return namespace === slice && (actions[subType] || defaultActions[subType])
? actionReducer
? actionReducer(state, payload)
: Object.assign({}, state, payload)
: state;
};
return {
initial, reducer, slice,
selectors: allSelectors, actions: allActions,
initial,
reducer,
slice,
selectors: allSelectors,
actions: allActions
};

@@ -148,3 +178,2 @@ };

[key]: payload
})
;
});

@@ -1,64 +0,96 @@

const { describe } = require('riteway');
const { describe, Try } = require('riteway');
const { SLICE_VALUE_ERROR } = require('./errors');
const autodux = require('./');
const id = autodux.id;
const assign = autodux.assign;
const createDux = () => autodux({
slice: 'counter',
initial: 0,
actions: {
increment: {
reducer: state => state + 1
const { id, assign } = autodux;
const createCounterDux = (initial = 0) =>
autodux({
// The slice of state your reducer controls.
slice: 'counter',
// The initial value for the slice of state.
initial,
// No need to implement switching logic, it's done for you.
actions: {
// Shorthand definition of action and corresponding reducer.
increment: state => state + 1,
decrement: state => state - 1,
// Another way to define action and reducer.
multiply: {
// Define custom mapping of action creator parameter to action payload.
create: ({ by }) => by,
reducer: (state, payload) => state * payload
},
// Define action and reducer without custom mapping of action creator parameter to action payload.
divide: {
reducer: (state, payload) => Math.floor(state / payload)
}
},
decrement: {
reducer: state => state - 1
},
multiply: {
create: id,
reducer: (state, payload) => state * payload
selectors: {
// No need to select the state slice, it's done for you.
getValue: id,
// Get access to the root state in case you need it.
getState: (_, rootState) => rootState
}
},
selectors: {
getValue: id,
getStore: (_, store) => store
}
});
});
describe('autodux().slice', async assert => {
describe('autodux({ … }).slice', async assert => {
assert({
given: 'autodux is called with args',
should: 'have the correct string value',
actual: createDux().slice,
expected: 'counter',
given: "'autodux' is called with 'slice'",
should: 'have the correct value',
actual: createCounterDux().slice,
expected: 'counter'
});
});
describe('autodux().actions', async assert => {
describe('autodux({ … }).initial', async assert => {
assert({
given: "'autodux' is called with 'slice' and 'initial'",
should: 'return valid initial state',
actual: createCounterDux().initial,
expected: 0
});
assert({
given: 'autodux is called with args',
given: "'autodux' is called without 'initial'",
should: 'return initial state as an empty string',
actual: autodux({ slice: 'user' }).initial,
expected: ''
});
});
describe('autodux({ … }).actions', async assert => {
assert({
given: "'autodux' is called with 'slice' and 'actions'",
should: 'contain action creators',
actual: Object.keys(createDux().actions),
expected: ['setCounter', 'increment', 'decrement', 'multiply']
actual: Object.keys(createCounterDux().actions),
expected: ['setCounter', 'increment', 'decrement', 'multiply', 'divide']
});
{
const { actions } = createDux();
const actual = [
actions.increment(),
actions.decrement(),
actions.multiply(2)
];
const expected = [
{ type: 'counter/increment', payload: undefined },
{ type: 'counter/decrement', payload: undefined },
{ type: 'counter/multiply', payload: 2 },
];
const { actions } = createCounterDux();
assert({
given: 'autodux is called with args',
should: 'produce correct action objects',
actual,
expected
given: "'autodux' is called with 'slice' and 'actions'",
should: 'contain action creators that return correct action objects',
actual: [
actions.increment(),
actions.decrement(),
actions.multiply({ by: 2 }),
actions.divide(1)
],
expected: [
{ type: 'counter/increment', payload: undefined },
{ type: 'counter/decrement', payload: undefined },
{ type: 'counter/multiply', payload: 2 },
{ type: 'counter/divide', payload: 1 }
]
});

@@ -69,57 +101,36 @@ }

const {
actions: {
setCounter,
increment,
decrement,
multiply
}
} = createDux();
actions: { setCounter, increment, decrement, multiply, divide }
} = createCounterDux();
const actual = [
setCounter.type,
increment.type,
decrement.type,
multiply.type
];
const expected = [
'counter/setCounter',
'counter/increment',
'counter/decrement',
'counter/multiply'
];
assert({
given: 'autodux is called with args',
should: 'produce namespaced action type constants',
actual,
expected
given: "'autodux' is called with 'slice' and 'actions'",
should: 'contain action creators with correct action type constants',
actual: [
setCounter.type,
increment.type,
decrement.type,
multiply.type,
divide.type
],
expected: [
'counter/setCounter',
'counter/increment',
'counter/decrement',
'counter/multiply',
'counter/divide'
]
});
}
});
describe('autodux().reducer', async assert => {
{
const {
actions: {
increment,
decrement
},
reducer,
initial
} = createDux();
const { actions } = autodux({
slice: 'words'
});
const actions = [
increment(),
increment(),
increment(),
decrement()
];
assert({
given: 'a reducer',
should: 'switch correctly',
actual: actions.reduce(reducer, initial),
expected: 2
given: "'autodux' is called with 'slice' and without 'actions'",
should:
"contain a single action creator ('set${slice}') for setting the state of the slice",
actual: Object.keys(actions).length,
expected: 1
});

@@ -129,62 +140,27 @@ }

{
const {
actions: {
increment,
multiply
},
reducer,
initial
} = createDux();
const { actions } = createCounterDux();
const actions = [
increment(),
increment(),
multiply(2)
];
const value = 50;
assert({
given: 'a reducer',
should: 'deliver action payloads',
actual: actions.reduce(reducer, initial),
expected: 4
given: "'autodux' is called with 'slice' and 'actions'",
should:
"contain action creator ('set${slice}') for setting the state of the slice",
actual: actions.setCounter(value),
expected: {
type: 'counter/setCounter',
payload: value
}
});
}
});
describe('autodux().selectors', async assert => {
const { getValue } = createDux().selectors;
{
assert({
given: 'a property and value',
should: 'return a selector that knows its state slice',
actual: getValue({ counter: 3 }),
expected: 3
});
}
const { actions, reducer, initial } = createCounterDux(128);
{
const initial = {
key1: 'value 1',
key2: 'value 2'
};
const store = {
slice: initial
};
const { selectors: { getKey1, getKey2 } } = autodux({
slice: 'slice',
initial
});
const actual = {
key1: getKey1(store),
key2: getKey2(store)
};
assert({
given: 'a property and value',
should: 'expose a selector for each key in the initial state',
actual,
expected: initial
given: "'autodux' is called with 'slice' and 'actions'",
should:
'return action creator that maps parameters to action payload by default',
actual: [actions.divide(2)].reduce(reducer, initial),
expected: 64
});

@@ -194,14 +170,4 @@ }

{
const initial = {
userName: 'Anonymous',
avatar: 'anonymous.png'
};
const store = {
user: initial
};
const {
selectors: {
getUser
}
actions: { setUserName, setAge }
} = autodux({

@@ -211,53 +177,63 @@ slice: 'user',

userName: 'Anonymous',
avatar: 'anon.png'
age: 0
}
});
const userName = 'Freddie';
const age = 23;
assert({
given: 'selectors',
should: 'expose a selector for the entire reducer state',
actual: getUser(store),
expected: initial
given: "'autodux' is called with 'slice' and without 'actions'",
should:
'contain correct action creators for each key in the initial state',
actual: [setUserName(userName), setAge(age)],
expected: [
{
type: 'user/setUserName',
payload: userName
},
{
type: 'user/setAge',
payload: age
}
]
});
}
});
describe('autodux({ … }).reducer', async assert => {
{
const { getStore } = createDux().selectors;
const {
actions: { increment, decrement },
reducer,
initial
} = createCounterDux();
assert({
given: 'a store',
should: 'pass entire store as a second parameter to selectors',
actual: getStore({ counter: 3, foo: 'bar' }),
expected: { counter: 3, foo: 'bar' }
given: "'autodux' is called with 'slice' and 'actions'",
should: 'return reducer that switches correctly',
actual: [increment(), increment(), increment(), decrement()].reduce(
reducer,
initial
),
expected: 2
});
}
});
describe('autodux() action creators', async assert => {
{
const {
actions: {
setUserName
}
} = autodux({
slice: 'user',
initial: {
userName: 'Anonymous',
}
});
const userName = 'Foo';
actions: { increment, multiply },
reducer,
initial
} = createCounterDux();
const actual = setUserName(userName);
const expected = {
type: 'user/setUserName',
payload: userName,
};
assert({
given: 'no action for supplied initial state',
should: 'return an action creator which returns an action with the correct type and payload',
actual,
expected,
given: "'autodux' is called with 'slice' and 'actions'",
should:
'return reducer that receives action payload as the second parameter',
actual: [increment(), increment(), multiply({ by: 2 })].reduce(
reducer,
initial
),
expected: 4
});

@@ -267,23 +243,14 @@ }

{
const initial = { name: 'Jim' };
const value = 'UserName';
const { actions } = autodux({
slice: 'emptyCreator',
actions: {
nothing: {
reducer: x => x
}
}
const { reducer } = autodux({
slice: 'user',
initial
});
const expected = {
type: 'emptyCreator/nothing',
payload: value
};
assert({
given: 'no action creators',
should: 'should default missing action creators to identity',
actual: actions.nothing(value),
expected
given: "'autodux' is called with 'slice' and without 'actions'",
should: 'return reducer that returns valid default state',
actual: reducer(),
expected: initial
});

@@ -293,39 +260,48 @@ }

{
const value = 'UserName';
const { actions } = autodux({
slice: 'emptyCreator',
actions: {
nothing: {
reducer: x => x
}
}
});
const {
actions: { setInfo },
reducer,
initial
} = autodux({ slice: 'info', initial: 'Some text goes here…' });
const expected = {
type: 'emptyCreator/nothing',
payload: value
};
assert({
given: 'no reducer',
should: 'default missing reducer to spread payload into state',
actual: actions.nothing(value),
expected
given: "'autodux' is called with 'slice' and without 'actions'",
should:
'return reducer that changes the state to the primitive value of action payload',
actual: [
[setInfo('Hi!')].reduce(reducer, initial),
[setInfo(9)].reduce(reducer, initial),
[setInfo(undefined)].reduce(reducer, initial),
[setInfo(true)].reduce(reducer, initial),
[setInfo(null)].reduce(reducer, initial)
],
expected: ['Hi!', 9, undefined, true, null]
});
}
});
describe('autodux({ … }).selectors', async assert => {
{
const initial = { a: 'a' };
const rootState = {
album: {
name: 'The Works',
year: 1984
}
};
const { reducer } = autodux({
initial,
actions: {
reducer: x => x
}
const {
selectors: { getName, getYear },
initial
} = autodux({
slice: 'album',
initial: rootState.album
});
assert({
given: 'no args',
should: 'return valid default state',
actual: reducer(),
given: "'autodux' is called with 'slice' and 'initial'",
should: 'expose a selector for each key in the initial state',
actual: {
name: getName(rootState),
year: getYear(rootState)
},
expected: initial

@@ -336,50 +312,46 @@ });

{
const rootState = {
user: {
userName: 'Anonymous',
avatar: 'anonymous.png'
}
};
const {
reducer,
actions: {
increment,
decrement,
multiply
},
selectors: {
getValue
}
selectors: { getUser },
initial
} = autodux({
// the slice of state your reducer controls
slice: 'counter',
slice: 'user',
initial: rootState.user
});
// The initial value of your reducer state
initial: 0,
assert({
given: "'autodux' is called with 'slice' and 'initial'",
should: 'expose a selector for the entire state of the slice',
actual: getUser(rootState),
expected: initial
});
}
// No need to implement switching logic -- it's
// done for you.
actions: {
increment: state => state + 1,
decrement: state => state - 1,
multiply: {
create: ({ by }) => by,
reducer: (state, payload) => state * payload
}
},
{
const { getValue } = createCounterDux().selectors;
// No need to select the state slice -- it's done for you.
selectors: {
getValue: id
}
assert({
given: "'autodux' is called with 'slice' and 'selectors'",
should: 'return a selector that knows its state slice',
actual: getValue({ counter: 3 }),
expected: 3
});
}
const state = [
increment(),
increment(),
increment(),
decrement(),
multiply({ by: 2 })
].reduce(reducer, undefined);
{
const { getState } = createCounterDux().selectors;
const rootState = { counter: 3, foo: 'bar' };
assert({
given: 'functions as action values',
should: 'use function as a reducer',
actual: getValue({ counter: state }),
expected: 4
given: "'autodux' is called with 'slice' and 'selectors'",
should: 'return a selector that can return the root state object',
actual: getState(rootState),
expected: rootState
});

@@ -389,9 +361,29 @@ }

describe('autodux/assign(key)', async assert => {
describe('autodux()', async assert => {
assert({
given: "'autodux' is called without an argument",
should: 'throw an error',
actual: Try(autodux).toString(),
expected: new Error(SLICE_VALUE_ERROR).toString()
});
});
describe("autodux({ …, slice: undefined | null | '' })", async assert => {
const error = new Error(SLICE_VALUE_ERROR).toString();
assert({
given: "'autodux' is called with improper 'slice' value",
should: 'throw an error',
actual: [
Try(autodux, { slice: undefined }).toString(),
Try(autodux, { slice: null }).toString(),
Try(autodux, { slice: '' }).toString()
],
expected: [error, error, error]
});
});
describe('assign(key)', async assert => {
const {
actions: {
setUserName,
setAvatar
},
actions: { setUserName, setAvatar },
reducer

@@ -409,90 +401,19 @@ } = autodux({

});
const userName = 'Foo';
const avatar = 'foo.png';
const actual = [
setUserName(userName),
setAvatar(avatar)
].reduce(reducer, undefined);
const expected = {
userName,
avatar
};
assert({
given: 'default actions (without action keys)',
should: 'set the key in the state to the payload value',
actual,
expected,
});
});
describe('autodux/default', async assert => {
{
const {
actions: {
setUser
},
reducer
} = autodux({
slice: 'user',
initial: {
userName: 'Anonymous',
avatar: 'anonymous.png'
}
});
const userName = 'Foo';
const avatar = 'foo.png';
const actual = reducer(undefined, setUser({ userName, avatar }));
const expected = {
given: 'a key',
should:
'return a reducer that sets the key in the state to the action payload value',
actual: [setUserName(userName), setAvatar(avatar)].reduce(
reducer,
undefined
),
expected: {
userName,
avatar
};
assert({
given: 'actions (without action keys)',
should: 'create `set${slice}` to spread payload into state',
actual,
expected,
});
}
{
const {
actions: {
setUserName,
setAvatar
},
reducer
} = autodux({
slice: 'user',
initial: {
userName: 'Anonymous',
avatar: 'anonymous.png'
}
});
const userName = 'Foo';
const avatar = 'foo.png';
const actual = [
setUserName(userName),
setAvatar(avatar)
].reduce(reducer, undefined);
const expected = {
userName,
avatar
};
assert({
given: 'actions (without action keys)',
should: 'create assignment actions for each key in initial',
actual,
expected,
});
}
}
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet