src/__tests__/helpers/reducer.plugin.js
import { CHANGE } from '../../actionTypes'
import actions from '../../actions'
const { change } = actions
const describePlugin = (
vanillaReducer,
expect,
{ fromJS, deleteIn, getIn, setIn }
) => () => {
it('should initialize state when a plugin is given', () => {
const reducer = vanillaReducer.plugin({
foo: state => state
})
const state = reducer()
expect(state).toBeAMap()
expect(state).toBeSize(0)
})
it('should let plugin reducer respond to another action type', () => {
const state1 = fromJS({
foo: {
values: {
cat: 'dog',
rat: 'hog'
},
fields: {
cat: { touched: true },
rat: { touched: true }
}
}
})
const plugin = (state, action) => {
if (action.type === 'RAT_POISON') {
let result = state
result = deleteIn(result, 'values.rat')
result = deleteIn(result, 'fields.rat')
return result
}
return state
}
const reducer = vanillaReducer.plugin({ foo: plugin })
const state2 = reducer(state1, { type: 'MILK', meta: { form: 'foo' } })
expect(state2).toBe(state1) // no change
const state3 = reducer(state2, {
type: 'RAT_POISON'
})
expect(state3).toEqualMap({
foo: {
values: {
cat: 'dog'
},
fields: {
cat: { touched: true }
}
}
})
})
it('should only respond to form specified when receiveAllFormActions is not set', () => {
const state1 = fromJS({
foo: {
values: {
cat: 'dog',
rat: 'hog'
},
fields: {
cat: { touched: true },
rat: { touched: true }
}
},
bar: {
values: {
cat: 'dog',
rat: 'hog'
},
fields: {
cat: { touched: true },
rat: { touched: true }
}
}
})
const plugin = (state, action) => {
if (action.type === 'RAT_POISON') {
let result = state
result = deleteIn(result, 'values.rat')
result = deleteIn(result, 'fields.rat')
return result
}
return state
}
const reducer = vanillaReducer.plugin({ foo: plugin, bar: plugin })
const state2 = reducer(state1, { type: 'MILK', meta: { form: 'foo' } })
expect(state2).toBe(state1) // no change
const state3 = reducer(state2, {
type: 'RAT_POISON',
meta: { form: 'foo' }
})
expect(state3).toEqualMap({
foo: {
values: {
cat: 'dog'
},
fields: {
cat: { touched: true }
}
},
bar: {
values: {
cat: 'dog',
rat: 'hog'
},
fields: {
cat: { touched: true },
rat: { touched: true }
}
}
})
})
it('should respond to actions from all forms when receiveAllFormActions is true', () => {
const state1 = fromJS({
foo: {
values: {
cat: 'dog',
rat: 'hog'
},
fields: {
cat: { touched: true },
rat: { touched: true }
}
},
bar: {
values: {
cat: 'dog',
rat: 'hog'
},
fields: {
cat: { touched: true },
rat: { touched: true }
}
}
})
const plugin = (state, action) => {
if (action.type === 'RAT_POISON') {
let result = state
result = deleteIn(result, 'values.rat')
result = deleteIn(result, 'fields.rat')
return result
}
return state
}
const reducer = vanillaReducer.plugin(
{ foo: plugin, bar: plugin },
{ receiveAllFormActions: true }
)
const state2 = reducer(state1, { type: 'MILK', meta: { form: 'foo' } })
expect(state2).toBe(state1) // no change
const state3 = reducer(state2, {
type: 'RAT_POISON',
meta: { form: 'foo' }
})
expect(state3).toEqualMap({
foo: {
values: {
cat: 'dog'
},
fields: {
cat: { touched: true }
}
},
bar: {
values: {
cat: 'dog'
},
fields: {
cat: { touched: true }
}
}
})
})
it('should be provided the state from before the vanillaReducer', () => {
const state1 = fromJS({
foo: {
values: {
cat: 'beta',
lastCat: 'alpha'
},
fields: {
cat: { touched: false },
lastCat: { touched: false }
}
}
})
// this plugin will change the value we are after so we can confirm we get the real starting state
const intermediatePlugin = state => setIn(state, 'values.cat', 'zed')
const plugin = (state, action, startingState) => {
if (action.type === CHANGE && action.meta.field === 'cat') {
let result = state
result = setIn(
result,
'values.lastCat',
getIn(startingState, 'values.cat')
)
result = setIn(result, 'fields.lastCat.touched', action.meta.touch)
return result
}
return state
}
const reducer = vanillaReducer
.plugin({ foo: intermediatePlugin })
.plugin({ foo: plugin })
const state2 = reducer(state1, change('foo', 'cat', 'charlie', true, false))
expect(state2).toEqualMap({
foo: {
anyTouched: true,
values: {
cat: 'zed',
lastCat: 'beta'
},
fields: {
cat: { touched: true },
lastCat: { touched: true }
}
}
})
})
}
export default describePlugin