API Examples

March 31, 2017 ยท View on GitHub

Reducer

Reducer(reducer).withState(state).expect(action).toReturnState(result)

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)

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)

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)

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)

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)

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');
  });

});