You can use expect.extend()
to do just that. If you're using create-react-app, you can put this example code below in the setupTests.ts
so it can be applied to all of the tests you run:
expect.extend({
toBeWithinRange(received, min, max) {
const pass = received >= min && received <= ceiling
return {
message: () =>
`expected ${received} to be in range ${floor} - ${ceiling}`,
pass,
}
},
})
Usage
it('should fail', () => {
expect(13).toBeWithinRange(1, 10)
})
When running the test above this is the output:

But we can do better than that. Look at how the built-in matchers display the error message:

As you can see the error is easier to read because the expected and received values have different colors and there is a matcher hint above to denote which one is which.
To do that we need to install this package jest-matcher-utils
and import a couple of methods to pretty print the matcher hint and values:
import { printExpected, printReceived, matcherHint } from "jest-matcher-utils"
const failMessage = (received, min, max) => () => `${matcherHint(
".toBeWithinRange",
"received",
"min, max"
)}
Expected value to be in range:
min: ${printExpected(min)}
max: ${printExpected(max)}
Received: ${printReceived(received)}`
expect.extend({
toBeWithinRange(received, min, max) {
const pass = received >= min && received <= max
return {
pass,
message: failMessage(received, min, max),
}
},
})
Now it looks way better and can help you identify the problem quicker

However there is a small bug in the code above, when you negate the assertion
expect(3).not.toBeWithinRange(1, 10)
The output is .toBeWithinRange
instead of .not.toBeWithinRange
:
expect(received).toBeWithinRange(min, max)
Expected value to be in range:
min: 1
max: 10
Received: 3
To fix that, you can conditionally add the negative word based on the pass
value
const failMessage = (received, min, max, not) => () => `${matcherHint(
`${not ? ".not" : ""}.toBeWithinRange`,
"received",
"min, max"
)}
Expected value${not ? " not " : " "}to be in range:
min: ${printExpected(min)}
max: ${printExpected(max)}
Received: ${printReceived(received)}`
toBeWithinRange(received, min, max) {
const pass = received >= min && received <= max
return {
pass,
message: failMessage(received, min, max, pass),
}
},
Now rerun the test again, you will see this:
Pass if false
expect(3).not.toBeWithinRange(1, 10)
expect(received).not.toBeWithinRange(min, max)
Expected value not to be in range:
min: 1
max: 10
Received: 3
Pass if true
expect(13).toBeWithinRange(1, 10)
expect(received).toBeWithinRange(min, max)
Expected value to be in range:
min: 1
max: 10
Received: 13