Giter Club home page Giter Club logo

jest-fp-ts's Introduction

Jest Matchers for the fp-ts ecosystem

Jest matchers for projects using fp-ts and io-ts.

Problem

If your TypeScript project is written in a functional programming style using fp-ts and io-ts, many of the values you'll want to check in your unit tests will come wrapped inside container types like Either, Option, or These. Jest has no awareness of these container types and no built-in matchers to help you to compare wrapped values against un-wrapped values. This leaves you with two options:

  1. Extract the received value from the container type before using a jest matcher.
  2. Lift the expected value into a container of the expected type before using a jest matcher.

Both options work, but tend to make your tests somewhat verbose, adding unnecessary work when writing your tests, and making it harder to read and maintain them.

Solution

@relmify/jest-fp-ts aims to add additional matchers to Jest's default ones, making it easier to test code that makes use of fp-ts functional containers.

Installation

With npm:

npm install -D @relmify/jest-fp-ts

With yarn:

yarn add -D @relmify/jest-fp-ts

You also need both fp-ts and io-ts installed in your project. If you're here, presumably you're already using fp-ts. Not every fp-ts project uses io-ts though. If you aren't using io-ts in your project, simply install it as a development dependency.

With npm:

npm install -D io-ts

With yarn:

yarn add -D io-ts

Setup

Add @relmify/jest-fp-ts to your Jest setupFilesAfterEnv configuration.

See jest documentation for additional help.

Setup with package.json

In your package.json file add:

"jest": {
  "setupFilesAfterEnv": ["@relmify/jest-fp-ts"]
}

Setup with jest.config.js

Instead of configuring jest using package.json, you can use a jest.config.js file to specify the setupFilesAfterEnv configuration. There you can specify a setup file such as ./jest.setup.js that will require @relmify/jest-fp-ts:

// jest.config.js
module.exports = {
  setupFilesAfterEnv: ['./jest.setup.js'],
};
// jest.setup.js
require('@relmify/jest-fp-ts');

If you are using other jest custom matcher packages too, you can require them in the same jest.setup.js file.

Typescript Editor Support

If your editor does not recognise the custom @relmify/jest-fp-ts matchers, add a global.d.ts file to your project with:

import '@relmify/jest-fp-ts';

Matchers

Either Matchers

.toBeEither()

Use .toBeEither() to check if a value is an Either (either a Left or a Right).

.toBeLeft()

Use .toBeLeft() to check if a value is a Left.

.toBeLeftWithErrorsMatching(value)

Use .toBeLeftWithErrorsMatching(value) when testing errors returned from io-ts codec decode() operations.

An io-ts type codec decode method will return a left with an array of ValidationError objects if the supplied value does can not be successfully validated and decoded to the specified io-ts type.

For codecs that are composed from multiple codecs, multiple errors may be returned as each sub-codec is applied to the values it is charged with validating.

This matcher provides an easy way to check if expected validation errors are present. To do this, it makes use of the io-ts PathReporter module.

To use this matcher, supply an array of strings that you expect to be present in the array of strings returned by PathReporter.report(). You can supply either regular expressions or substrings. The matcher will try to match each array entry against the array of ValidationErrors.

If the supplied object is not a Left that contains an array of ValidationErrors, or if any of the strings you supply cannot be matched to one of the ValidationErrors, the matcher will return false. If all of the strings you supply are matched, it will return true.

const Name = t.type({
  first: t.string,
  last: t.string,
});
type Name = t.TypeOf<typeof Name>;
const numberName = { first: 404, last: 401 };
test('if the received is a Left that contains errors matching the expected values', () => {
  expect(Name.decode(numberName)).toBeLeftWithErrorsMatching([/404/, '401']);
});

.toBeRight()

Use .toBeRight() to check if a value is a Right.

.toEqualLeft(value)

Use .toEqualLeft(value) to check if a value is a Left that contains a value that equals an expected value. See Jest's toEqual(value) documentationfor information about how the .toEqual() comparison works.

.toEqualRight(value)

Use .toEqualRight(value) to check if a value is a Right that contains a value that equals an expected value. See Jest's toEqual(value) documentationfor information about how the .toEqual() comparison works.

.toStrictEqualLeft(value)

Use .toStrictEqualLeft(value) to check if a value is a Left that contains a value that strictly equals an expected value. See Jest's toStrictEqual(value) documentation for information about how .toStrictEqual() differs from toEqual().

.toStrictEqualRight(value)

Use .toStrictEqualRight(value) to check if a value is a Right that contains a value that strictly equals an expected value. See Jest's toStrictEqual(value) documentation for information about how .toStrictEqual() differs from toEqual().

.toSubsetEqualLeft(value)

Use .toSubsetEqualLeft(value) to check if a value is a Left that contains an object with a subset of properties that match the expected object properties. The received value must contain all of the expected properties, and may contain more than the expected properties.

.toSubsetEqualRight(value)

Use .toSubsetEqualRight(value) to check if a value is a Right that contains an object with a subset of properties that match the expected object properties. The received value must contain all of the expected properties, and may contain more than the expected properties.

Option Matchers

.toBeNone()

Use .toBeNone() to check if a value is a None.

.toBeOption()

Use .toBeOption() to check if a value is a Option (either a Some or a None).

.toBeSome()

Use .toBeSome() to check if a value is a Some.

.toEqualSome(value)

Use .toEqualSome(value) to check if a value is a Some that contains a value that equals an expected value. See Jest's toEqual(value) documentationfor information about how the .toEqual() comparison works.

.toStrictEqualSome(value)

Use .toStrictEqualSome(value) to check if a value is a Some that contains a value that strictly equals an expected value. See Jest's toStrictEqual(value) documentation for information about how .toStrictEqual() differs from toEqual().

.toSubsetEqualSome(value)

Use .toSubsetEqualSome(value) to check if a value is a Some that contains an object with a subset of properties that match the expected object properties. The received value must contain all of the expected properties, and may contain more than the expected properties.

Asymmetric Matchers

All of the provided matchers are asymmetric matchers, which means that they can be called from within a standard jest .toEqual(value) like so:

test('passes if called as an asymmetric matcher', () => {
  expect(left('People who are truly strong lift others up.')).toEqual(
    expect.toEqualLeft('People who are truly strong lift others up.'),
  );
});

The provided toEqual*(value) matchers also accept asymmetric matchers - just like Jest's toEqual(value) does - which means you can pass in any of the standard Jest asymmetric matchers, or any of the jest-extended matchers.

test('if called with an asymmetric matcher', () => {
  expect(left('People who are truly powerful bring others together.')).toEqualLeft(
    expect.stringContaining('powerful'),
  );
});

LICENSE

MIT

Contributing

If you've come here to help contribute - Thanks! Take a look at contributing to see how to get started.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.