Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04133264e0 | ||
|
|
d2bf6062cb | ||
|
|
fb639d0f55 | ||
|
|
52b1a3a7f8 | ||
|
|
1f7880ee8c | ||
|
|
a6e1aef8d7 | ||
|
|
d2815982ce | ||
|
|
aa979277fb | ||
|
|
1e0c312f9f | ||
|
|
c5db939886 | ||
|
|
e470fb56d7 | ||
|
|
a8a6577cd7 | ||
|
|
1660015c12 | ||
|
|
faf210ab4c | ||
|
|
00fd4a819f | ||
|
|
091cd8c3b6 | ||
|
|
aba0c98eb9 | ||
|
|
a7eff79db0 | ||
|
|
2a5673e6ab | ||
|
|
c13dd26c4b | ||
|
|
2e8b477489 | ||
|
|
b2c2e08641 | ||
|
|
d7d75abc42 | ||
|
|
0b71d0a2a0 | ||
|
|
dfa5b6a53d | ||
|
|
7f75f23e5b | ||
|
|
502cb24bb8 | ||
|
|
0ae234dc6e | ||
|
|
38d102f1d1 | ||
|
|
906f37fe52 | ||
|
|
4a2b10998a | ||
|
|
d8b2efe4d6 | ||
|
|
9d9e8f0c17 | ||
|
|
4059ab7ba6 | ||
|
|
7b01003d0b | ||
|
|
8e85f3df74 | ||
|
|
b0034797fe | ||
|
|
83e9f88952 | ||
|
|
de13b47809 | ||
|
|
9e10743a1c | ||
|
|
5327157832 | ||
|
|
6e3128c792 | ||
|
|
bd2e877f4e | ||
|
|
5b23ffe174 | ||
|
|
384e0859c7 | ||
|
|
616682e487 | ||
|
|
3234d475cd |
@@ -3,25 +3,22 @@
|
|||||||
|
|
||||||
version: 2.1
|
version: 2.1
|
||||||
|
|
||||||
orbs:
|
|
||||||
node: circleci/node@3.0.0
|
|
||||||
|
|
||||||
executors:
|
executors:
|
||||||
node16:
|
node16:
|
||||||
docker:
|
docker:
|
||||||
- image: cimg/node:16.1.0-browsers
|
- image: cimg/node:16.14.0 # Latest 16.x
|
||||||
working_directory: ~/workspace
|
working_directory: ~/workspace
|
||||||
node14:
|
node14:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/node:14
|
- image: cimg/node:14.17.4 # Latest 14.x
|
||||||
working_directory: ~/workspace
|
working_directory: ~/workspace
|
||||||
node12_latest:
|
node12_latest:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/node:12
|
- image: cimg/node:12.22.10 # Latest 12.x
|
||||||
working_directory: ~/workspace
|
working_directory: ~/workspace
|
||||||
node12_17:
|
node12_17:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/node:12.17
|
- image: cimg/node:12.17.0 # Oldest version supported by Jasmine
|
||||||
working_directory: ~/workspace
|
working_directory: ~/workspace
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -60,8 +57,6 @@ jobs:
|
|||||||
|
|
||||||
test_browsers: &test_browsers
|
test_browsers: &test_browsers
|
||||||
executor: node14
|
executor: node14
|
||||||
environment:
|
|
||||||
SKIP_JASMINE_BROWSER_FLAKES: "true"
|
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: .
|
at: .
|
||||||
@@ -69,10 +64,10 @@ jobs:
|
|||||||
name: Install Sauce Connect
|
name: Install Sauce Connect
|
||||||
command: |
|
command: |
|
||||||
cd /tmp
|
cd /tmp
|
||||||
curl https://saucelabs.com/downloads/sc-4.6.4-linux.tar.gz | tar zxf -
|
curl https://saucelabs.com/downloads/sc-4.7.1-linux.tar.gz | tar zxf -
|
||||||
chmod +x sc-4.6.4-linux/bin/sc
|
chmod +x sc-4.7.1-linux/bin/sc
|
||||||
mkdir ~/workspace/bin
|
mkdir ~/workspace/bin
|
||||||
cp sc-4.6.4-linux/bin/sc ~/workspace/bin
|
cp sc-4.7.1-linux/bin/sc ~/workspace/bin
|
||||||
~/workspace/bin/sc --version
|
~/workspace/bin/sc --version
|
||||||
- run:
|
- run:
|
||||||
name: Run tests
|
name: Run tests
|
||||||
@@ -90,58 +85,8 @@ jobs:
|
|||||||
scripts/stop-sauce-connect $(cat sauce-pidfile)
|
scripts/stop-sauce-connect $(cat sauce-pidfile)
|
||||||
exit $exitcode
|
exit $exitcode
|
||||||
|
|
||||||
test_browser_flakes:
|
|
||||||
<<: *test_browsers
|
|
||||||
environment:
|
|
||||||
SKIP_JASMINE_BROWSER_FLAKES: "false"
|
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
cron:
|
|
||||||
triggers:
|
|
||||||
- schedule:
|
|
||||||
# Times are UTC.
|
|
||||||
cron: "0 11 * * *"
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- main
|
|
||||||
- "3.99"
|
|
||||||
- "4.0"
|
|
||||||
jobs:
|
|
||||||
- build:
|
|
||||||
executor: node16
|
|
||||||
name: build_node_16
|
|
||||||
- build:
|
|
||||||
executor: node14
|
|
||||||
name: build_node_14
|
|
||||||
- build:
|
|
||||||
executor: node12_latest
|
|
||||||
name: build_node_12_latest
|
|
||||||
- build:
|
|
||||||
executor: node12_17
|
|
||||||
name: build_node_12_17
|
|
||||||
- test_node:
|
|
||||||
executor: node16
|
|
||||||
name: test_node_16
|
|
||||||
requires:
|
|
||||||
- build_node_16
|
|
||||||
- test_node:
|
|
||||||
executor: node12_latest
|
|
||||||
name: test_node_12_latest
|
|
||||||
requires:
|
|
||||||
- build_node_12_latest
|
|
||||||
- test_node:
|
|
||||||
executor: node12_17
|
|
||||||
name: test_node_12_17
|
|
||||||
requires:
|
|
||||||
- build_node_12_17
|
|
||||||
- test_browsers:
|
|
||||||
requires:
|
|
||||||
- build_node_14
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
ignore: /pull\/.*/ # Don't run on pull requests.
|
|
||||||
|
|
||||||
push:
|
push:
|
||||||
jobs:
|
jobs:
|
||||||
@@ -183,23 +128,3 @@ workflows:
|
|||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
ignore: /pull\/.*/ # Don't run on pull requests.
|
ignore: /pull\/.*/ # Don't run on pull requests.
|
||||||
|
|
||||||
browser-flakes:
|
|
||||||
triggers:
|
|
||||||
- schedule:
|
|
||||||
# Times are UTC.
|
|
||||||
cron: "0 10 * * *"
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- browser-flakes
|
|
||||||
jobs:
|
|
||||||
- build:
|
|
||||||
executor: node14
|
|
||||||
name: build_node_14
|
|
||||||
- test_browser_flakes:
|
|
||||||
requires:
|
|
||||||
- build_node_14
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
ignore: /pull\/.*/ # Don't run on pull requests.
|
|
||||||
|
|||||||
46
README.md
46
README.md
@@ -20,35 +20,20 @@ Please read the [contributors' guide](https://github.com/jasmine/jasmine/blob/ma
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
For the Jasmine NPM module:<br>
|
There are several different ways to install Jasmine, depending on your
|
||||||
[https://github.com/jasmine/jasmine-npm](https://github.com/jasmine/jasmine-npm).
|
environment and how you'd like to use it. See the [Getting Started page](https://jasmine.github.io/pages/getting_started.html)
|
||||||
|
for details.
|
||||||
|
|
||||||
For the Jasmine browser runner:<br>
|
## Usage
|
||||||
[https://github.com/jasmine/jasmine-browser](https://github.com/jasmine/jasmine-browser).
|
|
||||||
|
|
||||||
To install Jasmine standalone on your local box (where **_{#.#.#}_** below is substituted by the release number downloaded):
|
See the [documentation site](https://jasmine.github.io/pages/docs_home.html),
|
||||||
|
particularly the [Your First Suite tutorial](https://jasmine.github.io/tutorials/your_first_suite)
|
||||||
* Download the standalone distribution for your desired release from the [releases page](https://github.com/jasmine/jasmine/releases).
|
for information on writing specs.
|
||||||
* Create a Jasmine directory in your project. - `mkdir my-project/jasmine`
|
|
||||||
* Move the dist to your project directory. - `mv jasmine/dist/jasmine-standalone-{#.#.#}.zip my-project/jasmine`
|
|
||||||
* Change directory. - `cd my-project/jasmine`
|
|
||||||
* Unzip the dist. - `unzip jasmine-standalone-{#.#.#}.zip`
|
|
||||||
|
|
||||||
Add the following to your HTML file:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<link rel="shortcut icon" type="image/png" href="lib/jasmine-{#.#.#}/jasmine_favicon.png">
|
|
||||||
<link rel="stylesheet" type="text/css" href="lib/jasmine-{#.#.#}/jasmine.css">
|
|
||||||
|
|
||||||
<script type="text/javascript" src="lib/jasmine-{#.#.#}/jasmine.js"></script>
|
|
||||||
<script type="text/javascript" src="lib/jasmine-{#.#.#}/jasmine-html.js"></script>
|
|
||||||
<script type="text/javascript" src="lib/jasmine-{#.#.#}/boot.js"></script>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Supported environments
|
## Supported environments
|
||||||
|
|
||||||
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 nodejs.
|
Microsoft Edge) as well as Node.
|
||||||
|
|
||||||
| Environment | Supported versions |
|
| Environment | Supported versions |
|
||||||
|-------------------|--------------------|
|
|-------------------|--------------------|
|
||||||
@@ -74,18 +59,19 @@ for the supported environments for each Jasmine release.
|
|||||||
|
|
||||||
## Maintainers
|
## Maintainers
|
||||||
|
|
||||||
* [Gregg Van Hove](mailto:gvanhove@pivotal.io), Pivotal Labs
|
* [Gwendolyn Van Hove](mailto:gwen@slackersoft.net)
|
||||||
|
* [Steve Gravrock](mailto:sdg@panix.com)
|
||||||
|
|
||||||
### Maintainers Emeritus
|
### Maintainers Emeritus
|
||||||
|
|
||||||
* [Davis W. Frank](mailto:dwfrank@pivotal.io), Pivotal Labs
|
* [Davis W. Frank](mailto:dwfrank@pivotal.io)
|
||||||
* [Rajan Agaskar](mailto:rajan@pivotal.io), Pivotal Labs
|
* [Rajan Agaskar](mailto:rajan@pivotal.io)
|
||||||
* [Greg Cobb](mailto:gcobb@pivotal.io), Pivotal Labs
|
* [Greg Cobb](mailto:gcobb@pivotal.io)
|
||||||
* [Chris Amavisca](mailto:camavisca@pivotal.io), Pivotal Labs
|
* [Chris Amavisca](mailto:camavisca@pivotal.io)
|
||||||
* [Christian Williams](mailto:antixian666@gmail.com), Cloud Foundry
|
* [Christian Williams](mailto:antixian666@gmail.com)
|
||||||
* Sheel Choksi
|
* Sheel Choksi
|
||||||
|
|
||||||
Copyright (c) 2008-2018 Pivotal Labs. This software is licensed under the MIT License.
|
Copyright (c) 2008-2022 Jasmine Maintainers. This software is licensed under the MIT License.
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ When ready to release - specs are all green and the stories are done:
|
|||||||
### Commit and push core changes
|
### Commit and push core changes
|
||||||
|
|
||||||
1. Run the browser tests using `scripts/run-all-browsers`.
|
1. Run the browser tests using `scripts/run-all-browsers`.
|
||||||
1. Commit release notes and version changes (jasmine.js, version.rb, package.json)
|
1. Commit release notes and version changes (jasmine.js, package.json)
|
||||||
1. Push
|
1. Push
|
||||||
1. Wait for Circle CI to go green
|
1. Wait for Circle CI to go green
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -152,6 +152,7 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
|
|||||||
'toHaveBeenCalledTimes',
|
'toHaveBeenCalledTimes',
|
||||||
'toHaveBeenCalledWith',
|
'toHaveBeenCalledWith',
|
||||||
'toHaveClass',
|
'toHaveClass',
|
||||||
|
'toHaveSpyInteractions',
|
||||||
'toMatch',
|
'toMatch',
|
||||||
'toThrow',
|
'toThrow',
|
||||||
'toThrowError',
|
'toThrowError',
|
||||||
@@ -640,6 +641,8 @@ getJasmineRequireObj().util = function(j$) {
|
|||||||
// All falsey values are either primitives, `null`, or `undefined.
|
// All falsey values are either primitives, `null`, or `undefined.
|
||||||
if (!argsAsArray[i] || str.match(primitives)) {
|
if (!argsAsArray[i] || str.match(primitives)) {
|
||||||
clonedArgs.push(argsAsArray[i]);
|
clonedArgs.push(argsAsArray[i]);
|
||||||
|
} else if (str === '[object Date]') {
|
||||||
|
clonedArgs.push(new Date(argsAsArray[i].valueOf()));
|
||||||
} else {
|
} else {
|
||||||
clonedArgs.push(j$.util.clone(argsAsArray[i]));
|
clonedArgs.push(j$.util.clone(argsAsArray[i]));
|
||||||
}
|
}
|
||||||
@@ -1039,7 +1042,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
|||||||
boilerplateEnd =
|
boilerplateEnd =
|
||||||
boilerplateStart + Spec.pendingSpecExceptionMessage.length;
|
boilerplateStart + Spec.pendingSpecExceptionMessage.length;
|
||||||
|
|
||||||
return fullMessage.substr(boilerplateEnd);
|
return fullMessage.slice(boilerplateEnd);
|
||||||
};
|
};
|
||||||
|
|
||||||
Spec.pendingSpecExceptionMessage = '=> marked Pending';
|
Spec.pendingSpecExceptionMessage = '=> marked Pending';
|
||||||
@@ -2169,7 +2172,10 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
}
|
}
|
||||||
addSpecsToSuite(suite, specDefinitions);
|
addSpecsToSuite(suite, specDefinitions);
|
||||||
if (suite.parentSuite && !suite.children.length) {
|
if (suite.parentSuite && !suite.children.length) {
|
||||||
throw new Error('describe with no children (describe() or it())');
|
throw new Error(
|
||||||
|
'describe with no children (describe() or it()): ' +
|
||||||
|
suite.getFullName()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return suite.metadata;
|
return suite.metadata;
|
||||||
};
|
};
|
||||||
@@ -5576,17 +5582,16 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function keys(obj, isArray) {
|
function keys(obj, isArray) {
|
||||||
var allKeys = Object.keys
|
var allKeys = (function(o) {
|
||||||
? Object.keys(obj)
|
var keys = [];
|
||||||
: (function(o) {
|
for (var key in o) {
|
||||||
var keys = [];
|
if (j$.util.has(o, key)) {
|
||||||
for (var key in o) {
|
keys.push(key);
|
||||||
if (j$.util.has(o, key)) {
|
}
|
||||||
keys.push(key);
|
}
|
||||||
}
|
// eslint-disable-next-line compat/compat
|
||||||
}
|
return keys.concat(Object.getOwnPropertySymbols(o));
|
||||||
return keys;
|
})(obj);
|
||||||
})(obj);
|
|
||||||
|
|
||||||
if (!isArray) {
|
if (!isArray) {
|
||||||
return allKeys;
|
return allKeys;
|
||||||
@@ -5956,6 +5961,14 @@ getJasmineRequireObj().toBeCloseTo = function() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Infinity is close to Infinity and -Infinity is close to -Infinity,
|
||||||
|
// regardless of the precision.
|
||||||
|
if (expected === Infinity || expected === -Infinity) {
|
||||||
|
return {
|
||||||
|
pass: actual === expected
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var pow = Math.pow(10, precision + 1);
|
var pow = Math.pow(10, precision + 1);
|
||||||
var delta = Math.abs(expected - actual);
|
var delta = Math.abs(expected - actual);
|
||||||
var maxDelta = Math.pow(10, -precision) / 2;
|
var maxDelta = Math.pow(10, -precision) / 2;
|
||||||
@@ -6926,6 +6939,82 @@ getJasmineRequireObj().toHaveSize = function(j$) {
|
|||||||
return toHaveSize;
|
return toHaveSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getJasmineRequireObj().toHaveSpyInteractions = function(j$) {
|
||||||
|
var getErrorMsg = j$.formatErrorMsg(
|
||||||
|
'<toHaveSpyInteractions>',
|
||||||
|
'expect(<spyObj>).toHaveSpyInteractions()'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link expect} the actual (a {@link SpyObj}) spies to have been called.
|
||||||
|
* @function
|
||||||
|
* @name matchers#toHaveSpyInteractions
|
||||||
|
* @since 4.1.0
|
||||||
|
* @example
|
||||||
|
* expect(mySpyObj).toHaveSpyInteractions();
|
||||||
|
* expect(mySpyObj).not.toHaveSpyInteractions();
|
||||||
|
*/
|
||||||
|
function toHaveSpyInteractions(matchersUtil) {
|
||||||
|
return {
|
||||||
|
compare: function(actual) {
|
||||||
|
var result = {};
|
||||||
|
|
||||||
|
if (!j$.isObject_(actual)) {
|
||||||
|
throw new Error(
|
||||||
|
getErrorMsg('Expected a spy object, but got ' + typeof actual + '.')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments.length > 1) {
|
||||||
|
throw new Error(getErrorMsg('Does not take arguments'));
|
||||||
|
}
|
||||||
|
|
||||||
|
result.pass = false;
|
||||||
|
let hasSpy = false;
|
||||||
|
const calledSpies = [];
|
||||||
|
for (const spy of Object.values(actual)) {
|
||||||
|
if (!j$.isSpy(spy)) continue;
|
||||||
|
hasSpy = true;
|
||||||
|
|
||||||
|
if (spy.calls.any()) {
|
||||||
|
result.pass = true;
|
||||||
|
calledSpies.push([spy.and.identity, spy.calls.count()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasSpy) {
|
||||||
|
throw new Error(
|
||||||
|
getErrorMsg(
|
||||||
|
'Expected a spy object with spies, but object has no spies.'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let resultMessage;
|
||||||
|
if (result.pass) {
|
||||||
|
resultMessage =
|
||||||
|
'Expected spy object spies not to have been called, ' +
|
||||||
|
'but the following spies were called: ';
|
||||||
|
resultMessage += calledSpies
|
||||||
|
.map(([spyName, spyCount]) => {
|
||||||
|
return `${spyName} called ${spyCount} time(s)`;
|
||||||
|
})
|
||||||
|
.join(', ');
|
||||||
|
} else {
|
||||||
|
resultMessage =
|
||||||
|
'Expected spy object spies to have been called, ' +
|
||||||
|
'but no spies were called.';
|
||||||
|
}
|
||||||
|
result.message = resultMessage;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return toHaveSpyInteractions;
|
||||||
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().toMatch = function(j$) {
|
getJasmineRequireObj().toMatch = function(j$) {
|
||||||
var getErrorMsg = j$.formatErrorMsg(
|
var getErrorMsg = j$.formatErrorMsg(
|
||||||
'<toMatch>',
|
'<toMatch>',
|
||||||
@@ -7488,7 +7577,7 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) {
|
|||||||
this.emitScalar('<global>');
|
this.emitScalar('<global>');
|
||||||
} else if (value.jasmineToString) {
|
} else if (value.jasmineToString) {
|
||||||
this.emitScalar(value.jasmineToString(this.pp_));
|
this.emitScalar(value.jasmineToString(this.pp_));
|
||||||
} else if (typeof value === 'string') {
|
} else if (j$.isString_(value)) {
|
||||||
this.emitString(value);
|
this.emitString(value);
|
||||||
} else if (j$.isSpy(value)) {
|
} else if (j$.isSpy(value)) {
|
||||||
this.emitScalar('spy on ' + value.and.identity);
|
this.emitScalar('spy on ' + value.and.identity);
|
||||||
@@ -8031,7 +8120,10 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
|||||||
maybeThenable = queueableFn.fn.call(self.userContext);
|
maybeThenable = queueableFn.fn.call(self.userContext);
|
||||||
|
|
||||||
if (maybeThenable && j$.isFunction_(maybeThenable.then)) {
|
if (maybeThenable && j$.isFunction_(maybeThenable.then)) {
|
||||||
maybeThenable.then(next, onPromiseRejection);
|
maybeThenable.then(
|
||||||
|
wrapInPromiseResolutionHandler(next),
|
||||||
|
onPromiseRejection
|
||||||
|
);
|
||||||
completedSynchronously = false;
|
completedSynchronously = false;
|
||||||
return { completedSynchronously: false };
|
return { completedSynchronously: false };
|
||||||
}
|
}
|
||||||
@@ -8130,6 +8222,16 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function wrapInPromiseResolutionHandler(fn) {
|
||||||
|
return function(maybeArg) {
|
||||||
|
if (j$.isError_(maybeArg)) {
|
||||||
|
fn(maybeArg);
|
||||||
|
} else {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return QueueRunner;
|
return QueueRunner;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -10186,5 +10288,5 @@ getJasmineRequireObj().UserContext = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().version = function() {
|
getJasmineRequireObj().version = function() {
|
||||||
return '4.0.0';
|
return '4.1.0';
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jasmine-core",
|
"name": "jasmine-core",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "4.0.0",
|
"version": "4.1.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/jasmine/jasmine.git"
|
"url": "https://github.com/jasmine/jasmine.git"
|
||||||
|
|||||||
22
release_notes/3.99.1.md
Normal file
22
release_notes/3.99.1.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Jasmine Core 3.99.1 Release Notes
|
||||||
|
|
||||||
|
This release fixes a bug in 3.99.0, which incorrectly reported a deprecation
|
||||||
|
warning when a promise returned from a function passed to `it`, `beforeEach`,
|
||||||
|
etc was resolved to a value.
|
||||||
|
|
||||||
|
## Supported environments
|
||||||
|
|
||||||
|
jasmine-core 3.99.1 has been tested in the following environments.
|
||||||
|
|
||||||
|
| Environment | Supported versions |
|
||||||
|
|-------------------|--------------------|
|
||||||
|
| Node | 10, 12, 14, 16 |
|
||||||
|
| Safari | 10-14 |
|
||||||
|
| Chrome | 98 |
|
||||||
|
| Firefox | 97, 78, 68 |
|
||||||
|
| Edge | 98 |
|
||||||
|
| Internet Explorer | 10, 11 |
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||||
21
release_notes/4.0.1.md
Normal file
21
release_notes/4.0.1.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Jasmine Core 4.0.1 Release Notes
|
||||||
|
|
||||||
|
This release fixes a bug in 4.0.0, which incorrectly reported a failure
|
||||||
|
when a promise returned from a function passed to `it`, `beforeEach`,
|
||||||
|
etc was resolved to a value.
|
||||||
|
|
||||||
|
## Supported environments
|
||||||
|
|
||||||
|
jasmine-core 4.0.1 has been tested in the following environments.
|
||||||
|
|
||||||
|
| Environment | Supported versions |
|
||||||
|
|-------------------|--------------------|
|
||||||
|
| Node | 12.17+, 14, 16 |
|
||||||
|
| Safari | 14-15 |
|
||||||
|
| Chrome | 98 |
|
||||||
|
| Firefox | 91, 97 |
|
||||||
|
| Edge | 98 |
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||||
38
release_notes/4.1.0.md
Normal file
38
release_notes/4.1.0.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Jasmine 4.1.0 Release Notes
|
||||||
|
|
||||||
|
## New Features and Bug Fixes
|
||||||
|
|
||||||
|
* toBeCloseTo treats Infinity and -Infinity as close to themselves
|
||||||
|
* Fixes [#1957](https://github.com/jasmine/jasmine/issues/1957)
|
||||||
|
|
||||||
|
* Replaced uses of deprecated String.prototype.substr()
|
||||||
|
* Merges [#1962](https://github.com/jasmine/jasmine/pull/1962) from @CommanderRoot
|
||||||
|
|
||||||
|
* Removed obsolete vendor-specific background-size CSS rules
|
||||||
|
* Fixes [#1961](https://github.com/jasmine/jasmine/issues/1961)
|
||||||
|
|
||||||
|
* Added toHaveSpyInteractions matcher
|
||||||
|
* Merges [#1959](https://github.com/jasmine/jasmine/pull/1959) from @nitobuenida
|
||||||
|
* Fixes [#1568](https://github.com/jasmine/jasmine/issues/1568)
|
||||||
|
|
||||||
|
* Pretty-print [new String("")] as "[ '' ]", not "[]"
|
||||||
|
|
||||||
|
* Fixed cloning of Date objects in Spy#calls#saveArgumentsByValue
|
||||||
|
* Merges [#1955](https://github.com/jasmine/jasmine/pull/1955) from @coyoteecd
|
||||||
|
* Fixes [#1885](https://github.com/jasmine/jasmine/issues/1885)
|
||||||
|
|
||||||
|
* Include the name of the suite in the empty suite error message
|
||||||
|
|
||||||
|
* toEqual checks keys that are Symbols
|
||||||
|
* Merges [#1879](https://github.com/jasmine/jasmine/pull/1879) from @laeleoni
|
||||||
|
* Fixes [#1811](https://github.com/jasmine/jasmine/issues/1811)
|
||||||
|
|
||||||
|
## Documentation Updates
|
||||||
|
|
||||||
|
* Replaced redundant installation instructions in README with link to docs
|
||||||
|
|
||||||
|
* Added links to usage instructions to README
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||||
@@ -235,9 +235,17 @@ describe('Env', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('throws an error when it has no children', function() {
|
it('throws an error when it has no children', function() {
|
||||||
expect(function() {
|
let ran = false;
|
||||||
env.describe('done method', function() {});
|
env.describe('parent suite', function() {
|
||||||
}).toThrowError('describe with no children (describe() or it())');
|
expect(function() {
|
||||||
|
env.describe('child suite', function() {});
|
||||||
|
}).toThrowError(
|
||||||
|
'describe with no children (describe() or it()): parent suite child suite'
|
||||||
|
);
|
||||||
|
ran = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(ran).toBeTrue();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,14 @@ describe('PrettyPrinter', function() {
|
|||||||
expect(pp("som' string")).toEqual("'som' string'");
|
expect(pp("som' string")).toEqual("'som' string'");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('stringifies empty string primitives and objects recognizably', function() {
|
||||||
|
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||||
|
expect(pp(new String(''))).toEqual(pp(''));
|
||||||
|
expect(pp(new String(''))).toEqual("''");
|
||||||
|
expect(pp([new String('')])).toEqual(pp(['']));
|
||||||
|
expect(pp([new String('')])).toEqual("[ '' ]");
|
||||||
|
});
|
||||||
|
|
||||||
it('should stringify primitives properly', function() {
|
it('should stringify primitives properly', function() {
|
||||||
var pp = jasmineUnderTest.makePrettyPrinter();
|
var pp = jasmineUnderTest.makePrettyPrinter();
|
||||||
expect(pp(true)).toEqual('true');
|
expect(pp(true)).toEqual('true');
|
||||||
|
|||||||
@@ -156,6 +156,81 @@ describe('QueueRunner', function() {
|
|||||||
expect(failFn).toHaveBeenCalledWith(err);
|
expect(failFn).toHaveBeenCalledWith(err);
|
||||||
expect(queueableFn2.fn).toHaveBeenCalled();
|
expect(queueableFn2.fn).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('as a result of a promise', function() {
|
||||||
|
describe('and the argument is an Error', function() {
|
||||||
|
// Since promise support was added, Jasmine has failed specs that
|
||||||
|
// return a promise that resolves to an error. That's probably not
|
||||||
|
// the desired behavior but it's also not something we should change
|
||||||
|
// except on a major release and with a deprecation warning in
|
||||||
|
// advance.
|
||||||
|
it('explicitly fails and moves to the next function', function(done) {
|
||||||
|
var err = new Error('foo'),
|
||||||
|
queueableFn1 = {
|
||||||
|
fn: function() {
|
||||||
|
return Promise.resolve(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
||||||
|
failFn = jasmine.createSpy('fail'),
|
||||||
|
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||||
|
queueableFns: [queueableFn1, queueableFn2],
|
||||||
|
fail: failFn,
|
||||||
|
onComplete: function() {
|
||||||
|
expect(failFn).toHaveBeenCalledWith(err);
|
||||||
|
expect(queueableFn2.fn).toHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
queueRunner.execute();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not log a deprecation', function(done) {
|
||||||
|
var err = new Error('foo'),
|
||||||
|
queueableFn1 = {
|
||||||
|
fn: function() {
|
||||||
|
return Promise.resolve(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deprecated = jasmine.createSpy('deprecated'),
|
||||||
|
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||||
|
queueableFns: [queueableFn1],
|
||||||
|
deprecated: deprecated,
|
||||||
|
onComplete: function() {
|
||||||
|
expect(deprecated).not.toHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
queueRunner.execute();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and the argument is not an Error', function() {
|
||||||
|
it('does not log a deprecation or report a failure', function(done) {
|
||||||
|
var queueableFn1 = {
|
||||||
|
fn: function() {
|
||||||
|
return Promise.resolve('not an error');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
failFn = jasmine.createSpy('fail'),
|
||||||
|
deprecated = jasmine.createSpy('deprecated'),
|
||||||
|
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||||
|
queueableFns: [queueableFn1],
|
||||||
|
deprecated: deprecated,
|
||||||
|
fail: failFn,
|
||||||
|
onComplete: function() {
|
||||||
|
expect(deprecated).not.toHaveBeenCalled();
|
||||||
|
expect(failFn).not.toHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
queueRunner.execute();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not cause an explicit fail if execution is being stopped', function() {
|
it('does not cause an explicit fail if execution is being stopped', function() {
|
||||||
|
|||||||
@@ -139,6 +139,32 @@ describe('jasmineUnderTest.util', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('cloneArgs', function() {
|
||||||
|
it('clones primitives as-is', function() {
|
||||||
|
expect(jasmineUnderTest.util.cloneArgs([true, false])).toEqual([
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]);
|
||||||
|
expect(jasmineUnderTest.util.cloneArgs([0, 1])).toEqual([0, 1]);
|
||||||
|
expect(jasmineUnderTest.util.cloneArgs(['str'])).toEqual(['str']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('clones Regexp objects as-is', function() {
|
||||||
|
var regex = /match/;
|
||||||
|
expect(jasmineUnderTest.util.cloneArgs([regex])).toEqual([regex]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('clones Date objects as-is', function() {
|
||||||
|
var date = new Date(2022, 1, 1);
|
||||||
|
expect(jasmineUnderTest.util.cloneArgs([date])).toEqual([date]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('clones null and undefined', function() {
|
||||||
|
expect(jasmineUnderTest.util.cloneArgs([null])).toEqual([null]);
|
||||||
|
expect(jasmineUnderTest.util.cloneArgs([undefined])).toEqual([undefined]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('getPropertyDescriptor', function() {
|
describe('getPropertyDescriptor', function() {
|
||||||
it('get property descriptor from object', function() {
|
it('get property descriptor from object', function() {
|
||||||
var obj = { prop: 1 },
|
var obj = { prop: 1 },
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ describe('ArrayContaining', function() {
|
|||||||
if (
|
if (
|
||||||
typeof a == 'string' &&
|
typeof a == 'string' &&
|
||||||
typeof b == 'string' &&
|
typeof b == 'string' &&
|
||||||
a.substr(0, 3) == 'foo' &&
|
a.slice(0, 3) == 'foo' &&
|
||||||
b.substr(0, 3) == 'foo'
|
b.slice(0, 3) == 'foo'
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ describe('ArrayWithExactContents', function() {
|
|||||||
if (
|
if (
|
||||||
typeof a == 'string' &&
|
typeof a == 'string' &&
|
||||||
typeof b == 'string' &&
|
typeof b == 'string' &&
|
||||||
a.substr(0, 3) == 'foo' &&
|
a.slice(0, 3) == 'foo' &&
|
||||||
b.substr(0, 3) == 'foo'
|
b.slice(0, 3) == 'foo'
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,8 +121,8 @@ describe('ObjectContaining', function() {
|
|||||||
if (
|
if (
|
||||||
typeof a == 'string' &&
|
typeof a == 'string' &&
|
||||||
typeof b == 'string' &&
|
typeof b == 'string' &&
|
||||||
a.substr(0, 3) == 'foo' &&
|
a.slice(0, 3) == 'foo' &&
|
||||||
b.substr(0, 3) == 'foo'
|
b.slice(0, 3) == 'foo'
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ describe('Custom Matchers (Integration)', function() {
|
|||||||
if (
|
if (
|
||||||
typeof a == 'string' &&
|
typeof a == 'string' &&
|
||||||
typeof b == 'string' &&
|
typeof b == 'string' &&
|
||||||
a.substr(0, 3) == 'foo' &&
|
a.slice(0, 3) == 'foo' &&
|
||||||
b.substr(0, 3) == 'foo'
|
b.slice(0, 3) == 'foo'
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -455,10 +455,6 @@ describe('Env integration', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('copes with async failures after done has been called', function(done) {
|
it('copes with async failures after done has been called', function(done) {
|
||||||
if (jasmine.getEnv().skipBrowserFlake) {
|
|
||||||
jasmine.getEnv().skipBrowserFlake();
|
|
||||||
}
|
|
||||||
|
|
||||||
var global = {
|
var global = {
|
||||||
setTimeout: function(fn, delay) {
|
setTimeout: function(fn, delay) {
|
||||||
return setTimeout(fn, delay);
|
return setTimeout(fn, delay);
|
||||||
@@ -1174,10 +1170,6 @@ describe('Env integration', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Mock clock can be installed and used in tests', function(done) {
|
it('Mock clock can be installed and used in tests', function(done) {
|
||||||
if (jasmine.getEnv().skipBrowserFlake) {
|
|
||||||
jasmine.getEnv().skipBrowserFlake();
|
|
||||||
}
|
|
||||||
|
|
||||||
var globalSetTimeout = jasmine
|
var globalSetTimeout = jasmine
|
||||||
.createSpy('globalSetTimeout')
|
.createSpy('globalSetTimeout')
|
||||||
.and.callFake(function(cb, t) {
|
.and.callFake(function(cb, t) {
|
||||||
@@ -1318,16 +1310,13 @@ describe('Env integration', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should not use the mock clock for asynchronous timeouts', function(done) {
|
it('should not use the mock clock for asynchronous timeouts', function(done) {
|
||||||
if (jasmine.getEnv().skipBrowserFlake) {
|
|
||||||
jasmine.getEnv().skipBrowserFlake();
|
|
||||||
}
|
|
||||||
|
|
||||||
createMockedEnv();
|
createMockedEnv();
|
||||||
var reporter = jasmine.createSpyObj('fakeReporter', ['specDone']),
|
var reporter = jasmine.createSpyObj('fakeReporter', ['specDone']),
|
||||||
clock = env.clock;
|
clock = env.clock;
|
||||||
|
|
||||||
reporter.specDone.and.callFake(function() {
|
reporter.specDone.and.callFake(function() {
|
||||||
realSetTimeout(function() {
|
realSetTimeout(function() {
|
||||||
|
jasmine.debugLog('Ticking after specDone');
|
||||||
jasmine.clock().tick(1);
|
jasmine.clock().tick(1);
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
@@ -1346,24 +1335,24 @@ describe('Env integration', function() {
|
|||||||
env.it('spec that should not time out', function(innerDone) {
|
env.it('spec that should not time out', function(innerDone) {
|
||||||
clock.tick(6);
|
clock.tick(6);
|
||||||
expect(true).toEqual(true);
|
expect(true).toEqual(true);
|
||||||
realSetTimeout(innerDone);
|
jasmine.debugLog('Calling realSetTimeout in spec');
|
||||||
|
realSetTimeout(function() {
|
||||||
|
jasmine.debugLog('Calling innerDone');
|
||||||
|
innerDone();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
env.execute(null, function() {
|
env.execute(null, function() {
|
||||||
expect(reporter.specDone).toHaveBeenCalledTimes(1);
|
expect(reporter.specDone).toHaveBeenCalledTimes(1);
|
||||||
expect(reporter.specDone.calls.argsFor(0)[0]).toEqual(
|
const event = reporter.specDone.calls.argsFor(0)[0];
|
||||||
jasmine.objectContaining({ status: 'passed' })
|
jasmine.debugLog('Spec result: ' + jasmine.basicPrettyPrinter_(event));
|
||||||
);
|
expect(event).toEqual(jasmine.objectContaining({ status: 'passed' }));
|
||||||
jasmine.clock().tick(1);
|
jasmine.clock().tick(1);
|
||||||
realSetTimeout(done);
|
realSetTimeout(done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should wait a custom interval before reporting async functions that fail to complete', function(done) {
|
it('should wait a custom interval before reporting async functions that fail to complete', function(done) {
|
||||||
if (jasmine.getEnv().skipBrowserFlake) {
|
|
||||||
jasmine.getEnv().skipBrowserFlake();
|
|
||||||
}
|
|
||||||
|
|
||||||
createMockedEnv();
|
createMockedEnv();
|
||||||
var reporter = jasmine.createSpyObj('fakeReport', [
|
var reporter = jasmine.createSpyObj('fakeReport', [
|
||||||
'jasmineDone',
|
'jasmineDone',
|
||||||
@@ -2939,10 +2928,6 @@ describe('Env integration', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('provides custom equality testers to async matchers', function(done) {
|
it('provides custom equality testers to async matchers', function(done) {
|
||||||
if (jasmine.getEnv().skipBrowserFlake) {
|
|
||||||
jasmine.getEnv().skipBrowserFlake();
|
|
||||||
}
|
|
||||||
|
|
||||||
var specDone = jasmine.createSpy('specDone');
|
var specDone = jasmine.createSpy('specDone');
|
||||||
|
|
||||||
env.addReporter({ specDone: specDone });
|
env.addReporter({ specDone: specDone });
|
||||||
|
|||||||
22
spec/core/integration/MatchersSpec.js
Normal file → Executable file
22
spec/core/integration/MatchersSpec.js
Normal file → Executable file
@@ -625,6 +625,28 @@ describe('Matchers (Integration)', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('toHaveSpyInteractions', function() {
|
||||||
|
let spyObj;
|
||||||
|
beforeEach(function() {
|
||||||
|
spyObj = env.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||||
|
spyObj.otherMethod = function() {};
|
||||||
|
});
|
||||||
|
|
||||||
|
verifyPasses(function(env) {
|
||||||
|
spyObj.spyA();
|
||||||
|
env.expect(spyObj).toHaveSpyInteractions();
|
||||||
|
});
|
||||||
|
|
||||||
|
verifyFails(function(env) {
|
||||||
|
env.expect(spyObj).toHaveSpyInteractions();
|
||||||
|
});
|
||||||
|
|
||||||
|
verifyFails(function(env) {
|
||||||
|
spyObj.otherMethod();
|
||||||
|
env.expect(spyObj).toHaveSpyInteractions();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('toMatch', function() {
|
describe('toMatch', function() {
|
||||||
verifyPasses(function(env) {
|
verifyPasses(function(env) {
|
||||||
env.expect('foo').toMatch(/oo$/);
|
env.expect('foo').toMatch(/oo$/);
|
||||||
|
|||||||
@@ -110,4 +110,42 @@ describe('toBeCloseTo', function() {
|
|||||||
result = matcher.compare(-2.82665525779431, -2.82666, 5);
|
result = matcher.compare(-2.82665525779431, -2.82666, 5);
|
||||||
expect(result.pass).toBe(true);
|
expect(result.pass).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Infinity handling', function() {
|
||||||
|
it('passes when the actual and expected are both Infinity', function() {
|
||||||
|
const matcher = jasmineUnderTest.matchers.toBeCloseTo();
|
||||||
|
const result = matcher.compare(Infinity, Infinity, 0);
|
||||||
|
expect(result.pass).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('passes when the actual and expected are both -Infinity', function() {
|
||||||
|
const matcher = jasmineUnderTest.matchers.toBeCloseTo();
|
||||||
|
const result = matcher.compare(-Infinity, -Infinity, 0);
|
||||||
|
expect(result.pass).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails when the actual is Infinity and the expected is -Infinity', function() {
|
||||||
|
const matcher = jasmineUnderTest.matchers.toBeCloseTo();
|
||||||
|
const result = matcher.compare(Infinity, -Infinity, 0);
|
||||||
|
expect(result.pass).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails when the actual is -Infinity and the expected is Infinity', function() {
|
||||||
|
const matcher = jasmineUnderTest.matchers.toBeCloseTo();
|
||||||
|
const result = matcher.compare(-Infinity, Infinity, 0);
|
||||||
|
expect(result.pass).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails when the actual is a number and the expected is Infinity', function() {
|
||||||
|
const matcher = jasmineUnderTest.matchers.toBeCloseTo();
|
||||||
|
const result = matcher.compare(42, Infinity, 0);
|
||||||
|
expect(result.pass).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails when the actual is a number and the expected is -Infinity', function() {
|
||||||
|
const matcher = jasmineUnderTest.matchers.toBeCloseTo();
|
||||||
|
const result = matcher.compare(42, -Infinity, 0);
|
||||||
|
expect(result.pass).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable compat/compat */
|
||||||
describe('toEqual', function() {
|
describe('toEqual', function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
@@ -1039,4 +1040,94 @@ describe('toEqual', function() {
|
|||||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// == Symbols ==
|
||||||
|
|
||||||
|
describe('Symbols', function() {
|
||||||
|
it('Fails if Symbol compared to Object', function() {
|
||||||
|
var sym = Symbol('foo');
|
||||||
|
var obj = {};
|
||||||
|
|
||||||
|
expect(sym).not.toEqual(obj);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Passes Symbol with itself', function() {
|
||||||
|
var sym = Symbol('foo');
|
||||||
|
|
||||||
|
expect(sym).toEqual(sym);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Fails if two Symbols with same value are compared', function() {
|
||||||
|
var symA = Symbol('foo');
|
||||||
|
var symB = Symbol('foo');
|
||||||
|
|
||||||
|
expect(symA).not.toEqual(symB);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Fails if two Symbols with different value are compared', function() {
|
||||||
|
var symA = Symbol('foo');
|
||||||
|
var symB = Symbol('bar');
|
||||||
|
|
||||||
|
expect(symA).not.toEqual(symB);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Fails if Symbol compared to NaN', function() {
|
||||||
|
var sym = Symbol('foo');
|
||||||
|
|
||||||
|
expect(sym).not.toEqual(NaN);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Fails if Symbol compared to Infinity', function() {
|
||||||
|
var sym = Symbol('foo');
|
||||||
|
|
||||||
|
expect(sym).not.toEqual(Infinity);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Fails if Symbol compared to String', function() {
|
||||||
|
var sym = Symbol('foo');
|
||||||
|
var str = 'foo';
|
||||||
|
|
||||||
|
expect(sym).not.toEqual(str);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Fails if Symbol compared to Number', function() {
|
||||||
|
var sym = Symbol('foo');
|
||||||
|
var num = Math.random();
|
||||||
|
|
||||||
|
expect(sym).not.toEqual(num);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Fails if Symbol compared to Boolean', function() {
|
||||||
|
var sym = Symbol('foo');
|
||||||
|
|
||||||
|
expect(sym).not.toEqual(true);
|
||||||
|
expect(sym).not.toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Fails if Symbol compared to Undefined', function() {
|
||||||
|
var sym = Symbol('foo');
|
||||||
|
|
||||||
|
expect(sym).not.toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Fails if Symbol compared to null', function() {
|
||||||
|
var sym = Symbol('foo');
|
||||||
|
|
||||||
|
expect(sym).not.toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Fails if Symbol compared to []', function() {
|
||||||
|
var sym = Symbol('foo');
|
||||||
|
var arr = ['foo'];
|
||||||
|
|
||||||
|
expect(sym).not.toEqual(arr);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Fails if Symbol compared to Function', function() {
|
||||||
|
var sym = Symbol('foo');
|
||||||
|
var f = function func() {};
|
||||||
|
|
||||||
|
expect(sym).not.toEqual(f);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
115
spec/core/matchers/toHaveSpyInteractionsSpec.js
Executable file
115
spec/core/matchers/toHaveSpyInteractionsSpec.js
Executable file
@@ -0,0 +1,115 @@
|
|||||||
|
describe('toHaveSpyInteractions', function() {
|
||||||
|
it('passes when there are spy interactions', function() {
|
||||||
|
let matcher = jasmineUnderTest.matchers.toHaveSpyInteractions();
|
||||||
|
let spyObj = jasmineUnderTest
|
||||||
|
.getEnv()
|
||||||
|
.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||||
|
|
||||||
|
spyObj.spyA();
|
||||||
|
|
||||||
|
let result = matcher.compare(spyObj);
|
||||||
|
expect(result.pass).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('passes when there are multiple spy interactions', function() {
|
||||||
|
let matcher = jasmineUnderTest.matchers.toHaveSpyInteractions();
|
||||||
|
let spyObj = jasmineUnderTest
|
||||||
|
.getEnv()
|
||||||
|
.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||||
|
|
||||||
|
spyObj.spyA();
|
||||||
|
spyObj.spyB();
|
||||||
|
spyObj.spyA();
|
||||||
|
|
||||||
|
let result = matcher.compare(spyObj);
|
||||||
|
expect(result.pass).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails when there are no spy interactions', function() {
|
||||||
|
let matcher = jasmineUnderTest.matchers.toHaveSpyInteractions();
|
||||||
|
let spyObj = jasmineUnderTest
|
||||||
|
.getEnv()
|
||||||
|
.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||||
|
|
||||||
|
let result = matcher.compare(spyObj);
|
||||||
|
expect(result.pass).toBe(false);
|
||||||
|
expect(result.message).toContain(
|
||||||
|
'Expected spy object spies to have been called'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows the right message is negated', function() {
|
||||||
|
let matcher = jasmineUnderTest.matchers.toHaveSpyInteractions();
|
||||||
|
let spyObj = jasmineUnderTest
|
||||||
|
.getEnv()
|
||||||
|
.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||||
|
|
||||||
|
spyObj.spyA();
|
||||||
|
|
||||||
|
let result = matcher.compare(spyObj);
|
||||||
|
expect(result.pass).toBe(true);
|
||||||
|
expect(result.message).toContain(
|
||||||
|
// Will be shown only on negate.
|
||||||
|
'Expected spy object spies not to have been called'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails when only non-observed spy object interactions are interacted', function() {
|
||||||
|
let matcher = jasmineUnderTest.matchers.toHaveSpyInteractions();
|
||||||
|
let spyObj = jasmineUnderTest
|
||||||
|
.getEnv()
|
||||||
|
.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||||
|
spyObj.otherMethod = function() {};
|
||||||
|
|
||||||
|
spyObj.otherMethod();
|
||||||
|
|
||||||
|
let result = matcher.compare(spyObj);
|
||||||
|
expect(result.pass).toBe(false);
|
||||||
|
expect(result.message).toContain(
|
||||||
|
'Expected spy object spies to have been called'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`throws an error if a non-object is passed`, function() {
|
||||||
|
let matcher = jasmineUnderTest.matchers.toHaveSpyInteractions();
|
||||||
|
|
||||||
|
expect(function() {
|
||||||
|
matcher.compare(true);
|
||||||
|
}).toThrowError(Error, /Expected a spy object, but got/);
|
||||||
|
|
||||||
|
expect(function() {
|
||||||
|
matcher.compare(123);
|
||||||
|
}).toThrowError(Error, /Expected a spy object, but got/);
|
||||||
|
|
||||||
|
expect(function() {
|
||||||
|
matcher.compare('string');
|
||||||
|
}).toThrowError(Error, /Expected a spy object, but got/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws an error if arguments are passed', function() {
|
||||||
|
let matcher = jasmineUnderTest.matchers.toHaveSpyInteractions();
|
||||||
|
let spyObj = jasmineUnderTest
|
||||||
|
.getEnv()
|
||||||
|
.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||||
|
|
||||||
|
expect(function() {
|
||||||
|
matcher.compare(spyObj, 'an argument');
|
||||||
|
}).toThrowError(Error, /Does not take arguments/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws an error if the spy object has no spies', function() {
|
||||||
|
let matcher = jasmineUnderTest.matchers.toHaveSpyInteractions();
|
||||||
|
const spyObj = jasmineUnderTest
|
||||||
|
.getEnv()
|
||||||
|
.createSpyObj('NewClass', ['notSpy']);
|
||||||
|
// Removing spy since spy objects cannot be created without spies.
|
||||||
|
spyObj.notSpy = function() {};
|
||||||
|
|
||||||
|
expect(function() {
|
||||||
|
matcher.compare(spyObj);
|
||||||
|
}).toThrowError(
|
||||||
|
Error,
|
||||||
|
/Expected a spy object with spies, but object has no spies/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
(function(env) {
|
|
||||||
env.skipBrowserFlake = function() {
|
|
||||||
pending(
|
|
||||||
'Skipping specs that are known to be flaky in browsers in this run'
|
|
||||||
);
|
|
||||||
};
|
|
||||||
})(jasmine.getEnv());
|
|
||||||
@@ -41,7 +41,3 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (process.env.SKIP_JASMINE_BROWSER_FLAKES === 'true') {
|
|
||||||
module.exports.helpers.push('helpers/disableBrowserFlakes.js');
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1028,7 +1028,10 @@ getJasmineRequireObj().Env = function(j$) {
|
|||||||
}
|
}
|
||||||
addSpecsToSuite(suite, specDefinitions);
|
addSpecsToSuite(suite, specDefinitions);
|
||||||
if (suite.parentSuite && !suite.children.length) {
|
if (suite.parentSuite && !suite.children.length) {
|
||||||
throw new Error('describe with no children (describe() or it())');
|
throw new Error(
|
||||||
|
'describe with no children (describe() or it()): ' +
|
||||||
|
suite.getFullName()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return suite.metadata;
|
return suite.metadata;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) {
|
|||||||
this.emitScalar('<global>');
|
this.emitScalar('<global>');
|
||||||
} else if (value.jasmineToString) {
|
} else if (value.jasmineToString) {
|
||||||
this.emitScalar(value.jasmineToString(this.pp_));
|
this.emitScalar(value.jasmineToString(this.pp_));
|
||||||
} else if (typeof value === 'string') {
|
} else if (j$.isString_(value)) {
|
||||||
this.emitString(value);
|
this.emitString(value);
|
||||||
} else if (j$.isSpy(value)) {
|
} else if (j$.isSpy(value)) {
|
||||||
this.emitScalar('spy on ' + value.and.identity);
|
this.emitScalar('spy on ' + value.and.identity);
|
||||||
|
|||||||
@@ -177,7 +177,10 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
|||||||
maybeThenable = queueableFn.fn.call(self.userContext);
|
maybeThenable = queueableFn.fn.call(self.userContext);
|
||||||
|
|
||||||
if (maybeThenable && j$.isFunction_(maybeThenable.then)) {
|
if (maybeThenable && j$.isFunction_(maybeThenable.then)) {
|
||||||
maybeThenable.then(next, onPromiseRejection);
|
maybeThenable.then(
|
||||||
|
wrapInPromiseResolutionHandler(next),
|
||||||
|
onPromiseRejection
|
||||||
|
);
|
||||||
completedSynchronously = false;
|
completedSynchronously = false;
|
||||||
return { completedSynchronously: false };
|
return { completedSynchronously: false };
|
||||||
}
|
}
|
||||||
@@ -276,5 +279,15 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function wrapInPromiseResolutionHandler(fn) {
|
||||||
|
return function(maybeArg) {
|
||||||
|
if (j$.isError_(maybeArg)) {
|
||||||
|
fn(maybeArg);
|
||||||
|
} else {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return QueueRunner;
|
return QueueRunner;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
|||||||
boilerplateEnd =
|
boilerplateEnd =
|
||||||
boilerplateStart + Spec.pendingSpecExceptionMessage.length;
|
boilerplateStart + Spec.pendingSpecExceptionMessage.length;
|
||||||
|
|
||||||
return fullMessage.substr(boilerplateEnd);
|
return fullMessage.slice(boilerplateEnd);
|
||||||
};
|
};
|
||||||
|
|
||||||
Spec.pendingSpecExceptionMessage = '=> marked Pending';
|
Spec.pendingSpecExceptionMessage = '=> marked Pending';
|
||||||
|
|||||||
@@ -525,17 +525,16 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function keys(obj, isArray) {
|
function keys(obj, isArray) {
|
||||||
var allKeys = Object.keys
|
var allKeys = (function(o) {
|
||||||
? Object.keys(obj)
|
var keys = [];
|
||||||
: (function(o) {
|
for (var key in o) {
|
||||||
var keys = [];
|
if (j$.util.has(o, key)) {
|
||||||
for (var key in o) {
|
keys.push(key);
|
||||||
if (j$.util.has(o, key)) {
|
}
|
||||||
keys.push(key);
|
}
|
||||||
}
|
// eslint-disable-next-line compat/compat
|
||||||
}
|
return keys.concat(Object.getOwnPropertySymbols(o));
|
||||||
return keys;
|
})(obj);
|
||||||
})(obj);
|
|
||||||
|
|
||||||
if (!isArray) {
|
if (!isArray) {
|
||||||
return allKeys;
|
return allKeys;
|
||||||
|
|||||||
1
src/core/matchers/requireMatchers.js
Normal file → Executable file
1
src/core/matchers/requireMatchers.js
Normal file → Executable file
@@ -27,6 +27,7 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
|
|||||||
'toHaveBeenCalledTimes',
|
'toHaveBeenCalledTimes',
|
||||||
'toHaveBeenCalledWith',
|
'toHaveBeenCalledWith',
|
||||||
'toHaveClass',
|
'toHaveClass',
|
||||||
|
'toHaveSpyInteractions',
|
||||||
'toMatch',
|
'toMatch',
|
||||||
'toThrow',
|
'toThrow',
|
||||||
'toThrowError',
|
'toThrowError',
|
||||||
|
|||||||
@@ -27,6 +27,14 @@ getJasmineRequireObj().toBeCloseTo = function() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Infinity is close to Infinity and -Infinity is close to -Infinity,
|
||||||
|
// regardless of the precision.
|
||||||
|
if (expected === Infinity || expected === -Infinity) {
|
||||||
|
return {
|
||||||
|
pass: actual === expected
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var pow = Math.pow(10, precision + 1);
|
var pow = Math.pow(10, precision + 1);
|
||||||
var delta = Math.abs(expected - actual);
|
var delta = Math.abs(expected - actual);
|
||||||
var maxDelta = Math.pow(10, -precision) / 2;
|
var maxDelta = Math.pow(10, -precision) / 2;
|
||||||
|
|||||||
75
src/core/matchers/toHaveSpyInteractions.js
Executable file
75
src/core/matchers/toHaveSpyInteractions.js
Executable file
@@ -0,0 +1,75 @@
|
|||||||
|
getJasmineRequireObj().toHaveSpyInteractions = function(j$) {
|
||||||
|
var getErrorMsg = j$.formatErrorMsg(
|
||||||
|
'<toHaveSpyInteractions>',
|
||||||
|
'expect(<spyObj>).toHaveSpyInteractions()'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link expect} the actual (a {@link SpyObj}) spies to have been called.
|
||||||
|
* @function
|
||||||
|
* @name matchers#toHaveSpyInteractions
|
||||||
|
* @since 4.1.0
|
||||||
|
* @example
|
||||||
|
* expect(mySpyObj).toHaveSpyInteractions();
|
||||||
|
* expect(mySpyObj).not.toHaveSpyInteractions();
|
||||||
|
*/
|
||||||
|
function toHaveSpyInteractions(matchersUtil) {
|
||||||
|
return {
|
||||||
|
compare: function(actual) {
|
||||||
|
var result = {};
|
||||||
|
|
||||||
|
if (!j$.isObject_(actual)) {
|
||||||
|
throw new Error(
|
||||||
|
getErrorMsg('Expected a spy object, but got ' + typeof actual + '.')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments.length > 1) {
|
||||||
|
throw new Error(getErrorMsg('Does not take arguments'));
|
||||||
|
}
|
||||||
|
|
||||||
|
result.pass = false;
|
||||||
|
let hasSpy = false;
|
||||||
|
const calledSpies = [];
|
||||||
|
for (const spy of Object.values(actual)) {
|
||||||
|
if (!j$.isSpy(spy)) continue;
|
||||||
|
hasSpy = true;
|
||||||
|
|
||||||
|
if (spy.calls.any()) {
|
||||||
|
result.pass = true;
|
||||||
|
calledSpies.push([spy.and.identity, spy.calls.count()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasSpy) {
|
||||||
|
throw new Error(
|
||||||
|
getErrorMsg(
|
||||||
|
'Expected a spy object with spies, but object has no spies.'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let resultMessage;
|
||||||
|
if (result.pass) {
|
||||||
|
resultMessage =
|
||||||
|
'Expected spy object spies not to have been called, ' +
|
||||||
|
'but the following spies were called: ';
|
||||||
|
resultMessage += calledSpies
|
||||||
|
.map(([spyName, spyCount]) => {
|
||||||
|
return `${spyName} called ${spyCount} time(s)`;
|
||||||
|
})
|
||||||
|
.join(', ');
|
||||||
|
} else {
|
||||||
|
resultMessage =
|
||||||
|
'Expected spy object spies to have been called, ' +
|
||||||
|
'but no spies were called.';
|
||||||
|
}
|
||||||
|
result.message = resultMessage;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return toHaveSpyInteractions;
|
||||||
|
};
|
||||||
@@ -54,6 +54,8 @@ getJasmineRequireObj().util = function(j$) {
|
|||||||
// All falsey values are either primitives, `null`, or `undefined.
|
// All falsey values are either primitives, `null`, or `undefined.
|
||||||
if (!argsAsArray[i] || str.match(primitives)) {
|
if (!argsAsArray[i] || str.match(primitives)) {
|
||||||
clonedArgs.push(argsAsArray[i]);
|
clonedArgs.push(argsAsArray[i]);
|
||||||
|
} else if (str === '[object Date]') {
|
||||||
|
clonedArgs.push(new Date(argsAsArray[i].valueOf()));
|
||||||
} else {
|
} else {
|
||||||
clonedArgs.push(j$.util.clone(argsAsArray[i]));
|
clonedArgs.push(j$.util.clone(argsAsArray[i]));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,9 +71,6 @@ body {
|
|||||||
.jasmine-banner .jasmine-title {
|
.jasmine-banner .jasmine-title {
|
||||||
background: url('../../images/jasmine-horizontal.png') no-repeat;
|
background: url('../../images/jasmine-horizontal.png') no-repeat;
|
||||||
background: url('../../images/jasmine-horizontal.svg') no-repeat, none;
|
background: url('../../images/jasmine-horizontal.svg') no-repeat, none;
|
||||||
-moz-background-size: 100%;
|
|
||||||
-o-background-size: 100%;
|
|
||||||
-webkit-background-size: 100%;
|
|
||||||
background-size: 100%;
|
background-size: 100%;
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
float: left;
|
||||||
|
|||||||
Reference in New Issue
Block a user