Added expectAsync(...).already
* Causes async matchers to immediately fail if the promise is pending * Fixes #1845
This commit is contained in:
@@ -46,6 +46,12 @@ getJasmineRequireObj().Expectation = function(j$) {
|
||||
* Asynchronous matchers that operate on an actual value which is a promise,
|
||||
* and return a promise.
|
||||
*
|
||||
* Most async matchers will wait indefinitely for the promise to be resolved
|
||||
* or rejected, resulting in a spec timeout if that never happens. If you
|
||||
* expect that the promise will already be resolved or rejected at the time
|
||||
* the matcher is called, you can use the {@link async-matchers#already}
|
||||
* modifier to get a faster failure with a more helpful message.
|
||||
*
|
||||
* Note: Specs must await the result of each async matcher, return the
|
||||
* promise returned by the matcher, or return a promise that's derived from
|
||||
* the one returned by the matcher. Otherwise the matcher will not be
|
||||
@@ -115,6 +121,23 @@ getJasmineRequireObj().Expectation = function(j$) {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Fail as soon as possible if the actual is pending.
|
||||
* Otherwise evaluate the matcher.
|
||||
* @member
|
||||
* @name async-matchers#already
|
||||
* @type {async-matchers}
|
||||
* @example
|
||||
* await expectAsync(myPromise).already.toBeResolved();
|
||||
* @example
|
||||
* return expectAsync(myPromise).already.toBeResolved();
|
||||
*/
|
||||
Object.defineProperty(AsyncExpectation.prototype, 'already', {
|
||||
get: function() {
|
||||
return addFilter(this, expectSettledPromiseFilter);
|
||||
}
|
||||
});
|
||||
|
||||
function wrapSyncCompare(name, matcherFactory) {
|
||||
return function() {
|
||||
var result = this.expector.compare(name, matcherFactory, arguments);
|
||||
@@ -193,6 +216,27 @@ getJasmineRequireObj().Expectation = function(j$) {
|
||||
buildFailureMessage: negatedFailureMessage
|
||||
};
|
||||
|
||||
var expectSettledPromiseFilter = {
|
||||
selectComparisonFunc: function(matcher) {
|
||||
return function(actual) {
|
||||
var matcherArgs = arguments;
|
||||
|
||||
return j$.isPending_(actual).then(function(isPending) {
|
||||
if (isPending) {
|
||||
return {
|
||||
pass: false,
|
||||
message:
|
||||
'Expected a promise to be settled (via ' +
|
||||
'expectAsync(...).already) but it was pending.'
|
||||
};
|
||||
} else {
|
||||
return matcher.compare.apply(null, matcherArgs);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
function ContextAddingFilter(message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@@ -203,6 +203,19 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
return matches ? matches[1] : '<anonymous>';
|
||||
};
|
||||
|
||||
j$.isPending_ = function(promise) {
|
||||
var sentinel = {};
|
||||
// eslint-disable-next-line compat/compat
|
||||
return Promise.race([promise, Promise.resolve(sentinel)]).then(
|
||||
function(result) {
|
||||
return result === sentinel;
|
||||
},
|
||||
function() {
|
||||
return false;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
|
||||
* that will succeed if the actual value being compared is an instance of the specified class/constructor.
|
||||
|
||||
Reference in New Issue
Block a user