-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Mohammad Hasani
committed
Jan 18, 2019
1 parent
279e517
commit b170555
Showing
5 changed files
with
81 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { createReducer } from '../create-reducer' | ||
import { createAction } from '../create-action' | ||
|
||
describe('createReducer', () => { | ||
const increment = createAction('[Counter] increment') | ||
const decrement = createAction('[Counter] decrement') | ||
const reset = createAction('[Counter] reset', resolve => (value: number) => | ||
resolve(value) | ||
) | ||
|
||
const handleIncrement = jest.fn((state: number) => state + 1) | ||
const handleDecrement = jest.fn((state: number) => state - 1) | ||
const handleReset = jest.fn( | ||
(_: number, { payload }: ReturnType<typeof reset>) => payload | ||
) | ||
|
||
const defaultState = 0 | ||
const counter = createReducer(defaultState, handle => [ | ||
handle(increment, handleIncrement), | ||
handle(decrement, handleDecrement), | ||
handle(reset, handleReset), | ||
]) | ||
|
||
beforeEach(() => { | ||
handleIncrement.mockReset() | ||
handleDecrement.mockReset() | ||
handleReset.mockReset() | ||
}) | ||
|
||
it('should initiate with default state when state is undefined', () => { | ||
expect(counter(undefined, increment())).toBe( | ||
counter(defaultState, increment()) | ||
) | ||
}) | ||
|
||
it('should pass through state when there is no proper handler', () => { | ||
expect(counter(defaultState, { type: 'NOT DEFINED' })).toBe(defaultState) | ||
}) | ||
|
||
it('should calls related handler of the given action', () => { | ||
expect(counter(defaultState, increment)).toBe(handleIncrement(defaultState)) | ||
expect(handleIncrement).toBeCalledTimes(2) | ||
expect(handleDecrement).not.toBeCalled() | ||
expect(handleReset).not.toBeCalled() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { | ||
createHandlerMap, | ||
CreateHandlerMap, | ||
HandlerMap, | ||
} from './create-handler-map' | ||
import { merge } from './utils' | ||
|
||
/** | ||
* Reducer factory | ||
* @description combines multiple handler map into single reducer | ||
* @example | ||
* const counter = createReducer(0, handle => [ | ||
* handle(increment, state => state + 1), | ||
* handle(decrement, state => state - 1), | ||
* ]) | ||
*/ | ||
export function createReducer<State, HM extends HandlerMap<State, any>>( | ||
defaultState: State, | ||
handlerMapsCreator: (handle: CreateHandlerMap<State>) => HM[] | ||
) { | ||
const handlerMap = merge(...handlerMapsCreator(createHandlerMap)) | ||
|
||
return ( | ||
state = defaultState, | ||
action: HM extends HandlerMap<State, infer T> ? T : never | ||
) => { | ||
const handler = handlerMap[action.type] | ||
|
||
return handler ? handler(state, action) : state | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export { action, Action, AnyAction } from './action' | ||
export { createAction, ActionCreator } from './create-action' | ||
export { getType } from './get-type' | ||
export { createReducer } from './create-reducer' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './object' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export const merge = <T extends {}>(...objs: T[]): T => | ||
Object.assign({}, ...objs) |