Compare commits
158 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58d13570ac | ||
|
|
005648acd8 | ||
|
|
d963be5eec | ||
|
|
57c294b307 | ||
|
|
f3b26a0688 | ||
|
|
8804ddb8cf | ||
|
|
439be97c34 | ||
|
|
c48fb0b0e7 | ||
|
|
4c47bf6c0b | ||
|
|
e86a7f00a6 | ||
|
|
504ef27899 | ||
|
|
2a39339755 | ||
|
|
2c440b8e44 | ||
|
|
b13329114c | ||
|
|
ab34f272da | ||
|
|
1af0e62ef7 | ||
|
|
572452a15a | ||
|
|
896412367a | ||
|
|
503a7409f0 | ||
|
|
c1db8f2f82 | ||
|
|
bb9175cb66 | ||
|
|
8cadfbd829 | ||
|
|
86aeb5c88a | ||
|
|
469b557828 | ||
|
|
503715c275 | ||
|
|
4482355885 | ||
|
|
6542364381 | ||
|
|
1fc911e0fa | ||
|
|
7f0087b805 | ||
|
|
fdad8849df | ||
|
|
7a289f1de7 | ||
|
|
ef981bb794 | ||
|
|
c3fb3e985a | ||
|
|
7fc3408051 | ||
|
|
af1b43eeff | ||
|
|
4c043717a9 | ||
|
|
fb4c16b23e | ||
|
|
3b28ee7c29 | ||
|
|
40be00310d | ||
|
|
64d58ed1f0 | ||
|
|
497a7fc3e5 | ||
|
|
1f318c3c93 | ||
|
|
be29aa95eb | ||
|
|
e3c9a59c6c | ||
|
|
b312ed4940 | ||
|
|
00f6708e1f | ||
|
|
af5984d5d6 | ||
|
|
be23836c9d | ||
|
|
7944250290 | ||
|
|
3a47a3bd04 | ||
|
|
1c9382c990 | ||
|
|
394be99832 | ||
|
|
de9815f436 | ||
|
|
62a667a8e3 | ||
|
|
d277827d5e | ||
|
|
644c175338 | ||
|
|
a6d7eb2a06 | ||
|
|
2fd9d7b13f | ||
|
|
dd8a65cb60 | ||
|
|
e72d161fab | ||
|
|
4e96514634 | ||
|
|
9c9836c5b3 | ||
|
|
20b914c554 | ||
|
|
058e77b824 | ||
|
|
dcaac62a6c | ||
|
|
b696bec9e3 | ||
|
|
799d9897fd | ||
|
|
2a2a671b65 | ||
|
|
a0b4f3748d | ||
|
|
43073b3bc5 | ||
|
|
f26b005807 | ||
|
|
1206952ca6 | ||
|
|
286524959b | ||
|
|
70d49e5b57 | ||
|
|
2c32dd5703 | ||
|
|
10601f5af6 | ||
|
|
c10ab4e704 | ||
|
|
c1d1d69be2 | ||
|
|
3513249d73 | ||
|
|
21bfbbb721 | ||
|
|
88b90ec258 | ||
|
|
17826cd044 | ||
|
|
6cb9507f62 | ||
|
|
50c88e7774 | ||
|
|
3e64ce3310 | ||
|
|
00586e50e0 | ||
|
|
dc80a282ba | ||
|
|
27c650ec08 | ||
|
|
56daa6f461 | ||
|
|
e4c7d8af45 | ||
|
|
ee88ecc614 | ||
|
|
ec038273f1 | ||
|
|
c5bdd79a1e | ||
|
|
dbc1a0aa56 | ||
|
|
5862b22aef | ||
|
|
163f93d6ff | ||
|
|
1893bf6c16 | ||
|
|
095745ab12 | ||
|
|
68db3f6fcf | ||
|
|
1e4f0d1545 | ||
|
|
c546d2cb6d | ||
|
|
6e097528f5 | ||
|
|
4e1f36cbb0 | ||
|
|
0aee81cfb9 | ||
|
|
1e50b49092 | ||
|
|
6aecf16cde | ||
|
|
f2de1be96a | ||
|
|
00c1e3d608 | ||
|
|
6a2a30d540 | ||
|
|
5f4a1c4276 | ||
|
|
a4ef3687ee | ||
|
|
61fb353197 | ||
|
|
9065b4c3b7 | ||
|
|
3e2872a1df | ||
|
|
140225e7c3 | ||
|
|
8b38389d56 | ||
|
|
b7c2a2f6fb | ||
|
|
c5d4a40219 | ||
|
|
c7c8b6b93e | ||
|
|
8a42437059 | ||
|
|
cacc6f4278 | ||
|
|
d815e99456 | ||
|
|
5e3f937221 | ||
|
|
5504965bea | ||
|
|
d666f1efbb | ||
|
|
4515b76f07 | ||
|
|
0897e31a2d | ||
|
|
fb05da1fc3 | ||
|
|
9555cb9842 | ||
|
|
d6fa9dd1a0 | ||
|
|
25fbe0646a | ||
|
|
316ce1e2d3 | ||
|
|
82cc1083b6 | ||
|
|
c2f04ba627 | ||
|
|
97a46f4560 | ||
|
|
113134cdbd | ||
|
|
dad5f5fd6b | ||
|
|
fa72544974 | ||
|
|
e303de52ed | ||
|
|
5f9315731e | ||
|
|
ce850c472a | ||
|
|
8b3a6561b1 | ||
|
|
2fc5182ddc | ||
|
|
6be2102b64 | ||
|
|
c6a79d3ab7 | ||
|
|
3f232fba80 | ||
|
|
cde6ea79a3 | ||
|
|
0782a73a98 | ||
|
|
37073e2768 | ||
|
|
f7f928fdd3 | ||
|
|
503b653a10 | ||
|
|
7a38db2e32 | ||
|
|
a1f1b4ae0f | ||
|
|
c39c110eca | ||
|
|
18b2646d1d | ||
|
|
9aed55bb91 | ||
|
|
90d6f9d73c | ||
|
|
2745d7d515 |
205
.circleci/config.yml
Normal file
205
.circleci/config.yml
Normal file
@@ -0,0 +1,205 @@
|
||||
# Run tests against supported Node versions, and (except for pull requests)
|
||||
# against supported browsers.
|
||||
|
||||
version: 2.1
|
||||
|
||||
orbs:
|
||||
node: circleci/node@3.0.0
|
||||
|
||||
executors:
|
||||
node16:
|
||||
docker:
|
||||
- image: cimg/node:16.1.0-browsers
|
||||
working_directory: ~/workspace
|
||||
node14:
|
||||
docker:
|
||||
- image: circleci/node:14
|
||||
working_directory: ~/workspace
|
||||
node12:
|
||||
docker:
|
||||
- image: circleci/node:12
|
||||
working_directory: ~/workspace
|
||||
node10:
|
||||
docker:
|
||||
- image: circleci/node:10
|
||||
working_directory: ~/workspace
|
||||
|
||||
jobs:
|
||||
build:
|
||||
parameters:
|
||||
executor:
|
||||
type: executor
|
||||
executor: << parameters.executor >>
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Report Node and NPM versions
|
||||
command: echo "Using Node $(node --version) and NPM $(npm --version)"
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: npm install
|
||||
- run:
|
||||
name: Build
|
||||
command: npm run build
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- .
|
||||
|
||||
test_node: &test_node
|
||||
parameters:
|
||||
executor:
|
||||
type: executor
|
||||
executor: << parameters.executor >>
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Run tests
|
||||
command: npm test
|
||||
|
||||
test_browsers: &test_browsers
|
||||
executor: node14
|
||||
environment:
|
||||
SKIP_JASMINE_BROWSER_FLAKES: "true"
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
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
|
||||
mkdir ~/workspace/bin
|
||||
cp sc-4.6.4-linux/bin/sc ~/workspace/bin
|
||||
~/workspace/bin/sc --version
|
||||
- run:
|
||||
name: Run tests
|
||||
command: |
|
||||
# Do everything in one step because Sauce Connect won't exit
|
||||
# cleanly if we kill it from a different step than it started in.
|
||||
|
||||
export PATH=$PATH:$HOME/workspace/bin
|
||||
export SAUCE_TUNNEL_IDENTIFIER=$CIRCLE_BUILD_NUM
|
||||
scripts/start-sauce-connect sauce-pidfile
|
||||
set +o errexit
|
||||
scripts/run-all-browsers
|
||||
exitcode=$?
|
||||
set -o errexit
|
||||
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
|
||||
name: build_node_12
|
||||
- build:
|
||||
executor: node10
|
||||
name: build_node_10
|
||||
- test_node:
|
||||
executor: node16
|
||||
name: test_node_16
|
||||
requires:
|
||||
- build_node_16
|
||||
- test_node:
|
||||
executor: node12
|
||||
name: test_node_12
|
||||
requires:
|
||||
- build_node_12
|
||||
- test_node:
|
||||
executor: node10
|
||||
name: test_node_10
|
||||
requires:
|
||||
- build_node_10
|
||||
- test_browsers:
|
||||
requires:
|
||||
- build_node_14
|
||||
filters:
|
||||
branches:
|
||||
ignore: /pull\/.*/ # Don't run on pull requests.
|
||||
|
||||
push:
|
||||
jobs:
|
||||
- build:
|
||||
executor: node16
|
||||
name: build_node_16
|
||||
- build:
|
||||
executor: node14
|
||||
name: build_node_14
|
||||
- build:
|
||||
executor: node12
|
||||
name: build_node_12
|
||||
- build:
|
||||
executor: node10
|
||||
name: build_node_10
|
||||
- test_node:
|
||||
executor: node16
|
||||
name: test_node_16
|
||||
requires:
|
||||
- build_node_16
|
||||
- test_node:
|
||||
executor: node14
|
||||
name: test_node_14
|
||||
requires:
|
||||
- build_node_14
|
||||
- test_node:
|
||||
executor: node12
|
||||
name: test_node_12
|
||||
requires:
|
||||
- build_node_12
|
||||
- test_node:
|
||||
executor: node10
|
||||
name: test_node_10
|
||||
requires:
|
||||
- build_node_10
|
||||
- test_browsers:
|
||||
requires:
|
||||
- build_node_14
|
||||
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.
|
||||
83
.github/CONTRIBUTING.md
vendored
83
.github/CONTRIBUTING.md
vendored
@@ -1,6 +1,12 @@
|
||||
# Developing for Jasmine Core
|
||||
|
||||
We welcome your contributions! Thanks for helping make Jasmine a better project for everyone. Please review the backlog and discussion lists before starting work. What you're looking for may already have been done. If it hasn't, the community can help make your contribution better. If you want to contribute but don't know what to work on, [issues tagged ready for work](https://github.com/jasmine/jasmine/labels/ready%20for%20work) should have enough detail to get started.
|
||||
We welcome your contributions! Thanks for helping make Jasmine a better project
|
||||
for everyone. Please review the backlog and discussion lists before starting
|
||||
work. What you're looking for may already have been done. If it hasn't, the
|
||||
community can help make your contribution better. If you want to contribute but
|
||||
don't know what to work on,
|
||||
[issues tagged help needed](https://github.com/jasmine/jasmine/labels/help%20needed)
|
||||
should have enough detail to get started.
|
||||
|
||||
## Links
|
||||
|
||||
@@ -35,8 +41,8 @@ Once you've pushed a feature branch to your forked repo, you're ready to open a
|
||||
* `/spec` contains all of the tests
|
||||
* mirrors the source directory
|
||||
* there are some additional files
|
||||
* `/dist` contains the standalone distributions as zip files
|
||||
* `/lib` contains the generated files for distribution as the Jasmine Rubygem and the Python package
|
||||
* `/lib` contains the compiled copy of Jasmine. This is used to self-test and
|
||||
distributed as the `jasmine-core` Node, Ruby, and Python packages.
|
||||
|
||||
### Self-testing
|
||||
|
||||
@@ -44,39 +50,31 @@ Note that Jasmine tests itself. The files in `lib` are loaded first, defining th
|
||||
|
||||
The tests should always use `jasmineUnderTest` to refer to the objects and functions that are being tested. But the tests can use functions on `jasmine` as needed. _Be careful how you structure any new test code_. Copy the patterns you see in the existing code - this ensures that the code you're testing is not leaking into the `jasmine` reference and vice-versa.
|
||||
|
||||
### `boot.js`
|
||||
### `boot0.js` and `boot1.js`
|
||||
|
||||
This file does all of the setup necessary for Jasmine to work. It loads all of the code, creates an `Env`, attaches the global functions, and builds the reporter. It also sets up the execution of the `Env` - for browsers this is in `window.onload`. While the default in `lib` is appropriate for browsers, projects may wish to customize this file.
|
||||
|
||||
For example, for Jasmine development there is a different `dev_boot.js` for Jasmine development that does more work.
|
||||
These files file does all of the setup necessary for Jasmine to work in a
|
||||
browser. They load all of the code, create an `Env`, attach the global
|
||||
functions, and build the reporter. It also sets up the execution of the
|
||||
`Env` - for browsers this is in `window.onload`. While the default in `lib`
|
||||
is appropriate for browsers, projects may wish to customize this file.
|
||||
|
||||
### Compatibility
|
||||
|
||||
Jasmine supports the following environments:
|
||||
|
||||
* Browsers
|
||||
* IE10+
|
||||
* Edge Latest
|
||||
* Firefox Latest
|
||||
* Chrome Latest
|
||||
* Safari 8+
|
||||
|
||||
* Node.js
|
||||
* 8
|
||||
* 10
|
||||
* 12
|
||||
Jasmine runs in both Node and browsers, including some older browsers that do
|
||||
not support the latest JavaScript features. See the README for the list of
|
||||
currently supported environments.
|
||||
|
||||
## Development
|
||||
|
||||
All source code belongs in `src/`. The `core/` directory contains the bulk of Jasmine's functionality. This code should remain browser- and environment-agnostic. If your feature or fix cannot be, as mentioned above, please degrade gracefully. Any code that depends on a browser (specifically, it expects `window` to be the global or `document` is present) should live in `src/html/`.
|
||||
|
||||
### Install Dependencies
|
||||
### Install Dev Dependencies
|
||||
|
||||
Jasmine Core relies on Node.js.
|
||||
|
||||
To install the Node dependencies, you will need Node.js, Npm, and [Grunt](http://gruntjs.com/), the [grunt-cli](https://github.com/gruntjs/grunt-cli) and ensure that `grunt` is on your path.
|
||||
To install the Node dependencies, you will need Node.js and npm.
|
||||
|
||||
$ npm install --local
|
||||
$ npm install
|
||||
|
||||
...will install all of the node modules locally. Now run
|
||||
|
||||
@@ -88,22 +86,35 @@ To install the Node dependencies, you will need Node.js, Npm, and [Grunt](http:/
|
||||
|
||||
Or, How to make a successful pull request
|
||||
|
||||
* _Do not change the public interface_. Lots of projects depend on Jasmine and if you aren't careful you'll break them
|
||||
* _Be environment agnostic_ - server-side developers are just as important as browser developers
|
||||
* _Be browser agnostic_ - if you must rely on browser-specific functionality, please write it in a way that degrades gracefully
|
||||
* _Write specs_ - Jasmine's a testing framework; don't add functionality without test-driving it
|
||||
* _Write code in the style of the rest of the repo_ - Jasmine should look like a cohesive whole
|
||||
* _Ensure the *entire* test suite is green_ in all the big browsers, Node, and ESLint - your contribution shouldn't break Jasmine for other users
|
||||
* _Do not change the public interface_. Lots of projects depend on Jasmine and
|
||||
if you aren't careful you'll break them.
|
||||
* _Be environment agnostic_ - server-side developers are just as important as
|
||||
browser developers.
|
||||
* _Be browser agnostic_ - if you must rely on browser-specific functionality,
|
||||
please write it in a way that degrades gracefully.
|
||||
* _Write specs_ - Jasmine's a testing framework. Don't add functionality
|
||||
without test-driving it.
|
||||
* _Write code in the style of the rest of the repo_ - Jasmine should look like
|
||||
a cohesive whole.
|
||||
* _Ensure the *entire* test suite is green_ in all the big browsers, Node, and
|
||||
ESLint. Your contribution shouldn't break Jasmine for other users.
|
||||
|
||||
Follow these tips and your pull request, patch, or suggestion is much more likely to be integrated.
|
||||
|
||||
### Running Specs
|
||||
|
||||
Jasmine uses some internal tooling to test itself in browser on Travis. This tooling _should_ work locally as well.
|
||||
Be sure to run the tests in at least one supported Node version and at least a
|
||||
couple of supported browsers. It's also a good idea to run the tests in Internet
|
||||
Explorer if you've touched code in `src/html`, if your change involves newer
|
||||
JavaScript language/runtime features, or if you're unfamiliar with writing code
|
||||
for older browsers. To run the tests in Node, simply use `npm test` as described
|
||||
above. To run the tests in a browser, run `npm run serve` and then visit
|
||||
`http://localhost:8888`.
|
||||
|
||||
$ node spec/support/ci.js
|
||||
If you have the necessary Selenium drivers installed, you can also use Jasmine's
|
||||
CI tooling:
|
||||
|
||||
You can also set the `JASMINE_BROWSER` environment variable to specify which browser should be used.
|
||||
$ JASMINE_BROWSER=<name of browser> node spec/support/ci.js
|
||||
|
||||
The easiest way to run the tests in **Internet Explorer** is to run a VM that has IE installed. It's easy to do this with VirtualBox.
|
||||
|
||||
@@ -112,16 +123,16 @@ The easiest way to run the tests in **Internet Explorer** is to run a VM that ha
|
||||
1. Unzip the downloaded archive. There should be an OVA file inside.
|
||||
1. In VirtualBox, choose `File > Import Appliance` and select the OVA file. Accept the default settings in the dialog that appears. Now you have a Windows VM!
|
||||
1. Run the VM and start IE.
|
||||
1. With `npm run serve` running on your host machine, navigate to `http://10.0.2.2:8888` in IE.
|
||||
1. With `npm run serve` running on your host machine, navigate to `http://<your IP address>:8888` in IE.
|
||||
|
||||
## Before Committing or Submitting a Pull Request
|
||||
|
||||
1. Ensure all specs are green in browser *and* node
|
||||
1. Ensure all specs are green in browser *and* node.
|
||||
1. Ensure eslint and prettier are clean as part of your `npm test` command. You can run `npm run cleanup` to have prettier re-write the files.
|
||||
1. Build `jasmine.js` with `npm run build` and run all specs again - this ensures that your changes self-test well
|
||||
1. Build `jasmine.js` with `npm run build` and run all specs again - this ensures that your changes self-test well.
|
||||
1. Revert your changes to `jasmine.js` and `jasmine-html.js`
|
||||
* We do this because `jasmine.js` and `jasmine-html.js` are auto-generated (as you've seen in the previous steps) and accepting multiple pull requests when this auto-generated file changes causes lots of headaches
|
||||
* When we accept your pull request, we will generate these files as a separate commit and merge the entire branch into main
|
||||
|
||||
Note that we use Travis for Continuous Integration. We only accept green pull requests.
|
||||
Note that we use Circle CI for Continuous Integration. We only accept green pull requests.
|
||||
|
||||
|
||||
3
.github/ISSUE_TEMPLATE.md
vendored
3
.github/ISSUE_TEMPLATE.md
vendored
@@ -3,9 +3,12 @@
|
||||
- When in doubt, create an issue here.
|
||||
- If you have an issue with the Jasmine docs, file an issue in the docs repo
|
||||
here: https://github.com/jasmine/jasmine.github.io
|
||||
- If you have an issue with TypeScript typings, start a discussion at
|
||||
[DefinitelyTpyed](https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/new?category=issues-with-a-types-package)
|
||||
- This repository is for the core Jasmine framework
|
||||
- If you are using a test runner that wraps Jasmine, consider filing an issue with that library if appropriate:
|
||||
- [Jasmine npm](https://github.com/jasmine/jasmine-npm/issues)
|
||||
- [Jasmine browser runner](https://github.com/jasmine/jasmine-browser/issues)
|
||||
- [Jasmine gem](https://github.com/jasmine/jasmine-gem/issues)
|
||||
- [Jasmine py](https://github.com/jasmine/jasmine-py/issues)
|
||||
- [Gulp Jasmine Browser](https://github.com/jasmine/gulp-jasmine-browser/issues)
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -25,3 +25,4 @@ build/
|
||||
dist
|
||||
nbproject/
|
||||
*.iml
|
||||
.envrc
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule "pages"]
|
||||
path = pages
|
||||
url = https://github.com/pivotal/jasmine.git
|
||||
29
.npmignore
29
.npmignore
@@ -1,29 +0,0 @@
|
||||
dist/
|
||||
grunt/
|
||||
node_modules
|
||||
pkg/
|
||||
release_notes/
|
||||
spec/
|
||||
src/
|
||||
Gemfile
|
||||
Gemfile.lock
|
||||
Rakefile
|
||||
jasmine-core.gemspec
|
||||
.bundle/
|
||||
.gitignore
|
||||
.gitmodules
|
||||
.idea
|
||||
.jshintrc
|
||||
.rspec
|
||||
.sass-cache/
|
||||
.travis.yml
|
||||
*.sh
|
||||
*.py
|
||||
Gruntfile.js
|
||||
lib/jasmine-core.rb
|
||||
lib/jasmine-core/boot/
|
||||
lib/jasmine-core/spec
|
||||
lib/jasmine-core/version.rb
|
||||
lib/jasmine-core/*.py
|
||||
sauce_connect.log
|
||||
ci.js
|
||||
52
.travis.yml
52
.travis.yml
@@ -1,52 +0,0 @@
|
||||
language: node_js
|
||||
node_js: 14
|
||||
|
||||
script: $TEST_COMMAND
|
||||
|
||||
env:
|
||||
global:
|
||||
- USE_SAUCE=true
|
||||
- TEST_COMMAND="bash travis-core-script.sh"
|
||||
- secure: WSPWhlnC4mWSnSPquX+m1/BCu5ch5NygkaHuM2Nea7lD8oS3XLX8QncZZAsQ4lnNfqoDDuBOizG0AESiqNvE4y6x5qvLLTS6q+ce255ZEMZ71TBdZgDEEvGMEjOPPsVXiXyTQOP1lwOPlrbZvaPgWV7e11KIBab6DfFcQpnvDgo=
|
||||
- secure: SW7CJhZnwaNT749Gdnhvqb5rbXlAOsygUAzh9qhtyvbqXKkmJdBIEsO01YF6pbju1X2twE9JvWCOxeZju43NgQChJlPsGbjY2j3k/TdQeTAJesQe2K7ytwghunI30gjEovtRH0T3w1EmcKPH8yj5eBIcB2OYoJHx8KEC7e68q1g=
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- node_js: "14"
|
||||
env: JASMINE_LONG_PROPERTY_TESTS="y" TEST_COMMAND="npm test"
|
||||
- node_js: "12"
|
||||
env: TEST_COMMAND="npm test"
|
||||
- node_js: "10"
|
||||
env: TEST_COMMAND="npm test"
|
||||
- env: JASMINE_BROWSER="internet explorer" SAUCE_BROWSER_VERSION=11 SAUCE_OS="Windows 8.1"
|
||||
if: type != pull_request
|
||||
addons:
|
||||
sauce_connect: true
|
||||
- env: JASMINE_BROWSER="internet explorer" SAUCE_BROWSER_VERSION=10 SAUCE_OS="Windows 8"
|
||||
if: type != pull_request
|
||||
addons:
|
||||
sauce_connect: true
|
||||
- env: JASMINE_BROWSER="firefox" SAUCE_BROWSER_VERSION='' SAUCE_OS="Windows 10"
|
||||
if: type != pull_request
|
||||
addons:
|
||||
sauce_connect: true
|
||||
- env: JASMINE_BROWSER="firefox" SAUCE_BROWSER_VERSION='68' SAUCE_OS="Windows 10"
|
||||
if: type != pull_request
|
||||
addons:
|
||||
sauce_connect: true
|
||||
- env: JASMINE_BROWSER="chrome" SAUCE_BROWSER_VERSION='' SAUCE_OS="Windows 10"
|
||||
if: type != pull_request
|
||||
addons:
|
||||
sauce_connect: true
|
||||
- env: JASMINE_BROWSER="safari" SAUCE_BROWSER_VERSION="13" SAUCE_OS="OS X 10.13"
|
||||
if: type != pull_request
|
||||
addons:
|
||||
sauce_connect: true
|
||||
- env: JASMINE_BROWSER="safari" SAUCE_BROWSER_VERSION="8" SAUCE_OS="OS X 10.10"
|
||||
if: type != pull_request
|
||||
addons:
|
||||
sauce_connect: true
|
||||
- env: JASMINE_BROWSER="MicrosoftEdge" SAUCE_BROWSER_VERSION="" SAUCE_OS="Windows 10"
|
||||
if: type != pull_request
|
||||
addons:
|
||||
sauce_connect: true
|
||||
14
Gruntfile.js
14
Gruntfile.js
@@ -40,11 +40,17 @@ module.exports = function(grunt) {
|
||||
jasmine = new Jasmine({jasmineCore: jasmineCore});
|
||||
|
||||
jasmine.loadConfigFile('./spec/support/jasmine.json');
|
||||
jasmine.onComplete(function(passed) {
|
||||
done(passed);
|
||||
});
|
||||
|
||||
jasmine.execute();
|
||||
jasmine.exitOnCompletion = false;
|
||||
jasmine.execute().then(
|
||||
result => {
|
||||
done(result.overallStatus === 'passed');
|
||||
},
|
||||
err => {
|
||||
console.error(err);
|
||||
exit(1);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
19
README.md
19
README.md
@@ -1,6 +1,6 @@
|
||||
<a name="README">[<img src="https://rawgithub.com/jasmine/jasmine/main/images/jasmine-horizontal.svg" width="400px" />](http://jasmine.github.io)</a>
|
||||
|
||||
[](https://travis-ci.com/jasmine/jasmine)
|
||||
[](https://circleci.com/gh/jasmine/jasmine)
|
||||
[](https://www.codetriage.com/jasmine/jasmine)
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine?ref=badge_shield)
|
||||
|
||||
@@ -11,8 +11,6 @@ Jasmine is a Behavior Driven Development testing framework for JavaScript. It do
|
||||
Documentation & guides live here: [http://jasmine.github.io](http://jasmine.github.io/)
|
||||
For a quick start guide of Jasmine, see the beginning of [http://jasmine.github.io/edge/introduction.html](http://jasmine.github.io/edge/introduction.html).
|
||||
|
||||
Upgrading from Jasmine 2.x? Check out the [3.0 release notes](https://github.com/jasmine/jasmine/blob/v3.0.0/release_notes/3.0.md) for a list of what's new (including breaking changes).
|
||||
|
||||
## Contributing
|
||||
|
||||
Please read the [contributors' guide](https://github.com/jasmine/jasmine/blob/main/.github/CONTRIBUTING.md).
|
||||
@@ -22,15 +20,12 @@ Please read the [contributors' guide](https://github.com/jasmine/jasmine/blob/ma
|
||||
For the Jasmine NPM module:<br>
|
||||
[https://github.com/jasmine/jasmine-npm](https://github.com/jasmine/jasmine-npm).
|
||||
|
||||
For the Jasmine browser runner:<br>
|
||||
[https://github.com/jasmine/jasmine-browser](https://github.com/jasmine/jasmine-browser).
|
||||
|
||||
For the Jasmine Ruby Gem:<br>
|
||||
[https://github.com/jasmine/jasmine-gem](https://github.com/jasmine/jasmine-gem).
|
||||
|
||||
For the Jasmine Python Egg:<br>
|
||||
[https://github.com/jasmine/jasmine-py](https://github.com/jasmine/jasmine-py).
|
||||
|
||||
For the Jasmine headless browser gulp plugin:<br>
|
||||
[https://github.com/jasmine/gulp-jasmine-browser](https://github.com/jasmine/gulp-jasmine-browser).
|
||||
|
||||
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).
|
||||
@@ -56,10 +51,10 @@ Jasmine tests itself across many browsers (Safari, Chrome, Firefox, Microsoft Ed
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 10, 12, 14 |
|
||||
| Safari | 8-13 |
|
||||
| Node | 10, 12, 14, 16 |
|
||||
| Safari | 8-14 |
|
||||
| Chrome | Evergreen |
|
||||
| Firefox | Evergreen, 68 |
|
||||
| Firefox | Evergreen, 68, 78, 91 |
|
||||
| Edge | Evergreen |
|
||||
| Internet Explorer | 10, 11 |
|
||||
|
||||
|
||||
11
RELEASE.md
11
RELEASE.md
@@ -28,16 +28,17 @@ When jasmine-core revs its major or minor version, the binding libraries should
|
||||
|
||||
When ready to release - specs are all green and the stories are done:
|
||||
|
||||
1. Update the release notes in `release_notes` - use the Anchorman gem to generate the markdown file and edit accordingly
|
||||
1. Update the release notes in `release_notes` - use the Anchorman gem to generate the markdown file and edit accordingly. Include a list of supported environments.
|
||||
1. Update the version in `package.json`
|
||||
1. Run `npm run build`.
|
||||
1. Copy version to the Ruby gem with `grunt build:copyVersionToGem`
|
||||
|
||||
### 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. Push
|
||||
1. Wait for Travis to go green
|
||||
1. Wait for Circle CI to go green
|
||||
|
||||
### Build standalone distribution
|
||||
|
||||
@@ -58,6 +59,7 @@ Install [twine](https://github.com/pypa/twine)
|
||||
|
||||
### Release the core NPM module
|
||||
|
||||
1. Run the tests on Windows. (CI only tests on Linux.)
|
||||
1. `npm adduser` to save your credentials locally
|
||||
1. `npm publish .` to publish what's in `package.json`
|
||||
|
||||
@@ -77,7 +79,8 @@ Probably only need to do this when releasing a minor version, and not a patch ve
|
||||
1. Create release notes using Anchorman as above
|
||||
1. In `package.json`, update both the package version and the jasmine-core dependency version
|
||||
1. Commit and push.
|
||||
1. Wait for Travis to go green again.
|
||||
1. Wait for Circle CI to go green again.
|
||||
1. Run the tests on Windows locally.
|
||||
1. `grunt release `. (Note: This will publish the package by running `npm publish`.)
|
||||
|
||||
#### Gem
|
||||
@@ -86,7 +89,7 @@ Probably only need to do this when releasing a minor version, and not a patch ve
|
||||
1. Update the version number in `lib/jasmine/version.rb`.
|
||||
1. Update the jasmine-core dependency version in `jasmine.gemspec`.
|
||||
1. Commit and push.
|
||||
1. Wait for Travis to go green again.
|
||||
1. Wait for Circle CI to go green again.
|
||||
1. `rake release`
|
||||
|
||||
### Finally
|
||||
|
||||
@@ -29,7 +29,7 @@ module.exports = {
|
||||
cwd: libJasmineCore("")
|
||||
},
|
||||
{
|
||||
src: [ "boot.js" ],
|
||||
src: [ "boot0.js", "boot1.js" ],
|
||||
dest: standaloneLibDir,
|
||||
expand: true,
|
||||
cwd: libJasmineCore("boot")
|
||||
|
||||
@@ -41,6 +41,14 @@ module.exports = {
|
||||
src: ['lib/jasmine-core/boot/boot.js'],
|
||||
dest: 'lib/jasmine-core/boot.js'
|
||||
},
|
||||
boot0: {
|
||||
src: ['lib/jasmine-core/boot/boot0.js'],
|
||||
dest: 'lib/jasmine-core/boot0.js'
|
||||
},
|
||||
boot1: {
|
||||
src: ['lib/jasmine-core/boot/boot1.js'],
|
||||
dest: 'lib/jasmine-core/boot1.js'
|
||||
},
|
||||
nodeBoot: {
|
||||
src: ['lib/jasmine-core/boot/node_boot.js'],
|
||||
dest: 'lib/jasmine-core/node_boot.js'
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
const sass = require('node-sass');
|
||||
const sass = require('sass');
|
||||
|
||||
module.exports = {
|
||||
options: {
|
||||
implementation: sass,
|
||||
outputStyle: 'compact',
|
||||
sourceComments: false
|
||||
},
|
||||
dist: {
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
|
||||
<script src="lib/jasmine-<%= jasmineVersion %>/jasmine.js"></script>
|
||||
<script src="lib/jasmine-<%= jasmineVersion %>/jasmine-html.js"></script>
|
||||
<script src="lib/jasmine-<%= jasmineVersion %>/boot.js"></script>
|
||||
<script src="lib/jasmine-<%= jasmineVersion %>/boot0.js"></script>
|
||||
<!-- optional: include a file here that configures the Jasmine env -->
|
||||
<script src="lib/jasmine-<%= jasmineVersion %>/boot1.js"></script>
|
||||
|
||||
<!-- include source files here... -->
|
||||
<script src="src/Player.js"></script>
|
||||
|
||||
@@ -8,7 +8,18 @@ Gem::Specification.new do |s|
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.authors = ["Gregg Van Hove"]
|
||||
s.summary = %q{JavaScript BDD framework}
|
||||
s.description = %q{Test your JavaScript without any framework dependencies, in any environment, and with a nice descriptive syntax.}
|
||||
s.description = <<~DESC
|
||||
Test your JavaScript without any framework dependencies, in any environment,
|
||||
and with a nice descriptive syntax.
|
||||
|
||||
Jasmine for Ruby is deprecated. The direct replacment for the jasmine-core
|
||||
gem is the jasmine-core NPM package. If you are also using the jasmine gem,
|
||||
we recommend using the jasmine-browser-runner NPM package instead. It
|
||||
supports all the same scenarios as the jasmine gem gem plus Webpacker. See
|
||||
https://jasmine.github.io/setup/browser.html for setup instructions, and
|
||||
https://github.com/jasmine/jasmine-gem/blob/main/release_notes/3.9.0.md
|
||||
for other options.
|
||||
DESC
|
||||
s.email = %q{jasmine-js@googlegroups.com}
|
||||
s.homepage = "http://jasmine.github.io"
|
||||
s.license = "MIT"
|
||||
|
||||
@@ -5,11 +5,12 @@ var path = require('path'),
|
||||
fs = require('fs');
|
||||
|
||||
var rootPath = path.join(__dirname, "jasmine-core"),
|
||||
bootFiles = ['boot.js'],
|
||||
bootFiles = ['boot0.js', 'boot1.js'],
|
||||
legacyBootFiles = ['boot.js'],
|
||||
nodeBootFiles = ['node_boot.js'],
|
||||
cssFiles = [],
|
||||
jsFiles = [],
|
||||
jsFilesToSkip = ['jasmine.js'].concat(bootFiles, nodeBootFiles);
|
||||
jsFilesToSkip = ['jasmine.js'].concat(bootFiles, legacyBootFiles, nodeBootFiles);
|
||||
|
||||
fs.readdirSync(rootPath).forEach(function(file) {
|
||||
if(fs.statSync(path.join(rootPath, file)).isFile()) {
|
||||
|
||||
@@ -1,3 +1,28 @@
|
||||
if ENV["SUPPRESS_JASMINE_DEPRECATION"].nil?
|
||||
puts <<~END_DEPRECATION_MSG
|
||||
The Jasmine Ruby gems are deprecated. There will be no further releases after
|
||||
the end of the Jasmine 3.x series. We recommend that most users migrate to the
|
||||
jasmine-browser-runner npm package, which is the direct replacement for the
|
||||
jasmine gem. See <https://jasmine.github.io/setup/browser.html> for setup
|
||||
instructions, including for Rails applications that use either Sprockets or
|
||||
Webpacker.
|
||||
|
||||
If jasmine-browser-runner doesn't meet your needs, one of these might:
|
||||
|
||||
* The jasmine npm package to run specs in Node.js:
|
||||
<https://github.com/jasmine/jasmine-npm>
|
||||
* The standalone distribution to run specs in browsers with no additional
|
||||
tools: <https://github.com/jasmine/jasmine#installation>
|
||||
* The jasmine-core npm package if all you need is the Jasmine assets:
|
||||
<https://github.com/jasmine/jasmine>. This is the direct equivalent of the
|
||||
jasmine-core Ruby gem.
|
||||
|
||||
To prevent this message from appearing, set the SUPPRESS_JASMINE_DEPRECATION
|
||||
environment variable.
|
||||
|
||||
END_DEPRECATION_MSG
|
||||
end
|
||||
|
||||
module Jasmine
|
||||
module Core
|
||||
class << self
|
||||
@@ -6,7 +31,7 @@ module Jasmine
|
||||
end
|
||||
|
||||
def js_files
|
||||
(["jasmine.js"] + Dir.glob(File.join(path, "*.js"))).map { |f| File.basename(f) }.uniq - boot_files - node_boot_files
|
||||
(["jasmine.js"] + Dir.glob(File.join(path, "*.js"))).map { |f| File.basename(f) }.uniq - boot_files - ["boot0.js", "boot1.js"] - node_boot_files
|
||||
end
|
||||
|
||||
SPEC_TYPES = ["core", "html", "node"]
|
||||
@@ -24,7 +49,7 @@ module Jasmine
|
||||
end
|
||||
|
||||
def boot_files
|
||||
["boot.js"]
|
||||
["boot0.js", "boot1.js"]
|
||||
end
|
||||
|
||||
def node_boot_files
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2008-2021 Pivotal Labs
|
||||
Copyright (c) 2008-2022 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -21,6 +21,10 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
|
||||
NOTE: This file is deprecated and will be removed in a future release.
|
||||
Include both boot0.js and boot1.js (in that order) instead.
|
||||
|
||||
Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
|
||||
|
||||
If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
|
||||
@@ -77,8 +81,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
var filterSpecs = !!queryString.getParam("spec");
|
||||
|
||||
var config = {
|
||||
failFast: queryString.getParam("failFast"),
|
||||
oneFailurePerSpec: queryString.getParam("oneFailurePerSpec"),
|
||||
stopOnSpecFailure: queryString.getParam("failFast"),
|
||||
stopSpecOnExpectationFailure: queryString.getParam("oneFailurePerSpec"),
|
||||
hideDisabled: queryString.getParam("hideDisabled")
|
||||
};
|
||||
|
||||
@@ -158,4 +162,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
return destination;
|
||||
}
|
||||
|
||||
env.deprecated('boot.js is deprecated. Please use boot0.js and boot1.js instead.',
|
||||
{ ignoreRunnable: true });
|
||||
}());
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
/**
|
||||
|
||||
NOTE: This file is deprecated and will be removed in a future release.
|
||||
Include both boot0.js and boot1.js (in that order) instead.
|
||||
|
||||
Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
|
||||
|
||||
If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
|
||||
@@ -55,8 +59,8 @@
|
||||
var filterSpecs = !!queryString.getParam("spec");
|
||||
|
||||
var config = {
|
||||
failFast: queryString.getParam("failFast"),
|
||||
oneFailurePerSpec: queryString.getParam("oneFailurePerSpec"),
|
||||
stopOnSpecFailure: queryString.getParam("failFast"),
|
||||
stopSpecOnExpectationFailure: queryString.getParam("oneFailurePerSpec"),
|
||||
hideDisabled: queryString.getParam("hideDisabled")
|
||||
};
|
||||
|
||||
@@ -136,4 +140,6 @@
|
||||
return destination;
|
||||
}
|
||||
|
||||
env.deprecated('boot.js is deprecated. Please use boot0.js and boot1.js instead.',
|
||||
{ ignoreRunnable: true });
|
||||
}());
|
||||
|
||||
42
lib/jasmine-core/boot/boot0.js
Normal file
42
lib/jasmine-core/boot/boot0.js
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
This file starts the process of "booting" Jasmine. It initializes Jasmine,
|
||||
makes its globals available, and creates the env. This file should be loaded
|
||||
after `jasmine.js` and `jasmine_html.js`, but before `boot1.js` or any project
|
||||
source files or spec files are loaded.
|
||||
*/
|
||||
(function() {
|
||||
var jasmineRequire = window.jasmineRequire || require('./jasmine.js');
|
||||
|
||||
/**
|
||||
* ## Require & Instantiate
|
||||
*
|
||||
* Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
|
||||
*/
|
||||
var jasmine = jasmineRequire.core(jasmineRequire),
|
||||
global = jasmine.getGlobal();
|
||||
global.jasmine = jasmine;
|
||||
|
||||
/**
|
||||
* Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
|
||||
*/
|
||||
jasmineRequire.html(jasmine);
|
||||
|
||||
/**
|
||||
* Create the Jasmine environment. This is used to run all specs in a project.
|
||||
*/
|
||||
var env = jasmine.getEnv();
|
||||
|
||||
/**
|
||||
* ## The Global Interface
|
||||
*
|
||||
* Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
|
||||
*/
|
||||
var jasmineInterface = jasmineRequire.interface(jasmine, env);
|
||||
|
||||
/**
|
||||
* Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
|
||||
*/
|
||||
for (var property in jasmineInterface) {
|
||||
global[property] = jasmineInterface[property];
|
||||
}
|
||||
}());
|
||||
111
lib/jasmine-core/boot/boot1.js
Normal file
111
lib/jasmine-core/boot/boot1.js
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
This file finishes "booting" Jasmine, performing all of the necessary
|
||||
initialization before executing the loaded environment and all of a project's
|
||||
specs. This file should be loaded after `boot0.js` but before any project
|
||||
source files or spec files are loaded. Thus this file can also be used to
|
||||
customize Jasmine for a project.
|
||||
|
||||
If a project is using Jasmine via the standalone distribution, this file can
|
||||
be customized directly. If you only wish to configure the Jasmine env, you
|
||||
can load another file that calls `jasmine.getEnv().configure({...})`
|
||||
after `boot0.js` is loaded and before this file is loaded.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var env = jasmine.getEnv();
|
||||
|
||||
/**
|
||||
* ## Runner Parameters
|
||||
*
|
||||
* More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
|
||||
*/
|
||||
|
||||
var queryString = new jasmine.QueryString({
|
||||
getWindowLocation: function() { return window.location; }
|
||||
});
|
||||
|
||||
var filterSpecs = !!queryString.getParam("spec");
|
||||
|
||||
var config = {
|
||||
stopOnSpecFailure: queryString.getParam("failFast"),
|
||||
stopSpecOnExpectationFailure: queryString.getParam("oneFailurePerSpec"),
|
||||
hideDisabled: queryString.getParam("hideDisabled")
|
||||
};
|
||||
|
||||
var random = queryString.getParam("random");
|
||||
|
||||
if (random !== undefined && random !== "") {
|
||||
config.random = random;
|
||||
}
|
||||
|
||||
var seed = queryString.getParam("seed");
|
||||
if (seed) {
|
||||
config.seed = seed;
|
||||
}
|
||||
|
||||
/**
|
||||
* ## Reporters
|
||||
* The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
|
||||
*/
|
||||
var htmlReporter = new jasmine.HtmlReporter({
|
||||
env: env,
|
||||
navigateWithNewParam: function(key, value) { return queryString.navigateWithNewParam(key, value); },
|
||||
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
|
||||
getContainer: function() { return document.body; },
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
|
||||
timer: new jasmine.Timer(),
|
||||
filterSpecs: filterSpecs
|
||||
});
|
||||
|
||||
/**
|
||||
* The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript.
|
||||
*/
|
||||
env.addReporter(jsApiReporter);
|
||||
env.addReporter(htmlReporter);
|
||||
|
||||
/**
|
||||
* Filter which specs will be run by matching the start of the full name against the `spec` query param.
|
||||
*/
|
||||
var specFilter = new jasmine.HtmlSpecFilter({
|
||||
filterString: function() { return queryString.getParam("spec"); }
|
||||
});
|
||||
|
||||
config.specFilter = function(spec) {
|
||||
return specFilter.matches(spec.getFullName());
|
||||
};
|
||||
|
||||
env.configure(config);
|
||||
|
||||
/**
|
||||
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
|
||||
*/
|
||||
window.setTimeout = window.setTimeout;
|
||||
window.setInterval = window.setInterval;
|
||||
window.clearTimeout = window.clearTimeout;
|
||||
window.clearInterval = window.clearInterval;
|
||||
|
||||
/**
|
||||
* ## Execution
|
||||
*
|
||||
* Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
|
||||
*/
|
||||
var currentWindowOnload = window.onload;
|
||||
|
||||
window.onload = function() {
|
||||
if (currentWindowOnload) {
|
||||
currentWindowOnload();
|
||||
}
|
||||
htmlReporter.initialize();
|
||||
env.execute();
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function for readability above.
|
||||
*/
|
||||
function extend(destination, source) {
|
||||
for (var property in source) destination[property] = source[property];
|
||||
return destination;
|
||||
}
|
||||
|
||||
}());
|
||||
64
lib/jasmine-core/boot0.js
Normal file
64
lib/jasmine-core/boot0.js
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright (c) 2008-2022 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
This file starts the process of "booting" Jasmine. It initializes Jasmine,
|
||||
makes its globals available, and creates the env. This file should be loaded
|
||||
after `jasmine.js` and `jasmine_html.js`, but before `boot1.js` or any project
|
||||
source files or spec files are loaded.
|
||||
*/
|
||||
(function() {
|
||||
var jasmineRequire = window.jasmineRequire || require('./jasmine.js');
|
||||
|
||||
/**
|
||||
* ## Require & Instantiate
|
||||
*
|
||||
* Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
|
||||
*/
|
||||
var jasmine = jasmineRequire.core(jasmineRequire),
|
||||
global = jasmine.getGlobal();
|
||||
global.jasmine = jasmine;
|
||||
|
||||
/**
|
||||
* Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
|
||||
*/
|
||||
jasmineRequire.html(jasmine);
|
||||
|
||||
/**
|
||||
* Create the Jasmine environment. This is used to run all specs in a project.
|
||||
*/
|
||||
var env = jasmine.getEnv();
|
||||
|
||||
/**
|
||||
* ## The Global Interface
|
||||
*
|
||||
* Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
|
||||
*/
|
||||
var jasmineInterface = jasmineRequire.interface(jasmine, env);
|
||||
|
||||
/**
|
||||
* Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
|
||||
*/
|
||||
for (var property in jasmineInterface) {
|
||||
global[property] = jasmineInterface[property];
|
||||
}
|
||||
}());
|
||||
133
lib/jasmine-core/boot1.js
Normal file
133
lib/jasmine-core/boot1.js
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright (c) 2008-2022 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
This file finishes "booting" Jasmine, performing all of the necessary
|
||||
initialization before executing the loaded environment and all of a project's
|
||||
specs. This file should be loaded after `boot0.js` but before any project
|
||||
source files or spec files are loaded. Thus this file can also be used to
|
||||
customize Jasmine for a project.
|
||||
|
||||
If a project is using Jasmine via the standalone distribution, this file can
|
||||
be customized directly. If you only wish to configure the Jasmine env, you
|
||||
can load another file that calls `jasmine.getEnv().configure({...})`
|
||||
after `boot0.js` is loaded and before this file is loaded.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var env = jasmine.getEnv();
|
||||
|
||||
/**
|
||||
* ## Runner Parameters
|
||||
*
|
||||
* More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
|
||||
*/
|
||||
|
||||
var queryString = new jasmine.QueryString({
|
||||
getWindowLocation: function() { return window.location; }
|
||||
});
|
||||
|
||||
var filterSpecs = !!queryString.getParam("spec");
|
||||
|
||||
var config = {
|
||||
stopOnSpecFailure: queryString.getParam("failFast"),
|
||||
stopSpecOnExpectationFailure: queryString.getParam("oneFailurePerSpec"),
|
||||
hideDisabled: queryString.getParam("hideDisabled")
|
||||
};
|
||||
|
||||
var random = queryString.getParam("random");
|
||||
|
||||
if (random !== undefined && random !== "") {
|
||||
config.random = random;
|
||||
}
|
||||
|
||||
var seed = queryString.getParam("seed");
|
||||
if (seed) {
|
||||
config.seed = seed;
|
||||
}
|
||||
|
||||
/**
|
||||
* ## Reporters
|
||||
* The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
|
||||
*/
|
||||
var htmlReporter = new jasmine.HtmlReporter({
|
||||
env: env,
|
||||
navigateWithNewParam: function(key, value) { return queryString.navigateWithNewParam(key, value); },
|
||||
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
|
||||
getContainer: function() { return document.body; },
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
|
||||
timer: new jasmine.Timer(),
|
||||
filterSpecs: filterSpecs
|
||||
});
|
||||
|
||||
/**
|
||||
* The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript.
|
||||
*/
|
||||
env.addReporter(jsApiReporter);
|
||||
env.addReporter(htmlReporter);
|
||||
|
||||
/**
|
||||
* Filter which specs will be run by matching the start of the full name against the `spec` query param.
|
||||
*/
|
||||
var specFilter = new jasmine.HtmlSpecFilter({
|
||||
filterString: function() { return queryString.getParam("spec"); }
|
||||
});
|
||||
|
||||
config.specFilter = function(spec) {
|
||||
return specFilter.matches(spec.getFullName());
|
||||
};
|
||||
|
||||
env.configure(config);
|
||||
|
||||
/**
|
||||
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
|
||||
*/
|
||||
window.setTimeout = window.setTimeout;
|
||||
window.setInterval = window.setInterval;
|
||||
window.clearTimeout = window.clearTimeout;
|
||||
window.clearInterval = window.clearInterval;
|
||||
|
||||
/**
|
||||
* ## Execution
|
||||
*
|
||||
* Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
|
||||
*/
|
||||
var currentWindowOnload = window.onload;
|
||||
|
||||
window.onload = function() {
|
||||
if (currentWindowOnload) {
|
||||
currentWindowOnload();
|
||||
}
|
||||
htmlReporter.initialize();
|
||||
env.execute();
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function for readability above.
|
||||
*/
|
||||
function extend(destination, source) {
|
||||
for (var property in source) destination[property] = source[property];
|
||||
return destination;
|
||||
}
|
||||
|
||||
}());
|
||||
@@ -1,4 +1,33 @@
|
||||
import pkg_resources
|
||||
import os
|
||||
|
||||
if 'SUPPRESS_JASMINE_DEPRECATION' not in os.environ:
|
||||
print('DEPRECATION WARNING:\n' +
|
||||
'\n' +
|
||||
'The Jasmine packages for Python are deprecated. There will be no further\n' +
|
||||
'releases after the end of the Jasmine 3.x series. We recommend migrating to the\n' +
|
||||
'following options:\n' +
|
||||
'\n' +
|
||||
'* jasmine-browser-runner (<https://github.com/jasmine/jasmine-browser>,\n' +
|
||||
' `npm install jasmine-browser-runner`) to run specs in browsers, including\n' +
|
||||
' headless Chrome and Saucelabs. This is the most direct replacement for the\n' +
|
||||
' jasmine server` and `jasmine ci` commands provided by the `jasmine` Python\n' +
|
||||
' package.\n' +
|
||||
'* The jasmine npm package (<https://github.com/jasmine/jasmine-npm>,\n' +
|
||||
' `npm install jasmine`) to run specs under Node.js.\n' +
|
||||
'* The standalone distribution from the latest Jasmine release\n' +
|
||||
' <https://github.com/jasmine/jasmine/releases> to run specs in browsers with\n' +
|
||||
' no additional tools.\n' +
|
||||
'* The jasmine-core npm package (`npm install jasmine-core`) if all you need is\n' +
|
||||
' the Jasmine assets. This is the direct equivalent of the jasmine-core Python\n' +
|
||||
' package.\n' +
|
||||
'\n' +
|
||||
'Except for the standalone distribution, all of the above are distributed through\n' +
|
||||
'npm.\n' +
|
||||
'\n' +
|
||||
'To prevent this message from appearing, set the SUPPRESS_JASMINE_DEPRECATION\n' +
|
||||
'environment variable.\n')
|
||||
|
||||
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
@@ -25,9 +54,14 @@ class Core(object):
|
||||
# jasmine.js needs to be first
|
||||
js_files.insert(0, 'jasmine.js')
|
||||
|
||||
# boot needs to be last
|
||||
# Remove the legacy boot file
|
||||
js_files.remove('boot.js')
|
||||
js_files.append('boot.js')
|
||||
|
||||
# boot files need to be last
|
||||
js_files.remove('boot0.js')
|
||||
js_files.remove('boot1.js')
|
||||
js_files.append('boot0.js')
|
||||
js_files.append('boot1.js')
|
||||
|
||||
return cls._uniq(js_files)
|
||||
|
||||
@@ -57,4 +91,4 @@ class Core(object):
|
||||
|
||||
seen[marker] = 1
|
||||
result.append(item)
|
||||
return result
|
||||
return result
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2008-2021 Pivotal Labs
|
||||
Copyright (c) 2008-2022 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -208,7 +208,10 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
' of ' +
|
||||
totalSpecsDefined +
|
||||
' specs - run all';
|
||||
var skippedLink = addToExistingQueryString('spec', '');
|
||||
// include window.location.pathname to fix issue with karma-jasmine-html-reporter in angular: see https://github.com/jasmine/jasmine/issues/1906
|
||||
var skippedLink =
|
||||
(window.location.pathname || '') +
|
||||
addToExistingQueryString('spec', '');
|
||||
alert.appendChild(
|
||||
createDom(
|
||||
'span',
|
||||
@@ -308,7 +311,8 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
addDeprecationWarnings(doneResult);
|
||||
|
||||
for (i = 0; i < deprecationWarnings.length; i++) {
|
||||
var context;
|
||||
var children = [],
|
||||
context;
|
||||
|
||||
switch (deprecationWarnings[i].runnableType) {
|
||||
case 'spec':
|
||||
@@ -321,13 +325,23 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
context = '';
|
||||
}
|
||||
|
||||
deprecationWarnings[i].message.split('\n').forEach(function(line) {
|
||||
children.push(line);
|
||||
children.push(createDom('br'));
|
||||
});
|
||||
|
||||
children[0] = 'DEPRECATION: ' + children[0];
|
||||
children.push(context);
|
||||
|
||||
if (deprecationWarnings[i].stack) {
|
||||
children.push(createExpander(deprecationWarnings[i].stack));
|
||||
}
|
||||
|
||||
alert.appendChild(
|
||||
createDom(
|
||||
'span',
|
||||
{ className: 'jasmine-bar jasmine-warning' },
|
||||
'DEPRECATION: ' + deprecationWarnings[i].message,
|
||||
createDom('br'),
|
||||
context
|
||||
children
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -555,17 +569,20 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
);
|
||||
|
||||
var failFastCheckbox = optionsMenuDom.querySelector('#jasmine-fail-fast');
|
||||
failFastCheckbox.checked = config.failFast;
|
||||
failFastCheckbox.checked = config.stopOnSpecFailure;
|
||||
failFastCheckbox.onclick = function() {
|
||||
navigateWithNewParam('failFast', !config.failFast);
|
||||
navigateWithNewParam('failFast', !config.stopOnSpecFailure);
|
||||
};
|
||||
|
||||
var throwCheckbox = optionsMenuDom.querySelector(
|
||||
'#jasmine-throw-failures'
|
||||
);
|
||||
throwCheckbox.checked = config.oneFailurePerSpec;
|
||||
throwCheckbox.checked = config.stopSpecOnExpectationFailure;
|
||||
throwCheckbox.onclick = function() {
|
||||
navigateWithNewParam('throwFailures', !config.oneFailurePerSpec);
|
||||
navigateWithNewParam(
|
||||
'oneFailurePerSpec',
|
||||
!config.stopSpecOnExpectationFailure
|
||||
);
|
||||
};
|
||||
|
||||
var randomCheckbox = optionsMenuDom.querySelector(
|
||||
@@ -635,24 +652,55 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
suite = suite.parent;
|
||||
}
|
||||
|
||||
return addToExistingQueryString('spec', els.join(' '));
|
||||
// include window.location.pathname to fix issue with karma-jasmine-html-reporter in angular: see https://github.com/jasmine/jasmine/issues/1906
|
||||
return (
|
||||
(window.location.pathname || '') +
|
||||
addToExistingQueryString('spec', els.join(' '))
|
||||
);
|
||||
}
|
||||
|
||||
function addDeprecationWarnings(result, runnableType) {
|
||||
if (result && result.deprecationWarnings) {
|
||||
for (var i = 0; i < result.deprecationWarnings.length; i++) {
|
||||
var warning = result.deprecationWarnings[i].message;
|
||||
if (!j$.util.arrayContains(warning)) {
|
||||
deprecationWarnings.push({
|
||||
message: warning,
|
||||
runnableName: result.fullName,
|
||||
runnableType: runnableType
|
||||
});
|
||||
}
|
||||
deprecationWarnings.push({
|
||||
message: warning,
|
||||
stack: result.deprecationWarnings[i].stack,
|
||||
runnableName: result.fullName,
|
||||
runnableType: runnableType
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createExpander(stackTrace) {
|
||||
var expandLink = createDom('a', { href: '#' }, 'Show stack trace');
|
||||
var root = createDom(
|
||||
'div',
|
||||
{ className: 'jasmine-expander' },
|
||||
expandLink,
|
||||
createDom(
|
||||
'div',
|
||||
{ className: 'jasmine-expander-contents jasmine-stack-trace' },
|
||||
stackTrace
|
||||
)
|
||||
);
|
||||
|
||||
expandLink.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (root.classList.contains('jasmine-expanded')) {
|
||||
root.classList.remove('jasmine-expanded');
|
||||
expandLink.textContent = 'Show stack trace';
|
||||
} else {
|
||||
root.classList.add('jasmine-expanded');
|
||||
expandLink.textContent = 'Hide stack trace';
|
||||
}
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
function find(selector) {
|
||||
return getContainer().querySelector('.jasmine_html-reporter ' + selector);
|
||||
}
|
||||
@@ -666,11 +714,23 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
}
|
||||
|
||||
function createDom(type, attrs, childrenVarArgs) {
|
||||
var el = createElement(type);
|
||||
function createDom(type, attrs, childrenArrayOrVarArgs) {
|
||||
var el = createElement(type),
|
||||
children,
|
||||
i;
|
||||
|
||||
for (var i = 2; i < arguments.length; i++) {
|
||||
var child = arguments[i];
|
||||
if (j$.isArray_(childrenArrayOrVarArgs)) {
|
||||
children = childrenArrayOrVarArgs;
|
||||
} else {
|
||||
children = [];
|
||||
|
||||
for (i = 2; i < arguments.length; i++) {
|
||||
children.push(arguments[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < children.length; i++) {
|
||||
var child = children[i];
|
||||
|
||||
if (typeof child === 'string') {
|
||||
el.appendChild(createTextNode(child));
|
||||
@@ -699,11 +759,19 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
function specHref(result) {
|
||||
return addToExistingQueryString('spec', result.fullName);
|
||||
// include window.location.pathname to fix issue with karma-jasmine-html-reporter in angular: see https://github.com/jasmine/jasmine/issues/1906
|
||||
return (
|
||||
(window.location.pathname || '') +
|
||||
addToExistingQueryString('spec', result.fullName)
|
||||
);
|
||||
}
|
||||
|
||||
function seedHref(seed) {
|
||||
return addToExistingQueryString('seed', seed);
|
||||
// include window.location.pathname to fix issue with karma-jasmine-html-reporter in angular: see https://github.com/jasmine/jasmine/issues/1906
|
||||
return (
|
||||
(window.location.pathname || '') +
|
||||
addToExistingQueryString('seed', seed)
|
||||
);
|
||||
}
|
||||
|
||||
function defaultQueryString(key, value) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2008-2021 Pivotal Labs
|
||||
Copyright (c) 2008-2022 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
#
|
||||
module Jasmine
|
||||
module Core
|
||||
VERSION = "3.7.1"
|
||||
VERSION = "3.99.0"
|
||||
end
|
||||
end
|
||||
|
||||
22
package.json
22
package.json
@@ -1,13 +1,14 @@
|
||||
{
|
||||
"name": "jasmine-core",
|
||||
"license": "MIT",
|
||||
"version": "3.7.1",
|
||||
"version": "3.99.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jasmine/jasmine.git"
|
||||
},
|
||||
"keywords": [
|
||||
"test",
|
||||
"testing",
|
||||
"jasmine",
|
||||
"tdd",
|
||||
"bdd"
|
||||
@@ -22,16 +23,20 @@
|
||||
"ci": "node spec/support/ci.js",
|
||||
"ci:performance": "node spec/support/ci.js jasmine-browser-performance.json"
|
||||
},
|
||||
"description": "Official packaging of Jasmine's core files for use by Node.js projects.",
|
||||
"description": "Simple JavaScript testing framework for browsers and node.js",
|
||||
"homepage": "https://jasmine.github.io",
|
||||
"main": "./lib/jasmine-core.js",
|
||||
"files": [
|
||||
"MIT.LICENSE",
|
||||
"README.md",
|
||||
"images/*.{png,svg}",
|
||||
"lib/**/*.{js,css}",
|
||||
"package.json"
|
||||
],
|
||||
"devDependencies": {
|
||||
"acorn": "^6.0.0",
|
||||
"ejs": "^2.5.5",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-compat": "^3.8.0",
|
||||
"express": "^4.16.4",
|
||||
"fast-check": "^1.21.0",
|
||||
"fast-glob": "^2.2.6",
|
||||
"grunt": "^1.0.4",
|
||||
"grunt-cli": "^1.3.2",
|
||||
@@ -39,13 +44,12 @@
|
||||
"grunt-contrib-concat": "^1.0.1",
|
||||
"grunt-css-url-embed": "^1.11.1",
|
||||
"grunt-sass": "^3.0.2",
|
||||
"jasmine": "^3.4.0",
|
||||
"jasmine-browser-runner": "^0.4.0",
|
||||
"jasmine": "^3.10.0",
|
||||
"jasmine-browser-runner": "github:jasmine/jasmine-browser#main",
|
||||
"jsdom": "^15.0.0",
|
||||
"load-grunt-tasks": "^4.0.0",
|
||||
"node-sass": "^4.11.0",
|
||||
"prettier": "1.17.1",
|
||||
"selenium-webdriver": "^3.6.0",
|
||||
"sass": "^1.32.12",
|
||||
"shelljs": "^0.8.3",
|
||||
"temp": "^0.9.0"
|
||||
},
|
||||
|
||||
57
release_notes/3.10.0.md
Normal file
57
release_notes/3.10.0.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Jasmine Core 3.10 Release Notes
|
||||
|
||||
## New features and bug fixes
|
||||
|
||||
* Added support for running Jasmine multiple times
|
||||
* If the env is configured with `autoCleanClosures: false`, then it can be
|
||||
executed repeatedly.
|
||||
* Merges #1934 from @nicojs
|
||||
* Fixes #1925
|
||||
|
||||
* Improved error message when an async expectation occurs after the spec
|
||||
finishes
|
||||
* Merges #1937 from @AndreWillomitzer
|
||||
* Fixes #1854
|
||||
|
||||
* Reject timeout values that are too large for setTimeout
|
||||
* See #1930
|
||||
|
||||
* Don't immediately move to the next queueable fn on async error
|
||||
|
||||
This allows assertion failures and other errors that occur after the async
|
||||
error to be routed to the correct spec/suite.
|
||||
|
||||
* Added a stringContaining asymmetric equality tester
|
||||
* Fixes #1923.
|
||||
|
||||
* The jasmine-core Ruby gem now prints a deprecation message when loaded unless
|
||||
the SUPPRESS_JASMINE_DEPRECATION environment variable is set.
|
||||
|
||||
|
||||
## Documentation updates
|
||||
|
||||
* Added discussion of max timeout value to jsdocs
|
||||
* Merges #1931 from @trusktr
|
||||
|
||||
* Added missing @since annotations
|
||||
|
||||
* Improved jsdocs for asymmetric equality testers
|
||||
|
||||
* Added a deprecation notice to the jasmine-core Ruby gem's description
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 3.10.0 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 10, 12, 14, 16 |
|
||||
| Safari | 8-14 |
|
||||
| Chrome | 94 |
|
||||
| Firefox | 93, 78, 68 |
|
||||
| Edge | 94 |
|
||||
| Internet Explorer | 10, 11 |
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
12
release_notes/3.10.1.md
Normal file
12
release_notes/3.10.1.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Jasmine Core 3.10.1 Release Notes
|
||||
|
||||
## Bugfixes
|
||||
|
||||
* Fixed missing pendingReason in pending spec results
|
||||
* Fixes [#1939](https://github.com/jasmine/jasmine/issues/1939)
|
||||
* Merges [#1940](https://github.com/jasmine/jasmine/pull/1940) from @jan-molak
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
132
release_notes/3.8.0.md
Normal file
132
release_notes/3.8.0.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# Jasmine Core 3.8 Release Notes
|
||||
|
||||
## Summary
|
||||
|
||||
This is a maintenance release of Jasmine with a number of new features and fixes.
|
||||
|
||||
## Python deprecation
|
||||
|
||||
The Jasmine packages for Python are deprecated. We intend to continue releasing
|
||||
them through the end of the 3.x series, but after that they will be
|
||||
discontinued. We recommend migrating to the following alternatives:
|
||||
|
||||
* The [jasmine-browser-runner](https://github.com/jasmine/jasmine-browser)
|
||||
npm package to run specs in browsers, including headless Chrome and
|
||||
Saucelabs. This is the most direct replacement for the `jasmine server`
|
||||
and `jasmine ci` commands provided by the `jasmine` Python package.
|
||||
* The [jasmine](https://github.com/jasmine/jasmine-npm) npm package (
|
||||
`npm install jasmine`) to run specs under Node.js.
|
||||
* The standalone distribution from the
|
||||
[latest Jasmine release](https://github.com/jasmine/jasmine/releases) to
|
||||
run specs in browsers with no additional tools.
|
||||
* The [jasmine-core](https://github.com/jasmine/jasmine) npm package if all
|
||||
you need is the Jasmine assets. This is the direct equivalent of the
|
||||
jasmine-core Python package.
|
||||
|
||||
|
||||
## New features and bug fixes
|
||||
|
||||
* Fixed spec filtering in Karma
|
||||
* Merges [#1920](https://github.com/jasmine/jasmine/pull/1920) from @jlpstolwijk
|
||||
* Fixes [#1906](https://github.com/jasmine/jasmine/issues/1906)
|
||||
|
||||
* Added expectAsync(...).already
|
||||
* Causes async matchers to immediately fail if the promise is pending
|
||||
* See https://jasmine.github.io/api/3.8/async-matchers.html#already
|
||||
* Fixes [#1845](https://github.com/jasmine/jasmine/issues/1845)
|
||||
|
||||
* Include rejection details in failure messages for toBeResolved and toBeResolvedWith
|
||||
|
||||
* Fixed "stop spec on expectation failure" checkbox in standalone
|
||||
|
||||
* Added option for spyOnAllFunctions to include non-enumerable props
|
||||
* Makes spyOnAllFunctions work on instance methods of ES6 classes
|
||||
* Merges [#1909](https://github.com/jasmine/jasmine/pull/1909) from @Dari-k
|
||||
* Fixes [#1897](https://github.com/jasmine/jasmine/issues/1897)
|
||||
|
||||
* Added Spy#calls#thisFor
|
||||
* Provides the `this` value for a given spy call
|
||||
* Merges [#1903](https://github.com/jasmine/jasmine/pull/1903) from @ajvincent
|
||||
|
||||
* Improved handling of unhandled promise rejections with no error in Node
|
||||
* Fixes [#1759](https://github.com/jasmine/jasmine/issues/1759)
|
||||
|
||||
|
||||
## Documentation updates
|
||||
|
||||
* Updated package description
|
||||
|
||||
* Updated contributing guide
|
||||
|
||||
* Added TypeScript typings and jasmine-browser-runner to issue template
|
||||
|
||||
* Removed constructors from jsdocs of classes that aren't user-constructable
|
||||
|
||||
* Fixed config.seed type in jsdocs
|
||||
* Merges [#1892](https://github.com/jasmine/jasmine/pull/1892) from @UziTech
|
||||
|
||||
* Added jsdocs for the following:
|
||||
* asymmetric equality testers
|
||||
* Env#execute
|
||||
* Env#allowRespy
|
||||
* The public portion of Spec
|
||||
* Spy.callData.returnValue
|
||||
* Env#topSuite and Suite
|
||||
|
||||
* Added a jsdoc cross-reference from Configuration to its usage
|
||||
|
||||
* Added a note about correct usage of async matchers
|
||||
|
||||
* Added support for ArrayBuffers to matchersUtil.equals
|
||||
* Merges [#1891](https://github.com/jasmine/jasmine/pull/1892) from @Finesse
|
||||
* Merges [#1689](https://github.com/jasmine/jasmine/pull/1892) from @dankurka
|
||||
* Fixes [#1687](https://github.com/jasmine/jasmine/issues/1687)
|
||||
|
||||
|
||||
## Internal notes
|
||||
|
||||
* Fixed typo in spec name
|
||||
* Merges [#1918](https://github.com/jasmine/jasmine/pull/1918) from @eltociear
|
||||
|
||||
* Specify files to include in the NPM package rather than files to exclude
|
||||
|
||||
* Added test coverage for MatchersUtil#equals with typed arrays
|
||||
|
||||
* Removed checks for typed array support in the test suite
|
||||
* All supported browsers have all typed arrays except for Uint8ClampedArray,
|
||||
BigInt64Array, and BigUint64Array.
|
||||
|
||||
* Fixed test failures on IE 10
|
||||
|
||||
* Test matrix updates
|
||||
* Added Node 16
|
||||
* Added Safari 14
|
||||
* Added Firefox 78 (closest match to current ESR)
|
||||
* Removed Safari 10-12 to speed up CI. The newer and older versions we test
|
||||
provide a good measure of safety.
|
||||
|
||||
* Replaced node-sass dev dependency that isn't compatible with Node 16
|
||||
|
||||
* Removed unused dev dependencies
|
||||
|
||||
* Migrated CI from Travis to Circle
|
||||
|
||||
* Compensate for clock jitter in specs
|
||||
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 3.8.0 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 10, 12, 14, 16 |
|
||||
| Safari | 8-14 |
|
||||
| Chrome | 91 |
|
||||
| Firefox | 89, 68, 78 |
|
||||
| Edge | 91 |
|
||||
| Internet Explorer | 10, 11 |
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
65
release_notes/3.9.0.md
Normal file
65
release_notes/3.9.0.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Jasmine Core 3.9 Release Notes
|
||||
|
||||
## New features and bug fixes
|
||||
|
||||
* Fixed Trusted Types error in `j$.isError_` in Chromium-based browsers
|
||||
* Merges [#1921](https://github.com/jasmine/jasmine/pull/1921) from @bjarkler
|
||||
* Fixes [#1910](https://github.com/jasmine/jasmine/issues/1910)
|
||||
* Fixes [#1653](https://github.com/jasmine/jasmine/issues/1653)
|
||||
|
||||
* Better reporting of unhandled promise rejections with truthy but non-`Error`
|
||||
reasons on Node
|
||||
* `Env#execute` returns a promise in environments that support promises
|
||||
* Renamed `failFast` and `oneFailurePerSpec` config props to `stopOnSpecFailure`
|
||||
and `stopSpecOnExpectationFailure`
|
||||
|
||||
The new names are more self-explanatory and consistent with jasmine-npm. The
|
||||
old names are deprecated but will still work until the next major release.
|
||||
|
||||
* Split `boot.js` into two files to allow the env to be configured in between
|
||||
|
||||
This is mainly intended to support jasmine-browser-runner, which will load
|
||||
a script that configures the env in between the two boot files (`boot0.js` and
|
||||
`boot1.js`). The single-file `boot.js` will still be included until the next
|
||||
major release.
|
||||
|
||||
## Ruby deprecation
|
||||
|
||||
The Jasmine Ruby gems are deprecated. There will be no further releases after
|
||||
the end of the Jasmine 3.x series. We recommend that most users migrate to the
|
||||
[jasmine-browser-runner](https://github.com/jasmine/jasmine-browser)
|
||||
npm package, which is the direct replacement for the `jasmine` gem.
|
||||
|
||||
If `jasmine-browser-runner` doesn't meet your needs, one of these might:
|
||||
|
||||
* The [jasmine](https://github.com/jasmine/jasmine-npm) npm package to run
|
||||
specs in Node.js.
|
||||
* The [standalone distribution](https://github.com/jasmine/jasmine#installation)
|
||||
to run specs in browsers with no additional tools.
|
||||
* The [jasmine-core](https://github.com/jasmine/jasmine) npm package if all
|
||||
you need is the Jasmine assets. This is the direct equivalent of the
|
||||
`jasmine-core` Ruby gem.
|
||||
|
||||
## Documentation updates
|
||||
|
||||
* Added API docs for `Suite#id` and `Spec#id`
|
||||
* Marked `Env#hideDisabled` deprecated in jsdocs
|
||||
|
||||
|
||||
------
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 3.9.0 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 10, 12, 14, 16 |
|
||||
| Safari | 8-14 |
|
||||
| Chrome | 92 |
|
||||
| Firefox | 91, 78, 68 |
|
||||
| Edge | 92 |
|
||||
| Internet Explorer | 10, 11 |
|
||||
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
15
release_notes/3.99.0.md
Normal file
15
release_notes/3.99.0.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Jasmine Core 3.99.0 Release Notes
|
||||
|
||||
## Summary
|
||||
|
||||
This release adds deprecation warnings for breaking changes that will be
|
||||
introduced in Jasmine 4.0. Please see the
|
||||
[migration guide](https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0)
|
||||
for more information.
|
||||
|
||||
This is the last planned release of jasmine-core for Ruby or Python. Versions
|
||||
4.0 and later will be offered only via NPM and the standalone distribution.
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
44
scripts/run-all-browsers
Executable file
44
scripts/run-all-browsers
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
|
||||
run_browser() {
|
||||
browser=$1
|
||||
version=$2
|
||||
description="$browser $version"
|
||||
if [ $version = "latest" ]; then
|
||||
version=""
|
||||
fi
|
||||
|
||||
echo
|
||||
echo
|
||||
echo "Running $description"
|
||||
echo
|
||||
USE_SAUCE=true JASMINE_BROWSER=$browser SAUCE_BROWSER_VERSION=$version npm run ci
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "PASS: $description" >> "$passfile"
|
||||
else
|
||||
echo "FAIL: $description" >> "$failfile"
|
||||
fi
|
||||
}
|
||||
|
||||
passfile=`mktemp -t jasmine-results.XXXXXX` || exit 1
|
||||
failfile=`mktemp -t jasmine-results.XXXXXX` || exit 1
|
||||
run_browser "internet explorer" 11
|
||||
run_browser "internet explorer" 10
|
||||
run_browser chrome latest
|
||||
run_browser firefox latest
|
||||
run_browser firefox 91
|
||||
run_browser firefox 78
|
||||
run_browser firefox 68
|
||||
run_browser safari 14
|
||||
run_browser safari 13
|
||||
run_browser safari 9
|
||||
run_browser safari 8
|
||||
run_browser MicrosoftEdge latest
|
||||
|
||||
echo
|
||||
cat "$passfile" "$failfile"
|
||||
|
||||
if [ -s "$failfile" ]; then
|
||||
exit 1
|
||||
fi
|
||||
37
scripts/start-sauce-connect
Executable file
37
scripts/start-sauce-connect
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
||||
if [ $# -gt 1 -o "$1" = "--help" ]; then
|
||||
echo "Usage: $0 [pidfile]" 1>&2
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
pidfile=`mktemp`
|
||||
else
|
||||
pidfile="$1"
|
||||
fi
|
||||
|
||||
outfile=`mktemp`
|
||||
echo "Starting Sauce Connect"
|
||||
if [ -z "$SAUCE_TUNNEL_IDENTIFIER" ]; then
|
||||
sc -u "$SAUCE_USERNAME" -k "$SAUCE_ACCESS_KEY" -X 4445 --pidfile "$pidfile" 2>&1 | tee "$outfile" &
|
||||
else
|
||||
sc -u "$SAUCE_USERNAME" -k "$SAUCE_ACCESS_KEY" -X 4445 --pidfile "$pidfile" -i "$SAUCE_TUNNEL_IDENTIFIER" 2>&1 | tee "$outfile" &
|
||||
fi
|
||||
|
||||
while ! fgrep "Sauce Connect is up, you may start your tests." "$outfile" > /dev/null; do
|
||||
sleep 1
|
||||
|
||||
if ! ps -p $(cat "$pidfile") > /dev/null; then
|
||||
echo "Sauce Connect exited"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if ! nc -z localhost 4445; then
|
||||
echo "Can't connect to Sauce tunnel"
|
||||
killall sc
|
||||
exit 1
|
||||
fi
|
||||
33
scripts/stop-sauce-connect
Executable file
33
scripts/stop-sauce-connect
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 sauce-connect-pid" 1>&2
|
||||
exit
|
||||
fi
|
||||
|
||||
pid="$1"
|
||||
echo "PID: $pid"
|
||||
|
||||
echo "Stopping Sauce Connect"
|
||||
# Sauce Connect docs say that we can just kill -9 it if we don't care about
|
||||
# failing any ongoing sessions. In practice, that sometimes works but usually
|
||||
# leaks a tunnel so badly that you can't even stop it from the web UI.
|
||||
# Instead of doing that, we give Sauce Connect some time to shut down
|
||||
# gracefully and then give up.
|
||||
kill -INT $pid
|
||||
|
||||
# Wait up to 2 minutes, then give up if it's still running
|
||||
n=0
|
||||
while [ $n -lt 120 ] && ps -p $pid > /dev/null; do
|
||||
sleep 1
|
||||
kill -INT $pid 2> /dev/null || true
|
||||
n=$(($n + 1))
|
||||
done
|
||||
|
||||
if ps -p $pid > /dev/null; then
|
||||
echo "Could not shut down Sauce Connect"
|
||||
fi
|
||||
|
||||
exit $exitcode
|
||||
32
setup.py
32
setup.py
@@ -4,15 +4,41 @@ import json
|
||||
with open('package.json') as packageFile:
|
||||
version = json.load(packageFile)['version']
|
||||
|
||||
short_description=('Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on '+
|
||||
'browsers, DOM, or any JavaScript framework. Thus it\'s suited for websites, '+
|
||||
'Node.js (http://nodejs.org) projects, or anywhere that JavaScript can run.')
|
||||
deprecation=('The Jasmine packages for Python are deprecated. There will be no further\n' +
|
||||
'releases after the end of the Jasmine 3.x series. We recommend migrating to the\n' +
|
||||
'following options:\n' +
|
||||
'\n' +
|
||||
'* jasmine-browser-runner (<https://github.com/jasmine/jasmine-browser>,\n' +
|
||||
' `npm install jasmine-browser-runner`) to run specs in browsers, including\n' +
|
||||
' headless Chrome and Saucelabs. This is the most direct replacement for the\n' +
|
||||
' jasmine server` and `jasmine ci` commands provided by the `jasmine` Python\n' +
|
||||
' package.\n' +
|
||||
'* The jasmine npm package (<https://github.com/jasmine/jasmine-npm>,\n' +
|
||||
' `npm install jasmine`) to run specs under Node.js.\n' +
|
||||
'* The standalone distribution from the latest Jasmine release\n' +
|
||||
' <https://github.com/jasmine/jasmine/releases> to run specs in browsers with\n' +
|
||||
' no additional tools.\n' +
|
||||
'* The jasmine-core npm package (`npm install jasmine-core`) if all you need is\n' +
|
||||
' the Jasmine assets. This is the direct equivalent of the jasmine-core Python\n' +
|
||||
' package.\n' +
|
||||
'\n' +
|
||||
'Except for the standalone distribution, all of the above are distributed through\n'
|
||||
'npm.\n')
|
||||
long_description = short_description + '\n\n' + deprecation
|
||||
|
||||
|
||||
setup(
|
||||
name="jasmine-core",
|
||||
version=version,
|
||||
url="http://jasmine.github.io",
|
||||
author="Pivotal Labs",
|
||||
author_email="jasmine-js@googlegroups.com",
|
||||
description=('Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on '+
|
||||
'browsers, DOM, or any JavaScript framework. Thus it\'s suited for websites, '+
|
||||
'Node.js (http://nodejs.org) projects, or anywhere that JavaScript can run.'),
|
||||
description=short_description,
|
||||
long_description=long_description,
|
||||
long_description_content_type='text/plain',
|
||||
license='MIT',
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
|
||||
@@ -96,8 +96,8 @@ describe('AsyncExpectation', function() {
|
||||
jasmine.getEnv().requirePromises();
|
||||
|
||||
var matchersUtil = {
|
||||
buildFailureMessage: function() {
|
||||
return 'failure message';
|
||||
pp: function(val) {
|
||||
return val.toString();
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
@@ -114,7 +114,8 @@ describe('AsyncExpectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(
|
||||
false,
|
||||
jasmine.objectContaining({
|
||||
message: 'Some context: failure message'
|
||||
message:
|
||||
'Some context: Expected a promise to be resolved but it was rejected with rejected.'
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -144,7 +145,8 @@ describe('AsyncExpectation', function() {
|
||||
false,
|
||||
jasmine.objectContaining({
|
||||
message:
|
||||
"Some context: Expected a promise to be resolved to 'a' but it was rejected."
|
||||
"Some context: Expected a promise to be resolved to 'a' " +
|
||||
"but it was rejected with 'b'."
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -267,23 +269,18 @@ describe('AsyncExpectation', function() {
|
||||
matchersUtil = {
|
||||
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
|
||||
},
|
||||
customEqualityTesters = ['a'],
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
expectation;
|
||||
|
||||
expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
matchersUtil: matchersUtil,
|
||||
customAsyncMatchers: matchers,
|
||||
customEqualityTesters: customEqualityTesters,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
});
|
||||
|
||||
return expectation.toFoo('hello').then(function() {
|
||||
expect(matcherFactory).toHaveBeenCalledWith(
|
||||
matchersUtil,
|
||||
customEqualityTesters
|
||||
);
|
||||
expect(matcherFactory).toHaveBeenCalledWith(matchersUtil);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -30,6 +30,20 @@ describe('CallTracker', function() {
|
||||
expect(callTracker.argsFor(1)).toEqual([0, 'foo']);
|
||||
});
|
||||
|
||||
it("tracks the 'this' object from each execution", function() {
|
||||
var callTracker = new jasmineUnderTest.CallTracker();
|
||||
|
||||
var this0 = {},
|
||||
this1 = {};
|
||||
callTracker.track({ object: this0, args: [] });
|
||||
callTracker.track({ object: this1, args: [] });
|
||||
callTracker.track({ args: [] });
|
||||
|
||||
expect(callTracker.thisFor(0)).toBe(this0);
|
||||
expect(callTracker.thisFor(1)).toBe(this1);
|
||||
expect(callTracker.thisFor(2)).toBe(undefined);
|
||||
});
|
||||
|
||||
it('returns any empty array when there was no call', function() {
|
||||
var callTracker = new jasmineUnderTest.CallTracker();
|
||||
|
||||
|
||||
@@ -950,6 +950,28 @@ describe('Clock (acceptance)', function() {
|
||||
expect(timeoutDate).toEqual(baseTime.getTime() + 150);
|
||||
});
|
||||
|
||||
it('logs a deprecation when mockDate is called with a non-Date', function() {
|
||||
var delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
global = { Date: Date },
|
||||
mockDate = new jasmineUnderTest.MockDate(global),
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
{ setTimeout: setTimeout },
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
),
|
||||
env = jasmineUnderTest.getEnv();
|
||||
|
||||
spyOn(env, 'deprecated');
|
||||
clock.mockDate(12345);
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'The argument to jasmine.clock().mockDate(), if specified, should be ' +
|
||||
'a Date instance. Passing anything other than a Date will be ' +
|
||||
'treated as an error in a future release.'
|
||||
);
|
||||
});
|
||||
|
||||
it('mocks the Date object and updates the date per delayed function', function() {
|
||||
var delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
global = { Date: Date },
|
||||
|
||||
329
spec/core/DeprecatorSpec.js
Normal file
329
spec/core/DeprecatorSpec.js
Normal file
@@ -0,0 +1,329 @@
|
||||
/* eslint no-console: 0 */
|
||||
describe('Deprecator', function() {
|
||||
describe('#deprecate', function() {
|
||||
beforeEach(function() {
|
||||
spyOn(console, 'error');
|
||||
});
|
||||
|
||||
it('logs the mesage without context when the runnable is the top suite', function() {
|
||||
var runnable = { addDeprecationWarning: function() {} };
|
||||
var deprecator = new jasmineUnderTest.Deprecator(runnable);
|
||||
deprecator.verboseDeprecations(true);
|
||||
|
||||
deprecator.addDeprecationWarning(runnable, 'the message', {
|
||||
omitStackTrace: true
|
||||
});
|
||||
|
||||
expect(console.error).toHaveBeenCalledWith('DEPRECATION: the message');
|
||||
});
|
||||
|
||||
it('logs the message in a descendant suite', function() {
|
||||
var runnable = {
|
||||
addDeprecationWarning: function() {},
|
||||
getFullName: function() {
|
||||
return 'the suite';
|
||||
},
|
||||
children: []
|
||||
};
|
||||
var deprecator = new jasmineUnderTest.Deprecator({});
|
||||
deprecator.verboseDeprecations(true);
|
||||
|
||||
deprecator.addDeprecationWarning(runnable, 'the message', {
|
||||
omitStackTrace: true
|
||||
});
|
||||
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
'DEPRECATION: the message (in suite: the suite)'
|
||||
);
|
||||
});
|
||||
|
||||
it('logs and reports the message in a spec', function() {
|
||||
var runnable = {
|
||||
addDeprecationWarning: function() {},
|
||||
getFullName: function() {
|
||||
return 'the spec';
|
||||
}
|
||||
};
|
||||
var deprecator = new jasmineUnderTest.Deprecator({});
|
||||
deprecator.verboseDeprecations(true);
|
||||
|
||||
deprecator.addDeprecationWarning(runnable, 'the message', {
|
||||
omitStackTrace: true
|
||||
});
|
||||
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
'DEPRECATION: the message (in spec: the spec)'
|
||||
);
|
||||
});
|
||||
|
||||
it('logs and reports the message without runnable info when ignoreRunnable is true', function() {
|
||||
var topSuite = jasmine.createSpyObj('topSuite', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
var deprecator = new jasmineUnderTest.Deprecator(topSuite);
|
||||
var runnable = jasmine.createSpyObj('spec', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
runnable.getFullName.and.returnValue('a spec');
|
||||
|
||||
deprecator.addDeprecationWarning(runnable, 'the message', {
|
||||
ignoreRunnable: true
|
||||
});
|
||||
|
||||
expect(topSuite.addDeprecationWarning).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
message: jasmine.stringMatching(/^the message/)
|
||||
})
|
||||
);
|
||||
expect(runnable.addDeprecationWarning).not.toHaveBeenCalled();
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(/the message/)
|
||||
);
|
||||
expect(console.error).not.toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(/a spec/)
|
||||
);
|
||||
});
|
||||
|
||||
describe('with no options', function() {
|
||||
it('includes the stack trace', function() {
|
||||
testStackTrace(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
it('omits the stack trace when omitStackTrace is true', function() {
|
||||
testNoStackTrace({ omitStackTrace: true });
|
||||
});
|
||||
|
||||
it('includes the stack trace when omitStackTrace is false', function() {
|
||||
testStackTrace({ omitStackTrace: false });
|
||||
});
|
||||
|
||||
it('includes the stack trace when omitStackTrace is undefined', function() {
|
||||
testStackTrace({ includeStackTrace: undefined });
|
||||
});
|
||||
|
||||
it('emits the deprecation only once when verboseDeprecations is not set', function() {
|
||||
var deprecator = new jasmineUnderTest.Deprecator({});
|
||||
var runnable1 = jasmine.createSpyObj('runnable1', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
var runnable2 = jasmine.createSpyObj('runnable2', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
|
||||
deprecator.addDeprecationWarning(runnable1, 'the message');
|
||||
deprecator.addDeprecationWarning(runnable1, 'the message');
|
||||
deprecator.addDeprecationWarning(runnable2, 'the message');
|
||||
|
||||
expect(runnable1.addDeprecationWarning).toHaveBeenCalledTimes(1);
|
||||
expect(runnable2.addDeprecationWarning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('emits the deprecation only once when verboseDeprecations is false', function() {
|
||||
var deprecator = new jasmineUnderTest.Deprecator({});
|
||||
var runnable1 = jasmine.createSpyObj('runnable1', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
var runnable2 = jasmine.createSpyObj('runnable2', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
|
||||
deprecator.verboseDeprecations(false);
|
||||
deprecator.addDeprecationWarning(runnable1, 'the message');
|
||||
deprecator.addDeprecationWarning(runnable1, 'the message');
|
||||
deprecator.addDeprecationWarning(runnable2, 'the message');
|
||||
|
||||
expect(runnable1.addDeprecationWarning).toHaveBeenCalledTimes(1);
|
||||
expect(runnable2.addDeprecationWarning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('emits the deprecation for each call when verboseDeprecations is true', function() {
|
||||
var deprecator = new jasmineUnderTest.Deprecator({});
|
||||
var runnable1 = jasmine.createSpyObj('runnable1', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
var runnable2 = jasmine.createSpyObj('runnable2', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
|
||||
deprecator.verboseDeprecations(true);
|
||||
deprecator.addDeprecationWarning(runnable1, 'the message');
|
||||
deprecator.addDeprecationWarning(runnable1, 'the message');
|
||||
deprecator.addDeprecationWarning(runnable2, 'the message');
|
||||
|
||||
expect(runnable1.addDeprecationWarning).toHaveBeenCalledTimes(2);
|
||||
expect(runnable2.addDeprecationWarning).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('includes a note about verboseDeprecations', function() {
|
||||
var deprecator = new jasmineUnderTest.Deprecator({});
|
||||
var runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
|
||||
deprecator.addDeprecationWarning(runnable, 'the message');
|
||||
|
||||
expect(runnable.addDeprecationWarning).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
runnable.addDeprecationWarning.calls.argsFor(0)[0].message
|
||||
).toContain(verboseDeprecationsNote());
|
||||
expect(console.error).toHaveBeenCalledTimes(1);
|
||||
expect(console.error.calls.argsFor(0)[0]).toContain(
|
||||
verboseDeprecationsNote()
|
||||
);
|
||||
});
|
||||
|
||||
it('omits the note about verboseDeprecations when verboseDeprecations is true', function() {
|
||||
var deprecator = new jasmineUnderTest.Deprecator({});
|
||||
var runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
|
||||
deprecator.verboseDeprecations(true);
|
||||
deprecator.addDeprecationWarning(runnable, 'the message');
|
||||
|
||||
expect(runnable.addDeprecationWarning).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
runnable.addDeprecationWarning.calls.argsFor(0)[0].message
|
||||
).not.toContain(verboseDeprecationsNote());
|
||||
expect(console.error).toHaveBeenCalledTimes(1);
|
||||
expect(console.error.calls.argsFor(0)[0]).not.toContain(
|
||||
verboseDeprecationsNote()
|
||||
);
|
||||
});
|
||||
|
||||
describe('When the deprecation is an Error', function() {
|
||||
// This form is used by external systems like atom-jasmine3-test-runner
|
||||
// to report their own deprecations through Jasmine. See
|
||||
// <https://github.com/jasmine/jasmine/pull/1498>.
|
||||
it('passes the error through unchanged', function() {
|
||||
var deprecator = new jasmineUnderTest.Deprecator({});
|
||||
var runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
var exceptionFormatter = new jasmineUnderTest.ExceptionFormatter();
|
||||
var deprecation, originalStack;
|
||||
|
||||
try {
|
||||
throw new Error('the deprecation');
|
||||
} catch (err) {
|
||||
deprecation = err;
|
||||
originalStack = err.stack;
|
||||
}
|
||||
|
||||
deprecator.addDeprecationWarning(runnable, deprecation);
|
||||
|
||||
expect(runnable.addDeprecationWarning).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
runnable.addDeprecationWarning.calls.argsFor(0)[0].message
|
||||
).toEqual('the deprecation');
|
||||
expect(runnable.addDeprecationWarning.calls.argsFor(0)[0].stack).toBe(
|
||||
originalStack
|
||||
);
|
||||
expect(console.error).toHaveBeenCalledTimes(1);
|
||||
expect(console.error.calls.argsFor(0)[0].message).toEqual(
|
||||
'the deprecation'
|
||||
);
|
||||
expect(console.error.calls.argsFor(0)[0].stack).toEqual(originalStack);
|
||||
});
|
||||
|
||||
it('reports the deprecation every time, regardless of config.verboseDeprecations', function() {
|
||||
var deprecator = new jasmineUnderTest.Deprecator({});
|
||||
var runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
var deprecation;
|
||||
|
||||
try {
|
||||
throw new Error('the deprecation');
|
||||
} catch (err) {
|
||||
deprecation = err;
|
||||
}
|
||||
|
||||
deprecator.addDeprecationWarning(runnable, deprecation);
|
||||
deprecator.addDeprecationWarning(runnable, deprecation);
|
||||
|
||||
expect(runnable.addDeprecationWarning).toHaveBeenCalledTimes(2);
|
||||
expect(console.error).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('omits the note about verboseDeprecations', function() {
|
||||
var deprecator = new jasmineUnderTest.Deprecator({});
|
||||
var runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
var deprecation;
|
||||
|
||||
try {
|
||||
throw new Error('the deprecation');
|
||||
} catch (err) {
|
||||
deprecation = err;
|
||||
}
|
||||
|
||||
deprecator.addDeprecationWarning(runnable, deprecation);
|
||||
|
||||
expect(runnable.addDeprecationWarning).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
runnable.addDeprecationWarning.calls.argsFor(0)[0].message
|
||||
).not.toContain(verboseDeprecationsNote());
|
||||
expect(console.error).toHaveBeenCalledTimes(1);
|
||||
expect(console.error.calls.argsFor(0)[0]).not.toContain(
|
||||
verboseDeprecationsNote()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
function verboseDeprecationsNote() {
|
||||
return (
|
||||
'Note: This message will be shown only once. Set the ' +
|
||||
'verboseDeprecations config property to true to see every occurrence.'
|
||||
);
|
||||
}
|
||||
|
||||
function testStackTrace(options) {
|
||||
var deprecator = new jasmineUnderTest.Deprecator({});
|
||||
var runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
|
||||
deprecator.addDeprecationWarning(runnable, 'the message', options);
|
||||
|
||||
expect(runnable.addDeprecationWarning).toHaveBeenCalledWith({
|
||||
message: jasmine.stringMatching(/^the message/),
|
||||
omitStackTrace: false
|
||||
});
|
||||
expect(console.error).toHaveBeenCalledTimes(1);
|
||||
expect(console.error.calls.argsFor(0)[0]).toContain('the message');
|
||||
expect(console.error.calls.argsFor(0)[0]).toContain('DeprecatorSpec.js');
|
||||
}
|
||||
|
||||
function testNoStackTrace(options) {
|
||||
var deprecator = new jasmineUnderTest.Deprecator({});
|
||||
var runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
|
||||
deprecator.addDeprecationWarning(runnable, 'the message', options);
|
||||
|
||||
expect(runnable.addDeprecationWarning).toHaveBeenCalledWith({
|
||||
message: jasmine.stringMatching(/^the message/),
|
||||
omitStackTrace: true
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -26,9 +26,228 @@ describe('Env', function() {
|
||||
});
|
||||
|
||||
describe('#topSuite', function() {
|
||||
it('returns the Jasmine top suite for users to traverse the spec tree', function() {
|
||||
var suite = env.topSuite();
|
||||
it('returns an object that describes the tree of suites and specs', function() {
|
||||
var suite;
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
env.it('a top level spec');
|
||||
env.describe('a suite', function() {
|
||||
env.it('a spec');
|
||||
env.describe('a nested suite', function() {
|
||||
env.it('a nested spec');
|
||||
});
|
||||
});
|
||||
|
||||
suite = env.topSuite();
|
||||
expect(suite.description).toEqual('Jasmine__TopLevel__Suite');
|
||||
expect(suite.getFullName()).toEqual('');
|
||||
expect(suite.children.length).toEqual(2);
|
||||
|
||||
expect(suite.children[0].description).toEqual('a top level spec');
|
||||
expect(suite.children[0].getFullName()).toEqual('a top level spec');
|
||||
expect(suite.children[0].children).toBeFalsy();
|
||||
|
||||
expect(suite.children[1].description).toEqual('a suite');
|
||||
expect(suite.children[1].getFullName()).toEqual('a suite');
|
||||
expect(suite.children[1].parentSuite).toBe(suite);
|
||||
expect(suite.children[1].children.length).toEqual(2);
|
||||
|
||||
expect(suite.children[1].children[0].description).toEqual('a spec');
|
||||
expect(suite.children[1].children[0].getFullName()).toEqual(
|
||||
'a suite a spec'
|
||||
);
|
||||
expect(suite.children[1].children[0].children).toBeFalsy();
|
||||
|
||||
expect(suite.children[1].children[1].description).toEqual(
|
||||
'a nested suite'
|
||||
);
|
||||
expect(suite.children[1].children[1].getFullName()).toEqual(
|
||||
'a suite a nested suite'
|
||||
);
|
||||
expect(suite.children[1].children[1].parentSuite).toBe(suite.children[1]);
|
||||
expect(suite.children[1].children[1].children.length).toEqual(1);
|
||||
|
||||
expect(suite.children[1].children[1].children[0].description).toEqual(
|
||||
'a nested spec'
|
||||
);
|
||||
expect(suite.children[1].children[1].children[0].getFullName()).toEqual(
|
||||
'a suite a nested suite a nested spec'
|
||||
);
|
||||
expect(suite.children[1].children[1].children[0].children).toBeFalsy();
|
||||
});
|
||||
|
||||
it('does not deprecate access to public Suite and Spec members', function() {
|
||||
jasmine.getEnv().requireProxy();
|
||||
var suite;
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
env.it('a top level spec');
|
||||
env.describe('a suite', function() {
|
||||
env.it('a spec');
|
||||
});
|
||||
|
||||
suite = env.topSuite();
|
||||
suite.id;
|
||||
suite.description;
|
||||
suite.getFullName();
|
||||
suite.children;
|
||||
suite.parentSuite;
|
||||
suite.children[0].id;
|
||||
suite.children[0].description;
|
||||
suite.children[0].getFullName();
|
||||
suite.children[0].children;
|
||||
|
||||
suite.children[1].id;
|
||||
suite.children[1].description;
|
||||
suite.children[1].getFullName();
|
||||
suite.children[1].parentSuite;
|
||||
suite.children[1].children;
|
||||
|
||||
expect(env.deprecated).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('deprecates access to internal Spec members via it(), fit(), and xit()', function() {
|
||||
jasmine.getEnv().requireProxy();
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
['it', 'fit', 'xit'].forEach(function(method) {
|
||||
var spec = env[method]('a spec', function() {});
|
||||
expect(env.deprecated).not.toHaveBeenCalled();
|
||||
|
||||
spec.pend();
|
||||
expect(env.deprecated)
|
||||
.withContext('via ' + method)
|
||||
.toHaveBeenCalledWith(
|
||||
'Access to private Spec members (in this case `pend`) is not ' +
|
||||
'supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Spec.html> for correct usage.'
|
||||
);
|
||||
env.deprecated.calls.reset();
|
||||
|
||||
spec.expectationFactory = {};
|
||||
expect(env.deprecated)
|
||||
.withContext('via ' + method)
|
||||
.toHaveBeenCalledWith(
|
||||
'Access to private Spec members (in this case `expectationFactory`) is not ' +
|
||||
'supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Spec.html> for correct usage.'
|
||||
);
|
||||
env.deprecated.calls.reset();
|
||||
|
||||
spec.expectationFactory = {};
|
||||
expect(env.deprecated)
|
||||
.withContext('via ' + method)
|
||||
.toHaveBeenCalledWith(
|
||||
'Access to private Spec members (in this case `expectationFactory`) is not ' +
|
||||
'supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Spec.html> for correct usage.'
|
||||
);
|
||||
env.deprecated.calls.reset();
|
||||
});
|
||||
});
|
||||
|
||||
it('deprecates access to internal Spec and Suite members via describe(), fdescribe(), and xdescribe()', function() {
|
||||
jasmine.getEnv().requireProxy();
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
['describe', 'fdescribe', 'xdescribe'].forEach(function(method) {
|
||||
var suite = env[method]('a suite', function() {
|
||||
env.it('a spec');
|
||||
});
|
||||
|
||||
suite.expectationFactory;
|
||||
expect(env.deprecated)
|
||||
.withContext('via ' + method)
|
||||
.toHaveBeenCalledWith(
|
||||
'Access to private Suite ' +
|
||||
'members (in this case `expectationFactory`) is ' +
|
||||
'not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Suite.html> for correct usage.'
|
||||
);
|
||||
env.deprecated.calls.reset();
|
||||
|
||||
suite.expectationFactory = {};
|
||||
expect(env.deprecated)
|
||||
.withContext('via ' + method)
|
||||
.toHaveBeenCalledWith(
|
||||
'Access to private Suite ' +
|
||||
'members (in this case `expectationFactory`) is ' +
|
||||
'not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Suite.html> for correct usage.'
|
||||
);
|
||||
env.deprecated.calls.reset();
|
||||
|
||||
suite.status();
|
||||
expect(env.deprecated)
|
||||
.withContext('via ' + method)
|
||||
.toHaveBeenCalledWith(
|
||||
'Access to private Suite ' +
|
||||
'members (in this case `status`) is ' +
|
||||
'not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Suite.html> for correct usage.'
|
||||
);
|
||||
env.deprecated.calls.reset();
|
||||
});
|
||||
});
|
||||
|
||||
it('deprecates access to internal Suite and Spec members via topSuite', function() {
|
||||
jasmine.getEnv().requireProxy();
|
||||
var topSuite, expectationFactory, spec;
|
||||
|
||||
env.it('a top level spec');
|
||||
spyOn(env, 'deprecated');
|
||||
topSuite = env.topSuite();
|
||||
|
||||
topSuite.expectationFactory;
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'Access to private Suite ' +
|
||||
'members (in this case `expectationFactory`) is ' +
|
||||
'not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Suite.html> for correct usage.'
|
||||
);
|
||||
env.deprecated.calls.reset();
|
||||
|
||||
topSuite.expectationFactory = expectationFactory;
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'Access to private Suite ' +
|
||||
'members (in this case `expectationFactory`) is ' +
|
||||
'not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Suite.html> for correct usage.'
|
||||
);
|
||||
|
||||
topSuite.status();
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'Access to private Suite ' +
|
||||
'members (in this case `status`) is ' +
|
||||
'not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Suite.html> for correct usage.'
|
||||
);
|
||||
|
||||
spec = topSuite.children[0];
|
||||
spec.pend();
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'Access to private Spec ' +
|
||||
'members (in this case `pend`) ' +
|
||||
'is not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Spec.html> for correct usage.'
|
||||
);
|
||||
|
||||
expectationFactory = spec.expectationFactory;
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'Access to private Spec ' +
|
||||
'members (in this case `expectationFactory`) ' +
|
||||
'is not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Spec.html> for correct usage.'
|
||||
);
|
||||
env.deprecated.calls.reset();
|
||||
|
||||
spec.expectationFactory = expectationFactory;
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'Access to private Spec ' +
|
||||
'members (in this case `expectationFactory`) ' +
|
||||
'is not supported and will break in a future release. See ' +
|
||||
'<https://jasmine.github.io/api/edge/Spec.html> for correct usage.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -37,7 +256,7 @@ describe('Env', function() {
|
||||
});
|
||||
|
||||
it('can configure specs to throw errors on expectation failures', function() {
|
||||
env.configure({ oneFailurePerSpec: true });
|
||||
env.configure({ stopSpecOnExpectationFailure: true });
|
||||
|
||||
spyOn(jasmineUnderTest, 'Spec');
|
||||
env.it('foo', function() {});
|
||||
@@ -49,7 +268,7 @@ describe('Env', function() {
|
||||
});
|
||||
|
||||
it('can configure suites to throw errors on expectation failures', function() {
|
||||
env.configure({ oneFailurePerSpec: true });
|
||||
env.configure({ stopSpecOnExpectationFailure: true });
|
||||
|
||||
spyOn(jasmineUnderTest, 'Suite');
|
||||
env.describe('foo', function() {});
|
||||
@@ -60,6 +279,119 @@ describe('Env', function() {
|
||||
);
|
||||
});
|
||||
|
||||
it('ignores configuration properties that are present but undefined', function() {
|
||||
spyOn(env, 'deprecated');
|
||||
var initialConfig = {
|
||||
random: true,
|
||||
seed: '123',
|
||||
failFast: true,
|
||||
failSpecWithNoExpectations: true,
|
||||
oneFailurePerSpec: true,
|
||||
stopSpecOnExpectationFailure: true,
|
||||
stopOnSpecFailure: true,
|
||||
hideDisabled: true
|
||||
};
|
||||
env.configure(initialConfig);
|
||||
|
||||
env.configure({
|
||||
random: undefined,
|
||||
seed: undefined,
|
||||
failFast: undefined,
|
||||
failSpecWithNoExpectations: undefined,
|
||||
oneFailurePerSpec: undefined,
|
||||
stopSpecOnExpectationFailure: undefined,
|
||||
stopOnSpecFailure: undefined,
|
||||
hideDisabled: undefined
|
||||
});
|
||||
|
||||
expect(env.configuration()).toEqual(
|
||||
jasmine.objectContaining(initialConfig)
|
||||
);
|
||||
});
|
||||
|
||||
it('sets stopOnSpecFailure when failFast is set, and vice versa', function() {
|
||||
spyOn(env, 'deprecated');
|
||||
env.configure({ failFast: true });
|
||||
expect(env.configuration()).toEqual(
|
||||
jasmine.objectContaining({
|
||||
failFast: true,
|
||||
stopOnSpecFailure: true
|
||||
})
|
||||
);
|
||||
|
||||
env.configure({ stopOnSpecFailure: false });
|
||||
expect(env.configuration()).toEqual(
|
||||
jasmine.objectContaining({
|
||||
failFast: false,
|
||||
stopOnSpecFailure: false
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects a single call that sets stopOnSpecFailure and failFast to different values', function() {
|
||||
spyOn(env, 'deprecated');
|
||||
expect(function() {
|
||||
env.configure({ failFast: true, stopOnSpecFailure: false });
|
||||
}).toThrowError(
|
||||
'stopOnSpecFailure and failFast are aliases for each ' +
|
||||
"other. Don't set failFast if you also set stopOnSpecFailure."
|
||||
);
|
||||
});
|
||||
|
||||
it('deprecates the failFast config property', function() {
|
||||
spyOn(env, 'deprecated');
|
||||
env.configure({ failFast: true });
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'The `failFast` config property is deprecated and will be removed in a ' +
|
||||
'future version of Jasmine. Please use `stopOnSpecFailure` instead.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
});
|
||||
|
||||
it('sets stopSpecOnExpectationFailure when oneFailurePerSpec is set, and vice versa', function() {
|
||||
spyOn(env, 'deprecated');
|
||||
env.configure({ oneFailurePerSpec: true });
|
||||
expect(env.configuration()).toEqual(
|
||||
jasmine.objectContaining({
|
||||
oneFailurePerSpec: true,
|
||||
stopSpecOnExpectationFailure: true
|
||||
})
|
||||
);
|
||||
|
||||
env.configure({ stopSpecOnExpectationFailure: false });
|
||||
expect(env.configuration()).toEqual(
|
||||
jasmine.objectContaining({
|
||||
oneFailurePerSpec: false,
|
||||
stopSpecOnExpectationFailure: false
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects a single call that sets stopSpecOnExpectationFailure and oneFailurePerSpec to different values', function() {
|
||||
spyOn(env, 'deprecated');
|
||||
expect(function() {
|
||||
env.configure({
|
||||
oneFailurePerSpec: true,
|
||||
stopSpecOnExpectationFailure: false
|
||||
});
|
||||
}).toThrowError(
|
||||
'stopSpecOnExpectationFailure and oneFailurePerSpec are ' +
|
||||
"aliases for each other. Don't set oneFailurePerSpec if you also set " +
|
||||
'stopSpecOnExpectationFailure.'
|
||||
);
|
||||
});
|
||||
|
||||
it('deprecates the oneFailurePerSpec config property', function() {
|
||||
spyOn(env, 'deprecated');
|
||||
env.configure({ oneFailurePerSpec: true });
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'The `oneFailurePerSpec` config property is deprecated and will be ' +
|
||||
'removed in a future version of Jasmine. Please use ' +
|
||||
'`stopSpecOnExpectationFailure` instead.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
});
|
||||
|
||||
describe('promise library', function() {
|
||||
it('can be configured without a custom library', function() {
|
||||
env.configure({});
|
||||
@@ -67,11 +399,17 @@ describe('Env', function() {
|
||||
});
|
||||
|
||||
it('can be configured with a custom library', function() {
|
||||
spyOn(env, 'deprecated');
|
||||
var myLibrary = {
|
||||
resolve: jasmine.createSpy(),
|
||||
reject: jasmine.createSpy()
|
||||
};
|
||||
env.configure({ Promise: myLibrary });
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'The `Promise` config property is deprecated. Future versions of ' +
|
||||
'Jasmine will create native promises even if the `Promise` config ' +
|
||||
'property is set. Please remove it.'
|
||||
);
|
||||
});
|
||||
|
||||
it('cannot be configured with an invalid promise library', function() {
|
||||
@@ -141,11 +479,24 @@ describe('Env', function() {
|
||||
);
|
||||
|
||||
expect(function() {
|
||||
env.describe('fn arg', function() {});
|
||||
env.describe('fn arg', function() {
|
||||
env.it('has a spec', function() {});
|
||||
});
|
||||
}).not.toThrowError(
|
||||
'describe expects a function argument; received [object Function]'
|
||||
);
|
||||
});
|
||||
|
||||
it('logs a deprecation when it has no children', function() {
|
||||
spyOn(env, 'deprecated');
|
||||
env.describe('no children', function() {});
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'describe with no children' +
|
||||
' (describe() or it()) is deprecated and will be removed in a future ' +
|
||||
'version of Jasmine. Please either remove the describe or add ' +
|
||||
'children to it.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#it', function() {
|
||||
@@ -169,12 +520,30 @@ describe('Env', function() {
|
||||
env.it('async', jasmine.getEnv().makeAsyncAwaitFunction());
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('throws an error when the timeout value is too large for setTimeout', function() {
|
||||
expect(function() {
|
||||
env.it('huge timeout', function() {}, 2147483648);
|
||||
}).toThrowError('Timeout value cannot be greater than 2147483647');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#xit', function() {
|
||||
it('calls spec.exclude with "Temporarily disabled with xit"', function() {
|
||||
var excludeSpy = jasmine.createSpy();
|
||||
spyOn(env, 'it_').and.returnValue({
|
||||
exclude: excludeSpy
|
||||
});
|
||||
env.xit('foo', function() {});
|
||||
expect(excludeSpy).toHaveBeenCalledWith('Temporarily disabled with xit');
|
||||
});
|
||||
|
||||
it('calls spec.pend with "Temporarily disabled with xit"', function() {
|
||||
var pendSpy = jasmine.createSpy();
|
||||
spyOn(env, 'it').and.returnValue({
|
||||
var realExclude = jasmineUnderTest.Spec.prototype.exclude;
|
||||
|
||||
spyOn(env, 'it_').and.returnValue({
|
||||
exclude: realExclude,
|
||||
pend: pendSpy
|
||||
});
|
||||
env.xit('foo', function() {});
|
||||
@@ -211,6 +580,12 @@ describe('Env', function() {
|
||||
/fit expects a function argument; received \[object (Undefined|DOMWindow|Object)\]/
|
||||
);
|
||||
});
|
||||
|
||||
it('throws an error when the timeout value is too large for setTimeout', function() {
|
||||
expect(function() {
|
||||
env.fit('huge timeout', function() {}, 2147483648);
|
||||
}).toThrowError('Timeout value cannot be greater than 2147483647');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#beforeEach', function() {
|
||||
@@ -228,6 +603,12 @@ describe('Env', function() {
|
||||
env.beforeEach(jasmine.getEnv().makeAsyncAwaitFunction());
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('throws an error when the timeout value is too large for setTimeout', function() {
|
||||
expect(function() {
|
||||
env.beforeEach(function() {}, 2147483648);
|
||||
}).toThrowError('Timeout value cannot be greater than 2147483647');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#beforeAll', function() {
|
||||
@@ -245,6 +626,12 @@ describe('Env', function() {
|
||||
env.beforeAll(jasmine.getEnv().makeAsyncAwaitFunction());
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('throws an error when the timeout value is too large for setTimeout', function() {
|
||||
expect(function() {
|
||||
env.beforeAll(function() {}, 2147483648);
|
||||
}).toThrowError('Timeout value cannot be greater than 2147483647');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#afterEach', function() {
|
||||
@@ -262,6 +649,12 @@ describe('Env', function() {
|
||||
env.afterEach(jasmine.getEnv().makeAsyncAwaitFunction());
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('throws an error when the timeout value is too large for setTimeout', function() {
|
||||
expect(function() {
|
||||
env.afterEach(function() {}, 2147483648);
|
||||
}).toThrowError('Timeout value cannot be greater than 2147483647');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#afterAll', function() {
|
||||
@@ -279,6 +672,12 @@ describe('Env', function() {
|
||||
env.afterAll(jasmine.getEnv().makeAsyncAwaitFunction());
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('throws an error when the timeout value is too large for setTimeout', function() {
|
||||
expect(function() {
|
||||
env.afterAll(function() {}, 2147483648);
|
||||
}).toThrowError('Timeout value cannot be greater than 2147483647');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when not constructed with suppressLoadErrors: true', function() {
|
||||
@@ -378,4 +777,90 @@ describe('Env', function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("deprecates access to 'this' in describes", function() {
|
||||
jasmine.getEnv().requireProxy();
|
||||
var msg =
|
||||
"Access to 'this' in describe functions (and in arrow " +
|
||||
'functions inside describe functions) is deprecated.',
|
||||
ran = false;
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
env.describe('a suite', function() {
|
||||
expect(this.description).toEqual('a suite');
|
||||
expect(env.deprecated).toHaveBeenCalledWith(msg);
|
||||
env.deprecated.calls.reset();
|
||||
|
||||
this.foo = 1;
|
||||
expect(env.deprecated).toHaveBeenCalledWith(msg);
|
||||
expect(this.foo).toEqual(1);
|
||||
env.deprecated.calls.reset();
|
||||
|
||||
expect(this.getFullName()).toEqual('a suite');
|
||||
expect(env.deprecated).toHaveBeenCalledWith(msg);
|
||||
env.deprecated.calls.reset();
|
||||
|
||||
env.it('has a spec');
|
||||
ran = true;
|
||||
});
|
||||
|
||||
expect(ran).toBeTrue();
|
||||
});
|
||||
|
||||
// TODO: Remove this in the next major version. Suites were never meant to be
|
||||
// exposed via describe 'this' in >= 2.0, and user code should not rely on it.
|
||||
// This spec is just here to make sure we don't break user code that *does*
|
||||
// rely on it in older browsers (without Proxy) while deprecating it.
|
||||
it("sets 'this' to the Suite in describes", function() {
|
||||
var suiteThis;
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
env.describe('a suite', function() {
|
||||
suiteThis = this;
|
||||
env.it('has a spec');
|
||||
});
|
||||
|
||||
expect(suiteThis).toBeInstanceOf(jasmineUnderTest.Suite);
|
||||
});
|
||||
|
||||
describe('#execute', function() {
|
||||
it('returns a promise when the environment supports promises', function() {
|
||||
jasmine.getEnv().requirePromises();
|
||||
expect(env.execute()).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
it('returns a promise when a custom promise constructor is provided', function() {
|
||||
function CustomPromise() {}
|
||||
CustomPromise.resolve = function() {};
|
||||
CustomPromise.reject = function() {};
|
||||
|
||||
spyOn(env, 'deprecated');
|
||||
env.configure({ Promise: CustomPromise });
|
||||
expect(env.execute()).toBeInstanceOf(CustomPromise);
|
||||
});
|
||||
|
||||
it('returns undefined when promises are unavailable', function() {
|
||||
jasmine.getEnv().requireNoPromises();
|
||||
expect(env.execute()).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should reset the topSuite when run twice', function() {
|
||||
jasmine.getEnv().requirePromises();
|
||||
spyOn(jasmineUnderTest.Suite.prototype, 'reset');
|
||||
return env
|
||||
.execute() // 1
|
||||
.then(function() {
|
||||
return env.execute(); // 2
|
||||
})
|
||||
.then(function() {
|
||||
var id;
|
||||
expect(
|
||||
jasmineUnderTest.Suite.prototype.reset
|
||||
).toHaveBeenCalledOnceWith();
|
||||
id = jasmineUnderTest.Suite.prototype.reset.calls.thisFor(0).id;
|
||||
expect(id).toBeTruthy();
|
||||
expect(id).toEqual(env.topSuite().id);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -33,7 +33,11 @@ describe('Exceptions:', function() {
|
||||
});
|
||||
|
||||
it('should handle exceptions thrown directly in top-level describe blocks and continue', function(done) {
|
||||
var secondDescribe = jasmine.createSpy('second describe');
|
||||
var secondDescribe = jasmine
|
||||
.createSpy('second describe')
|
||||
.and.callFake(function() {
|
||||
env.it('has a test', function() {});
|
||||
});
|
||||
env.describe('a suite that throws an exception', function() {
|
||||
env.it('is a test that should pass', function() {
|
||||
this.expect(true).toEqual(true);
|
||||
|
||||
@@ -40,6 +40,38 @@ describe('Expectation', function() {
|
||||
matchersUtil = {
|
||||
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
expectation;
|
||||
|
||||
expectation = jasmineUnderTest.Expectation.factory({
|
||||
matchersUtil: matchersUtil,
|
||||
customMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
});
|
||||
|
||||
expectation.toFoo('hello');
|
||||
|
||||
expect(matcherFactory).toHaveBeenCalledWith(matchersUtil);
|
||||
});
|
||||
|
||||
// TODO: remove this in the next major release
|
||||
it('passes custom equality testers when the matcher factory takes two arguments', function() {
|
||||
var fakeCompare = function() {
|
||||
return { pass: true };
|
||||
},
|
||||
matcherFactory = function(matchersUtil, customTesters) {
|
||||
return { compare: fakeCompare };
|
||||
},
|
||||
matcherFactorySpy = jasmine
|
||||
.createSpy('matcher', matcherFactory)
|
||||
.and.callThrough(),
|
||||
matchers = {
|
||||
toFoo: matcherFactorySpy
|
||||
},
|
||||
matchersUtil = {
|
||||
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
|
||||
},
|
||||
customEqualityTesters = ['a'],
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
expectation;
|
||||
@@ -54,7 +86,7 @@ describe('Expectation', function() {
|
||||
|
||||
expectation.toFoo('hello');
|
||||
|
||||
expect(matcherFactory).toHaveBeenCalledWith(
|
||||
expect(matcherFactorySpy).toHaveBeenCalledWith(
|
||||
matchersUtil,
|
||||
customEqualityTesters
|
||||
);
|
||||
|
||||
@@ -122,7 +122,7 @@ describe('GlobalErrors', function() {
|
||||
errors.uninstall();
|
||||
});
|
||||
|
||||
it('reports uncaughtException in node.js', function() {
|
||||
it('reports uncaught exceptions in node.js', function() {
|
||||
var fakeGlobal = {
|
||||
process: {
|
||||
on: jasmine.createSpy('process.on'),
|
||||
@@ -170,52 +170,118 @@ describe('GlobalErrors', function() {
|
||||
);
|
||||
});
|
||||
|
||||
it('reports unhandledRejection in node.js', function() {
|
||||
var fakeGlobal = {
|
||||
process: {
|
||||
on: jasmine.createSpy('process.on'),
|
||||
removeListener: jasmine.createSpy('process.removeListener'),
|
||||
listeners: jasmine
|
||||
.createSpy('process.listeners')
|
||||
.and.returnValue(['foo']),
|
||||
removeAllListeners: jasmine.createSpy('process.removeAllListeners')
|
||||
}
|
||||
},
|
||||
handler = jasmine.createSpy('errorHandler'),
|
||||
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
||||
describe('Reporting unhandled promise rejections in node.js', function() {
|
||||
it('reports rejections with `Error` reasons', function() {
|
||||
var fakeGlobal = {
|
||||
process: {
|
||||
on: jasmine.createSpy('process.on'),
|
||||
removeListener: jasmine.createSpy('process.removeListener'),
|
||||
listeners: jasmine
|
||||
.createSpy('process.listeners')
|
||||
.and.returnValue(['foo']),
|
||||
removeAllListeners: jasmine.createSpy('process.removeAllListeners')
|
||||
}
|
||||
},
|
||||
handler = jasmine.createSpy('errorHandler'),
|
||||
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
||||
|
||||
errors.install();
|
||||
expect(fakeGlobal.process.on).toHaveBeenCalledWith(
|
||||
'unhandledRejection',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
expect(fakeGlobal.process.listeners).toHaveBeenCalledWith(
|
||||
'unhandledRejection'
|
||||
);
|
||||
expect(fakeGlobal.process.removeAllListeners).toHaveBeenCalledWith(
|
||||
'unhandledRejection'
|
||||
);
|
||||
errors.install();
|
||||
expect(fakeGlobal.process.on).toHaveBeenCalledWith(
|
||||
'unhandledRejection',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
expect(fakeGlobal.process.listeners).toHaveBeenCalledWith(
|
||||
'unhandledRejection'
|
||||
);
|
||||
expect(fakeGlobal.process.removeAllListeners).toHaveBeenCalledWith(
|
||||
'unhandledRejection'
|
||||
);
|
||||
|
||||
errors.pushListener(handler);
|
||||
errors.pushListener(handler);
|
||||
|
||||
var addedListener = fakeGlobal.process.on.calls.argsFor(1)[1];
|
||||
addedListener(new Error('bar'));
|
||||
var addedListener = fakeGlobal.process.on.calls.argsFor(1)[1];
|
||||
addedListener(new Error('bar'));
|
||||
|
||||
expect(handler).toHaveBeenCalledWith(new Error('bar'));
|
||||
expect(handler.calls.argsFor(0)[0].jasmineMessage).toBe(
|
||||
'Unhandled promise rejection: Error: bar'
|
||||
);
|
||||
expect(handler).toHaveBeenCalledWith(new Error('bar'));
|
||||
expect(handler.calls.argsFor(0)[0].jasmineMessage).toBe(
|
||||
'Unhandled promise rejection: Error: bar'
|
||||
);
|
||||
|
||||
errors.uninstall();
|
||||
errors.uninstall();
|
||||
|
||||
expect(fakeGlobal.process.removeListener).toHaveBeenCalledWith(
|
||||
'unhandledRejection',
|
||||
addedListener
|
||||
);
|
||||
expect(fakeGlobal.process.on).toHaveBeenCalledWith(
|
||||
'unhandledRejection',
|
||||
'foo'
|
||||
);
|
||||
expect(fakeGlobal.process.removeListener).toHaveBeenCalledWith(
|
||||
'unhandledRejection',
|
||||
addedListener
|
||||
);
|
||||
expect(fakeGlobal.process.on).toHaveBeenCalledWith(
|
||||
'unhandledRejection',
|
||||
'foo'
|
||||
);
|
||||
});
|
||||
|
||||
it('reports rejections with non-`Error` reasons', function() {
|
||||
var fakeGlobal = {
|
||||
process: {
|
||||
on: jasmine.createSpy('process.on'),
|
||||
removeListener: function() {},
|
||||
listeners: function() {
|
||||
return [];
|
||||
},
|
||||
removeAllListeners: function() {}
|
||||
}
|
||||
},
|
||||
handler = jasmine.createSpy('errorHandler'),
|
||||
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
||||
|
||||
errors.install();
|
||||
errors.pushListener(handler);
|
||||
|
||||
expect(fakeGlobal.process.on.calls.argsFor(1)[0]).toEqual(
|
||||
'unhandledRejection'
|
||||
);
|
||||
var addedListener = fakeGlobal.process.on.calls.argsFor(1)[1];
|
||||
addedListener(17);
|
||||
|
||||
expect(handler).toHaveBeenCalledWith(
|
||||
new Error(
|
||||
'Unhandled promise rejection: 17\n' +
|
||||
'(Tip: to get a useful stack trace, use ' +
|
||||
'Promise.reject(new Error(...)) instead of Promise.reject(...).)'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('reports rejections with no reason provided', function() {
|
||||
var fakeGlobal = {
|
||||
process: {
|
||||
on: jasmine.createSpy('process.on'),
|
||||
removeListener: function() {},
|
||||
listeners: function() {
|
||||
return [];
|
||||
},
|
||||
removeAllListeners: function() {}
|
||||
}
|
||||
},
|
||||
handler = jasmine.createSpy('errorHandler'),
|
||||
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
||||
|
||||
errors.install();
|
||||
errors.pushListener(handler);
|
||||
|
||||
expect(fakeGlobal.process.on.calls.argsFor(1)[0]).toEqual(
|
||||
'unhandledRejection'
|
||||
);
|
||||
var addedListener = fakeGlobal.process.on.calls.argsFor(1)[1];
|
||||
addedListener(undefined);
|
||||
|
||||
expect(handler).toHaveBeenCalledWith(
|
||||
new Error(
|
||||
'Unhandled promise rejection with no error or message\n' +
|
||||
'(Tip: to get a useful stack trace, use ' +
|
||||
'Promise.reject(new Error(...)) instead of Promise.reject().)'
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Reporting unhandled promise rejections in the browser', function() {
|
||||
|
||||
@@ -149,31 +149,111 @@ describe('QueueRunner', function() {
|
||||
expect(queueableFn2.fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('explicitly fails an async function when next is called with an Error and moves to the next function', function() {
|
||||
var err = new Error('foo'),
|
||||
queueableFn1 = {
|
||||
fn: function(done) {
|
||||
setTimeout(function() {
|
||||
done(err);
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
||||
failFn = jasmine.createSpy('fail'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2],
|
||||
fail: failFn
|
||||
describe('When next is called with an argument', function() {
|
||||
describe('that is an Error', function() {
|
||||
it('explicitly fails and moves to the next function', function() {
|
||||
var err = new Error('foo'),
|
||||
queueableFn1 = {
|
||||
fn: function(done) {
|
||||
setTimeout(function() {
|
||||
done(err);
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
||||
failFn = jasmine.createSpy('fail'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2],
|
||||
fail: failFn
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
|
||||
expect(failFn).not.toHaveBeenCalled();
|
||||
expect(queueableFn2.fn).not.toHaveBeenCalled();
|
||||
|
||||
jasmine.clock().tick(100);
|
||||
|
||||
expect(failFn).toHaveBeenCalledWith(err);
|
||||
expect(queueableFn2.fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
it('does not log a deprecation', function() {
|
||||
var err = new Error('foo'),
|
||||
queueableFn1 = {
|
||||
fn: function(done) {
|
||||
setTimeout(function() {
|
||||
done(err);
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
deprecated = jasmine.createSpy('deprecated'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1],
|
||||
deprecated: deprecated
|
||||
});
|
||||
|
||||
expect(failFn).not.toHaveBeenCalled();
|
||||
expect(queueableFn2.fn).not.toHaveBeenCalled();
|
||||
queueRunner.execute();
|
||||
|
||||
jasmine.clock().tick(100);
|
||||
jasmine.clock().tick(100);
|
||||
|
||||
expect(failFn).toHaveBeenCalledWith(err);
|
||||
expect(queueableFn2.fn).toHaveBeenCalled();
|
||||
expect(deprecated).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('that is not an Error', function() {
|
||||
it('logs a deprecation', function() {
|
||||
var queueableFn1 = {
|
||||
fn: function(done) {
|
||||
setTimeout(function() {
|
||||
done('not an Error');
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
deprecated = jasmine.createSpy('deprecated'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1],
|
||||
deprecated: deprecated
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
|
||||
jasmine.clock().tick(100);
|
||||
|
||||
expect(deprecated).toHaveBeenCalledWith(
|
||||
'Any argument passed to a done callback will be treated as an ' +
|
||||
'error in a future release. Call the done callback without ' +
|
||||
"arguments if you don't want to trigger a spec failure."
|
||||
);
|
||||
});
|
||||
|
||||
it('moves to the next function without failing', function() {
|
||||
var queueableFn1 = {
|
||||
fn: function(done) {
|
||||
setTimeout(function() {
|
||||
done('not an Error');
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
||||
failFn = jasmine.createSpy('fail'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2],
|
||||
fail: failFn,
|
||||
deprecated: function() {}
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
|
||||
expect(failFn).not.toHaveBeenCalled();
|
||||
expect(queueableFn2.fn).not.toHaveBeenCalled();
|
||||
|
||||
jasmine.clock().tick(100);
|
||||
|
||||
expect(failFn).not.toHaveBeenCalled();
|
||||
expect(queueableFn2.fn).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('does not cause an explicit fail if execution is being stopped', function() {
|
||||
@@ -225,6 +305,32 @@ describe('QueueRunner', function() {
|
||||
expect(onComplete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not call onMultipleDone if an asynchrnous function completes after timing out', function() {
|
||||
var timeout = 3,
|
||||
queueableFn = {
|
||||
fn: function(done) {
|
||||
queueableFnDone = done;
|
||||
},
|
||||
type: 'queueable',
|
||||
timeout: timeout
|
||||
},
|
||||
onComplete = jasmine.createSpy('onComplete'),
|
||||
onMultipleDone = jasmine.createSpy('onMultipleDone'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
onComplete: onComplete,
|
||||
onMultipleDone: onMultipleDone
|
||||
}),
|
||||
queueableFnDone;
|
||||
|
||||
queueRunner.execute();
|
||||
jasmine.clock().tick(timeout);
|
||||
queueableFnDone();
|
||||
|
||||
expect(onComplete).toHaveBeenCalled();
|
||||
expect(onMultipleDone).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('by default does not set a timeout for asynchronous functions', function() {
|
||||
var beforeFn = { fn: function(done) {} },
|
||||
queueableFn = { fn: jasmine.createSpy('fn') },
|
||||
@@ -300,13 +406,16 @@ describe('QueueRunner', function() {
|
||||
}
|
||||
},
|
||||
nextQueueableFn = { fn: jasmine.createSpy('nextFn') },
|
||||
onMultipleDone = jasmine.createSpy('onMultipleDone'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn, nextQueueableFn]
|
||||
queueableFns: [queueableFn, nextQueueableFn],
|
||||
onMultipleDone: onMultipleDone
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
jasmine.clock().tick(1);
|
||||
expect(nextQueueableFn.fn.calls.count()).toEqual(1);
|
||||
expect(onMultipleDone).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not move to the next spec if done is called after an exception has ended the spec', function() {
|
||||
@@ -317,13 +426,17 @@ describe('QueueRunner', function() {
|
||||
}
|
||||
},
|
||||
nextQueueableFn = { fn: jasmine.createSpy('nextFn') },
|
||||
deprecated = jasmine.createSpy('deprecated'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
deprecated: deprecated,
|
||||
queueableFns: [queueableFn, nextQueueableFn]
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
jasmine.clock().tick(1);
|
||||
expect(nextQueueableFn.fn.calls.count()).toEqual(1);
|
||||
// Don't issue a deprecation. The error already tells the user that
|
||||
// something went wrong.
|
||||
expect(deprecated).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return a null when you call done', function() {
|
||||
@@ -523,8 +636,7 @@ describe('QueueRunner', function() {
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
deprecated: deprecated
|
||||
}),
|
||||
env = jasmineUnderTest.getEnv();
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
|
||||
@@ -533,7 +645,8 @@ describe('QueueRunner', function() {
|
||||
'before/it/after function took a done callback but also returned a ' +
|
||||
'promise. This is not supported and will stop working in the future. ' +
|
||||
'Either remove the done callback (recommended) or change the function ' +
|
||||
'to not return a promise.'
|
||||
'to not return a promise.',
|
||||
{ omitStackTrace: true }
|
||||
);
|
||||
});
|
||||
|
||||
@@ -553,7 +666,8 @@ describe('QueueRunner', function() {
|
||||
'before/it/after function was defined with the async keyword but ' +
|
||||
'also took a done callback. This is not supported and will stop ' +
|
||||
'working in the future. Either remove the done callback ' +
|
||||
'(recommended) or remove the async keyword.'
|
||||
'(recommended) or remove the async keyword.',
|
||||
{ omitStackTrace: true }
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -669,9 +783,13 @@ describe('QueueRunner', function() {
|
||||
jasmine.clock().uninstall();
|
||||
});
|
||||
|
||||
it('skips to cleanup functions on the first exception', function() {
|
||||
it('skips to cleanup functions once the fn completes after an unhandled exception', function() {
|
||||
var errorListeners = [],
|
||||
queueableFn = { fn: function(done) {} },
|
||||
queueableFn = {
|
||||
fn: function(done) {
|
||||
queueableFnDone = done;
|
||||
}
|
||||
},
|
||||
nextQueueableFn = { fn: jasmine.createSpy('nextFunction') },
|
||||
cleanupFn = { fn: jasmine.createSpy('cleanup') },
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
@@ -686,10 +804,13 @@ describe('QueueRunner', function() {
|
||||
queueableFns: [queueableFn, nextQueueableFn],
|
||||
cleanupFns: [cleanupFn],
|
||||
completeOnFirstError: true
|
||||
});
|
||||
}),
|
||||
queueableFnDone;
|
||||
|
||||
queueRunner.execute();
|
||||
errorListeners[errorListeners.length - 1](new Error('error'));
|
||||
expect(cleanupFn.fn).not.toHaveBeenCalled();
|
||||
queueableFnDone();
|
||||
expect(nextQueueableFn.fn).not.toHaveBeenCalled();
|
||||
expect(cleanupFn.fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -516,4 +516,33 @@ describe('Spec', function() {
|
||||
args.cleanupFns[0].fn();
|
||||
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([]);
|
||||
});
|
||||
|
||||
it('passes an onMultipleDone that logs a deprecation', function() {
|
||||
var queueRunnerFactory = jasmine.createSpy('queueRunnerFactory'),
|
||||
deprecated = jasmine.createSpy('depredated'),
|
||||
spec = new jasmineUnderTest.Spec({
|
||||
deprecated: deprecated,
|
||||
queueableFn: { fn: function() {} },
|
||||
queueRunnerFactory: queueRunnerFactory,
|
||||
getSpecName: function() {
|
||||
return 'a spec';
|
||||
}
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
|
||||
expect(queueRunnerFactory).toHaveBeenCalled();
|
||||
queueRunnerFactory.calls.argsFor(0)[0].onMultipleDone();
|
||||
|
||||
expect(deprecated).toHaveBeenCalledWith(
|
||||
"An asynchronous function called its 'done' " +
|
||||
'callback more than once. This is a bug in the spec, beforeAll, ' +
|
||||
'beforeEach, afterAll, or afterEach function in question. This will ' +
|
||||
'be treated as an error in a future version. See' +
|
||||
'<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> ' +
|
||||
'for more information.\n' +
|
||||
'(in spec: a spec)',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -407,6 +407,123 @@ describe('SpyRegistry', function() {
|
||||
expect(subject.toString).not.toBe('I am a spy');
|
||||
expect(subject.hasOwnProperty).not.toBe('I am a spy');
|
||||
});
|
||||
describe('when includeNonEnumerable is true', function() {
|
||||
it('does not override Object.prototype methods', function() {
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
});
|
||||
var subject = {
|
||||
spied1: function() {}
|
||||
};
|
||||
|
||||
spyRegistry.spyOnAllFunctions(subject, true);
|
||||
|
||||
expect(subject.spied1).toBe('I am a spy');
|
||||
expect(subject.toString).not.toBe('I am a spy');
|
||||
expect(subject.hasOwnProperty).not.toBe('I am a spy');
|
||||
});
|
||||
|
||||
it('overrides non-enumerable properties', function() {
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
});
|
||||
var subject = {
|
||||
spied1: function() {},
|
||||
spied2: function() {}
|
||||
};
|
||||
|
||||
Object.defineProperty(subject, 'spied2', {
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
spyRegistry.spyOnAllFunctions(subject, true);
|
||||
|
||||
expect(subject.spied1).toBe('I am a spy');
|
||||
expect(subject.spied2).toBe('I am a spy');
|
||||
});
|
||||
|
||||
it('should not spy on non-enumerable functions named constructor', function() {
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
});
|
||||
var subject = {
|
||||
constructor: function() {}
|
||||
};
|
||||
|
||||
Object.defineProperty(subject, 'constructor', {
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
spyRegistry.spyOnAllFunctions(subject, true);
|
||||
|
||||
expect(subject.constructor).not.toBe('I am a spy');
|
||||
});
|
||||
|
||||
it('should spy on enumerable functions named constructor', function() {
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
});
|
||||
var subject = {
|
||||
constructor: function() {}
|
||||
};
|
||||
|
||||
spyRegistry.spyOnAllFunctions(subject, true);
|
||||
|
||||
expect(subject.constructor).toBe('I am a spy');
|
||||
});
|
||||
|
||||
it('should not throw an exception if we try and access strict mode restricted properties', function() {
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
});
|
||||
var subject = function() {};
|
||||
var fn = function() {
|
||||
spyRegistry.spyOnAllFunctions(subject, true);
|
||||
};
|
||||
|
||||
expect(fn).not.toThrow();
|
||||
});
|
||||
|
||||
it('should not spy on properties which are more permissable further up the prototype chain', function() {
|
||||
var spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
});
|
||||
var subjectParent = Object.defineProperty({}, 'sharedProp', {
|
||||
value: function() {},
|
||||
writable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
var subject = Object.create(subjectParent);
|
||||
|
||||
Object.defineProperty(subject, 'sharedProp', {
|
||||
value: function() {}
|
||||
});
|
||||
|
||||
var fn = function() {
|
||||
spyRegistry.spyOnAllFunctions(subject, true);
|
||||
};
|
||||
|
||||
expect(fn).not.toThrow();
|
||||
expect(subject).not.toBe('I am a spy');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#clearSpies', function() {
|
||||
|
||||
@@ -213,7 +213,7 @@ describe('Spies', function() {
|
||||
).toBe(1);
|
||||
});
|
||||
|
||||
it('allows base name to be ommitted when assigning methods and properties', function() {
|
||||
it('allows base name to be omitted when assigning methods and properties', function() {
|
||||
var spyObj = env.createSpyObj({ m: 3 }, { p: 4 });
|
||||
|
||||
expect(spyObj.m()).toEqual(3);
|
||||
@@ -271,6 +271,7 @@ describe('Spies', function() {
|
||||
reject: jasmine.createSpy()
|
||||
};
|
||||
customPromise.resolve.and.returnValue('resolved');
|
||||
spyOn(env, 'deprecated');
|
||||
env.configure({ Promise: customPromise });
|
||||
|
||||
var spy = env.createSpy('foo').and.resolveTo(42);
|
||||
|
||||
@@ -90,7 +90,7 @@ describe('SpyStrategy', function() {
|
||||
|
||||
expect(function() {
|
||||
spyStrategy.exec();
|
||||
}).toThrow({ code: 'ESRCH' });
|
||||
}).toThrow(jasmine.objectContaining({ code: 'ESRCH' }));
|
||||
expect(originalFn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
@@ -142,4 +142,130 @@ describe('Suite', function() {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('attr.autoCleanClosures', function() {
|
||||
function arrangeSuite(attrs) {
|
||||
var suite = new jasmineUnderTest.Suite(attrs);
|
||||
suite.beforeAll(function() {});
|
||||
suite.beforeEach(function() {});
|
||||
suite.afterEach(function() {});
|
||||
suite.afterAll(function() {});
|
||||
return suite;
|
||||
}
|
||||
|
||||
it('should clean closures when "attr.autoCleanClosures" is missing', function() {
|
||||
var suite = arrangeSuite({});
|
||||
suite.cleanupBeforeAfter();
|
||||
expect(suite.beforeAllFns[0].fn).toBe(null);
|
||||
expect(suite.beforeFns[0].fn).toBe(null);
|
||||
expect(suite.afterFns[0].fn).toBe(null);
|
||||
expect(suite.afterAllFns[0].fn).toBe(null);
|
||||
});
|
||||
|
||||
it('should clean closures when "attr.autoCleanClosures" is true', function() {
|
||||
var suite = arrangeSuite({ autoCleanClosures: true });
|
||||
suite.cleanupBeforeAfter();
|
||||
expect(suite.beforeAllFns[0].fn).toBe(null);
|
||||
expect(suite.beforeFns[0].fn).toBe(null);
|
||||
expect(suite.afterFns[0].fn).toBe(null);
|
||||
expect(suite.afterAllFns[0].fn).toBe(null);
|
||||
});
|
||||
|
||||
it('should NOT clean closures when "attr.autoCleanClosures" is false', function() {
|
||||
var suite = arrangeSuite({ autoCleanClosures: false });
|
||||
suite.cleanupBeforeAfter();
|
||||
expect(suite.beforeAllFns[0].fn).not.toBe(null);
|
||||
expect(suite.beforeFns[0].fn).not.toBe(null);
|
||||
expect(suite.afterFns[0].fn).not.toBe(null);
|
||||
expect(suite.afterAllFns[0].fn).not.toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#reset', function() {
|
||||
it('should reset the "pending" status', function() {
|
||||
var suite = new jasmineUnderTest.Suite({});
|
||||
suite.pend();
|
||||
suite.reset();
|
||||
expect(suite.getResult().status).toBe('passed');
|
||||
});
|
||||
|
||||
it('should not reset the "pending" status when the suite was excluded', function() {
|
||||
var suite = new jasmineUnderTest.Suite({});
|
||||
suite.exclude();
|
||||
suite.reset();
|
||||
expect(suite.getResult().status).toBe('pending');
|
||||
});
|
||||
|
||||
it('should also reset the children', function() {
|
||||
var suite = new jasmineUnderTest.Suite({});
|
||||
var child1 = jasmine.createSpyObj(['reset']);
|
||||
var child2 = jasmine.createSpyObj(['reset']);
|
||||
suite.addChild(child1);
|
||||
suite.addChild(child2);
|
||||
|
||||
suite.reset();
|
||||
|
||||
expect(child1.reset).toHaveBeenCalled();
|
||||
expect(child2.reset).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should reset the failedExpectations', function() {
|
||||
var suite = new jasmineUnderTest.Suite({
|
||||
expectationResultFactory: function(error) {
|
||||
return error;
|
||||
}
|
||||
});
|
||||
suite.onException(new Error());
|
||||
|
||||
suite.reset();
|
||||
|
||||
var result = suite.getResult();
|
||||
expect(result.status).toBe('passed');
|
||||
expect(result.failedExpectations).toHaveSize(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#onMultipleDone', function() {
|
||||
it('logs a special deprecation when it is the top suite', function() {
|
||||
var env = jasmine.createSpyObj('env', ['deprecated']);
|
||||
var suite = new jasmineUnderTest.Suite({ env: env, parentSuite: null });
|
||||
|
||||
suite.onMultipleDone();
|
||||
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'A top-level beforeAll or afterAll function called its ' +
|
||||
"'done' callback more than once. This is a bug in the beforeAll " +
|
||||
'or afterAll function in question. This will be treated as an ' +
|
||||
'error in a future version. See' +
|
||||
'<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> ' +
|
||||
'for more information.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
});
|
||||
|
||||
it('logs a deprecation including the suite name when it is a normal suite', function() {
|
||||
var env = jasmine.createSpyObj('env', ['deprecated']);
|
||||
var suite = new jasmineUnderTest.Suite({
|
||||
env: env,
|
||||
description: 'the suite',
|
||||
parentSuite: {
|
||||
description: 'the parent suite',
|
||||
parentSuite: {}
|
||||
}
|
||||
});
|
||||
|
||||
suite.onMultipleDone();
|
||||
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
"An asynchronous function called its 'done' callback more than " +
|
||||
'once. This is a bug in the spec, beforeAll, beforeEach, afterAll, ' +
|
||||
'or afterEach function in question. This will be treated as an error ' +
|
||||
'in a future version. See' +
|
||||
'<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> ' +
|
||||
'for more information.\n' +
|
||||
'(in suite: the parent suite the suite)',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -291,7 +291,8 @@ describe('TreeProcessor', function() {
|
||||
onComplete: treeComplete,
|
||||
onException: jasmine.any(Function),
|
||||
userContext: { root: 'context' },
|
||||
queueableFns: [{ fn: jasmine.any(Function) }]
|
||||
queueableFns: [{ fn: jasmine.any(Function) }],
|
||||
onMultipleDone: null
|
||||
});
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn('foo');
|
||||
@@ -321,16 +322,19 @@ describe('TreeProcessor', function() {
|
||||
onComplete: treeComplete,
|
||||
onException: jasmine.any(Function),
|
||||
userContext: { root: 'context' },
|
||||
queueableFns: [{ fn: jasmine.any(Function) }]
|
||||
queueableFns: [{ fn: jasmine.any(Function) }],
|
||||
onMultipleDone: null
|
||||
});
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn(nodeDone);
|
||||
|
||||
expect(queueRunner).toHaveBeenCalledWith({
|
||||
onComplete: jasmine.any(Function),
|
||||
onMultipleDone: null,
|
||||
queueableFns: [{ fn: jasmine.any(Function) }],
|
||||
userContext: { node: 'context' },
|
||||
onException: jasmine.any(Function)
|
||||
onException: jasmine.any(Function),
|
||||
onMultipleDone: null
|
||||
});
|
||||
|
||||
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn('foo');
|
||||
|
||||
@@ -13,27 +13,54 @@ describe('asymmetricEqualityTesterArgCompatShim', function() {
|
||||
expect(shim.bar).toBe(matchersUtil.bar);
|
||||
});
|
||||
|
||||
it('provides all the properties of the customEqualityTesters', function() {
|
||||
it('provides and deprecates all the properties of the customEqualityTesters', function() {
|
||||
var customEqualityTesters = [function() {}, function() {}],
|
||||
shim = jasmineUnderTest.asymmetricEqualityTesterArgCompatShim(
|
||||
{},
|
||||
customEqualityTesters
|
||||
);
|
||||
),
|
||||
deprecated = spyOn(jasmineUnderTest.getEnv(), 'deprecated'),
|
||||
expectedMessage =
|
||||
'The second argument to asymmetricMatch is now a MatchersUtil. ' +
|
||||
'Using it as an array of custom equality testers is deprecated and will stop ' +
|
||||
'working in a future release. ' +
|
||||
'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#asymmetricMatch-cet> for details.';
|
||||
|
||||
expect(shim.length).toBe(2);
|
||||
expect(deprecated).toHaveBeenCalledWith(expectedMessage);
|
||||
deprecated.calls.reset();
|
||||
|
||||
expect(shim[0]).toBe(customEqualityTesters[0]);
|
||||
expect(deprecated).toHaveBeenCalledWith(expectedMessage);
|
||||
deprecated.calls.reset();
|
||||
|
||||
expect(shim[1]).toBe(customEqualityTesters[1]);
|
||||
expect(deprecated).toHaveBeenCalledWith(expectedMessage);
|
||||
});
|
||||
|
||||
it('provides all the properties of Array.prototype', function() {
|
||||
var shim = jasmineUnderTest.asymmetricEqualityTesterArgCompatShim({}, []);
|
||||
it('provides and deprecates all the properties of Array.prototype', function() {
|
||||
var shim = jasmineUnderTest.asymmetricEqualityTesterArgCompatShim({}, []),
|
||||
deprecated = spyOn(jasmineUnderTest.getEnv(), 'deprecated'),
|
||||
expectedMessage =
|
||||
'The second argument to asymmetricMatch is now a MatchersUtil. ' +
|
||||
'Using it as an array of custom equality testers is deprecated and will stop ' +
|
||||
'working in a future release. ' +
|
||||
'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#asymmetricMatch-cet> for details.';
|
||||
|
||||
expect(shim.filter).toBe(Array.prototype.filter);
|
||||
expect(deprecated).toHaveBeenCalledWith(expectedMessage);
|
||||
deprecated.calls.reset();
|
||||
|
||||
expect(shim.forEach).toBe(Array.prototype.forEach);
|
||||
expect(deprecated).toHaveBeenCalledWith(expectedMessage);
|
||||
deprecated.calls.reset();
|
||||
|
||||
expect(shim.map).toBe(Array.prototype.map);
|
||||
expect(deprecated).toHaveBeenCalledWith(expectedMessage);
|
||||
deprecated.calls.reset();
|
||||
});
|
||||
|
||||
it('provides properties of Array.prototype', function() {
|
||||
it('provides and deprecates properties of Array.prototype', function() {
|
||||
var keys = [
|
||||
'concat',
|
||||
'every',
|
||||
@@ -66,10 +93,10 @@ describe('asymmetricEqualityTesterArgCompatShim', function() {
|
||||
'flatMap',
|
||||
'includes',
|
||||
'keys',
|
||||
'toSource',
|
||||
'values'
|
||||
],
|
||||
shim = jasmineUnderTest.asymmetricEqualityTesterArgCompatShim({}, []),
|
||||
deprecated = spyOn(jasmineUnderTest.getEnv(), 'deprecated'),
|
||||
i,
|
||||
k;
|
||||
|
||||
@@ -82,6 +109,8 @@ describe('asymmetricEqualityTesterArgCompatShim', function() {
|
||||
expect(shim[k])
|
||||
.withContext(k)
|
||||
.toBe(Array.prototype[k]);
|
||||
expect(deprecated).toHaveBeenCalled();
|
||||
deprecated.calls.reset();
|
||||
}
|
||||
|
||||
// Properties that are present on only some supported runtimes
|
||||
@@ -92,10 +121,24 @@ describe('asymmetricEqualityTesterArgCompatShim', function() {
|
||||
expect(shim[k])
|
||||
.withContext(k)
|
||||
.toBe(Array.prototype[k]);
|
||||
expect(deprecated)
|
||||
.withContext(k)
|
||||
.toHaveBeenCalled();
|
||||
deprecated.calls.reset();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('does not deprecate properties of Object.prototype', function() {
|
||||
var shim = jasmineUnderTest.asymmetricEqualityTesterArgCompatShim({}, []),
|
||||
deprecated = spyOn(jasmineUnderTest.getEnv(), 'deprecated');
|
||||
|
||||
expect(shim.hasOwnProperty).toBe(Object.prototype.hasOwnProperty);
|
||||
expect(shim.isPrototypeOf).toBe(Object.prototype.isPrototypeOf);
|
||||
|
||||
expect(deprecated).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('When Array.prototype additions collide with MatchersUtil methods', function() {
|
||||
function keys() {
|
||||
return [
|
||||
@@ -137,4 +180,18 @@ describe('asymmetricEqualityTesterArgCompatShim', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('When the matchersUtil is already an asymmetricEqualityTesterArgCompatShim', function() {
|
||||
it('does not trigger any deprecations', function() {
|
||||
var shim1 = jasmineUnderTest.asymmetricEqualityTesterArgCompatShim(
|
||||
{},
|
||||
[]
|
||||
);
|
||||
spyOn(jasmineUnderTest.getEnv(), 'deprecated');
|
||||
|
||||
jasmineUnderTest.asymmetricEqualityTesterArgCompatShim(shim1, []);
|
||||
|
||||
expect(jasmineUnderTest.getEnv().deprecated).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -46,9 +46,7 @@ describe('Any', function() {
|
||||
});
|
||||
|
||||
it('matches a TypedArray', function() {
|
||||
jasmine.getEnv().requireFunctioningTypedArrays();
|
||||
|
||||
var any = new jasmineUnderTest.Any(Uint32Array); // eslint-disable-line compat/compat
|
||||
var any = new jasmineUnderTest.Any(Uint32Array);
|
||||
|
||||
expect(any.asymmetricMatch(new Uint32Array([]))).toBe(true); // eslint-disable-line compat/compat
|
||||
});
|
||||
|
||||
@@ -40,8 +40,6 @@ describe('Anything', function() {
|
||||
});
|
||||
|
||||
it('matches a TypedArray', function() {
|
||||
jasmine.getEnv().requireFunctioningTypedArrays();
|
||||
|
||||
var anything = new jasmineUnderTest.Anything();
|
||||
|
||||
expect(anything.asymmetricMatch(new Uint32Array([]))).toBe(true); // eslint-disable-line compat/compat
|
||||
|
||||
@@ -42,7 +42,6 @@ describe('Empty', function() {
|
||||
});
|
||||
|
||||
it('matches an empty typed array', function() {
|
||||
jasmine.getEnv().requireFunctioningTypedArrays();
|
||||
var empty = new jasmineUnderTest.Empty();
|
||||
|
||||
expect(empty.asymmetricMatch(new Int16Array())).toBe(true); // eslint-disable-line compat/compat
|
||||
|
||||
@@ -44,7 +44,6 @@ describe('NotEmpty', function() {
|
||||
});
|
||||
|
||||
it('matches a non empty typed array', function() {
|
||||
jasmine.getEnv().requireFunctioningTypedArrays();
|
||||
var notEmpty = new jasmineUnderTest.NotEmpty();
|
||||
|
||||
expect(notEmpty.asymmetricMatch(new Int16Array([1, 2, 3]))).toBe(true); // eslint-disable-line compat/compat
|
||||
|
||||
27
spec/core/asymmetric_equality/StringContainingSpec.js
Normal file
27
spec/core/asymmetric_equality/StringContainingSpec.js
Normal file
@@ -0,0 +1,27 @@
|
||||
describe('StringContaining', function() {
|
||||
it('searches for a provided substring when the expected is a String', function() {
|
||||
var matcher = new jasmineUnderTest.StringContaining('foo');
|
||||
|
||||
expect(matcher.asymmetricMatch('barfoobaz')).toBe(true);
|
||||
expect(matcher.asymmetricMatch('barbaz')).toBe(false);
|
||||
});
|
||||
|
||||
it('raises an Error when the expected is not a String', function() {
|
||||
expect(function() {
|
||||
new jasmineUnderTest.StringContaining(/foo/);
|
||||
}).toThrowError(/not a String/);
|
||||
});
|
||||
|
||||
it('fails when the actual is not a String', function() {
|
||||
var matcher = new jasmineUnderTest.StringContaining('x');
|
||||
expect(matcher.asymmetricMatch(['x'])).toBe(false);
|
||||
});
|
||||
|
||||
it("jasmineToString's itself", function() {
|
||||
var matching = new jasmineUnderTest.StringContaining('foo');
|
||||
|
||||
expect(matching.jasmineToString()).toEqual(
|
||||
'<jasmine.stringContaining("foo")>'
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -29,6 +29,43 @@ describe('base helpers', function() {
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
it('returns true for an Error subclass', function() {
|
||||
function MyError() {}
|
||||
MyError.prototype = new Error();
|
||||
expect(jasmineUnderTest.isError_(new MyError())).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for an un-thrown Error with no message in this environment', function() {
|
||||
expect(jasmineUnderTest.isError_(new Error())).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for an Error that originated from another frame', function() {
|
||||
var iframe, error;
|
||||
|
||||
if (typeof window === 'undefined') {
|
||||
pending('This test only runs in browsers.');
|
||||
}
|
||||
|
||||
iframe = document.createElement('iframe');
|
||||
iframe.style.display = 'none';
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
try {
|
||||
error = iframe.contentWindow.eval('new Error()');
|
||||
expect(jasmineUnderTest.isError_(error)).toBe(true);
|
||||
} finally {
|
||||
document.body.removeChild(iframe);
|
||||
}
|
||||
});
|
||||
|
||||
it('returns false for a falsy value', function() {
|
||||
expect(jasmineUnderTest.isError_(undefined)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false for a non-Error object', function() {
|
||||
expect(jasmineUnderTest.isError_({})).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isAsymmetricEqualityTester_', function() {
|
||||
@@ -75,4 +112,78 @@ describe('base helpers', function() {
|
||||
expect(jasmineUnderTest.isURL({})).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isPending_', function() {
|
||||
it('returns a promise that resolves to true when the promise is pending', function() {
|
||||
jasmine.getEnv().requirePromises();
|
||||
// eslint-disable-next-line compat/compat
|
||||
var promise = new Promise(function() {});
|
||||
return expectAsync(jasmineUnderTest.isPending_(promise)).toBeResolvedTo(
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it('returns a promise that resolves to false when the promise is resolved', function() {
|
||||
jasmine.getEnv().requirePromises();
|
||||
// eslint-disable-next-line compat/compat
|
||||
var promise = Promise.resolve();
|
||||
return expectAsync(jasmineUnderTest.isPending_(promise)).toBeResolvedTo(
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
it('returns a promise that resolves to false when the promise is rejected', function() {
|
||||
jasmine.getEnv().requirePromises();
|
||||
// eslint-disable-next-line compat/compat
|
||||
var promise = Promise.reject();
|
||||
return expectAsync(jasmineUnderTest.isPending_(promise)).toBeResolvedTo(
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('DEFAULT_TIMEOUT_INTERVAL setter', function() {
|
||||
var max = 2147483647;
|
||||
|
||||
beforeEach(function() {
|
||||
this.initialValue = jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL;
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = this.initialValue;
|
||||
});
|
||||
|
||||
it('accepts only values <= ' + max, function() {
|
||||
expect(function() {
|
||||
jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = max + 1;
|
||||
}).toThrowError(
|
||||
'jasmine.DEFAULT_TIMEOUT_INTERVAL cannot be greater than ' + max
|
||||
);
|
||||
|
||||
jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = max;
|
||||
expect(jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL).toEqual(max);
|
||||
});
|
||||
|
||||
it('is consistent with setTimeout in this environment', function(done) {
|
||||
var f1 = jasmine.createSpy('setTimeout callback for ' + max),
|
||||
f2 = jasmine.createSpy('setTimeout callback for ' + (max + 1)),
|
||||
id;
|
||||
|
||||
// Suppress printing of TimeoutOverflowWarning in node
|
||||
spyOn(console, 'error');
|
||||
|
||||
id = setTimeout(f1, max);
|
||||
setTimeout(function() {
|
||||
clearTimeout(id);
|
||||
expect(f1).not.toHaveBeenCalled();
|
||||
|
||||
id = setTimeout(f2, max + 1);
|
||||
setTimeout(function() {
|
||||
clearTimeout(id);
|
||||
expect(f2).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -231,6 +231,16 @@ describe('Asymmetric equality testers (Integration)', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('stringContaining', function() {
|
||||
verifyPasses(function(env) {
|
||||
env.expect('foo').toEqual(jasmineUnderTest.stringContaining('o'));
|
||||
});
|
||||
|
||||
verifyFails(function(env) {
|
||||
env.expect('bar').toEqual(jasmineUnderTest.stringContaining('o'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('truthy', function() {
|
||||
verifyPasses(function(env) {
|
||||
env.expect(true).toEqual(jasmineUnderTest.truthy());
|
||||
|
||||
@@ -91,26 +91,22 @@ describe('Custom Async Matchers (Integration)', function() {
|
||||
env.execute(null, done);
|
||||
});
|
||||
|
||||
// TODO: remove this in the next major release.
|
||||
it('passes the jasmine utility and current equality testers to the matcher factory', function(done) {
|
||||
it('passes the jasmine utility to the matcher factory', function(done) {
|
||||
jasmine.getEnv().requirePromises();
|
||||
|
||||
var matcherFactory = function() {
|
||||
var matcherFactory = function(util) {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({ pass: true });
|
||||
}
|
||||
};
|
||||
},
|
||||
matcherFactorySpy = jasmine
|
||||
.createSpy('matcherFactorySpy')
|
||||
.and.callFake(matcherFactory),
|
||||
customEqualityFn = function() {
|
||||
return true;
|
||||
};
|
||||
matcherFactorySpy = jasmine.createSpy(
|
||||
'matcherFactorySpy',
|
||||
matcherFactory
|
||||
);
|
||||
|
||||
env.it('spec with expectation', function() {
|
||||
env.addCustomEqualityTester(customEqualityFn);
|
||||
env.addAsyncMatchers({
|
||||
toBeReal: matcherFactorySpy
|
||||
});
|
||||
@@ -120,8 +116,7 @@ describe('Custom Async Matchers (Integration)', function() {
|
||||
|
||||
var specExpectations = function() {
|
||||
expect(matcherFactorySpy).toHaveBeenCalledWith(
|
||||
jasmine.any(jasmineUnderTest.MatchersUtil),
|
||||
[customEqualityFn]
|
||||
jasmine.any(jasmineUnderTest.MatchersUtil)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -129,6 +124,53 @@ describe('Custom Async Matchers (Integration)', function() {
|
||||
env.execute(null, done);
|
||||
});
|
||||
|
||||
// TODO: remove this in the next major release.
|
||||
describe('When a matcher factory takes at least two arguments', function() {
|
||||
it('passes the jasmine utility and current equality testers to the matcher factory', function(done) {
|
||||
jasmine.getEnv().requirePromises();
|
||||
|
||||
var matcherFactory = function(util, customTesters) {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({ pass: true });
|
||||
}
|
||||
};
|
||||
},
|
||||
matcherFactorySpy = jasmine.createSpy(
|
||||
'matcherFactorySpy',
|
||||
matcherFactory
|
||||
),
|
||||
customEqualityFn = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
env.it('spec with expectation', function() {
|
||||
env.addCustomEqualityTester(customEqualityFn);
|
||||
env.addAsyncMatchers({
|
||||
toBeReal: matcherFactorySpy
|
||||
});
|
||||
|
||||
return env.expectAsync(true).toBeReal();
|
||||
});
|
||||
|
||||
var specExpectations = function() {
|
||||
expect(matcherFactorySpy).toHaveBeenCalledWith(
|
||||
jasmine.any(jasmineUnderTest.MatchersUtil),
|
||||
[customEqualityFn]
|
||||
);
|
||||
};
|
||||
|
||||
spyOn(env, 'deprecated');
|
||||
env.addReporter({
|
||||
specDone: specExpectations,
|
||||
jasmineDone: function() {
|
||||
done();
|
||||
}
|
||||
});
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
|
||||
it('provides custom equality testers to the matcher factory via matchersUtil', function(done) {
|
||||
jasmine.getEnv().requirePromises();
|
||||
|
||||
@@ -164,4 +206,41 @@ describe('Custom Async Matchers (Integration)', function() {
|
||||
env.addReporter({ specDone: specExpectations });
|
||||
env.execute(null, done);
|
||||
});
|
||||
|
||||
it('logs a distinct deprecation for each matcher if the matcher factory takes two arguments', function(done) {
|
||||
var matcherFactory = function(matchersUtil, customEqualityTesters) {
|
||||
return { compare: function() {} };
|
||||
};
|
||||
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
env.beforeEach(function() {
|
||||
env.addAsyncMatchers({ toBeFoo: matcherFactory });
|
||||
env.addAsyncMatchers({ toBeBar: matcherFactory });
|
||||
});
|
||||
|
||||
env.it('a spec', function() {});
|
||||
env.it('another spec', function() {});
|
||||
|
||||
function jasmineDone() {
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(
|
||||
'The matcher factory for "toBeFoo" accepts custom equality testers, ' +
|
||||
'but this parameter will no longer be passed in a future release. ' +
|
||||
'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
|
||||
)
|
||||
);
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(
|
||||
'The matcher factory for "toBeBar" accepts custom equality testers, ' +
|
||||
'but this parameter will no longer be passed in a future release. ' +
|
||||
'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
|
||||
)
|
||||
);
|
||||
done();
|
||||
}
|
||||
|
||||
env.addReporter({ jasmineDone: jasmineDone });
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -111,6 +111,7 @@ describe('Custom Matchers (Integration)', function() {
|
||||
it('supports asymmetric equality testers that take a list of custom equality testers', function(done) {
|
||||
// TODO: remove this in the next major release.
|
||||
spyOn(jasmineUnderTest, 'getEnv').and.returnValue(env);
|
||||
spyOn(env, 'deprecated'); // suppress warnings
|
||||
|
||||
env.it('spec using custom asymmetric equality tester', function() {
|
||||
var customEqualityFn = function(a, b) {
|
||||
@@ -143,6 +144,8 @@ describe('Custom Matchers (Integration)', function() {
|
||||
});
|
||||
|
||||
it('displays an appropriate failure message if a custom equality matcher fails', function(done) {
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
env.it('spec using custom equality matcher', function() {
|
||||
var customEqualityFn = function(a, b) {
|
||||
// "foo" is not equal to anything
|
||||
@@ -244,9 +247,8 @@ describe('Custom Matchers (Integration)', function() {
|
||||
env.execute(null, done);
|
||||
});
|
||||
|
||||
// TODO: remove this in the next major release.
|
||||
it('passes the jasmine utility and current equality testers to the matcher factory', function(done) {
|
||||
var matcherFactory = function() {
|
||||
it('passes the jasmine utility to the matcher factory', function(done) {
|
||||
var matcherFactory = function(util) {
|
||||
return {
|
||||
compare: function() {
|
||||
return { pass: true };
|
||||
@@ -255,13 +257,9 @@ describe('Custom Matchers (Integration)', function() {
|
||||
},
|
||||
matcherFactorySpy = jasmine
|
||||
.createSpy('matcherFactorySpy')
|
||||
.and.callFake(matcherFactory),
|
||||
customEqualityFn = function() {
|
||||
return true;
|
||||
};
|
||||
.and.callFake(matcherFactory);
|
||||
|
||||
env.it('spec with expectation', function() {
|
||||
env.addCustomEqualityTester(customEqualityFn);
|
||||
env.addMatchers({
|
||||
toBeReal: matcherFactorySpy
|
||||
});
|
||||
@@ -271,8 +269,7 @@ describe('Custom Matchers (Integration)', function() {
|
||||
|
||||
var specExpectations = function() {
|
||||
expect(matcherFactorySpy).toHaveBeenCalledWith(
|
||||
jasmine.any(jasmineUnderTest.MatchersUtil),
|
||||
[customEqualityFn]
|
||||
jasmine.any(jasmineUnderTest.MatchersUtil)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -280,6 +277,52 @@ describe('Custom Matchers (Integration)', function() {
|
||||
env.execute(null, done);
|
||||
});
|
||||
|
||||
// TODO: remove this in the next major release.
|
||||
describe('When a matcher factory takes at least two arguments', function() {
|
||||
it('passes the jasmine utility and current equality testers to the matcher factory', function(done) {
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
var matcherFactory = function(util, customTesters) {
|
||||
return {
|
||||
compare: function() {
|
||||
return { pass: true };
|
||||
}
|
||||
};
|
||||
},
|
||||
matcherFactorySpy = jasmine.createSpy(
|
||||
'matcherFactorySpy',
|
||||
matcherFactory
|
||||
),
|
||||
customEqualityFn = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
env.it('spec with expectation', function() {
|
||||
env.addCustomEqualityTester(customEqualityFn);
|
||||
env.addMatchers({
|
||||
toBeReal: matcherFactorySpy
|
||||
});
|
||||
|
||||
env.expect(true).toBeReal();
|
||||
});
|
||||
|
||||
var specExpectations = function() {
|
||||
expect(matcherFactorySpy).toHaveBeenCalledWith(
|
||||
jasmine.any(jasmineUnderTest.MatchersUtil),
|
||||
[customEqualityFn]
|
||||
);
|
||||
};
|
||||
|
||||
env.addReporter({
|
||||
specDone: specExpectations,
|
||||
jasmineDone: function() {
|
||||
done();
|
||||
}
|
||||
});
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
|
||||
it('provides custom equality testers to the matcher factory via matchersUtil', function(done) {
|
||||
var matcherFactory = function(matchersUtil) {
|
||||
return {
|
||||
@@ -311,4 +354,41 @@ describe('Custom Matchers (Integration)', function() {
|
||||
env.addReporter({ specDone: specExpectations });
|
||||
env.execute(null, done);
|
||||
});
|
||||
|
||||
it('logs a distinct deprecation per matcher if the matcher factory takes two arguments', function(done) {
|
||||
var matcherFactory = function(matchersUtil, customEqualityTesters) {
|
||||
return { compare: function() {} };
|
||||
};
|
||||
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
env.beforeEach(function() {
|
||||
env.addMatchers({ toBeFoo: matcherFactory });
|
||||
env.addMatchers({ toBeBar: matcherFactory });
|
||||
});
|
||||
|
||||
env.it('a spec', function() {});
|
||||
env.it('another spec', function() {});
|
||||
|
||||
function jasmineDone() {
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(
|
||||
'The matcher factory for "toBeFoo" accepts custom equality testers, ' +
|
||||
'but this parameter will no longer be passed in a future release. ' +
|
||||
'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
|
||||
)
|
||||
);
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(
|
||||
'The matcher factory for "toBeBar" accepts custom equality testers, ' +
|
||||
'but this parameter will no longer be passed in a future release. ' +
|
||||
'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
|
||||
)
|
||||
);
|
||||
done();
|
||||
}
|
||||
|
||||
env.addReporter({ jasmineDone: jasmineDone });
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
|
||||
322
spec/core/integration/DeprecationSpec.js
Normal file
322
spec/core/integration/DeprecationSpec.js
Normal file
@@ -0,0 +1,322 @@
|
||||
/* eslint no-console: 0 */
|
||||
describe('Deprecation (integration)', function() {
|
||||
var env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmineUnderTest.Env();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
env.cleanup_();
|
||||
});
|
||||
|
||||
it('reports a deprecation on the top suite', function(done) {
|
||||
var reporter = jasmine.createSpyObj('reporter', ['jasmineDone']);
|
||||
env.addReporter(reporter);
|
||||
spyOn(console, 'error');
|
||||
|
||||
env.beforeAll(function() {
|
||||
env.deprecated('the message');
|
||||
});
|
||||
env.it('a spec', function() {});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(reporter.jasmineDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
deprecationWarnings: [
|
||||
jasmine.objectContaining({
|
||||
message: jasmine.stringMatching(/^the message/)
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(/^DEPRECATION: the message/)
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('reports a deprecation on a descendent suite', function(done) {
|
||||
var reporter = jasmine.createSpyObj('reporter', ['suiteDone']);
|
||||
env.addReporter(reporter);
|
||||
spyOn(console, 'error');
|
||||
|
||||
env.describe('a suite', function() {
|
||||
env.beforeAll(function() {
|
||||
env.deprecated('the message');
|
||||
});
|
||||
env.it('a spec', function() {});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(reporter.suiteDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
deprecationWarnings: [
|
||||
jasmine.objectContaining({
|
||||
message: jasmine.stringMatching(/^the message/)
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(
|
||||
/^DEPRECATION: the message \(in suite: a suite\)/
|
||||
)
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('reports a deprecation on a spec', function(done) {
|
||||
var reporter = jasmine.createSpyObj('reporter', ['specDone']);
|
||||
env.addReporter(reporter);
|
||||
spyOn(console, 'error');
|
||||
|
||||
env.describe('a suite', function() {
|
||||
env.it('a spec', function() {
|
||||
env.deprecated('the message');
|
||||
});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
deprecationWarnings: [
|
||||
jasmine.objectContaining({
|
||||
message: jasmine.stringMatching(/^the message/)
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(
|
||||
/^DEPRECATION: the message \(in spec: a suite a spec\)/
|
||||
)
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('omits the suite or spec context when ignoreRunnable is true', function(done) {
|
||||
var reporter = jasmine.createSpyObj('reporter', ['jasmineDone']);
|
||||
env.addReporter(reporter);
|
||||
spyOn(console, 'error');
|
||||
|
||||
env.it('a spec', function() {
|
||||
env.deprecated('the message', { ignoreRunnable: true });
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(reporter.jasmineDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
deprecationWarnings: [
|
||||
jasmine.objectContaining({
|
||||
message: jasmine.stringMatching(/^the message/)
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(/the message/)
|
||||
);
|
||||
expect(console.error).not.toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(/a spec/)
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('includes the stack trace', function(done) {
|
||||
var reporter = jasmine.createSpyObj('reporter', ['specDone']);
|
||||
env.addReporter(reporter);
|
||||
spyOn(console, 'error');
|
||||
|
||||
env.describe('a suite', function() {
|
||||
env.it('a spec', function() {
|
||||
env.deprecated('the message');
|
||||
});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
deprecationWarnings: [
|
||||
jasmine.objectContaining({
|
||||
stack: jasmine.stringMatching(/DeprecationSpec.js/)
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
expect(console.error).toHaveBeenCalled();
|
||||
expect(console.error.calls.argsFor(0)[0].replace(/\n/g, 'NL')).toMatch(
|
||||
/^DEPRECATION: the message \(in spec: a suite a spec\)NL.*DeprecationSpec.js/
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('excludes the stack trace when omitStackTrace is true', function(done) {
|
||||
var reporter = jasmine.createSpyObj('reporter', ['specDone']);
|
||||
env.addReporter(reporter);
|
||||
spyOn(console, 'error');
|
||||
|
||||
env.describe('a suite', function() {
|
||||
env.it('a spec', function() {
|
||||
env.deprecated('the message', { omitStackTrace: true });
|
||||
});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
deprecationWarnings: [
|
||||
jasmine.objectContaining({
|
||||
stack: jasmine.falsy()
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
expect(console.error).toHaveBeenCalled();
|
||||
expect(console.error).not.toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(/DeprecationSpec.js/)
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('emits a given deprecation only once', function(done) {
|
||||
var reporter = jasmine.createSpyObj('reporter', ['specDone', 'suiteDone']);
|
||||
env.addReporter(reporter);
|
||||
spyOn(console, 'error');
|
||||
|
||||
env.describe('a suite', function() {
|
||||
env.beforeAll(function() {
|
||||
env.deprecated('the message');
|
||||
env.deprecated('the message');
|
||||
});
|
||||
|
||||
env.it('a spec', function() {
|
||||
env.deprecated('the message');
|
||||
env.deprecated('a different message');
|
||||
});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(reporter.suiteDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
deprecationWarnings: [
|
||||
// only one
|
||||
jasmine.objectContaining({
|
||||
message: jasmine.stringMatching(/^the message/)
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
deprecationWarnings: [
|
||||
// only the other one
|
||||
jasmine.objectContaining({
|
||||
message: jasmine.stringMatching(/^a different message/)
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
expect(console.error).toHaveBeenCalledTimes(2);
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(
|
||||
/^DEPRECATION: the message \(in suite: a suite\)/
|
||||
)
|
||||
);
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(
|
||||
/^DEPRECATION: a different message \(in spec: a suite a spec\)/
|
||||
)
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('emits a given deprecation each time when config.verboseDeprecations is true', function(done) {
|
||||
var reporter = jasmine.createSpyObj('reporter', ['specDone', 'suiteDone']);
|
||||
env.addReporter(reporter);
|
||||
spyOn(console, 'error');
|
||||
|
||||
env.configure({ verboseDeprecations: true });
|
||||
|
||||
env.describe('a suite', function() {
|
||||
env.beforeAll(function() {
|
||||
env.deprecated('the message');
|
||||
env.deprecated('the message');
|
||||
});
|
||||
|
||||
env.it('a spec', function() {
|
||||
env.deprecated('the message');
|
||||
});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(reporter.suiteDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
deprecationWarnings: [
|
||||
jasmine.objectContaining({
|
||||
message: jasmine.stringMatching(/^the message/)
|
||||
}),
|
||||
jasmine.objectContaining({
|
||||
message: jasmine.stringMatching(/^the message/)
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
deprecationWarnings: [
|
||||
jasmine.objectContaining({
|
||||
message: jasmine.stringMatching(/^the message/)
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
expect(console.error).toHaveBeenCalledTimes(3);
|
||||
expect(console.error.calls.argsFor(0)[0]).toMatch(
|
||||
/^DEPRECATION: the message \(in suite: a suite\)/
|
||||
);
|
||||
expect(console.error.calls.argsFor(1)[0]).toMatch(
|
||||
/^DEPRECATION: the message \(in suite: a suite\)/
|
||||
);
|
||||
expect(console.error.calls.argsFor(2)[0]).toMatch(
|
||||
/^DEPRECATION: the message \(in spec: a suite a spec\)/
|
||||
);
|
||||
expect(console.error.calls.argsFor(2)[0]).toMatch(
|
||||
/^DEPRECATION: the message \(in spec: a suite a spec\)/
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('handles deprecations that occur before execute() is called', function(done) {
|
||||
var reporter = jasmine.createSpyObj('reporter', ['jasmineDone']);
|
||||
env.addReporter(reporter);
|
||||
spyOn(console, 'error');
|
||||
|
||||
env.deprecated('the message');
|
||||
env.it('a spec', function() {});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(reporter.jasmineDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
deprecationWarnings: [
|
||||
jasmine.objectContaining({
|
||||
message: jasmine.stringMatching(/^the message/)
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(/^DEPRECATION: the message/)
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -459,9 +459,13 @@ 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) {
|
||||
setTimeout(fn, delay);
|
||||
return setTimeout(fn, delay);
|
||||
},
|
||||
clearTimeout: function(fn, delay) {
|
||||
clearTimeout(fn, delay);
|
||||
@@ -509,6 +513,200 @@ describe('Env integration', function() {
|
||||
env.execute(null, assertions);
|
||||
});
|
||||
|
||||
it('deprecates multiple calls to done in the top suite', function(done) {
|
||||
var reporter = jasmine.createSpyObj('fakeReporter', ['jasmineDone']);
|
||||
var message =
|
||||
'A top-level beforeAll or afterAll function called its ' +
|
||||
"'done' callback more than once. This is a bug in the beforeAll " +
|
||||
'or afterAll function in question. This will be treated as an ' +
|
||||
'error in a future version. See' +
|
||||
'<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> ' +
|
||||
'for more information.';
|
||||
|
||||
spyOn(console, 'error');
|
||||
env.addReporter(reporter);
|
||||
env.configure({ verboseDeprecations: true });
|
||||
env.beforeAll(function(innerDone) {
|
||||
innerDone();
|
||||
innerDone();
|
||||
});
|
||||
env.it('a spec, so the beforeAll runs', function() {});
|
||||
env.afterAll(function(innerDone) {
|
||||
innerDone();
|
||||
innerDone();
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
var warnings;
|
||||
expect(reporter.jasmineDone).toHaveBeenCalled();
|
||||
warnings = reporter.jasmineDone.calls.argsFor(0)[0].deprecationWarnings;
|
||||
expect(warnings.length).toEqual(2);
|
||||
expect(warnings[0])
|
||||
.withContext('top beforeAll')
|
||||
.toEqual(jasmine.objectContaining({ message: message }));
|
||||
expect(warnings[1])
|
||||
.withContext('top afterAll')
|
||||
.toEqual(jasmine.objectContaining({ message: message }));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('deprecates multiple calls to done in a non-top suite', function(done) {
|
||||
var reporter = jasmine.createSpyObj('fakeReporter', ['jasmineDone']);
|
||||
var message =
|
||||
"An asynchronous function called its 'done' " +
|
||||
'callback more than once. This is a bug in the spec, beforeAll, ' +
|
||||
'beforeEach, afterAll, or afterEach function in question. This will ' +
|
||||
'be treated as an error in a future version. See' +
|
||||
'<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> ' +
|
||||
'for more information.';
|
||||
|
||||
spyOn(console, 'error');
|
||||
env.addReporter(reporter);
|
||||
env.configure({ verboseDeprecations: true });
|
||||
env.describe('a suite', function() {
|
||||
env.beforeAll(function(innerDone) {
|
||||
innerDone();
|
||||
innerDone();
|
||||
});
|
||||
env.it('a spec, so that before/afters run', function() {});
|
||||
env.afterAll(function(innerDone) {
|
||||
innerDone();
|
||||
innerDone();
|
||||
});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
var warnings;
|
||||
expect(reporter.jasmineDone).toHaveBeenCalled();
|
||||
warnings = reporter.jasmineDone.calls.argsFor(0)[0].deprecationWarnings;
|
||||
expect(warnings.length).toEqual(2);
|
||||
expect(warnings[0])
|
||||
.withContext('suite beforeAll')
|
||||
.toEqual(
|
||||
jasmine.objectContaining({
|
||||
message: message + '\n(in suite: a suite)'
|
||||
})
|
||||
);
|
||||
expect(warnings[1])
|
||||
.withContext('suite afterAll')
|
||||
.toEqual(
|
||||
jasmine.objectContaining({
|
||||
message: message + '\n(in suite: a suite)'
|
||||
})
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('deprecates multiple calls to done in a spec', function(done) {
|
||||
var reporter = jasmine.createSpyObj('fakeReporter', ['jasmineDone']);
|
||||
var message =
|
||||
"An asynchronous function called its 'done' " +
|
||||
'callback more than once. This is a bug in the spec, beforeAll, ' +
|
||||
'beforeEach, afterAll, or afterEach function in question. This will ' +
|
||||
'be treated as an error in a future version. See' +
|
||||
'<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> ' +
|
||||
'for more information.\n' +
|
||||
'(in spec: a suite a spec)';
|
||||
|
||||
spyOn(console, 'error');
|
||||
env.addReporter(reporter);
|
||||
env.configure({ verboseDeprecations: true });
|
||||
env.describe('a suite', function() {
|
||||
env.beforeEach(function(innerDone) {
|
||||
innerDone();
|
||||
innerDone();
|
||||
});
|
||||
env.it('a spec', function(innerDone) {
|
||||
innerDone();
|
||||
innerDone();
|
||||
});
|
||||
env.afterEach(function(innerDone) {
|
||||
innerDone();
|
||||
innerDone();
|
||||
});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
var warnings;
|
||||
expect(reporter.jasmineDone).toHaveBeenCalled();
|
||||
warnings = reporter.jasmineDone.calls.argsFor(0)[0].deprecationWarnings;
|
||||
expect(warnings.length).toEqual(3);
|
||||
expect(warnings[0])
|
||||
.withContext('warning caused by beforeEach')
|
||||
.toEqual(jasmine.objectContaining({ message: message }));
|
||||
expect(warnings[1])
|
||||
.withContext('warning caused by it')
|
||||
.toEqual(jasmine.objectContaining({ message: message }));
|
||||
expect(warnings[2])
|
||||
.withContext('warning caused by afterEach')
|
||||
.toEqual(jasmine.objectContaining({ message: message }));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('deprecates multiple calls to done in reporters', function(done) {
|
||||
var message =
|
||||
"An asynchronous reporter callback called its 'done' callback more " +
|
||||
'than once. This is a bug in the reporter callback in question. This ' +
|
||||
'will be treated as an error in a future version. See' +
|
||||
'<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> ' +
|
||||
'for more information.\nNote: This message ' +
|
||||
'will be shown only once. Set the verboseDeprecations config property ' +
|
||||
'to true to see every occurrence.';
|
||||
|
||||
var reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone']);
|
||||
reporter.specDone = function(result, done) {
|
||||
done();
|
||||
done();
|
||||
};
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.it('a spec', function() {});
|
||||
|
||||
spyOn(console, 'error');
|
||||
env.execute(null, function() {
|
||||
expect(reporter.jasmineDone).toHaveBeenCalled();
|
||||
warnings = reporter.jasmineDone.calls.argsFor(0)[0].deprecationWarnings;
|
||||
expect(warnings.length).toEqual(1);
|
||||
expect(warnings[0]).toEqual(
|
||||
jasmine.objectContaining({ message: message })
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('does not deprecate a call to done that comes after a timeout', function(done) {
|
||||
var reporter = jasmine.createSpyObj('fakeReporter', ['jasmineDone']),
|
||||
firstSpecDone;
|
||||
|
||||
reporter.specDone = function(result, reporterDone) {
|
||||
setTimeout(function() {
|
||||
firstSpecDone();
|
||||
reporterDone();
|
||||
});
|
||||
};
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.it(
|
||||
'a spec',
|
||||
function(innerDone) {
|
||||
firstSpecDone = innerDone;
|
||||
},
|
||||
1
|
||||
);
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(reporter.jasmineDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
deprecationWarnings: []
|
||||
})
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('suiteDone reporting', function() {
|
||||
it('reports when an afterAll fails an expectation', function(done) {
|
||||
var reporter = jasmine.createSpyObj('fakeReport', ['suiteDone']);
|
||||
@@ -656,8 +854,8 @@ describe('Env integration', function() {
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
// Expect >= 9 rather than >= 10 to compensate for clock imprecision
|
||||
expect(duration).toBeGreaterThanOrEqual(9);
|
||||
// Expect > 0 to compensate for clock imprecision
|
||||
expect(duration).toBeGreaterThan(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -683,8 +881,8 @@ describe('Env integration', function() {
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
// Expect >= 9 rather than >= 10 to compensate for clock imprecision
|
||||
expect(duration).toBeGreaterThanOrEqual(9);
|
||||
// Expect > 0 to compensate for clock imprecision
|
||||
expect(duration).toBeGreaterThan(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -1007,10 +1205,14 @@ 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) {
|
||||
setTimeout(cb, t);
|
||||
return setTimeout(cb, t);
|
||||
}),
|
||||
delayedFunctionForGlobalClock = jasmine.createSpy(
|
||||
'delayedFunctionForGlobalClock'
|
||||
@@ -1025,7 +1227,7 @@ describe('Env integration', function() {
|
||||
setTimeout: globalSetTimeout,
|
||||
clearTimeout: clearTimeout,
|
||||
setImmediate: function(cb) {
|
||||
setTimeout(cb, 0);
|
||||
return setTimeout(cb, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1057,6 +1259,42 @@ describe('Env integration', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('logs a deprecation warning when the mock clock is ticked reentrantly', function(done) {
|
||||
var ticked = false,
|
||||
env = jasmineUnderTest.getEnv();
|
||||
spyOn(env, 'deprecated');
|
||||
|
||||
env.beforeEach(function() {
|
||||
env.clock.install();
|
||||
});
|
||||
|
||||
env.afterEach(function() {
|
||||
env.clock.uninstall();
|
||||
});
|
||||
|
||||
env.it('ticks inside tick', function() {
|
||||
setTimeout(function() {
|
||||
ticked = true;
|
||||
env.clock.tick();
|
||||
}, 1);
|
||||
|
||||
env.clock.tick(1);
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(ticked).toBeTrue();
|
||||
expect(env.deprecated).toHaveBeenCalledWith(
|
||||
'The behavior of reentrant calls to jasmine.clock().tick() will ' +
|
||||
'change in a future version. Either modify the affected spec to ' +
|
||||
'not call tick() from within a setTimeout or setInterval handler, ' +
|
||||
'or be aware that it may behave differently in the future. See ' +
|
||||
'<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-reentrant-calls-to-jasmine-clock-tick> ' +
|
||||
'for details.'
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should run async specs in order, waiting for them to complete', function(done) {
|
||||
var mutatedVar;
|
||||
|
||||
@@ -1100,7 +1338,7 @@ describe('Env integration', function() {
|
||||
setInterval: setInterval,
|
||||
clearInterval: clearInterval,
|
||||
setImmediate: function(cb) {
|
||||
realSetTimeout(cb, 0);
|
||||
return realSetTimeout(cb, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1147,6 +1385,10 @@ 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;
|
||||
@@ -1185,6 +1427,10 @@ describe('Env integration', function() {
|
||||
});
|
||||
|
||||
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',
|
||||
@@ -1948,6 +2194,7 @@ describe('Env integration', function() {
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
env.it('has a test', function() {});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
@@ -1972,6 +2219,7 @@ describe('Env integration', function() {
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
env.it('has a test', function() {});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
@@ -1994,6 +2242,7 @@ describe('Env integration', function() {
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
env.it('has a test', function() {});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
@@ -2239,7 +2488,7 @@ describe('Env integration', function() {
|
||||
it('reports errors that occur during loading', function(done) {
|
||||
var global = {
|
||||
setTimeout: function(fn, delay) {
|
||||
setTimeout(fn, delay);
|
||||
return setTimeout(fn, delay);
|
||||
},
|
||||
clearTimeout: function(fn, delay) {
|
||||
clearTimeout(fn, delay);
|
||||
@@ -2296,7 +2545,7 @@ describe('Env integration', function() {
|
||||
var originalOnerror = jasmine.createSpy('original onerror');
|
||||
var global = {
|
||||
setTimeout: function(fn, delay) {
|
||||
setTimeout(fn, delay);
|
||||
return setTimeout(fn, delay);
|
||||
},
|
||||
clearTimeout: function(fn, delay) {
|
||||
clearTimeout(fn, delay);
|
||||
@@ -2497,10 +2746,10 @@ describe('Env integration', function() {
|
||||
it('is "failed"', function(done) {
|
||||
var global = {
|
||||
setTimeout: function(fn, delay) {
|
||||
setTimeout(fn, delay);
|
||||
return setTimeout(fn, delay);
|
||||
},
|
||||
clearTimeout: function(fn, delay) {
|
||||
clearTimeout(fn, delay);
|
||||
return clearTimeout(fn, delay);
|
||||
}
|
||||
};
|
||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||
@@ -2607,70 +2856,6 @@ describe('Env integration', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should report deprecation warnings on the correct specs and suites', function(done) {
|
||||
var reporter = jasmine.createSpyObj('reporter', [
|
||||
'jasmineDone',
|
||||
'suiteDone',
|
||||
'specDone'
|
||||
]);
|
||||
|
||||
// prevent deprecation from being displayed, as well as letting us observe calls
|
||||
spyOn(console, 'error');
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.deprecated('top level deprecation');
|
||||
|
||||
env.describe('suite', function() {
|
||||
env.beforeAll(function() {
|
||||
env.deprecated('suite level deprecation');
|
||||
});
|
||||
|
||||
env.it('spec', function() {
|
||||
env.deprecated('spec level deprecation');
|
||||
});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
var result = reporter.jasmineDone.calls.argsFor(0)[0];
|
||||
expect(result.deprecationWarnings).toEqual([
|
||||
jasmine.objectContaining({ message: 'top level deprecation' })
|
||||
]);
|
||||
/* eslint-disable-next-line no-console */
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
'DEPRECATION: top level deprecation'
|
||||
);
|
||||
|
||||
expect(reporter.suiteDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
fullName: 'suite',
|
||||
deprecationWarnings: [
|
||||
jasmine.objectContaining({ message: 'suite level deprecation' })
|
||||
]
|
||||
})
|
||||
);
|
||||
/* eslint-disable-next-line no-console */
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
'DEPRECATION: suite level deprecation (in suite: suite)'
|
||||
);
|
||||
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
fullName: 'suite spec',
|
||||
deprecationWarnings: [
|
||||
jasmine.objectContaining({ message: 'spec level deprecation' })
|
||||
]
|
||||
})
|
||||
);
|
||||
/* eslint-disable-next-line no-console */
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
'DEPRECATION: spec level deprecation (in spec: suite spec)'
|
||||
);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should report deprecation stack with an error object', function(done) {
|
||||
var exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
|
||||
reporter = jasmine.createSpyObj('reporter', [
|
||||
@@ -2883,6 +3068,8 @@ describe('Env integration', function() {
|
||||
resolve = res;
|
||||
});
|
||||
|
||||
env.configure({ random: false });
|
||||
|
||||
env.describe('a suite', function() {
|
||||
env.it('does not wait', function() {
|
||||
// Note: we intentionally don't return the result of each expectAsync.
|
||||
@@ -2892,6 +3079,12 @@ describe('Env integration', function() {
|
||||
});
|
||||
});
|
||||
|
||||
env.it('another spec', function(done) {
|
||||
// This is here to make sure that the async expectation evaluates
|
||||
// before the Jasmine under test finishes, especially on Safari 8 and 9.
|
||||
setTimeout(done, 10);
|
||||
});
|
||||
|
||||
env.addReporter({
|
||||
specDone: function() {
|
||||
resolve();
|
||||
@@ -2908,7 +3101,9 @@ describe('Env integration', function() {
|
||||
message:
|
||||
'Spec "a suite does not wait" ran a "toBeResolved" expectation ' +
|
||||
'after it finished.\n' +
|
||||
'Did you forget to return or await the result of expectAsync?',
|
||||
'1. Did you forget to return or await the result of expectAsync?\n' +
|
||||
'2. Was done() invoked before an async operation completed?\n' +
|
||||
'3. Did an expectation follow a call to done()?',
|
||||
matcherName: 'toBeResolved'
|
||||
}),
|
||||
jasmine.objectContaining({
|
||||
@@ -2919,7 +3114,9 @@ describe('Env integration', function() {
|
||||
'after it finished.\n' +
|
||||
"Message: \"Expected a promise to be resolved to 'something else' " +
|
||||
'but it was resolved to undefined."\n' +
|
||||
'Did you forget to return or await the result of expectAsync?',
|
||||
'1. Did you forget to return or await the result of expectAsync?\n' +
|
||||
'2. Was done() invoked before an async operation completed?\n' +
|
||||
'3. Did an expectation follow a call to done()?',
|
||||
matcherName: 'toBeResolvedTo'
|
||||
})
|
||||
]);
|
||||
@@ -2938,6 +3135,8 @@ describe('Env integration', function() {
|
||||
resolve = res;
|
||||
});
|
||||
|
||||
env.configure({ random: false });
|
||||
|
||||
env.describe('a suite', function() {
|
||||
env.afterAll(function() {
|
||||
// Note: we intentionally don't return the result of expectAsync.
|
||||
@@ -2948,6 +3147,12 @@ describe('Env integration', function() {
|
||||
env.it('is a spec', function() {});
|
||||
});
|
||||
|
||||
env.it('another spec', function(done) {
|
||||
// This is here to make sure that the async expectation evaluates
|
||||
// before the Jasmine under test finishes, especially on Safari 8 and 9.
|
||||
setTimeout(done, 10);
|
||||
});
|
||||
|
||||
env.addReporter({
|
||||
suiteDone: function() {
|
||||
resolve();
|
||||
@@ -2964,7 +3169,9 @@ describe('Env integration', function() {
|
||||
message:
|
||||
'Suite "a suite" ran a "toBeResolved" expectation ' +
|
||||
'after it finished.\n' +
|
||||
'Did you forget to return or await the result of expectAsync?',
|
||||
'1. Did you forget to return or await the result of expectAsync?\n' +
|
||||
'2. Was done() invoked before an async operation completed?\n' +
|
||||
'3. Did an expectation follow a call to done()?',
|
||||
matcherName: 'toBeResolved'
|
||||
})
|
||||
]);
|
||||
@@ -3002,6 +3209,112 @@ describe('Env integration', function() {
|
||||
env.execute(null, done);
|
||||
});
|
||||
|
||||
describe('The promise returned by #execute', function() {
|
||||
beforeEach(function() {
|
||||
this.savedInterval = jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL;
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = this.savedInterval;
|
||||
});
|
||||
|
||||
it('is resolved after reporter events are dispatched', function() {
|
||||
jasmine.getEnv().requirePromises();
|
||||
var reporter = jasmine.createSpyObj('reporter', [
|
||||
'specDone',
|
||||
'suiteDone',
|
||||
'jasmineDone'
|
||||
]);
|
||||
|
||||
env.addReporter(reporter);
|
||||
env.describe('suite', function() {
|
||||
env.it('spec', function() {});
|
||||
});
|
||||
|
||||
return env.execute(null).then(function() {
|
||||
expect(reporter.specDone).toHaveBeenCalled();
|
||||
expect(reporter.suiteDone).toHaveBeenCalled();
|
||||
expect(reporter.jasmineDone).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('is resolved after the stack is cleared', function(done) {
|
||||
jasmine.getEnv().requirePromises();
|
||||
var realClearStack = jasmineUnderTest.getClearStack(
|
||||
jasmineUnderTest.getGlobal()
|
||||
),
|
||||
clearStackSpy = jasmine
|
||||
.createSpy('clearStack')
|
||||
.and.callFake(realClearStack);
|
||||
spyOn(jasmineUnderTest, 'getClearStack').and.returnValue(clearStackSpy);
|
||||
|
||||
// Create a new env that has the clearStack defined above
|
||||
env.cleanup_();
|
||||
env = new jasmineUnderTest.Env();
|
||||
|
||||
env.describe('suite', function() {
|
||||
env.it('spec', function() {});
|
||||
});
|
||||
|
||||
env.execute(null).then(function() {
|
||||
expect(clearStackSpy).toHaveBeenCalled(); // (many times)
|
||||
clearStackSpy.calls.reset();
|
||||
setTimeout(function() {
|
||||
expect(clearStackSpy).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('is resolved after QueueRunner timeouts are cleared', function() {
|
||||
jasmine.getEnv().requirePromises();
|
||||
var setTimeoutSpy = spyOn(
|
||||
jasmineUnderTest.getGlobal(),
|
||||
'setTimeout'
|
||||
).and.callThrough();
|
||||
var clearTimeoutSpy = spyOn(
|
||||
jasmineUnderTest.getGlobal(),
|
||||
'clearTimeout'
|
||||
).and.callThrough();
|
||||
|
||||
jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 123456; // a distinctive value
|
||||
|
||||
env = new jasmineUnderTest.Env();
|
||||
|
||||
env.describe('suite', function() {
|
||||
env.it('spec', function() {});
|
||||
});
|
||||
|
||||
return env.execute(null).then(function() {
|
||||
var timeoutIds = setTimeoutSpy.calls
|
||||
.all()
|
||||
.filter(function(call) {
|
||||
return call.args[1] === 123456;
|
||||
})
|
||||
.map(function(call) {
|
||||
return call.returnValue;
|
||||
});
|
||||
|
||||
expect(timeoutIds.length).toBeGreaterThan(0);
|
||||
|
||||
timeoutIds.forEach(function(timeoutId) {
|
||||
expect(clearTimeoutSpy).toHaveBeenCalledWith(timeoutId);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('is resolved even if specs fail', function() {
|
||||
jasmine.getEnv().requirePromises();
|
||||
env.describe('suite', function() {
|
||||
env.it('spec', function() {
|
||||
env.expect(true).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
return expectAsync(env.execute(null)).toBeResolved();
|
||||
});
|
||||
});
|
||||
|
||||
describe('The optional callback argument to #execute', function() {
|
||||
beforeEach(function() {
|
||||
this.savedInterval = jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL;
|
||||
|
||||
@@ -754,4 +754,89 @@ describe('Matchers (Integration)', function() {
|
||||
'a predicate, but it threw Error with message |nope|.'
|
||||
});
|
||||
});
|
||||
|
||||
describe('When an async matcher is used with .already()', function() {
|
||||
it('propagates the matcher result when the promise is resolved', function(done) {
|
||||
jasmine.getEnv().requirePromises();
|
||||
|
||||
env.it('a spec', function() {
|
||||
// eslint-disable-next-line compat/compat
|
||||
return env.expectAsync(Promise.resolve()).already.toBeRejected();
|
||||
});
|
||||
|
||||
var specExpectations = function(result) {
|
||||
expect(result.status).toEqual('failed');
|
||||
expect(result.failedExpectations.length)
|
||||
.withContext('Number of failed expectations')
|
||||
.toEqual(1);
|
||||
expect(result.failedExpectations[0].message).toEqual(
|
||||
'Expected [object Promise] to be rejected.'
|
||||
);
|
||||
expect(result.failedExpectations[0].matcherName)
|
||||
.withContext('Matcher name')
|
||||
.not.toEqual('');
|
||||
};
|
||||
|
||||
env.addReporter({ specDone: specExpectations });
|
||||
env.execute(null, done);
|
||||
});
|
||||
|
||||
it('propagates the matcher result when the promise is rejected', function(done) {
|
||||
jasmine.getEnv().requirePromises();
|
||||
|
||||
env.it('a spec', function() {
|
||||
return (
|
||||
env
|
||||
// eslint-disable-next-line compat/compat
|
||||
.expectAsync(Promise.reject(new Error('nope')))
|
||||
.already.toBeResolved()
|
||||
);
|
||||
});
|
||||
|
||||
var specExpectations = function(result) {
|
||||
expect(result.status).toEqual('failed');
|
||||
expect(result.failedExpectations.length)
|
||||
.withContext('Number of failed expectations')
|
||||
.toEqual(1);
|
||||
expect(result.failedExpectations[0].message).toEqual(
|
||||
'Expected a promise to be resolved but it was ' +
|
||||
'rejected with Error: nope.'
|
||||
);
|
||||
expect(result.failedExpectations[0].matcherName)
|
||||
.withContext('Matcher name')
|
||||
.not.toEqual('');
|
||||
};
|
||||
|
||||
env.addReporter({ specDone: specExpectations });
|
||||
env.execute(null, done);
|
||||
});
|
||||
|
||||
it('fails when the promise is pending', function(done) {
|
||||
jasmine.getEnv().requirePromises();
|
||||
|
||||
// eslint-disable-next-line compat/compat
|
||||
var promise = new Promise(function() {});
|
||||
|
||||
env.it('a spec', function() {
|
||||
return env.expectAsync(promise).already.toBeResolved();
|
||||
});
|
||||
|
||||
var specExpectations = function(result) {
|
||||
expect(result.status).toEqual('failed');
|
||||
expect(result.failedExpectations.length)
|
||||
.withContext('Number of failed expectations')
|
||||
.toEqual(1);
|
||||
expect(result.failedExpectations[0].message).toEqual(
|
||||
'Expected a promise to be settled ' +
|
||||
'(via expectAsync(...).already) but it was pending.'
|
||||
);
|
||||
expect(result.failedExpectations[0].matcherName)
|
||||
.withContext('Matcher name')
|
||||
.not.toEqual('');
|
||||
};
|
||||
|
||||
env.addReporter({ specDone: specExpectations });
|
||||
env.execute(null, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -550,10 +550,17 @@ describe('spec running', function() {
|
||||
var pendingSpec,
|
||||
suite = env.describe('default current suite', function() {
|
||||
pendingSpec = env.it('I am a pending spec');
|
||||
});
|
||||
}),
|
||||
reporter = jasmine.createSpyObj('reporter', ['specDone']);
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(pendingSpec.status()).toBe('pending');
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
status: 'pending'
|
||||
})
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -785,7 +792,7 @@ describe('spec running', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('When throwOnExpectationFailure is set', function() {
|
||||
describe('When stopSpecOnExpectationFailure is set', function() {
|
||||
it('skips to cleanup functions after an error', function(done) {
|
||||
var actions = [];
|
||||
|
||||
@@ -814,7 +821,7 @@ describe('spec running', function() {
|
||||
});
|
||||
});
|
||||
|
||||
env.configure({ oneFailurePerSpec: true });
|
||||
env.configure({ stopSpecOnExpectationFailure: true });
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(actions).toEqual([
|
||||
@@ -845,7 +852,7 @@ describe('spec running', function() {
|
||||
});
|
||||
});
|
||||
|
||||
env.configure({ oneFailurePerSpec: true });
|
||||
env.configure({ stopSpecOnExpectationFailure: true });
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(actions).toEqual(['beforeEach', 'afterEach']);
|
||||
@@ -870,7 +877,7 @@ describe('spec running', function() {
|
||||
});
|
||||
});
|
||||
|
||||
env.configure({ oneFailurePerSpec: true });
|
||||
env.configure({ stopSpecOnExpectationFailure: true });
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(actions).toEqual(['beforeEach', 'afterEach']);
|
||||
@@ -980,35 +987,10 @@ describe('spec running', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('when stopOnSpecFailure is on', function() {
|
||||
function behavesLikeStopOnSpecFailureIsOn(configureFn) {
|
||||
it('does not run further specs when one fails', function(done) {
|
||||
var actions = [];
|
||||
|
||||
env.describe('wrapper', function() {
|
||||
env.it('fails', function() {
|
||||
actions.push('fails');
|
||||
env.expect(1).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
env.describe('holder', function() {
|
||||
env.it('does not run', function() {
|
||||
actions.push('does not run');
|
||||
});
|
||||
});
|
||||
|
||||
env.configure({ random: false, failFast: true });
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(actions).toEqual(['fails']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('does not run further specs when one fails when configured with deprecated option', function(done) {
|
||||
var actions = [];
|
||||
|
||||
spyOn(env, 'deprecated');
|
||||
var actions = [],
|
||||
config;
|
||||
|
||||
env.describe('wrapper', function() {
|
||||
env.it('fails', function() {
|
||||
@@ -1024,13 +1006,239 @@ describe('spec running', function() {
|
||||
});
|
||||
|
||||
env.configure({ random: false });
|
||||
env.stopOnSpecFailure(true);
|
||||
configureFn(env);
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(actions).toEqual(['fails']);
|
||||
expect(env.deprecated).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('when failFast is on', function() {
|
||||
behavesLikeStopOnSpecFailureIsOn(function(env) {
|
||||
spyOn(env, 'deprecated');
|
||||
env.configure({ failFast: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('when stopOnSpecFailure is on', function() {
|
||||
behavesLikeStopOnSpecFailureIsOn(function(env) {
|
||||
env.configure({ stopOnSpecFailure: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('when stopOnSpecFailure is enabled via the deprecated method', function() {
|
||||
behavesLikeStopOnSpecFailureIsOn(function(env) {
|
||||
spyOn(env, 'deprecated');
|
||||
env.stopOnSpecFailure(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('run multiple times', function() {
|
||||
beforeEach(function() {
|
||||
env.configure({ autoCleanClosures: false, random: false });
|
||||
});
|
||||
|
||||
it('should be able to run multiple times', function(done) {
|
||||
var actions = [];
|
||||
|
||||
env.describe('Suite', function() {
|
||||
env.it('spec1', function() {
|
||||
actions.push('spec1');
|
||||
});
|
||||
env.describe('inner suite', function() {
|
||||
env.it('spec2', function() {
|
||||
actions.push('spec2');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(actions).toEqual(['spec1', 'spec2']);
|
||||
env.execute(null, function() {
|
||||
expect(actions).toEqual(['spec1', 'spec2', 'spec1', 'spec2']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should reset results between runs', function(done) {
|
||||
var specResults = {};
|
||||
var suiteResults = {};
|
||||
var firstExecution = true;
|
||||
|
||||
env.addReporter({
|
||||
specDone: function(spec) {
|
||||
specResults[spec.description] = spec.status;
|
||||
},
|
||||
suiteDone: function(suite) {
|
||||
suiteResults[suite.description] = suite.status;
|
||||
},
|
||||
jasmineDone: function() {
|
||||
firstExecution = false;
|
||||
}
|
||||
});
|
||||
|
||||
env.describe('suite0', function() {
|
||||
env.it('spec1', function() {
|
||||
if (firstExecution) {
|
||||
env.expect(1).toBe(2);
|
||||
}
|
||||
});
|
||||
env.describe('suite1', function() {
|
||||
env.it('spec2', function() {
|
||||
if (firstExecution) {
|
||||
env.pending();
|
||||
}
|
||||
});
|
||||
env.xit('spec3', function() {}); // Always pending
|
||||
});
|
||||
env.describe('suite2', function() {
|
||||
env.it('spec4', function() {
|
||||
if (firstExecution) {
|
||||
throw new Error('spec 3 fails');
|
||||
}
|
||||
});
|
||||
});
|
||||
env.describe('suite3', function() {
|
||||
env.beforeEach(function() {
|
||||
throw new Error('suite 3 fails');
|
||||
});
|
||||
env.it('spec5', function() {});
|
||||
});
|
||||
env.xdescribe('suite4', function() {
|
||||
// Always pending
|
||||
env.it('spec6', function() {});
|
||||
});
|
||||
env.describe('suite5', function() {
|
||||
env.it('spec7');
|
||||
});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(specResults).toEqual({
|
||||
spec1: 'failed',
|
||||
spec2: 'pending',
|
||||
spec3: 'pending',
|
||||
spec4: 'failed',
|
||||
spec5: 'failed',
|
||||
spec6: 'pending',
|
||||
spec7: 'pending'
|
||||
});
|
||||
expect(suiteResults).toEqual({
|
||||
suite0: 'passed',
|
||||
suite1: 'passed',
|
||||
suite2: 'passed',
|
||||
suite3: 'passed',
|
||||
suite4: 'pending',
|
||||
suite5: 'passed'
|
||||
});
|
||||
env.execute(null, function() {
|
||||
expect(specResults).toEqual({
|
||||
spec1: 'passed',
|
||||
spec2: 'passed',
|
||||
spec3: 'pending',
|
||||
spec4: 'passed',
|
||||
spec5: 'failed',
|
||||
spec6: 'pending',
|
||||
spec7: 'pending'
|
||||
});
|
||||
expect(suiteResults).toEqual({
|
||||
suite0: 'passed',
|
||||
suite1: 'passed',
|
||||
suite2: 'passed',
|
||||
suite3: 'passed',
|
||||
suite4: 'pending',
|
||||
suite5: 'passed'
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should execute before and after hooks per run', function(done) {
|
||||
var timeline = [];
|
||||
var timelineFn = function(hookName) {
|
||||
return function() {
|
||||
timeline.push(hookName);
|
||||
};
|
||||
};
|
||||
var expectedTimeLine = [
|
||||
'beforeAll',
|
||||
'beforeEach',
|
||||
'spec1',
|
||||
'afterEach',
|
||||
'beforeEach',
|
||||
'spec2',
|
||||
'afterEach',
|
||||
'afterAll'
|
||||
];
|
||||
|
||||
env.describe('suite0', function() {
|
||||
env.beforeAll(timelineFn('beforeAll'));
|
||||
env.beforeEach(timelineFn('beforeEach'));
|
||||
env.afterEach(timelineFn('afterEach'));
|
||||
env.afterAll(timelineFn('afterAll'));
|
||||
env.it('spec1', timelineFn('spec1'));
|
||||
env.it('spec2', timelineFn('spec2'));
|
||||
});
|
||||
env.execute(null, function() {
|
||||
expect(timeline).toEqual(expectedTimeLine);
|
||||
timeline = [];
|
||||
env.execute(null, function() {
|
||||
expect(timeline).toEqual(expectedTimeLine);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to filter out different tests in subsequent runs', function(done) {
|
||||
var specResults = {};
|
||||
var focussedSpec = 'spec1';
|
||||
|
||||
env.configure({
|
||||
specFilter: function(spec) {
|
||||
return spec.description === focussedSpec;
|
||||
}
|
||||
});
|
||||
|
||||
env.addReporter({
|
||||
specDone: function(spec) {
|
||||
specResults[spec.description] = spec.status;
|
||||
}
|
||||
});
|
||||
|
||||
env.describe('suite0', function() {
|
||||
env.it('spec1', function() {});
|
||||
env.it('spec2', function() {});
|
||||
env.it('spec3', function() {});
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(specResults).toEqual({
|
||||
spec1: 'passed',
|
||||
spec2: 'excluded',
|
||||
spec3: 'excluded'
|
||||
});
|
||||
focussedSpec = 'spec2';
|
||||
env.execute(null, function() {
|
||||
expect(specResults).toEqual({
|
||||
spec1: 'excluded',
|
||||
spec2: 'passed',
|
||||
spec3: 'excluded'
|
||||
});
|
||||
focussedSpec = 'spec3';
|
||||
env.execute(null, function() {
|
||||
expect(specResults).toEqual({
|
||||
spec1: 'excluded',
|
||||
spec2: 'excluded',
|
||||
spec3: 'passed'
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,12 +15,19 @@ describe('toBeResolved', function() {
|
||||
it('fails if the actual is rejected', function() {
|
||||
jasmine.getEnv().requirePromises();
|
||||
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil(),
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil({
|
||||
pp: jasmineUnderTest.makePrettyPrinter([])
|
||||
}),
|
||||
matcher = jasmineUnderTest.asyncMatchers.toBeResolved(matchersUtil),
|
||||
actual = Promise.reject('AsyncExpectationSpec rejection');
|
||||
actual = Promise.reject(new Error('AsyncExpectationSpec rejection'));
|
||||
|
||||
return matcher.compare(actual).then(function(result) {
|
||||
expect(result).toEqual(jasmine.objectContaining({ pass: false }));
|
||||
expect(result).toEqual({
|
||||
pass: false,
|
||||
message:
|
||||
'Expected a promise to be resolved but it was rejected ' +
|
||||
'with Error: AsyncExpectationSpec rejection.'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -19,14 +19,15 @@ describe('#toBeResolvedTo', function() {
|
||||
pp: jasmineUnderTest.makePrettyPrinter()
|
||||
}),
|
||||
matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(matchersUtil),
|
||||
actual = Promise.reject('AsyncExpectationSpec error');
|
||||
actual = Promise.reject(new Error('AsyncExpectationSpec error'));
|
||||
|
||||
return matcher.compare(actual, '').then(function(result) {
|
||||
expect(result).toEqual(
|
||||
jasmine.objectContaining({
|
||||
pass: false,
|
||||
message:
|
||||
"Expected a promise to be resolved to '' but it was rejected."
|
||||
"Expected a promise to be resolved to '' but it was rejected " +
|
||||
'with Error: AsyncExpectationSpec error.'
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
@@ -7,78 +7,6 @@ describe('matchersUtil', function() {
|
||||
});
|
||||
|
||||
describe('equals', function() {
|
||||
describe('Properties', function() {
|
||||
var fc;
|
||||
|
||||
beforeEach(function() {
|
||||
fc = jasmine.getEnv().requireFastCheck();
|
||||
});
|
||||
|
||||
function basicAnythingSettings() {
|
||||
return {
|
||||
key: fc.oneof(fc.string(), fc.constantFrom('k1', 'k2', 'k3')),
|
||||
// Limiting depth & number of keys allows fast-check to try
|
||||
// a lot more scalar values.
|
||||
maxDepth: 2,
|
||||
maxKeys: 5,
|
||||
withBoxedValues: true,
|
||||
withMap: true,
|
||||
withSet: true
|
||||
};
|
||||
}
|
||||
|
||||
function numRuns() {
|
||||
var many = 5000000;
|
||||
|
||||
// Be thorough but very slow when specified (usually on CI).
|
||||
if (process.env.JASMINE_LONG_PROPERTY_TESTS) {
|
||||
/* eslint-disable-next-line no-console */
|
||||
console.log(
|
||||
'Using',
|
||||
many,
|
||||
'runs of fc.assert because JASMINE_LONG_PROPERTY_TESTS was set. This may take several minutes.'
|
||||
);
|
||||
return many;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
it('is symmetric', function() {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.anything(basicAnythingSettings()),
|
||||
fc.anything(basicAnythingSettings()),
|
||||
function(a, b) {
|
||||
return (
|
||||
jasmineUnderTest.matchersUtil.equals(a, b) ===
|
||||
jasmineUnderTest.matchersUtil.equals(b, a)
|
||||
);
|
||||
}
|
||||
),
|
||||
{
|
||||
numRuns: numRuns(),
|
||||
examples: [[0, 5e-324]]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('is reflexive', function() {
|
||||
var anythingSettings = basicAnythingSettings();
|
||||
anythingSettings.withMap = false;
|
||||
fc.assert(
|
||||
fc.property(fc.dedup(fc.anything(anythingSettings), 2), function(
|
||||
values
|
||||
) {
|
||||
return jasmineUnderTest.matchersUtil.equals(values[0], values[1]);
|
||||
}),
|
||||
{
|
||||
numRuns: numRuns()
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('passes for literals that are triple-equal', function() {
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
expect(matchersUtil.equals(null, null)).toBe(true);
|
||||
@@ -506,6 +434,8 @@ describe('matchersUtil', function() {
|
||||
},
|
||||
matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
|
||||
spyOn(jasmineUnderTest.getEnv(), 'deprecated'); // suppress warning
|
||||
|
||||
expect(matchersUtil.equals(1, 2, [tester])).toBe(true);
|
||||
});
|
||||
|
||||
@@ -534,6 +464,7 @@ describe('matchersUtil', function() {
|
||||
|
||||
it('passes for two empty Objects', function() {
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
spyOn(jasmineUnderTest.getEnv(), 'deprecated'); // suppress warning
|
||||
expect(matchersUtil.equals({}, {}, [tester])).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -559,6 +490,8 @@ describe('matchersUtil', function() {
|
||||
},
|
||||
matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
|
||||
spyOn(jasmineUnderTest.getEnv(), 'deprecated'); // suppress warning
|
||||
|
||||
expect(matchersUtil.equals(1, 1, [tester])).toBe(false);
|
||||
});
|
||||
|
||||
@@ -586,6 +519,8 @@ describe('matchersUtil', function() {
|
||||
},
|
||||
matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
|
||||
spyOn(jasmineUnderTest.getEnv(), 'deprecated'); // suppress warning
|
||||
|
||||
expect(
|
||||
matchersUtil.equals(asymmetricTester, true, [symmetricTester])
|
||||
).toBe(true);
|
||||
@@ -622,6 +557,7 @@ describe('matchersUtil', function() {
|
||||
matchersUtil = new jasmineUnderTest.MatchersUtil(),
|
||||
shim;
|
||||
|
||||
spyOn(jasmineUnderTest.getEnv(), 'deprecated'); // suppress warning
|
||||
matchersUtil.equals(true, asymmetricTester, [symmetricTester]);
|
||||
shim = asymmetricTester.asymmetricMatch.calls.argsFor(0)[1];
|
||||
expect(shim).toEqual(jasmine.any(jasmineUnderTest.MatchersUtil));
|
||||
@@ -642,6 +578,7 @@ describe('matchersUtil', function() {
|
||||
}),
|
||||
shim;
|
||||
|
||||
spyOn(jasmineUnderTest.getEnv(), 'deprecated'); // suppress warning
|
||||
matchersUtil.equals(true, asymmetricTester);
|
||||
shim = asymmetricTester.asymmetricMatch.calls.argsFor(0)[1];
|
||||
expect(shim).toEqual(jasmine.any(jasmineUnderTest.MatchersUtil));
|
||||
@@ -885,6 +822,172 @@ describe('matchersUtil', function() {
|
||||
);
|
||||
});
|
||||
|
||||
it('passes for ArrayBuffers with same length and content', function() {
|
||||
jasmine.getEnv().requireFunctioningArrayBuffers();
|
||||
var buffer1 = new ArrayBuffer(4); // eslint-disable-line compat/compat
|
||||
var buffer2 = new ArrayBuffer(4); // eslint-disable-line compat/compat
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
expect(matchersUtil.equals(buffer1, buffer2)).toBe(true);
|
||||
});
|
||||
|
||||
it('fails for ArrayBuffers with same length but different content', function() {
|
||||
jasmine.getEnv().requireFunctioningArrayBuffers();
|
||||
var buffer1 = new ArrayBuffer(4); // eslint-disable-line compat/compat
|
||||
var buffer2 = new ArrayBuffer(4); // eslint-disable-line compat/compat
|
||||
var array1 = new Uint8Array(buffer1); // eslint-disable-line compat/compat
|
||||
array1[0] = 1;
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
expect(matchersUtil.equals(buffer1, buffer2)).toBe(false);
|
||||
});
|
||||
|
||||
describe('Typed arrays', function() {
|
||||
it('fails for typed arrays of same length and contents but different types', function() {
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
// eslint-disable-next-line compat/compat
|
||||
var a1 = new Int8Array(1);
|
||||
// eslint-disable-next-line compat/compat
|
||||
var a2 = new Uint8Array(1);
|
||||
a1[0] = a2[0] = 0;
|
||||
expect(matchersUtil.equals(a1, a2)).toBe(false);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line compat/compat
|
||||
[
|
||||
'Int8Array',
|
||||
'Uint8Array',
|
||||
'Uint8ClampedArray',
|
||||
'Int16Array',
|
||||
'Uint16Array',
|
||||
'Int32Array',
|
||||
'Uint32Array',
|
||||
'Float32Array',
|
||||
'Float64Array'
|
||||
].forEach(function(typeName) {
|
||||
function requireType() {
|
||||
var TypedArrayCtor = jasmine.getGlobal()[typeName];
|
||||
|
||||
if (!TypedArrayCtor) {
|
||||
pending('Browser does not support ' + typeName);
|
||||
}
|
||||
|
||||
return TypedArrayCtor;
|
||||
}
|
||||
|
||||
it(
|
||||
'passes for ' + typeName + 's with same length and content',
|
||||
function() {
|
||||
var TypedArrayCtor = requireType();
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
var a1 = new TypedArrayCtor(2);
|
||||
var a2 = new TypedArrayCtor(2);
|
||||
a1[0] = a2[0] = 0;
|
||||
a1[1] = a2[1] = 1;
|
||||
expect(matchersUtil.equals(a1, a2)).toBe(true);
|
||||
}
|
||||
);
|
||||
|
||||
it('fails for ' + typeName + 's with different length', function() {
|
||||
var TypedArrayCtor = requireType();
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
var a1 = new TypedArrayCtor(2);
|
||||
var a2 = new TypedArrayCtor(1);
|
||||
a1[0] = a1[1] = a2[0] = 0;
|
||||
expect(matchersUtil.equals(a1, a2)).toBe(false);
|
||||
});
|
||||
|
||||
it(
|
||||
'fails for ' + typeName + 's with same length but different content',
|
||||
function() {
|
||||
var TypedArrayCtor = requireType();
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
var a1 = new TypedArrayCtor(1);
|
||||
var a2 = new TypedArrayCtor(1);
|
||||
a1[0] = 0;
|
||||
a2[0] = 1;
|
||||
expect(matchersUtil.equals(a1, a2)).toBe(false);
|
||||
}
|
||||
);
|
||||
|
||||
it('checks nonstandard properties of ' + typeName, function() {
|
||||
var TypedArrayCtor = requireType();
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
var a1 = new TypedArrayCtor(1);
|
||||
var a2 = new TypedArrayCtor(1);
|
||||
a1[0] = a2[0] = 0;
|
||||
a1.extra = 'yes';
|
||||
expect(matchersUtil.equals(a1, a2)).toBe(false);
|
||||
});
|
||||
|
||||
it('works with custom equality testers with ' + typeName, function() {
|
||||
var TypedArrayCtor = requireType();
|
||||
var a1 = new TypedArrayCtor(1);
|
||||
var a2 = new TypedArrayCtor(1);
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil({
|
||||
customTesters: [
|
||||
function() {
|
||||
return true;
|
||||
}
|
||||
]
|
||||
});
|
||||
a1[0] = 0;
|
||||
a2[0] = 1;
|
||||
expect(matchersUtil.equals(a1, a2)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
['BigInt64Array', 'BigUint64Array'].forEach(function(typeName) {
|
||||
function requireType() {
|
||||
var TypedArrayCtor = jasmine.getGlobal()[typeName];
|
||||
|
||||
if (!TypedArrayCtor) {
|
||||
pending('Browser does not support ' + typeName);
|
||||
}
|
||||
|
||||
return TypedArrayCtor;
|
||||
}
|
||||
|
||||
it(
|
||||
'passes for ' + typeName + 's with same length and content',
|
||||
function() {
|
||||
var TypedArrayCtor = requireType();
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
var a1 = new TypedArrayCtor(2);
|
||||
var a2 = new TypedArrayCtor(2);
|
||||
// eslint-disable-next-line compat/compat
|
||||
a1[0] = a2[0] = BigInt(0);
|
||||
// eslint-disable-next-line compat/compat
|
||||
a1[1] = a2[1] = BigInt(1);
|
||||
expect(matchersUtil.equals(a1, a2)).toBe(true);
|
||||
}
|
||||
);
|
||||
|
||||
it('fails for ' + typeName + 's with different length', function() {
|
||||
var TypedArrayCtor = requireType();
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
var a1 = new TypedArrayCtor(2);
|
||||
var a2 = new TypedArrayCtor(1);
|
||||
// eslint-disable-next-line compat/compat
|
||||
a1[0] = a1[1] = a2[0] = BigInt(0);
|
||||
expect(matchersUtil.equals(a1, a2)).toBe(false);
|
||||
});
|
||||
|
||||
it(
|
||||
'fails for ' + typeName + 's with same length but different content',
|
||||
function() {
|
||||
var TypedArrayCtor = requireType();
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
var a1 = new TypedArrayCtor(2);
|
||||
var a2 = new TypedArrayCtor(2);
|
||||
// eslint-disable-next-line compat/compat
|
||||
a1[0] = a1[1] = a2[0] = BigInt(0);
|
||||
// eslint-disable-next-line compat/compat
|
||||
a2[1] = BigInt(1);
|
||||
expect(matchersUtil.equals(a1, a2)).toBe(false);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when running in an environment with array polyfills', function() {
|
||||
var findIndexDescriptor = Object.getOwnPropertyDescriptor(
|
||||
Array.prototype,
|
||||
@@ -957,12 +1060,13 @@ describe('matchersUtil', function() {
|
||||
'recordMismatch',
|
||||
'withPath',
|
||||
'setRoots'
|
||||
]);
|
||||
]),
|
||||
matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
|
||||
diffBuilder.withPath.and.callFake(function(p, block) {
|
||||
block();
|
||||
});
|
||||
jasmineUnderTest.matchersUtil.equals(actual, expected, [], diffBuilder);
|
||||
matchersUtil.equals(actual, expected, diffBuilder);
|
||||
|
||||
expect(diffBuilder.setRoots).toHaveBeenCalledWith(actual, expected);
|
||||
expect(diffBuilder.withPath).toHaveBeenCalledWith(
|
||||
@@ -984,11 +1088,13 @@ describe('matchersUtil', function() {
|
||||
'recordMismatch',
|
||||
'withPath',
|
||||
'setRoots'
|
||||
]);
|
||||
]),
|
||||
matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
|
||||
diffBuilder.withPath.and.callFake(function(p, block) {
|
||||
block();
|
||||
});
|
||||
jasmineUnderTest.matchersUtil.equals(actual, expected, [], diffBuilder);
|
||||
matchersUtil.equals(actual, expected, diffBuilder);
|
||||
|
||||
expect(diffBuilder.setRoots).toHaveBeenCalledWith(actual, expected);
|
||||
expect(diffBuilder.withPath).toHaveBeenCalledWith(
|
||||
@@ -999,11 +1105,42 @@ describe('matchersUtil', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('logs a deprecation warning when custom equality testers are passed', function() {
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil(),
|
||||
deprecated = spyOn(jasmineUnderTest.getEnv(), 'deprecated');
|
||||
|
||||
matchersUtil.equals(0, 0, []);
|
||||
|
||||
expect(deprecated).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(
|
||||
'Passing custom equality testers ' +
|
||||
'to MatchersUtil#equals is deprecated. ' +
|
||||
'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('logs a deprecation warning when a diffBuilder is provided as the fourth argument', function() {
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil(),
|
||||
deprecated = spyOn(jasmineUnderTest.getEnv(), 'deprecated');
|
||||
|
||||
matchersUtil.equals(0, 0, null, new jasmineUnderTest.NullDiffBuilder());
|
||||
|
||||
expect(deprecated).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(
|
||||
'Diff builder should be passed as the ' +
|
||||
'third argument to MatchersUtil#equals, not the fourth. ' +
|
||||
'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('uses a diffBuilder if one is provided as the fourth argument', function() {
|
||||
// TODO: remove this in the next major release.
|
||||
var diffBuilder = new jasmineUnderTest.DiffBuilder(),
|
||||
matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
|
||||
spyOn(jasmineUnderTest.getEnv(), 'deprecated'); // suppress warning
|
||||
spyOn(diffBuilder, 'recordMismatch');
|
||||
spyOn(diffBuilder, 'withPath').and.callThrough();
|
||||
|
||||
@@ -1073,9 +1210,17 @@ describe('matchersUtil', function() {
|
||||
var customTester = function(a, b) {
|
||||
return true;
|
||||
},
|
||||
matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
matchersUtil = new jasmineUnderTest.MatchersUtil(),
|
||||
deprecated = spyOn(jasmineUnderTest.getEnv(), 'deprecated');
|
||||
|
||||
expect(matchersUtil.contains([1, 2], 3, [customTester])).toBe(true);
|
||||
|
||||
expect(deprecated).toHaveBeenCalledWith(
|
||||
jasmine.stringMatching(
|
||||
'Passing custom equality testers to MatchersUtil#contains is deprecated. ' +
|
||||
'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('uses custom equality testers if passed to the constructor and actual is an Array', function() {
|
||||
@@ -1090,6 +1235,22 @@ describe('matchersUtil', function() {
|
||||
expect(matchersUtil.contains([1, 2], 3)).toBe(true);
|
||||
});
|
||||
|
||||
it('logs a single deprecation warning when custom equality testers are passed', function() {
|
||||
// TODO: remove this in the next major release.
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil(),
|
||||
deprecated = spyOn(jasmineUnderTest.getEnv(), 'deprecated');
|
||||
|
||||
matchersUtil.contains([0], 0, []);
|
||||
|
||||
expect(deprecated).toHaveBeenCalledOnceWith(
|
||||
jasmine.stringMatching(
|
||||
'Passing custom equality testers ' +
|
||||
'to MatchersUtil#contains is deprecated. ' +
|
||||
'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('fails when actual is undefined', function() {
|
||||
var matchersUtil = new jasmineUnderTest.MatchersUtil();
|
||||
expect(matchersUtil.contains(undefined, 'A')).toBe(false);
|
||||
|
||||
@@ -257,8 +257,6 @@ describe('toEqual', function() {
|
||||
});
|
||||
|
||||
it('reports mismatches between arrays of different types', function() {
|
||||
jasmine.getEnv().requireFunctioningTypedArrays();
|
||||
|
||||
var actual = new Uint32Array([1, 2, 3]), // eslint-disable-line compat/compat
|
||||
expected = new Uint16Array([1, 2, 3]), // eslint-disable-line compat/compat
|
||||
message =
|
||||
|
||||
24
spec/helpers/checkForArrayBuffer.js
Normal file
24
spec/helpers/checkForArrayBuffer.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/* eslint-disable compat/compat */
|
||||
(function(env) {
|
||||
function hasFunctioningArrayBuffers() {
|
||||
if (typeof ArrayBuffer === 'undefined') {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
var buffer = new ArrayBuffer(2);
|
||||
var view8bit = new Uint8Array(buffer);
|
||||
var view16bit = new Uint16Array(buffer);
|
||||
view16bit[0] = 0xabcd;
|
||||
return view8bit[0] === 0xcd && view8bit[1] === 0xab;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
env.requireFunctioningArrayBuffers = function() {
|
||||
if (!hasFunctioningArrayBuffers()) {
|
||||
env.pending('Browser has incomplete or missing support for ArrayBuffer');
|
||||
}
|
||||
};
|
||||
})(jasmine.getEnv());
|
||||
17
spec/helpers/checkForProxy.js
Normal file
17
spec/helpers/checkForProxy.js
Normal file
@@ -0,0 +1,17 @@
|
||||
/* eslint-disable compat/compat */
|
||||
(function(env) {
|
||||
function hasProxyConstructor() {
|
||||
try {
|
||||
new Proxy({}, {});
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
env.requireProxy = function() {
|
||||
if (!hasProxyConstructor()) {
|
||||
env.pending('Environment does not support Proxy');
|
||||
}
|
||||
};
|
||||
})(jasmine.getEnv());
|
||||
@@ -1,24 +0,0 @@
|
||||
/* eslint-disable compat/compat */
|
||||
(function(env) {
|
||||
function hasFunctioningTypedArrays() {
|
||||
if (typeof Uint32Array === 'undefined') {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
var a = new Uint32Array([1, 2, 3]);
|
||||
if (a.length !== 3) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
env.requireFunctioningTypedArrays = function() {
|
||||
if (!hasFunctioningTypedArrays()) {
|
||||
env.pending('Browser has incomplete or missing support for typed arrays');
|
||||
}
|
||||
};
|
||||
})(jasmine.getEnv());
|
||||
7
spec/helpers/disableBrowserFlakes.js
Normal file
7
spec/helpers/disableBrowserFlakes.js
Normal file
@@ -0,0 +1,7 @@
|
||||
(function(env) {
|
||||
env.skipBrowserFlake = function() {
|
||||
pending(
|
||||
'Skipping specs that are known to be flaky in browsers in this run'
|
||||
);
|
||||
};
|
||||
})(jasmine.getEnv());
|
||||
@@ -42,9 +42,9 @@
|
||||
: 'Expected runnable "' +
|
||||
fullName +
|
||||
'" to have failures ' +
|
||||
jasmine.pp(expectedFailures) +
|
||||
jasmine.basicPrettyPrinter_(expectedFailures) +
|
||||
' but it had ' +
|
||||
jasmine.pp(foundFailures)
|
||||
jasmine.basicPrettyPrinter_(foundFailures)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,4 +4,10 @@
|
||||
env.pending('Environment does not support promises');
|
||||
}
|
||||
};
|
||||
|
||||
env.requireNoPromises = function() {
|
||||
if (typeof Promise === 'function') {
|
||||
env.pending('Environment supports promises');
|
||||
}
|
||||
};
|
||||
})(jasmine.getEnv());
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
(function(env) {
|
||||
var NODE_JS =
|
||||
typeof process !== 'undefined' &&
|
||||
process.versions &&
|
||||
typeof process.versions.node === 'string';
|
||||
|
||||
env.requireFastCheck = function() {
|
||||
if (!NODE_JS) {
|
||||
env.pending(
|
||||
"Property tests don't run in the browser. Use `npm test` to run them."
|
||||
);
|
||||
}
|
||||
|
||||
return require('fast-check');
|
||||
};
|
||||
})(jasmine.getEnv());
|
||||
4
spec/helpers/resetEnv.js
Normal file
4
spec/helpers/resetEnv.js
Normal file
@@ -0,0 +1,4 @@
|
||||
beforeEach(function() {
|
||||
// env is stateful. Ensure that it does not leak between tests.
|
||||
jasmineUnderTest.currentEnv_ = null;
|
||||
});
|
||||
@@ -303,6 +303,128 @@ describe('HtmlReporter', function() {
|
||||
expect(alertBars[3].innerHTML).toMatch(/global deprecation/);
|
||||
expect(alertBars[3].innerHTML).not.toMatch(/in /);
|
||||
});
|
||||
|
||||
it('displays expandable stack traces', function() {
|
||||
var container = document.createElement('div'),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
createTextNode: function() {
|
||||
return document.createTextNode.apply(document, arguments);
|
||||
}
|
||||
}),
|
||||
expander,
|
||||
expanderLink,
|
||||
expanderContents;
|
||||
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
reporter.jasmineDone({
|
||||
deprecationWarnings: [
|
||||
{
|
||||
message: 'a deprecation',
|
||||
stack: 'a stack trace'
|
||||
}
|
||||
],
|
||||
failedExpectations: []
|
||||
});
|
||||
|
||||
expander = container.querySelector(
|
||||
'.jasmine-alert .jasmine-bar .jasmine-expander'
|
||||
);
|
||||
expanderContents = expander.querySelector('.jasmine-expander-contents');
|
||||
expect(expanderContents.textContent).toMatch(/a stack trace/);
|
||||
|
||||
expanderLink = expander.querySelector('a');
|
||||
expect(expander).not.toHaveClass('jasmine-expanded');
|
||||
expect(expanderLink.textContent).toMatch(/Show stack trace/);
|
||||
|
||||
expanderLink.click();
|
||||
expect(expander).toHaveClass('jasmine-expanded');
|
||||
expect(expanderLink.textContent).toMatch(/Hide stack trace/);
|
||||
expanderLink.click();
|
||||
|
||||
expect(expander).not.toHaveClass('jasmine-expanded');
|
||||
expect(expanderLink.textContent).toMatch(/Show stack trace/);
|
||||
});
|
||||
|
||||
it('omits the expander when there is no stack trace', function() {
|
||||
var container = document.createElement('div'),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
createTextNode: function() {
|
||||
return document.createTextNode.apply(document, arguments);
|
||||
}
|
||||
}),
|
||||
warningBar;
|
||||
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
reporter.jasmineDone({
|
||||
deprecationWarnings: [
|
||||
{
|
||||
message: 'a deprecation',
|
||||
stack: ''
|
||||
}
|
||||
],
|
||||
failedExpectations: []
|
||||
});
|
||||
|
||||
warningBar = container.querySelector('.jasmine-warning');
|
||||
expect(warningBar.querySelector('.jasmine-expander')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('nicely formats the verboseDeprecations note', function() {
|
||||
var container = document.createElement('div'),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
reporter = new jasmineUnderTest.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
createTextNode: function() {
|
||||
return document.createTextNode.apply(document, arguments);
|
||||
}
|
||||
}),
|
||||
alertBar;
|
||||
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
reporter.jasmineDone({
|
||||
deprecationWarnings: [
|
||||
{
|
||||
message:
|
||||
'a deprecation\nNote: This message will be shown only once. Set config.verboseDeprecations to true to see every occurrence.'
|
||||
}
|
||||
],
|
||||
failedExpectations: []
|
||||
});
|
||||
|
||||
alertBar = container.querySelector('.jasmine-warning');
|
||||
|
||||
expect(alertBar.innerHTML).toMatch(
|
||||
/a deprecation<br>Note: This message will be shown only once/
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when Jasmine is done', function() {
|
||||
@@ -484,7 +606,7 @@ describe('HtmlReporter', function() {
|
||||
var suiteDetail = outerSuite.childNodes[0];
|
||||
var suiteLink = suiteDetail.childNodes[0];
|
||||
expect(suiteLink.innerHTML).toEqual('A Suite');
|
||||
expect(suiteLink.getAttribute('href')).toEqual('?foo=bar&spec=A Suite');
|
||||
expect(suiteLink.getAttribute('href')).toEqual('/?foo=bar&spec=A Suite');
|
||||
|
||||
var specs = outerSuite.childNodes[1];
|
||||
var spec = specs.childNodes[0];
|
||||
@@ -494,7 +616,7 @@ describe('HtmlReporter', function() {
|
||||
var specLink = spec.childNodes[0];
|
||||
expect(specLink.innerHTML).toEqual('with a spec');
|
||||
expect(specLink.getAttribute('href')).toEqual(
|
||||
'?foo=bar&spec=A Suite with a spec'
|
||||
'/?foo=bar&spec=A Suite with a spec'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -663,7 +785,7 @@ describe('HtmlReporter', function() {
|
||||
}
|
||||
});
|
||||
|
||||
env.configure({ failFast: true });
|
||||
env.configure({ stopOnSpecFailure: true });
|
||||
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
@@ -717,7 +839,7 @@ describe('HtmlReporter', function() {
|
||||
}
|
||||
});
|
||||
|
||||
env.configure({ failFast: true });
|
||||
env.configure({ stopOnSpecFailure: true });
|
||||
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
@@ -769,7 +891,7 @@ describe('HtmlReporter', function() {
|
||||
}
|
||||
});
|
||||
|
||||
env.configure({ oneFailurePerSpec: true });
|
||||
env.configure({ stopSpecOnExpectationFailure: true });
|
||||
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
@@ -802,7 +924,7 @@ describe('HtmlReporter', function() {
|
||||
var throwingExpectationsUI = container.querySelector('.jasmine-throw');
|
||||
throwingExpectationsUI.click();
|
||||
|
||||
expect(navigateHandler).toHaveBeenCalledWith('throwFailures', true);
|
||||
expect(navigateHandler).toHaveBeenCalledWith('oneFailurePerSpec', true);
|
||||
});
|
||||
|
||||
it('should navigate and change the setting to off', function() {
|
||||
@@ -823,7 +945,7 @@ describe('HtmlReporter', function() {
|
||||
}
|
||||
});
|
||||
|
||||
env.configure({ oneFailurePerSpec: true });
|
||||
env.configure({ stopSpecOnExpectationFailure: true });
|
||||
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
@@ -831,7 +953,10 @@ describe('HtmlReporter', function() {
|
||||
var throwingExpectationsUI = container.querySelector('.jasmine-throw');
|
||||
throwingExpectationsUI.click();
|
||||
|
||||
expect(navigateHandler).toHaveBeenCalledWith('throwFailures', false);
|
||||
expect(navigateHandler).toHaveBeenCalledWith(
|
||||
'oneFailurePerSpec',
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('UI for hiding disabled specs', function() {
|
||||
@@ -1047,7 +1172,7 @@ describe('HtmlReporter', function() {
|
||||
var seedBar = container.querySelector('.jasmine-seed-bar');
|
||||
expect(seedBar.textContent).toBe(', randomized with seed 424242');
|
||||
var seedLink = container.querySelector('.jasmine-seed-bar a');
|
||||
expect(seedLink.getAttribute('href')).toBe('?seed=424242');
|
||||
expect(seedLink.getAttribute('href')).toBe('/?seed=424242');
|
||||
});
|
||||
|
||||
it('should not show the current seed bar if not randomizing', function() {
|
||||
@@ -1096,7 +1221,7 @@ describe('HtmlReporter', function() {
|
||||
reporter.jasmineDone({ order: { random: true } });
|
||||
|
||||
var skippedLink = container.querySelector('.jasmine-skipped a');
|
||||
expect(skippedLink.getAttribute('href')).toEqual('?foo=bar&spec=');
|
||||
expect(skippedLink.getAttribute('href')).toEqual('/?foo=bar&spec=');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ describe('npm package', function() {
|
||||
});
|
||||
|
||||
it('has bootFiles', function() {
|
||||
expect(this.packagedCore.files.bootFiles).toEqual(['boot.js']);
|
||||
expect(this.packagedCore.files.bootFiles).toEqual(['boot0.js', 'boot1.js']);
|
||||
expect(this.packagedCore.files.nodeBootFiles).toEqual(['node_boot.js']);
|
||||
|
||||
var packagedCore = this.packagedCore;
|
||||
@@ -83,6 +83,10 @@ describe('npm package', function() {
|
||||
expect(fileName).toExistInPath(packagedCore.files.bootDir);
|
||||
});
|
||||
|
||||
// For backwards compatibility, boot.js should be packaged even though
|
||||
// it is no longer in bootFiles.
|
||||
expect('boot.js').toExistInPath(packagedCore.files.bootDir);
|
||||
|
||||
var packagedCore = this.packagedCore;
|
||||
this.packagedCore.files.nodeBootFiles.forEach(function(fileName) {
|
||||
expect(fileName).toExistInPath(packagedCore.files.bootDir);
|
||||
@@ -99,4 +103,65 @@ describe('npm package', function() {
|
||||
expect(images).toContain('jasmine-horizontal.svg');
|
||||
expect(images).toContain('jasmine_favicon.png');
|
||||
});
|
||||
|
||||
it('does not have CI config files and scripts', function() {
|
||||
expect(fs.existsSync(path.resolve(this.tmpDir, 'package/.circleci'))).toBe(
|
||||
false
|
||||
);
|
||||
expect(fs.existsSync(path.resolve(this.tmpDir, 'package/scripts'))).toBe(
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
it('does not have any unexpected files in the root directory', function() {
|
||||
var files = fs.readdirSync(this.tmpDir);
|
||||
expect(files).toEqual(['package']);
|
||||
});
|
||||
|
||||
it('does not have any unexpected files in the package directory', function() {
|
||||
var files = fs.readdirSync(path.resolve(this.tmpDir, 'package'));
|
||||
files.sort();
|
||||
expect(files).toEqual([
|
||||
'MIT.LICENSE',
|
||||
'README.md',
|
||||
'images',
|
||||
'lib',
|
||||
'package.json'
|
||||
]);
|
||||
});
|
||||
|
||||
it('only has images in the images dir', function() {
|
||||
var files = fs.readdirSync(path.resolve(this.tmpDir, 'package/images')),
|
||||
i;
|
||||
|
||||
for (i = 0; i < files.length; i++) {
|
||||
expect(files[i]).toMatch(/\.(svg|png)$/);
|
||||
}
|
||||
});
|
||||
|
||||
it('only has JS and CSS files in the lib dir', function() {
|
||||
var files = [],
|
||||
i;
|
||||
|
||||
function getFiles(dir) {
|
||||
var dirents = fs.readdirSync(dir, { withFileTypes: true }),
|
||||
j;
|
||||
|
||||
for (j = 0; j < dirents.length; j++) {
|
||||
dirent = dirents[j];
|
||||
|
||||
if (dirent.isDirectory()) {
|
||||
getFiles(path.resolve(dir, dirent.name));
|
||||
} else {
|
||||
files.push(path.resolve(dir, dirent.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getFiles(path.resolve(this.tmpDir, 'package/lib'));
|
||||
|
||||
for (i = 0; i < files.length; i++) {
|
||||
expect(files[i]).toMatch(/\.(js|css)$/);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,16 +20,17 @@ module.exports = {
|
||||
'helpers/asyncAwait.js',
|
||||
'helpers/generator.js',
|
||||
'helpers/BrowserFlags.js',
|
||||
'helpers/checkForArrayBuffer.js',
|
||||
'helpers/checkForMap.js',
|
||||
'helpers/checkForProxy.js',
|
||||
'helpers/checkForSet.js',
|
||||
'helpers/checkForSymbol.js',
|
||||
'helpers/checkForTypedArrays.js',
|
||||
'helpers/checkForUrl.js',
|
||||
'helpers/domHelpers.js',
|
||||
'helpers/integrationMatchers.js',
|
||||
'helpers/promises.js',
|
||||
'helpers/requireFastCheck.js',
|
||||
'helpers/defineJasmineUnderTest.js'
|
||||
'helpers/defineJasmineUnderTest.js',
|
||||
'helpers/resetEnv.js'
|
||||
],
|
||||
random: true,
|
||||
browser: {
|
||||
@@ -41,11 +42,13 @@ module.exports = {
|
||||
browserVersion: process.env.SAUCE_BROWSER_VERSION,
|
||||
build: `Core ${process.env.TRAVIS_BUILD_NUMBER || 'Ran locally'}`,
|
||||
tags: ['Jasmine-Core'],
|
||||
tunnelIdentifier: process.env.TRAVIS_JOB_NUMBER
|
||||
? process.env.TRAVIS_JOB_NUMBER.toString()
|
||||
: null,
|
||||
tunnelIdentifier: process.env.SAUCE_TUNNEL_IDENTIFIER,
|
||||
username: process.env.SAUCE_USERNAME,
|
||||
accessKey: process.env.SAUCE_ACCESS_KEY
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (process.env.SKIP_JASMINE_BROWSER_FLAKES === 'true') {
|
||||
module.exports.helpers.push('helpers/disableBrowserFlakes.js');
|
||||
}
|
||||
|
||||
@@ -7,16 +7,18 @@
|
||||
"helpers": [
|
||||
"helpers/asyncAwait.js",
|
||||
"helpers/generator.js",
|
||||
"helpers/checkForArrayBuffer.js",
|
||||
"helpers/checkForMap.js",
|
||||
"helpers/checkForProxy.js",
|
||||
"helpers/checkForSet.js",
|
||||
"helpers/checkForSymbol.js",
|
||||
"helpers/checkForTypedArrays.js",
|
||||
"helpers/checkForUrl.js",
|
||||
"helpers/domHelpers.js",
|
||||
"helpers/integrationMatchers.js",
|
||||
"helpers/promises.js",
|
||||
"helpers/requireFastCheck.js",
|
||||
"helpers/nodeDefineJasmineUnderTest.js"
|
||||
"helpers/overrideConsoleLogForCircleCi.js",
|
||||
"helpers/nodeDefineJasmineUnderTest.js",
|
||||
"helpers/resetEnv.js"
|
||||
],
|
||||
"random": true
|
||||
}
|
||||
|
||||
@@ -49,6 +49,19 @@ getJasmineRequireObj().CallTracker = function(j$) {
|
||||
return call ? call.args : [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the "this" object that was passed to a specific invocation of this spy.
|
||||
* @name Spy#calls#thisFor
|
||||
* @since 3.8.0
|
||||
* @function
|
||||
* @param {Integer} index The 0-based invocation index.
|
||||
* @return {Object?}
|
||||
*/
|
||||
this.thisFor = function(index) {
|
||||
var call = calls[index];
|
||||
return call ? call.object : undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the raw calls array for this spy.
|
||||
* @name Spy#calls#all
|
||||
|
||||
@@ -6,9 +6,12 @@ getJasmineRequireObj().Clock = function() {
|
||||
typeof process.versions.node === 'string';
|
||||
|
||||
/**
|
||||
* _Note:_ Do not construct this directly, Jasmine will make one during booting. You can get the current clock with {@link jasmine.clock}.
|
||||
* @class Clock
|
||||
* @classdesc Jasmine's mock clock is used when testing time dependent code.
|
||||
* @since 1.3.0
|
||||
* @classdesc Jasmine's mock clock is used when testing time dependent code.<br>
|
||||
* _Note:_ Do not construct this directly. You can get the current clock with
|
||||
* {@link jasmine.clock}.
|
||||
* @hideconstructor
|
||||
*/
|
||||
function Clock(global, delayedFunctionSchedulerFactory, mockDate) {
|
||||
var self = this,
|
||||
|
||||
@@ -6,13 +6,31 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
|
||||
var currentTime = 0;
|
||||
var delayedFnCount = 0;
|
||||
var deletedKeys = [];
|
||||
var ticking = false;
|
||||
|
||||
self.tick = function(millis, tickDate) {
|
||||
millis = millis || 0;
|
||||
var endTime = currentTime + millis;
|
||||
if (ticking) {
|
||||
j$.getEnv().deprecated(
|
||||
'The behavior of reentrant calls to jasmine.clock().tick() will ' +
|
||||
'change in a future version. Either modify the affected spec to ' +
|
||||
'not call tick() from within a setTimeout or setInterval handler, ' +
|
||||
'or be aware that it may behave differently in the future. See ' +
|
||||
'<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-reentrant-calls-to-jasmine-clock-tick> ' +
|
||||
'for details.'
|
||||
);
|
||||
}
|
||||
|
||||
runScheduledFunctions(endTime, tickDate);
|
||||
currentTime = endTime;
|
||||
ticking = true;
|
||||
|
||||
try {
|
||||
millis = millis || 0;
|
||||
var endTime = currentTime + millis;
|
||||
|
||||
runScheduledFunctions(endTime, tickDate);
|
||||
currentTime = endTime;
|
||||
} finally {
|
||||
ticking = false;
|
||||
}
|
||||
};
|
||||
|
||||
self.scheduleFunction = function(
|
||||
|
||||
90
src/core/Deprecator.js
Normal file
90
src/core/Deprecator.js
Normal file
@@ -0,0 +1,90 @@
|
||||
getJasmineRequireObj().Deprecator = function(j$) {
|
||||
function Deprecator(topSuite) {
|
||||
this.topSuite_ = topSuite;
|
||||
this.verbose_ = false;
|
||||
this.toSuppress_ = [];
|
||||
}
|
||||
|
||||
var verboseNote =
|
||||
'Note: This message will be shown only once. Set the verboseDeprecations ' +
|
||||
'config property to true to see every occurrence.';
|
||||
|
||||
Deprecator.prototype.verboseDeprecations = function(enabled) {
|
||||
this.verbose_ = enabled;
|
||||
};
|
||||
|
||||
// runnable is a spec or a suite.
|
||||
// deprecation is a string or an Error.
|
||||
// See Env#deprecated for a description of the options argument.
|
||||
Deprecator.prototype.addDeprecationWarning = function(
|
||||
runnable,
|
||||
deprecation,
|
||||
options
|
||||
) {
|
||||
options = options || {};
|
||||
|
||||
if (!this.verbose_ && !j$.isError_(deprecation)) {
|
||||
if (this.toSuppress_.indexOf(deprecation) !== -1) {
|
||||
return;
|
||||
}
|
||||
this.toSuppress_.push(deprecation);
|
||||
}
|
||||
|
||||
this.log_(runnable, deprecation, options);
|
||||
this.report_(runnable, deprecation, options);
|
||||
};
|
||||
|
||||
Deprecator.prototype.log_ = function(runnable, deprecation, options) {
|
||||
var context;
|
||||
|
||||
if (j$.isError_(deprecation)) {
|
||||
console.error(deprecation);
|
||||
return;
|
||||
}
|
||||
|
||||
if (runnable === this.topSuite_ || options.ignoreRunnable) {
|
||||
context = '';
|
||||
} else if (runnable.children) {
|
||||
context = ' (in suite: ' + runnable.getFullName() + ')';
|
||||
} else {
|
||||
context = ' (in spec: ' + runnable.getFullName() + ')';
|
||||
}
|
||||
|
||||
if (!options.omitStackTrace) {
|
||||
context += '\n' + this.stackTrace_();
|
||||
}
|
||||
|
||||
if (!this.verbose_) {
|
||||
context += '\n' + verboseNote;
|
||||
}
|
||||
|
||||
console.error('DEPRECATION: ' + deprecation + context);
|
||||
};
|
||||
|
||||
Deprecator.prototype.stackTrace_ = function() {
|
||||
var formatter = new j$.ExceptionFormatter();
|
||||
return formatter.stack(j$.util.errorWithStack()).replace(/^Error\n/m, '');
|
||||
};
|
||||
|
||||
Deprecator.prototype.report_ = function(runnable, deprecation, options) {
|
||||
if (options.ignoreRunnable) {
|
||||
runnable = this.topSuite_;
|
||||
}
|
||||
|
||||
if (j$.isError_(deprecation)) {
|
||||
runnable.addDeprecationWarning(deprecation);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.verbose_) {
|
||||
deprecation += '\n' + verboseNote;
|
||||
}
|
||||
|
||||
runnable.addDeprecationWarning({
|
||||
message: deprecation,
|
||||
omitStackTrace: options.omitStackTrace || false
|
||||
});
|
||||
};
|
||||
|
||||
return Deprecator;
|
||||
};
|
||||
585
src/core/Env.js
585
src/core/Env.js
@@ -1,10 +1,11 @@
|
||||
getJasmineRequireObj().Env = function(j$) {
|
||||
/**
|
||||
* _Note:_ Do not construct this directly, Jasmine will make one during booting.
|
||||
* @name Env
|
||||
* @class Env
|
||||
* @since 2.0.0
|
||||
* @classdesc The Jasmine environment
|
||||
* @constructor
|
||||
* @classdesc The Jasmine environment.<br>
|
||||
* _Note:_ Do not construct this directly. You can obtain the Env instance by
|
||||
* calling {@link jasmine.getEnv}.
|
||||
* @hideconstructor
|
||||
*/
|
||||
function Env(options) {
|
||||
options = options || {};
|
||||
@@ -35,7 +36,8 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
|
||||
/**
|
||||
* This represents the available options to configure Jasmine.
|
||||
* Options that are not provided will use their default values
|
||||
* Options that are not provided will use their default values.
|
||||
* @see Env#configure
|
||||
* @interface Configuration
|
||||
* @since 3.3.0
|
||||
*/
|
||||
@@ -53,7 +55,7 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
* Null causes the seed to be determined randomly at the start of execution.
|
||||
* @name Configuration#seed
|
||||
* @since 3.3.0
|
||||
* @type function
|
||||
* @type (number|string)
|
||||
* @default null
|
||||
*/
|
||||
seed: null,
|
||||
@@ -63,8 +65,17 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
* @since 3.3.0
|
||||
* @type Boolean
|
||||
* @default false
|
||||
* @deprecated Use the `stopOnSpecFailure` config property instead.
|
||||
*/
|
||||
failFast: false,
|
||||
/**
|
||||
* Whether to stop execution of the suite after the first spec failure
|
||||
* @name Configuration#stopOnSpecFailure
|
||||
* @since 3.9.0
|
||||
* @type Boolean
|
||||
* @default false
|
||||
*/
|
||||
stopOnSpecFailure: false,
|
||||
/**
|
||||
* Whether to fail the spec if it ran no expectations. By default
|
||||
* a spec that ran no expectations is reported as passed. Setting this
|
||||
@@ -81,14 +92,30 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
* @since 3.3.0
|
||||
* @type Boolean
|
||||
* @default false
|
||||
* @deprecated Use the `stopSpecOnExpectationFailure` config property instead.
|
||||
*/
|
||||
oneFailurePerSpec: false,
|
||||
/**
|
||||
* Whether to cause specs to only have one expectation failure.
|
||||
* @name Configuration#stopSpecOnExpectationFailure
|
||||
* @since 3.3.0
|
||||
* @type Boolean
|
||||
* @default false
|
||||
*/
|
||||
stopSpecOnExpectationFailure: false,
|
||||
/**
|
||||
* A function that takes a spec and returns true if it should be executed
|
||||
* or false if it should be skipped.
|
||||
* @callback SpecFilter
|
||||
* @param {Spec} spec - The spec that the filter is being applied to.
|
||||
* @return boolean
|
||||
*/
|
||||
/**
|
||||
* Function to use to filter specs
|
||||
* @name Configuration#specFilter
|
||||
* @since 3.3.0
|
||||
* @type function
|
||||
* @default true
|
||||
* @type SpecFilter
|
||||
* @default A function that always returns true.
|
||||
*/
|
||||
specFilter: function() {
|
||||
return true;
|
||||
@@ -110,8 +137,31 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
* @since 3.5.0
|
||||
* @type function
|
||||
* @default undefined
|
||||
* @deprecated In a future version, Jasmine will ignore the Promise config
|
||||
* property and always create native promises instead.
|
||||
*/
|
||||
Promise: undefined
|
||||
Promise: undefined,
|
||||
/**
|
||||
* Clean closures when a suite is done running (done by clearing the stored function reference).
|
||||
* This prevents memory leaks, but you won't be able to run jasmine multiple times.
|
||||
* @name Configuration#autoCleanClosures
|
||||
* @since 3.10.0
|
||||
* @type boolean
|
||||
* @default true
|
||||
*/
|
||||
autoCleanClosures: true,
|
||||
/**
|
||||
* Whether or not to issue warnings for certain deprecated functionality
|
||||
* every time it's used. If not set or set to false, deprecation warnings
|
||||
* for methods that tend to be called frequently will be issued only once
|
||||
* or otherwise throttled to to prevent the suite output from being flooded
|
||||
* with warnings.
|
||||
* @name Configuration#verboseDeprecations
|
||||
* @since 3.6.0
|
||||
* @type Boolean
|
||||
* @default false
|
||||
*/
|
||||
verboseDeprecations: false
|
||||
};
|
||||
|
||||
var currentSuite = function() {
|
||||
@@ -161,35 +211,91 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
* @function
|
||||
*/
|
||||
this.configure = function(configuration) {
|
||||
var booleanProps = [
|
||||
'random',
|
||||
'failSpecWithNoExpectations',
|
||||
'hideDisabled',
|
||||
'autoCleanClosures'
|
||||
];
|
||||
|
||||
booleanProps.forEach(function(prop) {
|
||||
if (typeof configuration[prop] !== 'undefined') {
|
||||
config[prop] = !!configuration[prop];
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof configuration.failFast !== 'undefined') {
|
||||
// We can't unconditionally issue a warning here because then users who
|
||||
// get the configuration from Jasmine, modify it, and pass it back would
|
||||
// see the warning.
|
||||
if (configuration.failFast !== config.failFast) {
|
||||
this.deprecated(
|
||||
'The `failFast` config property is deprecated and will be removed ' +
|
||||
'in a future version of Jasmine. Please use `stopOnSpecFailure` ' +
|
||||
'instead.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof configuration.stopOnSpecFailure !== 'undefined') {
|
||||
if (configuration.stopOnSpecFailure !== configuration.failFast) {
|
||||
throw new Error(
|
||||
'stopOnSpecFailure and failFast are aliases for ' +
|
||||
"each other. Don't set failFast if you also set stopOnSpecFailure."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
config.failFast = configuration.failFast;
|
||||
config.stopOnSpecFailure = configuration.failFast;
|
||||
} else if (typeof configuration.stopOnSpecFailure !== 'undefined') {
|
||||
config.failFast = configuration.stopOnSpecFailure;
|
||||
config.stopOnSpecFailure = configuration.stopOnSpecFailure;
|
||||
}
|
||||
|
||||
if (typeof configuration.oneFailurePerSpec !== 'undefined') {
|
||||
// We can't unconditionally issue a warning here because then users who
|
||||
// get the configuration from Jasmine, modify it, and pass it back would
|
||||
// see the warning.
|
||||
if (configuration.oneFailurePerSpec !== config.oneFailurePerSpec) {
|
||||
this.deprecated(
|
||||
'The `oneFailurePerSpec` config property is deprecated and will be ' +
|
||||
'removed in a future version of Jasmine. Please use ' +
|
||||
'`stopSpecOnExpectationFailure` instead.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof configuration.stopSpecOnExpectationFailure !== 'undefined') {
|
||||
if (
|
||||
configuration.stopSpecOnExpectationFailure !==
|
||||
configuration.oneFailurePerSpec
|
||||
) {
|
||||
throw new Error(
|
||||
'stopSpecOnExpectationFailure and oneFailurePerSpec are aliases for ' +
|
||||
"each other. Don't set oneFailurePerSpec if you also set stopSpecOnExpectationFailure."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
config.oneFailurePerSpec = configuration.oneFailurePerSpec;
|
||||
config.stopSpecOnExpectationFailure = configuration.oneFailurePerSpec;
|
||||
} else if (
|
||||
typeof configuration.stopSpecOnExpectationFailure !== 'undefined'
|
||||
) {
|
||||
config.oneFailurePerSpec = configuration.stopSpecOnExpectationFailure;
|
||||
config.stopSpecOnExpectationFailure =
|
||||
configuration.stopSpecOnExpectationFailure;
|
||||
}
|
||||
|
||||
if (configuration.specFilter) {
|
||||
config.specFilter = configuration.specFilter;
|
||||
}
|
||||
|
||||
if (configuration.hasOwnProperty('random')) {
|
||||
config.random = !!configuration.random;
|
||||
}
|
||||
|
||||
if (configuration.hasOwnProperty('seed')) {
|
||||
if (typeof configuration.seed !== 'undefined') {
|
||||
config.seed = configuration.seed;
|
||||
}
|
||||
|
||||
if (configuration.hasOwnProperty('failFast')) {
|
||||
config.failFast = configuration.failFast;
|
||||
}
|
||||
|
||||
if (configuration.hasOwnProperty('failSpecWithNoExpectations')) {
|
||||
config.failSpecWithNoExpectations =
|
||||
configuration.failSpecWithNoExpectations;
|
||||
}
|
||||
|
||||
if (configuration.hasOwnProperty('oneFailurePerSpec')) {
|
||||
config.oneFailurePerSpec = configuration.oneFailurePerSpec;
|
||||
}
|
||||
|
||||
if (configuration.hasOwnProperty('hideDisabled')) {
|
||||
config.hideDisabled = configuration.hideDisabled;
|
||||
}
|
||||
|
||||
// Don't use hasOwnProperty to check for Promise existence because Promise
|
||||
// can be initialized to undefined, either explicitly or by using the
|
||||
// object returned from Env#configuration. In particular, Karma does this.
|
||||
@@ -199,12 +305,22 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
typeof configuration.Promise.reject === 'function'
|
||||
) {
|
||||
customPromise = configuration.Promise;
|
||||
self.deprecated(
|
||||
'The `Promise` config property is deprecated. Future versions ' +
|
||||
'of Jasmine will create native promises even if the `Promise` ' +
|
||||
'config property is set. Please remove it.'
|
||||
);
|
||||
} else {
|
||||
throw new Error(
|
||||
'Custom promise library missing `resolve`/`reject` functions'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (configuration.hasOwnProperty('verboseDeprecations')) {
|
||||
config.verboseDeprecations = configuration.verboseDeprecations;
|
||||
deprecator.verboseDeprecations(config.verboseDeprecations);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -225,13 +341,19 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
Object.defineProperty(this, 'specFilter', {
|
||||
get: function() {
|
||||
self.deprecated(
|
||||
'Getting specFilter directly from Env is deprecated and will be removed in a future version of Jasmine, please check the specFilter option from `configuration`'
|
||||
'Getting specFilter directly from Env is deprecated and will be ' +
|
||||
'removed in a future version of Jasmine. Please check the ' +
|
||||
'specFilter option from `configuration` instead.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
return config.specFilter;
|
||||
},
|
||||
set: function(val) {
|
||||
self.deprecated(
|
||||
'Setting specFilter directly on Env is deprecated and will be removed in a future version of Jasmine, please use the specFilter option in `configure`'
|
||||
'Setting specFilter directly on Env is deprecated and will be ' +
|
||||
'removed in a future version of Jasmine. Please use the ' +
|
||||
'specFilter option in `configure` instead.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
config.specFilter = val;
|
||||
}
|
||||
@@ -278,6 +400,17 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
runnableResources[currentRunnable().id].customMatchers;
|
||||
|
||||
for (var matcherName in matchersToAdd) {
|
||||
if (matchersToAdd[matcherName].length > 1) {
|
||||
self.deprecated(
|
||||
'The matcher factory for "' +
|
||||
matcherName +
|
||||
'" ' +
|
||||
'accepts custom equality testers, but this parameter will no longer be ' +
|
||||
'passed in a future release. ' +
|
||||
'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
|
||||
);
|
||||
}
|
||||
|
||||
customMatchers[matcherName] = matchersToAdd[matcherName];
|
||||
}
|
||||
};
|
||||
@@ -292,6 +425,17 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
runnableResources[currentRunnable().id].customAsyncMatchers;
|
||||
|
||||
for (var matcherName in matchersToAdd) {
|
||||
if (matchersToAdd[matcherName].length > 1) {
|
||||
self.deprecated(
|
||||
'The matcher factory for "' +
|
||||
matcherName +
|
||||
'" ' +
|
||||
'accepts custom equality testers, but this parameter will no longer be ' +
|
||||
'passed in a future release. ' +
|
||||
'See <https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#matchers-cet> for details.'
|
||||
);
|
||||
}
|
||||
|
||||
customAsyncMatchers[matcherName] = matchersToAdd[matcherName];
|
||||
}
|
||||
};
|
||||
@@ -374,7 +518,9 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
}
|
||||
|
||||
delayedExpectationResult.message +=
|
||||
'Did you forget to return or await the result of expectAsync?';
|
||||
'1. Did you forget to return or await the result of expectAsync?\n' +
|
||||
'2. Was done() invoked before an async operation completed?\n' +
|
||||
'3. Did an expectation follow a call to done()?';
|
||||
|
||||
topSuite.result.failedExpectations.push(delayedExpectationResult);
|
||||
}
|
||||
@@ -439,10 +585,11 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
delete runnableResources[id];
|
||||
};
|
||||
|
||||
var beforeAndAfterFns = function(suite) {
|
||||
var beforeAndAfterFns = function(targetSuite) {
|
||||
return function() {
|
||||
var befores = [],
|
||||
afters = [];
|
||||
afters = [],
|
||||
suite = targetSuite;
|
||||
|
||||
while (suite) {
|
||||
befores = befores.concat(suite.beforeFns);
|
||||
@@ -485,18 +632,24 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
* @since 2.3.0
|
||||
* @function
|
||||
* @param {Boolean} value Whether to throw when a expectation fails
|
||||
* @deprecated Use the `oneFailurePerSpec` option with {@link Env#configure}
|
||||
* @deprecated Use the `stopSpecOnExpectationFailure` option with {@link Env#configure}
|
||||
*/
|
||||
this.throwOnExpectationFailure = function(value) {
|
||||
this.deprecated(
|
||||
'Setting throwOnExpectationFailure directly on Env is deprecated and will be removed in a future version of Jasmine, please use the oneFailurePerSpec option in `configure`'
|
||||
'Setting throwOnExpectationFailure directly on Env is deprecated and ' +
|
||||
'will be removed in a future version of Jasmine. Please use the ' +
|
||||
'stopSpecOnExpectationFailure option in `configure`.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
this.configure({ oneFailurePerSpec: !!value });
|
||||
};
|
||||
|
||||
this.throwingExpectationFailures = function() {
|
||||
this.deprecated(
|
||||
'Getting throwingExpectationFailures directly from Env is deprecated and will be removed in a future version of Jasmine, please check the oneFailurePerSpec option from `configuration`'
|
||||
'Getting throwingExpectationFailures directly from Env is deprecated ' +
|
||||
'and will be removed in a future version of Jasmine. Please check ' +
|
||||
'the stopSpecOnExpectationFailure option from `configuration`.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
return config.oneFailurePerSpec;
|
||||
};
|
||||
@@ -507,18 +660,24 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
* @since 2.7.0
|
||||
* @function
|
||||
* @param {Boolean} value Whether to stop suite execution when a spec fails
|
||||
* @deprecated Use the `failFast` option with {@link Env#configure}
|
||||
* @deprecated Use the `stopOnSpecFailure` option with {@link Env#configure}
|
||||
*/
|
||||
this.stopOnSpecFailure = function(value) {
|
||||
this.deprecated(
|
||||
'Setting stopOnSpecFailure directly is deprecated and will be removed in a future version of Jasmine, please use the failFast option in `configure`'
|
||||
'Setting stopOnSpecFailure directly is deprecated and will be ' +
|
||||
'removed in a future version of Jasmine. Please use the ' +
|
||||
'stopOnSpecFailure option in `configure`.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
this.configure({ failFast: !!value });
|
||||
this.configure({ stopOnSpecFailure: !!value });
|
||||
};
|
||||
|
||||
this.stoppingOnSpecFailure = function() {
|
||||
this.deprecated(
|
||||
'Getting stoppingOnSpecFailure directly from Env is deprecated and will be removed in a future version of Jasmine, please check the failFast option from `configuration`'
|
||||
'Getting stoppingOnSpecFailure directly from Env is deprecated and ' +
|
||||
'will be removed in a future version of Jasmine. Please check the ' +
|
||||
'stopOnSpecFailure option from `configuration`.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
return config.failFast;
|
||||
};
|
||||
@@ -533,14 +692,20 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
*/
|
||||
this.randomizeTests = function(value) {
|
||||
this.deprecated(
|
||||
'Setting randomizeTests directly is deprecated and will be removed in a future version of Jasmine, please use the random option in `configure`'
|
||||
'Setting randomizeTests directly is deprecated and will be removed ' +
|
||||
'in a future version of Jasmine. Please use the random option in ' +
|
||||
'`configure` instead.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
config.random = !!value;
|
||||
};
|
||||
|
||||
this.randomTests = function() {
|
||||
this.deprecated(
|
||||
'Getting randomTests directly from Env is deprecated and will be removed in a future version of Jasmine, please check the random option from `configuration`'
|
||||
'Getting randomTests directly from Env is deprecated and will be ' +
|
||||
'removed in a future version of Jasmine. Please check the random ' +
|
||||
'option from `configuration` instead.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
return config.random;
|
||||
};
|
||||
@@ -555,7 +720,10 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
*/
|
||||
this.seed = function(value) {
|
||||
this.deprecated(
|
||||
'Setting seed directly is deprecated and will be removed in a future version of Jasmine, please use the seed option in `configure`'
|
||||
'Setting seed directly is deprecated and will be removed in a ' +
|
||||
'future version of Jasmine. Please use the seed option in ' +
|
||||
'`configure` instead.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
if (value) {
|
||||
config.seed = value;
|
||||
@@ -565,7 +733,10 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
|
||||
this.hidingDisabled = function(value) {
|
||||
this.deprecated(
|
||||
'Getting hidingDisabled directly from Env is deprecated and will be removed in a future version of Jasmine, please check the hideDisabled option from `configuration`'
|
||||
'Getting hidingDisabled directly from Env is deprecated and will ' +
|
||||
'be removed in a future version of Jasmine. Please check the ' +
|
||||
'hideDisabled option from `configuration` instead.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
return config.hideDisabled;
|
||||
};
|
||||
@@ -574,41 +745,51 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
* @name Env#hideDisabled
|
||||
* @since 3.2.0
|
||||
* @function
|
||||
* @deprecated Use the `hideDisabled` option with {@link Env#configure}
|
||||
*/
|
||||
this.hideDisabled = function(value) {
|
||||
this.deprecated(
|
||||
'Setting hideDisabled directly is deprecated and will be removed in a future version of Jasmine, please use the hideDisabled option in `configure`'
|
||||
'Setting hideDisabled directly is deprecated and will be removed ' +
|
||||
'in a future version of Jasmine. Please use the hideDisabled option ' +
|
||||
'in `configure` instead.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
config.hideDisabled = !!value;
|
||||
};
|
||||
|
||||
this.deprecated = function(deprecation) {
|
||||
/**
|
||||
* Causes a deprecation warning to be logged to the console and reported to
|
||||
* reporters.
|
||||
*
|
||||
* The optional second parameter is an object that can have either of the
|
||||
* following properties:
|
||||
*
|
||||
* omitStackTrace: Whether to omit the stack trace. Optional. Defaults to
|
||||
* false. This option is ignored if the deprecation is an Error. Set this
|
||||
* when the stack trace will not contain anything that helps the user find
|
||||
* the source of the deprecation.
|
||||
*
|
||||
* ignoreRunnable: Whether to log the deprecation on the root suite, ignoring
|
||||
* the spec or suite that's running when it happens. Optional. Defaults to
|
||||
* false.
|
||||
*
|
||||
* @name Env#deprecated
|
||||
* @since 2.99
|
||||
* @function
|
||||
* @param {String|Error} deprecation The deprecation message
|
||||
* @param {Object} [options] Optional extra options, as described above
|
||||
*/
|
||||
this.deprecated = function(deprecation, options) {
|
||||
var runnable = currentRunnable() || topSuite;
|
||||
var context;
|
||||
|
||||
if (runnable === topSuite) {
|
||||
context = '';
|
||||
} else if (runnable === currentSuite()) {
|
||||
context = ' (in suite: ' + runnable.getFullName() + ')';
|
||||
} else {
|
||||
context = ' (in spec: ' + runnable.getFullName() + ')';
|
||||
}
|
||||
|
||||
runnable.addDeprecationWarning(deprecation);
|
||||
if (
|
||||
typeof console !== 'undefined' &&
|
||||
typeof console.error === 'function'
|
||||
) {
|
||||
console.error('DEPRECATION: ' + deprecation + context);
|
||||
}
|
||||
deprecator.addDeprecationWarning(runnable, deprecation, options);
|
||||
};
|
||||
|
||||
var queueRunnerFactory = function(options, args) {
|
||||
var failFast = false;
|
||||
if (options.isLeaf) {
|
||||
failFast = config.oneFailurePerSpec;
|
||||
failFast = config.stopSpecOnExpectationFailure;
|
||||
} else if (!options.isReporter) {
|
||||
failFast = config.failFast;
|
||||
failFast = config.stopOnSpecFailure;
|
||||
}
|
||||
options.clearStack = options.clearStack || clearStack;
|
||||
options.timeout = {
|
||||
@@ -634,13 +815,22 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
description: 'Jasmine__TopLevel__Suite',
|
||||
expectationFactory: expectationFactory,
|
||||
asyncExpectationFactory: suiteAsyncExpectationFactory,
|
||||
expectationResultFactory: expectationResultFactory
|
||||
expectationResultFactory: expectationResultFactory,
|
||||
autoCleanClosures: config.autoCleanClosures
|
||||
});
|
||||
defaultResourcesForRunnable(topSuite.id);
|
||||
var deprecator = new j$.Deprecator(topSuite);
|
||||
currentDeclarationSuite = topSuite;
|
||||
|
||||
/**
|
||||
* Provides the root suite, through which all suites and specs can be
|
||||
* accessed.
|
||||
* @function
|
||||
* @name Env#topSuite
|
||||
* @return {Suite} the root suite
|
||||
* @since 2.0.0
|
||||
*/
|
||||
this.topSuite = function() {
|
||||
return topSuite;
|
||||
return j$.deprecatingSuiteProxy(topSuite, null, this);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -715,11 +905,43 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
*/
|
||||
'specDone'
|
||||
],
|
||||
queueRunnerFactory
|
||||
queueRunnerFactory,
|
||||
self.deprecated
|
||||
);
|
||||
|
||||
// Both params are optional.
|
||||
/**
|
||||
* Executes the specs.
|
||||
*
|
||||
* If called with no parameters or with a falsy value as the first parameter,
|
||||
* all specs will be executed except those that are excluded by a
|
||||
* [spec filter]{@link Configuration#specFilter} or other mechanism. If the
|
||||
* first parameter is a list of spec/suite IDs, only those specs/suites will
|
||||
* be run.
|
||||
*
|
||||
* Both parameters are optional, but a completion callback is only valid as
|
||||
* the second parameter. To specify a completion callback but not a list of
|
||||
* specs/suites to run, pass null or undefined as the first parameter.
|
||||
*
|
||||
* execute should not be called more than once.
|
||||
*
|
||||
* If the environment supports promises, execute will return a promise that
|
||||
* is resolved after the suite finishes executing. The promise will be
|
||||
* resolved (not rejected) as long as the suite runs to completion. Use a
|
||||
* {@link Reporter} to determine whether or not the suite passed.
|
||||
*
|
||||
* @name Env#execute
|
||||
* @since 2.0.0
|
||||
* @function
|
||||
* @param {(string[])=} runnablesToRun IDs of suites and/or specs to run
|
||||
* @param {Function=} onComplete Function that will be called after all specs have run
|
||||
* @return {Promise<undefined>}
|
||||
*/
|
||||
this.execute = function(runnablesToRun, onComplete) {
|
||||
if (this._executedBefore) {
|
||||
topSuite.reset();
|
||||
}
|
||||
this._executedBefore = true;
|
||||
defaultResourcesForRunnable(topSuite.id);
|
||||
installGlobalErrors();
|
||||
|
||||
if (!runnablesToRun) {
|
||||
@@ -777,65 +999,88 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
var jasmineTimer = new j$.Timer();
|
||||
jasmineTimer.start();
|
||||
|
||||
/**
|
||||
* Information passed to the {@link Reporter#jasmineStarted} event.
|
||||
* @typedef JasmineStartedInfo
|
||||
* @property {Int} totalSpecsDefined - The total number of specs defined in this suite.
|
||||
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
|
||||
*/
|
||||
reporter.jasmineStarted(
|
||||
{
|
||||
totalSpecsDefined: totalSpecsDefined,
|
||||
order: order
|
||||
},
|
||||
function() {
|
||||
currentlyExecutingSuites.push(topSuite);
|
||||
var Promise = customPromise || global.Promise;
|
||||
|
||||
processor.execute(function() {
|
||||
clearResourcesForRunnable(topSuite.id);
|
||||
currentlyExecutingSuites.pop();
|
||||
var overallStatus, incompleteReason;
|
||||
|
||||
if (hasFailures || topSuite.result.failedExpectations.length > 0) {
|
||||
overallStatus = 'failed';
|
||||
} else if (focusedRunnables.length > 0) {
|
||||
overallStatus = 'incomplete';
|
||||
incompleteReason = 'fit() or fdescribe() was found';
|
||||
} else if (totalSpecsDefined === 0) {
|
||||
overallStatus = 'incomplete';
|
||||
incompleteReason = 'No specs found';
|
||||
} else {
|
||||
overallStatus = 'passed';
|
||||
if (Promise) {
|
||||
return new Promise(function(resolve) {
|
||||
runAll(function() {
|
||||
if (onComplete) {
|
||||
onComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Information passed to the {@link Reporter#jasmineDone} event.
|
||||
* @typedef JasmineDoneInfo
|
||||
* @property {OverallStatus} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'.
|
||||
* @property {Int} totalTime - The total time (in ms) that it took to execute the suite
|
||||
* @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete.
|
||||
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
|
||||
* @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
|
||||
* @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level.
|
||||
*/
|
||||
reporter.jasmineDone(
|
||||
{
|
||||
overallStatus: overallStatus,
|
||||
totalTime: jasmineTimer.elapsed(),
|
||||
incompleteReason: incompleteReason,
|
||||
order: order,
|
||||
failedExpectations: topSuite.result.failedExpectations,
|
||||
deprecationWarnings: topSuite.result.deprecationWarnings
|
||||
},
|
||||
function() {
|
||||
if (onComplete) {
|
||||
onComplete();
|
||||
}
|
||||
}
|
||||
);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
runAll(function() {
|
||||
if (onComplete) {
|
||||
onComplete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function runAll(done) {
|
||||
/**
|
||||
* Information passed to the {@link Reporter#jasmineStarted} event.
|
||||
* @typedef JasmineStartedInfo
|
||||
* @property {Int} totalSpecsDefined - The total number of specs defined in this suite.
|
||||
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
reporter.jasmineStarted(
|
||||
{
|
||||
totalSpecsDefined: totalSpecsDefined,
|
||||
order: order
|
||||
},
|
||||
function() {
|
||||
currentlyExecutingSuites.push(topSuite);
|
||||
|
||||
processor.execute(function() {
|
||||
clearResourcesForRunnable(topSuite.id);
|
||||
currentlyExecutingSuites.pop();
|
||||
var overallStatus, incompleteReason;
|
||||
|
||||
if (
|
||||
hasFailures ||
|
||||
topSuite.result.failedExpectations.length > 0
|
||||
) {
|
||||
overallStatus = 'failed';
|
||||
} else if (focusedRunnables.length > 0) {
|
||||
overallStatus = 'incomplete';
|
||||
incompleteReason = 'fit() or fdescribe() was found';
|
||||
} else if (totalSpecsDefined === 0) {
|
||||
overallStatus = 'incomplete';
|
||||
incompleteReason = 'No specs found';
|
||||
} else {
|
||||
overallStatus = 'passed';
|
||||
}
|
||||
|
||||
/**
|
||||
* Information passed to the {@link Reporter#jasmineDone} event.
|
||||
* @typedef JasmineDoneInfo
|
||||
* @property {OverallStatus} overallStatus - The overall result of the suite: 'passed', 'failed', or 'incomplete'.
|
||||
* @property {Int} totalTime - The total time (in ms) that it took to execute the suite
|
||||
* @property {IncompleteReason} incompleteReason - Explanation of why the suite was incomplete.
|
||||
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
|
||||
* @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
|
||||
* @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level.
|
||||
* @since 2.4.0
|
||||
*/
|
||||
reporter.jasmineDone(
|
||||
{
|
||||
overallStatus: overallStatus,
|
||||
totalTime: jasmineTimer.elapsed(),
|
||||
incompleteReason: incompleteReason,
|
||||
order: order,
|
||||
failedExpectations: topSuite.result.failedExpectations,
|
||||
deprecationWarnings: topSuite.result.deprecationWarnings
|
||||
},
|
||||
done
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -910,6 +1155,15 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Configures whether Jasmine should allow the same function to be spied on
|
||||
* more than once during the execution of a spec. By default, spying on
|
||||
* a function that is already a spy will cause an error.
|
||||
* @name Env#allowRespy
|
||||
* @function
|
||||
* @since 2.5.0
|
||||
* @param {boolean} allow Whether to allow respying
|
||||
*/
|
||||
this.allowRespy = function(allow) {
|
||||
spyRegistry.allowRespy(allow);
|
||||
};
|
||||
@@ -974,7 +1228,8 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
expectationFactory: expectationFactory,
|
||||
asyncExpectationFactory: suiteAsyncExpectationFactory,
|
||||
expectationResultFactory: expectationResultFactory,
|
||||
throwOnExpectationFailure: config.oneFailurePerSpec
|
||||
throwOnExpectationFailure: config.oneFailurePerSpec,
|
||||
autoCleanClosures: config.autoCleanClosures
|
||||
});
|
||||
|
||||
return suite;
|
||||
@@ -987,20 +1242,27 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
if (specDefinitions.length > 0) {
|
||||
throw new Error('describe does not expect any arguments');
|
||||
}
|
||||
if (currentDeclarationSuite.markedPending) {
|
||||
suite.pend();
|
||||
if (currentDeclarationSuite.markedExcluding) {
|
||||
suite.exclude();
|
||||
}
|
||||
addSpecsToSuite(suite, specDefinitions);
|
||||
return suite;
|
||||
if (suite.parentSuite && !suite.children.length) {
|
||||
this.deprecated(
|
||||
'describe with no children (describe() or it()) is ' +
|
||||
'deprecated and will be removed in a future version of Jasmine. ' +
|
||||
'Please either remove the describe or add children to it.'
|
||||
);
|
||||
}
|
||||
return j$.deprecatingSuiteProxy(suite, suite.parentSuite, this);
|
||||
};
|
||||
|
||||
this.xdescribe = function(description, specDefinitions) {
|
||||
ensureIsNotNested('xdescribe');
|
||||
ensureIsFunction(specDefinitions, 'xdescribe');
|
||||
var suite = suiteFactory(description);
|
||||
suite.pend();
|
||||
suite.exclude();
|
||||
addSpecsToSuite(suite, specDefinitions);
|
||||
return suite;
|
||||
return j$.deprecatingSuiteProxy(suite, suite.parentSuite, this);
|
||||
};
|
||||
|
||||
var focusedRunnables = [];
|
||||
@@ -1015,7 +1277,7 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
unfocusAncestor();
|
||||
addSpecsToSuite(suite, specDefinitions);
|
||||
|
||||
return suite;
|
||||
return j$.deprecatingSuiteProxy(suite, suite.parentSuite, this);
|
||||
};
|
||||
|
||||
function addSpecsToSuite(suite, specDefinitions) {
|
||||
@@ -1025,7 +1287,7 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
|
||||
var declarationError = null;
|
||||
try {
|
||||
specDefinitions.call(suite);
|
||||
specDefinitions.call(j$.deprecatingThisProxy(suite, self));
|
||||
} catch (e) {
|
||||
declarationError = e;
|
||||
}
|
||||
@@ -1067,6 +1329,7 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
beforeAndAfterFns: beforeAndAfterFns(suite),
|
||||
expectationFactory: expectationFactory,
|
||||
asyncExpectationFactory: specAsyncExpectationFactory,
|
||||
deprecated: self.deprecated,
|
||||
resultCallback: specResultCallback,
|
||||
getSpecName: function(spec) {
|
||||
return getSpecName(spec, suite);
|
||||
@@ -1083,6 +1346,7 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
timeout: timeout || 0
|
||||
},
|
||||
throwOnExpectationFailure: config.oneFailurePerSpec,
|
||||
autoCleanClosures: config.autoCleanClosures,
|
||||
timer: new j$.Timer()
|
||||
});
|
||||
return spec;
|
||||
@@ -1105,21 +1369,32 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
this.it = function(description, fn, timeout) {
|
||||
this.it_ = function(description, fn, timeout) {
|
||||
ensureIsNotNested('it');
|
||||
// it() sometimes doesn't have a fn argument, so only check the type if
|
||||
// it's given.
|
||||
if (arguments.length > 1 && typeof fn !== 'undefined') {
|
||||
ensureIsFunctionOrAsync(fn, 'it');
|
||||
}
|
||||
|
||||
if (timeout) {
|
||||
j$.util.validateTimeout(timeout);
|
||||
}
|
||||
|
||||
var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
|
||||
if (currentDeclarationSuite.markedPending) {
|
||||
spec.pend();
|
||||
if (currentDeclarationSuite.markedExcluding) {
|
||||
spec.exclude();
|
||||
}
|
||||
currentDeclarationSuite.addChild(spec);
|
||||
|
||||
return spec;
|
||||
};
|
||||
|
||||
this.it = function(description, fn, timeout) {
|
||||
var spec = this.it_(description, fn, timeout);
|
||||
return j$.deprecatingSpecProxy(spec, this);
|
||||
};
|
||||
|
||||
this.xit = function(description, fn, timeout) {
|
||||
ensureIsNotNested('xit');
|
||||
// xit(), like it(), doesn't always have a fn argument, so only check the
|
||||
@@ -1127,19 +1402,23 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
if (arguments.length > 1 && typeof fn !== 'undefined') {
|
||||
ensureIsFunctionOrAsync(fn, 'xit');
|
||||
}
|
||||
var spec = this.it.apply(this, arguments);
|
||||
spec.pend('Temporarily disabled with xit');
|
||||
return spec;
|
||||
var spec = this.it_.apply(this, arguments);
|
||||
spec.exclude('Temporarily disabled with xit');
|
||||
return j$.deprecatingSpecProxy(spec, this);
|
||||
};
|
||||
|
||||
this.fit = function(description, fn, timeout) {
|
||||
ensureIsNotNested('fit');
|
||||
ensureIsFunctionOrAsync(fn, 'fit');
|
||||
|
||||
if (timeout) {
|
||||
j$.util.validateTimeout(timeout);
|
||||
}
|
||||
var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
|
||||
currentDeclarationSuite.addChild(spec);
|
||||
focusedRunnables.push(spec.id);
|
||||
unfocusAncestor();
|
||||
return spec;
|
||||
return j$.deprecatingSpecProxy(spec, this);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1199,6 +1478,11 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
this.beforeEach = function(beforeEachFunction, timeout) {
|
||||
ensureIsNotNested('beforeEach');
|
||||
ensureIsFunctionOrAsync(beforeEachFunction, 'beforeEach');
|
||||
|
||||
if (timeout) {
|
||||
j$.util.validateTimeout(timeout);
|
||||
}
|
||||
|
||||
currentDeclarationSuite.beforeEach({
|
||||
fn: beforeEachFunction,
|
||||
timeout: timeout || 0
|
||||
@@ -1208,6 +1492,11 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
this.beforeAll = function(beforeAllFunction, timeout) {
|
||||
ensureIsNotNested('beforeAll');
|
||||
ensureIsFunctionOrAsync(beforeAllFunction, 'beforeAll');
|
||||
|
||||
if (timeout) {
|
||||
j$.util.validateTimeout(timeout);
|
||||
}
|
||||
|
||||
currentDeclarationSuite.beforeAll({
|
||||
fn: beforeAllFunction,
|
||||
timeout: timeout || 0
|
||||
@@ -1217,6 +1506,11 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
this.afterEach = function(afterEachFunction, timeout) {
|
||||
ensureIsNotNested('afterEach');
|
||||
ensureIsFunctionOrAsync(afterEachFunction, 'afterEach');
|
||||
|
||||
if (timeout) {
|
||||
j$.util.validateTimeout(timeout);
|
||||
}
|
||||
|
||||
afterEachFunction.isCleanup = true;
|
||||
currentDeclarationSuite.afterEach({
|
||||
fn: afterEachFunction,
|
||||
@@ -1227,6 +1521,11 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
this.afterAll = function(afterAllFunction, timeout) {
|
||||
ensureIsNotNested('afterAll');
|
||||
ensureIsFunctionOrAsync(afterAllFunction, 'afterAll');
|
||||
|
||||
if (timeout) {
|
||||
j$.util.validateTimeout(timeout);
|
||||
}
|
||||
|
||||
currentDeclarationSuite.afterAll({
|
||||
fn: afterAllFunction,
|
||||
timeout: timeout || 0
|
||||
|
||||
@@ -90,7 +90,7 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
|
||||
}
|
||||
|
||||
if (!empty) {
|
||||
return 'error properties: ' + j$.pp(result) + '\n';
|
||||
return 'error properties: ' + j$.basicPrettyPrinter_(result) + '\n';
|
||||
}
|
||||
|
||||
return '';
|
||||
|
||||
@@ -43,7 +43,35 @@ getJasmineRequireObj().Expectation = function(j$) {
|
||||
});
|
||||
|
||||
/**
|
||||
* Asynchronous matchers.
|
||||
* Asynchronous matchers that operate on an actual value which is a promise,
|
||||
* and return a promise.
|
||||
*
|
||||
* Most async matchers will wait indefinitely for the promise to be resolved
|
||||
* or rejected, resulting in a spec timeout if that never happens. If you
|
||||
* expect that the promise will already be resolved or rejected at the time
|
||||
* the matcher is called, you can use the {@link async-matchers#already}
|
||||
* modifier to get a faster failure with a more helpful message.
|
||||
*
|
||||
* Note: Specs must await the result of each async matcher, return the
|
||||
* promise returned by the matcher, or return a promise that's derived from
|
||||
* the one returned by the matcher. Otherwise the matcher will not be
|
||||
* evaluated before the spec completes.
|
||||
*
|
||||
* @example
|
||||
* // Good
|
||||
* await expectAsync(aPromise).toBeResolved();
|
||||
* @example
|
||||
* // Good
|
||||
* return expectAsync(aPromise).toBeResolved();
|
||||
* @example
|
||||
* // Good
|
||||
* return expectAsync(aPromise).toBeResolved()
|
||||
* .then(function() {
|
||||
* // more spec code
|
||||
* });
|
||||
* @example
|
||||
* // Bad
|
||||
* expectAsync(aPromise).toBeResolved();
|
||||
* @namespace async-matchers
|
||||
*/
|
||||
function AsyncExpectation(options) {
|
||||
@@ -93,6 +121,24 @@ getJasmineRequireObj().Expectation = function(j$) {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Fail as soon as possible if the actual is pending.
|
||||
* Otherwise evaluate the matcher.
|
||||
* @member
|
||||
* @name async-matchers#already
|
||||
* @since 3.8.0
|
||||
* @type {async-matchers}
|
||||
* @example
|
||||
* await expectAsync(myPromise).already.toBeResolved();
|
||||
* @example
|
||||
* return expectAsync(myPromise).already.toBeResolved();
|
||||
*/
|
||||
Object.defineProperty(AsyncExpectation.prototype, 'already', {
|
||||
get: function() {
|
||||
return addFilter(this, expectSettledPromiseFilter);
|
||||
}
|
||||
});
|
||||
|
||||
function wrapSyncCompare(name, matcherFactory) {
|
||||
return function() {
|
||||
var result = this.expector.compare(name, matcherFactory, arguments);
|
||||
@@ -171,6 +217,27 @@ getJasmineRequireObj().Expectation = function(j$) {
|
||||
buildFailureMessage: negatedFailureMessage
|
||||
};
|
||||
|
||||
var expectSettledPromiseFilter = {
|
||||
selectComparisonFunc: function(matcher) {
|
||||
return function(actual) {
|
||||
var matcherArgs = arguments;
|
||||
|
||||
return j$.isPending_(actual).then(function(isPending) {
|
||||
if (isPending) {
|
||||
return {
|
||||
pass: false,
|
||||
message:
|
||||
'Expected a promise to be settled (via ' +
|
||||
'expectAsync(...).already) but it was pending.'
|
||||
};
|
||||
} else {
|
||||
return matcher.compare.apply(null, matcherArgs);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
function ContextAddingFilter(message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ getJasmineRequireObj().buildExpectationResult = function(j$) {
|
||||
var result = {
|
||||
matcherName: options.matcherName,
|
||||
message: message(),
|
||||
stack: stack(),
|
||||
stack: options.omitStackTrace ? '' : stack(),
|
||||
passed: options.passed
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,15 @@ getJasmineRequireObj().Expector = function(j$) {
|
||||
|
||||
this.args.unshift(this.actual);
|
||||
|
||||
var matcher = matcherFactory(this.matchersUtil, this.customEqualityTesters);
|
||||
// TODO: Remove support for passing customEqualityTesters in the next major release.
|
||||
var matcher;
|
||||
|
||||
if (matcherFactory.length >= 2) {
|
||||
matcher = matcherFactory(this.matchersUtil, this.customEqualityTesters);
|
||||
} else {
|
||||
matcher = matcherFactory(this.matchersUtil);
|
||||
}
|
||||
|
||||
var comparisonFunc = this.filters.selectComparisonFunc(matcher);
|
||||
return comparisonFunc || matcher.compare;
|
||||
};
|
||||
|
||||
@@ -17,7 +17,28 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
||||
this.jasmineHandlers = {};
|
||||
this.installOne_ = function installOne_(errorType, jasmineMessage) {
|
||||
function taggedOnError(error) {
|
||||
error.jasmineMessage = jasmineMessage + ': ' + error;
|
||||
var substituteMsg;
|
||||
|
||||
if (j$.isError_(error)) {
|
||||
error.jasmineMessage = jasmineMessage + ': ' + error;
|
||||
} else {
|
||||
if (error) {
|
||||
substituteMsg = jasmineMessage + ': ' + error;
|
||||
} else {
|
||||
substituteMsg = jasmineMessage + ' with no error or message';
|
||||
}
|
||||
|
||||
if (errorType === 'unhandledRejection') {
|
||||
substituteMsg +=
|
||||
'\n' +
|
||||
'(Tip: to get a useful stack trace, use ' +
|
||||
'Promise.reject(new Error(...)) instead of Promise.reject(' +
|
||||
(error ? '...' : '') +
|
||||
').)';
|
||||
}
|
||||
|
||||
error = new Error(substituteMsg);
|
||||
}
|
||||
|
||||
var handler = handlers[handlers.length - 1];
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
getJasmineRequireObj().MockDate = function() {
|
||||
getJasmineRequireObj().MockDate = function(j$) {
|
||||
function MockDate(global) {
|
||||
var self = this;
|
||||
var currentTime = 0;
|
||||
@@ -16,6 +16,14 @@ getJasmineRequireObj().MockDate = function() {
|
||||
if (mockDate instanceof GlobalDate) {
|
||||
currentTime = mockDate.getTime();
|
||||
} else {
|
||||
if (!j$.util.isUndefined(mockDate)) {
|
||||
j$.getEnv().deprecated(
|
||||
'The argument to jasmine.clock().mockDate(), if specified, ' +
|
||||
'should be a Date instance. Passing anything other than a Date ' +
|
||||
'will be treated as an error in a future release.'
|
||||
);
|
||||
}
|
||||
|
||||
currentTime = new GlobalDate().getTime();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,14 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
StopExecutionError.prototype = new Error();
|
||||
j$.StopExecutionError = StopExecutionError;
|
||||
|
||||
function once(fn) {
|
||||
function once(fn, onTwice) {
|
||||
var called = false;
|
||||
return function(arg) {
|
||||
if (!called) {
|
||||
if (called) {
|
||||
if (onTwice) {
|
||||
onTwice();
|
||||
}
|
||||
} else {
|
||||
called = true;
|
||||
// Direct call using single parameter, because cleanup/next does not need more
|
||||
fn(arg);
|
||||
@@ -17,6 +21,16 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
};
|
||||
}
|
||||
|
||||
function fallbackOnMultipleDone() {
|
||||
console.error(
|
||||
new Error(
|
||||
"An asynchronous function called its 'done' " +
|
||||
'callback more than once, in a QueueRunner without a onMultipleDone ' +
|
||||
'handler.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function emptyFn() {}
|
||||
|
||||
function QueueRunner(attrs) {
|
||||
@@ -31,6 +45,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
fn();
|
||||
};
|
||||
this.onException = attrs.onException || emptyFn;
|
||||
this.onMultipleDone = attrs.onMultipleDone || fallbackOnMultipleDone;
|
||||
this.userContext = attrs.userContext || new j$.UserContext();
|
||||
this.timeout = attrs.timeout || {
|
||||
setTimeout: setTimeout,
|
||||
@@ -88,8 +103,9 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
var self = this,
|
||||
completedSynchronously = true,
|
||||
handleError = function handleError(error) {
|
||||
// TODO probably shouldn't next() right away here.
|
||||
// That makes debugging async failures much more confusing.
|
||||
onException(error);
|
||||
next(error);
|
||||
},
|
||||
cleanup = once(function cleanup() {
|
||||
if (timeoutId !== void 0) {
|
||||
@@ -97,31 +113,52 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
}
|
||||
self.globalErrors.popListener(handleError);
|
||||
}),
|
||||
next = once(function next(err) {
|
||||
cleanup();
|
||||
next = once(
|
||||
function next(err) {
|
||||
cleanup();
|
||||
|
||||
if (j$.isError_(err)) {
|
||||
if (!(err instanceof StopExecutionError) && !err.jasmineMessage) {
|
||||
self.fail(err);
|
||||
if (j$.isError_(err)) {
|
||||
if (!(err instanceof StopExecutionError) && !err.jasmineMessage) {
|
||||
self.fail(err);
|
||||
}
|
||||
self.errored = errored = true;
|
||||
} else if (typeof err !== 'undefined' && !self.errored) {
|
||||
self.deprecated(
|
||||
'Any argument passed to a done callback will be treated as an ' +
|
||||
'error in a future release. Call the done callback without ' +
|
||||
"arguments if you don't want to trigger a spec failure."
|
||||
);
|
||||
}
|
||||
self.errored = errored = true;
|
||||
}
|
||||
|
||||
function runNext() {
|
||||
if (self.completeOnFirstError && errored) {
|
||||
self.skipToCleanup(iterativeIndex);
|
||||
function runNext() {
|
||||
if (self.completeOnFirstError && errored) {
|
||||
self.skipToCleanup(iterativeIndex);
|
||||
} else {
|
||||
self.run(iterativeIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (completedSynchronously) {
|
||||
self.setTimeout(runNext);
|
||||
} else {
|
||||
self.run(iterativeIndex + 1);
|
||||
runNext();
|
||||
}
|
||||
},
|
||||
function() {
|
||||
try {
|
||||
if (!timedOut) {
|
||||
self.onMultipleDone();
|
||||
}
|
||||
} catch (error) {
|
||||
// Any error we catch here is probably due to a bug in Jasmine,
|
||||
// and it's not likely to end up anywhere useful if we let it
|
||||
// propagate. Log it so it can at least show up when debugging.
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
if (completedSynchronously) {
|
||||
self.setTimeout(runNext);
|
||||
} else {
|
||||
runNext();
|
||||
}
|
||||
}),
|
||||
),
|
||||
errored = false,
|
||||
timedOut = false,
|
||||
queueableFn = self.queueableFns[iterativeIndex],
|
||||
timeoutId,
|
||||
maybeThenable;
|
||||
@@ -137,6 +174,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
if (queueableFn.timeout !== undefined) {
|
||||
var timeoutInterval = queueableFn.timeout || j$.DEFAULT_TIMEOUT_INTERVAL;
|
||||
timeoutId = self.setTimeout(function() {
|
||||
timedOut = true;
|
||||
var error = new Error(
|
||||
'Timeout - Async function did not complete within ' +
|
||||
timeoutInterval +
|
||||
@@ -145,6 +183,9 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
? '(custom timeout)'
|
||||
: '(set by jasmine.DEFAULT_TIMEOUT_INTERVAL)')
|
||||
);
|
||||
// TODO Need to decide what to do about a successful completion after a
|
||||
// timeout. That should probably not be a deprecation, and maybe not
|
||||
// an error in 4.0. (But a diagnostic of some sort might be helpful.)
|
||||
onException(error);
|
||||
next();
|
||||
}, timeoutInterval);
|
||||
@@ -210,30 +251,39 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
|
||||
this.clearStack(function() {
|
||||
self.globalErrors.popListener(self.handleFinalError);
|
||||
self.onComplete(self.errored && new StopExecutionError());
|
||||
|
||||
if (self.errored) {
|
||||
self.onComplete(new StopExecutionError());
|
||||
} else {
|
||||
self.onComplete();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
QueueRunner.prototype.diagnoseConflictingAsync_ = function(fn, retval) {
|
||||
var msg;
|
||||
|
||||
if (retval && j$.isFunction_(retval.then)) {
|
||||
// Issue a warning that matches the user's code
|
||||
// Issue a warning that matches the user's code.
|
||||
// Omit the stack trace because there's almost certainly no user code
|
||||
// on the stack at this point.
|
||||
if (j$.isAsyncFunction_(fn)) {
|
||||
this.deprecated(
|
||||
msg =
|
||||
'An asynchronous before/it/after ' +
|
||||
'function was defined with the async keyword but also took a ' +
|
||||
'done callback. This is not supported and will stop working in' +
|
||||
' the future. Either remove the done callback (recommended) or ' +
|
||||
'remove the async keyword.'
|
||||
);
|
||||
'function was defined with the async keyword but also took a ' +
|
||||
'done callback. This is not supported and will stop working in' +
|
||||
' the future. Either remove the done callback (recommended) or ' +
|
||||
'remove the async keyword.';
|
||||
} else {
|
||||
this.deprecated(
|
||||
msg =
|
||||
'An asynchronous before/it/after ' +
|
||||
'function took a done callback but also returned a promise. ' +
|
||||
'This is not supported and will stop working in the future. ' +
|
||||
'Either remove the done callback (recommended) or change the ' +
|
||||
'function to not return a promise.'
|
||||
);
|
||||
'function took a done callback but also returned a promise. ' +
|
||||
'This is not supported and will stop working in the future. ' +
|
||||
'Either remove the done callback (recommended) or change the ' +
|
||||
'function to not return a promise.';
|
||||
}
|
||||
|
||||
this.deprecated(msg, { omitStackTrace: true });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
getJasmineRequireObj().ReportDispatcher = function(j$) {
|
||||
function ReportDispatcher(methods, queueRunnerFactory) {
|
||||
function ReportDispatcher(methods, queueRunnerFactory, deprecated) {
|
||||
var dispatchedMethods = methods || [];
|
||||
|
||||
for (var i = 0; i < dispatchedMethods.length; i++) {
|
||||
@@ -43,7 +43,18 @@ getJasmineRequireObj().ReportDispatcher = function(j$) {
|
||||
queueRunnerFactory({
|
||||
queueableFns: fns,
|
||||
onComplete: onComplete,
|
||||
isReporter: true
|
||||
isReporter: true,
|
||||
onMultipleDone: function() {
|
||||
deprecated(
|
||||
"An asynchronous reporter callback called its 'done' callback " +
|
||||
'more than once. This is a bug in the reporter callback in ' +
|
||||
'question. This will be treated as an error in a future ' +
|
||||
'version. See' +
|
||||
'<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> ' +
|
||||
'for more information.',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
114
src/core/Spec.js
114
src/core/Spec.js
@@ -1,9 +1,28 @@
|
||||
getJasmineRequireObj().Spec = function(j$) {
|
||||
/**
|
||||
* @interface Spec
|
||||
* @see Configuration#specFilter
|
||||
* @since 2.0.0
|
||||
*/
|
||||
function Spec(attrs) {
|
||||
this.expectationFactory = attrs.expectationFactory;
|
||||
this.asyncExpectationFactory = attrs.asyncExpectationFactory;
|
||||
this.resultCallback = attrs.resultCallback || function() {};
|
||||
/**
|
||||
* The unique ID of this spec.
|
||||
* @name Spec#id
|
||||
* @readonly
|
||||
* @type {string}
|
||||
* @since 2.0.0
|
||||
*/
|
||||
this.id = attrs.id;
|
||||
/**
|
||||
* The description passed to the {@link it} that created this spec.
|
||||
* @name Spec#description
|
||||
* @readonly
|
||||
* @type {string}
|
||||
* @since 2.0.0
|
||||
*/
|
||||
this.description = attrs.description || '';
|
||||
this.queueableFn = attrs.queueableFn;
|
||||
this.beforeAndAfterFns =
|
||||
@@ -17,6 +36,8 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
return {};
|
||||
};
|
||||
this.onStart = attrs.onStart || function() {};
|
||||
this.autoCleanClosures =
|
||||
attrs.autoCleanClosures === undefined ? true : !!attrs.autoCleanClosures;
|
||||
this.getSpecName =
|
||||
attrs.getSpecName ||
|
||||
function() {
|
||||
@@ -24,6 +45,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
};
|
||||
this.expectationResultFactory =
|
||||
attrs.expectationResultFactory || function() {};
|
||||
this.deprecated = attrs.deprecated || function() {};
|
||||
this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
|
||||
this.catchingExceptions =
|
||||
attrs.catchingExceptions ||
|
||||
@@ -34,7 +56,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
this.timer = attrs.timer || new j$.Timer();
|
||||
|
||||
if (!this.queueableFn.fn) {
|
||||
this.pend();
|
||||
this.exclude();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +71,8 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
* @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec.
|
||||
* @property {number} duration - The time in ms used by the spec execution, including any before/afterEach.
|
||||
* @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSpecProperty}
|
||||
*/
|
||||
* @since 2.0.0
|
||||
x */
|
||||
this.result = {
|
||||
id: this.id,
|
||||
description: this.description,
|
||||
@@ -101,7 +124,9 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
|
||||
var complete = {
|
||||
fn: function(done) {
|
||||
self.queueableFn.fn = null;
|
||||
if (self.autoCleanClosures) {
|
||||
self.queueableFn.fn = null;
|
||||
}
|
||||
self.result.status = self.status(excluded, failSpecWithNoExp);
|
||||
self.result.duration = self.timer.elapsed();
|
||||
self.resultCallback(self.result, done);
|
||||
@@ -118,13 +143,32 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
onException: function() {
|
||||
self.onException.apply(self, arguments);
|
||||
},
|
||||
onComplete: function() {
|
||||
onComplete(
|
||||
self.result.status === 'failed' &&
|
||||
new j$.StopExecutionError('spec failed')
|
||||
onMultipleDone: function() {
|
||||
// Issue a deprecation. Include the context ourselves and pass
|
||||
// ignoreRunnable: true, since getting here always means that we've already
|
||||
// moved on and the current runnable isn't the one that caused the problem.
|
||||
self.deprecated(
|
||||
"An asynchronous function called its 'done' " +
|
||||
'callback more than once. This is a bug in the spec, beforeAll, ' +
|
||||
'beforeEach, afterAll, or afterEach function in question. This will ' +
|
||||
'be treated as an error in a future version. See' +
|
||||
'<https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0#deprecations-due-to-calling-done-multiple-times> ' +
|
||||
'for more information.\n' +
|
||||
'(in spec: ' +
|
||||
self.getFullName() +
|
||||
')',
|
||||
{ ignoreRunnable: true }
|
||||
);
|
||||
},
|
||||
userContext: this.userContext()
|
||||
onComplete: function() {
|
||||
if (self.result.status === 'failed') {
|
||||
onComplete(new j$.StopExecutionError('spec failed'));
|
||||
} else {
|
||||
onComplete();
|
||||
}
|
||||
},
|
||||
userContext: this.userContext(),
|
||||
runnableName: this.getFullName.bind(this)
|
||||
};
|
||||
|
||||
if (this.markedPending || excluded === true) {
|
||||
@@ -138,6 +182,36 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
this.queueRunnerFactory(runnerConfig);
|
||||
};
|
||||
|
||||
Spec.prototype.reset = function() {
|
||||
/**
|
||||
* @typedef SpecResult
|
||||
* @property {Int} id - The unique id of this spec.
|
||||
* @property {String} description - The description passed to the {@link it} that created this spec.
|
||||
* @property {String} fullName - The full description including all ancestors of this spec.
|
||||
* @property {Expectation[]} failedExpectations - The list of expectations that failed during execution of this spec.
|
||||
* @property {Expectation[]} passedExpectations - The list of expectations that passed during execution of this spec.
|
||||
* @property {Expectation[]} deprecationWarnings - The list of deprecation warnings that occurred during execution this spec.
|
||||
* @property {String} pendingReason - If the spec is {@link pending}, this will be the reason.
|
||||
* @property {String} status - Once the spec has completed, this string represents the pass/fail status of this spec.
|
||||
* @property {number} duration - The time in ms used by the spec execution, including any before/afterEach.
|
||||
* @property {Object} properties - User-supplied properties, if any, that were set using {@link Env#setSpecProperty}
|
||||
* @since 2.0.0
|
||||
*/
|
||||
this.result = {
|
||||
id: this.id,
|
||||
description: this.description,
|
||||
fullName: this.getFullName(),
|
||||
failedExpectations: [],
|
||||
passedExpectations: [],
|
||||
deprecationWarnings: [],
|
||||
pendingReason: this.excludeMessage,
|
||||
duration: null,
|
||||
properties: null,
|
||||
trace: null
|
||||
};
|
||||
this.markedPending = this.markedExcluding;
|
||||
};
|
||||
|
||||
Spec.prototype.onException = function onException(e) {
|
||||
if (Spec.isPendingSpecException(e)) {
|
||||
this.pend(extractCustomPendingMessage(e));
|
||||
@@ -161,6 +235,10 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
* Marks state as pending
|
||||
* @param {string} [message] An optional reason message
|
||||
*/
|
||||
Spec.prototype.pend = function(message) {
|
||||
this.markedPending = true;
|
||||
if (message) {
|
||||
@@ -168,6 +246,19 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Like {@link Spec#pend}, but pending state will survive {@link Spec#reset}
|
||||
* Useful for fit, xit, where pending state remains.
|
||||
* @param {string} [message] An optional reason message
|
||||
*/
|
||||
Spec.prototype.exclude = function(message) {
|
||||
this.markedExcluding = true;
|
||||
if (this.message) {
|
||||
this.excludeMessage = message;
|
||||
}
|
||||
this.pend(message);
|
||||
};
|
||||
|
||||
Spec.prototype.getResult = function() {
|
||||
this.result.status = this.status();
|
||||
return this.result;
|
||||
@@ -195,6 +286,13 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
return 'passed';
|
||||
};
|
||||
|
||||
/**
|
||||
* The full description including all ancestors of this spec.
|
||||
* @name Spec#getFullName
|
||||
* @function
|
||||
* @returns {string}
|
||||
* @since 2.0.0
|
||||
*/
|
||||
Spec.prototype.getFullName = function() {
|
||||
return this.getSpecName(this);
|
||||
};
|
||||
|
||||
@@ -13,9 +13,11 @@ getJasmineRequireObj().Spy = function(j$) {
|
||||
});
|
||||
|
||||
/**
|
||||
* _Note:_ Do not construct this directly, use {@link spyOn}, {@link spyOnProperty}, {@link jasmine.createSpy}, or {@link jasmine.createSpyObj}
|
||||
* @constructor
|
||||
* @name Spy
|
||||
* @classdesc _Note:_ Do not construct this directly. Use {@link spyOn},
|
||||
* {@link spyOnProperty}, {@link jasmine.createSpy}, or
|
||||
* {@link jasmine.createSpyObj} instead.
|
||||
* @class Spy
|
||||
* @hideconstructor
|
||||
*/
|
||||
function Spy(
|
||||
name,
|
||||
@@ -44,6 +46,7 @@ getJasmineRequireObj().Spy = function(j$) {
|
||||
* @property {object} object - `this` context for the invocation.
|
||||
* @property {number} invocationOrder - Order of the invocation.
|
||||
* @property {Array} args - The arguments passed for this invocation.
|
||||
* @property returnValue - The value that was returned from this invocation.
|
||||
*/
|
||||
var callData = {
|
||||
object: context,
|
||||
@@ -164,7 +167,7 @@ getJasmineRequireObj().Spy = function(j$) {
|
||||
"Spy '" +
|
||||
strategyArgs.name +
|
||||
"' received a call with arguments " +
|
||||
j$.pp(Array.prototype.slice.call(args)) +
|
||||
j$.basicPrettyPrinter_(Array.prototype.slice.call(args)) +
|
||||
' but all configured strategies specify other arguments.'
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -163,7 +163,7 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
return spy;
|
||||
};
|
||||
|
||||
this.spyOnAllFunctions = function(obj) {
|
||||
this.spyOnAllFunctions = function(obj, includeNonEnumerable) {
|
||||
if (j$.util.isUndefined(obj)) {
|
||||
throw new Error(
|
||||
'spyOnAllFunctions could not find an object to spy upon'
|
||||
@@ -171,30 +171,27 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
}
|
||||
|
||||
var pointer = obj,
|
||||
props = [],
|
||||
prop,
|
||||
descriptor;
|
||||
propsToSpyOn = [],
|
||||
properties,
|
||||
propertiesToSkip = [];
|
||||
|
||||
while (pointer) {
|
||||
for (prop in pointer) {
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(pointer, prop) &&
|
||||
pointer[prop] instanceof Function
|
||||
) {
|
||||
descriptor = Object.getOwnPropertyDescriptor(pointer, prop);
|
||||
if (
|
||||
(descriptor.writable || descriptor.set) &&
|
||||
descriptor.configurable
|
||||
) {
|
||||
props.push(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (
|
||||
pointer &&
|
||||
(!includeNonEnumerable || pointer !== Object.prototype)
|
||||
) {
|
||||
properties = getProps(pointer, includeNonEnumerable);
|
||||
properties = properties.filter(function(prop) {
|
||||
return propertiesToSkip.indexOf(prop) === -1;
|
||||
});
|
||||
propertiesToSkip = propertiesToSkip.concat(properties);
|
||||
propsToSpyOn = propsToSpyOn.concat(
|
||||
getSpyableFunctionProps(pointer, properties)
|
||||
);
|
||||
pointer = Object.getPrototypeOf(pointer);
|
||||
}
|
||||
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
this.spyOn(obj, props[i]);
|
||||
for (var i = 0; i < propsToSpyOn.length; i++) {
|
||||
this.spyOn(obj, propsToSpyOn[i]);
|
||||
}
|
||||
|
||||
return obj;
|
||||
@@ -209,5 +206,49 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
|
||||
};
|
||||
}
|
||||
|
||||
function getProps(obj, includeNonEnumerable) {
|
||||
var enumerableProperties = Object.keys(obj);
|
||||
|
||||
if (!includeNonEnumerable) {
|
||||
return enumerableProperties;
|
||||
}
|
||||
|
||||
return Object.getOwnPropertyNames(obj).filter(function(prop) {
|
||||
return (
|
||||
prop !== 'constructor' ||
|
||||
enumerableProperties.indexOf('constructor') > -1
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function getSpyableFunctionProps(obj, propertiesToCheck) {
|
||||
var props = [],
|
||||
prop;
|
||||
for (var i = 0; i < propertiesToCheck.length; i++) {
|
||||
prop = propertiesToCheck[i];
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(obj, prop) &&
|
||||
isSpyableProp(obj, prop)
|
||||
) {
|
||||
props.push(prop);
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
function isSpyableProp(obj, prop) {
|
||||
var value, descriptor;
|
||||
try {
|
||||
value = obj[prop];
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
if (value instanceof Function) {
|
||||
descriptor = Object.getOwnPropertyDescriptor(obj, prop);
|
||||
return (descriptor.writable || descriptor.set) && descriptor.configurable;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return SpyRegistry;
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user