npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

redux-thunk-testing

v3.2.0

Published

Test utility and Snapshot testing for complex and nested redux-thunks

Downloads

14

Readme

redux-thunk-testing

Test utility and Snapshot testing for complex and nested redux-thunks

npm Build Status Coverage Status TypeScript Support


About

redux-thunk-testing is a small utility/wrapper which aims to help in testing complex thunk actions and their side effects easily. The library runs through the action, executing all the thunks that are found, and subsequently provides utilities around the results for testing.

Conceptually, this allows you to set all your conditions, before running the action similarly to how it would execute in the context of your application.

Motivation

redux-thunk is a simple middleware for async and side-effects logic, and is nearly as ubiquitous as redux itself.

However, as more complex flows and async actions are added, it becomes harder and more unwieldy to test. Some projects like redux-saga were created to help handle such issues, but there might be situations where using such projects might not be a viable option due to constraints and requirements of the project.

Features

  • Supports Snapshot Testing
  • Test / Assertion framework agnostic.
    • ActionTester - for usage with any assertion library. (eg: Chai.js)
    • JestActionTester - for usage with jest.fn().
  • Supports thunk.withExtraArgument
    • For more info about extraArguments, check out: here and here
  • Supports actions that return thunks.
  • Supports flux standard actions with a thunk as the payload. see notes
  • TypeScript support (definition file)

Installation

Install the library via:

npm install redux-thunk-testing --save-dev

Documentation

Quick overview of functions / classes:

  • class ActionTester
  • class JestActionTester
  • function actionArraySnapshot
  • function actionSnapshot
  • function actionTesterSnapshot
  • function actionTracer
  • function actionTypes
  • function createActionRunner

The classes encapsulates the functions within this library.

Please refer to Project Documentation for the full list of available methods.

Examples

About the redux-thunk-readme-example

These are sample tests written for the "make a sandwich" code example from redux-thunk README.md. A copy of the example has been copied over. Please see examples/redux-thunk-readme/action.js.

Small change:

Unlike the original example, fetchSecretSauce() is assumed to be injected as an extraArgument to a thunk. This is the only change.

Snippet:

test('have enough money to make sandwiches for all', async () => {
  // Setup testing conditions
  // -------------------------------

  // It is recommended to use thunk.withExtraArguments to inject
  // your dependencies like apis as you can avoid module mocking by doing so.
  const getState = jest.fn();
  const extraArgs = {
    api: {
      fetchSecretSauce: jest.fn()
    }
  };

  // Mocking the return values of api etc.
  extraArgs.api.fetchSecretSauce.mockImplementation(() =>
    Promise.resolve('sauce')
  );

  getState.mockImplementation(() => ({
    sandwiches: {
      isShopOpen: true
    },
    myMoney: 100
  }));

  // Create the runner
  // -------------------------------

  // Setup tester + other thunk paramters
  const tester = new JestActionTester(jest.fn());
  // OR if you're not using jest.
  const tester = new ActionTester();

  // set the extra thunk arguments
  tester.setArgs(getState, extraArgs);

  // Run the action
  // -------------------------------

  await tester.dispatch(makeSandwichesForEverybody());

  // Expectations
  // -------------------------------

  // Using Jest Snapshot
  expect(tester.calls).toMatchSnapshot();

  // Generating our own inline snapshot with
  // expected function calls
  const expected = actionArraySnapshot([
    makeSandwichesForEverybody(),
    makeASandwichWithSecretSauce('My Grandma'),
    makeASandwich('My Grandma', 'sauce'),
    makeASandwichWithSecretSauce('Me'),
    makeASandwichWithSecretSauce('My wife'),
    makeASandwich('Me', 'sauce'),
    makeASandwich('My wife', 'sauce'),
    makeASandwichWithSecretSauce('Our kids'),
    makeASandwich('Our kids', 'sauce'),
    withdrawMoney(42)
  ]);

  // Snapshot Testing (without depending on Jest)
  expect(tester.toSnapshot()).toEqual(expected);

  // Alternatively, just check the types
  expect(tester.toTypes()).toEqual([
    'THUNK_ACTION',
    'THUNK_ACTION',
    'MAKE_SANDWICH',
    'THUNK_ACTION',
    'THUNK_ACTION',
    'MAKE_SANDWICH',
    'MAKE_SANDWICH',
    'THUNK_ACTION',
    'MAKE_SANDWICH',
    'WITHDRAW'
  ]);
});

Notes

Tests are async

The runner treats all thunks as async methods / returning promises, even if you are returning a basic type (eg: boolean, string).

As such, when using the tester, you should always use await or provide a done callback.

eg:

// using async-await
await tester.dispatch(action());

// using Promises
Promise.resolve(tester.dispatch(action())) // dispatch always returns a promise
  .then(() => {
    // ...expectations here

    done();
  });

// using a callback
tester.dispatch(action(), () => {
  // ...expectations here

  done();
});

THUNK_ACTION type

This action.type is logged when the action being dispatched is a direct function / thunk and not a functional payload of a "Flux Standard Action"

// Given
const action = () => (dispatch, getState, extraArgs) => {
  // code ...
};

// when testing
tester.dispatch(action());

// will resolve to (within the test suite)
tester.dispatch({
  type: 'THUNK_ACTION',
  payload: action()
});

Flux Standard Action with Thunk payload

Note: This is optional

If you don't want to see "THUNK_ACTION" in your tests, you might want to consider dispatching FSA with a thunk payload.

i.e.

// Instead of
function action() {
  return dispatch => {
    // code
  };
}

// Try
function action() {
  return {
    type: 'NAMED_ACTION',
    payload: dispatch => {
      // code
    }
  };
}

However, in order to do the above, you will need the following middleware.

const fsaThunk = () => next => action => {
  if (typeof action.payload === 'function') {
    // Convert to a thunk action
    return next(action.payload);
  }
  return next(action);
};

// Add it to your redux store.
import thunk from 'redux-thunk';

const store = createStore(
  rootReducer,
  applyMiddleware(
    fsaThunk, // needs to be applied before the thunk
    thunk
  )
);

License

redux-thunk-testing is MIT licensed