# API Examples ## Reducer ### `Reducer(reducer).withState(state).expect(action).toReturnState(result)` ```js import { Reducer } from 'redux-testkit'; import uut from '../reducer'; describe('counter reducer', () => { it('should handle INCREMENT action on initial state', () => { const action = { type: 'INCREMENT' }; const result = { counter: 1 }; Reducer(uut).expect(action).toReturnState(result); }); it('should handle INCREMENT action on existing state', () => { const action = { type: 'INCREMENT' }; const state = { counter: 1 }; const result = { counter: 2 }; Reducer(uut).withState(state).expect(action).toReturnState(result); }); it('should handle COMPLEX action on complex state', () => { const initialState = uut(); const action = { type: 'COMPLEX' }; const state = { ...initialState, value: 'before' }; const result = { ...initialState, value: 'after' }; Reducer(uut).withState(state).expect(action).toReturnState(result); }); }); ```
### `Reducer(reducer).withState(state).expect(action).toChangeInState(changes)` ```js import { Reducer } from 'redux-testkit'; import uut from '../reducer'; describe('person reducer', () => { it('should handle UPDATE_NAME action and only check that name changed', () => { const action = { type: 'UPDATE_NAME', newName: 'John' }; const state = { person: { name: 'Bill', age: 35, height: 1.85 } }; const changes = { person: { name: 'John' } }; Reducer(uut).withState(state).expect(action).toChangeInState(changes); }); }); ```
### `Reducer(reducer).withState(state).execute(action)` ```js import { Reducer } from 'redux-testkit'; import uut from '../reducer'; describe('movies reducer', () => { it('should handle ADD_MOVIE action on existing state with custom expectations', () => { const action = { type: 'ADD_MOVIE', name: 'Frozen' }; const state = { movies: [] }; const result = Reducer(uut).withState(state).execute(action); expect(result.movies.length).toEqual(1); expect(result.movies).toContain('Frozen'); }); }); ```
## Selector ### `Selector(selector).expect(state, ...args).toReturn(result)` ```js import { Selector } from 'redux-testkit'; import * as uut from '../reducer'; describe('numbers selectors', () => { it('should select integers from numbers state', () => { const state = { numbers: [1, 2.2, 3.14, 4, 5.75, 6] }; const result = [1, 4, 6]; Selector(uut.getIntegers).expect(state).toReturn(result); }); }); ```
### `Selector(selector).execute(state, ...args)` ```js import { Selector } from 'redux-testkit'; import * as uut from '../reducer'; describe('numbers selectors', () => { it('should select integers from numbers state', () => { const state = { numbers: [1, 2.2, 3.14, 4, 5.75, 6] }; const result = Selector(uut.getIntegers).execute(state); expect(result.length).toEqual(3); expect(result).toContain(4); }); }); ```
## Thunk ### `Thunk(thunk).withState(state).execute(...args)` ```js import { Thunk } from 'redux-testkit'; import * as uut from '../actions'; import redditService from '../../../services/reddit'; jest.mock('../../../services/reddit'); describe('posts actions', () => { beforeEach(() => { jest.resetAllMocks(); }); it('should clear all posts', () => { const dispatches = Thunk(uut.clearPosts).execute(); expect(dispatches.length).toBe(1); expect(dispatches[0].getType()).toEqual('POSTS_UPDATED'); expect(dispatches[0].getAction()).toEqual({ type: 'POSTS_UPDATED', posts: [] }); }); it('should fetch posts from server', async () => { redditService.getPostsBySubreddit.mockReturnValueOnce(['post1', 'post2']); const dispatches = await Thunk(uut.fetchPosts).execute(); expect(dispatches.length).toBe(3); expect(dispatches[0].getAction()).toEqual({ type: 'POSTS_LOADING', loading: true }); expect(dispatches[1].getAction()).toEqual({ type: 'POSTS_UPDATED', posts: ['post1', 'post2'] }); expect(dispatches[2].getAction()).toEqual({ type: 'POSTS_LOADING', loading: false }); }); it('should filter posts', () => { const state = { loading: false, posts: ['funny1', 'scary2', 'funny3'] }; const dispatches = Thunk(uut.filterPosts).withState(state).execute('funny'); expect(dispatches.length).toBe(1); expect(dispatches[0].getAction()).toEqual({ type: 'POSTS_UPDATED', posts: ['funny1', 'funny3'] }); }); it('should test a thunk that dispatches another thunk', async () => { const dispatches = await Thunk(uut.login).execute(); expect(dispatches.length).toBe(1); expect(dispatches[0].isFunction()).toBe(true); expect(dispatches[0].getName()).toEqual('refreshSession'); }); }); ```