Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd1b7ce9c7 | ||
|
|
3653d6e0ef | ||
|
|
c3387f8dbf | ||
|
|
3d54184c7f | ||
|
|
6f23e706d7 | ||
|
|
cc69edf92c | ||
|
|
ba7560f65e | ||
|
|
c3960c4a96 | ||
|
|
5c21f94bb1 | ||
|
|
8cd7c94490 | ||
|
|
6a6fa7b29a | ||
|
|
4984548cab | ||
|
|
6941bde7e2 | ||
|
|
1504f25ced | ||
|
|
99e350ac85 | ||
|
|
1624b07589 |
@@ -4,6 +4,10 @@
|
||||
version: 2.1
|
||||
|
||||
executors:
|
||||
node22:
|
||||
docker:
|
||||
- image: cimg/node:22.0.0
|
||||
working_directory: ~/workspace
|
||||
node20:
|
||||
docker:
|
||||
- image: cimg/node:20.0.0
|
||||
@@ -94,12 +98,20 @@ workflows:
|
||||
|
||||
push:
|
||||
jobs:
|
||||
- build:
|
||||
executor: node22
|
||||
name: build_node_22
|
||||
- build:
|
||||
executor: node20
|
||||
name: build_node_20
|
||||
- build:
|
||||
executor: node18
|
||||
name: build_node_18
|
||||
- test_node:
|
||||
executor: node22
|
||||
name: test_node_22
|
||||
requires:
|
||||
- build_node_22
|
||||
- test_node:
|
||||
executor: node20
|
||||
name: test_node_20
|
||||
@@ -115,6 +127,11 @@ workflows:
|
||||
name: test_parallel_node_18
|
||||
requires:
|
||||
- build_node_18
|
||||
- test_parallel:
|
||||
executor: node22
|
||||
name: test_parallel_node_22
|
||||
requires:
|
||||
- build_node_22
|
||||
- test_parallel:
|
||||
executor: node20
|
||||
name: test_parallel_node_20
|
||||
|
||||
46
.eslintrc
Normal file
46
.eslintrc
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"extends": [
|
||||
"plugin:compat/recommended"
|
||||
],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"es2017": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
"rules": {
|
||||
"quotes": [
|
||||
"error",
|
||||
"single",
|
||||
{
|
||||
"avoidEscape": true
|
||||
}
|
||||
],
|
||||
"no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
"args": "none"
|
||||
}
|
||||
],
|
||||
"no-implicit-globals": "error",
|
||||
"block-spacing": "error",
|
||||
"func-call-spacing": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"key-spacing": "error",
|
||||
"no-tabs": "error",
|
||||
"no-trailing-spaces": "error",
|
||||
"no-whitespace-before-property": "error",
|
||||
"semi": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"space-before-blocks": "error",
|
||||
"no-eval": "error",
|
||||
"no-var": "error",
|
||||
"no-debugger": "error"
|
||||
}
|
||||
}
|
||||
3
.prettierrc
Normal file
3
.prettierrc
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"singleQuote": true
|
||||
}
|
||||
@@ -29,7 +29,7 @@ Microsoft Edge) as well as Node.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|---------------------|
|
||||
| Node | 18, 20 |
|
||||
| Node | 18, 20, 22 |
|
||||
| Safari | 15-17 |
|
||||
| Chrome | Evergreen |
|
||||
| Firefox | Evergreen, 102, 115 |
|
||||
|
||||
@@ -463,7 +463,11 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
'tr',
|
||||
{},
|
||||
createDom('td', {}, entry.timestamp.toString()),
|
||||
createDom('td', {}, entry.message)
|
||||
createDom(
|
||||
'td',
|
||||
{ className: 'jasmine-debug-log-msg' },
|
||||
entry.message
|
||||
)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -295,4 +295,7 @@ body {
|
||||
}
|
||||
.jasmine_html-reporter .jasmine-debug-log table, .jasmine_html-reporter .jasmine-debug-log th, .jasmine_html-reporter .jasmine-debug-log td {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
.jasmine_html-reporter .jasmine-debug-log .jasmine-debug-log-msg {
|
||||
white-space: pre;
|
||||
}
|
||||
@@ -400,9 +400,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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.
|
||||
* @name jasmine.any
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared is an instance of the specified class/constructor.
|
||||
* @name asymmetricEqualityTesters.any
|
||||
* @emittedName jasmine.any
|
||||
* @since 1.3.0
|
||||
* @function
|
||||
* @param {Constructor} clazz - The constructor to check against.
|
||||
@@ -412,9 +413,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 not `null` and not `undefined`.
|
||||
* @name jasmine.anything
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared is not `null` and not `undefined`.
|
||||
* @name asymmetricEqualityTesters.anything
|
||||
* @emittedName jasmine.anything
|
||||
* @since 2.2.0
|
||||
* @function
|
||||
*/
|
||||
@@ -423,9 +425,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 `true` or anything truthy.
|
||||
* @name jasmine.truthy
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared is `true` or anything truthy.
|
||||
* @name asymmetricEqualityTesters.truthy
|
||||
* @emittedName jasmine.truthy
|
||||
* @since 3.1.0
|
||||
* @function
|
||||
*/
|
||||
@@ -434,9 +437,11 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 `null`, `undefined`, `0`, `false` or anything falsey.
|
||||
* @name jasmine.falsy
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared is `null`, `undefined`, `0`, `false` or anything
|
||||
* falsy.
|
||||
* @name asymmetricEqualityTesters.falsy
|
||||
* @emittedName jasmine.falsy
|
||||
* @since 3.1.0
|
||||
* @function
|
||||
*/
|
||||
@@ -445,9 +450,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 empty.
|
||||
* @name jasmine.empty
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared is empty.
|
||||
* @name asymmetricEqualityTesters.empty
|
||||
* @emittedName jasmine.empty
|
||||
* @since 3.1.0
|
||||
* @function
|
||||
*/
|
||||
@@ -456,10 +462,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher}
|
||||
* that passes if the actual value is the same as the sample as determined
|
||||
* by the `===` operator.
|
||||
* @name jasmine.is
|
||||
* Get an {@link AsymmetricEqualityTester} that passes if the actual value is
|
||||
* the same as the sample as determined by the `===` operator.
|
||||
* @name asymmetricEqualityTesters.is
|
||||
* @emittedName jasmine.is
|
||||
* @function
|
||||
* @param {Object} sample - The value to compare the actual to.
|
||||
*/
|
||||
@@ -468,9 +474,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 not empty.
|
||||
* @name jasmine.notEmpty
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared is not empty.
|
||||
* @name asymmetricEqualityTesters.notEmpty
|
||||
* @emittedName jasmine.notEmpty
|
||||
* @since 3.1.0
|
||||
* @function
|
||||
*/
|
||||
@@ -479,9 +486,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 contains at least the keys and values.
|
||||
* @name jasmine.objectContaining
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared contains at least the specified keys and values.
|
||||
* @name asymmetricEqualityTesters.objectContaining
|
||||
* @emittedName jasmine.objectContaining
|
||||
* @since 1.3.0
|
||||
* @function
|
||||
* @param {Object} sample - The subset of properties that _must_ be in the actual.
|
||||
@@ -491,9 +499,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 is a `String` that matches the `RegExp` or `String`.
|
||||
* @name jasmine.stringMatching
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value is a `String` that matches the `RegExp` or `String`.
|
||||
* @name asymmetricEqualityTesters.stringMatching
|
||||
* @emittedName jasmine.stringMatching
|
||||
* @since 2.2.0
|
||||
* @function
|
||||
* @param {RegExp|String} expected
|
||||
@@ -503,9 +512,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 is a `String` that contains the specified `String`.
|
||||
* @name jasmine.stringContaining
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value is a `String` that contains the specified `String`.
|
||||
* @name asymmetricEqualityTesters.stringContaining
|
||||
* @emittedName jasmine.stringContaining
|
||||
* @since 3.10.0
|
||||
* @function
|
||||
* @param {String} expected
|
||||
@@ -515,9 +525,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 is an `Array` that contains at least the elements in the sample.
|
||||
* @name jasmine.arrayContaining
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value is an `Array` that contains at least the elements in the sample.
|
||||
* @name asymmetricEqualityTesters.arrayContaining
|
||||
* @emittedName jasmine.arrayContaining
|
||||
* @since 2.2.0
|
||||
* @function
|
||||
* @param {Array} sample
|
||||
@@ -527,9 +538,11 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 is an `Array` that contains all of the elements in the sample in any order.
|
||||
* @name jasmine.arrayWithExactContents
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value is an `Array` that contains all of the elements in the sample in
|
||||
* any order.
|
||||
* @name asymmetricEqualityTesters.arrayWithExactContents
|
||||
* @emittedName jasmine.arrayWithExactContents
|
||||
* @since 2.8.0
|
||||
* @function
|
||||
* @param {Array} sample
|
||||
@@ -539,10 +552,11 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 every key/value pair in the sample passes the deep equality comparison
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if every
|
||||
* key/value pair in the sample passes the deep equality comparison
|
||||
* with at least one key/value pair in the actual value being compared
|
||||
* @name jasmine.mapContaining
|
||||
* @name asymmetricEqualityTesters.mapContaining
|
||||
* @emittedName jasmine.mapContaining
|
||||
* @since 3.5.0
|
||||
* @function
|
||||
* @param {Map} sample - The subset of items that _must_ be in the actual.
|
||||
@@ -552,10 +566,11 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 every item in the sample passes the deep equality comparison
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if every item
|
||||
* in the sample passes the deep equality comparison
|
||||
* with at least one item in the actual value being compared
|
||||
* @name jasmine.setContaining
|
||||
* @name asymmetricEqualityTesters.setContaining
|
||||
* @emittedName jasmine.setContaining
|
||||
* @since 3.5.0
|
||||
* @function
|
||||
* @param {Set} sample - The subset of items that _must_ be in the actual.
|
||||
@@ -611,14 +626,26 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
* handling will be restored when the promise returned from the callback is
|
||||
* settled.
|
||||
*
|
||||
* When the JavaScript runtime reports an uncaught error or unhandled rejection,
|
||||
* the spy will be called with a single parameter representing Jasmine's best
|
||||
* effort at describing the error. This parameter may be of any type, because
|
||||
* JavaScript allows anything to be thrown or used as the reason for a
|
||||
* rejected promise, but Error instances and strings are most common.
|
||||
*
|
||||
* Note: The JavaScript runtime may deliver uncaught error events and unhandled
|
||||
* rejection events asynchronously, especially in browsers. If the event
|
||||
* occurs after the promise returned from the callback is settled, it won't
|
||||
* be routed to the spy even if the underlying error occurred previously.
|
||||
* It's up to you to ensure that the returned promise isn't resolved until
|
||||
* all of the error/rejection events that you want to handle have occurred.
|
||||
* It's up to you to ensure that all of the error/rejection events that you
|
||||
* want to handle have occurred before you resolve the promise returned from
|
||||
* the callback.
|
||||
*
|
||||
* You must await the return value of spyOnGlobalErrorsAsync.
|
||||
* You must ensure that the `it`/`beforeEach`/etc fn that called
|
||||
* `spyOnGlobalErrorsAsync` does not signal completion until after the
|
||||
* promise returned by `spyOnGlobalErrorsAsync` is resolved. Normally this is
|
||||
* done by `await`ing the returned promise. Leaving the global error spy
|
||||
* installed after the `it`/`beforeEach`/etc fn that installed it signals
|
||||
* completion is likely to cause problems and is not supported.
|
||||
* @name jasmine.spyOnGlobalErrorsAsync
|
||||
* @function
|
||||
* @async
|
||||
@@ -3655,19 +3682,24 @@ getJasmineRequireObj().Expectation = function(j$) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add some context for an {@link expect}
|
||||
* Add some context to be included in matcher failures for an
|
||||
* {@link expect|expectation}, so that it can be more easily distinguished
|
||||
* from similar expectations.
|
||||
* @function
|
||||
* @name matchers#withContext
|
||||
* @since 3.3.0
|
||||
* @param {String} message - Additional context to show when the matcher fails
|
||||
* @return {matchers}
|
||||
* @example
|
||||
* expect(things[0]).withContext('thing 0').toEqual('a');
|
||||
* expect(things[1]).withContext('thing 1').toEqual('b');
|
||||
*/
|
||||
Expectation.prototype.withContext = function withContext(message) {
|
||||
return addFilter(this, new ContextAddingFilter(message));
|
||||
};
|
||||
|
||||
/**
|
||||
* Invert the matcher following this {@link expect}
|
||||
* Invert the matcher following this {@link expect|expectation}
|
||||
* @member
|
||||
* @name matchers#not
|
||||
* @since 1.3.0
|
||||
@@ -4070,6 +4102,7 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
||||
|
||||
function dispatchBrowserError(error, event) {
|
||||
if (overrideHandler) {
|
||||
// See discussion of spyOnGlobalErrorsAsync in base.js
|
||||
overrideHandler(error);
|
||||
return;
|
||||
}
|
||||
@@ -4113,6 +4146,7 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
||||
const handler = handlers[handlers.length - 1];
|
||||
|
||||
if (overrideHandler) {
|
||||
// See discussion of spyOnGlobalErrorsAsync in base.js
|
||||
overrideHandler(error);
|
||||
return;
|
||||
}
|
||||
@@ -6524,7 +6558,7 @@ getJasmineRequireObj().toHaveSize = function(j$) {
|
||||
* array = [1,2];
|
||||
* expect(array).toHaveSize(2);
|
||||
*/
|
||||
function toHaveSize() {
|
||||
function toHaveSize(matchersUtil) {
|
||||
return {
|
||||
compare: function(actual, expected) {
|
||||
const result = {
|
||||
@@ -6539,12 +6573,29 @@ getJasmineRequireObj().toHaveSize = function(j$) {
|
||||
throw new Error('Cannot get size of ' + actual + '.');
|
||||
}
|
||||
|
||||
let actualSize;
|
||||
if (j$.isSet(actual) || j$.isMap(actual)) {
|
||||
result.pass = actual.size === expected;
|
||||
actualSize = actual.size;
|
||||
} else if (isLength(actual.length)) {
|
||||
result.pass = actual.length === expected;
|
||||
actualSize = actual.length;
|
||||
} else {
|
||||
result.pass = Object.keys(actual).length === expected;
|
||||
actualSize = Object.keys(actual).length;
|
||||
}
|
||||
|
||||
result.pass = actualSize === expected;
|
||||
|
||||
if (!result.pass) {
|
||||
result.message = function() {
|
||||
return (
|
||||
'Expected ' +
|
||||
matchersUtil.pp(actual) +
|
||||
' with size ' +
|
||||
actualSize +
|
||||
' to have size ' +
|
||||
expected +
|
||||
'.'
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -7684,8 +7735,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
}
|
||||
|
||||
QueueRunner.prototype.execute = function() {
|
||||
this.handleFinalError = error => {
|
||||
this.onException(error);
|
||||
this.handleFinalError = (error, event) => {
|
||||
this.onException(errorOrMsgForGlobalError(error, event));
|
||||
};
|
||||
this.globalErrors.pushListener(this.handleFinalError);
|
||||
this.run(0);
|
||||
@@ -7715,10 +7766,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
this.recordError_(iterativeIndex);
|
||||
};
|
||||
|
||||
function handleError(error) {
|
||||
// TODO probably shouldn't next() right away here.
|
||||
// That makes debugging async failures much more confusing.
|
||||
onException(error);
|
||||
function handleError(error, event) {
|
||||
onException(errorOrMsgForGlobalError(error, event));
|
||||
}
|
||||
const cleanup = once(() => {
|
||||
if (timeoutId !== void 0) {
|
||||
@@ -7904,6 +7953,17 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
};
|
||||
}
|
||||
|
||||
function errorOrMsgForGlobalError(error, event) {
|
||||
// TODO: In cases where error is a string or undefined, the error message
|
||||
// that gets sent to reporters will be `${message} thrown`, which could
|
||||
// be improved to not say "thrown" when the cause wasn't necessarily
|
||||
// an exception or to provide hints about throwing Errors rather than
|
||||
// strings.
|
||||
return (
|
||||
error || (event && event.message) || 'Global error event with no message'
|
||||
);
|
||||
}
|
||||
|
||||
return QueueRunner;
|
||||
};
|
||||
|
||||
@@ -8408,6 +8468,12 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
}),
|
||||
|
||||
/**
|
||||
* <p>Members of the jasmine global.</p>
|
||||
* <p>Note: The members of the
|
||||
* {@link asymmetricEqualityTesters|asymmetricEqualityTesters namespace}
|
||||
* are also accessed via the jasmine global, but due to jsdoc limitations
|
||||
* they are not listed here.</p>
|
||||
*
|
||||
* @namespace jasmine
|
||||
*/
|
||||
jasmine: jasmine
|
||||
@@ -8541,6 +8607,28 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
return env.setDefaultSpyStrategy(defaultStrategyFn);
|
||||
};
|
||||
|
||||
/**
|
||||
* {@link AsymmetricEqualityTester|Asymmetric equality testers} allow for
|
||||
* non-exact matching in matchers that use Jasmine's deep value equality
|
||||
* semantics, such as {@link matchers#toEqual|toEqual},
|
||||
* {@link matchers#toContain|toContain}, and
|
||||
* {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}.
|
||||
*
|
||||
* @example
|
||||
* const someComplexObject = {
|
||||
* foo: 'bar',
|
||||
* baz: 'a string that contains "something"',
|
||||
* qux: 'whatever'
|
||||
* };
|
||||
* // Passes.
|
||||
* expect(someComplexObject).toEqual(jasmine.objectContaining({
|
||||
* foo: 'bar',
|
||||
* baz: jasmine.stringContaining('something')
|
||||
* });
|
||||
*
|
||||
* @namespace asymmetricEqualityTesters
|
||||
*/
|
||||
|
||||
return jasmineInterface;
|
||||
};
|
||||
|
||||
@@ -9746,7 +9834,7 @@ getJasmineRequireObj().StackTrace = function(j$) {
|
||||
// e.g. " at /some/path:4320:20
|
||||
{ re: /\s*at (.+)$/, fileLineColIx: 1, style: 'v8' },
|
||||
|
||||
// PhantomJS on OS X, Safari, Firefox
|
||||
// Safari, most Firefox stack frames
|
||||
// e.g. "run@http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||
// or "http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||
{
|
||||
@@ -9754,6 +9842,15 @@ getJasmineRequireObj().StackTrace = function(j$) {
|
||||
fnIx: 2,
|
||||
fileLineColIx: 3,
|
||||
style: 'webkit'
|
||||
},
|
||||
|
||||
// Some Firefox stack frames when the developer tools are open
|
||||
// e.g. "promise callback*specStarted@http://localhost:8888/__jasmine__/jasmine.js:1880:41"
|
||||
{
|
||||
re: /^^(?:((?:promise callback|[^\s]+ handler)\*([^@\s]+)@)|@)?([^\s]+)$/,
|
||||
fnIx: 2,
|
||||
fileLineColIx: 3,
|
||||
style: 'webkit'
|
||||
}
|
||||
];
|
||||
|
||||
@@ -10813,5 +10910,5 @@ getJasmineRequireObj().UserContext = function(j$) {
|
||||
};
|
||||
|
||||
getJasmineRequireObj().version = function() {
|
||||
return '5.1.2';
|
||||
return '5.2.0';
|
||||
};
|
||||
|
||||
51
package.json
51
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jasmine-core",
|
||||
"license": "MIT",
|
||||
"version": "5.1.2",
|
||||
"version": "5.2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jasmine/jasmine.git"
|
||||
@@ -52,55 +52,6 @@
|
||||
"shelljs": "^0.8.3",
|
||||
"temp": "^0.9.0"
|
||||
},
|
||||
"prettier": {
|
||||
"singleQuote": true
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"plugin:compat/recommended"
|
||||
],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"es2017": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
"rules": {
|
||||
"quotes": [
|
||||
"error",
|
||||
"single",
|
||||
{
|
||||
"avoidEscape": true
|
||||
}
|
||||
],
|
||||
"no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
"args": "none"
|
||||
}
|
||||
],
|
||||
"no-implicit-globals": "error",
|
||||
"block-spacing": "error",
|
||||
"func-call-spacing": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"key-spacing": "error",
|
||||
"no-tabs": "error",
|
||||
"no-trailing-spaces": "error",
|
||||
"no-whitespace-before-property": "error",
|
||||
"semi": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"space-before-blocks": "error",
|
||||
"no-eval": "error",
|
||||
"no-var": "error",
|
||||
"no-debugger": "error"
|
||||
}
|
||||
},
|
||||
"browserslist": [
|
||||
"Safari >= 15",
|
||||
"Firefox >= 102",
|
||||
|
||||
51
release_notes/4.6.1.md
Normal file
51
release_notes/4.6.1.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Jasmine Core 4.6.1 Release Notes
|
||||
|
||||
## Summary
|
||||
|
||||
This is a one-time backport of bug fixes from 5.x, for the benefit of Karma
|
||||
users who may not be aware that they're still using 4.x.
|
||||
|
||||
No further 4.x releases are planned. If possible, you should upgrade to the
|
||||
latest 5.x instead of 4.6.1. If you're using Karma, you can do this by
|
||||
installing jasmine-core 5.x and adding an override to package.json:
|
||||
|
||||
```
|
||||
{
|
||||
// ...
|
||||
"overrides": {
|
||||
"karma-jasmine": {
|
||||
"jasmine-core": "^5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Removed unnecessary throw when building stack trace
|
||||
|
||||
* Fixed error when formatting Error object with non-Error cause property
|
||||
|
||||
Merges [#2013](https://github.com/jasmine/jasmine/pull/2013) from @angrycat9000.
|
||||
|
||||
Fixes [#2011](https://github.com/jasmine/jasmine/issues/2011).
|
||||
|
||||
* Accessibility: Always provide a non-color indication that a spec is pending
|
||||
|
||||
* Accessibility: Improved contrast of version number and inactive tab links
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 4.6.1 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 12.17+, 14, 16, 18 |
|
||||
| Safari | 14-16 |
|
||||
| Chrome | 125 |
|
||||
| Firefox | 91, 102, 126 |
|
||||
| Edge | 124 |
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
35
release_notes/5.2.0.md
Normal file
35
release_notes/5.2.0.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Jasmine Core 5.2.0 Release Notes
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Fixed stack trace filtering in FF when the developer tools are open
|
||||
* Fixed handling of browser `error` events with message but no error
|
||||
|
||||
## New Features
|
||||
|
||||
* Improved the error message of the toHaveSize matcher.
|
||||
* Merges [#2033](https://github.com/jasmine/jasmine/pull/2033) from @stephanreiter
|
||||
* HTML reporter: show debug logs with white-space: pre
|
||||
|
||||
## Documentation improvements
|
||||
|
||||
* Improved discoverability of asymmetric equality testers
|
||||
* Added an example for withContext()
|
||||
* Clarified spyOnGlobalErrorsAsync API docs
|
||||
* Added Node 22 to supported environments
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 18, 20, 22 |
|
||||
| Safari | 15-17 |
|
||||
| Chrome | 126 |
|
||||
| Firefox | 102, 115, 128 |
|
||||
| Edge | 126 |
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
@@ -153,12 +153,33 @@ describe('ExceptionFormatter', function() {
|
||||
);
|
||||
});
|
||||
|
||||
it('filters Jasmine stack frames with Firefox async annotations', function() {
|
||||
const error = {
|
||||
stack:
|
||||
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
|
||||
'promise callback*fn1@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
|
||||
'setTimeout handler*fn2@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
|
||||
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28'
|
||||
};
|
||||
const subject = new jasmineUnderTest.ExceptionFormatter({
|
||||
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
|
||||
});
|
||||
const result = subject.stack(error);
|
||||
expect(result).toEqual(
|
||||
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
|
||||
'<Jasmine>\n' +
|
||||
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28'
|
||||
);
|
||||
});
|
||||
|
||||
it('filters Jasmine stack frames in this environment', function() {
|
||||
const error = new Error('an error');
|
||||
const subject = new jasmineUnderTest.ExceptionFormatter({
|
||||
jasmineFile: jasmine.util.jasmineFile()
|
||||
});
|
||||
const result = subject.stack(error);
|
||||
jasmine.debugLog('Original stack trace: ' + error.stack);
|
||||
jasmine.debugLog('Filtered stack trace: ' + result);
|
||||
const lines = result.split('\n');
|
||||
|
||||
if (lines[0].match(/an error/)) {
|
||||
|
||||
@@ -328,6 +328,62 @@ describe('GlobalErrors', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Reporting uncaught exceptions in node.js', function() {
|
||||
it('prepends a descriptive message when the error is not an `Error`', function() {
|
||||
const fakeGlobal = {
|
||||
process: {
|
||||
on: jasmine.createSpy('process.on'),
|
||||
removeListener: function() {},
|
||||
listeners: function() {
|
||||
return [];
|
||||
},
|
||||
removeAllListeners: function() {}
|
||||
}
|
||||
};
|
||||
const handler = jasmine.createSpy('errorHandler');
|
||||
const errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
||||
|
||||
errors.install();
|
||||
errors.pushListener(handler);
|
||||
|
||||
uncaughtExceptionListener(fakeGlobal)(17);
|
||||
|
||||
expect(handler).toHaveBeenCalledWith(new Error('Uncaught exception: 17'));
|
||||
});
|
||||
|
||||
it('substitutes a descriptive message when the error is falsy', function() {
|
||||
const fakeGlobal = {
|
||||
process: {
|
||||
on: jasmine.createSpy('process.on'),
|
||||
removeListener: function() {},
|
||||
listeners: function() {
|
||||
return [];
|
||||
},
|
||||
removeAllListeners: function() {}
|
||||
}
|
||||
};
|
||||
const handler = jasmine.createSpy('errorHandler');
|
||||
const errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
||||
|
||||
errors.install();
|
||||
errors.pushListener(handler);
|
||||
|
||||
uncaughtExceptionListener(fakeGlobal)();
|
||||
|
||||
expect(handler).toHaveBeenCalledWith(
|
||||
new Error('Uncaught exception with no error or message')
|
||||
);
|
||||
});
|
||||
|
||||
function uncaughtExceptionListener(global) {
|
||||
// Grab the right listener
|
||||
expect(global.process.on.calls.argsFor(0)[0]).toEqual(
|
||||
'uncaughtException'
|
||||
);
|
||||
return global.process.on.calls.argsFor(0)[1];
|
||||
}
|
||||
});
|
||||
|
||||
describe('#setOverrideListener', function() {
|
||||
it('overrides the existing handlers in browsers until removed', function() {
|
||||
const fakeGlobal = browserGlobal();
|
||||
|
||||
@@ -459,6 +459,32 @@ describe('QueueRunner', function() {
|
||||
expect(nextQueueableFn.fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('handles a global error event with a message but no error', function() {
|
||||
const queueableFn = {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
fn: function(done) {
|
||||
const currentHandler = globalErrors.pushListener.calls.mostRecent()
|
||||
.args[0];
|
||||
currentHandler(undefined, { message: 'nope' });
|
||||
},
|
||||
timeout: 1
|
||||
};
|
||||
const onException = jasmine.createSpy('onException');
|
||||
const globalErrors = {
|
||||
pushListener: jasmine.createSpy('pushListener'),
|
||||
popListener: jasmine.createSpy('popListener')
|
||||
};
|
||||
const queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
onException: onException,
|
||||
globalErrors: globalErrors
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
|
||||
expect(onException).toHaveBeenCalledWith('nope');
|
||||
});
|
||||
|
||||
it('handles exceptions thrown while waiting for the stack to clear', function() {
|
||||
const queueableFn = {
|
||||
fn: function(done) {
|
||||
@@ -492,6 +518,40 @@ describe('QueueRunner', function() {
|
||||
clearStack.calls.argsFor(0)[0]();
|
||||
expect(onException).toHaveBeenCalledWith(error);
|
||||
});
|
||||
|
||||
it('handles a global error event with no error while waiting for the stack to clear', function() {
|
||||
const queueableFn = {
|
||||
fn: function(done) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
const errorListeners = [];
|
||||
const globalErrors = {
|
||||
pushListener: function(f) {
|
||||
errorListeners.push(f);
|
||||
},
|
||||
popListener: function() {
|
||||
errorListeners.pop();
|
||||
}
|
||||
};
|
||||
const clearStack = jasmine.createSpy('clearStack');
|
||||
const onException = jasmine.createSpy('onException');
|
||||
const queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
globalErrors: globalErrors,
|
||||
clearStack: clearStack,
|
||||
onException: onException
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
jasmine.clock().tick();
|
||||
expect(clearStack).toHaveBeenCalled();
|
||||
expect(errorListeners.length).toEqual(1);
|
||||
errorListeners[0](undefined, { message: 'nope' });
|
||||
|
||||
clearStack.calls.argsFor(0)[0]();
|
||||
expect(onException).toHaveBeenCalledWith('nope');
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a function that returns a promise', function() {
|
||||
|
||||
@@ -179,7 +179,10 @@ describe('base helpers', function() {
|
||||
f2 = jasmine.createSpy('setTimeout callback for ' + (max + 1));
|
||||
|
||||
// Suppress printing of TimeoutOverflowWarning in node
|
||||
spyOn(console, 'error');
|
||||
if (typeof process !== 'undefined' && process.emitWarning) {
|
||||
spyOn(process, 'emitWarning'); // Node 22
|
||||
}
|
||||
spyOn(console, 'error'); // Node <22
|
||||
|
||||
let id = setTimeout(f1, max);
|
||||
setTimeout(function() {
|
||||
|
||||
@@ -15,6 +15,17 @@ describe('toHaveSize', function() {
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
|
||||
it('informs about the size of an array whose length does not match', function() {
|
||||
const matcher = jasmineUnderTest.matchers.toHaveSize({
|
||||
pp: jasmineUnderTest.makePrettyPrinter()
|
||||
}),
|
||||
result = matcher.compare([1, 2, 3], 2);
|
||||
|
||||
expect(result.message()).toEqual(
|
||||
'Expected [ 1, 2, 3 ] with size 3 to have size 2.'
|
||||
);
|
||||
});
|
||||
|
||||
it('passes for an object with the proper number of keys', function() {
|
||||
const matcher = jasmineUnderTest.matchers.toHaveSize(),
|
||||
result = matcher.compare({ a: 1, b: 2 }, 2);
|
||||
|
||||
@@ -16,19 +16,24 @@ getJasmineRequireObj().Expectation = function(j$) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add some context for an {@link expect}
|
||||
* Add some context to be included in matcher failures for an
|
||||
* {@link expect|expectation}, so that it can be more easily distinguished
|
||||
* from similar expectations.
|
||||
* @function
|
||||
* @name matchers#withContext
|
||||
* @since 3.3.0
|
||||
* @param {String} message - Additional context to show when the matcher fails
|
||||
* @return {matchers}
|
||||
* @example
|
||||
* expect(things[0]).withContext('thing 0').toEqual('a');
|
||||
* expect(things[1]).withContext('thing 1').toEqual('b');
|
||||
*/
|
||||
Expectation.prototype.withContext = function withContext(message) {
|
||||
return addFilter(this, new ContextAddingFilter(message));
|
||||
};
|
||||
|
||||
/**
|
||||
* Invert the matcher following this {@link expect}
|
||||
* Invert the matcher following this {@link expect|expectation}
|
||||
* @member
|
||||
* @name matchers#not
|
||||
* @since 1.3.0
|
||||
|
||||
@@ -12,6 +12,7 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
||||
|
||||
function dispatchBrowserError(error, event) {
|
||||
if (overrideHandler) {
|
||||
// See discussion of spyOnGlobalErrorsAsync in base.js
|
||||
overrideHandler(error);
|
||||
return;
|
||||
}
|
||||
@@ -55,6 +56,7 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
||||
const handler = handlers[handlers.length - 1];
|
||||
|
||||
if (overrideHandler) {
|
||||
// See discussion of spyOnGlobalErrorsAsync in base.js
|
||||
overrideHandler(error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -65,8 +65,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
}
|
||||
|
||||
QueueRunner.prototype.execute = function() {
|
||||
this.handleFinalError = error => {
|
||||
this.onException(error);
|
||||
this.handleFinalError = (error, event) => {
|
||||
this.onException(errorOrMsgForGlobalError(error, event));
|
||||
};
|
||||
this.globalErrors.pushListener(this.handleFinalError);
|
||||
this.run(0);
|
||||
@@ -96,10 +96,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
this.recordError_(iterativeIndex);
|
||||
};
|
||||
|
||||
function handleError(error) {
|
||||
// TODO probably shouldn't next() right away here.
|
||||
// That makes debugging async failures much more confusing.
|
||||
onException(error);
|
||||
function handleError(error, event) {
|
||||
onException(errorOrMsgForGlobalError(error, event));
|
||||
}
|
||||
const cleanup = once(() => {
|
||||
if (timeoutId !== void 0) {
|
||||
@@ -285,5 +283,16 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
};
|
||||
}
|
||||
|
||||
function errorOrMsgForGlobalError(error, event) {
|
||||
// TODO: In cases where error is a string or undefined, the error message
|
||||
// that gets sent to reporters will be `${message} thrown`, which could
|
||||
// be improved to not say "thrown" when the cause wasn't necessarily
|
||||
// an exception or to provide hints about throwing Errors rather than
|
||||
// strings.
|
||||
return (
|
||||
error || (event && event.message) || 'Global error event with no message'
|
||||
);
|
||||
}
|
||||
|
||||
return QueueRunner;
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ getJasmineRequireObj().StackTrace = function(j$) {
|
||||
// e.g. " at /some/path:4320:20
|
||||
{ re: /\s*at (.+)$/, fileLineColIx: 1, style: 'v8' },
|
||||
|
||||
// PhantomJS on OS X, Safari, Firefox
|
||||
// Safari, most Firefox stack frames
|
||||
// e.g. "run@http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||
// or "http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||
{
|
||||
@@ -40,6 +40,15 @@ getJasmineRequireObj().StackTrace = function(j$) {
|
||||
fnIx: 2,
|
||||
fileLineColIx: 3,
|
||||
style: 'webkit'
|
||||
},
|
||||
|
||||
// Some Firefox stack frames when the developer tools are open
|
||||
// e.g. "promise callback*specStarted@http://localhost:8888/__jasmine__/jasmine.js:1880:41"
|
||||
{
|
||||
re: /^^(?:((?:promise callback|[^\s]+ handler)\*([^@\s]+)@)|@)?([^\s]+)$/,
|
||||
fnIx: 2,
|
||||
fileLineColIx: 3,
|
||||
style: 'webkit'
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
119
src/core/base.js
119
src/core/base.js
@@ -224,9 +224,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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.
|
||||
* @name jasmine.any
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared is an instance of the specified class/constructor.
|
||||
* @name asymmetricEqualityTesters.any
|
||||
* @emittedName jasmine.any
|
||||
* @since 1.3.0
|
||||
* @function
|
||||
* @param {Constructor} clazz - The constructor to check against.
|
||||
@@ -236,9 +237,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 not `null` and not `undefined`.
|
||||
* @name jasmine.anything
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared is not `null` and not `undefined`.
|
||||
* @name asymmetricEqualityTesters.anything
|
||||
* @emittedName jasmine.anything
|
||||
* @since 2.2.0
|
||||
* @function
|
||||
*/
|
||||
@@ -247,9 +249,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 `true` or anything truthy.
|
||||
* @name jasmine.truthy
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared is `true` or anything truthy.
|
||||
* @name asymmetricEqualityTesters.truthy
|
||||
* @emittedName jasmine.truthy
|
||||
* @since 3.1.0
|
||||
* @function
|
||||
*/
|
||||
@@ -258,9 +261,11 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 `null`, `undefined`, `0`, `false` or anything falsey.
|
||||
* @name jasmine.falsy
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared is `null`, `undefined`, `0`, `false` or anything
|
||||
* falsy.
|
||||
* @name asymmetricEqualityTesters.falsy
|
||||
* @emittedName jasmine.falsy
|
||||
* @since 3.1.0
|
||||
* @function
|
||||
*/
|
||||
@@ -269,9 +274,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 empty.
|
||||
* @name jasmine.empty
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared is empty.
|
||||
* @name asymmetricEqualityTesters.empty
|
||||
* @emittedName jasmine.empty
|
||||
* @since 3.1.0
|
||||
* @function
|
||||
*/
|
||||
@@ -280,10 +286,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher}
|
||||
* that passes if the actual value is the same as the sample as determined
|
||||
* by the `===` operator.
|
||||
* @name jasmine.is
|
||||
* Get an {@link AsymmetricEqualityTester} that passes if the actual value is
|
||||
* the same as the sample as determined by the `===` operator.
|
||||
* @name asymmetricEqualityTesters.is
|
||||
* @emittedName jasmine.is
|
||||
* @function
|
||||
* @param {Object} sample - The value to compare the actual to.
|
||||
*/
|
||||
@@ -292,9 +298,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 not empty.
|
||||
* @name jasmine.notEmpty
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared is not empty.
|
||||
* @name asymmetricEqualityTesters.notEmpty
|
||||
* @emittedName jasmine.notEmpty
|
||||
* @since 3.1.0
|
||||
* @function
|
||||
*/
|
||||
@@ -303,9 +310,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 contains at least the keys and values.
|
||||
* @name jasmine.objectContaining
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value being compared contains at least the specified keys and values.
|
||||
* @name asymmetricEqualityTesters.objectContaining
|
||||
* @emittedName jasmine.objectContaining
|
||||
* @since 1.3.0
|
||||
* @function
|
||||
* @param {Object} sample - The subset of properties that _must_ be in the actual.
|
||||
@@ -315,9 +323,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 is a `String` that matches the `RegExp` or `String`.
|
||||
* @name jasmine.stringMatching
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value is a `String` that matches the `RegExp` or `String`.
|
||||
* @name asymmetricEqualityTesters.stringMatching
|
||||
* @emittedName jasmine.stringMatching
|
||||
* @since 2.2.0
|
||||
* @function
|
||||
* @param {RegExp|String} expected
|
||||
@@ -327,9 +336,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 is a `String` that contains the specified `String`.
|
||||
* @name jasmine.stringContaining
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value is a `String` that contains the specified `String`.
|
||||
* @name asymmetricEqualityTesters.stringContaining
|
||||
* @emittedName jasmine.stringContaining
|
||||
* @since 3.10.0
|
||||
* @function
|
||||
* @param {String} expected
|
||||
@@ -339,9 +349,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 is an `Array` that contains at least the elements in the sample.
|
||||
* @name jasmine.arrayContaining
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value is an `Array` that contains at least the elements in the sample.
|
||||
* @name asymmetricEqualityTesters.arrayContaining
|
||||
* @emittedName jasmine.arrayContaining
|
||||
* @since 2.2.0
|
||||
* @function
|
||||
* @param {Array} sample
|
||||
@@ -351,9 +362,11 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 is an `Array` that contains all of the elements in the sample in any order.
|
||||
* @name jasmine.arrayWithExactContents
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||
* value is an `Array` that contains all of the elements in the sample in
|
||||
* any order.
|
||||
* @name asymmetricEqualityTesters.arrayWithExactContents
|
||||
* @emittedName jasmine.arrayWithExactContents
|
||||
* @since 2.8.0
|
||||
* @function
|
||||
* @param {Array} sample
|
||||
@@ -363,10 +376,11 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 every key/value pair in the sample passes the deep equality comparison
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if every
|
||||
* key/value pair in the sample passes the deep equality comparison
|
||||
* with at least one key/value pair in the actual value being compared
|
||||
* @name jasmine.mapContaining
|
||||
* @name asymmetricEqualityTesters.mapContaining
|
||||
* @emittedName jasmine.mapContaining
|
||||
* @since 3.5.0
|
||||
* @function
|
||||
* @param {Map} sample - The subset of items that _must_ be in the actual.
|
||||
@@ -376,10 +390,11 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an {@link AsymmetricEqualityTester}, 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 every item in the sample passes the deep equality comparison
|
||||
* Get an {@link AsymmetricEqualityTester} that will succeed if every item
|
||||
* in the sample passes the deep equality comparison
|
||||
* with at least one item in the actual value being compared
|
||||
* @name jasmine.setContaining
|
||||
* @name asymmetricEqualityTesters.setContaining
|
||||
* @emittedName jasmine.setContaining
|
||||
* @since 3.5.0
|
||||
* @function
|
||||
* @param {Set} sample - The subset of items that _must_ be in the actual.
|
||||
@@ -435,14 +450,26 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
||||
* handling will be restored when the promise returned from the callback is
|
||||
* settled.
|
||||
*
|
||||
* When the JavaScript runtime reports an uncaught error or unhandled rejection,
|
||||
* the spy will be called with a single parameter representing Jasmine's best
|
||||
* effort at describing the error. This parameter may be of any type, because
|
||||
* JavaScript allows anything to be thrown or used as the reason for a
|
||||
* rejected promise, but Error instances and strings are most common.
|
||||
*
|
||||
* Note: The JavaScript runtime may deliver uncaught error events and unhandled
|
||||
* rejection events asynchronously, especially in browsers. If the event
|
||||
* occurs after the promise returned from the callback is settled, it won't
|
||||
* be routed to the spy even if the underlying error occurred previously.
|
||||
* It's up to you to ensure that the returned promise isn't resolved until
|
||||
* all of the error/rejection events that you want to handle have occurred.
|
||||
* It's up to you to ensure that all of the error/rejection events that you
|
||||
* want to handle have occurred before you resolve the promise returned from
|
||||
* the callback.
|
||||
*
|
||||
* You must await the return value of spyOnGlobalErrorsAsync.
|
||||
* You must ensure that the `it`/`beforeEach`/etc fn that called
|
||||
* `spyOnGlobalErrorsAsync` does not signal completion until after the
|
||||
* promise returned by `spyOnGlobalErrorsAsync` is resolved. Normally this is
|
||||
* done by `await`ing the returned promise. Leaving the global error spy
|
||||
* installed after the `it`/`beforeEach`/etc fn that installed it signals
|
||||
* completion is likely to cause problems and is not supported.
|
||||
* @name jasmine.spyOnGlobalErrorsAsync
|
||||
* @function
|
||||
* @async
|
||||
|
||||
@@ -9,7 +9,7 @@ getJasmineRequireObj().toHaveSize = function(j$) {
|
||||
* array = [1,2];
|
||||
* expect(array).toHaveSize(2);
|
||||
*/
|
||||
function toHaveSize() {
|
||||
function toHaveSize(matchersUtil) {
|
||||
return {
|
||||
compare: function(actual, expected) {
|
||||
const result = {
|
||||
@@ -24,12 +24,29 @@ getJasmineRequireObj().toHaveSize = function(j$) {
|
||||
throw new Error('Cannot get size of ' + actual + '.');
|
||||
}
|
||||
|
||||
let actualSize;
|
||||
if (j$.isSet(actual) || j$.isMap(actual)) {
|
||||
result.pass = actual.size === expected;
|
||||
actualSize = actual.size;
|
||||
} else if (isLength(actual.length)) {
|
||||
result.pass = actual.length === expected;
|
||||
actualSize = actual.length;
|
||||
} else {
|
||||
result.pass = Object.keys(actual).length === expected;
|
||||
actualSize = Object.keys(actual).length;
|
||||
}
|
||||
|
||||
result.pass = actualSize === expected;
|
||||
|
||||
if (!result.pass) {
|
||||
result.message = function() {
|
||||
return (
|
||||
'Expected ' +
|
||||
matchersUtil.pp(actual) +
|
||||
' with size ' +
|
||||
actualSize +
|
||||
' to have size ' +
|
||||
expected +
|
||||
'.'
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -345,6 +345,12 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
}),
|
||||
|
||||
/**
|
||||
* <p>Members of the jasmine global.</p>
|
||||
* <p>Note: The members of the
|
||||
* {@link asymmetricEqualityTesters|asymmetricEqualityTesters namespace}
|
||||
* are also accessed via the jasmine global, but due to jsdoc limitations
|
||||
* they are not listed here.</p>
|
||||
*
|
||||
* @namespace jasmine
|
||||
*/
|
||||
jasmine: jasmine
|
||||
@@ -478,5 +484,27 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
||||
return env.setDefaultSpyStrategy(defaultStrategyFn);
|
||||
};
|
||||
|
||||
/**
|
||||
* {@link AsymmetricEqualityTester|Asymmetric equality testers} allow for
|
||||
* non-exact matching in matchers that use Jasmine's deep value equality
|
||||
* semantics, such as {@link matchers#toEqual|toEqual},
|
||||
* {@link matchers#toContain|toContain}, and
|
||||
* {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}.
|
||||
*
|
||||
* @example
|
||||
* const someComplexObject = {
|
||||
* foo: 'bar',
|
||||
* baz: 'a string that contains "something"',
|
||||
* qux: 'whatever'
|
||||
* };
|
||||
* // Passes.
|
||||
* expect(someComplexObject).toEqual(jasmine.objectContaining({
|
||||
* foo: 'bar',
|
||||
* baz: jasmine.stringContaining('something')
|
||||
* });
|
||||
*
|
||||
* @namespace asymmetricEqualityTesters
|
||||
*/
|
||||
|
||||
return jasmineInterface;
|
||||
};
|
||||
|
||||
@@ -430,7 +430,11 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
'tr',
|
||||
{},
|
||||
createDom('td', {}, entry.timestamp.toString()),
|
||||
createDom('td', {}, entry.message)
|
||||
createDom(
|
||||
'td',
|
||||
{ className: 'jasmine-debug-log-msg' },
|
||||
entry.message
|
||||
)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -424,5 +424,9 @@ body {
|
||||
table, th, td {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.jasmine-debug-log-msg {
|
||||
white-space: pre;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user