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
|
||||
|
||||
orbs:
|
||||
node: circleci/node@3.0.0
|
||||
|
||||
executors:
|
||||
node16:
|
||||
docker:
|
||||
- image: cimg/node:16.1.0-browsers
|
||||
- image: cimg/node:16.14.0 # Latest 16.x
|
||||
working_directory: ~/workspace
|
||||
node14:
|
||||
docker:
|
||||
- image: circleci/node:14
|
||||
- image: cimg/node:14.17.4 # Latest 14.x
|
||||
working_directory: ~/workspace
|
||||
node12_latest:
|
||||
docker:
|
||||
- image: circleci/node:12
|
||||
- image: cimg/node:12.22.10 # Latest 12.x
|
||||
working_directory: ~/workspace
|
||||
node12_17:
|
||||
docker:
|
||||
- image: circleci/node:12.17
|
||||
- image: cimg/node:12.17.0 # Oldest version supported by Jasmine
|
||||
working_directory: ~/workspace
|
||||
|
||||
jobs:
|
||||
@@ -60,8 +57,6 @@ jobs:
|
||||
|
||||
test_browsers: &test_browsers
|
||||
executor: node14
|
||||
environment:
|
||||
SKIP_JASMINE_BROWSER_FLAKES: "true"
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
@@ -69,10 +64,10 @@ jobs:
|
||||
name: Install Sauce Connect
|
||||
command: |
|
||||
cd /tmp
|
||||
curl https://saucelabs.com/downloads/sc-4.6.4-linux.tar.gz | tar zxf -
|
||||
chmod +x sc-4.6.4-linux/bin/sc
|
||||
curl https://saucelabs.com/downloads/sc-4.7.1-linux.tar.gz | tar zxf -
|
||||
chmod +x sc-4.7.1-linux/bin/sc
|
||||
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
|
||||
- run:
|
||||
name: Run tests
|
||||
@@ -90,58 +85,8 @@ jobs:
|
||||
scripts/stop-sauce-connect $(cat sauce-pidfile)
|
||||
exit $exitcode
|
||||
|
||||
test_browser_flakes:
|
||||
<<: *test_browsers
|
||||
environment:
|
||||
SKIP_JASMINE_BROWSER_FLAKES: "false"
|
||||
|
||||
workflows:
|
||||
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:
|
||||
jobs:
|
||||
@@ -183,23 +128,3 @@ workflows:
|
||||
filters:
|
||||
branches:
|
||||
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
|
||||
|
||||
For the Jasmine NPM module:<br>
|
||||
[https://github.com/jasmine/jasmine-npm](https://github.com/jasmine/jasmine-npm).
|
||||
There are several different ways to install Jasmine, depending on your
|
||||
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>
|
||||
[https://github.com/jasmine/jasmine-browser](https://github.com/jasmine/jasmine-browser).
|
||||
## Usage
|
||||
|
||||
To install Jasmine standalone on your local box (where **_{#.#.#}_** below is substituted by the release number downloaded):
|
||||
|
||||
* Download the standalone distribution for your desired release from the [releases page](https://github.com/jasmine/jasmine/releases).
|
||||
* 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>
|
||||
```
|
||||
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)
|
||||
for information on writing specs.
|
||||
|
||||
## Supported environments
|
||||
|
||||
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 |
|
||||
|-------------------|--------------------|
|
||||
@@ -74,18 +59,19 @@ for the supported environments for each Jasmine release.
|
||||
|
||||
## 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
|
||||
|
||||
* [Davis W. Frank](mailto:dwfrank@pivotal.io), Pivotal Labs
|
||||
* [Rajan Agaskar](mailto:rajan@pivotal.io), Pivotal Labs
|
||||
* [Greg Cobb](mailto:gcobb@pivotal.io), Pivotal Labs
|
||||
* [Chris Amavisca](mailto:camavisca@pivotal.io), Pivotal Labs
|
||||
* [Christian Williams](mailto:antixian666@gmail.com), Cloud Foundry
|
||||
* [Davis W. Frank](mailto:dwfrank@pivotal.io)
|
||||
* [Rajan Agaskar](mailto:rajan@pivotal.io)
|
||||
* [Greg Cobb](mailto:gcobb@pivotal.io)
|
||||
* [Chris Amavisca](mailto:camavisca@pivotal.io)
|
||||
* [Christian Williams](mailto:antixian666@gmail.com)
|
||||
* 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
|
||||
|
||||
@@ -36,7 +36,7 @@ When ready to release - specs are all green and the stories are done:
|
||||
### Commit and push core changes
|
||||
|
||||
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. 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',
|
||||
'toHaveBeenCalledWith',
|
||||
'toHaveClass',
|
||||
'toHaveSpyInteractions',
|
||||
'toMatch',
|
||||
'toThrow',
|
||||
'toThrowError',
|
||||
@@ -640,6 +641,8 @@ getJasmineRequireObj().util = function(j$) {
|
||||
// All falsey values are either primitives, `null`, or `undefined.
|
||||
if (!argsAsArray[i] || str.match(primitives)) {
|
||||
clonedArgs.push(argsAsArray[i]);
|
||||
} else if (str === '[object Date]') {
|
||||
clonedArgs.push(new Date(argsAsArray[i].valueOf()));
|
||||
} else {
|
||||
clonedArgs.push(j$.util.clone(argsAsArray[i]));
|
||||
}
|
||||
@@ -1039,7 +1042,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
boilerplateEnd =
|
||||
boilerplateStart + Spec.pendingSpecExceptionMessage.length;
|
||||
|
||||
return fullMessage.substr(boilerplateEnd);
|
||||
return fullMessage.slice(boilerplateEnd);
|
||||
};
|
||||
|
||||
Spec.pendingSpecExceptionMessage = '=> marked Pending';
|
||||
@@ -2169,7 +2172,10 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
}
|
||||
addSpecsToSuite(suite, specDefinitions);
|
||||
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;
|
||||
};
|
||||
@@ -5576,17 +5582,16 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
|
||||
};
|
||||
|
||||
function keys(obj, isArray) {
|
||||
var allKeys = Object.keys
|
||||
? Object.keys(obj)
|
||||
: (function(o) {
|
||||
var keys = [];
|
||||
for (var key in o) {
|
||||
if (j$.util.has(o, key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
})(obj);
|
||||
var allKeys = (function(o) {
|
||||
var keys = [];
|
||||
for (var key in o) {
|
||||
if (j$.util.has(o, key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line compat/compat
|
||||
return keys.concat(Object.getOwnPropertySymbols(o));
|
||||
})(obj);
|
||||
|
||||
if (!isArray) {
|
||||
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 delta = Math.abs(expected - actual);
|
||||
var maxDelta = Math.pow(10, -precision) / 2;
|
||||
@@ -6926,6 +6939,82 @@ getJasmineRequireObj().toHaveSize = function(j$) {
|
||||
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$) {
|
||||
var getErrorMsg = j$.formatErrorMsg(
|
||||
'<toMatch>',
|
||||
@@ -7488,7 +7577,7 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) {
|
||||
this.emitScalar('<global>');
|
||||
} else if (value.jasmineToString) {
|
||||
this.emitScalar(value.jasmineToString(this.pp_));
|
||||
} else if (typeof value === 'string') {
|
||||
} else if (j$.isString_(value)) {
|
||||
this.emitString(value);
|
||||
} else if (j$.isSpy(value)) {
|
||||
this.emitScalar('spy on ' + value.and.identity);
|
||||
@@ -8031,7 +8120,10 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
maybeThenable = queueableFn.fn.call(self.userContext);
|
||||
|
||||
if (maybeThenable && j$.isFunction_(maybeThenable.then)) {
|
||||
maybeThenable.then(next, onPromiseRejection);
|
||||
maybeThenable.then(
|
||||
wrapInPromiseResolutionHandler(next),
|
||||
onPromiseRejection
|
||||
);
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -10186,5 +10288,5 @@ getJasmineRequireObj().UserContext = function(j$) {
|
||||
};
|
||||
|
||||
getJasmineRequireObj().version = function() {
|
||||
return '4.0.0';
|
||||
return '4.1.0';
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jasmine-core",
|
||||
"license": "MIT",
|
||||
"version": "4.0.0",
|
||||
"version": "4.1.0",
|
||||
"repository": {
|
||||
"type": "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() {
|
||||
expect(function() {
|
||||
env.describe('done method', function() {});
|
||||
}).toThrowError('describe with no children (describe() or it())');
|
||||
let ran = false;
|
||||
env.describe('parent suite', function() {
|
||||
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'");
|
||||
});
|
||||
|
||||
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() {
|
||||
var pp = jasmineUnderTest.makePrettyPrinter();
|
||||
expect(pp(true)).toEqual('true');
|
||||
|
||||
@@ -156,6 +156,81 @@ describe('QueueRunner', function() {
|
||||
expect(failFn).toHaveBeenCalledWith(err);
|
||||
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() {
|
||||
|
||||
@@ -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() {
|
||||
it('get property descriptor from object', function() {
|
||||
var obj = { prop: 1 },
|
||||
|
||||
@@ -58,8 +58,8 @@ describe('ArrayContaining', function() {
|
||||
if (
|
||||
typeof a == 'string' &&
|
||||
typeof b == 'string' &&
|
||||
a.substr(0, 3) == 'foo' &&
|
||||
b.substr(0, 3) == 'foo'
|
||||
a.slice(0, 3) == 'foo' &&
|
||||
b.slice(0, 3) == 'foo'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ describe('ArrayWithExactContents', function() {
|
||||
if (
|
||||
typeof a == 'string' &&
|
||||
typeof b == 'string' &&
|
||||
a.substr(0, 3) == 'foo' &&
|
||||
b.substr(0, 3) == 'foo'
|
||||
a.slice(0, 3) == 'foo' &&
|
||||
b.slice(0, 3) == 'foo'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -121,8 +121,8 @@ describe('ObjectContaining', function() {
|
||||
if (
|
||||
typeof a == 'string' &&
|
||||
typeof b == 'string' &&
|
||||
a.substr(0, 3) == 'foo' &&
|
||||
b.substr(0, 3) == 'foo'
|
||||
a.slice(0, 3) == 'foo' &&
|
||||
b.slice(0, 3) == 'foo'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -81,8 +81,8 @@ describe('Custom Matchers (Integration)', function() {
|
||||
if (
|
||||
typeof a == 'string' &&
|
||||
typeof b == 'string' &&
|
||||
a.substr(0, 3) == 'foo' &&
|
||||
b.substr(0, 3) == 'foo'
|
||||
a.slice(0, 3) == 'foo' &&
|
||||
b.slice(0, 3) == 'foo'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -455,10 +455,6 @@ describe('Env integration', function() {
|
||||
});
|
||||
|
||||
it('copes with async failures after done has been called', function(done) {
|
||||
if (jasmine.getEnv().skipBrowserFlake) {
|
||||
jasmine.getEnv().skipBrowserFlake();
|
||||
}
|
||||
|
||||
var global = {
|
||||
setTimeout: function(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) {
|
||||
if (jasmine.getEnv().skipBrowserFlake) {
|
||||
jasmine.getEnv().skipBrowserFlake();
|
||||
}
|
||||
|
||||
var globalSetTimeout = jasmine
|
||||
.createSpy('globalSetTimeout')
|
||||
.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) {
|
||||
if (jasmine.getEnv().skipBrowserFlake) {
|
||||
jasmine.getEnv().skipBrowserFlake();
|
||||
}
|
||||
|
||||
createMockedEnv();
|
||||
var reporter = jasmine.createSpyObj('fakeReporter', ['specDone']),
|
||||
clock = env.clock;
|
||||
|
||||
reporter.specDone.and.callFake(function() {
|
||||
realSetTimeout(function() {
|
||||
jasmine.debugLog('Ticking after specDone');
|
||||
jasmine.clock().tick(1);
|
||||
}, 0);
|
||||
});
|
||||
@@ -1346,24 +1335,24 @@ describe('Env integration', function() {
|
||||
env.it('spec that should not time out', function(innerDone) {
|
||||
clock.tick(6);
|
||||
expect(true).toEqual(true);
|
||||
realSetTimeout(innerDone);
|
||||
jasmine.debugLog('Calling realSetTimeout in spec');
|
||||
realSetTimeout(function() {
|
||||
jasmine.debugLog('Calling innerDone');
|
||||
innerDone();
|
||||
});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(reporter.specDone).toHaveBeenCalledTimes(1);
|
||||
expect(reporter.specDone.calls.argsFor(0)[0]).toEqual(
|
||||
jasmine.objectContaining({ status: 'passed' })
|
||||
);
|
||||
const event = reporter.specDone.calls.argsFor(0)[0];
|
||||
jasmine.debugLog('Spec result: ' + jasmine.basicPrettyPrinter_(event));
|
||||
expect(event).toEqual(jasmine.objectContaining({ status: 'passed' }));
|
||||
jasmine.clock().tick(1);
|
||||
realSetTimeout(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();
|
||||
var reporter = jasmine.createSpyObj('fakeReport', [
|
||||
'jasmineDone',
|
||||
@@ -2939,10 +2928,6 @@ describe('Env integration', function() {
|
||||
});
|
||||
|
||||
it('provides custom equality testers to async matchers', function(done) {
|
||||
if (jasmine.getEnv().skipBrowserFlake) {
|
||||
jasmine.getEnv().skipBrowserFlake();
|
||||
}
|
||||
|
||||
var specDone = jasmine.createSpy('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() {
|
||||
verifyPasses(function(env) {
|
||||
env.expect('foo').toMatch(/oo$/);
|
||||
|
||||
@@ -110,4 +110,42 @@ describe('toBeCloseTo', function() {
|
||||
result = matcher.compare(-2.82665525779431, -2.82666, 5);
|
||||
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() {
|
||||
'use strict';
|
||||
|
||||
@@ -1039,4 +1040,94 @@ describe('toEqual', function() {
|
||||
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);
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@ getJasmineRequireObj().makePrettyPrinter = function(j$) {
|
||||
this.emitScalar('<global>');
|
||||
} else if (value.jasmineToString) {
|
||||
this.emitScalar(value.jasmineToString(this.pp_));
|
||||
} else if (typeof value === 'string') {
|
||||
} else if (j$.isString_(value)) {
|
||||
this.emitString(value);
|
||||
} else if (j$.isSpy(value)) {
|
||||
this.emitScalar('spy on ' + value.and.identity);
|
||||
|
||||
@@ -177,7 +177,10 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
maybeThenable = queueableFn.fn.call(self.userContext);
|
||||
|
||||
if (maybeThenable && j$.isFunction_(maybeThenable.then)) {
|
||||
maybeThenable.then(next, onPromiseRejection);
|
||||
maybeThenable.then(
|
||||
wrapInPromiseResolutionHandler(next),
|
||||
onPromiseRejection
|
||||
);
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -316,7 +316,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
boilerplateEnd =
|
||||
boilerplateStart + Spec.pendingSpecExceptionMessage.length;
|
||||
|
||||
return fullMessage.substr(boilerplateEnd);
|
||||
return fullMessage.slice(boilerplateEnd);
|
||||
};
|
||||
|
||||
Spec.pendingSpecExceptionMessage = '=> marked Pending';
|
||||
|
||||
@@ -525,17 +525,16 @@ getJasmineRequireObj().MatchersUtil = function(j$) {
|
||||
};
|
||||
|
||||
function keys(obj, isArray) {
|
||||
var allKeys = Object.keys
|
||||
? Object.keys(obj)
|
||||
: (function(o) {
|
||||
var keys = [];
|
||||
for (var key in o) {
|
||||
if (j$.util.has(o, key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
})(obj);
|
||||
var allKeys = (function(o) {
|
||||
var keys = [];
|
||||
for (var key in o) {
|
||||
if (j$.util.has(o, key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line compat/compat
|
||||
return keys.concat(Object.getOwnPropertySymbols(o));
|
||||
})(obj);
|
||||
|
||||
if (!isArray) {
|
||||
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',
|
||||
'toHaveBeenCalledWith',
|
||||
'toHaveClass',
|
||||
'toHaveSpyInteractions',
|
||||
'toMatch',
|
||||
'toThrow',
|
||||
'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 delta = Math.abs(expected - actual);
|
||||
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.
|
||||
if (!argsAsArray[i] || str.match(primitives)) {
|
||||
clonedArgs.push(argsAsArray[i]);
|
||||
} else if (str === '[object Date]') {
|
||||
clonedArgs.push(new Date(argsAsArray[i].valueOf()));
|
||||
} else {
|
||||
clonedArgs.push(j$.util.clone(argsAsArray[i]));
|
||||
}
|
||||
|
||||
@@ -71,9 +71,6 @@ body {
|
||||
.jasmine-banner .jasmine-title {
|
||||
background: url('../../images/jasmine-horizontal.png') no-repeat;
|
||||
background: url('../../images/jasmine-horizontal.svg') no-repeat, none;
|
||||
-moz-background-size: 100%;
|
||||
-o-background-size: 100%;
|
||||
-webkit-background-size: 100%;
|
||||
background-size: 100%;
|
||||
display: block;
|
||||
float: left;
|
||||
|
||||
Reference in New Issue
Block a user