Merge branch '3.99' into 4.0
This commit is contained in:
@@ -6,9 +6,11 @@ getJasmineRequireObj().Clock = function() {
|
||||
typeof process.versions.node === 'string';
|
||||
|
||||
/**
|
||||
* _Note:_ Do not construct this directly, Jasmine will make one during booting. You can get the current clock with {@link jasmine.clock}.
|
||||
* @class Clock
|
||||
* @classdesc Jasmine's mock clock is used when testing time dependent code.
|
||||
* @classdesc Jasmine's mock clock is used when testing time dependent code.<br>
|
||||
* _Note:_ Do not construct this directly. You can get the current clock with
|
||||
* {@link jasmine.clock}.
|
||||
* @hideconstructor
|
||||
*/
|
||||
function Clock(global, delayedFunctionSchedulerFactory, mockDate) {
|
||||
var self = this,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
getJasmineRequireObj().Env = function(j$) {
|
||||
/**
|
||||
* _Note:_ Do not construct this directly, Jasmine will make one during booting.
|
||||
* @name Env
|
||||
* @class Env
|
||||
* @since 2.0.0
|
||||
* @classdesc The Jasmine environment
|
||||
* @constructor
|
||||
* @classdesc The Jasmine environment.<br>
|
||||
* _Note:_ Do not construct this directly. You can obtain the Env instance by
|
||||
* calling {@link jasmine.getEnv}.
|
||||
* @hideconstructor
|
||||
*/
|
||||
function Env(options) {
|
||||
options = options || {};
|
||||
@@ -35,7 +36,8 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
|
||||
/**
|
||||
* This represents the available options to configure Jasmine.
|
||||
* Options that are not provided will use their default values
|
||||
* Options that are not provided will use their default values.
|
||||
* @see Env#configure
|
||||
* @interface Configuration
|
||||
* @since 3.3.0
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -13,9 +13,11 @@ getJasmineRequireObj().Spy = function(j$) {
|
||||
});
|
||||
|
||||
/**
|
||||
* _Note:_ Do not construct this directly, use {@link spyOn}, {@link spyOnProperty}, {@link jasmine.createSpy}, or {@link jasmine.createSpyObj}
|
||||
* @constructor
|
||||
* @name Spy
|
||||
* @classdesc _Note:_ Do not construct this directly. Use {@link spyOn},
|
||||
* {@link spyOnProperty}, {@link jasmine.createSpy}, or
|
||||
* {@link jasmine.createSpyObj} instead.
|
||||
* @class Spy
|
||||
* @hideconstructor
|
||||
*/
|
||||
function Spy(
|
||||
name,
|
||||
|
||||
@@ -163,7 +163,7 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
return spy;
|
||||
};
|
||||
|
||||
this.spyOnAllFunctions = function(obj) {
|
||||
this.spyOnAllFunctions = function(obj, includeNonEnumerable) {
|
||||
if (j$.util.isUndefined(obj)) {
|
||||
throw new Error(
|
||||
'spyOnAllFunctions could not find an object to spy upon'
|
||||
@@ -171,30 +171,27 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
}
|
||||
|
||||
var pointer = obj,
|
||||
props = [],
|
||||
prop,
|
||||
descriptor;
|
||||
propsToSpyOn = [],
|
||||
properties,
|
||||
propertiesToSkip = [];
|
||||
|
||||
while (pointer) {
|
||||
for (prop in pointer) {
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(pointer, prop) &&
|
||||
pointer[prop] instanceof Function
|
||||
) {
|
||||
descriptor = Object.getOwnPropertyDescriptor(pointer, prop);
|
||||
if (
|
||||
(descriptor.writable || descriptor.set) &&
|
||||
descriptor.configurable
|
||||
) {
|
||||
props.push(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (
|
||||
pointer &&
|
||||
(!includeNonEnumerable || pointer !== Object.prototype)
|
||||
) {
|
||||
properties = getProps(pointer, includeNonEnumerable);
|
||||
properties = properties.filter(function(prop) {
|
||||
return propertiesToSkip.indexOf(prop) === -1;
|
||||
});
|
||||
propertiesToSkip = propertiesToSkip.concat(properties);
|
||||
propsToSpyOn = propsToSpyOn.concat(
|
||||
getSpyableFunctionProps(pointer, properties)
|
||||
);
|
||||
pointer = Object.getPrototypeOf(pointer);
|
||||
}
|
||||
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
this.spyOn(obj, props[i]);
|
||||
for (var i = 0; i < propsToSpyOn.length; i++) {
|
||||
this.spyOn(obj, propsToSpyOn[i]);
|
||||
}
|
||||
|
||||
return obj;
|
||||
@@ -209,5 +206,49 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
};
|
||||
}
|
||||
|
||||
function getProps(obj, includeNonEnumerable) {
|
||||
var enumerableProperties = Object.keys(obj);
|
||||
|
||||
if (!includeNonEnumerable) {
|
||||
return enumerableProperties;
|
||||
}
|
||||
|
||||
return Object.getOwnPropertyNames(obj).filter(function(prop) {
|
||||
return (
|
||||
prop !== 'constructor' ||
|
||||
enumerableProperties.indexOf('constructor') > -1
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function getSpyableFunctionProps(obj, propertiesToCheck) {
|
||||
var props = [],
|
||||
prop;
|
||||
for (var i = 0; i < propertiesToCheck.length; i++) {
|
||||
prop = propertiesToCheck[i];
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(obj, prop) &&
|
||||
isSpyableProp(obj, prop)
|
||||
) {
|
||||
props.push(prop);
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
function isSpyableProp(obj, prop) {
|
||||
var value, descriptor;
|
||||
try {
|
||||
value = obj[prop];
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
if (value instanceof Function) {
|
||||
descriptor = Object.getOwnPropertyDescriptor(obj, prop);
|
||||
return (descriptor.writable || descriptor.set) && descriptor.configurable;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return SpyRegistry;
|
||||
};
|
||||
|
||||
@@ -201,6 +201,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.
|
||||
|
||||
@@ -10,7 +10,7 @@ getJasmineRequireObj().toBeResolved = function(j$) {
|
||||
* @example
|
||||
* return expectAsync(aPromise).toBeResolved();
|
||||
*/
|
||||
return function toBeResolved() {
|
||||
return function toBeResolved(matchersUtil) {
|
||||
return {
|
||||
compare: function(actual) {
|
||||
if (!j$.isPromiseLike(actual)) {
|
||||
@@ -21,8 +21,15 @@ getJasmineRequireObj().toBeResolved = function(j$) {
|
||||
function() {
|
||||
return { pass: true };
|
||||
},
|
||||
function() {
|
||||
return { pass: false };
|
||||
function(e) {
|
||||
return {
|
||||
pass: false,
|
||||
message:
|
||||
'Expected a promise to be resolved but it was ' +
|
||||
'rejected with ' +
|
||||
matchersUtil.pp(e) +
|
||||
'.'
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -45,10 +45,14 @@ getJasmineRequireObj().toBeResolvedTo = function(j$) {
|
||||
};
|
||||
}
|
||||
},
|
||||
function() {
|
||||
function(e) {
|
||||
return {
|
||||
pass: false,
|
||||
message: prefix(false) + ' but it was rejected.'
|
||||
message:
|
||||
prefix(false) +
|
||||
' but it was rejected with ' +
|
||||
matchersUtil.pp(e) +
|
||||
'.'
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
getJasmineRequireObj().MatchersUtil = function(j$) {
|
||||
/**
|
||||
* @class MatchersUtil
|
||||
* @classdesc Utilities for use in implementing matchers.<br>
|
||||
* _Note:_ Do not construct this directly. Jasmine will construct one and
|
||||
* pass it to matchers and asymmetric equality testers.
|
||||
* @name MatchersUtil
|
||||
* @classdesc Utilities for use in implementing matchers
|
||||
* @constructor
|
||||
* @hideconstructor
|
||||
*/
|
||||
function MatchersUtil(options) {
|
||||
options = options || {};
|
||||
@@ -599,3 +599,28 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
|
||||
|
||||
return MatchersUtil;
|
||||
};
|
||||
|
||||
/**
|
||||
* @interface AsymmetricEqualityTester
|
||||
* @classdesc An asymmetric equality tester is an object that can match multiple
|
||||
* objects. Examples include jasmine.any() and jasmine.stringMatching().
|
||||
* User-defined asymmetric equality testers can also be defined and used in
|
||||
* expectations.
|
||||
* @see custom_asymmetric_equality_testers
|
||||
* @since 2.0.0
|
||||
*/
|
||||
/**
|
||||
* Determines whether a value matches this tester
|
||||
* @function
|
||||
* @name AsymmetricEqualityTester#asymmetricMatch
|
||||
* @param value {any} The value to test
|
||||
* @param matchersUtil {MatchersUtil} utilities for testing equality, etc
|
||||
* @return {Boolean}
|
||||
*/
|
||||
/**
|
||||
* Returns a string representation of this tester to use in matcher failure messages
|
||||
* @function
|
||||
* @name AsymmetricEqualityTester#jasmineToString
|
||||
* @param pp {function} Function that takes a value and returns a pretty-printed representation
|
||||
* @return {String}
|
||||
*/
|
||||
|
||||
@@ -285,10 +285,11 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
* @function
|
||||
* @global
|
||||
* @param {Object} obj - The object upon which to install the {@link Spy}s
|
||||
* @param {boolean} includeNonEnumerable - Whether or not to add spies to non-enumerable properties
|
||||
* @returns {Object} the spied object
|
||||
*/
|
||||
spyOnAllFunctions: function(obj) {
|
||||
return env.spyOnAllFunctions(obj);
|
||||
spyOnAllFunctions: function(obj, includeNonEnumerable) {
|
||||
return env.spyOnAllFunctions(obj, includeNonEnumerable);
|
||||
},
|
||||
|
||||
jsApiReporter: new jasmine.JsApiReporter({
|
||||
|
||||
@@ -177,7 +177,10 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
' of ' +
|
||||
totalSpecsDefined +
|
||||
' specs - run all';
|
||||
var skippedLink = addToExistingQueryString('spec', '');
|
||||
// include window.location.pathname to fix issue with karma-jasmine-html-reporter in angular: see https://github.com/jasmine/jasmine/issues/1906
|
||||
var skippedLink =
|
||||
(window.location.pathname || '') +
|
||||
addToExistingQueryString('spec', '');
|
||||
alert.appendChild(
|
||||
createDom(
|
||||
'span',
|
||||
@@ -545,7 +548,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
);
|
||||
throwCheckbox.checked = config.oneFailurePerSpec;
|
||||
throwCheckbox.onclick = function() {
|
||||
navigateWithNewParam('throwFailures', !config.oneFailurePerSpec);
|
||||
navigateWithNewParam('oneFailurePerSpec', !config.oneFailurePerSpec);
|
||||
};
|
||||
|
||||
var randomCheckbox = optionsMenuDom.querySelector(
|
||||
@@ -615,7 +618,11 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
suite = suite.parent;
|
||||
}
|
||||
|
||||
return addToExistingQueryString('spec', els.join(' '));
|
||||
// include window.location.pathname to fix issue with karma-jasmine-html-reporter in angular: see https://github.com/jasmine/jasmine/issues/1906
|
||||
return (
|
||||
(window.location.pathname || '') +
|
||||
addToExistingQueryString('spec', els.join(' '))
|
||||
);
|
||||
}
|
||||
|
||||
function addDeprecationWarnings(result, runnableType) {
|
||||
@@ -718,11 +725,19 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
function specHref(result) {
|
||||
return addToExistingQueryString('spec', result.fullName);
|
||||
// include window.location.pathname to fix issue with karma-jasmine-html-reporter in angular: see https://github.com/jasmine/jasmine/issues/1906
|
||||
return (
|
||||
(window.location.pathname || '') +
|
||||
addToExistingQueryString('spec', result.fullName)
|
||||
);
|
||||
}
|
||||
|
||||
function seedHref(seed) {
|
||||
return addToExistingQueryString('seed', seed);
|
||||
// include window.location.pathname to fix issue with karma-jasmine-html-reporter in angular: see https://github.com/jasmine/jasmine/issues/1906
|
||||
return (
|
||||
(window.location.pathname || '') +
|
||||
addToExistingQueryString('seed', seed)
|
||||
);
|
||||
}
|
||||
|
||||
function defaultQueryString(key, value) {
|
||||
|
||||
Reference in New Issue
Block a user