expect.addAssertion(...)
Signature:
New assertions can be added to Unexpected the following way.
The above assertion definition makes the following expects possible:
Let's dissect the different parts of the custom assertion we just introduced.
The first parameter to addAssertion
is a string or an array of strings
stating the patterns this assertion should match. A pattern has the following
syntax. A word in angle brackets represents a type of either the subject
or one of the parameters to the assertion. In this case the assertion
is only defined for arrays. If no subject type is specified,
the assertion will be defined for the type any
, and would
be applicable any type. See the Extending Unexpected with new types
section for more information about the type system in Unexpected.
A word in square brackets represents a flag that can either be
there or not. If the flag is present expect.flags[flag]
will contain
the value true
. In this case not
is a flag. When a flag it present
in a nested expect
it will be inserted if the flag is present;
otherwise it will be removed. Text that is in parentheses with
vertical bars between them are treated as alternative texts that can
be used. In this case you can write ordered as an alternative to
sorted.
The second and last parameter to addAssertion
is function that will
be called when expect
is invoked with an expectation matching the
type and pattern of the assertion.
So in this case, when expect
is called the following way:
The handler to our assertion will be called with the values the following way, where the not flag in the nested expect will be removed:
Overriding the standard error message
When you create a new assertion Unexpected will generate an error message from the assertion text and the input arguments. In some cases it can be preferable to tweak the output instead of creating completely custom output using expect.fail.
You can override how the subject
is displayed by providing a
subjectOutput
for the specific assertion. You can also override the output of
the arguments by overriding parts of argsOutput
or provide a
completely custom output for the arguments by setting argsOutput
to
an output function on the assertion.
Here is a few examples:
Controlling the output of nested expects
When a call to expect
fails inside your assertion the standard error
message for the custom assertion will be used. In the case of our
sorted assertion fails, the output will be:
We can control the output of the nested expects by changing the
expect.errorMode
property.
The bubble error mode will hoist the next level error message to this level.
If we change the error mode to bubble, we get the following output:
In the nested error mode the next level error message is included and indented underneath the standard error message.
If we change the error mode to nested, we get the following output:
The defaultOrNested error mode uses the default mode if the error chain contains a diff; otherwise it the nested error mode will be used.
If we change the error mode to defaultOrNested, we get the following output:
In the diff error mode will hoist the first found diff as the error message. If no diff is present, it will fall back to the default error mode.
If we change the error mode to diff, we get the following output:
Asynchronous assertions
Unexpected comes with built-in support for asynchronous assertions. You basically just return a promise from the assertion.
For the purpose of explaining how we can make an asynchronous assertion we will define a silly type which contains a value that can only be retrieved after a delay:
It would be pretty nice if we could use
to satisfy on the value of a Timelock
,
even if the retrieval is delayed. Then we would be able to do stuff
like this:
First we need to define a type for handling the Timelock
:
Let's see how it works:
The best resource for learning more about custom assertions is to look at how the predefined assertions are built: