expect.shift([newSubject])
Inside an assertion that takes another assertion as the last parameter via
the <assertion>
type, you can use expect.shift
to invoke that assertion,
optionally replacing the subject with an alternative one.
expect.addAssertion('<string> when parsed as an integer <assertion>',function (expect, subject) {expect(subject, 'to match', /^[1-9][0-9]*$/);return expect.shift(parseInt(subject, 10));});expect('42', 'when parsed as an integer', 'to be greater than', 10);
If you omit the newSubject
parameter to expect.shift
, the current subject
will be preserved. This is mainly useful for assertions that have side effects,
for example mocking out parts of the environment.
It is important that the return value of expect.shift
is returned (or yielded
as the fulfillment value of a promise) from your assertion. That way everything
will work out when delegating to an asynchronous assertion, ie. one that returns
a promise. The promise will then be propagated correctly.
Promise-based flows
If your assertion does not take an <assertion>
as a parameter, or if it
optionally takes one via <assertion?>
and is invoked without,
expect.shift
will propagate its argument as the fulfillment value of the
promise returned from your assertion:
expect.addAssertion('<string> [when] parsed as an integer <assertion?>',function (expect, subject) {expect(subject, 'to match', /^[1-9][0-9]*$/);return expect.shift(parseInt(subject, 10));});return expect('42', 'parsed as an integer').then(function (integer) {return expect(integer, 'to be within', 30, 50);});
Multiple invocations
You can call expect.shift()
multiple times in your assertion if you want
to delegate to the other assertion several times, optionally with different
subjects. Remember that each invocation could result in a promise -- make
sure to gather up the return values and use expect.promise.all
or a similar
construct to resolve them all, for example:
expect.addAssertion('<number> up to [and including] <number> <assertion?>',function (expect, subject, value) {expect.errorMode = 'nested';const numbers = [];for (let i = subject;i < (expect.flags['and including'] ? value + 1 : value);i += 1) {numbers.push(i);}return expect.promise.all(numbers.map(function (number) {return expect.promise(function () {return expect.shift(number);});}));});expect(5, 'up to and including', 100, 'to be greater than', 4);
Again, this has the nice property that the shifted values will be provided as the fulfillment value of the promise if invoked without an assertion:
return expect(10, 'up to', 20).then(function (numbers) {expect(numbers, 'to have length', 10);});