Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8c3325b56 | ||
|
|
84c7e2b21b | ||
|
|
dda25bb29e | ||
|
|
9ccf2ef96b | ||
|
|
c6fa55bfc8 | ||
|
|
06bcf1c2e1 | ||
|
|
40f402d117 | ||
|
|
71f6a95ce5 | ||
|
|
5cd7d47f72 | ||
|
|
d0fe5c4712 | ||
|
|
f602c4911c | ||
|
|
7aaf7eaf30 | ||
|
|
35f16e8125 | ||
|
|
acc777c267 | ||
|
|
1c74356691 | ||
|
|
bbebea0fa5 | ||
|
|
66eb27b0af | ||
|
|
7a63c06a65 | ||
|
|
554dfd4923 | ||
|
|
36a6e2aa1d | ||
|
|
3c4b73f136 | ||
|
|
bc3ed74336 | ||
|
|
97b6f33cc2 | ||
|
|
a9889ddb31 | ||
|
|
cd1b7ce9c7 | ||
|
|
3653d6e0ef | ||
|
|
c3387f8dbf | ||
|
|
3d54184c7f | ||
|
|
6f23e706d7 | ||
|
|
cc69edf92c | ||
|
|
ba7560f65e | ||
|
|
c3960c4a96 | ||
|
|
5c21f94bb1 | ||
|
|
8cd7c94490 | ||
|
|
6a6fa7b29a | ||
|
|
4984548cab | ||
|
|
6941bde7e2 | ||
|
|
1504f25ced | ||
|
|
99e350ac85 | ||
|
|
1624b07589 |
@@ -4,6 +4,10 @@
|
|||||||
version: 2.1
|
version: 2.1
|
||||||
|
|
||||||
executors:
|
executors:
|
||||||
|
node22:
|
||||||
|
docker:
|
||||||
|
- image: cimg/node:22.0.0
|
||||||
|
working_directory: ~/workspace
|
||||||
node20:
|
node20:
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/node:20.0.0
|
- image: cimg/node:20.0.0
|
||||||
@@ -94,12 +98,20 @@ workflows:
|
|||||||
|
|
||||||
push:
|
push:
|
||||||
jobs:
|
jobs:
|
||||||
|
- build:
|
||||||
|
executor: node22
|
||||||
|
name: build_node_22
|
||||||
- build:
|
- build:
|
||||||
executor: node20
|
executor: node20
|
||||||
name: build_node_20
|
name: build_node_20
|
||||||
- build:
|
- build:
|
||||||
executor: node18
|
executor: node18
|
||||||
name: build_node_18
|
name: build_node_18
|
||||||
|
- test_node:
|
||||||
|
executor: node22
|
||||||
|
name: test_node_22
|
||||||
|
requires:
|
||||||
|
- build_node_22
|
||||||
- test_node:
|
- test_node:
|
||||||
executor: node20
|
executor: node20
|
||||||
name: test_node_20
|
name: test_node_20
|
||||||
@@ -115,6 +127,11 @@ workflows:
|
|||||||
name: test_parallel_node_18
|
name: test_parallel_node_18
|
||||||
requires:
|
requires:
|
||||||
- build_node_18
|
- build_node_18
|
||||||
|
- test_parallel:
|
||||||
|
executor: node22
|
||||||
|
name: test_parallel_node_22
|
||||||
|
requires:
|
||||||
|
- build_node_22
|
||||||
- test_parallel:
|
- test_parallel:
|
||||||
executor: node20
|
executor: node20
|
||||||
name: test_parallel_node_20
|
name: test_parallel_node_20
|
||||||
|
|||||||
47
.eslintrc
Normal file
47
.eslintrc
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"extends": [
|
||||||
|
"plugin:compat/recommended"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"node": true,
|
||||||
|
"es2017": true
|
||||||
|
},
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 2018
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"curly": "error",
|
||||||
|
"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
|
||||||
|
}
|
||||||
18
README.md
18
README.md
@@ -27,18 +27,22 @@ for information on writing specs, and [the FAQ](https://jasmine.github.io/pages/
|
|||||||
Jasmine tests itself across popular browsers (Safari, Chrome, Firefox, and
|
Jasmine tests itself across popular browsers (Safari, Chrome, Firefox, and
|
||||||
Microsoft Edge) as well as Node.
|
Microsoft Edge) as well as Node.
|
||||||
|
|
||||||
| Environment | Supported versions |
|
| Environment | Supported versions |
|
||||||
|-------------------|---------------------|
|
|-------------------|----------------------------|
|
||||||
| Node | 18, 20 |
|
| Node | 18, 20, 22 |
|
||||||
| Safari | 15-17 |
|
| Safari | 15-17 |
|
||||||
| Chrome | Evergreen |
|
| Chrome | Evergreen |
|
||||||
| Firefox | Evergreen, 102, 115 |
|
| Firefox | Evergreen, 102*, 115*, 128 |
|
||||||
| Edge | Evergreen |
|
| Edge | Evergreen |
|
||||||
|
|
||||||
For evergreen browsers, each version of Jasmine is tested against the version of the browser that is available to us
|
For evergreen browsers, each version of Jasmine is tested against the version of the browser that is available to us
|
||||||
at the time of release. Other browsers, as well as older & newer versions of some supported browsers, are likely to work.
|
at the time of release. Other browsers, as well as older & newer versions of some supported browsers, are likely to work.
|
||||||
However, Jasmine isn't tested against them and they aren't actively supported.
|
However, Jasmine isn't tested against them and they aren't actively supported.
|
||||||
|
|
||||||
|
\* Environments that are past end of life are supported on a best-effort basis.
|
||||||
|
They may be dropped in a future minor release of Jasmine if continued support
|
||||||
|
becomes impractical.
|
||||||
|
|
||||||
To find out what environments work with a particular Jasmine release, see the [release notes](https://github.com/jasmine/jasmine/tree/main/release_notes).
|
To find out what environments work with a particular Jasmine release, see the [release notes](https://github.com/jasmine/jasmine/tree/main/release_notes).
|
||||||
|
|
||||||
## Maintainers
|
## Maintainers
|
||||||
|
|||||||
@@ -463,7 +463,11 @@ jasmineRequire.HtmlReporter = function(j$) {
|
|||||||
'tr',
|
'tr',
|
||||||
{},
|
{},
|
||||||
createDom('td', {}, entry.timestamp.toString()),
|
createDom('td', {}, entry.timestamp.toString()),
|
||||||
createDom('td', {}, entry.message)
|
createDom(
|
||||||
|
'td',
|
||||||
|
{ className: 'jasmine-debug-log-msg' },
|
||||||
|
entry.message
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -296,3 +296,6 @@ body {
|
|||||||
.jasmine_html-reporter .jasmine-debug-log table, .jasmine_html-reporter .jasmine-debug-log th, .jasmine_html-reporter .jasmine-debug-log td {
|
.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;
|
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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared is an instance of the specified class/constructor.
|
* value being compared is an instance of the specified class/constructor.
|
||||||
* @name jasmine.any
|
* @name asymmetricEqualityTesters.any
|
||||||
|
* @emittedName jasmine.any
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
* @function
|
* @function
|
||||||
* @param {Constructor} clazz - The constructor to check against.
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared is not `null` and not `undefined`.
|
* value being compared is not `null` and not `undefined`.
|
||||||
* @name jasmine.anything
|
* @name asymmetricEqualityTesters.anything
|
||||||
|
* @emittedName jasmine.anything
|
||||||
* @since 2.2.0
|
* @since 2.2.0
|
||||||
* @function
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared is `true` or anything truthy.
|
* value being compared is `true` or anything truthy.
|
||||||
* @name jasmine.truthy
|
* @name asymmetricEqualityTesters.truthy
|
||||||
|
* @emittedName jasmine.truthy
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
* @function
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared is `null`, `undefined`, `0`, `false` or anything falsey.
|
* value being compared is `null`, `undefined`, `0`, `false` or anything
|
||||||
* @name jasmine.falsy
|
* falsy.
|
||||||
|
* @name asymmetricEqualityTesters.falsy
|
||||||
|
* @emittedName jasmine.falsy
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
* @function
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared is empty.
|
* value being compared is empty.
|
||||||
* @name jasmine.empty
|
* @name asymmetricEqualityTesters.empty
|
||||||
|
* @emittedName jasmine.empty
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
@@ -456,10 +462,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher}
|
* Get an {@link AsymmetricEqualityTester} that passes if the actual value is
|
||||||
* that passes if the actual value is the same as the sample as determined
|
* the same as the sample as determined by the `===` operator.
|
||||||
* by the `===` operator.
|
* @name asymmetricEqualityTesters.is
|
||||||
* @name jasmine.is
|
* @emittedName jasmine.is
|
||||||
* @function
|
* @function
|
||||||
* @param {Object} sample - The value to compare the actual to.
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared is not empty.
|
* value being compared is not empty.
|
||||||
* @name jasmine.notEmpty
|
* @name asymmetricEqualityTesters.notEmpty
|
||||||
|
* @emittedName jasmine.notEmpty
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
* @function
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared contains at least the keys and values.
|
* value being compared contains at least the specified keys and values.
|
||||||
* @name jasmine.objectContaining
|
* @name asymmetricEqualityTesters.objectContaining
|
||||||
|
* @emittedName jasmine.objectContaining
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
* @function
|
* @function
|
||||||
* @param {Object} sample - The subset of properties that _must_ be in the actual.
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value is a `String` that matches the `RegExp` or `String`.
|
* value is a `String` that matches the `RegExp` or `String`.
|
||||||
* @name jasmine.stringMatching
|
* @name asymmetricEqualityTesters.stringMatching
|
||||||
|
* @emittedName jasmine.stringMatching
|
||||||
* @since 2.2.0
|
* @since 2.2.0
|
||||||
* @function
|
* @function
|
||||||
* @param {RegExp|String} expected
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value is a `String` that contains the specified `String`.
|
* value is a `String` that contains the specified `String`.
|
||||||
* @name jasmine.stringContaining
|
* @name asymmetricEqualityTesters.stringContaining
|
||||||
|
* @emittedName jasmine.stringContaining
|
||||||
* @since 3.10.0
|
* @since 3.10.0
|
||||||
* @function
|
* @function
|
||||||
* @param {String} expected
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value is an `Array` that contains at least the elements in the sample.
|
* value is an `Array` that contains at least the elements in the sample.
|
||||||
* @name jasmine.arrayContaining
|
* @name asymmetricEqualityTesters.arrayContaining
|
||||||
|
* @emittedName jasmine.arrayContaining
|
||||||
* @since 2.2.0
|
* @since 2.2.0
|
||||||
* @function
|
* @function
|
||||||
* @param {Array} sample
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value is an `Array` that contains all of the elements in the sample in any order.
|
* value is an `Array` that contains all of the elements in the sample in
|
||||||
* @name jasmine.arrayWithExactContents
|
* any order.
|
||||||
|
* @name asymmetricEqualityTesters.arrayWithExactContents
|
||||||
|
* @emittedName jasmine.arrayWithExactContents
|
||||||
* @since 2.8.0
|
* @since 2.8.0
|
||||||
* @function
|
* @function
|
||||||
* @param {Array} sample
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if every
|
||||||
* that will succeed if every key/value pair in the sample passes the deep equality comparison
|
* key/value pair in the sample passes the deep equality comparison
|
||||||
* with at least one key/value pair in the actual value being compared
|
* 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
|
* @since 3.5.0
|
||||||
* @function
|
* @function
|
||||||
* @param {Map} sample - The subset of items that _must_ be in the actual.
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if every item
|
||||||
* that will succeed if every item in the sample passes the deep equality comparison
|
* in the sample passes the deep equality comparison
|
||||||
* with at least one item in the actual value being compared
|
* with at least one item in the actual value being compared
|
||||||
* @name jasmine.setContaining
|
* @name asymmetricEqualityTesters.setContaining
|
||||||
|
* @emittedName jasmine.setContaining
|
||||||
* @since 3.5.0
|
* @since 3.5.0
|
||||||
* @function
|
* @function
|
||||||
* @param {Set} sample - The subset of items that _must_ be in the actual.
|
* @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
|
* handling will be restored when the promise returned from the callback is
|
||||||
* settled.
|
* 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
|
* Note: The JavaScript runtime may deliver uncaught error events and unhandled
|
||||||
* rejection events asynchronously, especially in browsers. If the event
|
* rejection events asynchronously, especially in browsers. If the event
|
||||||
* occurs after the promise returned from the callback is settled, it won't
|
* 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.
|
* 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
|
* It's up to you to ensure that all of the error/rejection events that you
|
||||||
* all of the error/rejection events that you want to handle have occurred.
|
* 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
|
* @name jasmine.spyOnGlobalErrorsAsync
|
||||||
* @function
|
* @function
|
||||||
* @async
|
* @async
|
||||||
@@ -888,9 +915,9 @@ getJasmineRequireObj().Spec = function(j$) {
|
|||||||
* @property {String} fullName - The full description including all ancestors of this spec.
|
* @property {String} fullName - The full description including all ancestors of this spec.
|
||||||
* @property {String|null} parentSuiteId - The ID of the suite containing this spec, or null if this spec is not in a describe().
|
* @property {String|null} parentSuiteId - The ID of the suite containing this spec, or null if this spec is not in a describe().
|
||||||
* @property {String} filename - The name of the file the spec was defined in.
|
* @property {String} filename - The name of the file the spec was defined in.
|
||||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed during execution of this spec.
|
* @property {ExpectationResult[]} failedExpectations - The list of expectations that failed during execution of this spec.
|
||||||
* @property {Expectation[]} passedExpectations - The list of expectations that passed during execution of this spec.
|
* @property {ExpectationResult[]} passedExpectations - The list of expectations that passed during execution of this spec.
|
||||||
* @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred during execution this spec.
|
* @property {ExpectationResult[]} deprecationWarnings - The list of deprecation warnings that occurred during execution this spec.
|
||||||
* @property {String} pendingReason - If the spec is {@link pending}, this will be the reason.
|
* @property {String} pendingReason - If the spec is {@link pending}, this will be the reason.
|
||||||
* @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec.
|
* @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec.
|
||||||
* @property {number} duration - The time in ms used by the spec execution, including any before/afterEach.
|
* @property {number} duration - The time in ms used by the spec execution, including any before/afterEach.
|
||||||
@@ -1402,12 +1429,19 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
* @extends Error
|
* @extends Error
|
||||||
* @description Represents a failure of an expectation evaluated with
|
* @description Represents a failure of an expectation evaluated with
|
||||||
* {@link throwUnless}. Properties of this error are a subset of the
|
* {@link throwUnless}. Properties of this error are a subset of the
|
||||||
* properties of {@link Expectation} and have the same values.
|
* properties of {@link ExpectationResult} and have the same values.
|
||||||
|
*
|
||||||
|
* Note: The expected and actual properties are deprecated and may be removed
|
||||||
|
* in a future release. In many Jasmine configurations they are passed
|
||||||
|
* through JSON serialization and deserialization, which is inherently
|
||||||
|
* lossy. In such cases, the expected and actual values may be placeholders
|
||||||
|
* or approximations of the original objects.
|
||||||
|
*
|
||||||
* @property {String} matcherName - The name of the matcher that was executed for this expectation.
|
* @property {String} matcherName - The name of the matcher that was executed for this expectation.
|
||||||
* @property {String} message - The failure message for the expectation.
|
* @property {String} message - The failure message for the expectation.
|
||||||
* @property {Boolean} passed - Whether the expectation passed or failed.
|
* @property {Boolean} passed - Whether the expectation passed or failed.
|
||||||
* @property {Object} expected - If the expectation failed, what was the expected value.
|
* @property {Object} expected - Deprecated. If the expectation failed, what was the expected value.
|
||||||
* @property {Object} actual - If the expectation failed, what actual value was produced.
|
* @property {Object} actual - Deprecated. If the expectation failed, what actual value was produced.
|
||||||
*/
|
*/
|
||||||
const error = new Error(result.message);
|
const error = new Error(result.message);
|
||||||
error.passed = result.passed;
|
error.passed = result.passed;
|
||||||
@@ -2403,7 +2437,9 @@ getJasmineRequireObj().MapContaining = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MapContaining.prototype.asymmetricMatch = function(other, matchersUtil) {
|
MapContaining.prototype.asymmetricMatch = function(other, matchersUtil) {
|
||||||
if (!j$.isMap(other)) return false;
|
if (!j$.isMap(other)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (const [key, value] of this.sample) {
|
for (const [key, value] of this.sample) {
|
||||||
// for each key/value pair in `sample`
|
// for each key/value pair in `sample`
|
||||||
@@ -2542,7 +2578,9 @@ getJasmineRequireObj().SetContaining = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetContaining.prototype.asymmetricMatch = function(other, matchersUtil) {
|
SetContaining.prototype.asymmetricMatch = function(other, matchersUtil) {
|
||||||
if (!j$.isSet(other)) return false;
|
if (!j$.isSet(other)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (const item of this.sample) {
|
for (const item of this.sample) {
|
||||||
// for each item in `sample` there should be at least one matching item in `other`
|
// for each item in `sample` there should be at least one matching item in `other`
|
||||||
@@ -2636,13 +2674,21 @@ getJasmineRequireObj().buildExpectationResult = function(j$) {
|
|||||||
const exceptionFormatter = new j$.ExceptionFormatter();
|
const exceptionFormatter = new j$.ExceptionFormatter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef Expectation
|
* Describes the result of evaluating an expectation
|
||||||
|
*
|
||||||
|
* Note: The expected and actual properties are deprecated and may be removed
|
||||||
|
* in a future release. In many Jasmine configurations they are passed
|
||||||
|
* through JSON serialization and deserialization, which is inherently
|
||||||
|
* lossy. In such cases, the expected and actual values may be placeholders
|
||||||
|
* or approximations of the original objects.
|
||||||
|
*
|
||||||
|
* @typedef ExpectationResult
|
||||||
* @property {String} matcherName - The name of the matcher that was executed for this expectation.
|
* @property {String} matcherName - The name of the matcher that was executed for this expectation.
|
||||||
* @property {String} message - The failure message for the expectation.
|
* @property {String} message - The failure message for the expectation.
|
||||||
* @property {String} stack - The stack trace for the failure if available.
|
* @property {String} stack - The stack trace for the failure if available.
|
||||||
* @property {Boolean} passed - Whether the expectation passed or failed.
|
* @property {Boolean} passed - Whether the expectation passed or failed.
|
||||||
* @property {Object} expected - If the expectation failed, what was the expected value.
|
* @property {Object} expected - Deprecated. If the expectation failed, what was the expected value.
|
||||||
* @property {Object} actual - If the expectation failed, what actual value was produced.
|
* @property {Object} actual - Deprecated. If the expectation failed, what actual value was produced.
|
||||||
* @property {String|undefined} globalErrorType - The type of an error that
|
* @property {String|undefined} globalErrorType - The type of an error that
|
||||||
* is reported on the top suite. Valid values are undefined, "afterAll",
|
* is reported on the top suite. Valid values are undefined, "afterAll",
|
||||||
* "load", "lateExpectation", and "lateError".
|
* "load", "lateExpectation", and "lateError".
|
||||||
@@ -2849,7 +2895,8 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
const maxInlineCallCount = 10;
|
const maxInlineCallCount = 10;
|
||||||
|
|
||||||
function browserQueueMicrotaskImpl(global) {
|
function browserQueueMicrotaskImpl(global) {
|
||||||
const { setTimeout, queueMicrotask } = global;
|
const unclampedSetTimeout = getUnclampedSetTimeout(global);
|
||||||
|
const { queueMicrotask } = global;
|
||||||
let currentCallCount = 0;
|
let currentCallCount = 0;
|
||||||
return function clearStack(fn) {
|
return function clearStack(fn) {
|
||||||
currentCallCount++;
|
currentCallCount++;
|
||||||
@@ -2858,7 +2905,7 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
queueMicrotask(fn);
|
queueMicrotask(fn);
|
||||||
} else {
|
} else {
|
||||||
currentCallCount = 0;
|
currentCallCount = 0;
|
||||||
setTimeout(fn);
|
unclampedSetTimeout(fn);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -2872,6 +2919,37 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function messageChannelImpl(global) {
|
function messageChannelImpl(global) {
|
||||||
|
const { setTimeout } = global;
|
||||||
|
const postMessage = getPostMessage(global);
|
||||||
|
|
||||||
|
let currentCallCount = 0;
|
||||||
|
return function clearStack(fn) {
|
||||||
|
currentCallCount++;
|
||||||
|
|
||||||
|
if (currentCallCount < maxInlineCallCount) {
|
||||||
|
postMessage(fn);
|
||||||
|
} else {
|
||||||
|
currentCallCount = 0;
|
||||||
|
setTimeout(fn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUnclampedSetTimeout(global) {
|
||||||
|
const { setTimeout } = global;
|
||||||
|
if (j$.util.isUndefined(global.MessageChannel)) {
|
||||||
|
return setTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
const postMessage = getPostMessage(global);
|
||||||
|
return function unclampedSetTimeout(fn) {
|
||||||
|
postMessage(function() {
|
||||||
|
setTimeout(fn);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPostMessage(global) {
|
||||||
const { MessageChannel, setTimeout } = global;
|
const { MessageChannel, setTimeout } = global;
|
||||||
const channel = new MessageChannel();
|
const channel = new MessageChannel();
|
||||||
let head = {};
|
let head = {};
|
||||||
@@ -2895,17 +2973,9 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let currentCallCount = 0;
|
return function postMessage(fn) {
|
||||||
return function clearStack(fn) {
|
tail = tail.next = { task: fn };
|
||||||
currentCallCount++;
|
channel.port2.postMessage(0);
|
||||||
|
|
||||||
if (currentCallCount < maxInlineCallCount) {
|
|
||||||
tail = tail.next = { task: fn };
|
|
||||||
channel.port2.postMessage(0);
|
|
||||||
} else {
|
|
||||||
currentCallCount = 0;
|
|
||||||
setTimeout(fn);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2915,20 +2985,25 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
global.process.versions &&
|
global.process.versions &&
|
||||||
typeof global.process.versions.node === 'string';
|
typeof global.process.versions.node === 'string';
|
||||||
|
|
||||||
const SAFARI =
|
// Windows builds of WebKit have a fairly generic user agent string when no application name is provided:
|
||||||
|
// e.g. "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/605.1.15 (KHTML, like Gecko)"
|
||||||
|
const SAFARI_OR_WIN_WEBKIT =
|
||||||
global.navigator &&
|
global.navigator &&
|
||||||
/^((?!chrome|android).)*safari/i.test(global.navigator.userAgent);
|
/(^((?!chrome|android).)*safari)|(Win64; x64\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\)$)/i.test(
|
||||||
|
global.navigator.userAgent
|
||||||
|
);
|
||||||
|
|
||||||
if (NODE_JS) {
|
if (NODE_JS) {
|
||||||
// Unlike browsers, Node doesn't require us to do a periodic setTimeout
|
// Unlike browsers, Node doesn't require us to do a periodic setTimeout
|
||||||
// so we avoid the overhead.
|
// so we avoid the overhead.
|
||||||
return nodeQueueMicrotaskImpl(global);
|
return nodeQueueMicrotaskImpl(global);
|
||||||
} else if (
|
} else if (
|
||||||
SAFARI ||
|
SAFARI_OR_WIN_WEBKIT ||
|
||||||
j$.util.isUndefined(global.MessageChannel) /* tests */
|
j$.util.isUndefined(global.MessageChannel) /* tests */
|
||||||
) {
|
) {
|
||||||
// queueMicrotask is dramatically faster than MessageChannel in Safari,
|
// queueMicrotask is dramatically faster than MessageChannel in Safari
|
||||||
// at least through version 16.
|
// and other WebKit-based browsers, such as the one distributed by Playwright
|
||||||
|
// to test Safari-like behavior on Windows.
|
||||||
// Some of our own integration tests provide a mock queueMicrotask in all
|
// Some of our own integration tests provide a mock queueMicrotask in all
|
||||||
// environments because it's simpler to mock than MessageChannel.
|
// environments because it's simpler to mock than MessageChannel.
|
||||||
return browserQueueMicrotaskImpl(global);
|
return browserQueueMicrotaskImpl(global);
|
||||||
@@ -3655,19 +3730,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
|
* @function
|
||||||
* @name matchers#withContext
|
* @name matchers#withContext
|
||||||
* @since 3.3.0
|
* @since 3.3.0
|
||||||
* @param {String} message - Additional context to show when the matcher fails
|
* @param {String} message - Additional context to show when the matcher fails
|
||||||
* @return {matchers}
|
* @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) {
|
Expectation.prototype.withContext = function withContext(message) {
|
||||||
return addFilter(this, new ContextAddingFilter(message));
|
return addFilter(this, new ContextAddingFilter(message));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invert the matcher following this {@link expect}
|
* Invert the matcher following this {@link expect|expectation}
|
||||||
* @member
|
* @member
|
||||||
* @name matchers#not
|
* @name matchers#not
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
@@ -4070,6 +4150,7 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
|||||||
|
|
||||||
function dispatchBrowserError(error, event) {
|
function dispatchBrowserError(error, event) {
|
||||||
if (overrideHandler) {
|
if (overrideHandler) {
|
||||||
|
// See discussion of spyOnGlobalErrorsAsync in base.js
|
||||||
overrideHandler(error);
|
overrideHandler(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -4113,6 +4194,7 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
|||||||
const handler = handlers[handlers.length - 1];
|
const handler = handlers[handlers.length - 1];
|
||||||
|
|
||||||
if (overrideHandler) {
|
if (overrideHandler) {
|
||||||
|
// See discussion of spyOnGlobalErrorsAsync in base.js
|
||||||
overrideHandler(error);
|
overrideHandler(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -6524,7 +6606,7 @@ getJasmineRequireObj().toHaveSize = function(j$) {
|
|||||||
* array = [1,2];
|
* array = [1,2];
|
||||||
* expect(array).toHaveSize(2);
|
* expect(array).toHaveSize(2);
|
||||||
*/
|
*/
|
||||||
function toHaveSize() {
|
function toHaveSize(matchersUtil) {
|
||||||
return {
|
return {
|
||||||
compare: function(actual, expected) {
|
compare: function(actual, expected) {
|
||||||
const result = {
|
const result = {
|
||||||
@@ -6539,12 +6621,29 @@ getJasmineRequireObj().toHaveSize = function(j$) {
|
|||||||
throw new Error('Cannot get size of ' + actual + '.');
|
throw new Error('Cannot get size of ' + actual + '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let actualSize;
|
||||||
if (j$.isSet(actual) || j$.isMap(actual)) {
|
if (j$.isSet(actual) || j$.isMap(actual)) {
|
||||||
result.pass = actual.size === expected;
|
actualSize = actual.size;
|
||||||
} else if (isLength(actual.length)) {
|
} else if (isLength(actual.length)) {
|
||||||
result.pass = actual.length === expected;
|
actualSize = actual.length;
|
||||||
} else {
|
} 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;
|
return result;
|
||||||
@@ -6599,7 +6698,10 @@ getJasmineRequireObj().toHaveSpyInteractions = function(j$) {
|
|||||||
let hasSpy = false;
|
let hasSpy = false;
|
||||||
const calledSpies = [];
|
const calledSpies = [];
|
||||||
for (const spy of Object.values(actual)) {
|
for (const spy of Object.values(actual)) {
|
||||||
if (!j$.isSpy(spy)) continue;
|
if (!j$.isSpy(spy)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
hasSpy = true;
|
hasSpy = true;
|
||||||
|
|
||||||
if (spy.calls.any()) {
|
if (spy.calls.any()) {
|
||||||
@@ -7684,8 +7786,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QueueRunner.prototype.execute = function() {
|
QueueRunner.prototype.execute = function() {
|
||||||
this.handleFinalError = error => {
|
this.handleFinalError = (error, event) => {
|
||||||
this.onException(error);
|
this.onException(errorOrMsgForGlobalError(error, event));
|
||||||
};
|
};
|
||||||
this.globalErrors.pushListener(this.handleFinalError);
|
this.globalErrors.pushListener(this.handleFinalError);
|
||||||
this.run(0);
|
this.run(0);
|
||||||
@@ -7715,10 +7817,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
|||||||
this.recordError_(iterativeIndex);
|
this.recordError_(iterativeIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
function handleError(error) {
|
function handleError(error, event) {
|
||||||
// TODO probably shouldn't next() right away here.
|
onException(errorOrMsgForGlobalError(error, event));
|
||||||
// That makes debugging async failures much more confusing.
|
|
||||||
onException(error);
|
|
||||||
}
|
}
|
||||||
const cleanup = once(() => {
|
const cleanup = once(() => {
|
||||||
if (timeoutId !== void 0) {
|
if (timeoutId !== void 0) {
|
||||||
@@ -7904,6 +8004,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;
|
return QueueRunner;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -7991,6 +8102,32 @@ getJasmineRequireObj().ReportDispatcher = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().reporterEvents = function() {
|
getJasmineRequireObj().reporterEvents = function() {
|
||||||
|
/**
|
||||||
|
* Used to tell Jasmine what optional or uncommonly implemented features
|
||||||
|
* the reporter supports. If not specified, the defaults described in
|
||||||
|
* {@link ReporterCapabilities} will apply.
|
||||||
|
* @name Reporter#reporterCapabilities
|
||||||
|
* @type ReporterCapabilities | undefined
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Used to tell Jasmine what optional or uncommonly implemented features
|
||||||
|
* the reporter supports.
|
||||||
|
* @interface ReporterCapabilities
|
||||||
|
* @see Reporter#reporterCapabilities
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Indicates whether the reporter supports parallel execution. Jasmine will
|
||||||
|
* not allow parallel execution unless all reporters that are in use set this
|
||||||
|
* capability to true.
|
||||||
|
* @name ReporterCapabilities#parallel
|
||||||
|
* @type boolean | undefined
|
||||||
|
* @default false
|
||||||
|
* @see running_specs_in_parallel
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
|
||||||
const events = [
|
const events = [
|
||||||
/**
|
/**
|
||||||
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
|
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
|
||||||
@@ -8408,6 +8545,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
|
* @namespace jasmine
|
||||||
*/
|
*/
|
||||||
jasmine: jasmine
|
jasmine: jasmine
|
||||||
@@ -8541,6 +8684,28 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
|||||||
return env.setDefaultSpyStrategy(defaultStrategyFn);
|
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;
|
return jasmineInterface;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -8879,8 +9044,8 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
* @property {String} incompleteCode - Machine-readable explanation of why the suite was incomplete: 'focused', 'noSpecsFound', or undefined.
|
* @property {String} incompleteCode - Machine-readable explanation of why the suite was incomplete: 'focused', 'noSpecsFound', or undefined.
|
||||||
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite. Note that this property is not present when Jasmine is run in parallel mode.
|
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite. Note that this property is not present when Jasmine is run in parallel mode.
|
||||||
* @property {Int} numWorkers - Number of parallel workers. Note that this property is only present when Jasmine is run in parallel mode.
|
* @property {Int} numWorkers - Number of parallel workers. Note that this property is only present when Jasmine is run in parallel mode.
|
||||||
* @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
|
* @property {ExpectationResult[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
|
||||||
* @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level.
|
* @property {ExpectationResult[]} deprecationWarnings - List of deprecation warnings that occurred at the global level.
|
||||||
* @since 2.4.0
|
* @since 2.4.0
|
||||||
*/
|
*/
|
||||||
const jasmineDoneInfo = {
|
const jasmineDoneInfo = {
|
||||||
@@ -9361,6 +9526,16 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
|||||||
|
|
||||||
obj[methodName] = spiedMethod;
|
obj[methodName] = spiedMethod;
|
||||||
|
|
||||||
|
// Check if setting the property actually worked. Some objects, such as
|
||||||
|
// localStorage in Firefox and later Safari versions, have no-op setters.
|
||||||
|
if (obj[methodName] !== spiedMethod) {
|
||||||
|
throw new Error(
|
||||||
|
j$.formatErrorMsg('<spyOn>')(
|
||||||
|
`Can't spy on ${methodName} because assigning to it had no effect`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return spiedMethod;
|
return spiedMethod;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -9714,9 +9889,7 @@ getJasmineRequireObj().SpyStrategy = function(j$) {
|
|||||||
|
|
||||||
getJasmineRequireObj().StackTrace = function(j$) {
|
getJasmineRequireObj().StackTrace = function(j$) {
|
||||||
function StackTrace(error) {
|
function StackTrace(error) {
|
||||||
let lines = error.stack.split('\n').filter(function(line) {
|
let lines = error.stack.split('\n');
|
||||||
return line !== '';
|
|
||||||
});
|
|
||||||
|
|
||||||
const extractResult = extractMessage(error.message, lines);
|
const extractResult = extractMessage(error.message, lines);
|
||||||
|
|
||||||
@@ -9725,6 +9898,10 @@ getJasmineRequireObj().StackTrace = function(j$) {
|
|||||||
lines = extractResult.remainder;
|
lines = extractResult.remainder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lines = lines.filter(function(line) {
|
||||||
|
return line !== '';
|
||||||
|
});
|
||||||
|
|
||||||
const parseResult = tryParseFrames(lines);
|
const parseResult = tryParseFrames(lines);
|
||||||
this.frames = parseResult.frames;
|
this.frames = parseResult.frames;
|
||||||
this.style = parseResult.style;
|
this.style = parseResult.style;
|
||||||
@@ -9746,7 +9923,7 @@ getJasmineRequireObj().StackTrace = function(j$) {
|
|||||||
// e.g. " at /some/path:4320:20
|
// e.g. " at /some/path:4320:20
|
||||||
{ re: /\s*at (.+)$/, fileLineColIx: 1, style: 'v8' },
|
{ 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"
|
// e.g. "run@http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||||
// or "http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
// or "http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||||
{
|
{
|
||||||
@@ -9754,6 +9931,15 @@ getJasmineRequireObj().StackTrace = function(j$) {
|
|||||||
fnIx: 2,
|
fnIx: 2,
|
||||||
fileLineColIx: 3,
|
fileLineColIx: 3,
|
||||||
style: 'webkit'
|
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'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -9940,8 +10126,8 @@ getJasmineRequireObj().Suite = function(j$) {
|
|||||||
* @property {String} fullName - The full description including all ancestors of this suite.
|
* @property {String} fullName - The full description including all ancestors of this suite.
|
||||||
* @property {String|null} parentSuiteId - The ID of the suite containing this suite, or null if this is not in another describe().
|
* @property {String|null} parentSuiteId - The ID of the suite containing this suite, or null if this is not in another describe().
|
||||||
* @property {String} filename - The name of the file the suite was defined in.
|
* @property {String} filename - The name of the file the suite was defined in.
|
||||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
|
* @property {ExpectationResult[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
|
||||||
* @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite.
|
* @property {ExpectationResult[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite.
|
||||||
* @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite.
|
* @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite.
|
||||||
* @property {number} duration - The time in ms for Suite execution, including any before/afterAll, before/afterEach.
|
* @property {number} duration - The time in ms for Suite execution, including any before/afterAll, before/afterEach.
|
||||||
* @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSuiteProperty}
|
* @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSuiteProperty}
|
||||||
@@ -10813,5 +10999,5 @@ getJasmineRequireObj().UserContext = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().version = function() {
|
getJasmineRequireObj().version = function() {
|
||||||
return '5.1.2';
|
return '5.4.0';
|
||||||
};
|
};
|
||||||
|
|||||||
51
package.json
51
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jasmine-core",
|
"name": "jasmine-core",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "5.1.2",
|
"version": "5.4.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/jasmine/jasmine.git"
|
"url": "https://github.com/jasmine/jasmine.git"
|
||||||
@@ -52,55 +52,6 @@
|
|||||||
"shelljs": "^0.8.3",
|
"shelljs": "^0.8.3",
|
||||||
"temp": "^0.9.0"
|
"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": [
|
"browserslist": [
|
||||||
"Safari >= 15",
|
"Safari >= 15",
|
||||||
"Firefox >= 102",
|
"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)_
|
||||||
35
release_notes/5.3.0.md
Normal file
35
release_notes/5.3.0.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Jasmine Core 5.3.0 Release Notes
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
* Improved performance in Safari
|
||||||
|
* Merges [#2040](https://github.com/jasmine/jasmine/pull/2040) from @dcsaszar
|
||||||
|
* Fixes [#2008](https://github.com/jasmine/jasmine/issues/2008)
|
||||||
|
|
||||||
|
* Improved performance in Playwright Webkit on Windows
|
||||||
|
* Merges [#2034](https://github.com/jasmine/jasmine/pull/2034) from @m-akinc
|
||||||
|
|
||||||
|
* Throw if spying has no effect, as when spying on localStorage methods in Firefox and Safari 17
|
||||||
|
* See [#2036](https://github.com/jasmine/jasmine/issues/2036) and [#2007](https://github.com/jasmine/jasmine/issues/2007)
|
||||||
|
|
||||||
|
|
||||||
|
## Documentation improvements
|
||||||
|
|
||||||
|
* Added API reference for reporter capabilities
|
||||||
|
|
||||||
|
## Supported environments
|
||||||
|
|
||||||
|
This version has been tested in the following environments.
|
||||||
|
|
||||||
|
| Environment | Supported versions |
|
||||||
|
|-------------------|--------------------|
|
||||||
|
| Node | 18, 20, 22 |
|
||||||
|
| Safari | 15-17 |
|
||||||
|
| Chrome | 128 |
|
||||||
|
| Firefox | 102, 115, 130 |
|
||||||
|
| Edge | 128 |
|
||||||
|
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||||
39
release_notes/5.4.0.md
Normal file
39
release_notes/5.4.0.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Jasmine Core 5.4.0 Release Notes
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
* Fixed de-duplication of exception messages containing blank lines on Node and Chrome
|
||||||
|
|
||||||
|
This is particularly helpful when reporting testing-library errors, which
|
||||||
|
have messages that contain blank lines and can be hundreds or even thousands
|
||||||
|
of lines long.
|
||||||
|
|
||||||
|
* Document that the expected and actual properties of expectation results are deprecated
|
||||||
|
|
||||||
|
The values of these properties are not reliable in configurations where
|
||||||
|
reporter messages are JSON serialized. They appear to have been seldom if ever
|
||||||
|
used. They will be removed in the next major release.
|
||||||
|
|
||||||
|
* Added Firefox 128 (current ESR) to supported browsers
|
||||||
|
|
||||||
|
## Supported environments
|
||||||
|
|
||||||
|
This version has been tested in the following environments.
|
||||||
|
|
||||||
|
| Environment | Supported versions |
|
||||||
|
|-------------------|-------------------------|
|
||||||
|
| Node | 18, 20, 22 |
|
||||||
|
| Safari | 15-17 |
|
||||||
|
| Chrome | 129* |
|
||||||
|
| Firefox | 102**, 115**, 128, 131* |
|
||||||
|
| Edge | 129* |
|
||||||
|
|
||||||
|
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||||
|
version available at release time.<br>
|
||||||
|
\** Environments that are past end of life are supported on a best-effort basis.
|
||||||
|
They may be dropped in a future minor release of Jasmine if continued support
|
||||||
|
becomes impractical.
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||||
@@ -36,6 +36,7 @@ failfile=`mktemp -t jasmine-results.XXXXXX` || exit 1
|
|||||||
run_browser chrome latest "macOS 12"
|
run_browser chrome latest "macOS 12"
|
||||||
|
|
||||||
run_browser firefox latest
|
run_browser firefox latest
|
||||||
|
run_browser firefox 128
|
||||||
run_browser firefox 115
|
run_browser firefox 115
|
||||||
run_browser firefox 102
|
run_browser firefox 102
|
||||||
run_browser safari 17
|
run_browser safari 17
|
||||||
|
|||||||
@@ -20,6 +20,47 @@ describe('ClearStack', function() {
|
|||||||
MessageChannel: fakeMessageChannel
|
MessageChannel: fakeMessageChannel
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('uses MessageChannel to reduce setTimeout clamping', function() {
|
||||||
|
const fakeChannel = fakeMessageChannel();
|
||||||
|
spyOn(fakeChannel.port2, 'postMessage');
|
||||||
|
const queueMicrotask = jasmine.createSpy('queueMicrotask');
|
||||||
|
const global = {
|
||||||
|
navigator: {
|
||||||
|
userAgent:
|
||||||
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.0.8 (KHTML, like Gecko) Version/15.1 Safari/605.0.8'
|
||||||
|
},
|
||||||
|
MessageChannel: function() {
|
||||||
|
return fakeChannel;
|
||||||
|
},
|
||||||
|
queueMicrotask
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearStack = jasmineUnderTest.getClearStack(global);
|
||||||
|
|
||||||
|
for (let i = 0; i < 9; i++) {
|
||||||
|
clearStack(function() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(fakeChannel.port2.postMessage).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
clearStack(function() {});
|
||||||
|
|
||||||
|
expect(fakeChannel.port2.postMessage).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("in WebKit (Playwright's build for Windows)", function() {
|
||||||
|
usesQueueMicrotaskWithSetTimeout(function() {
|
||||||
|
return {
|
||||||
|
navigator: {
|
||||||
|
userAgent:
|
||||||
|
'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/605.1.15 (KHTML, like Gecko)'
|
||||||
|
},
|
||||||
|
// queueMicrotask should be used even though MessageChannel is present
|
||||||
|
MessageChannel: fakeMessageChannel
|
||||||
|
};
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('in browsers other than Safari', function() {
|
describe('in browsers other than Safari', function() {
|
||||||
|
|||||||
@@ -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() {
|
it('filters Jasmine stack frames in this environment', function() {
|
||||||
const error = new Error('an error');
|
const error = new Error('an error');
|
||||||
const subject = new jasmineUnderTest.ExceptionFormatter({
|
const subject = new jasmineUnderTest.ExceptionFormatter({
|
||||||
jasmineFile: jasmine.util.jasmineFile()
|
jasmineFile: jasmine.util.jasmineFile()
|
||||||
});
|
});
|
||||||
const result = subject.stack(error);
|
const result = subject.stack(error);
|
||||||
|
jasmine.debugLog('Original stack trace: ' + error.stack);
|
||||||
|
jasmine.debugLog('Filtered stack trace: ' + result);
|
||||||
const lines = result.split('\n');
|
const lines = result.split('\n');
|
||||||
|
|
||||||
if (lines[0].match(/an error/)) {
|
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() {
|
describe('#setOverrideListener', function() {
|
||||||
it('overrides the existing handlers in browsers until removed', function() {
|
it('overrides the existing handlers in browsers until removed', function() {
|
||||||
const fakeGlobal = browserGlobal();
|
const fakeGlobal = browserGlobal();
|
||||||
|
|||||||
@@ -459,6 +459,32 @@ describe('QueueRunner', function() {
|
|||||||
expect(nextQueueableFn.fn).toHaveBeenCalled();
|
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() {
|
it('handles exceptions thrown while waiting for the stack to clear', function() {
|
||||||
const queueableFn = {
|
const queueableFn = {
|
||||||
fn: function(done) {
|
fn: function(done) {
|
||||||
@@ -492,6 +518,40 @@ describe('QueueRunner', function() {
|
|||||||
clearStack.calls.argsFor(0)[0]();
|
clearStack.calls.argsFor(0)[0]();
|
||||||
expect(onException).toHaveBeenCalledWith(error);
|
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() {
|
describe('with a function that returns a promise', function() {
|
||||||
|
|||||||
@@ -94,6 +94,30 @@ describe('SpyRegistry', function() {
|
|||||||
}).not.toThrowError(/is not declared writable or has no setter/);
|
}).not.toThrowError(/is not declared writable or has no setter/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('throws if assigning to the property is a no-op', function() {
|
||||||
|
const scope = {};
|
||||||
|
|
||||||
|
function original() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(scope, 'myFunc', {
|
||||||
|
get() {
|
||||||
|
return original;
|
||||||
|
},
|
||||||
|
set() {}
|
||||||
|
});
|
||||||
|
|
||||||
|
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||||
|
createSpy: createSpy
|
||||||
|
});
|
||||||
|
expect(function() {
|
||||||
|
spyRegistry.spyOn(scope, 'myFunc');
|
||||||
|
}).toThrowError(
|
||||||
|
"<spyOn> : Can't spy on myFunc because assigning to it had no effect"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('overrides the method on the object and returns the spy', function() {
|
it('overrides the method on the object and returns the spy', function() {
|
||||||
const originalFunctionWasCalled = false,
|
const originalFunctionWasCalled = false,
|
||||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||||
|
|||||||
@@ -51,6 +51,27 @@ describe('StackTrace', function() {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('understands Chrome/Edge style traces with messages containing blank lines', function() {
|
||||||
|
const error = {
|
||||||
|
message: 'line 1\n\nline 2',
|
||||||
|
stack:
|
||||||
|
'Error: line 1\n\nline 2\n' +
|
||||||
|
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
|
||||||
|
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = new jasmineUnderTest.StackTrace(error);
|
||||||
|
|
||||||
|
expect(result.message).toEqual('Error: line 1\n\nline 2');
|
||||||
|
const rawFrames = result.frames.map(function(f) {
|
||||||
|
return f.raw;
|
||||||
|
});
|
||||||
|
expect(rawFrames).toEqual([
|
||||||
|
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
|
||||||
|
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it('understands Node style traces', function() {
|
it('understands Node style traces', function() {
|
||||||
const error = {
|
const error = {
|
||||||
message: 'nope',
|
message: 'nope',
|
||||||
@@ -95,7 +116,7 @@ describe('StackTrace', function() {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('understands Safari <=14/Firefox/Phantom-OS X style traces', function() {
|
it('understands Safari <=14/Firefox style traces', function() {
|
||||||
const error = {
|
const error = {
|
||||||
message: 'nope',
|
message: 'nope',
|
||||||
stack:
|
stack:
|
||||||
@@ -149,7 +170,7 @@ describe('StackTrace', function() {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not mistake gibberish for Safari/Firefox/Phantom-OS X style traces', function() {
|
it('does not mistake gibberish for Safari/Firefox style traces', function() {
|
||||||
const error = {
|
const error = {
|
||||||
message: 'nope',
|
message: 'nope',
|
||||||
stack: 'randomcharsnotincludingwhitespace'
|
stack: 'randomcharsnotincludingwhitespace'
|
||||||
@@ -159,36 +180,6 @@ describe('StackTrace', function() {
|
|||||||
expect(result.frames).toEqual([{ raw: error.stack }]);
|
expect(result.frames).toEqual([{ raw: error.stack }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('understands Phantom-Linux style traces', function() {
|
|
||||||
const error = {
|
|
||||||
message: 'nope',
|
|
||||||
stack:
|
|
||||||
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
|
|
||||||
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = new jasmineUnderTest.StackTrace(error);
|
|
||||||
|
|
||||||
expect(result.message).toBeFalsy();
|
|
||||||
expect(result.style).toEqual('v8');
|
|
||||||
expect(result.frames).toEqual([
|
|
||||||
{
|
|
||||||
raw:
|
|
||||||
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
|
|
||||||
func: 'UserContext.<anonymous>',
|
|
||||||
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
|
|
||||||
line: 115
|
|
||||||
},
|
|
||||||
{
|
|
||||||
raw:
|
|
||||||
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
|
|
||||||
func: 'QueueRunner.run',
|
|
||||||
file: 'http://localhost:8888/__jasmine__/jasmine.js',
|
|
||||||
line: 4320
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('ignores blank lines', function() {
|
it('ignores blank lines', function() {
|
||||||
const error = {
|
const error = {
|
||||||
message: 'nope',
|
message: 'nope',
|
||||||
@@ -241,7 +232,7 @@ describe('StackTrace', function() {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('consideres different types of errors', function() {
|
it('considers different types of errors', function() {
|
||||||
const error = {
|
const error = {
|
||||||
message: 'nope',
|
message: 'nope',
|
||||||
stack:
|
stack:
|
||||||
|
|||||||
@@ -179,7 +179,10 @@ describe('base helpers', function() {
|
|||||||
f2 = jasmine.createSpy('setTimeout callback for ' + (max + 1));
|
f2 = jasmine.createSpy('setTimeout callback for ' + (max + 1));
|
||||||
|
|
||||||
// Suppress printing of TimeoutOverflowWarning in node
|
// 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);
|
let id = setTimeout(f1, max);
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
|
|||||||
@@ -1315,8 +1315,9 @@ describe('Env integration', function() {
|
|||||||
'works with constructors when using callThrough spy strategy',
|
'works with constructors when using callThrough spy strategy',
|
||||||
function() {
|
function() {
|
||||||
function MyClass(foo) {
|
function MyClass(foo) {
|
||||||
if (!(this instanceof MyClass))
|
if (!(this instanceof MyClass)) {
|
||||||
throw new Error('You must use the new keyword.');
|
throw new Error('You must use the new keyword.');
|
||||||
|
}
|
||||||
this.foo = foo;
|
this.foo = foo;
|
||||||
}
|
}
|
||||||
const subject = { MyClass: MyClass };
|
const subject = { MyClass: MyClass };
|
||||||
|
|||||||
@@ -15,6 +15,17 @@ describe('toHaveSize', function() {
|
|||||||
expect(result.pass).toBe(false);
|
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() {
|
it('passes for an object with the proper number of keys', function() {
|
||||||
const matcher = jasmineUnderTest.matchers.toHaveSize(),
|
const matcher = jasmineUnderTest.matchers.toHaveSize(),
|
||||||
result = matcher.compare({ a: 1, b: 2 }, 2);
|
result = matcher.compare({ a: 1, b: 2 }, 2);
|
||||||
|
|||||||
@@ -12,14 +12,12 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
function getSourceFiles() {
|
function getSourceFiles() {
|
||||||
const src_files = ['core/**/*.js', 'version.js'].map(function(file) {
|
const globs = ['../../src/core/**/*.js', '../../src/version.js'];
|
||||||
return path.join(__dirname, '../../', 'src/', file);
|
const srcFiles = globs.flatMap(g => glob.sync(g, { cwd: __dirname }));
|
||||||
});
|
|
||||||
|
|
||||||
const files = src_files.flatMap(g => glob.sync(g));
|
for (const file of srcFiles) {
|
||||||
files.forEach(function(resolvedFile) {
|
require(file);
|
||||||
require(resolvedFile);
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getSourceFiles();
|
getSourceFiles();
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
const maxInlineCallCount = 10;
|
const maxInlineCallCount = 10;
|
||||||
|
|
||||||
function browserQueueMicrotaskImpl(global) {
|
function browserQueueMicrotaskImpl(global) {
|
||||||
const { setTimeout, queueMicrotask } = global;
|
const unclampedSetTimeout = getUnclampedSetTimeout(global);
|
||||||
|
const { queueMicrotask } = global;
|
||||||
let currentCallCount = 0;
|
let currentCallCount = 0;
|
||||||
return function clearStack(fn) {
|
return function clearStack(fn) {
|
||||||
currentCallCount++;
|
currentCallCount++;
|
||||||
@@ -11,7 +12,7 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
queueMicrotask(fn);
|
queueMicrotask(fn);
|
||||||
} else {
|
} else {
|
||||||
currentCallCount = 0;
|
currentCallCount = 0;
|
||||||
setTimeout(fn);
|
unclampedSetTimeout(fn);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -25,6 +26,37 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function messageChannelImpl(global) {
|
function messageChannelImpl(global) {
|
||||||
|
const { setTimeout } = global;
|
||||||
|
const postMessage = getPostMessage(global);
|
||||||
|
|
||||||
|
let currentCallCount = 0;
|
||||||
|
return function clearStack(fn) {
|
||||||
|
currentCallCount++;
|
||||||
|
|
||||||
|
if (currentCallCount < maxInlineCallCount) {
|
||||||
|
postMessage(fn);
|
||||||
|
} else {
|
||||||
|
currentCallCount = 0;
|
||||||
|
setTimeout(fn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUnclampedSetTimeout(global) {
|
||||||
|
const { setTimeout } = global;
|
||||||
|
if (j$.util.isUndefined(global.MessageChannel)) {
|
||||||
|
return setTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
const postMessage = getPostMessage(global);
|
||||||
|
return function unclampedSetTimeout(fn) {
|
||||||
|
postMessage(function() {
|
||||||
|
setTimeout(fn);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPostMessage(global) {
|
||||||
const { MessageChannel, setTimeout } = global;
|
const { MessageChannel, setTimeout } = global;
|
||||||
const channel = new MessageChannel();
|
const channel = new MessageChannel();
|
||||||
let head = {};
|
let head = {};
|
||||||
@@ -48,17 +80,9 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let currentCallCount = 0;
|
return function postMessage(fn) {
|
||||||
return function clearStack(fn) {
|
tail = tail.next = { task: fn };
|
||||||
currentCallCount++;
|
channel.port2.postMessage(0);
|
||||||
|
|
||||||
if (currentCallCount < maxInlineCallCount) {
|
|
||||||
tail = tail.next = { task: fn };
|
|
||||||
channel.port2.postMessage(0);
|
|
||||||
} else {
|
|
||||||
currentCallCount = 0;
|
|
||||||
setTimeout(fn);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,20 +92,25 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
global.process.versions &&
|
global.process.versions &&
|
||||||
typeof global.process.versions.node === 'string';
|
typeof global.process.versions.node === 'string';
|
||||||
|
|
||||||
const SAFARI =
|
// Windows builds of WebKit have a fairly generic user agent string when no application name is provided:
|
||||||
|
// e.g. "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/605.1.15 (KHTML, like Gecko)"
|
||||||
|
const SAFARI_OR_WIN_WEBKIT =
|
||||||
global.navigator &&
|
global.navigator &&
|
||||||
/^((?!chrome|android).)*safari/i.test(global.navigator.userAgent);
|
/(^((?!chrome|android).)*safari)|(Win64; x64\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\)$)/i.test(
|
||||||
|
global.navigator.userAgent
|
||||||
|
);
|
||||||
|
|
||||||
if (NODE_JS) {
|
if (NODE_JS) {
|
||||||
// Unlike browsers, Node doesn't require us to do a periodic setTimeout
|
// Unlike browsers, Node doesn't require us to do a periodic setTimeout
|
||||||
// so we avoid the overhead.
|
// so we avoid the overhead.
|
||||||
return nodeQueueMicrotaskImpl(global);
|
return nodeQueueMicrotaskImpl(global);
|
||||||
} else if (
|
} else if (
|
||||||
SAFARI ||
|
SAFARI_OR_WIN_WEBKIT ||
|
||||||
j$.util.isUndefined(global.MessageChannel) /* tests */
|
j$.util.isUndefined(global.MessageChannel) /* tests */
|
||||||
) {
|
) {
|
||||||
// queueMicrotask is dramatically faster than MessageChannel in Safari,
|
// queueMicrotask is dramatically faster than MessageChannel in Safari
|
||||||
// at least through version 16.
|
// and other WebKit-based browsers, such as the one distributed by Playwright
|
||||||
|
// to test Safari-like behavior on Windows.
|
||||||
// Some of our own integration tests provide a mock queueMicrotask in all
|
// Some of our own integration tests provide a mock queueMicrotask in all
|
||||||
// environments because it's simpler to mock than MessageChannel.
|
// environments because it's simpler to mock than MessageChannel.
|
||||||
return browserQueueMicrotaskImpl(global);
|
return browserQueueMicrotaskImpl(global);
|
||||||
|
|||||||
@@ -272,12 +272,19 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
* @extends Error
|
* @extends Error
|
||||||
* @description Represents a failure of an expectation evaluated with
|
* @description Represents a failure of an expectation evaluated with
|
||||||
* {@link throwUnless}. Properties of this error are a subset of the
|
* {@link throwUnless}. Properties of this error are a subset of the
|
||||||
* properties of {@link Expectation} and have the same values.
|
* properties of {@link ExpectationResult} and have the same values.
|
||||||
|
*
|
||||||
|
* Note: The expected and actual properties are deprecated and may be removed
|
||||||
|
* in a future release. In many Jasmine configurations they are passed
|
||||||
|
* through JSON serialization and deserialization, which is inherently
|
||||||
|
* lossy. In such cases, the expected and actual values may be placeholders
|
||||||
|
* or approximations of the original objects.
|
||||||
|
*
|
||||||
* @property {String} matcherName - The name of the matcher that was executed for this expectation.
|
* @property {String} matcherName - The name of the matcher that was executed for this expectation.
|
||||||
* @property {String} message - The failure message for the expectation.
|
* @property {String} message - The failure message for the expectation.
|
||||||
* @property {Boolean} passed - Whether the expectation passed or failed.
|
* @property {Boolean} passed - Whether the expectation passed or failed.
|
||||||
* @property {Object} expected - If the expectation failed, what was the expected value.
|
* @property {Object} expected - Deprecated. If the expectation failed, what was the expected value.
|
||||||
* @property {Object} actual - If the expectation failed, what actual value was produced.
|
* @property {Object} actual - Deprecated. If the expectation failed, what actual value was produced.
|
||||||
*/
|
*/
|
||||||
const error = new Error(result.message);
|
const error = new Error(result.message);
|
||||||
error.passed = result.passed;
|
error.passed = result.passed;
|
||||||
|
|||||||
@@ -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
|
* @function
|
||||||
* @name matchers#withContext
|
* @name matchers#withContext
|
||||||
* @since 3.3.0
|
* @since 3.3.0
|
||||||
* @param {String} message - Additional context to show when the matcher fails
|
* @param {String} message - Additional context to show when the matcher fails
|
||||||
* @return {matchers}
|
* @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) {
|
Expectation.prototype.withContext = function withContext(message) {
|
||||||
return addFilter(this, new ContextAddingFilter(message));
|
return addFilter(this, new ContextAddingFilter(message));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invert the matcher following this {@link expect}
|
* Invert the matcher following this {@link expect|expectation}
|
||||||
* @member
|
* @member
|
||||||
* @name matchers#not
|
* @name matchers#not
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
|||||||
|
|
||||||
function dispatchBrowserError(error, event) {
|
function dispatchBrowserError(error, event) {
|
||||||
if (overrideHandler) {
|
if (overrideHandler) {
|
||||||
|
// See discussion of spyOnGlobalErrorsAsync in base.js
|
||||||
overrideHandler(error);
|
overrideHandler(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -55,6 +56,7 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
|||||||
const handler = handlers[handlers.length - 1];
|
const handler = handlers[handlers.length - 1];
|
||||||
|
|
||||||
if (overrideHandler) {
|
if (overrideHandler) {
|
||||||
|
// See discussion of spyOnGlobalErrorsAsync in base.js
|
||||||
overrideHandler(error);
|
overrideHandler(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QueueRunner.prototype.execute = function() {
|
QueueRunner.prototype.execute = function() {
|
||||||
this.handleFinalError = error => {
|
this.handleFinalError = (error, event) => {
|
||||||
this.onException(error);
|
this.onException(errorOrMsgForGlobalError(error, event));
|
||||||
};
|
};
|
||||||
this.globalErrors.pushListener(this.handleFinalError);
|
this.globalErrors.pushListener(this.handleFinalError);
|
||||||
this.run(0);
|
this.run(0);
|
||||||
@@ -96,10 +96,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
|||||||
this.recordError_(iterativeIndex);
|
this.recordError_(iterativeIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
function handleError(error) {
|
function handleError(error, event) {
|
||||||
// TODO probably shouldn't next() right away here.
|
onException(errorOrMsgForGlobalError(error, event));
|
||||||
// That makes debugging async failures much more confusing.
|
|
||||||
onException(error);
|
|
||||||
}
|
}
|
||||||
const cleanup = once(() => {
|
const cleanup = once(() => {
|
||||||
if (timeoutId !== void 0) {
|
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;
|
return QueueRunner;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -177,8 +177,8 @@ getJasmineRequireObj().Runner = function(j$) {
|
|||||||
* @property {String} incompleteCode - Machine-readable explanation of why the suite was incomplete: 'focused', 'noSpecsFound', or undefined.
|
* @property {String} incompleteCode - Machine-readable explanation of why the suite was incomplete: 'focused', 'noSpecsFound', or undefined.
|
||||||
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite. Note that this property is not present when Jasmine is run in parallel mode.
|
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite. Note that this property is not present when Jasmine is run in parallel mode.
|
||||||
* @property {Int} numWorkers - Number of parallel workers. Note that this property is only present when Jasmine is run in parallel mode.
|
* @property {Int} numWorkers - Number of parallel workers. Note that this property is only present when Jasmine is run in parallel mode.
|
||||||
* @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
|
* @property {ExpectationResult[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
|
||||||
* @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level.
|
* @property {ExpectationResult[]} deprecationWarnings - List of deprecation warnings that occurred at the global level.
|
||||||
* @since 2.4.0
|
* @since 2.4.0
|
||||||
*/
|
*/
|
||||||
const jasmineDoneInfo = {
|
const jasmineDoneInfo = {
|
||||||
|
|||||||
@@ -148,9 +148,9 @@ getJasmineRequireObj().Spec = function(j$) {
|
|||||||
* @property {String} fullName - The full description including all ancestors of this spec.
|
* @property {String} fullName - The full description including all ancestors of this spec.
|
||||||
* @property {String|null} parentSuiteId - The ID of the suite containing this spec, or null if this spec is not in a describe().
|
* @property {String|null} parentSuiteId - The ID of the suite containing this spec, or null if this spec is not in a describe().
|
||||||
* @property {String} filename - The name of the file the spec was defined in.
|
* @property {String} filename - The name of the file the spec was defined in.
|
||||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed during execution of this spec.
|
* @property {ExpectationResult[]} failedExpectations - The list of expectations that failed during execution of this spec.
|
||||||
* @property {Expectation[]} passedExpectations - The list of expectations that passed during execution of this spec.
|
* @property {ExpectationResult[]} passedExpectations - The list of expectations that passed during execution of this spec.
|
||||||
* @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred during execution this spec.
|
* @property {ExpectationResult[]} deprecationWarnings - The list of deprecation warnings that occurred during execution this spec.
|
||||||
* @property {String} pendingReason - If the spec is {@link pending}, this will be the reason.
|
* @property {String} pendingReason - If the spec is {@link pending}, this will be the reason.
|
||||||
* @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec.
|
* @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec.
|
||||||
* @property {number} duration - The time in ms used by the spec execution, including any before/afterEach.
|
* @property {number} duration - The time in ms used by the spec execution, including any before/afterEach.
|
||||||
|
|||||||
@@ -84,6 +84,16 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
|||||||
|
|
||||||
obj[methodName] = spiedMethod;
|
obj[methodName] = spiedMethod;
|
||||||
|
|
||||||
|
// Check if setting the property actually worked. Some objects, such as
|
||||||
|
// localStorage in Firefox and later Safari versions, have no-op setters.
|
||||||
|
if (obj[methodName] !== spiedMethod) {
|
||||||
|
throw new Error(
|
||||||
|
j$.formatErrorMsg('<spyOn>')(
|
||||||
|
`Can't spy on ${methodName} because assigning to it had no effect`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return spiedMethod;
|
return spiedMethod;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
getJasmineRequireObj().StackTrace = function(j$) {
|
getJasmineRequireObj().StackTrace = function(j$) {
|
||||||
function StackTrace(error) {
|
function StackTrace(error) {
|
||||||
let lines = error.stack.split('\n').filter(function(line) {
|
let lines = error.stack.split('\n');
|
||||||
return line !== '';
|
|
||||||
});
|
|
||||||
|
|
||||||
const extractResult = extractMessage(error.message, lines);
|
const extractResult = extractMessage(error.message, lines);
|
||||||
|
|
||||||
@@ -11,6 +9,10 @@ getJasmineRequireObj().StackTrace = function(j$) {
|
|||||||
lines = extractResult.remainder;
|
lines = extractResult.remainder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lines = lines.filter(function(line) {
|
||||||
|
return line !== '';
|
||||||
|
});
|
||||||
|
|
||||||
const parseResult = tryParseFrames(lines);
|
const parseResult = tryParseFrames(lines);
|
||||||
this.frames = parseResult.frames;
|
this.frames = parseResult.frames;
|
||||||
this.style = parseResult.style;
|
this.style = parseResult.style;
|
||||||
@@ -32,7 +34,7 @@ getJasmineRequireObj().StackTrace = function(j$) {
|
|||||||
// e.g. " at /some/path:4320:20
|
// e.g. " at /some/path:4320:20
|
||||||
{ re: /\s*at (.+)$/, fileLineColIx: 1, style: 'v8' },
|
{ 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"
|
// e.g. "run@http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||||
// or "http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
// or "http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||||
{
|
{
|
||||||
@@ -40,6 +42,15 @@ getJasmineRequireObj().StackTrace = function(j$) {
|
|||||||
fnIx: 2,
|
fnIx: 2,
|
||||||
fileLineColIx: 3,
|
fileLineColIx: 3,
|
||||||
style: 'webkit'
|
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'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -105,8 +105,8 @@ getJasmineRequireObj().Suite = function(j$) {
|
|||||||
* @property {String} fullName - The full description including all ancestors of this suite.
|
* @property {String} fullName - The full description including all ancestors of this suite.
|
||||||
* @property {String|null} parentSuiteId - The ID of the suite containing this suite, or null if this is not in another describe().
|
* @property {String|null} parentSuiteId - The ID of the suite containing this suite, or null if this is not in another describe().
|
||||||
* @property {String} filename - The name of the file the suite was defined in.
|
* @property {String} filename - The name of the file the suite was defined in.
|
||||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
|
* @property {ExpectationResult[]} failedExpectations - The list of expectations that failed in an {@link afterAll} for this suite.
|
||||||
* @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite.
|
* @property {ExpectationResult[]} deprecationWarnings - The list of deprecation warnings that occurred on this suite.
|
||||||
* @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite.
|
* @property {String} status - Once the suite has completed, this string represents the pass/fail status of this suite.
|
||||||
* @property {number} duration - The time in ms for Suite execution, including any before/afterAll, before/afterEach.
|
* @property {number} duration - The time in ms for Suite execution, including any before/afterAll, before/afterEach.
|
||||||
* @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSuiteProperty}
|
* @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSuiteProperty}
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ getJasmineRequireObj().MapContaining = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MapContaining.prototype.asymmetricMatch = function(other, matchersUtil) {
|
MapContaining.prototype.asymmetricMatch = function(other, matchersUtil) {
|
||||||
if (!j$.isMap(other)) return false;
|
if (!j$.isMap(other)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (const [key, value] of this.sample) {
|
for (const [key, value] of this.sample) {
|
||||||
// for each key/value pair in `sample`
|
// for each key/value pair in `sample`
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ getJasmineRequireObj().SetContaining = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetContaining.prototype.asymmetricMatch = function(other, matchersUtil) {
|
SetContaining.prototype.asymmetricMatch = function(other, matchersUtil) {
|
||||||
if (!j$.isSet(other)) return false;
|
if (!j$.isSet(other)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (const item of this.sample) {
|
for (const item of this.sample) {
|
||||||
// for each item in `sample` there should be at least one matching item in `other`
|
// for each item in `sample` there should be at least one matching item in `other`
|
||||||
|
|||||||
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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared is an instance of the specified class/constructor.
|
* value being compared is an instance of the specified class/constructor.
|
||||||
* @name jasmine.any
|
* @name asymmetricEqualityTesters.any
|
||||||
|
* @emittedName jasmine.any
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
* @function
|
* @function
|
||||||
* @param {Constructor} clazz - The constructor to check against.
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared is not `null` and not `undefined`.
|
* value being compared is not `null` and not `undefined`.
|
||||||
* @name jasmine.anything
|
* @name asymmetricEqualityTesters.anything
|
||||||
|
* @emittedName jasmine.anything
|
||||||
* @since 2.2.0
|
* @since 2.2.0
|
||||||
* @function
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared is `true` or anything truthy.
|
* value being compared is `true` or anything truthy.
|
||||||
* @name jasmine.truthy
|
* @name asymmetricEqualityTesters.truthy
|
||||||
|
* @emittedName jasmine.truthy
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
* @function
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared is `null`, `undefined`, `0`, `false` or anything falsey.
|
* value being compared is `null`, `undefined`, `0`, `false` or anything
|
||||||
* @name jasmine.falsy
|
* falsy.
|
||||||
|
* @name asymmetricEqualityTesters.falsy
|
||||||
|
* @emittedName jasmine.falsy
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
* @function
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared is empty.
|
* value being compared is empty.
|
||||||
* @name jasmine.empty
|
* @name asymmetricEqualityTesters.empty
|
||||||
|
* @emittedName jasmine.empty
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
@@ -280,10 +286,10 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an {@link AsymmetricEqualityTester}, usable in any {@link matchers|matcher}
|
* Get an {@link AsymmetricEqualityTester} that passes if the actual value is
|
||||||
* that passes if the actual value is the same as the sample as determined
|
* the same as the sample as determined by the `===` operator.
|
||||||
* by the `===` operator.
|
* @name asymmetricEqualityTesters.is
|
||||||
* @name jasmine.is
|
* @emittedName jasmine.is
|
||||||
* @function
|
* @function
|
||||||
* @param {Object} sample - The value to compare the actual to.
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared is not empty.
|
* value being compared is not empty.
|
||||||
* @name jasmine.notEmpty
|
* @name asymmetricEqualityTesters.notEmpty
|
||||||
|
* @emittedName jasmine.notEmpty
|
||||||
* @since 3.1.0
|
* @since 3.1.0
|
||||||
* @function
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value being compared contains at least the keys and values.
|
* value being compared contains at least the specified keys and values.
|
||||||
* @name jasmine.objectContaining
|
* @name asymmetricEqualityTesters.objectContaining
|
||||||
|
* @emittedName jasmine.objectContaining
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
* @function
|
* @function
|
||||||
* @param {Object} sample - The subset of properties that _must_ be in the actual.
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value is a `String` that matches the `RegExp` or `String`.
|
* value is a `String` that matches the `RegExp` or `String`.
|
||||||
* @name jasmine.stringMatching
|
* @name asymmetricEqualityTesters.stringMatching
|
||||||
|
* @emittedName jasmine.stringMatching
|
||||||
* @since 2.2.0
|
* @since 2.2.0
|
||||||
* @function
|
* @function
|
||||||
* @param {RegExp|String} expected
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value is a `String` that contains the specified `String`.
|
* value is a `String` that contains the specified `String`.
|
||||||
* @name jasmine.stringContaining
|
* @name asymmetricEqualityTesters.stringContaining
|
||||||
|
* @emittedName jasmine.stringContaining
|
||||||
* @since 3.10.0
|
* @since 3.10.0
|
||||||
* @function
|
* @function
|
||||||
* @param {String} expected
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value is an `Array` that contains at least the elements in the sample.
|
* value is an `Array` that contains at least the elements in the sample.
|
||||||
* @name jasmine.arrayContaining
|
* @name asymmetricEqualityTesters.arrayContaining
|
||||||
|
* @emittedName jasmine.arrayContaining
|
||||||
* @since 2.2.0
|
* @since 2.2.0
|
||||||
* @function
|
* @function
|
||||||
* @param {Array} sample
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if the actual
|
||||||
* that will succeed if the actual value is an `Array` that contains all of the elements in the sample in any order.
|
* value is an `Array` that contains all of the elements in the sample in
|
||||||
* @name jasmine.arrayWithExactContents
|
* any order.
|
||||||
|
* @name asymmetricEqualityTesters.arrayWithExactContents
|
||||||
|
* @emittedName jasmine.arrayWithExactContents
|
||||||
* @since 2.8.0
|
* @since 2.8.0
|
||||||
* @function
|
* @function
|
||||||
* @param {Array} sample
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if every
|
||||||
* that will succeed if every key/value pair in the sample passes the deep equality comparison
|
* key/value pair in the sample passes the deep equality comparison
|
||||||
* with at least one key/value pair in the actual value being compared
|
* 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
|
* @since 3.5.0
|
||||||
* @function
|
* @function
|
||||||
* @param {Map} sample - The subset of items that _must_ be in the actual.
|
* @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}),
|
* Get an {@link AsymmetricEqualityTester} that will succeed if every item
|
||||||
* that will succeed if every item in the sample passes the deep equality comparison
|
* in the sample passes the deep equality comparison
|
||||||
* with at least one item in the actual value being compared
|
* with at least one item in the actual value being compared
|
||||||
* @name jasmine.setContaining
|
* @name asymmetricEqualityTesters.setContaining
|
||||||
|
* @emittedName jasmine.setContaining
|
||||||
* @since 3.5.0
|
* @since 3.5.0
|
||||||
* @function
|
* @function
|
||||||
* @param {Set} sample - The subset of items that _must_ be in the actual.
|
* @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
|
* handling will be restored when the promise returned from the callback is
|
||||||
* settled.
|
* 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
|
* Note: The JavaScript runtime may deliver uncaught error events and unhandled
|
||||||
* rejection events asynchronously, especially in browsers. If the event
|
* rejection events asynchronously, especially in browsers. If the event
|
||||||
* occurs after the promise returned from the callback is settled, it won't
|
* 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.
|
* 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
|
* It's up to you to ensure that all of the error/rejection events that you
|
||||||
* all of the error/rejection events that you want to handle have occurred.
|
* 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
|
* @name jasmine.spyOnGlobalErrorsAsync
|
||||||
* @function
|
* @function
|
||||||
* @async
|
* @async
|
||||||
|
|||||||
@@ -4,13 +4,21 @@ getJasmineRequireObj().buildExpectationResult = function(j$) {
|
|||||||
const exceptionFormatter = new j$.ExceptionFormatter();
|
const exceptionFormatter = new j$.ExceptionFormatter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef Expectation
|
* Describes the result of evaluating an expectation
|
||||||
|
*
|
||||||
|
* Note: The expected and actual properties are deprecated and may be removed
|
||||||
|
* in a future release. In many Jasmine configurations they are passed
|
||||||
|
* through JSON serialization and deserialization, which is inherently
|
||||||
|
* lossy. In such cases, the expected and actual values may be placeholders
|
||||||
|
* or approximations of the original objects.
|
||||||
|
*
|
||||||
|
* @typedef ExpectationResult
|
||||||
* @property {String} matcherName - The name of the matcher that was executed for this expectation.
|
* @property {String} matcherName - The name of the matcher that was executed for this expectation.
|
||||||
* @property {String} message - The failure message for the expectation.
|
* @property {String} message - The failure message for the expectation.
|
||||||
* @property {String} stack - The stack trace for the failure if available.
|
* @property {String} stack - The stack trace for the failure if available.
|
||||||
* @property {Boolean} passed - Whether the expectation passed or failed.
|
* @property {Boolean} passed - Whether the expectation passed or failed.
|
||||||
* @property {Object} expected - If the expectation failed, what was the expected value.
|
* @property {Object} expected - Deprecated. If the expectation failed, what was the expected value.
|
||||||
* @property {Object} actual - If the expectation failed, what actual value was produced.
|
* @property {Object} actual - Deprecated. If the expectation failed, what actual value was produced.
|
||||||
* @property {String|undefined} globalErrorType - The type of an error that
|
* @property {String|undefined} globalErrorType - The type of an error that
|
||||||
* is reported on the top suite. Valid values are undefined, "afterAll",
|
* is reported on the top suite. Valid values are undefined, "afterAll",
|
||||||
* "load", "lateExpectation", and "lateError".
|
* "load", "lateExpectation", and "lateError".
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ getJasmineRequireObj().toHaveSize = function(j$) {
|
|||||||
* array = [1,2];
|
* array = [1,2];
|
||||||
* expect(array).toHaveSize(2);
|
* expect(array).toHaveSize(2);
|
||||||
*/
|
*/
|
||||||
function toHaveSize() {
|
function toHaveSize(matchersUtil) {
|
||||||
return {
|
return {
|
||||||
compare: function(actual, expected) {
|
compare: function(actual, expected) {
|
||||||
const result = {
|
const result = {
|
||||||
@@ -24,12 +24,29 @@ getJasmineRequireObj().toHaveSize = function(j$) {
|
|||||||
throw new Error('Cannot get size of ' + actual + '.');
|
throw new Error('Cannot get size of ' + actual + '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let actualSize;
|
||||||
if (j$.isSet(actual) || j$.isMap(actual)) {
|
if (j$.isSet(actual) || j$.isMap(actual)) {
|
||||||
result.pass = actual.size === expected;
|
actualSize = actual.size;
|
||||||
} else if (isLength(actual.length)) {
|
} else if (isLength(actual.length)) {
|
||||||
result.pass = actual.length === expected;
|
actualSize = actual.length;
|
||||||
} else {
|
} 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;
|
return result;
|
||||||
|
|||||||
@@ -32,7 +32,10 @@ getJasmineRequireObj().toHaveSpyInteractions = function(j$) {
|
|||||||
let hasSpy = false;
|
let hasSpy = false;
|
||||||
const calledSpies = [];
|
const calledSpies = [];
|
||||||
for (const spy of Object.values(actual)) {
|
for (const spy of Object.values(actual)) {
|
||||||
if (!j$.isSpy(spy)) continue;
|
if (!j$.isSpy(spy)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
hasSpy = true;
|
hasSpy = true;
|
||||||
|
|
||||||
if (spy.calls.any()) {
|
if (spy.calls.any()) {
|
||||||
|
|||||||
@@ -1,4 +1,30 @@
|
|||||||
getJasmineRequireObj().reporterEvents = function() {
|
getJasmineRequireObj().reporterEvents = function() {
|
||||||
|
/**
|
||||||
|
* Used to tell Jasmine what optional or uncommonly implemented features
|
||||||
|
* the reporter supports. If not specified, the defaults described in
|
||||||
|
* {@link ReporterCapabilities} will apply.
|
||||||
|
* @name Reporter#reporterCapabilities
|
||||||
|
* @type ReporterCapabilities | undefined
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Used to tell Jasmine what optional or uncommonly implemented features
|
||||||
|
* the reporter supports.
|
||||||
|
* @interface ReporterCapabilities
|
||||||
|
* @see Reporter#reporterCapabilities
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Indicates whether the reporter supports parallel execution. Jasmine will
|
||||||
|
* not allow parallel execution unless all reporters that are in use set this
|
||||||
|
* capability to true.
|
||||||
|
* @name ReporterCapabilities#parallel
|
||||||
|
* @type boolean | undefined
|
||||||
|
* @default false
|
||||||
|
* @see running_specs_in_parallel
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
|
||||||
const events = [
|
const events = [
|
||||||
/**
|
/**
|
||||||
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
|
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
|
||||||
|
|||||||
@@ -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
|
* @namespace jasmine
|
||||||
*/
|
*/
|
||||||
jasmine: jasmine
|
jasmine: jasmine
|
||||||
@@ -478,5 +484,27 @@ getJasmineRequireObj().interface = function(jasmine, env) {
|
|||||||
return env.setDefaultSpyStrategy(defaultStrategyFn);
|
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;
|
return jasmineInterface;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -430,7 +430,11 @@ jasmineRequire.HtmlReporter = function(j$) {
|
|||||||
'tr',
|
'tr',
|
||||||
{},
|
{},
|
||||||
createDom('td', {}, entry.timestamp.toString()),
|
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 {
|
table, th, td {
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.jasmine-debug-log-msg {
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user