Gathering detailed insights and metrics for @relmify/jest-fp-ts
Gathering detailed insights and metrics for @relmify/jest-fp-ts
Gathering detailed insights and metrics for @relmify/jest-fp-ts
Gathering detailed insights and metrics for @relmify/jest-fp-ts
npm install @relmify/jest-fp-ts
Typescript
Module System
Node Version
NPM Version
TypeScript (99.77%)
JavaScript (0.23%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
67 Stars
54 Commits
4 Forks
1 Watchers
1 Branches
2 Contributors
Updated on Mar 16, 2025
Latest Version
2.1.1
Package Id
@relmify/jest-fp-ts@2.1.1
Unpacked Size
160.93 kB
Size
24.94 kB
File Count
116
NPM Version
9.5.1
Node Version
18.16.0
Published on
Jun 15, 2023
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
19
Jest matchers for projects using fp-ts
and io-ts
.
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:
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.
@relmify/jest-fp-ts
adds additional matchers to Jest's default ones, making it easier to
test code that makes use of fp-ts
functional containers.
With npm:
1npm install -D @relmify/jest-fp-ts
With yarn:
1yarn 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:
1npm install -D io-ts
With yarn:
1yarn add -D io-ts
To make all @relmify/jest-fp-ts
matchers globally available in your test files, add
@relmify/jest-fp-ts
to your Jest setupFilesAfterEnv
configuration.
See jest documentation for additional help.
In your package.json
file add:
1"jest": { 2 "setupFilesAfterEnv": ["@relmify/jest-fp-ts"] 3}
1// jest.config.js 2module.exports = { 3 setupFilesAfterEnv: ['@relmify/jest-fp-ts'], 4};
1// vite.config.ts 2export default defineConfig({ 3 test: { 4 // ... 5 setupFiles: ['@relmify/jest-fp-ts'], 6 // ... 7 }, 8});
If your editor does not recognize the custom @relmify/jest-fp-ts
matchers, add a global.d.ts
file to your project with:
1import '@relmify/jest-fp-ts';
If you've added a global.d.ts
file and your editor still has problems recognizing these matchers,
you may need to specifically include the global.d.ts
file in your Typescript configuration using
the "include"
or "files"
property. For example, in tsconfig.json
:
1{ 2 "compilerOptions": { 3 "module": "commonjs", 4 "strict": true, 5 ... 6 }, 7 "include": ["**/*", "global.d.ts"], 8 "exclude": ["node_modules", "**/__tests__/*"] 9}
Alternatively, you can resolve this issue by adding import '@relmify/jest-fp-ts';
to each test
file that makes use of @relmify/jest-fp-ts
matchers.
Use .toBeEither()
to check if a value is consistent with an Either
. In other words, this matcher
confirms that the value is a Left
or a Right
.
Note that a Left
or a Right
value is also consistent with a These
and would also pass a
.toBeThese()
test.
The matchers below can be used for Left
and Right
values from an Either
or a These
.
Use .toBeLeft()
to check if a value is a Left
.
Use .toBeLeftErrorMatching(string | RegExp)
to check if a value is a Left
whose value is an
instance of Error
with a message
property that contains the supplied string or matches the
supplied RegExp
.
Use .toBeRight()
to check if a value is a Right
.
Use .toEqualLeft(value)
to check if a value is a Left
whose value equals an expected value. See
Jest's toEqual(value) documentation for information
about how the .toEqual()
comparison works.
Use .toEqualRight(value)
to check if a value is a Right
whose value equals an expected value. See
Jest's toEqual(value) documentation for information
about how the .toEqual()
comparison works.
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()
.
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()
.
Use .toSubsetEqualLeft(value)
to check if a value is a Left
whose value equals or subset matches
the expected value. A subset match passes when the received value is a Left
whose value is an object
with a subset of properties that match the expected object. The received value must contain all of
the expected properties, and may contain more than the expected properties.
You can also pass an array of values to match against a received Left
value that is an array of
values. In this case, each value in the expected array is compared against the corresponding value
in the array contained in the received Left
. Both arrays must be the same length or the match will
fail.
Note that an empty expected object will match against any received Left
whose value is an object.
Use .toSubsetEqualRight(value)
to check if a value is a Right
whose value equals or subset matches
the expected value. A subset match passes when the received value is a Right
whose value is an
object with a subset of properties that match the expected object. The received value must contain
all of the expected properties, and may contain more than the expected properties.
You can also pass an array of values to match against a received Right
value that is an array of
values. In this case, each value in the expected array is compared against the corresponding value
in the array contained in the received Right
. Both arrays must be the same length or the match will
fail.
Note that an empty expected object will match against any received Right
whose value is an object.
Use .toBeBoth()
to check if a value is a Both
.
Use .toBeThese()
to check if a value is consistent with a These
. In other words, this matcher
confirms that the value is a Left
, a Right
, or a Both
.
Note that a Left
or a Right
value is also consistent with an Either
and would also pass a
.toBeEither()
test.
Use .toEqualBoth(leftValue, rightValue)
to check if a value is a Both
that contains a left value
that equals an expected value, and a right value that equals an expected value. See Jest's
toEqual(value) documentationfor information about
how the .toEqual()
comparison works.
Use .toStrictEqualBoth(leftValue, rightValue)
to check if a value is a Both
that contains a left
value that strictly equals an expected value, and a right value that strictly equals an expected
value. See Jest's toStrictEqual(value)
documentation for information about how .toStrictEqual()
differs from toEqual()
.
Use .toSubsetEqualBoth(leftValue, rightValue)
to check if a value is a Both
whose left and right
values equal or subset match the expected leftValue
and rightValue
. A subset match passes when a
received value is an object with a subset of properties that match the expected object. The received
value must contain all of the expected properties, and may contain more than the expected
properties.
You can also pass arrays of values to match against received values that contain arrays of values. In this case, each value in the expected array is compared against the corresponding value in the array contained in the received. Both arrays must be the same length or the match will fail.
Note that an empty expected object will match against any received object.
Use .toBeNone()
to check if a value is a None
.
Use .toBeOption()
to check if a value is an Option
(either a Some
or a None
).
Use .toBeSome()
to check if a value is a Some
.
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.
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()
.
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.
Use .toBeLeftWithErrorsMatching(Array<string | RegExp>)
when testing validation errors returned by
io-ts
decode()
operations.
Note that a ValidationError
is NOT a standard javascript Error
object. See
.toBeLeftErrorMatching(string | RegExp) for a matcher that
works with standard Error
objects.
An io-ts
decode()
method will return a Left with an array of ValidationError
objects if the
supplied value 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
Pathreporter.report()
strings.
If the supplied object is not a Left
that contains an array of ValidationError
objects, or if
any of the strings you supply cannot be matched to one of the ValidationError
objects, the matcher
will return false
. If all of the strings you supply are matched, it will return true
.
Example:
1const Name = t.type({ 2 first: t.string, 3 last: t.string, 4}); 5type Name = t.TypeOf<typeof Name>; 6const numberName = { first: 404, last: 401 }; 7test('if the received is a Left that contains errors matching the expected values', () => { 8 expect(Name.decode(numberName)).toBeLeftWithErrorsMatching([/404/, '401']); 9});
Note:
This matcher supports the current (stable) io-ts
interface. There is a new experimental io-ts
decoder interface that returns Either<DecodeError, A>
results instead. This matcher does not
support that interface.
All of the provided matchers are asymmetric matchers, which means that they can be called from any other matcher that accepts asymmetric matchers like so:
1test('works if called as an asymmetric matcher', () => {
2 expect(left('Any sufficiently advanced technology is equivalent to magic.')).toEqual(
3 expect.toEqualLeft('Any sufficiently advanced technology is equivalent to magic.'),
4 );
5});
The provided toEqual*(value)
, toStrictEqual*(value)
and toSubsetEqual*(value)
matchers also
accept asymmetric matchers which means you can pass in any of the standard Jest asymmetric matchers,
or any of the jest-extended matchers. This can be especially handy when you don't want to check
against a literal value.
1test('works if called with an asymmetric matcher', () => { 2 expect(both(['error 1', 'error 2'], { first: 'Albert', last: 'Einstein' })).toEqualBoth( 3 expect.anything(), 4 { first: expect.any(String), last: expect.any(String) }, 5 ); 6});
The .toBeLeftWithErrorsMatching(Array<string | RegExp>)
matcher does not accept asymmetric
matchers. You can use standard jest matchers to achieve similar results like so:
1import * as t from 'io-ts'; 2import { PathReporter } from 'io-ts/lib/PathReporter'; 3import { toBeLeftWithErrorsMatching } from '@relmify/jest-fp-ts'; 4 5expect.extend({ toBeLeftWithErrorsMatching }); 6 7const Name = t.type({ 8 first: t.string, 9 last: t.string, 10}); 11type Name = t.TypeOf<typeof Name>; 12 13const receivedName = { first: 1, last: undefined }; 14const validation = Name.decode(receivedName); 15const errorStrings = PathReporter.report(validation); 16 17// Snapshots below use `@relmify/jest-serializer-strip-ansi` and `jest-snapshot-serializer-raw` to produce 18// more readable snapshot output. 19describe('Alternative ways to test validation errors', () => { 20 test('Standard asymmetric matchers can be used to test for strings within pathReporter output', () => { 21 expect(errorStrings).toEqual( 22 expect.arrayContaining([expect.stringMatching('1'), expect.stringMatching(/undefined/)]), 23 ); 24 }); 25 test('Standard snapshot tests can be used to test full pathReporter output', () => { 26 expect(errorStrings).toMatchInlineSnapshot(` 27 [ 28 Invalid value 1 supplied to : { first: string, last: string }/first: string, 29 Invalid value undefined supplied to : { first: string, last: string }/last: string, 30 ] 31 `); 32 }); 33 test('Standard snapshot tests can be used to test the raw array of validation errors (verbose!)', () => { 34 expect(validation).toMatchInlineSnapshot(` 35 { 36 _tag: Left, 37 left: [ 38 { 39 context: [ 40 { 41 actual: { 42 first: 1, 43 last: undefined, 44 }, 45 key: , 46 type: InterfaceType { 47 _tag: InterfaceType, 48 decode: [Function], 49 encode: [Function], 50 is: [Function], 51 name: { first: string, last: string }, 52 props: { 53 first: StringType { 54 _tag: StringType, 55 decode: [Function], 56 encode: [Function], 57 is: [Function], 58 name: string, 59 validate: [Function], 60 }, 61 last: StringType { 62 _tag: StringType, 63 decode: [Function], 64 encode: [Function], 65 is: [Function], 66 name: string, 67 validate: [Function], 68 }, 69 }, 70 validate: [Function], 71 }, 72 }, 73 { 74 actual: 1, 75 key: first, 76 type: StringType { 77 _tag: StringType, 78 decode: [Function], 79 encode: [Function], 80 is: [Function], 81 name: string, 82 validate: [Function], 83 }, 84 }, 85 ], 86 message: undefined, 87 value: 1, 88 }, 89 { 90 context: [ 91 { 92 actual: { 93 first: 1, 94 last: undefined, 95 }, 96 key: , 97 type: InterfaceType { 98 _tag: InterfaceType, 99 decode: [Function], 100 encode: [Function], 101 is: [Function], 102 name: { first: string, last: string }, 103 props: { 104 first: StringType { 105 _tag: StringType, 106 decode: [Function], 107 encode: [Function], 108 is: [Function], 109 name: string, 110 validate: [Function], 111 }, 112 last: StringType { 113 _tag: StringType, 114 decode: [Function], 115 encode: [Function], 116 is: [Function], 117 name: string, 118 validate: [Function], 119 }, 120 }, 121 validate: [Function], 122 }, 123 }, 124 { 125 actual: undefined, 126 key: last, 127 type: StringType { 128 _tag: StringType, 129 decode: [Function], 130 encode: [Function], 131 is: [Function], 132 name: string, 133 validate: [Function], 134 }, 135 }, 136 ], 137 message: undefined, 138 value: undefined, 139 }, 140 ], 141 } 142 `); 143 }); 144});
If you've come here to help contribute - Thanks! Take a look at CONTRIBUTING to see how to get started.
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
Reason
dependency not pinned by hash detected -- score normalized to 3
Details
Reason
8 existing vulnerabilities detected
Details
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
Found 1/29 approved changesets -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More