Compare commits

...

121 Commits

Author SHA1 Message Date
Gregg Van Hove
b3ccd4312c Bump version to 3.3.0 2018-10-25 09:47:09 -07:00
Gregg Van Hove
5524207658 Add api docs for .not and .withContext 2018-10-24 16:49:31 -07:00
Gregg Van Hove
1b5e0c0c10 Merge branch 'expect-context'
- Fixes #641
2018-10-24 16:32:28 -07:00
Gregg Van Hove
2d303a6e46 Merge common async/sync expectation stuff 2018-10-24 16:17:30 -07:00
Gregg Van Hove
1e47dcf2cc Pull async matchers out to their own functions
- Makes AsyncExpectation closer to Expectation
2018-10-23 16:02:31 -07:00
Gregg Van Hove
ba1e8f8008 Implement withContext for async expectations too 2018-10-22 16:42:36 -07:00
Gregg Van Hove
a91db0dfc2 more rejected to -> rejected with 2018-10-22 16:08:57 -07:00
Gregg Van Hove
1d130036f4 Merge branch 'master' into expect-context 2018-10-22 14:55:20 -07:00
Gregg Van Hove
e6a60a7bef Merge branch 'codymikol-toBeRejectedWith'
- Merges #1615 from @codymikol
- Closes #1600
- Fixes #1595
2018-10-22 11:20:03 -07:00
Gregg Van Hove
fe042fdf82 Use toBeRejectedWith instead of toBeRejectedTo 2018-10-22 11:18:56 -07:00
Gregg Van Hove
06854fe435 Merge branch 'toBeRejectedWith' of https://github.com/codymikol/jasmine into codymikol-toBeRejectedWith 2018-10-22 11:15:05 -07:00
Gregg Van Hove
7b9fc80b8f Merge branch 'tdurtschi-master'
- Merges #1616 from @tdurtshi
- Fixes #1614
2018-10-22 10:59:03 -07:00
Gregg Van Hove
3c47e71619 Also show tip for .not cases 2018-10-22 10:57:16 -07:00
Teagan Durtschi
7cbedcdda7 Add custom message for toBe() matcher when object equality check fails 2018-10-21 12:46:49 -04:00
Cody Mikol
3aa0115ae4 feat(toBeRejectedTo): implement toBeRejectedTo functionality
add functionality to determine whether a promise has been rejected to a
specific value via expectAsync

Fixes: #1595
2018-10-19 23:23:42 -04:00
Gregg Van Hove
440b6934aa Merge branch 'codymikol-assertAsync-promiseLike-support'
- Merges #1613 from @codymikol
- Fixes #1612
2018-10-19 16:24:30 -07:00
Cody Mikol
591bf1144b bugfix(assertAsync): add promiseLike support for angularJS promises
implement a promiseLike method so libraries using non-browser promise
implementations can still utilize assertAsync functionality.

Fixes: #1612
2018-10-18 21:28:32 -04:00
Gregg Van Hove
3ae61b14ad Merge branch 'm1010j-m1010j-add-status-marks-to-standalone'
- Merges #1610 from @m1010j
- Fixes #1596
2018-10-01 12:25:23 -07:00
Matthias Jenny
705a6508d4 Add status marks to standalone 2018-09-26 21:10:20 -04:00
Gregg Van Hove
306882f636 Merge branch 'nitobuendia-patch-1' 2018-09-25 17:29:10 -07:00
Gregg Van Hove
16fef04629 Merge branch 'patch-1' of https://github.com/nitobuendia/jasmine into nitobuendia-patch-1
- Merges #1601 from @nitobuendia
- Fixes #1594
2018-09-25 17:28:57 -07:00
Gregg Van Hove
d180c2026e Merge branch 'master' of https://github.com/Havunen/jasmine into Havunen-master
- Merges #1599 from @Havunen
2018-09-25 17:14:49 -07:00
Gregg Van Hove
92d0882a32 Introduce a configuration object to Env deprecating old single use functions
[finishes #159158038]
2018-09-25 17:08:41 -07:00
Nito Buendia
04679622b0 Add tests for formatting empty content errors. 2018-09-13 20:02:30 +08:00
Nito Buendia
b4cd1ec1ae Format according to style. 2018-09-13 19:48:53 +08:00
Nito Buendia
963b1cca22 Add tests for new unnamed errors. 2018-09-13 19:48:10 +08:00
Nito Buendia
d4f9b41eda Print error message when available
With the current set up, error message is only printed out when error name is available.
There are situations where the ErrorEvent object does not have a `name` property, but the message is still relevant.

For more details see #1594
2018-09-11 23:25:28 +08:00
Sampo Kivistö
1019b045cd Optimized clearTimeout cpu usage 2018-09-06 21:11:05 +03:00
Gregg Van Hove
6b9ae2db7e Merge pull request #1597 from limonte/patch-1
chore(package.json): http -> https
2018-09-04 12:27:05 -07:00
Limon Monte
33d8d2d3f4 chore(package.json): http -> https 2018-09-01 10:16:30 +03:00
Gregg Van Hove
12f56fdb7d bump version to 3.2.1 2018-08-14 17:19:23 -07:00
Gregg Van Hove
afa18e554c Correctly expost spyOnAllFunctions
- See #1581
2018-08-14 17:11:50 -07:00
Gregg Van Hove
7205d07c67 Merge pull request #1588 from fossabot/master
Add license scan report and status
2018-08-08 19:04:21 -07:00
Gregg Van Hove
83ba2eb4d6 Link to the correct repo in release notes 2018-08-08 17:41:24 -07:00
Gregg Van Hove
87865f00a3 Add issue links to release notes 2018-08-08 17:39:10 -07:00
Gregg Van Hove
112672c4a9 bump version to 3.2.0 2018-08-08 17:33:50 -07:00
fossabot
f05ab79731 Add license scan report and status
Signed-off-by: fossabot <badges@fossa.io>
2018-08-07 17:47:31 -07:00
Gregg Van Hove
3a52c444f8 Merge branch 'aeisenberg-spy-all'
- Merges #1581 from @aeisenberg
- Fixes #1421
2018-07-24 17:55:44 -07:00
Andrew Eisenberg
f62eb3b1a8 Add spyOnAllFunctions function
This function will spy on all writable and configurable functionss of
an object that is passed in. It can be used like this:

    spyOnAllFunctions(obj);

This commit addresses https://github.com/jasmine/jasmine/issues/1421
2018-07-20 07:58:17 -07:00
Gregg Van Hove
110c092c9e Fix regular expressions for different browsers 2018-06-18 17:55:24 -07:00
Gregg Van Hove
8bb0e2d494 Merge branch 'ikonst-set-timeout-error-message'
- Merges #1567 from @ikonst
2018-06-18 17:37:39 -07:00
Ilya Konstantinov
8c1b80daae Improve Jasmine timeout error message 2018-06-18 17:36:43 -07:00
Steve Gravrock
ac07c9ea97 Simplified ExpectationFilterChain#modifyFailureMessage 2018-06-09 12:34:30 -07:00
Steve Gravrock
0842a80c68 Cleanup 2018-06-09 12:26:34 -07:00
Gregg Van Hove
e2895a92dc Fix JSDoc naming for Env functions
- See #1565
2018-06-06 17:13:52 -07:00
Gregg Van Hove
03998c1b20 Add documentation for more public functions on Env
- Fixes #1565
2018-06-05 17:13:58 -07:00
Steve Gravrock
9472df0db4 Added a basic set of async matchers
- Fixes #1447
- Fixes #1547
2018-06-04 21:07:44 -07:00
Steve Gravrock
8a01e1f26c .withContext() works with .not 2018-06-02 22:06:53 -07:00
Steve Gravrock
321f161ce5 Made ExpectationFilterChain immutable 2018-06-02 13:57:29 -07:00
Steve Gravrock
202a677637 ExpectationFilterChain WIP 2018-06-02 13:57:07 -07:00
Gregg Van Hove
8f7327cb4d Properly cascade StopExecutionError's up the tree
- Fixes #1563
2018-05-30 17:32:14 -07:00
Gregg Van Hove
3636014917 Merge branch 'hide-grey-specs' of https://github.com/SamFare/jasmine into SamFare-hide-grey-specs
- Merges #1561 from @SamFare
2018-05-23 17:15:40 -07:00
SamFare
92d33c79c7 Implemented hiding of disabled specs 2018-05-22 13:30:33 +01:00
Steve Gravrock
e2897ce619 Added expect().withContext() to provide additional information in failure messages 2018-05-14 21:18:55 -07:00
Steve Gravrock
282c436463 Implemented matcher negation as a filter 2018-05-13 23:01:55 -07:00
Steve Gravrock
5cc22740c9 Test the public-ish interface 2018-05-13 22:48:58 -07:00
Steve Gravrock
533bda5d24 Split Expectation#wrapCompare into several smaller functions 2018-05-13 22:48:58 -07:00
Steve Gravrock
9fe9569b24 Additional tests for negated matcher failure messages 2018-05-13 22:48:20 -07:00
Steve Gravrock
e2d9eefccd Line-break long expectation failure messages
This makes failures somewhat easier to read. We still preserve whitespace
within lines to make whitespace-only failures readable, e.g.
expect('foo  bar').toEqual('foo bar'). See #296.
2018-05-12 09:42:38 -07:00
Gregg Van Hove
ced2b114e4 Better detection of DOM Nodes for equality
- Also use JSDom if a real one isn't present to get some more coverage
  there

- Fixes #1172
2018-05-04 18:01:08 -07:00
Gregg Van Hove
f7097281c9 IE doesn't support .name on a function 2018-05-03 17:34:15 -07:00
Gregg Van Hove
01a1113387 Merge branch 'yinm-fix-typo'
- Merges #1555 from @yinm
2018-05-03 17:21:18 -07:00
yinm
4d0b47ac4c Fix typo from incimplete to incomplete 2018-05-03 17:46:49 +09:00
Gregg Van Hove
d6cfc4a9b5 Merge branch 'riophae-master'
- Merges #1551 from @riophae
2018-05-02 17:52:03 -07:00
Fangzhou Li
fbcdbf5ab1 Allow omitting the name argument: createSpy(func) 2018-04-29 06:07:22 +08:00
Gregg Van Hove
7e14a97371 Explicitly pass in timing functions in mock clock integration specs
- This way we can make sure that clear stack always works no matter
  how long the suite in the spec is

[fixes #153518103]
2018-04-23 17:25:11 -07:00
Gregg Van Hove
c440d13754 Use the same global for everything in Env
- No longer use `getGlobal` for clearStack and QueueRunner
2018-04-13 17:14:48 -07:00
Gregg Van Hove
8e8f09b41f Force reinstall bundler and include firefox again 2018-04-03 17:33:20 -07:00
Gregg Van Hove
1decb14807 Ensure rubygems is up-to-date on travis
- See travis-ci/travis-ci#8969
2018-04-03 17:13:27 -07:00
Gregg Van Hove
a978f50f1d name new global status stuff correctly in API docs 2018-04-02 17:20:39 -07:00
Steve Gravrock
74287c578c Check for accidental global variable creation 2018-03-25 12:01:50 -07:00
Steve Gravrock
7f1cdc2d02 Fixed global variable leak
- Fixes #1534
2018-03-25 12:00:56 -07:00
Steve Gravrock
847a959b13 Merge branch 'handle-rejection' of https://github.com/johnjbarton/jasmine
- Merges #1521 from @johnjbarton
2018-03-24 19:49:58 -07:00
Steve Gravrock
05015a8b3e Correctly format stack traces for errors with multiline messages
- Fixes #1526
2018-03-10 12:03:08 -08:00
Steve Gravrock
6f960d8662 Merge branch 'better-array-errors' of https://github.com/majidmade/jasmine
- Merges #1527 from @majidmade
- Fixes #1485
2018-03-10 07:42:34 -08:00
Majid Razvi
11b8b59e03 Change message for extra elements at end of actual array. #1485 2018-03-10 00:05:07 -07:00
johnjbarton
f1ebe05f1d Report unhandled rejections as globalErrors.
Extend existing support for uncaughtExceptions to unhandledRejections now that many tests are async.
2018-03-01 16:47:50 -08:00
Gregg Van Hove
85b2a8c6c4 add some links to more tutorials from the api docs 2018-03-01 10:48:18 -08:00
Gregg Van Hove
557fb4ed72 proper links in release notes 2018-02-27 12:01:28 -08:00
Gregg Van Hove
ee52023b3d Bump version to 3.1 2018-02-27 11:57:20 -08:00
Gregg Van Hove
91296a44f2 Remove Safari 7 from Travis matrix 2018-02-27 11:10:07 -08:00
Gregg Van Hove
1923461b09 Ignore more browser fields when formatting Errors
- description from IE
- column from Safari
2018-02-27 09:52:19 -08:00
Gregg Van Hove
71116d3957 don't lock to 2.99 in dev 2018-02-27 09:33:10 -08:00
Gregg Van Hove
63cc7cafc8 Use Jasmine's arrayContains, instead of includes for better support 2018-02-26 17:57:37 -08:00
Gregg Van Hove
fdecf02472 Merge branch 'print_exception_properties' of https://github.com/jbunton-atlassian/jasmine into jbunton-atlassian-print_exception_properties
- Merges #1516 from @jbunton-atlassian
2018-02-26 17:48:28 -08:00
Gregg Van Hove
11f4d894a6 Merge branch 'node-load-errors'
- See #1519
2018-02-26 16:44:45 -08:00
James Bunton
1149d4edde Use j$.pp instead of JSON.stringify() for pretty printing 2018-02-27 10:22:06 +11:00
James Bunton
9ee85c35d2 Remove duplicate ignored property 2018-02-27 10:21:50 +11:00
Steve Gravrock
0367ca5294 Merge branch 'patch-closing-statement' of https://github.com/Sylhare/jasmine
- Merges #1512 from @Sylhare
2018-02-23 19:17:50 -08:00
James Bunton
763a83c833 Display error properties for failed specs 2018-02-23 14:43:47 +11:00
sylhare
7fb53dcdfa Fixing missing semi-colons 2018-02-21 09:01:24 -05:00
sgravrock
a9a112e88f Fixed release notes link 2018-02-18 21:08:52 -08:00
sgravrock
0184808a86 Updated README for 3.0 2018-02-18 21:06:51 -08:00
Steve Gravrock
1ac2a6f608 Allow node to report load time errors
[Fixes #153466462]
2018-02-17 15:45:42 -08:00
Gregg Van Hove
785f62c7a0 Fix naming and check functions for empty/notEmpty specs 2018-02-15 17:43:03 -08:00
Gregg Van Hove
d8c154a2c6 Update empty and notEmpty specs for better IE11 support 2018-02-15 17:23:44 -08:00
Gregg Van Hove
c974c4740c Merge branch 'master' of https://github.com/sjolicoeur/jasmine into sjolicoeur-master
- Merges #1460 from @sjolicoeur
2018-02-15 16:00:33 -08:00
Gregg Van Hove
2b27bd393f Add API docs for async reporters 2018-02-15 14:36:29 -08:00
Gregg Van Hove
3b77f38188 Return <anonymous> for functions that have no actual words between keyword and (
- Also fixes a potential catastrophic backtracking if someone has
severely damaged their own `toString` during test execution.
2018-02-15 12:31:10 -08:00
Steve Gravrock
11827572d3 Moved toHaveClass matcher into core so that it can be used in Karma
- Fixes #1503
2018-02-13 17:09:42 -08:00
Gregg Van Hove
8326ecf919 Merge branch 'deprecation-object' of https://github.com/UziTech/jasmine into UziTech-deprecation-object
- Merges #1498 from @UziTech
2018-02-13 16:57:24 -08:00
Gregg Van Hove
cd6a0de852 Merge pull request #1505 from codetriage-readme-bot/codetriage-badge
Add CodeTriage badge to jasmine/jasmine
2018-02-13 09:48:37 -08:00
codetriage-readme-bot
148d94558d Add CodeTriage badge to jasmine/jasmine
Adds a badge showing the number of people helping this repo on CodeTriage.

[![Open Source Helpers](https://www.codetriage.com/jasmine/jasmine/badges/users.svg)](https://www.codetriage.com/jasmine/jasmine)

## What is CodeTriage?

CodeTriage is an Open Source app that is designed to make contributing to Open Source projects easier. It works by sending subscribers a few open issues in their inbox. If subscribers get busy, there is an algorithm that backs off issue load so they do not get overwhelmed

[Read more about the CodeTriage project](https://www.codetriage.com/what).

## Why am I getting this PR?

Your project was picked by the human, @schneems. They selected it from the projects submitted to https://www.codetriage.com and hand edited the PR. How did your project get added to [CodeTriage](https://www.codetriage.com/what)? Roughly 8 months ago, [alopezsanchez](https://github.com/alopezsanchez) added this project to CodeTriage in order to start contributing. Since then, 2 people have subscribed to help this repo.

## What does adding a badge accomplish?

Adding a badge invites people to help contribute to your project. It also lets developers know that others are invested in the longterm success and maintainability of the project.

You can see an example of a CodeTriage badge on these popular OSS READMEs:

- [![](https://www.codetriage.com/rails/rails/badges/users.svg)](https://www.codetriage.com/rails/rails) https://github.com/rails/rails
- [![](https://www.codetriage.com/crystal-lang/crystal/badges/users.svg)](https://www.codetriage.com/crystal-lang/crystal) https://github.com/crystal-lang/crystal

## Have a question or comment?

While I am a bot, this PR was manually reviewed and monitored by a human - @schneems. My job is writing commit messages and handling PR logistics.

If you have any questions, you can reply back to this PR and they will be answered by @schneems. If you do not want a badge right now, no worries, close the PR, you will not hear from me again.

Thanks for making your project Open Source! Any feedback is greatly appreciated.
2018-02-13 10:29:49 -06:00
Gregg Van Hove
83beca6899 Merge branch '2.99-patch' 2018-02-09 09:32:09 -08:00
Gregg Van Hove
3c6308f1dc Don't include the specs in the ruby gem
- Bump to 2.99.2 for gem
2018-02-09 09:22:35 -08:00
Tony Brix
6193bc113b throw errors 2018-02-08 15:12:14 -06:00
Gregg Van Hove
fa6a80b76e Merge branch 'master' of https://github.com/aptx4869/jasmine into aptx4869-master
- Merges #1501 from @aptx4869
2018-02-08 10:22:36 -08:00
Gregg Van Hove
c861f6c6c2 Merge pull request #1499 from bcaudan/patch-1
Fix release note typo
2018-02-08 10:16:57 -08:00
aptx4869
4fcd4099ad Resolve merge conflict
Fixes #1500
2018-02-08 15:07:29 +08:00
Bastien Caudan
1d495587ff Fix release note typo 2018-02-08 08:02:13 +01:00
Tony Brix
c859128537 add tests 2018-02-07 23:58:26 -06:00
Tony Brix
a8a5b839ab allow adding a deprecation object 2018-02-07 22:44:32 -06:00
Gregg Van Hove
4e5d947faa Also lock for selenium runner 2018-02-07 14:58:14 -08:00
Gregg Van Hove
c2603efeb4 Specify Jasmine Gem 2.99 tag for bundle install 2018-02-07 14:55:28 -08:00
Gregg Van Hove
fbec3cc230 Only show deprecation for catch exceptions if you tell Jasmine not to catch
- Fixes #1497
2018-02-07 14:47:10 -08:00
Gregg Van Hove
1acbd1ef96 Add notes for environments that have lost support
- #1495
2018-02-07 09:19:33 -08:00
Gregg Van Hove
3d8e379fa6 bump dev dependency for npm 2018-02-06 15:37:21 -08:00
Gregg Van Hove
55267e11f6 Make sure ruby version is a string when passing to sauce labs 2018-02-06 13:37:12 -08:00
Gregg Van Hove
09a6e3714a Bump travis ruby version 2018-02-06 12:29:12 -08:00
Gregg Van Hove
8ec4d54685 no longer run specs for docs in CI 2018-02-06 11:54:25 -08:00
sjolicoeur
d90e20eb15 Added matchers: truthy, falsy, empty and notEmpty 2017-12-07 17:49:16 -08:00
95 changed files with 4720 additions and 747 deletions

View File

@@ -1,9 +1,17 @@
{
"bitwise": true,
"curly": true,
"globals": {
"clearTimeout": false,
"console": false,
"getJasmineRequireObj": true,
"jasmineRequire": true,
"setTimeout": false
},
"immed": true,
"newcap": true,
"trailing": true,
"loopfunc": true,
"quotmark": "single"
}
"quotmark": "single",
"undef": true
}

View File

@@ -2,8 +2,11 @@ language: ruby
cache: bundler
sudo: false
rvm: 2.2.2
rvm: 2.5
before_install:
- gem update --system
- gem install bundler
script: $TEST_COMMAND
env:
@@ -11,9 +14,6 @@ env:
- USE_SAUCE=true
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="firefox"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- secure: WSPWhlnC4mWSnSPquX+m1/BCu5ch5NygkaHuM2Nea7lD8oS3XLX8QncZZAsQ4lnNfqoDDuBOizG0AESiqNvE4y6x5qvLLTS6q+ce255ZEMZ71TBdZgDEEvGMEjOPPsVXiXyTQOP1lwOPlrbZvaPgWV7e11KIBab6DfFcQpnvDgo=
- secure: SW7CJhZnwaNT749Gdnhvqb5rbXlAOsygUAzh9qhtyvbqXKkmJdBIEsO01YF6pbju1X2twE9JvWCOxeZju43NgQChJlPsGbjY2j3k/TdQeTAJesQe2K7ytwghunI30gjEovtRH0T3w1EmcKPH8yj5eBIcB2OYoJHx8KEC7e68q1g=
@@ -31,6 +31,10 @@ matrix:
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh v9"
- env:
- JASMINE_BROWSER="firefox"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- env:
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.12"
@@ -43,10 +47,6 @@ matrix:
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.10"
- SAUCE_BROWSER_VERSION=8
- env:
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.9"
- SAUCE_BROWSER_VERSION=7
- env:
- JASMINE_BROWSER="MicrosoftEdge"
- SAUCE_OS="Windows 10"
@@ -66,7 +66,3 @@ matrix:
- env:
- JASMINE_BROWSER="phantomjs"
- USE_SAUCE=false
- env:
- USE_SAUCE=false
- JASMINE_BROWSER="phantomjs"
- TEST_COMMAND="bash travis-docs-script.sh"

View File

@@ -1,15 +1,17 @@
<a name="README">[<img src="https://rawgithub.com/jasmine/jasmine/master/images/jasmine-horizontal.svg" width="400px" />](http://jasmine.github.io)</a>
[![Build Status](https://travis-ci.org/jasmine/jasmine.svg?branch=master)](https://travis-ci.org/jasmine/jasmine)
[![Open Source Helpers](https://www.codetriage.com/jasmine/jasmine/badges/users.svg)](https://www.codetriage.com/jasmine/jasmine)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine?ref=badge_shield)
# A JavaScript Testing Framework
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.
Documentation & guides live here: [http://jasmine.github.io](http://jasmine.github.io/)
For a quick start guide of Jasmine 2.x, see the beginning of [http://jasmine.github.io/edge/introduction.html](http://jasmine.github.io/edge/introduction.html)
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 1.x? Check out the [2.0 release notes](https://github.com/jasmine/jasmine/blob/v2.0.0/release_notes/20.md) for a list of what's new (including breaking interface changes). You can also read the [upgrade guide](http://jasmine.github.io/2.0/upgrading.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
@@ -73,4 +75,8 @@ Jasmine tests itself across many browsers (Safari, Chrome, Firefox, PhantomJS, M
* [Christian Williams](mailto:antixian666@gmail.com), Cloud Foundry
* Sheel Choksi
Copyright (c) 2008-2017 Pivotal Labs. This software is licensed under the MIT License.
Copyright (c) 2008-2018 Pivotal Labs. This software is licensed under the MIT License.
## License
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine?ref=badge_large)

View File

@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
s.rubyforge_project = "jasmine-core"
s.license = "MIT"
s.files = Dir.glob("./lib/**/*") + Dir.glob("./lib/jasmine-core/spec/**/*.js")
s.files = Dir.glob("./lib/**/*")
s.require_paths = ["lib"]
s.add_development_dependency "rake"
s.add_development_dependency "sauce-connect"

View File

@@ -73,21 +73,21 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
var filterSpecs = !!queryString.getParam("spec");
var stoppingOnSpecFailure = queryString.getParam("failFast");
env.stopOnSpecFailure(stoppingOnSpecFailure);
var throwingExpectationFailures = queryString.getParam("throwFailures");
env.throwOnExpectationFailure(throwingExpectationFailures);
var config = {
failFast: queryString.getParam("failFast"),
oneFailurePerSpec: queryString.getParam("oneFailurePerSpec"),
hideDisabled: queryString.getParam("hideDisabled")
};
var random = queryString.getParam("random");
if (random !== undefined && random !== "") {
env.randomizeTests(random);
config.random = random;
}
var seed = queryString.getParam("seed");
if (seed) {
env.seed(seed);
config.seed = seed;
}
/**
@@ -118,10 +118,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
filterString: function() { return queryString.getParam("spec"); }
});
env.specFilter = function(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.
*/

View File

@@ -51,21 +51,21 @@
var filterSpecs = !!queryString.getParam("spec");
var stoppingOnSpecFailure = queryString.getParam("failFast");
env.stopOnSpecFailure(stoppingOnSpecFailure);
var throwingExpectationFailures = queryString.getParam("throwFailures");
env.throwOnExpectationFailure(throwingExpectationFailures);
var config = {
failFast: queryString.getParam("failFast"),
oneFailurePerSpec: queryString.getParam("oneFailurePerSpec"),
hideDisabled: queryString.getParam("hideDisabled")
};
var random = queryString.getParam("random");
if (random !== undefined && random !== "") {
env.randomizeTests(random);
config.random = random;
}
var seed = queryString.getParam("seed");
if (seed) {
env.seed(seed);
config.seed = seed;
}
/**
@@ -96,10 +96,12 @@
filterString: function() { return queryString.getParam("spec"); }
});
env.specFilter = function(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.
*/

View File

@@ -1,7 +1,7 @@
module.exports = function(jasmineRequire) {
var jasmine = jasmineRequire.core(jasmineRequire);
var env = jasmine.getEnv();
var env = jasmine.getEnv({suppressLoadErrors: true});
var jasmineInterface = jasmineRequire.interface(jasmine, env);

View File

@@ -25,7 +25,6 @@ jasmineRequire.html = function(j$) {
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
j$.QueryString = jasmineRequire.QueryString();
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
j$.matchers.toHaveClass = jasmineRequire.toHaveClass(j$);
};
jasmineRequire.HtmlReporter = function(j$) {
@@ -81,7 +80,7 @@ jasmineRequire.HtmlReporter = function(j$) {
function HtmlReporter(options) {
var env = options.env || {},
var config = function() { return (options.env && options.env.configuration()) || {}; },
getContainer = options.getContainer,
createElement = options.createElement,
createTextNode = options.createTextNode,
@@ -149,7 +148,7 @@ jasmineRequire.HtmlReporter = function(j$) {
}
symbols.appendChild(createDom('li', {
className: noExpectations(result) ? 'jasmine-empty' : 'jasmine-' + result.status,
className: this.displaySpecInCorrectFormat(result),
id: 'spec_' + result.id,
title: result.fullName
}
@@ -162,13 +161,25 @@ jasmineRequire.HtmlReporter = function(j$) {
addDeprecationWarnings(result);
};
this.displaySpecInCorrectFormat = function(result) {
return noExpectations(result) ? 'jasmine-empty' : this.resultStatus(result.status);
};
this.resultStatus = function(status) {
if(status === 'excluded') {
return config().hideDisabled ? 'jasmine-excluded-no-display' : 'jasmine-excluded';
}
return 'jasmine-' + status;
};
this.jasmineDone = function(doneResult) {
var banner = find('.jasmine-banner');
var alert = find('.jasmine-alert');
var order = doneResult && doneResult.order;
var i;
alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
banner.appendChild(optionsMenu(env));
banner.appendChild(optionsMenu(config()));
if (stateBuilder.specsExecuted < totalSpecsDefined) {
var skippedMessage = 'Ran ' + stateBuilder.specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
@@ -328,7 +339,7 @@ jasmineRequire.HtmlReporter = function(j$) {
}
}
function optionsMenu(env) {
function optionsMenu(config) {
var optionsMenuDom = createDom('div', { className: 'jasmine-run-options' },
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
createDom('div', { className: 'jasmine-payload' },
@@ -352,26 +363,39 @@ jasmineRequire.HtmlReporter = function(j$) {
id: 'jasmine-random-order',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order')),
createDom('div', { className: 'jasmine-hide-disabled' },
createDom('input', {
className: 'jasmine-disabled',
id: 'jasmine-hide-disabled',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-hide-disabled' }, 'hide disabled tests'))
)
);
var failFastCheckbox = optionsMenuDom.querySelector('#jasmine-fail-fast');
failFastCheckbox.checked = env.stoppingOnSpecFailure();
failFastCheckbox.checked = config.failFast;
failFastCheckbox.onclick = function() {
navigateWithNewParam('failFast', !env.stoppingOnSpecFailure());
navigateWithNewParam('failFast', !config.failFast);
};
var throwCheckbox = optionsMenuDom.querySelector('#jasmine-throw-failures');
throwCheckbox.checked = env.throwingExpectationFailures();
throwCheckbox.checked = config.oneFailurePerSpec;
throwCheckbox.onclick = function() {
navigateWithNewParam('throwFailures', !env.throwingExpectationFailures());
navigateWithNewParam('throwFailures', !config.oneFailurePerSpec);
};
var randomCheckbox = optionsMenuDom.querySelector('#jasmine-random-order');
randomCheckbox.checked = env.randomTests();
randomCheckbox.checked = config.random;
randomCheckbox.onclick = function() {
navigateWithNewParam('random', !env.randomTests());
navigateWithNewParam('random', !config.random);
};
var hideDisabled = optionsMenuDom.querySelector('#jasmine-hide-disabled');
hideDisabled.checked = config.hideDisabled;
hideDisabled.onclick = function() {
navigateWithNewParam('hideDisabled', !config.hideDisabled);
};
var optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger'),
@@ -600,37 +624,3 @@ jasmineRequire.QueryString = function() {
return QueryString;
};
jasmineRequire.toHaveClass = function(j$) {
/**
* {@link expect} the actual value to be a DOM element that has the expected class
* @function
* @name matchers#toHaveClass
* @param {Object} expected - The class name to test for
* @example
* var el = document.createElement('div');
* el.className = 'foo bar baz';
* expect(el).toHaveClass('bar');
*/
function toHaveClass(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
if (!isElement(actual)) {
throw new Error(j$.pp(actual) + ' is not a DOM element');
}
return {
pass: actual.classList.contains(expected)
};
}
};
}
function isElement(maybeEl) {
return maybeEl &&
maybeEl.classList &&
j$.isFunction_(maybeEl.classList.contains);
}
return toHaveClass;
};

View File

@@ -1,3 +1,4 @@
@charset "UTF-8";
body { overflow-y: scroll; }
.jasmine_html-reporter { background-color: #eee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333; }
@@ -15,15 +16,16 @@ body { overflow-y: scroll; }
.jasmine_html-reporter .jasmine-symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; }
.jasmine_html-reporter .jasmine-symbol-summary li { display: inline-block; height: 10px; width: 14px; font-size: 16px; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed { font-size: 14px; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed:before { color: #007069; content: "\02022"; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed:before { color: #007069; content: ""; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed { line-height: 9px; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed:before { color: #ca3a11; content: "×"; font-weight: bold; margin-left: -1px; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-excluded { font-size: 14px; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-excluded:before { color: #bababa; content: "\02022"; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-excluded:before { color: #bababa; content: ""; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-excluded-no-display { font-size: 14px; display: none; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending { line-height: 17px; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending:before { color: #ba9d37; content: "*"; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty { font-size: 14px; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty:before { color: #ba9d37; content: "\02022"; }
.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty:before { color: #ba9d37; content: ""; }
.jasmine_html-reporter .jasmine-run-options { float: right; margin-right: 5px; border: 1px solid #8a4182; color: #8a4182; position: relative; line-height: 20px; }
.jasmine_html-reporter .jasmine-run-options .jasmine-trigger { cursor: pointer; padding: 8px 16px; }
.jasmine_html-reporter .jasmine-run-options .jasmine-payload { position: absolute; display: none; right: -1px; border: 1px solid #8a4182; background-color: #eee; white-space: nowrap; padding: 4px 8px; }
@@ -33,13 +35,7 @@ body { overflow-y: scroll; }
.jasmine_html-reporter .jasmine-bar.jasmine-passed { background-color: #007069; }
.jasmine_html-reporter .jasmine-bar.jasmine-incomplete { background-color: #bababa; }
.jasmine_html-reporter .jasmine-bar.jasmine-skipped { background-color: #bababa; }
<<<<<<< HEAD
||||||| merged common ancestors
.jasmine_html-reporter .jasmine-bar.jasmine-errored { background-color: #ca3a11; }
=======
.jasmine_html-reporter .jasmine-bar.jasmine-errored { background-color: #ca3a11; }
.jasmine_html-reporter .jasmine-bar.jasmine-warning { background-color: #ba9d37; color: #333; }
>>>>>>> master
.jasmine_html-reporter .jasmine-bar.jasmine-menu { background-color: #fff; color: #aaa; }
.jasmine_html-reporter .jasmine-bar.jasmine-menu a { color: #333; }
.jasmine_html-reporter .jasmine-bar a { color: white; }
@@ -54,12 +50,17 @@ body { overflow-y: scroll; }
.jasmine_html-reporter .jasmine-summary li.jasmine-empty a { color: #ba9d37; }
.jasmine_html-reporter .jasmine-summary li.jasmine-pending a { color: #ba9d37; }
.jasmine_html-reporter .jasmine-summary li.jasmine-excluded a { color: #bababa; }
.jasmine_html-reporter .jasmine-specs li.jasmine-passed a:before { content: "• "; }
.jasmine_html-reporter .jasmine-specs li.jasmine-failed a:before { content: "× "; }
.jasmine_html-reporter .jasmine-specs li.jasmine-empty a:before { content: "* "; }
.jasmine_html-reporter .jasmine-specs li.jasmine-pending a:before { content: "• "; }
.jasmine_html-reporter .jasmine-specs li.jasmine-excluded a:before { content: "• "; }
.jasmine_html-reporter .jasmine-description + .jasmine-suite { margin-top: 0; }
.jasmine_html-reporter .jasmine-suite { margin-top: 14px; }
.jasmine_html-reporter .jasmine-suite a { color: #333; }
.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail { margin-bottom: 28px; }
.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description { background-color: #ca3a11; color: white; }
.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description a { color: white; }
.jasmine_html-reporter .jasmine-result-message { padding-top: 14px; color: #333; white-space: pre; }
.jasmine_html-reporter .jasmine-result-message { padding-top: 14px; color: #333; white-space: pre-wrap; }
.jasmine_html-reporter .jasmine-result-message span.jasmine-result { display: block; }
.jasmine_html-reporter .jasmine-stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666; border: 1px solid #ddd; background: white; white-space: pre; }

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
module.exports = function(jasmineRequire) {
var jasmine = jasmineRequire.core(jasmineRequire);
var env = jasmine.getEnv();
var env = jasmine.getEnv({suppressLoadErrors: true});
var jasmineInterface = jasmineRequire.interface(jasmine, env);

View File

@@ -1 +0,0 @@
../../spec

View File

@@ -4,6 +4,6 @@
#
module Jasmine
module Core
VERSION = "3.0.0"
VERSION = "3.3.0"
end
end

View File

@@ -1,7 +1,7 @@
{
"name": "jasmine-core",
"license": "MIT",
"version": "3.0.0",
"version": "3.3.0",
"repository": {
"type": "git",
"url": "https://github.com/jasmine/jasmine.git"
@@ -16,7 +16,7 @@
"test": "grunt jshint execSpecsInNode"
},
"description": "Official packaging of Jasmine's core files for use by Node.js projects.",
"homepage": "http://jasmine.github.io",
"homepage": "https://jasmine.github.io",
"main": "./lib/jasmine-core.js",
"devDependencies": {
"glob": "~7.1.2",
@@ -26,7 +26,8 @@
"grunt-contrib-compress": "^1.3.0",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-jshint": "^1.0.0",
"jasmine": "^2.5.0",
"jasmine": "^3.0.0",
"jsdom": "^9.12.0",
"load-grunt-tasks": "^0.4.0",
"shelljs": "^0.7.0",
"temp": "~0.8.1"

View File

@@ -10,7 +10,7 @@ There is also a 2.99 release of Jasmine that will present deprecation warnings f
* Replace old "catch exceptions" logic with proper fail fast with error reporting
- Fixes [#414](https://github.com/jasmine/jasmine/issues/414)
- Fixes [jasmine/jasmine-npm#16](https://github.com/jasmine/jasmine/jasmine-npm/issues/16)
- Fixes [jasmine/jasmine-npm#16](https://github.com/jasmine/jasmine-npm/issues/16)
* Detect an Error passed to `done` and add an expectation failure
- Fixes [#567](https://github.com/jasmine/jasmine/issues/567)
@@ -29,6 +29,13 @@ There is also a 2.99 release of Jasmine that will present deprecation warnings f
* Default to running tests in random order
* Additionally, Jasmine 3.0 drops support for older browsers and environments. Notably:
- Internet Explorer 8 and 9
- Ruby 1.x (for the Ruby gem)
- Rails 3.x (for the Ruby gem)
- Python 2.x (for the Python wheel)
- Nodejs 0.x (for the NPM package)
## Changes
* Remove node modules from python wheel, and update languages

54
release_notes/3.1.0.md Normal file
View File

@@ -0,0 +1,54 @@
# Jasmine-Core 3.1 Release Notes
## Summary
This release contains a number of fixes and pull requests
## Pull Requests and Issues
* Display error properties for failed specs
- Merges [#1516](https://github.com/jasmine/jasmine/issues/1516) from @jbunton-atlassian
* Allow node to report load time errors
- Fixes [#1519](https://github.com/jasmine/jasmine/issues/1519)
* Fixing missing semi-colons
- Merges [#1512](https://github.com/jasmine/jasmine/issues/1512) from @Sylhare
* Fixed release notes link
* Added matchers: truthy, falsy, empty and notEmpty
- Merges [#1460](https://github.com/jasmine/jasmine/issues/1460) from @sjolicoeur
* Add API docs for async reporters
* Return <anonymous> for functions that have no actual words between keyword and (
- Also fixes a potential catastrophic backtracking if someone has
severely damaged their own `toString` during test execution.
* Moved toHaveClass matcher into core so that it can be used in Karma
- Fixes [#1503](https://github.com/jasmine/jasmine/issues/1503)
* allow adding a deprecation object
- Merges [#1498](https://github.com/jasmine/jasmine/issues/1498) from @UziTech
* Add CodeTriage badge to jasmine/jasmine
- Merges [#1505](https://github.com/jasmine/jasmine/issues/1505) from @codetriage-readme-bot
* Resolve merge conflict
- Merges [#1501](https://github.com/jasmine/jasmine/issues/1501) from @aptx4869
- Fixes [#1500](https://github.com/jasmine/jasmine/issues/1500)
* Fix release note typo
- Merges [#1499](https://github.com/jasmine/jasmine/issues/1499) @bcaudan
* Only show deprecation for catch exceptions if you tell Jasmine not to catch
- Fixes [#1497](https://github.com/jasmine/jasmine/issues/1497)
* Add notes for environments that have lost support
- Fixes [#1495](https://github.com/jasmine/jasmine/issues/1495)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

83
release_notes/3.2.0.md Normal file
View File

@@ -0,0 +1,83 @@
# Jasmine-Core 3.2 Release Notes
## Summary
This release contains a number of fixes and pull requests
## Changes
* Add spyOnAllFunctions function
- Merges [#1581](https://github.com/jasmine/jasmine/issues/1581) from @aeisenberg
- Fixes [#1421](https://github.com/jasmine/jasmine/issues/1421)
* Improve timeout error message
- Merges [#1567](https://github.com/jasmine/jasmine/issues/1567) from @ikonst
* Fix JSDoc naming for Env functions
- See [#1565](https://github.com/jasmine/jasmine/issues/1565)
* Add documentation for more public functions on Env
- Fixes [#1565](https://github.com/jasmine/jasmine/issues/1565)
* Added a basic set of async matchers
- Fixes [#1447](https://github.com/jasmine/jasmine/issues/1447)
- Fixes [#1547](https://github.com/jasmine/jasmine/issues/1547)
* Properly cascade StopExecutionError's up the tree
- Fixes [#1563](https://github.com/jasmine/jasmine/issues/1563)
* Implemented hiding of disabled specs
- Merges [#1561](https://github.com/jasmine/jasmine/issues/1561) from @SamFare
* Line-break long expectation failure messages
- See [#296](https://github.com/jasmine/jasmine/issues/296)
* Better detection of DOM Nodes for equality
- Fixes [#1172](https://github.com/jasmine/jasmine/issues/1172)
* Fix typo from `incimplete` to `incomplete`
- Merges [#1555](https://github.com/jasmine/jasmine/issues/1555) from @yinm
* Allow omitting the name argument: `createSpy(func)`
- Merges [#1551](https://github.com/jasmine/jasmine/issues/1551) from @riophae
* name new global status stuff correctly in API docs
* Check for accidental global variable creation
* Fixed global variable leak
- Fixes [#1534](https://github.com/jasmine/jasmine/issues/1534)
* Correctly format stack traces for errors with multiline messages
- Fixes [#1526](https://github.com/jasmine/jasmine/issues/1526)
* Change message for extra elements at end of actual array
- Merges [#1527](https://github.com/jasmine/jasmine/issues/1527) from @majidmade
- Fixes [#1485](https://github.com/jasmine/jasmine/issues/1485)
* Report unhandled rejections as globalErrors.
- Merges [#1521](https://github.com/jasmine/jasmine/issues/1521) from @johnjbarton
* add some links to more tutorials from the api docs
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

11
release_notes/3.2.1.md Normal file
View File

@@ -0,0 +1,11 @@
# Jasmine-Core 3.2.1 Release Notes
## Changes
* Correctly expose `spyOnAllFunctions`
- See [#1581](https://github.com/jasmine/jasmine/issues/1581)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

47
release_notes/3.3.0.md Normal file
View File

@@ -0,0 +1,47 @@
# Jasmine Core 3.3 Release Notes
## Summary
This release includes a new way to configure Jasmine, the ability to provide additional
context with your expectations, and other things
## Changes
* Added expect().withContext() to provide additional information in failure messages
* Implement `withContext` for async expectations too
- Fixes [#641](https://github.com/jasmine/jasmine/issues/641)
* New asynchronous matcher `toBeRejectedWith`
- Merges [#1615](https://github.com/jasmine/jasmine/issues/1615) from @codymikol
- Closes [#1600](https://github.com/jasmine/jasmine/issues/1600)
- Fixes [#1595](https://github.com/jasmine/jasmine/issues/1595)
* Show a tip for `toBe` failures for how to get deep equality
- Merges [#1616](https://github.com/jasmine/jasmine/issues/1616) from @tdurtshi
- Fixes [#1614](https://github.com/jasmine/jasmine/issues/1614)
* `expectAsync` now works with non-native promies
- Merges [#1613](https://github.com/jasmine/jasmine/issues/1613) from @codymikol
- Fixes [#1612](https://github.com/jasmine/jasmine/issues/1612)
* Show status marks next to spec description in HTML reporter
- Merges [#1610](https://github.com/jasmine/jasmine/issues/1610) from @m1010j
- Fixes [#1596](https://github.com/jasmine/jasmine/issues/1596)
* Show error messages for `Error`s without a name
- Merges [#1601](https://github.com/jasmine/jasmine/issues/1601) from @nitobuendia
- Fixes [#1594](https://github.com/jasmine/jasmine/issues/1594)
* Optimized clearTimeout cpu usage
- Merges [#1599](https://github.com/jasmine/jasmine/issues/1599) from @Havunen
* Introduce a configuration object to `Env` deprecating old single use functions
- [finishes #159158038](http://www.pivotaltracker.com/story/159158038)
* Specify https for github urls in package.json
- Merges [#1597](https://github.com/jasmine/jasmine/issues/1597) @limonte
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

View File

@@ -0,0 +1,208 @@
describe('AsyncExpectation', function() {
beforeEach(function() {
jasmineUnderTest.Expectation.addAsyncCoreMatchers(jasmineUnderTest.asyncMatchers);
});
describe('Factory', function() {
it('throws an Error if promises are not available', function() {
var thenable = {then: function() {}},
options = {global: {}, actual: thenable}
function f() { jasmineUnderTest.Expectation.asyncFactory(options); }
expect(f).toThrowError('expectAsync is unavailable because the environment does not support promises.');
});
it('throws an Error if the argument is not a promise', function() {
jasmine.getEnv().requirePromises();
function f() {
jasmineUnderTest.Expectation.asyncFactory({actual: 'not a promise'});
}
expect(f).toThrowError('Expected expectAsync to be called with a promise.');
});
});
describe('#not', function() {
it('converts a pass to a fail', function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.resolve(),
expectation = jasmineUnderTest.Expectation.asyncFactory({
util: jasmineUnderTest.matchersUtil,
actual: actual,
addExpectationResult: addExpectationResult
});
return expectation.not.toBeResolved().then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
passed: false,
message: 'Expected a promise not to be resolved.'
})
);
});
});
it('converts a fail to a pass', function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.reject(),
expectation = jasmineUnderTest.Expectation.asyncFactory({
util: jasmineUnderTest.matchersUtil,
actual: actual,
addExpectationResult: addExpectationResult
});
return expectation.not.toBeResolved().then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(true,
jasmine.objectContaining({
passed: true,
message: ''
})
);
});
});
});
it('propagates rejections from the comparison function', function() {
jasmine.getEnv().requirePromises();
var error = new Error('ExpectationSpec failure');
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = dummyPromise(),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: actual,
addExpectationResult: addExpectationResult
});
spyOn(expectation, 'toBeResolved')
.and.returnValue(Promise.reject(error));
return expectation.toBeResolved()
.then(
function() { fail('Expected a rejection'); },
function(e) { expect(e).toBe(error); }
);
});
describe('#withContext', function() {
it("prepends the context to the generated failure message", function() {
jasmine.getEnv().requirePromises();
var util = {
buildFailureMessage: function() { return 'failure message'; }
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: Promise.reject('rejected'),
addExpectationResult: addExpectationResult,
util: util
});
return expectation.withContext('Some context').toBeResolved()
.then(
function() {
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: 'Some context: failure message'
}));
});
});
it("prepends the context to a custom failure message", function() {
jasmine.getEnv().requirePromises();
var util = {
buildFailureMessage: function() { return 'failure message'; }
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: Promise.reject('b'),
addExpectationResult: addExpectationResult,
util: util
});
return expectation.withContext('Some context').toBeResolvedTo('a')
.then(
function() {
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: Expected a promise to be resolved to 'a' but it was rejected."
}));
});
});
it("prepends the context to a custom failure message from a function", function() {
pending('should actually work, but no custom matchers for async yet');
jasmine.getEnv().requirePromises();
var util = {
buildFailureMessage: function() { return 'failure message'; }
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.reject(),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: actual,
addExpectationResult: addExpectationResult,
util: util
});
return expectation.withContext('Some context').toBeResolved()
.then(
function() {
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: 'Some context: msg'
}));
});
});
it("works with #not", function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.resolve(),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: actual,
addExpectationResult: addExpectationResult,
util: jasmineUnderTest.matchersUtil
});
return expectation.withContext('Some context').not.toBeResolved()
.then(
function() {
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: 'Some context: Expected a promise not to be resolved.'
}));
});
});
it("works with #not and a custom message", function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.resolve('a'),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: actual,
addExpectationResult: addExpectationResult,
util: jasmineUnderTest.matchersUtil
});
return expectation.withContext('Some context').not.toBeResolvedTo('a')
.then(
function() {
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: Expected a promise not to be resolved to 'a'."
}));
});
});
});
function dummyPromise() {
return new Promise(function(resolve, reject) {
});
}
});

View File

@@ -669,7 +669,7 @@ describe("Clock (acceptance)", function() {
expect(global.Date().getTime()).toEqual(baseTime.getTime() + 5);
expect(actualTimes).toEqual([baseTime.getTime(), baseTime.getTime() + 1, baseTime.getTime() + 3]);
})
});
it('correctly clears a scheduled timeout while the Clock is advancing', function () {
var delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),

View File

@@ -27,7 +27,7 @@ describe("Env", function() {
});
it('can configure specs to throw errors on expectation failures', function() {
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
spyOn(jasmineUnderTest, 'Spec');
env.it('foo', function() {});
@@ -37,7 +37,7 @@ describe("Env", function() {
});
it('can configure suites to throw errors on expectation failures', function() {
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
spyOn(jasmineUnderTest, 'Suite');
env.describe('foo', function() {});
@@ -46,6 +46,22 @@ describe("Env", function() {
}));
});
it('defaults to multiple failures for specs', function() {
spyOn(jasmineUnderTest, 'Spec');
env.it('bar', function() {});
expect(jasmineUnderTest.Spec).toHaveBeenCalledWith(jasmine.objectContaining({
throwOnExpectationFailure: false
}));
});
it('defaults to multiple failures for suites', function() {
spyOn(jasmineUnderTest, 'Suite');
env.describe('foo', function() {});
expect(jasmineUnderTest.Suite).toHaveBeenCalledWith(jasmine.objectContaining({
throwOnExpectationFailure: false
}));
});
describe('#describe', function () {
it("throws an error when given arguments", function() {
expect(function() {
@@ -197,4 +213,24 @@ describe("Env", function() {
}).not.toThrow();
});
});
describe('when not constructed with suppressLoadErrors: true', function() {
it('installs a global error handler on construction', function() {
var globalErrors = jasmine.createSpyObj('globalErrors', ['install', 'pushListener', 'popListener']);
spyOn(jasmineUnderTest, 'GlobalErrors').and.returnValue(globalErrors);
new jasmineUnderTest.Env();
expect(globalErrors.install).toHaveBeenCalled();
});
});
describe('when constructed with suppressLoadErrors: true', function() {
it('does not install a global error handler until execute is called', function() {
var globalErrors = jasmine.createSpyObj('globalErrors', ['install', 'pushListener', 'popListener']);
spyOn(jasmineUnderTest, 'GlobalErrors').and.returnValue(globalErrors);
env = new jasmineUnderTest.Env({suppressLoadErrors: true});
expect(globalErrors.install).not.toHaveBeenCalled();
env.execute();
expect(globalErrors.install).toHaveBeenCalled();
});
});
});

View File

@@ -37,6 +37,28 @@ describe("ExceptionFormatter", function() {
expect(message).toEqual('A Classic Mistake: you got your foo in my bar');
});
it('formats unnamed exceptions with message', function() {
var unnamedError = {message: 'This is an unnamed error message.'};
var exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
message = exceptionFormatter.message(unnamedError);
expect(message).toEqual('This is an unnamed error message.');
});
it('formats empty exceptions with toString format', function() {
var EmptyError = function() {};
EmptyError.prototype.toString = function() {
return '[EmptyError]';
};
var emptyError = new EmptyError();
var exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
message = exceptionFormatter.message(emptyError);
expect(message).toEqual('[EmptyError] thrown');
});
it("formats thrown exceptions that aren't errors", function() {
var thrown = "crazy error",
exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
@@ -56,6 +78,7 @@ describe("ExceptionFormatter", function() {
it("filters Jasmine stack frames from V8 style traces", function() {
var error = {
message: 'nope',
stack: 'Error: nope\n' +
' at fn1 (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at fn2 (http://localhost:8888/__jasmine__/jasmine.js:4320:20)\n' +
@@ -113,8 +136,38 @@ describe("ExceptionFormatter", function() {
}
});
it("handles multiline error messages in this environment", function() {
var error, i, msg = "an error\nwith two lines";
try { throw new Error(msg); } catch(e) { error = e; }
if (error.stack.indexOf(msg) === -1) {
pending("Stack traces don't have messages in this environment");
}
var subject = new jasmineUnderTest.ExceptionFormatter({
jasmineFile: jasmine.util.jasmineFile()
});
var result = subject.stack(error);
var lines = result.split('\n');
expect(lines[0]).toMatch(/an error/);
expect(lines[1]).toMatch(/with two lines/);
expect(lines[2]).toMatch(/ExceptionFormatterSpec.js/);
expect(lines[3]).toMatch(/<Jasmine>/);
});
it("returns null if no Error provided", function() {
expect(new jasmineUnderTest.ExceptionFormatter().stack()).toBeNull();
});
it("includes error properties in stack", function() {
var error;
try { throw new Error("an error") } catch(e) { error = e; }
error.someProperty = 'hello there';
var result = new jasmineUnderTest.ExceptionFormatter().stack(error);
expect(result).toMatch(/error properties:.*someProperty.*hello there/);
});
});
});

View File

@@ -0,0 +1,113 @@
describe('ExpectationFilterChain', function() {
describe('#addFilter', function() {
it('returns a new filter chain with the added filter', function() {
var first = jasmine.createSpy('first'),
second = jasmine.createSpy('second'),
orig = new jasmineUnderTest.ExpectationFilterChain({
modifyFailureMessage: first
}),
added = orig.addFilter({selectComparisonFunc: second});
added.modifyFailureMessage();
expect(first).toHaveBeenCalled();
added.selectComparisonFunc();
expect(second).toHaveBeenCalled();
});
it('does not modify the original filter chain', function() {
var orig = new jasmineUnderTest.ExpectationFilterChain({}),
f = jasmine.createSpy('f');
orig.addFilter({selectComparisonFunc: f});
orig.selectComparisonFunc();
expect(f).not.toHaveBeenCalled();
});
});
describe('#selectComparisonFunc', function() {
describe('When no filters have #selectComparisonFunc', function() {
it('returns undefined', function() {
var chain = new jasmineUnderTest.ExpectationFilterChain();
chain.addFilter({});
expect(chain.selectComparisonFunc()).toBeUndefined();
});
});
describe('When some filters have #selectComparisonFunc', function() {
it('calls the first filter that has #selectComparisonFunc', function() {
var first = jasmine.createSpy('first').and.returnValue('first'),
second = jasmine.createSpy('second').and.returnValue('second'),
chain = new jasmineUnderTest.ExpectationFilterChain()
.addFilter({selectComparisonFunc: first})
.addFilter({selectComparisonFunc: second}),
matcher = {},
result;
result = chain.selectComparisonFunc(matcher);
expect(first).toHaveBeenCalledWith(matcher);
expect(second).not.toHaveBeenCalled();
expect(result).toEqual('first');
});
});
});
describe('#buildFailureMessage', function() {
describe('When no filters have #buildFailureMessage', function() {
it('returns undefined', function() {
var chain = new jasmineUnderTest.ExpectationFilterChain();
chain.addFilter({});
expect(chain.buildFailureMessage()).toBeUndefined();
});
});
describe('When some filters have #buildFailureMessage', function() {
it('calls the first filter that has #buildFailureMessage', function() {
var first = jasmine.createSpy('first').and.returnValue('first'),
second = jasmine.createSpy('second').and.returnValue('second'),
chain = new jasmineUnderTest.ExpectationFilterChain()
.addFilter({buildFailureMessage: first})
.addFilter({buildFailureMessage: second}),
matcherResult = {pass: false},
matcherName = 'foo',
args = [],
util = {},
result;
result = chain.buildFailureMessage(matcherResult, matcherName, args, util);
expect(first).toHaveBeenCalledWith(matcherResult, matcherName, args, util);
expect(second).not.toHaveBeenCalled();
expect(result).toEqual('first');
});
});
});
describe('#modifyFailureMessage', function() {
describe('When no filters have #modifyFailureMessage', function() {
it('returns the original message', function() {
var chain = new jasmineUnderTest.ExpectationFilterChain();
chain.addFilter({});
expect(chain.modifyFailureMessage('msg')).toEqual('msg');
});
});
describe('When some filters have #modifyFailureMessage', function() {
it('calls the first filter that has #modifyFailureMessage', function() {
var first = jasmine.createSpy('first').and.returnValue('first'),
second = jasmine.createSpy('second').and.returnValue('second'),
chain = new jasmineUnderTest.ExpectationFilterChain()
.addFilter({modifyFailureMessage: first})
.addFilter({modifyFailureMessage: second}),
result;
result = chain.modifyFailureMessage('original');
expect(first).toHaveBeenCalledWith('original');
expect(second).not.toHaveBeenCalled();
expect(result).toEqual('first');
});
});
});
});

View File

@@ -44,6 +44,21 @@ describe("buildExpectationResult", function() {
expect(result.stack).toEqual('foo');
});
it("delegates stack formatting to the provided formatter if there was a provided errorForStack", function() {
var fakeError = {stack: 'foo'},
stackFormatter = jasmine.createSpy("stack formatter").and.returnValue(fakeError.stack);
var result = jasmineUnderTest.buildExpectationResult(
{
passed: false,
errorForStack: fakeError,
stackFormatter: stackFormatter
});
expect(stackFormatter).toHaveBeenCalledWith(fakeError);
expect(result.stack).toEqual('foo');
});
it("matcherName returns passed matcherName", function() {
var result = jasmineUnderTest.buildExpectationResult({matcherName: 'some-value'});
expect(result.matcherName).toBe('some-value');

View File

@@ -6,7 +6,7 @@ describe("Expectation", function() {
},
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers
});
@@ -22,31 +22,25 @@ describe("Expectation", function() {
jasmineUnderTest.Expectation.addCoreMatchers(coreMatchers);
expectation = new jasmineUnderTest.Expectation({});
expectation = jasmineUnderTest.Expectation.factory({});
expect(expectation.toQuux).toBeDefined();
});
it("Factory builds an expectation/negative expectation", function() {
var builtExpectation = jasmineUnderTest.Expectation.Factory();
expect(builtExpectation instanceof jasmineUnderTest.Expectation).toBe(true);
expect(builtExpectation.not instanceof jasmineUnderTest.Expectation).toBe(true);
expect(builtExpectation.not.isNot).toBe(true);
});
it("wraps matchers's compare functions, passing in matcher dependencies", function() {
var fakeCompare = function() { return { pass: true }; },
matcherFactory = jasmine.createSpy("matcher").and.returnValue({ compare: fakeCompare }),
matchers = {
toFoo: matcherFactory
},
util = {},
util = {
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
},
customEqualityTesters = ['a'],
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
util: util,
customMatchers: matchers,
customEqualityTesters: customEqualityTesters,
@@ -74,7 +68,7 @@ describe("Expectation", function() {
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
util: util,
customMatchers: matchers,
actual: "an actual",
@@ -100,7 +94,7 @@ describe("Expectation", function() {
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
util: util,
actual: "an actual",
@@ -115,7 +109,8 @@ describe("Expectation", function() {
message: "",
error: undefined,
expected: "hello",
actual: "an actual"
actual: "an actual",
errorForStack: undefined
});
});
@@ -133,7 +128,7 @@ describe("Expectation", function() {
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
util: util,
actual: "an actual",
@@ -148,7 +143,8 @@ describe("Expectation", function() {
expected: "hello",
actual: "an actual",
message: "",
error: undefined
error: undefined,
errorForStack: undefined
});
});
@@ -168,7 +164,7 @@ describe("Expectation", function() {
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
actual: "an actual",
customMatchers: matchers,
addExpectationResult: addExpectationResult
@@ -182,7 +178,8 @@ describe("Expectation", function() {
expected: "hello",
actual: "an actual",
message: "I am a custom message",
error: undefined
error: undefined,
errorForStack: undefined
});
});
@@ -202,7 +199,7 @@ describe("Expectation", function() {
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult
@@ -216,7 +213,8 @@ describe("Expectation", function() {
expected: "hello",
actual: "an actual",
message: "I am a custom message",
error: undefined
error: undefined,
errorForStack: undefined
});
});
@@ -235,12 +233,11 @@ describe("Expectation", function() {
actual = "an actual",
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
@@ -250,7 +247,8 @@ describe("Expectation", function() {
message: "",
error: undefined,
expected: "hello",
actual: actual
actual: actual,
errorForStack: undefined
});
});
@@ -269,13 +267,12 @@ describe("Expectation", function() {
actual = "an actual",
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
util: util,
addExpectationResult: addExpectationResult,
isNot: true
});
}).not;
expectation.toFoo("hello");
@@ -285,7 +282,8 @@ describe("Expectation", function() {
expected: "hello",
actual: actual,
message: "default message",
error: undefined
error: undefined,
errorForStack: undefined
});
});
@@ -306,12 +304,11 @@ describe("Expectation", function() {
actual = "an actual",
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
@@ -321,7 +318,8 @@ describe("Expectation", function() {
expected: "hello",
actual: actual,
message: "I am a custom message",
error: undefined
error: undefined,
errorForStack: undefined
});
});
@@ -338,12 +336,11 @@ describe("Expectation", function() {
actual = "an actual",
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
@@ -353,7 +350,8 @@ describe("Expectation", function() {
expected: "hello",
actual: actual,
message: "",
error: undefined
error: undefined,
errorForStack: undefined
});
});
@@ -375,12 +373,11 @@ describe("Expectation", function() {
actual = "an actual",
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
}).not;
expectation.toFoo("hello");
@@ -390,10 +387,11 @@ describe("Expectation", function() {
expected: "hello",
actual: actual,
message: "I'm a custom message",
error: undefined
error: undefined,
errorForStack: undefined
});
});
it("reports a custom error message to the spec", function() {
var customError = new Error("I am a custom error");
var matchers = {
@@ -412,7 +410,7 @@ describe("Expectation", function() {
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
actual: "an actual",
customMatchers: matchers,
addExpectationResult: addExpectationResult
@@ -426,9 +424,222 @@ describe("Expectation", function() {
expected: "hello",
actual: "an actual",
message: "I am a custom message",
error: customError
error: customError,
errorForStack: undefined
});
});
it("reports a custom message to the spec when a 'not' comparison fails", function() {
var customError = new Error("I am a custom error");
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: true,
message: "I am a custom message",
error: customError
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = jasmineUnderTest.Expectation.factory({
actual: "an actual",
customMatchers: matchers,
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
passed: false,
expected: "hello",
actual: "an actual",
message: "I am a custom message",
error: customError,
errorForStack: undefined
});
});
it("reports a custom message func to the spec when a 'not' comparison fails", function() {
var customError = new Error("I am a custom error");
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: true,
message: function() { return "I am a custom message"; },
error: customError
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
expectation = jasmineUnderTest.Expectation.factory({
actual: "an actual",
customMatchers: matchers,
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
passed: false,
expected: "hello",
actual: "an actual",
message: "I am a custom message",
error: customError,
errorForStack: undefined
});
});
describe("#withContext", function() {
it("prepends the context to the generated failure message", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: false }; }
};
}
},
util = {
buildFailureMessage: function() { return "failure message"; }
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
util: util,
actual: "an actual",
addExpectationResult: addExpectationResult
});
expectation.withContext("Some context").toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: failure message"
})
);
});
it("prepends the context to a custom failure message", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: false, message: "msg" }; }
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult
});
expectation.withContext("Some context").toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: msg"
})
);
});
it("prepends the context to a custom failure message from a function", function() {
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: false,
message: function() { return "msg"; }
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult
});
expectation.withContext("Some context").toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: msg"
})
);
});
it("works with #not", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: true }; }
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
util: jasmineUnderTest.matchersUtil,
actual: "an actual",
addExpectationResult: addExpectationResult
});
expectation.withContext("Some context").not.toFoo();
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: Expected 'an actual' not to foo."
})
);
});
it("works with #not and a custom message", function() {
var customError = new Error("I am a custom error");
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: true,
message: function() { return "I am a custom message"; },
error: customError
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation = jasmineUnderTest.Expectation.factory({
actual: "an actual",
customMatchers: matchers,
addExpectationResult: addExpectationResult
});
expectation.withContext("Some context").not.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false,
jasmine.objectContaining({
message: "Some context: I am a custom message",
})
);
});
});
});

View File

@@ -78,7 +78,7 @@ describe("GlobalErrors", function() {
errors.uninstall();
});
it("works in node.js", function() {
it("reports uncaughtException in node.js", function() {
var fakeGlobal = {
process: {
on: jasmine.createSpy('process.on'),
@@ -107,4 +107,34 @@ describe("GlobalErrors", function() {
expect(fakeGlobal.process.removeListener).toHaveBeenCalledWith('uncaughtException', addedListener);
expect(fakeGlobal.process.on).toHaveBeenCalledWith('uncaughtException', 'foo');
});
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);
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);
var addedListener = fakeGlobal.process.on.calls.argsFor(0)[1];
addedListener(new Error('bar'));
expect(handler).toHaveBeenCalledWith(new Error('bar'));
errors.uninstall();
expect(fakeGlobal.process.removeListener).toHaveBeenCalledWith('unhandledRejection', addedListener);
expect(fakeGlobal.process.on).toHaveBeenCalledWith('unhandledRejection', 'foo');
});
});

View File

@@ -183,7 +183,7 @@ describe("QueueRunner", function() {
it("sets a timeout if requested for asynchronous functions so they don't go on forever", function() {
var timeout = 3,
beforeFn = { fn: function(done) { }, type: 'before', timeout: function() { return timeout; } },
beforeFn = { fn: function(done) { }, type: 'before', timeout: timeout },
queueableFn = { fn: jasmine.createSpy('fn'), type: 'queueable' },
onComplete = jasmine.createSpy('onComplete'),
onException = jasmine.createSpy('onException'),
@@ -304,7 +304,7 @@ describe("QueueRunner", function() {
});
it("continues running functions when an exception is thrown in async code without timing out", function() {
var queueableFn = { fn: function(done) { throwAsync(); }, timeout: function() { return 1; } },
var queueableFn = { fn: function(done) { throwAsync(); }, timeout: 1 },
nextQueueableFn = { fn: jasmine.createSpy("nextFunction") },
onException = jasmine.createSpy('onException'),
globalErrors = { pushListener: jasmine.createSpy('pushListener'), popListener: jasmine.createSpy('popListener') },
@@ -481,15 +481,18 @@ describe("QueueRunner", function() {
var queueableFn = { fn: function() { throw new Error("error"); } },
nextQueueableFn = { fn: jasmine.createSpy("nextFunction") },
cleanupFn = { fn: jasmine.createSpy("cleanup") },
onComplete = jasmine.createSpy("onComplete"),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn, nextQueueableFn],
cleanupFns: [cleanupFn],
onComplete: onComplete,
completeOnFirstError: true
});
queueRunner.execute();
expect(nextQueueableFn.fn).not.toHaveBeenCalled();
expect(cleanupFn.fn).toHaveBeenCalled();
expect(onComplete).toHaveBeenCalledWith(jasmine.any(jasmineUnderTest.StopExecutionError));
});
it("does not skip when a cleanup function throws", function() {

View File

@@ -214,6 +214,97 @@ describe("SpyRegistry", function() {
});
});
describe("#spyOnAllFunctions", function() {
it("checks for the existence of the object", function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry();
expect(function() {
spyRegistry.spyOnAllFunctions(void 0);
}).toThrowError(/spyOnAllFunctions could not find an object to spy upon/);
});
it("overrides all writable and configurable functions of the object", function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({createSpy: function() {
return 'I am a spy';
}});
var createNoop = function() { return function() { /**/}; };
var noop1 = createNoop();
var noop2 = createNoop();
var noop3 = createNoop();
var noop4 = createNoop();
var noop5 = createNoop();
var parent = {
notSpied1: noop1
};
var subject = Object.create(parent);
Object.defineProperty(subject, 'spied1', {
value: noop1,
writable: true,
configurable: true,
enumerable: true
});
Object.defineProperty(subject, 'spied2', {
value: noop2,
writable: true,
configurable: true,
enumerable: true
});
var _spied3 = noop3;
Object.defineProperty(subject, 'spied3', {
configurable: true,
set: function (val) {
_spied3 = val;
},
get: function() {
return _spied3;
},
enumerable: true
});
subject.spied4 = noop4;
Object.defineProperty(subject, 'notSpied2', {
value: noop2,
writable: false,
configurable: true,
enumerable: true
});
Object.defineProperty(subject, 'notSpied3', {
value: noop3,
writable: true,
configurable: false,
enumerable: true
});
Object.defineProperty(subject, 'notSpied4', {
configurable: false,
set: function(val) { /**/ },
get: function() {
return noop4;
},
enumerable: true
});
Object.defineProperty(subject, 'notSpied5', {
value: noop5,
writable: true,
configurable: true,
enumerable: false
});
subject.notSpied6 = 6;
var spiedObject = spyRegistry.spyOnAllFunctions(subject);
expect(subject.notSpied1).toBe(noop1);
expect(subject.notSpied2).toBe(noop2);
expect(subject.notSpied3).toBe(noop3);
expect(subject.notSpied4).toBe(noop4);
expect(subject.notSpied5).toBe(noop5);
expect(subject.notSpied6).toBe(6);
expect(subject.spied1).toBe('I am a spy');
expect(subject.spied2).toBe('I am a spy');
expect(subject.spied3).toBe('I am a spy');
expect(subject.spied4).toBe('I am a spy');
expect(spiedObject).toBe(subject);
});
});
describe("#clearSpies", function() {
it("restores the original functions on the spied-upon objects", function() {
var spies = [],

View File

@@ -20,6 +20,18 @@ describe('Spies', function () {
expect(spy.bob).toEqual("test");
});
it("should allow you to omit the name argument and only pass the originalFn argument", function() {
var fn = function test() {};
var spy = env.createSpy(fn);
// IE doesn't do `.name`
if (fn.name === "test") {
expect(spy.and.identity).toEqual("test");
} else {
expect(spy.and.identity).toEqual("unknown");
}
})
it("warns the user that we intend to overwrite an existing property", function() {
TestClass.prototype.someFunction.and = "turkey";

View File

@@ -1,11 +1,14 @@
describe("StackTrace", function() {
it("understands Chrome/IE/Edge style traces", function() {
var raw =
'Error: nope\n' +
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)';
var error = {
message: 'nope',
stack:
'Error: nope\n' +
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
};
var result = new jasmineUnderTest.StackTrace(raw);
var result = new jasmineUnderTest.StackTrace(error);
expect(result.message).toEqual('Error: nope');
expect(result.style).toEqual('v8');
@@ -25,13 +28,36 @@ describe("StackTrace", function() {
]);
});
it("understands Chrome/IE/Edge style traces with multiline messages", function() {
var error = {
message: 'line 1\nline 2',
stack:
'Error: line 1\nline 2\n' +
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.message).toEqual('Error: line 1\nline 2');
var rawFrames = result.frames.map(function(f) { return f.raw; });
expect(rawFrames).toEqual([
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
]);
});
it("understands Node style traces", function() {
var raw = 'Error\n' +
' at /somewhere/jasmine/lib/jasmine-core/jasmine.js:4255:9\n' +
' at QueueRunner.complete [as onComplete] (/somewhere/jasmine/lib/jasmine-core/jasmine.js:579:9)\n' +
' at Immediate.<anonymous> (/somewhere/jasmine/lib/jasmine-core/jasmine.js:4314:12)\n' +
' at runCallback (timers.js:672:20)';
var result = new jasmineUnderTest.StackTrace(raw);
var error = {
message: 'nope',
stack:
'Error\n' +
' at /somewhere/jasmine/lib/jasmine-core/jasmine.js:4255:9\n' +
' at QueueRunner.complete [as onComplete] (/somewhere/jasmine/lib/jasmine-core/jasmine.js:579:9)\n' +
' at Immediate.<anonymous> (/somewhere/jasmine/lib/jasmine-core/jasmine.js:4314:12)\n' +
' at runCallback (timers.js:672:20)'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.message).toEqual('Error');
expect(result.style).toEqual('v8');
@@ -64,10 +90,13 @@ describe("StackTrace", function() {
});
it("understands Safari/Firefox/Phantom-OS X style traces", function() {
var raw =
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
'run@http://localhost:8888/__jasmine__/jasmine.js:4320:27';
var result = new jasmineUnderTest.StackTrace(raw);
var error = {
message: 'nope',
stack:
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
'run@http://localhost:8888/__jasmine__/jasmine.js:4320:27'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.message).toBeFalsy();
expect(result.style).toEqual('webkit');
@@ -88,20 +117,26 @@ describe("StackTrace", function() {
});
it("does not mistake gibberish for Safari/Firefox/Phantom-OS X style traces", function() {
var raw = 'randomcharsnotincludingwhitespace';
var result = new jasmineUnderTest.StackTrace(raw);
var error = {
message: 'nope',
stack: 'randomcharsnotincludingwhitespace'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.style).toBeNull();
expect(result.frames).toEqual([
{ raw: raw }
{ raw: error.stack }
]);
});
it("understands Phantom-Linux style traces", function() {
var raw =
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)';
var error = {
message: 'nope',
stack:
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
};
var result = new jasmineUnderTest.StackTrace(raw);
var result = new jasmineUnderTest.StackTrace(error);
expect(result.message).toBeFalsy();
expect(result.style).toEqual('v8');
@@ -122,10 +157,13 @@ describe("StackTrace", function() {
});
it("ignores blank lines", function() {
var raw =
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n';
var error = {
message: 'nope',
stack:
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n'
};
var result = new jasmineUnderTest.StackTrace(raw);
var result = new jasmineUnderTest.StackTrace(error);
expect(result.frames).toEqual([
{
@@ -138,12 +176,15 @@ describe("StackTrace", function() {
});
it("omits properties except 'raw' for frames that are not understood", function() {
var raw =
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' but this is quite unexpected\n' +
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)';
var error = {
message: 'nope',
stack:
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' but this is quite unexpected\n' +
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
};
var result = new jasmineUnderTest.StackTrace(raw);
var result = new jasmineUnderTest.StackTrace(error);
expect(result.style).toEqual('v8');
expect(result.frames).toEqual([
{

View File

@@ -297,7 +297,7 @@ describe("TreeProcessor", function() {
node.getResult.and.returnValue({ my: 'result' });
queueRunner.calls.mostRecent().args[0].onComplete();
expect(nodeComplete).toHaveBeenCalledWith(node, { my: 'result' }, nodeDone);
expect(nodeComplete).toHaveBeenCalledWith(node, { my: 'result' }, jasmine.any(Function));
});
it("runs a node with children", function() {
@@ -328,6 +328,37 @@ describe("TreeProcessor", function() {
expect(leaf2.execute).toHaveBeenCalledWith('bar', false);
});
it("cascades errors up the tree", function() {
var leaf = new Leaf(),
node = new Node({ children: [leaf] }),
root = new Node({ children: [node] }),
queueRunner = jasmine.createSpy('queueRunner'),
nodeComplete = jasmine.createSpy('nodeComplete'),
processor = new jasmineUnderTest.TreeProcessor({
tree: root,
runnableIds: [node.id],
nodeComplete: nodeComplete,
queueRunnerFactory: queueRunner
}),
treeComplete = jasmine.createSpy('treeComplete'),
nodeDone = jasmine.createSpy('nodeDone');
processor.execute(treeComplete);
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
queueableFns[0].fn(nodeDone);
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns.length).toBe(2);
queueableFns[1].fn('foo');
expect(leaf.execute).toHaveBeenCalledWith('foo', false);
queueRunner.calls.mostRecent().args[0].onComplete('things');
expect(nodeComplete).toHaveBeenCalled();
nodeComplete.calls.mostRecent().args[2]();
expect(nodeDone).toHaveBeenCalledWith('things');
});
it("runs an excluded node with leaf", function() {
var leaf1 = new Leaf(),
node = new Node({ children: [leaf1] }),
@@ -361,7 +392,7 @@ describe("TreeProcessor", function() {
node.getResult.and.returnValue({ im: 'disabled' });
queueRunner.calls.mostRecent().args[0].onComplete();
expect(nodeComplete).toHaveBeenCalledWith(node, { im: 'disabled' }, nodeDone);
expect(nodeComplete).toHaveBeenCalledWith(node, { im: 'disabled' }, jasmine.any(Function));
});
it("runs beforeAlls for a node with children", function() {

View File

@@ -32,7 +32,7 @@ describe("UserContext", function() {
describe('when using a regular object as parameter', function() {
beforeEach(function() {
this.context = {};
this.value = 'value'
this.value = 'value';
this.context.key = this.value;
this.cloned = jasmineUnderTest.UserContext.fromExisting(this.context);
});

View File

@@ -31,6 +31,105 @@ describe("jasmineUnderTest.util", function() {
});
});
describe("promise utils", function () {
var mockNativePromise,
mockPromiseLikeObject;
var mockPromiseLike = function () {this.then = function () {};};
beforeEach(function () {
jasmine.getEnv().requirePromises();
mockNativePromise = new Promise(function (res, rej) {});
mockPromiseLikeObject = new mockPromiseLike();
});
describe("isPromise", function () {
it("should return true when passed a native promise", function () {
expect(jasmineUnderTest.isPromise(mockNativePromise)).toBe(true);
});
it("should return false for promise like objects", function () {
expect(jasmineUnderTest.isPromise(mockPromiseLikeObject)).toBe(false);
});
it("should return false for strings", function () {
expect(jasmineUnderTest.isPromise("hello")).toBe(false);
});
it("should return false for numbers", function () {
expect(jasmineUnderTest.isPromise(3)).toBe(false);
});
it("should return false for null", function () {
expect(jasmineUnderTest.isPromise(null)).toBe(false);
});
it("should return false for undefined", function () {
expect(jasmineUnderTest.isPromise(undefined)).toBe(false);
});
it("should return false for arrays", function () {
expect(jasmineUnderTest.isPromise([])).toBe(false);
});
it("should return false for objects", function () {
expect(jasmineUnderTest.isPromise({})).toBe(false);
});
it("should return false for boolean values", function () {
expect(jasmineUnderTest.isPromise(true)).toBe(false);
});
});
describe("isPromiseLike", function () {
it("should return true when passed a native promise", function () {
expect(jasmineUnderTest.isPromiseLike(mockNativePromise)).toBe(true);
});
it("should return true for promise like objects", function () {
expect(jasmineUnderTest.isPromiseLike(mockPromiseLikeObject)).toBe(true);
});
it("should return false if then is not a function", function () {
expect(jasmineUnderTest.isPromiseLike({then:{its:"Not a function :O"}})).toBe(false);
});
it("should return false for strings", function () {
expect(jasmineUnderTest.isPromiseLike("hello")).toBe(false);
});
it("should return false for numbers", function () {
expect(jasmineUnderTest.isPromiseLike(3)).toBe(false);
});
it("should return false for null", function () {
expect(jasmineUnderTest.isPromiseLike(null)).toBe(false);
});
it("should return false for undefined", function () {
expect(jasmineUnderTest.isPromiseLike(undefined)).toBe(false);
});
it("should return false for arrays", function () {
expect(jasmineUnderTest.isPromiseLike([])).toBe(false);
});
it("should return false for objects", function () {
expect(jasmineUnderTest.isPromiseLike({})).toBe(false);
});
it("should return false for boolean values", function () {
expect(jasmineUnderTest.isPromiseLike(true)).toBe(false);
});
});
});
describe("isUndefined", function() {
it("reports if a variable is defined", function() {
var a;

View File

@@ -0,0 +1,51 @@
describe("Empty", function () {
it("matches an empty object", function () {
var empty = new jasmineUnderTest.Empty();
expect(empty.asymmetricMatch({})).toBe(true);
expect(empty.asymmetricMatch({undefined: false})).toBe(false);
});
it("matches an empty array", function () {
var empty = new jasmineUnderTest.Empty();
expect(empty.asymmetricMatch([])).toBe(true);
expect(empty.asymmetricMatch([1, 12, 3])).toBe(false);
});
it("matches an empty string", function () {
var empty = new jasmineUnderTest.Empty();
expect(empty.asymmetricMatch("")).toBe(true);
expect(empty.asymmetricMatch('')).toBe(true);
expect(empty.asymmetricMatch('12312')).toBe(false);
});
it("matches an empty map", function () {
jasmine.getEnv().requireFunctioningMaps();
var empty = new jasmineUnderTest.Empty();
var fullMap = new Map();
fullMap.set('thing', 2);
expect(empty.asymmetricMatch(new Map())).toBe(true);
expect(empty.asymmetricMatch(fullMap)).toBe(false);
});
it("matches an empty set", function () {
jasmine.getEnv().requireFunctioningSets();
var empty = new jasmineUnderTest.Empty();
var fullSet = new Set();
fullSet.add(3);
expect(empty.asymmetricMatch(new Set())).toBe(true);
expect(empty.asymmetricMatch(fullSet)).toBe(false);
});
it("matches an empty typed array", function() {
jasmine.getEnv().requireFunctioningTypedArrays();
var empty = new jasmineUnderTest.Empty();
expect(empty.asymmetricMatch(new Int16Array())).toBe(true);
expect(empty.asymmetricMatch(new Int16Array([1,2]))).toBe(false);
});
});

View File

@@ -0,0 +1,38 @@
describe("Falsy", function() {
it("is true for an empty string", function() {
var falsy = new jasmineUnderTest.Falsy();
expect(falsy.asymmetricMatch("")).toBe(true);
expect(falsy.asymmetricMatch('')).toBe(true);
expect(falsy.asymmetricMatch('asdasdad')).toBe(false);
});
it("is false for a number that is 0", function() {
var falsy = new jasmineUnderTest.Falsy(Number);
expect(falsy.asymmetricMatch(1)).toBe(false);
expect(falsy.asymmetricMatch(0)).toBe(true);
expect(falsy.asymmetricMatch(-23)).toBe(false);
expect(falsy.asymmetricMatch(-3.1)).toBe(false);
});
it("is true for a null or undefined", function() {
var falsy = new jasmineUnderTest.Falsy(Function);
expect(falsy.asymmetricMatch(null)).toBe(true);
expect(falsy.asymmetricMatch(undefined )).toBe(true);
});
it("is true for NaN", function() {
var falsy = new jasmineUnderTest.Falsy(Object);
expect(falsy.asymmetricMatch(NaN)).toBe(true);
});
it("is true for a false Boolean", function() {
var falsy = new jasmineUnderTest.Falsy(Boolean);
expect(falsy.asymmetricMatch(false)).toBe(true);
expect(falsy.asymmetricMatch(true)).toBe(false);
});
});

View File

@@ -0,0 +1,53 @@
describe("NotEmpty", function () {
it("matches a non empty object", function () {
var notEmpty = new jasmineUnderTest.NotEmpty();
expect(notEmpty.asymmetricMatch({undefined: false})).toBe(true);
expect(notEmpty.asymmetricMatch({})).toBe(false);
});
it("matches a non empty array", function () {
var notEmpty = new jasmineUnderTest.NotEmpty();
expect(notEmpty.asymmetricMatch([1, 12, 3])).toBe(true);
expect(notEmpty.asymmetricMatch([])).toBe(false);
});
it("matches a non empty string", function () {
var notEmpty = new jasmineUnderTest.NotEmpty();
expect(notEmpty.asymmetricMatch('12312')).toBe(true);
expect(notEmpty.asymmetricMatch("")).toBe(false);
expect(notEmpty.asymmetricMatch('')).toBe(false);
});
it("matches a non empty map", function () {
jasmine.getEnv().requireFunctioningMaps();
var notEmpty = new jasmineUnderTest.NotEmpty();
var fullMap = new Map();
fullMap.set('one', 1);
var emptyMap = new Map();
expect(notEmpty.asymmetricMatch(fullMap)).toBe(true);
expect(notEmpty.asymmetricMatch(emptyMap)).toBe(false);
});
it("matches a non empty set", function () {
jasmine.getEnv().requireFunctioningSets();
var notEmpty = new jasmineUnderTest.NotEmpty();
var filledSet = new Set();
filledSet.add(1);
var emptySet = new Set();
expect(notEmpty.asymmetricMatch(filledSet)).toBe(true);
expect(notEmpty.asymmetricMatch(emptySet)).toBe(false);
});
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);
expect(notEmpty.asymmetricMatch(new Int16Array())).toBe(false);
});
});

View File

@@ -0,0 +1,63 @@
describe("Truthy", function () {
it("is true for a non empty string", function () {
var truthy = new jasmineUnderTest.Truthy();
expect(truthy.asymmetricMatch("foo")).toBe(true);
expect(truthy.asymmetricMatch("")).toBe(false);
});
it("is true for a number that is not 0", function () {
var truthy = new jasmineUnderTest.Truthy();
expect(truthy.asymmetricMatch(1)).toBe(true);
expect(truthy.asymmetricMatch(0)).toBe(false);
expect(truthy.asymmetricMatch(-23)).toBe(true);
expect(truthy.asymmetricMatch(-3.1)).toBe(true);
});
it("is true for a function", function () {
var truthy = new jasmineUnderTest.Truthy();
expect(truthy.asymmetricMatch(function () {
})).toBe(true);
});
it("is true for an Object", function () {
var truthy = new jasmineUnderTest.Truthy();
expect(truthy.asymmetricMatch({})).toBe(true);
});
it("is true for a truthful Boolean", function () {
var truthy = new jasmineUnderTest.Truthy();
expect(truthy.asymmetricMatch(true)).toBe(true);
expect(truthy.asymmetricMatch(false)).toBe(false);
});
it("is true for an empty object", function () {
var truthy = new jasmineUnderTest.Truthy();
expect(truthy.asymmetricMatch({})).toBe(true);
});
it("is true for an empty array", function () {
var truthy = new jasmineUnderTest.Truthy();
expect(truthy.asymmetricMatch([])).toBe(true);
});
it("is true for a date", function () {
var truthy = new jasmineUnderTest.Truthy();
expect(truthy.asymmetricMatch(new Date())).toBe(true);
});
it("is true for a infiniti", function () {
var truthy = new jasmineUnderTest.Truthy();
expect(truthy.asymmetricMatch(Infinity)).toBe(true);
expect(truthy.asymmetricMatch(-Infinity)).toBe(true);
});
});

View File

@@ -4,7 +4,7 @@ describe("Custom Matchers (Integration)", function() {
beforeEach(function() {
env = new jasmineUnderTest.Env();
env.randomizeTests(false);
env.configure({random: false});
});
it("allows adding more matchers local to a spec", function(done) {
@@ -121,7 +121,7 @@ describe("Custom Matchers (Integration)", function() {
var specExpectations = function(result) {
expect(result.status).toEqual('passed');
}
};
env.addReporter({ specDone: specExpectations, jasmineDone: done });
env.execute();

View File

@@ -3,7 +3,7 @@ describe('Custom Spy Strategies (Integration)', function() {
beforeEach(function() {
env = new jasmineUnderTest.Env();
env.randomizeTests(false);
env.configure({random: false});
});
it('allows adding more strategies local to a suite', function(done) {

View File

@@ -17,7 +17,7 @@ describe("Env integration", function() {
};
env.addReporter({ jasmineDone: assertions});
env.randomizeTests(false);
env.configure({random: false});
env.describe("A Suite", function() {
env.it("with a spec", function() {
@@ -46,7 +46,7 @@ describe("Env integration", function() {
};
env.addReporter({ jasmineDone: assertions });
env.randomizeTests(false);
env.configure({random: false});
env.describe("Outer suite", function() {
env.it("an outer spec", function() {
@@ -81,7 +81,7 @@ describe("Env integration", function() {
};
env.addReporter({ jasmineDone: assertions });
env.randomizeTests(false);
env.configure({random: false});
env.describe("Outer suite", function() {
@@ -200,7 +200,7 @@ describe("Env integration", function() {
var env = new jasmineUnderTest.Env();
env.addReporter({jasmineDone: done});
env.randomizeTests(false);
env.configure({random: false});
env.describe("tests", function() {
var firstTimeThrough = true, firstSpecContext, secondSpecContext;
@@ -783,9 +783,11 @@ describe("Env integration", function() {
});
});
env.specFilter = function(spec) {
return /^first suite/.test(spec.getFullName());
};
env.configure({
specFilter: function(spec) {
return /^first suite/.test(spec.getFullName());
}
});
env.execute();
});
@@ -892,7 +894,7 @@ describe("Env integration", function() {
};
env.describe('test suite', function() {
env.beforeAll(function() { env.spyOn(testObj, 'foo');})
env.beforeAll(function() { env.spyOn(testObj, 'foo');});
env.it('spec 0', function() {
expect(jasmineUnderTest.isSpy(testObj.foo)).toBe(true);
@@ -940,10 +942,10 @@ describe("Env integration", function() {
});
it("Mock clock can be installed and used in tests", function(done) {
var globalSetTimeout = jasmine.createSpy('globalSetTimeout'),
var globalSetTimeout = jasmine.createSpy('globalSetTimeout').and.callFake(function(cb, t) { setTimeout(cb, t); }),
delayedFunctionForGlobalClock = jasmine.createSpy('delayedFunctionForGlobalClock'),
delayedFunctionForMockClock = jasmine.createSpy('delayedFunctionForMockClock'),
env = new jasmineUnderTest.Env({global: { setTimeout: globalSetTimeout }});
env = new jasmineUnderTest.Env({global: { setTimeout: globalSetTimeout, clearTimeout: clearTimeout, setImmediate: function(cb) { setTimeout(cb, 0); } }});
var assertions = function() {
expect(delayedFunctionForMockClock).toHaveBeenCalled();
@@ -953,7 +955,7 @@ describe("Env integration", function() {
};
env.addReporter({ jasmineDone: assertions });
env.randomizeTests(false);
env.configure({random: false});
env.describe("tests", function() {
env.it("test with mock clock", function() {
@@ -1005,6 +1007,25 @@ describe("Env integration", function() {
describe("with a mock clock", function() {
var realSetTimeout;
function createMockedEnv() {
// explicitly pass in timing functions so we can make sure that clear stack always works
// no matter how long the suite in the spec is
return new jasmineUnderTest.Env({ global: {
setTimeout: function(cb, t) {
var stack = jasmine.util.errorWithStack().stack;
if (stack.indexOf('ClearStack') >= 0) {
realSetTimeout(cb, t);
} else {
setTimeout(cb, t);
}
},
clearTimeout: clearTimeout,
setInterval: setInterval,
clearInterval: clearInterval,
setImmediate: function(cb) { realSetTimeout(cb, 0); }
}});
}
beforeEach(function() {
this.originalTimeout = jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL;
realSetTimeout = setTimeout;
@@ -1019,7 +1040,7 @@ describe("Env integration", function() {
});
it("should wait a default interval before failing specs that haven't called done yet", function(done) {
var env = new jasmineUnderTest.Env(),
var env = createMockedEnv(),
reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "jasmineDone" ]);
reporter.specDone.and.callFake(function(result) {
@@ -1048,7 +1069,7 @@ describe("Env integration", function() {
});
it("should not use the mock clock for asynchronous timeouts", function(done){
var env = new jasmineUnderTest.Env(),
var env = createMockedEnv(),
reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "jasmineDone" ]),
clock = env.clock;
@@ -1086,28 +1107,16 @@ describe("Env integration", function() {
});
it('should wait a custom interval before reporting async functions that fail to call done', function(done) {
var env = new jasmineUnderTest.Env(),
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone', 'suiteDone', 'specDone']),
timeoutFailure = (/^Error: Timeout - Async callback was not invoked within timeout specified by jasmine\.DEFAULT_TIMEOUT_INTERVAL\./);
var env = createMockedEnv(),
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone', 'suiteDone', 'specDone']);
reporter.specDone.and.callFake(function(r) {
realSetTimeout(function() {
jasmine.clock().tick(1);
}, 0);
});
reporter.suiteDone.and.callFake(function(r) {
realSetTimeout(function() {
jasmine.clock().tick(1);
}, 0);
});
reporter.jasmineDone.and.callFake(function() {
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('suite beforeAll', [ timeoutFailure ]);
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('suite afterAll', [ timeoutFailure ]);
expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite beforeEach times out', [ timeoutFailure ]);
expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite afterEach times out', [ timeoutFailure ]);
expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite it times out', [ timeoutFailure ]);
reporter.jasmineDone.and.callFake(function(r) {
expect(r.failedExpectations).toEqual([]);
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('suite beforeAll', [ /^Error: Timeout - Async callback was not invoked within 5000ms \(custom timeout\)/ ]);
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('suite afterAll', [ /^Error: Timeout - Async callback was not invoked within 2000ms \(custom timeout\)/ ]);
expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite beforeEach times out', [/^Error: Timeout - Async callback was not invoked within 1000ms \(custom timeout\)/]);
expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite afterEach times out', [ /^Error: Timeout - Async callback was not invoked within 4000ms \(custom timeout\)/ ]);
expect(reporter.specDone).toHaveFailedExpectationsForRunnable('suite it times out', [ /^Error: Timeout - Async callback was not invoked within 6000ms \(custom timeout\)/ ]);
jasmine.clock().tick(1);
realSetTimeout(done);
@@ -1469,8 +1478,7 @@ describe("Env integration", function() {
"specStarted",
"specDone"
]);
env.randomizeTests(true);
env.seed('123456');
env.configure({random: true, seed: '123456'});
reporter.jasmineDone.and.callFake(function(doneArg) {
expect(reporter.jasmineStarted).toHaveBeenCalled();
@@ -1484,7 +1492,7 @@ describe("Env integration", function() {
});
env.addReporter(reporter);
env.randomizeTests(true);
env.configure({random: true});
env.execute();
});
@@ -1616,7 +1624,7 @@ describe("Env integration", function() {
});
it("should be possible to get full name from a spec", function() {
var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
var env = new jasmineUnderTest.Env(),
topLevelSpec, nestedSpec, doublyNestedSpec;
env.describe("my tests", function() {
@@ -1638,7 +1646,7 @@ describe("Env integration", function() {
});
it("Custom equality testers should be per spec", function(done) {
var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
var env = new jasmineUnderTest.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [
"jasmineDone",
"specDone"
@@ -1655,7 +1663,7 @@ describe("Env integration", function() {
});
env.addReporter(reporter);
env.randomizeTests(false);
env.configure({random: false});
env.describe("testing custom equality testers", function() {
env.it("with a custom tester", function() {
@@ -1672,7 +1680,7 @@ describe("Env integration", function() {
});
it("Custom equality testers should be per suite", function(done) {
var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
var env = new jasmineUnderTest.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [
"jasmineDone",
"specDone"
@@ -1691,7 +1699,7 @@ describe("Env integration", function() {
});
env.addReporter(reporter);
env.randomizeTests(false);
env.configure({random: false});
env.describe("testing custom equality testers", function() {
env.beforeAll(function() { env.addCustomEqualityTester(function(a, b) { return true; }); });
@@ -1715,7 +1723,7 @@ describe("Env integration", function() {
});
it("Custom equality testers for toContain should be per spec", function(done) {
var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
var env = new jasmineUnderTest.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [
"jasmineDone",
"specDone"
@@ -1732,7 +1740,7 @@ describe("Env integration", function() {
});
env.addReporter(reporter);
env.randomizeTests(false);
env.configure({random: false});
env.describe("testing custom equality testers", function() {
env.it("with a custom tester", function() {
@@ -1766,7 +1774,7 @@ describe("Env integration", function() {
});
it("Custom equality testers for toContain should be per suite", function(done) {
var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
var env = new jasmineUnderTest.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [
"jasmineDone",
"specDone"
@@ -1785,7 +1793,7 @@ describe("Env integration", function() {
});
env.addReporter(reporter);
env.randomizeTests(false);
env.configure({random: false});
env.describe("testing custom equality testers", function() {
env.beforeAll(function() { env.addCustomEqualityTester(function(a, b) { return true; })});
@@ -1809,7 +1817,7 @@ describe("Env integration", function() {
});
it("Custom matchers should be per spec", function(done) {
var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
var env = new jasmineUnderTest.Env(),
matchers = {
toFoo: function() {}
};
@@ -1831,7 +1839,7 @@ describe("Env integration", function() {
});
it("Custom matchers should be per suite", function(done) {
var env = new jasmineUnderTest.Env({global: { setTimeout: setTimeout }}),
var env = new jasmineUnderTest.Env(),
matchers = {
toFoo: function() {}
};
@@ -2060,11 +2068,13 @@ describe("Env integration", function() {
env.execute();
});
describe('If suppressLoadErrors was called', function() {
it('does not report or handle errors that occur during loading', function(done) {
describe('If suppressLoadErrors: true was passed', function() {
it('does not install a global error handler during loading', function(done) {
var originalOnerror = jasmine.createSpy('original onerror')
var global = {
setTimeout: function(fn, delay) { setTimeout(fn, delay) },
clearTimeout: function(fn, delay) { clearTimeout(fn, delay) }
clearTimeout: function(fn, delay) { clearTimeout(fn, delay) },
onerror: originalOnerror
};
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
var globalErrors = new jasmineUnderTest.GlobalErrors(global);
@@ -2072,17 +2082,16 @@ describe("Env integration", function() {
globalErrors.pushListener(onerror);
spyOn(jasmineUnderTest, 'GlobalErrors').and.returnValue(globalErrors);
var env = new jasmineUnderTest.Env(),
var env = new jasmineUnderTest.Env({suppressLoadErrors: true});
reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']);
reporter.jasmineDone.and.callFake(function(e) {
expect(e.failedExpectations).toEqual([]);
expect(onerror).toHaveBeenCalledWith('Uncaught Error: ENOCHEESE');
expect(originalOnerror).toHaveBeenCalledWith('Uncaught Error: ENOCHEESE');
done();
});
env.addReporter(reporter);
env.suppressLoadErrors(true);
global.onerror('Uncaught Error: ENOCHEESE');
env.execute();
@@ -2303,6 +2312,9 @@ describe("Env integration", function() {
var env = new jasmineUnderTest.Env(),
reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']);
// prevent deprecation from being desplayed
spyOn(console, "error");
reporter.jasmineDone.and.callFake(function(result) {
expect(result.deprecationWarnings).toEqual([
jasmine.objectContaining({ message: 'top level deprecation' })
@@ -2341,4 +2353,167 @@ describe("Env integration", function() {
env.execute();
});
it('should report deprecation stack with an error object', function(done) {
var env = new jasmineUnderTest.Env(),
exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
reporter = jasmine.createSpyObj('reporter', ['jasmineDone', 'suiteDone', 'specDone']),
topLevelError, suiteLevelError, specLevelError;
try { throw new Error('top level deprecation') } catch (err) { topLevelError = err; }
try { throw new Error('suite level deprecation') } catch (err) { suiteLevelError = err; }
try { throw new Error('spec level deprecation') } catch (err) { specLevelError = err; }
// prevent deprecation from being desplayed
spyOn(console, "error");
reporter.jasmineDone.and.callFake(function(result) {
expect(result.deprecationWarnings).toEqual([
jasmine.objectContaining({
message: topLevelError.message,
stack: exceptionFormatter.stack(topLevelError)
})
]);
expect(reporter.suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({
fullName: 'suite',
deprecationWarnings: [
jasmine.objectContaining({
message: suiteLevelError.message,
stack: exceptionFormatter.stack(suiteLevelError)
})
]
}));
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({
fullName: 'suite spec',
deprecationWarnings: [
jasmine.objectContaining({
message: specLevelError.message,
stack: exceptionFormatter.stack(specLevelError)
})
]
}));
done();
});
env.addReporter(reporter);
env.deprecated(topLevelError);
env.describe('suite', function() {
env.beforeAll(function() {
env.deprecated(suiteLevelError);
});
env.it('spec', function() {
env.deprecated(specLevelError);
});
});
env.execute();
});
it('supports async matchers', function(done) {
jasmine.getEnv().requirePromises();
var env = new jasmineUnderTest.Env(),
specDone = jasmine.createSpy('specDone'),
suiteDone = jasmine.createSpy('suiteDone');
env.addReporter({
specDone: specDone,
suiteDone: suiteDone,
jasmineDone: function(result) {
expect(result.failedExpectations).toEqual([jasmine.objectContaining({
message: 'Expected a promise to be rejected.'
})]);
expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({
description: 'has an async failure',
failedExpectations: [jasmine.objectContaining({
message: 'Expected a promise to be rejected.'
})]
}));
expect(suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({
description: 'a suite',
failedExpectations: [jasmine.objectContaining({
message: 'Expected a promise to be rejected.'
})]
}));
done();
}
});
function fail(innerDone) {
var resolve;
var p = new Promise(function(res, rej) { resolve = res });
env.expectAsync(p).toBeRejected().then(innerDone);
resolve();
}
env.afterAll(fail);
env.describe('a suite', function() {
env.afterAll(fail);
env.it('has an async failure', fail);
});
env.execute();
});
it('provides custom equality testers to async matchers', function(done) {
jasmine.getEnv().requirePromises();
var env = new jasmineUnderTest.Env(),
specDone = jasmine.createSpy('specDone');
env.addReporter({
specDone: specDone,
jasmineDone: function() {
expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({
description: 'has an async failure',
failedExpectations: []
}));
done();
}
});
env.it('has an async failure', function() {
env.addCustomEqualityTester(function() { return true; });
var p = Promise.resolve('something');
return env.expectAsync(p).toBeResolvedTo('something else');
});
env.execute();
});
it('includes useful stack frames in async matcher failures', function(done) {
jasmine.getEnv().requirePromises();
var env = new jasmineUnderTest.Env(),
specDone = jasmine.createSpy('specDone');
env.addReporter({
specDone: specDone,
jasmineDone: function() {
expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({
failedExpectations: [jasmine.objectContaining({
stack: jasmine.stringMatching('EnvSpec.js')
})]
}));
done();
}
});
env.it('has an async failure', function() {
env.addCustomEqualityTester(function() { return true; });
var p = Promise.resolve();
return env.expectAsync(p).toBeRejected();
});
env.execute();
});
});

View File

@@ -4,7 +4,7 @@ describe("spec running", function () {
beforeEach(function() {
jasmine.getEnv().registerIntegrationMatchers();
env = new jasmineUnderTest.Env();
env.randomizeTests(false);
env.configure({random: false});
});
it('should assign spec ids sequentially', function() {
@@ -740,8 +740,7 @@ describe("spec running", function () {
it("should run the tests in a consistent order when a seed is supplied", function(done) {
var actions = [];
env.seed('123456');
env.randomizeTests(true);
env.configure({random: true, seed: '123456'});
env.beforeEach(function () {
actions.push('topSuite beforeEach');
@@ -865,7 +864,7 @@ describe("spec running", function () {
});
});
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
var assertions = function() {
expect(actions).toEqual([
@@ -900,7 +899,7 @@ describe("spec running", function () {
});
});
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
var assertions = function() {
expect(actions).toEqual([
@@ -932,7 +931,7 @@ describe("spec running", function () {
});
});
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
var assertions = function() {
expect(actions).toEqual([
@@ -946,23 +945,145 @@ describe("spec running", function () {
env.execute();
});
it("skips to cleanup functions after an error with deprecations", function(done) {
var actions = [];
spyOn(env, 'deprecated');
env.describe('Something', function() {
env.beforeEach(function() {
actions.push('outer beforeEach');
throw new Error("error");
});
env.afterEach(function() {
actions.push('outer afterEach');
});
env.describe('Inner', function() {
env.beforeEach(function() {
actions.push('inner beforeEach');
});
env.afterEach(function() {
actions.push('inner afterEach');
});
env.it('does it' , function() {
actions.push('inner it');
});
});
});
env.throwOnExpectationFailure(true);
var assertions = function() {
expect(actions).toEqual([
'outer beforeEach',
'inner afterEach',
'outer afterEach'
]);
expect(env.deprecated).toHaveBeenCalled();
done();
};
env.addReporter({jasmineDone: assertions});
env.execute();
});
it("skips to cleanup functions after done.fail is called with deprecations", function(done) {
var actions = [];
spyOn(env, 'deprecated');
env.describe('Something', function() {
env.beforeEach(function(done) {
actions.push('beforeEach');
done.fail('error');
actions.push('after done.fail');
});
env.afterEach(function() {
actions.push('afterEach');
});
env.it('does it' , function() {
actions.push('it');
});
});
env.throwOnExpectationFailure(true);
var assertions = function() {
expect(actions).toEqual([
'beforeEach',
'afterEach'
]);
expect(env.deprecated).toHaveBeenCalled();
done();
};
env.addReporter({jasmineDone: assertions});
env.execute();
});
it("skips to cleanup functions when an async function times out with deprecations", function(done) {
var actions = [];
spyOn(env, 'deprecated');
env.describe('Something', function() {
env.beforeEach(function(innerDone) {
actions.push('beforeEach');
}, 1);
env.afterEach(function() {
actions.push('afterEach');
});
env.it('does it' , function() {
actions.push('it');
});
});
env.throwOnExpectationFailure(true);
var assertions = function() {
expect(actions).toEqual([
'beforeEach',
'afterEach'
]);
expect(env.deprecated).toHaveBeenCalled();
done();
};
env.addReporter({jasmineDone: assertions});
env.execute();
});
});
describe("when stopOnSpecFailure is on", function() {
it("does not run further specs when one fails", function(done) {
var actions = [];
env.it('fails', function() {
actions.push('fails');
env.expect(1).toBe(2);
env.describe('wrapper', function() {
env.it('fails', function() {
actions.push('fails');
env.expect(1).toBe(2);
});
});
env.it('does not run', function() {
actions.push('does not run');
env.describe('holder', function() {
env.it('does not run', function() {
actions.push('does not run');
});
});
env.randomizeTests(false);
env.stopOnSpecFailure(true);
env.configure({random: false, failFast: true});
var assertions = function() {
expect(actions).toEqual(['fails']);
@@ -972,5 +1093,36 @@ describe("spec running", function () {
env.addReporter({ jasmineDone: assertions });
env.execute();
});
it("does not run further specs when one fails when configured with deprecated option", function(done) {
var actions = [];
spyOn(env, 'deprecated');
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});
env.stopOnSpecFailure(true);
var assertions = function() {
expect(actions).toEqual(['fails']);
expect(env.deprecated).toHaveBeenCalled();
done();
};
env.addReporter({ jasmineDone: assertions });
env.execute();
});
});
});

View File

@@ -0,0 +1,23 @@
describe('toBeRejected', function() {
it('passes if the actual is rejected', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeRejected(jasmineUnderTest.matchersUtil),
actual = Promise.reject('AsyncExpectationSpec rejection');
return matcher.compare(actual).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: true}));
});
});
it('fails if the actual is resolved', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeRejected(jasmineUnderTest.matchersUtil),
actual = Promise.resolve();
return matcher.compare(actual).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: false}));
});
});
});

View File

@@ -0,0 +1,63 @@
describe('#toBeRejectedWith', function () {
it('should return true if the promise is rejected with the expected value', function () {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWith(jasmineUnderTest.matchersUtil),
actual = Promise.reject({error: 'PEBCAK'});
return matcher.compare(actual, {error: 'PEBCAK'}).then(function (result) {
expect(result).toEqual(jasmine.objectContaining({ pass: true }));
});
});
it('should fail if the promise resolves', function () {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWith(jasmineUnderTest.matchersUtil),
actual = Promise.resolve();
return matcher.compare(actual, '').then(function (result) {
expect(result).toEqual(jasmine.objectContaining({ pass: false }));
});
});
it('should fail if the promise is rejected with a different value', function () {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWith(jasmineUnderTest.matchersUtil),
actual = Promise.reject('A Bad Apple');
return matcher.compare(actual, 'Some Cool Thing').then(function (result) {
expect(result).toEqual(jasmine.objectContaining({
pass: false,
message: "Expected a promise to be rejected with 'Some Cool Thing' but it was rejected with 'A Bad Apple'.",
}));
});
});
it('should build its error correctly when negated', function () {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWith(jasmineUnderTest.matchersUtil),
actual = Promise.reject(true);
return matcher.compare(actual, true).then(function (result) {
expect(result).toEqual(jasmine.objectContaining({
pass: true,
message: 'Expected a promise not to be rejected with true.'
}));
});
});
it('should support custom equality testers', function () {
jasmine.getEnv().requirePromises();
var customEqualityTesters = [function() { return true; }],
matcher = jasmineUnderTest.asyncMatchers.toBeRejectedWith(jasmineUnderTest.matchersUtil, customEqualityTesters),
actual = Promise.reject('actual');
return matcher.compare(actual, 'expected').then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: true}));
});
});
});

View File

@@ -0,0 +1,23 @@
describe('toBeResolved', function() {
it('passes if the actual is resolved', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeResolved(jasmineUnderTest.matchersUtil),
actual = Promise.resolve();
return matcher.compare(actual).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: true}));
});
});
it('fails if the actual is rejected', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeResolved(jasmineUnderTest.matchersUtil),
actual = Promise.reject('AsyncExpectationSpec rejection');
return matcher.compare(actual).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: false}));
});
});
});

View File

@@ -0,0 +1,66 @@
describe('#toBeResolvedTo', function() {
it('passes if the promise is resolved to the expected value', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(jasmineUnderTest.matchersUtil),
actual = Promise.resolve({foo: 42});
return matcher.compare(actual, {foo: 42}).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: true}));
});
});
it('fails if the promise is rejected', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(jasmineUnderTest.matchersUtil),
actual = Promise.reject('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.",
}));
});
});
it('fails if the promise is resolved to a different value', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(jasmineUnderTest.matchersUtil),
actual = Promise.resolve({foo: 17});
return matcher.compare(actual, {foo: 42}).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({
pass: false,
message: 'Expected a promise to be resolved to Object({ foo: 42 }) but it was resolved to Object({ foo: 17 }).',
}));
});
});
it('builds its message correctly when negated', function() {
jasmine.getEnv().requirePromises();
var matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(jasmineUnderTest.matchersUtil),
actual = Promise.resolve(true);
return matcher.compare(actual, true).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({
pass: true,
message: 'Expected a promise not to be resolved to true.'
}));
});
});
it('supports custom equality testers', function() {
jasmine.getEnv().requirePromises();
var customEqualityTesters = [function() { return true; }],
matcher = jasmineUnderTest.asyncMatchers.toBeResolvedTo(jasmineUnderTest.matchersUtil, customEqualityTesters),
actual = Promise.resolve('actual');
return matcher.compare(actual, 'expected').then(function(result) {
expect(result).toEqual(jasmine.objectContaining({pass: true}));
});
});
});

View File

@@ -145,7 +145,7 @@ describe("matchersUtil", function() {
actual = { b: 1 };
expect(jasmineUnderTest.matchersUtil.equals(actual, expected)).toBe(false);
})
});
it("fails when comparing an empty object to an empty array (issue #114)", function() {
var emptyObject = {},
@@ -211,11 +211,11 @@ describe("matchersUtil", function() {
return;
}
var a = document.createElement("div");
a.setAttribute("test-attr", "attr-value")
a.setAttribute("test-attr", "attr-value");
a.appendChild(document.createTextNode('test'));
var b = document.createElement("div");
b.setAttribute("test-attr", "attr-value2")
b.setAttribute("test-attr", "attr-value2");
b.appendChild(document.createTextNode('test'));
expect(jasmineUnderTest.matchersUtil.equals(a,b)).toBe(false);

View File

@@ -14,7 +14,7 @@ describe("toBeGreaterThanOrEqual", function() {
result = matcher.compare(1.0, 1.0);
expect(result.pass).toBe(true);
})
});
it("fails when actual < expected", function() {
var matcher = jasmineUnderTest.matchers.toBeGreaterThanOrEqual(),

View File

@@ -1,17 +1,56 @@
describe("toBe", function() {
it("passes when actual === expected", function() {
var matcher = jasmineUnderTest.matchers.toBe(),
it("passes with no message when actual === expected", function() {
var matcher = jasmineUnderTest.matchers.toBe(jasmineUnderTest.matchersUtil),
result;
result = matcher.compare(1, 1);
expect(result.pass).toBe(true);
});
it("fails when actual !== expected", function() {
var matcher = jasmineUnderTest.matchers.toBe(),
it("passes with a custom message when expected is an array", function() {
var matcher = jasmineUnderTest.matchers.toBe(jasmineUnderTest.matchersUtil),
result,
array = [1];
result = matcher.compare(array, array);
expect(result.pass).toBe(true);
expect(result.message).toBe("Expected [ 1 ] not to be [ 1 ]. Tip: To check for deep equality, use .toEqual() instead of .toBe().")
});
it("passes with a custom message when expected is an object", function() {
var matcher = jasmineUnderTest.matchers.toBe(jasmineUnderTest.matchersUtil),
result,
obj = {foo: "bar"};
result = matcher.compare(obj, obj);
expect(result.pass).toBe(true);
expect(result.message).toBe("Expected Object({ foo: 'bar' }) not to be Object({ foo: 'bar' }). Tip: To check for deep equality, use .toEqual() instead of .toBe().")
});
it("fails with no message when actual !== expected", function() {
var matcher = jasmineUnderTest.matchers.toBe(jasmineUnderTest.matchersUtil),
result;
result = matcher.compare(1, 2);
expect(result.pass).toBe(false);
expect(result.message).toBeUndefined();
});
it("fails with a custom message when expected is an array", function() {
var matcher = jasmineUnderTest.matchers.toBe(jasmineUnderTest.matchersUtil),
result;
result = matcher.compare([1], [1]);
expect(result.pass).toBe(false);
expect(result.message).toBe("Expected [ 1 ] to be [ 1 ]. Tip: To check for deep equality, use .toEqual() instead of .toBe().")
});
it("fails with a custom message when expected is an object", function() {
var matcher = jasmineUnderTest.matchers.toBe(jasmineUnderTest.matchersUtil),
result;
result = matcher.compare({foo: "bar"}, {foo: "bar"});
expect(result.pass).toBe(false);
expect(result.message).toBe("Expected Object({ foo: 'bar' }) to be Object({ foo: 'bar' }). Tip: To check for deep equality, use .toEqual() instead of .toBe().")
});
});

View File

@@ -95,7 +95,7 @@ describe("toEqual", function() {
expected = {x: {}},
message =
"Expected $.x not to have properties\n" +
" y: 'foo bar'"
" y: 'foo bar'";
expect(compareEquals(actual, expected).message).toEqual(message);
});
@@ -570,50 +570,67 @@ describe("toEqual", function() {
expect(compareEquals(actual, expected).pass).toBe(true);
});
function isNotRunningInBrowser() {
return typeof document === 'undefined'
}
it("reports mismatches between DOM nodes with different tags", function() {
if(isNotRunningInBrowser()) {
return;
describe('DOM nodes', function() {
function isNotRunningInBrowser() {
return typeof document === 'undefined'
}
var actual = {a: document.createElement('div')},
expected = {a: document.createElement('p')},
beforeEach(function(done) {
this.nonBrowser = isNotRunningInBrowser();
if (this.nonBrowser) {
var jsdom = require('jsdom');
var self = this;
jsdom.env('', function(err, win) {
if (err) {
done.fail(err);
} else {
jasmineUnderTest.getGlobal().Node = win.Node;
self.doc = win.document;
done();
}
});
} else {
this.doc = document;
done();
}
});
afterEach(function() {
if (this.nonBrowser) {
delete jasmineUnderTest.getGlobal().Node;
}
});
it("reports mismatches between DOM nodes with different tags", function() {
var actual = {a: this.doc.createElement('div')},
expected = {a: this.doc.createElement('p')},
message = 'Expected $.a = <div> to equal <p>.';
expect(compareEquals(actual, expected).message).toEqual(message);
});
expect(compareEquals(actual, expected).message).toEqual(message);
});
it('reports mismatches between DOM nodes with different content', function() {
if(isNotRunningInBrowser()) {
return;
}
it('reports mismatches between DOM nodes with different content', function() {
var nodeA = this.doc.createElement('div'),
nodeB = this.doc.createElement('div');
var nodeA = document.createElement('div'),
nodeB = document.createElement('div');
nodeA.setAttribute('thing', 'foo');
nodeB.setAttribute('thing', 'bar');
nodeA.innerText = 'foo'
nodeB.innerText = 'bar'
var actual = {a: nodeA},
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = <div>...</div> to equal <div>...</div>.';
message = 'Expected $.a = <div thing="foo"> to equal <div thing="bar">.';
expect(compareEquals(actual, expected).message).toEqual(message);
})
expect(compareEquals(actual, expected).message).toEqual(message);
});
it("reports mismatches between a DOM node and a bare Object", function() {
if(isNotRunningInBrowser()) {
return;
}
var actual = {a: document.createElement('div')},
it("reports mismatches between a DOM node and a bare Object", function() {
var actual = {a: this.doc.createElement('div')},
expected = {a: {}},
message = 'Expected $.a = <div> to equal Object({ }).';
expect(compareEquals(actual, expected).message).toEqual(message);
expect(compareEquals(actual, expected).message).toEqual(message);
});
});
it("reports asymmetric mismatches", function() {
@@ -658,7 +675,7 @@ describe("toEqual", function() {
boolean: false,
notDefined: 0,
aNull: void 0
}
};
var expected = {
foo: [
@@ -675,7 +692,7 @@ describe("toEqual", function() {
boolean: true,
notDefined: void 0,
aNull: null
}
};
var message =
'Expected $.foo[0].bar = 1 to equal 2.\n' +
@@ -690,19 +707,19 @@ describe("toEqual", function() {
'Expected $.inf = -Infinity to equal Infinity.\n' +
'Expected $.boolean = false to equal true.\n' +
'Expected $.notDefined = 0 to equal undefined.\n' +
'Expected $.aNull = undefined to equal null.'
'Expected $.aNull = undefined to equal null.';
expect(compareEquals(actual, expected).message).toEqual(message);
})
});
describe("different length arrays", function() {
it("actual array is longer", function() {
var actual = [1, 1, 2, 3, 5],
expected = [1, 1, 2, 3],
message = 'Expected $.length = 5 to equal 4.\n' +
'Expected $[4] = 5 to equal undefined.';
'Unexpected $[4] = 5 in array.';
expect(compareEquals(actual, expected).pass).toBe(false)
expect(compareEquals(actual, expected).pass).toBe(false);
expect(compareEquals(actual, expected).message).toEqual(message);
});
@@ -712,7 +729,38 @@ describe("toEqual", function() {
message = 'Expected $.length = 4 to equal 5.\n' +
'Expected $[4] = undefined to equal 5.';
expect(compareEquals(actual, expected).pass).toBe(false)
expect(compareEquals(actual, expected).pass).toBe(false);
expect(compareEquals(actual, expected).message).toEqual(message);
});
it("undefined in middle of actual array", function() {
var actual = [1, void 0, 3],
expected = [1, 2, 3],
message = 'Expected $[1] = undefined to equal 2.';
expect(compareEquals(actual, expected).pass).toBe(false);
expect(compareEquals(actual, expected).message).toEqual(message);
});
it("undefined in middle of expected array", function() {
var actual = [1, 2, 3],
expected = [1, void 0, 3],
message = 'Expected $[1] = 2 to equal undefined.';
expect(compareEquals(actual, expected).pass).toBe(false);
expect(compareEquals(actual, expected).message).toEqual(message);
});
it("actual array is longer by 4 elements", function() {
var actual = [1, 1, 2, 3, 5, 8, 13],
expected = [1, 1, 2],
message = 'Expected $.length = 7 to equal 3.\n' +
'Unexpected $[3] = 3 in array.\n' +
'Unexpected $[4] = 5 in array.\n' +
'Unexpected $[5] = 8 in array.\n' +
'Unexpected $[6] = 13 in array.';
expect(compareEquals(actual, expected).pass).toBe(false);
expect(compareEquals(actual, expected).message).toEqual(message);
});
@@ -725,7 +773,7 @@ describe("toEqual", function() {
'Expected $[5] = undefined to equal 8.\n' +
'Expected $[6] = undefined to equal 13.';
expect(compareEquals(actual, expected).pass).toBe(false)
expect(compareEquals(actual, expected).pass).toBe(false);
expect(compareEquals(actual, expected).message).toEqual(message);
});
@@ -736,27 +784,47 @@ describe("toEqual", function() {
'Expected $[0] = 1 to equal 2.\n' +
'Expected $[1] = undefined to equal 3.';
expect(compareEquals(actual, expected).pass).toBe(false)
expect(compareEquals(actual, expected).pass).toBe(false);
expect(compareEquals(actual, expected).message).toEqual(message);
});
it("object with nested array", function() {
it("object with nested array (actual longer than expected)", function() {
var actual = { values: [1, 1, 2, 3] },
expected = { values: [1, 1, 2] },
message = 'Expected $.values.length = 4 to equal 3.\n' +
'Expected $.values[3] = 3 to equal undefined.';
'Unexpected $.values[3] = 3 in array.';
expect(compareEquals(actual, expected).pass).toBe(false)
expect(compareEquals(actual, expected).pass).toBe(false);
expect(compareEquals(actual, expected).message).toEqual(message);
});
it("array with nested object", function() {
it("object with nested array (expected longer than actual)", function() {
var actual = { values: [1, 1, 2] },
expected = { values: [1, 1, 2, 3] },
message = 'Expected $.values.length = 3 to equal 4.\n' +
'Expected $.values[3] = undefined to equal 3.';
expect(compareEquals(actual, expected).pass).toBe(false);
expect(compareEquals(actual, expected).message).toEqual(message);
});
it("array with unexpected nested object", function() {
var actual = [1, 1, 2, { value: 3 }],
expected = [1, 1, 2],
message = 'Expected $.length = 4 to equal 3.\n' +
'Expected $[3] = Object({ value: 3 }) to equal undefined.';
'Unexpected $[3] = Object({ value: 3 }) in array.';
expect(compareEquals(actual, expected).pass).toBe(false)
expect(compareEquals(actual, expected).pass).toBe(false);
expect(compareEquals(actual, expected).message).toEqual(message);
});
it("array with missing nested object", function() {
var actual = [1, 1, 2],
expected = [1, 1, 2, { value: 3 }],
message = 'Expected $.length = 3 to equal 4.\n' +
'Expected $[3] = undefined to equal Object({ value: 3 }).';
expect(compareEquals(actual, expected).pass).toBe(false);
expect(compareEquals(actual, expected).message).toEqual(message);
});
@@ -767,9 +835,9 @@ describe("toEqual", function() {
'Expected $[0][1] = undefined to equal 1.\n' +
'Expected $[1].length = 2 to equal 1.\n' +
'Expected $[1][0] = 1 to equal 2.\n' +
'Expected $[1][1] = 2 to equal undefined.';
'Unexpected $[1][1] = 2 in array.';
expect(compareEquals(actual, expected).pass).toBe(false)
expect(compareEquals(actual, expected).pass).toBe(false);
expect(compareEquals(actual, expected).message).toEqual(message);
});
@@ -778,7 +846,7 @@ describe("toEqual", function() {
expected = [1, 2, void 0],
message = 'Expected $.length = 2 to equal 3.';
expect(compareEquals(actual, expected).pass).toBe(false)
expect(compareEquals(actual, expected).pass).toBe(false);
expect(compareEquals(actual, expected).message).toEqual(message);
});
})

View File

@@ -1,16 +1,38 @@
describe('toHaveClass', function() {
beforeEach(function(done) {
this.createElementWithClassName = function(className) {
var el = this.doc.createElement('div');
el.className = className;
return el;
};
if (typeof document !== 'undefined') {
this.doc = document;
done();
} else {
var jsdom = require('jsdom');
var self = this;
jsdom.env('', function(err, win) {
if (err) {
done.fail(err);
} else {
self.doc = win.document;
done();
}
});
}
});
it('fails for a DOM element that lacks the expected class', function() {
var matcher = jasmineUnderTest.matchers.toHaveClass(),
result = matcher.compare(document.createElement('div'), 'foo');
result = matcher.compare(this.createElementWithClassName(''), 'foo');
expect(result.pass).toBe(false);
});
it('passes for a DOM element that has the expected class', function() {
var matcher = jasmineUnderTest.matchers.toHaveClass(),
el = document.createElement('div');
el.className = 'foo bar baz';
el = this.createElementWithClassName('foo bar baz');
expect(matcher.compare(el, 'foo').pass).toBe(true);
expect(matcher.compare(el, 'bar').pass).toBe(true);
@@ -19,9 +41,7 @@ describe('toHaveClass', function() {
it('fails for a DOM element that only has other classes', function() {
var matcher = jasmineUnderTest.matchers.toHaveClass(),
el = document.createElement('div');
el.className = 'foo bar';
el = this.createElementWithClassName('foo bar');
expect(matcher.compare(el, 'fo').pass).toBe(false);
});
@@ -37,8 +57,9 @@ describe('toHaveClass', function() {
matcher.compare(undefined, 'foo');
}).toThrowError('undefined is not a DOM element');
var textNode = this.doc.createTextNode('');
expect(function() {
matcher.compare(document.createTextNode(''), 'foo')
matcher.compare(textNode, 'foo')
}).toThrowError('HTMLNode is not a DOM element');
expect(function() {

8
spec/helpers/promises.js Normal file
View File

@@ -0,0 +1,8 @@
(function(env) {
env.requirePromises = function() {
if (typeof Promise !== 'function') {
env.pending("Environment does not support promises");
}
};
})(jasmine.getEnv());

View File

@@ -103,7 +103,6 @@ describe("HtmlReporter", function() {
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
});
reporter.initialize();
reporter.specDone({id: 789, status: "excluded", fullName: "symbols should have titles", passedExpectations: [], failedExpectations: []});
var specEl = container.querySelector('.jasmine-symbol-summary li');
@@ -519,7 +518,7 @@ describe("HtmlReporter", function() {
}
});
env.stopOnSpecFailure(true);
env.configure({failFast: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -575,7 +574,7 @@ describe("HtmlReporter", function() {
}
});
env.stopOnSpecFailure(true);
env.configure({failFast: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -629,7 +628,7 @@ describe("HtmlReporter", function() {
}
});
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -685,7 +684,7 @@ describe("HtmlReporter", function() {
}
});
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -696,7 +695,82 @@ describe("HtmlReporter", function() {
expect(navigateHandler).toHaveBeenCalledWith('throwFailures', false);
});
});
describe("UI for hiding disabled specs", function() {
it("should be unchecked if not hiding disabled specs", function() {
var env = new jasmineUnderTest.Env(),
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);
}
});
env.configure({hideDisabled: false});
reporter.initialize();
reporter.jasmineDone({});
var disabledUI = container.querySelector(".jasmine-disabled");
expect(disabledUI.checked).toBe(false);
});
it("should be checked if hiding disabled", function() {
var env = new jasmineUnderTest.Env(),
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);
}
});
env.configure({hideDisabled: true});
reporter.initialize();
reporter.jasmineDone({});
var disabledUI = container.querySelector(".jasmine-disabled");
expect(disabledUI.checked).toBe(true);
});
it("should not display specs that have been disabled", function() {
var env = new jasmineUnderTest.Env(),
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); }
});
env.configure({hideDisabled: true});
reporter.initialize();
reporter.specDone({
id: 789,
status: "excluded",
fullName: "symbols should have titles",
passedExpectations: [],
failedExpectations: []
});
var specEl = container.querySelector('.jasmine-symbol-summary li');
expect(specEl.getAttribute("class")).toEqual("jasmine-excluded-no-display");
});
});
describe("UI for running tests in random order", function() {
it("should be unchecked if not randomizing", function() {
var env = new jasmineUnderTest.Env(),
@@ -715,7 +789,7 @@ describe("HtmlReporter", function() {
}
});
env.randomizeTests(false);
env.configure({random: false});
reporter.initialize();
reporter.jasmineDone({});
@@ -740,7 +814,7 @@ describe("HtmlReporter", function() {
}
});
env.randomizeTests(true);
env.configure({random: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -767,7 +841,7 @@ describe("HtmlReporter", function() {
}
});
env.randomizeTests(false);
env.configure({random: false});
reporter.initialize();
reporter.jasmineDone({});
@@ -796,7 +870,7 @@ describe("HtmlReporter", function() {
}
});
env.randomizeTests(true);
env.configure({random: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -1047,7 +1121,7 @@ describe("HtmlReporter", function() {
beforeEach(function() {
env = new jasmineUnderTest.Env();
container = document.createElement("div");
var getContainer = function() { return container; }
var getContainer = function() { return container; };
reporter = new jasmineUnderTest.HtmlReporter({
env: env,
getContainer: getContainer,

View File

@@ -24,4 +24,11 @@ describe("jasmineUnderTest.pp (HTML Dependent)", function () {
expect(jasmineUnderTest.pp(err)).toMatch(/Not enough arguments/);
}
});
it("should stringify HTML element with text and attributes", function() {
var el = document.createElement('div');
el.setAttribute('things', 'foo');
el.innerHTML = 'foo';
expect(jasmineUnderTest.pp(el)).toEqual('<div things="foo">...</div>');
});
});

View File

@@ -6,10 +6,10 @@ sauce:
name: jasmine-core <%= Time.now.to_s %>
username: <%= ENV['SAUCE_USERNAME'] %>
access_key: <%= ENV['SAUCE_ACCESS_KEY'] %>
build: <%= ENV['TRAVIS_BUILD_NUMBER'] || 'Ran locally' %>
build: Core <%= ENV['TRAVIS_BUILD_NUMBER'] || 'Ran locally' %>
tags:
- <%= ENV['TRAVIS_RUBY_VERSION'] || RUBY_VERSION %>
- CI
- Jasmine-Core
- "<%= ENV['TRAVIS_JOB_NUMBER'] %>"
tunnel_identifier: <%= ENV['TRAVIS_JOB_NUMBER'] ? %Q("#{ENV['TRAVIS_JOB_NUMBER']}") : nil %>
os: <%= ENV['SAUCE_OS'] %>
browser_version: "<%= ENV['SAUCE_BROWSER_VERSION'] %>"

View File

@@ -11,6 +11,7 @@
"helpers/checkForSymbol.js",
"helpers/checkForTypedArrays.js",
"helpers/integrationMatchers.js",
"helpers/promises.js",
"helpers/nodeDefineJasmineUnderTest.js"
],
"random": true

View File

@@ -24,6 +24,7 @@ helpers:
- 'helpers/checkForSymbol.js'
- 'helpers/checkForTypedArrays.js'
- 'helpers/integrationMatchers.js'
- 'helpers/promises.js'
- 'helpers/defineJasmineUnderTest.js'
spec_files:
- '**/*[Ss]pec.js'

View File

@@ -1,5 +1,6 @@
getJasmineRequireObj().Clock = function() {
/* global process */
var NODE_JS = typeof process !== 'undefined' && process.versions && typeof process.versions.node === 'string';
/**

View File

@@ -13,9 +13,9 @@ getJasmineRequireObj().Env = function(j$) {
var totalSpecsDefined = 0;
var realSetTimeout = j$.getGlobal().setTimeout;
var realClearTimeout = j$.getGlobal().clearTimeout;
var clearStack = j$.getClearStack(j$.getGlobal());
var realSetTimeout = global.setTimeout;
var realClearTimeout = global.clearTimeout;
var clearStack = j$.getClearStack(global);
this.clock = new j$.Clock(global, function () { return new j$.DelayedFunctionScheduler(); }, new j$.MockDate(global));
var runnableResources = {};
@@ -23,13 +23,62 @@ getJasmineRequireObj().Env = function(j$) {
var currentSpec = null;
var currentlyExecutingSuites = [];
var currentDeclarationSuite = null;
var throwOnExpectationFailure = false;
var stopOnSpecFailure = false;
var random = true;
var seed = null;
var handlingLoadErrors = true;
var hasFailures = false;
/**
* This represents the available options to configure Jasmine.
* Options that are not provided will use their default values
* @interface Configuration
*/
var config = {
/**
* Whether to randomize spec execution order
* @name Configuration#random
* @type Boolean
* @default true
*/
random: true,
/**
* Seed to use as the basis of randomization.
* Null causes the seed to be determined randomly at the start of execution.
* @name Configuration#seed
* @type function
* @default null
*/
seed: null,
/**
* Whether to stop execution of the suite after the first spec failure
* @name Configuration#failFast
* @type Boolean
* @default false
*/
failFast: false,
/**
* Whether to cause specs to only have one expectation failure.
* @name Configuration#oneFailurePerSpec
* @type Boolean
* @default false
*/
oneFailurePerSpec: false,
/**
* Function to use to filter specs
* @name Configuration#specFilter
* @type function
* @default true
*/
specFilter: function() {
return true;
},
/**
* Whether or not reporters should hide disabled specs from their output.
* Currently only supported by Jasmine's HTMLReporter
* @name Configuration#hideDisabled
* @type Boolean
* @default false
*/
hideDisabled: false
};
var currentSuite = function() {
return currentlyExecutingSuites[currentlyExecutingSuites.length - 1];
};
@@ -38,22 +87,87 @@ getJasmineRequireObj().Env = function(j$) {
return currentSpec || currentSuite();
};
var globalErrors = new j$.GlobalErrors();
globalErrors.install();
globalErrors.pushListener(function(message, filename, lineno) {
topSuite.result.failedExpectations.push({
passed: false,
globalErrorType: 'load',
message: message,
filename: filename,
lineno: lineno
});
});
var globalErrors = null;
this.specFilter = function() {
return true;
var installGlobalErrors = function() {
if (globalErrors) {
return;
}
globalErrors = new j$.GlobalErrors();
globalErrors.install();
};
if (!options.suppressLoadErrors) {
installGlobalErrors();
globalErrors.pushListener(function(message, filename, lineno) {
topSuite.result.failedExpectations.push({
passed: false,
globalErrorType: 'load',
message: message,
filename: filename,
lineno: lineno
});
});
}
/**
* Configure your jasmine environment
* @name Env#configure
* @argument {Configuration} configuration
* @function
*/
this.configure = function(configuration) {
if (configuration.specFilter) {
config.specFilter = configuration.specFilter;
}
if (configuration.hasOwnProperty('random')) {
config.random = !!configuration.random;
}
if (configuration.hasOwnProperty('seed')) {
config.seed = configuration.seed;
}
if (configuration.hasOwnProperty('failFast')) {
config.failFast = configuration.failFast;
}
if (configuration.hasOwnProperty('oneFailurePerSpec')) {
config.oneFailurePerSpec = configuration.oneFailurePerSpec;
}
if (configuration.hasOwnProperty('hideDisabled')) {
config.hideDisabled = configuration.hideDisabled;
}
};
/**
* Get the current configuration for your jasmine environment
* @name Env#configuration
* @function
* @returns {Configuration}
*/
this.configuration = function() {
var result = {};
for (var property in config) {
result[property] = config[property];
}
return result;
};
Object.defineProperty(this, 'specFilter', {
get: function() {
self.deprecated('Getting specFilter directly from Env is deprecated, please check the specFilter option from `configuration`');
return config.specFilter;
},
set: function(val) {
self.deprecated('Setting specFilter directly on Env is deprecated, please use the specFilter option in `configure`');
config.specFilter = val;
}
});
this.addSpyStrategy = function(name, fn) {
if(!currentRunnable()) {
throw new Error('Custom spy strategies must be added in a before function or a spec');
@@ -79,6 +193,7 @@ getJasmineRequireObj().Env = function(j$) {
};
j$.Expectation.addCoreMatchers(j$.matchers);
j$.Expectation.addAsyncCoreMatchers(j$.asyncMatchers);
var nextSpecId = 0;
var getNextSpecId = function() {
@@ -91,7 +206,7 @@ getJasmineRequireObj().Env = function(j$) {
};
var expectationFactory = function(actual, spec) {
return j$.Expectation.Factory({
return j$.Expectation.factory({
util: j$.matchersUtil,
customEqualityTesters: runnableResources[spec.id].customEqualityTesters,
customMatchers: runnableResources[spec.id].customMatchers,
@@ -104,6 +219,19 @@ getJasmineRequireObj().Env = function(j$) {
}
};
var asyncExpectationFactory = function(actual, spec) {
return j$.Expectation.asyncFactory({
util: j$.matchersUtil,
customEqualityTesters: runnableResources[spec.id].customEqualityTesters,
actual: actual,
addExpectationResult: addExpectationResult
});
function addExpectationResult(passed, result) {
return spec.addExpectationResult(passed, result);
}
};
var defaultResourcesForRunnable = function(id, parentRunnableId) {
var resources = {spies: [], customEqualityTesters: [], customMatchers: {}, customSpyStrategies: {}};
@@ -162,58 +290,101 @@ getJasmineRequireObj().Env = function(j$) {
var maximumSpecCallbackDepth = 20;
var currentSpecCallbackDepth = 0;
/**
* Sets whether Jasmine should throw an Error when an expectation fails.
* This causes a spec to only have one expectation failure.
* @name Env#throwOnExpectationFailure
* @function
* @param {Boolean} value Whether to throw when a expectation fails
* @deprecated Use the `oneFailurePerSpec` option with {@link Env#configure}
*/
this.throwOnExpectationFailure = function(value) {
throwOnExpectationFailure = !!value;
this.deprecated('Setting throwOnExpectationFailure directly on Env is deprecated, please use the oneFailurePerSpec option in `configure`');
this.configure({oneFailurePerSpec: !!value});
};
this.throwingExpectationFailures = function() {
return throwOnExpectationFailure;
this.deprecated('Getting throwingExpectationFailures directly from Env is deprecated, please check the oneFailurePerSpec option from `configuration`');
return config.oneFailurePerSpec;
};
/**
* Set whether to stop suite execution when a spec fails
* @name Env#stopOnSpecFailure
* @function
* @param {Boolean} value Whether to stop suite execution when a spec fails
* @deprecated Use the `failFast` option with {@link Env#configure}
*/
this.stopOnSpecFailure = function(value) {
stopOnSpecFailure = !!value;
this.deprecated('Setting stopOnSpecFailure directly is deprecated, please use the failFast option in `configure`');
this.configure({failFast: !!value});
};
this.stoppingOnSpecFailure = function() {
return stopOnSpecFailure;
this.deprecated('Getting stoppingOnSpecFailure directly from Env is deprecated, please check the failFast option from `configuration`');
return config.failFast;
};
/**
* Set whether to randomize test execution order
* @name Env#randomizeTests
* @function
* @param {Boolean} value Whether to randomize execution order
* @deprecated Use the `random` option with {@link Env#configure}
*/
this.randomizeTests = function(value) {
random = !!value;
this.deprecated('Setting randomizeTests directly is deprecated, please use the random option in `configure`');
config.random = !!value;
};
this.randomTests = function() {
return random;
this.deprecated('Getting randomTests directly from Env is deprecated, please check the random option from `configuration`');
return config.random;
};
/**
* Set the random number seed for spec randomization
* @name Env#seed
* @function
* @param {Number} value The seed value
* @deprecated Use the `seed` option with {@link Env#configure}
*/
this.seed = function(value) {
this.deprecated('Setting seed directly is deprecated, please use the seed option in `configure`');
if (value) {
seed = value;
config.seed = value;
}
return seed;
return config.seed;
};
this.suppressLoadErrors = function() {
if (handlingLoadErrors) {
globalErrors.popListener();
}
handlingLoadErrors = false;
this.hidingDisabled = function(value) {
this.deprecated('Getting hidingDisabled directly from Env is deprecated, please check the hideDisabled option from `configuration`');
return config.hideDisabled;
};
this.deprecated = function(msg) {
/**
* @name Env#hideDisabled
* @function
*/
this.hideDisabled = function(value) {
this.deprecated('Setting hideDisabled directly is deprecated, please use the hideDisabled option in `configure`');
config.hideDisabled = !!value;
};
this.deprecated = function(deprecation) {
var runnable = currentRunnable() || topSuite;
runnable.addDeprecationWarning(msg);
if(typeof console !== 'undefined' && typeof console.warn !== 'undefined') {
console.error('DEPRECATION: ' + msg);
runnable.addDeprecationWarning(deprecation);
if(typeof console !== 'undefined' && typeof console.error === 'function') {
console.error('DEPRECATION:', deprecation);
}
};
var queueRunnerFactory = function(options, args) {
var failFast = false;
if (options.isLeaf) {
failFast = throwOnExpectationFailure;
failFast = config.oneFailurePerSpec;
} else if (!options.isReporter) {
failFast = stopOnSpecFailure;
failFast = config.failFast;
}
options.clearStack = options.clearStack || clearStack;
options.timeout = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout};
@@ -233,6 +404,7 @@ getJasmineRequireObj().Env = function(j$) {
id: getNextSuiteId(),
description: 'Jasmine__TopLevel__Suite',
expectationFactory: expectationFactory,
asyncExpectationFactory: asyncExpectationFactory,
expectationResultFactory: expectationResultFactory
});
defaultResourcesForRunnable(topSuite.id);
@@ -245,6 +417,7 @@ getJasmineRequireObj().Env = function(j$) {
/**
* This represents the available reporter callback for an object passed to {@link Env#addReporter}.
* @interface Reporter
* @see custom_reporter
*/
var reporter = new j$.ReportDispatcher([
/**
@@ -252,6 +425,9 @@ getJasmineRequireObj().Env = function(j$) {
* @function
* @name Reporter#jasmineStarted
* @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
* @see async
*/
'jasmineStarted',
/**
@@ -259,6 +435,9 @@ getJasmineRequireObj().Env = function(j$) {
* @function
* @name Reporter#jasmineDone
* @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running.
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
* @see async
*/
'jasmineDone',
/**
@@ -266,6 +445,9 @@ getJasmineRequireObj().Env = function(j$) {
* @function
* @name Reporter#suiteStarted
* @param {SuiteResult} result Information about the individual {@link describe} being run
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
* @see async
*/
'suiteStarted',
/**
@@ -275,6 +457,9 @@ getJasmineRequireObj().Env = function(j$) {
* @function
* @name Reporter#suiteDone
* @param {SuiteResult} result
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
* @see async
*/
'suiteDone',
/**
@@ -282,6 +467,9 @@ getJasmineRequireObj().Env = function(j$) {
* @function
* @name Reporter#specStarted
* @param {SpecResult} result Information about the individual {@link it} being run
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
* @see async
*/
'specStarted',
/**
@@ -291,13 +479,16 @@ getJasmineRequireObj().Env = function(j$) {
* @function
* @name Reporter#specDone
* @param {SpecResult} result
* @param {Function} [done] Used to specify to Jasmine that this callback is asynchronous and Jasmine should wait until it has been called before moving on.
* @returns {} Optionally return a Promise instead of using `done` to cause Jasmine to wait for completion.
* @see async
*/
'specDone'
], queueRunnerFactory);
this.execute = function(runnablesToRun) {
var self = this;
this.suppressLoadErrors();
installGlobalErrors();
if(!runnablesToRun) {
if (focusedRunnables.length) {
@@ -308,8 +499,8 @@ getJasmineRequireObj().Env = function(j$) {
}
var order = new j$.Order({
random: random,
seed: seed
random: config.random,
seed: config.seed
});
var processor = new j$.TreeProcessor({
@@ -339,7 +530,7 @@ getJasmineRequireObj().Env = function(j$) {
return order.sort(node.children);
},
excludeNode: function(spec) {
return !self.specFilter(spec);
return !config.specFilter(spec);
}
});
@@ -379,8 +570,8 @@ getJasmineRequireObj().Env = function(j$) {
/**
* Information passed to the {@link Reporter#jasmineDone} event.
* @typedef JasmineDoneInfo
* @property {OverallStatus} - The overall result of the sute: 'passed', 'failed', or 'incomplete'.
* @property {IncompleteReason} - Explanation of why the suite was incimplete.
* @property {OverallStatus} overallStatus - The overall result of the sute: 'passed', 'failed', or 'incomplete'.
* @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.
@@ -407,10 +598,22 @@ getJasmineRequireObj().Env = function(j$) {
reporter.addReporter(reporterToAdd);
};
/**
* Provide a fallback reporter if no other reporters have been specified.
* @name Env#provideFallbackReporter
* @function
* @param {Reporter} reporterToAdd The reporter
* @see custom_reporter
*/
this.provideFallbackReporter = function(reporterToAdd) {
reporter.provideFallbackReporter(reporterToAdd);
};
/**
* Clear all registered reporters
* @name Env#clearReporters
* @function
*/
this.clearReporters = function() {
reporter.clearReporters();
};
@@ -449,7 +652,16 @@ getJasmineRequireObj().Env = function(j$) {
return spyRegistry.spyOnProperty.apply(spyRegistry, arguments);
};
this.spyOnAllFunctions = function() {
return spyRegistry.spyOnAllFunctions.apply(spyRegistry, arguments);
};
this.createSpy = function(name, originalFn) {
if (arguments.length === 1 && j$.isFunction_(name)) {
originalFn = name;
name = originalFn.name;
}
return spyFactory.createSpy(name, originalFn);
};
@@ -483,8 +695,9 @@ getJasmineRequireObj().Env = function(j$) {
description: description,
parentSuite: currentDeclarationSuite,
expectationFactory: expectationFactory,
asyncExpectationFactory: asyncExpectationFactory,
expectationResultFactory: expectationResultFactory,
throwOnExpectationFailure: throwOnExpectationFailure
throwOnExpectationFailure: config.oneFailurePerSpec
});
return suite;
@@ -576,6 +789,7 @@ getJasmineRequireObj().Env = function(j$) {
id: getNextSpecId(),
beforeAndAfterFns: beforeAndAfterFns(suite),
expectationFactory: expectationFactory,
asyncExpectationFactory: asyncExpectationFactory,
resultCallback: specResultCallback,
getSpecName: function(spec) {
return getSpecName(spec, suite);
@@ -587,9 +801,9 @@ getJasmineRequireObj().Env = function(j$) {
userContext: function() { return suite.clonedSharedUserContext(); },
queueableFn: {
fn: fn,
timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
timeout: timeout || 0
},
throwOnExpectationFailure: throwOnExpectationFailure
throwOnExpectationFailure: config.oneFailurePerSpec
});
return spec;
@@ -657,12 +871,20 @@ getJasmineRequireObj().Env = function(j$) {
return currentRunnable().expect(actual);
};
this.expectAsync = function(actual) {
if (!currentRunnable()) {
throw new Error('\'expectAsync\' was used when there was no current spec, this could be because an asynchronous test timed out');
}
return currentRunnable().expectAsync(actual);
};
this.beforeEach = function(beforeEachFunction, timeout) {
ensureIsNotNested('beforeEach');
ensureIsFunctionOrAsync(beforeEachFunction, 'beforeEach');
currentDeclarationSuite.beforeEach({
fn: beforeEachFunction,
timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
timeout: timeout || 0
});
};
@@ -671,7 +893,7 @@ getJasmineRequireObj().Env = function(j$) {
ensureIsFunctionOrAsync(beforeAllFunction, 'beforeAll');
currentDeclarationSuite.beforeAll({
fn: beforeAllFunction,
timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
timeout: timeout || 0
});
};
@@ -681,7 +903,7 @@ getJasmineRequireObj().Env = function(j$) {
afterEachFunction.isCleanup = true;
currentDeclarationSuite.afterEach({
fn: afterEachFunction,
timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
timeout: timeout || 0
});
};
@@ -690,7 +912,7 @@ getJasmineRequireObj().Env = function(j$) {
ensureIsFunctionOrAsync(afterAllFunction, 'afterAll');
currentDeclarationSuite.afterAll({
fn: afterAllFunction,
timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
timeout: timeout || 0
});
};
@@ -712,11 +934,11 @@ getJasmineRequireObj().Env = function(j$) {
message += ': ';
if (error.message) {
message += error.message;
} else if (jasmine.isString_(error)) {
} else if (j$.isString_(error)) {
message += error;
} else {
// pretty print all kind of objects. This includes arrays.
message += jasmine.pp(error);
message += j$.pp(error);
}
}
@@ -729,7 +951,7 @@ getJasmineRequireObj().Env = function(j$) {
error: error && error.message ? error : null
});
if (self.throwingExpectationFailures()) {
if (config.oneFailurePerSpec) {
throw new Error(message);
}
};

View File

@@ -7,6 +7,8 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
if (error.name && error.message) {
message += error.name + ': ' + error.message;
} else if (error.message) {
message += error.message;
} else {
message += error.toString() + ' thrown';
}
@@ -27,20 +29,24 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
return null;
}
var stackTrace = new j$.StackTrace(error.stack);
var stackTrace = new j$.StackTrace(error);
var lines = filterJasmine(stackTrace);
var result = '';
if (stackTrace.message) {
lines.unshift(stackTrace.message);
}
return lines.join('\n');
result += formatProperties(error);
result += lines.join('\n');
return result;
};
function filterJasmine(stackTrace) {
var result = [],
jasmineMarker = stackTrace.style === 'webkit' ? '<Jasmine>' : ' at <Jasmine>';
stackTrace.frames.forEach(function(frame) {
if (frame.file && frame.file !== jasmineFile) {
result.push(frame.raw);
@@ -48,9 +54,33 @@ getJasmineRequireObj().ExceptionFormatter = function(j$) {
result.push(jasmineMarker);
}
});
return result;
}
function formatProperties(error) {
if (!(error instanceof Object)) {
return;
}
var ignored = ['name', 'message', 'stack', 'fileName', 'sourceURL', 'line', 'lineNumber', 'column', 'description'];
var result = {};
var empty = true;
for (var prop in error) {
if (j$.util.arrayContains(ignored, prop)) {
continue;
}
result[prop] = error[prop];
empty = false;
}
if (!empty) {
return 'error properties: ' + j$.pp(result) + '\n';
}
return '';
}
}
return ExceptionFormatter;

View File

@@ -1,98 +1,186 @@
getJasmineRequireObj().Expectation = function() {
getJasmineRequireObj().Expectation = function(j$) {
var promiseForMessage = {
jasmineToString: function() { return 'a promise'; }
};
/**
* Matchers that come with Jasmine out of the box.
* @namespace matchers
*/
function Expectation(options) {
this.util = options.util || { buildFailureMessage: function() {} };
this.customEqualityTesters = options.customEqualityTesters || [];
this.actual = options.actual;
this.addExpectationResult = options.addExpectationResult || function(){};
this.isNot = options.isNot;
this.expector = new j$.Expector(options);
var customMatchers = options.customMatchers || {};
for (var matcherName in customMatchers) {
this[matcherName] = Expectation.prototype.wrapCompare(matcherName, customMatchers[matcherName]);
this[matcherName] = wrapSyncCompare(matcherName, customMatchers[matcherName]);
}
}
Expectation.prototype.wrapCompare = function(name, matcherFactory) {
return function() {
var args = Array.prototype.slice.call(arguments, 0),
expected = args.slice(0),
message = '';
args.unshift(this.actual);
var matcher = matcherFactory(this.util, this.customEqualityTesters),
matcherCompare = matcher.compare;
function defaultNegativeCompare() {
var result = matcher.compare.apply(null, args);
result.pass = !result.pass;
return result;
}
if (this.isNot) {
matcherCompare = matcher.negativeCompare || defaultNegativeCompare;
}
var result = matcherCompare.apply(null, args);
if (!result.pass) {
if (!result.message) {
args.unshift(this.isNot);
args.unshift(name);
message = this.util.buildFailureMessage.apply(null, args);
} else {
if (Object.prototype.toString.apply(result.message) === '[object Function]') {
message = result.message();
} else {
message = result.message;
}
}
}
if (expected.length == 1) {
expected = expected[0];
}
// TODO: how many of these params are needed?
this.addExpectationResult(
result.pass,
{
matcherName: name,
passed: result.pass,
message: message,
error: result.error,
actual: this.actual,
expected: expected // TODO: this may need to be arrayified/sliced
}
);
};
/**
* Add some context for an {@link expect}
* @function
* @name matchers#withContext
* @param {String} message - Additional context to show when the matcher fails
* @return {matchers}
*/
Expectation.prototype.withContext = function withContext(message) {
return addFilter(this, new ContextAddingFilter(message));
};
Expectation.addCoreMatchers = function(matchers) {
var prototype = Expectation.prototype;
/**
* Invert the matcher following this {@link expect}
* @member
* @name matchers#not
* @type {matchers}
* @example
* expect(something).not.toBe(true);
*/
Object.defineProperty(Expectation.prototype, 'not', {
get: function() {
return addFilter(this, syncNegatingFilter);
}
});
/**
* Asynchronous matchers.
* @namespace async-matchers
*/
function AsyncExpectation(options) {
var global = options.global || j$.getGlobal();
this.expector = new j$.Expector(options);
if (!global.Promise) {
throw new Error('expectAsync is unavailable because the environment does not support promises.');
}
if (!j$.isPromiseLike(this.expector.actual)) {
throw new Error('Expected expectAsync to be called with a promise.');
}
}
/**
* Add some context for an {@link expectAsync}
* @function
* @name async-matchers#withContext
* @param {String} message - Additional context to show when the async matcher fails
* @return {async-matchers}
*/
AsyncExpectation.prototype.withContext = function withContext(message) {
return addFilter(this, new ContextAddingFilter(message));
};
/**
* Invert the matcher following this {@link expectAsync}
* @member
* @name async-matchers#not
* @type {async-matchers}
* @example
* await expectAsync(myPromise).not.toBeResolved();
* @example
* return expectAsync(myPromise).not.toBeResolved();
*/
Object.defineProperty(AsyncExpectation.prototype, 'not', {
get: function() {
return addFilter(this, asyncNegatingFilter);
}
});
function wrapSyncCompare(name, matcherFactory) {
return function() {
var result = this.expector.compare(name, matcherFactory, arguments);
this.expector.processResult(result);
};
}
function wrapAsyncCompare(name, matcherFactory) {
return function() {
var self = this;
// Capture the call stack here, before we go async, so that it will contain
// frames that are relevant to the user instead of just parts of Jasmine.
var errorForStack = j$.util.errorWithStack();
return this.expector.compare(name, matcherFactory, arguments).then(function(result) {
self.expector.processResult(result, errorForStack, promiseForMessage);
});
};
}
function addCoreMatchers(prototype, matchers, wrapper) {
for (var matcherName in matchers) {
var matcher = matchers[matcherName];
prototype[matcherName] = prototype.wrapCompare(matcherName, matcher);
prototype[matcherName] = wrapper(matcherName, matcher);
}
}
function addFilter(source, filter) {
var result = Object.create(source);
result.expector = source.expector.addFilter(filter);
return result;
}
function negatedFailureMessage(result, matcherName, args, util) {
if (result.message) {
if (j$.isFunction_(result.message)) {
return result.message();
} else {
return result.message;
}
}
args = args.slice();
args.unshift(true);
args.unshift(matcherName);
return util.buildFailureMessage.apply(null, args);
}
function negate(result) {
result.pass = !result.pass;
return result;
}
var syncNegatingFilter = {
selectComparisonFunc: function(matcher) {
function defaultNegativeCompare() {
return negate(matcher.compare.apply(null, arguments));
}
return matcher.negativeCompare || defaultNegativeCompare;
},
buildFailureMessage: negatedFailureMessage
};
var asyncNegatingFilter = {
selectComparisonFunc: function(matcher) {
function defaultNegativeCompare() {
return matcher.compare.apply(this, arguments).then(negate);
}
return defaultNegativeCompare;
},
buildFailureMessage: negatedFailureMessage
};
function ContextAddingFilter(message) {
this.message = message;
}
ContextAddingFilter.prototype.modifyFailureMessage = function(msg) {
return this.message + ': ' + msg;
};
return {
factory: function(options) {
return new Expectation(options || {});
},
addCoreMatchers: function(matchers) {
addCoreMatchers(Expectation.prototype, matchers, wrapSyncCompare);
},
asyncFactory: function(options) {
return new AsyncExpectation(options || {});
},
addAsyncCoreMatchers: function(matchers) {
addCoreMatchers(AsyncExpectation.prototype, matchers, wrapAsyncCompare);
}
};
Expectation.Factory = function(options) {
options = options || {};
var expect = new Expectation(options);
// TODO: this would be nice as its own Object - NegativeExpectation
// TODO: copy instead of mutate options
options.isNot = true;
expect.not = new Expectation(options);
return expect;
};
return Expectation;
};

View File

@@ -0,0 +1,46 @@
getJasmineRequireObj().ExpectationFilterChain = function() {
function ExpectationFilterChain(maybeFilter, prev) {
this.filter_ = maybeFilter;
this.prev_ = prev;
}
ExpectationFilterChain.prototype.addFilter = function(filter) {
return new ExpectationFilterChain(filter, this);
};
ExpectationFilterChain.prototype.selectComparisonFunc = function(matcher) {
return this.callFirst_('selectComparisonFunc', arguments).result;
};
ExpectationFilterChain.prototype.buildFailureMessage = function(result, matcherName, args, util) {
return this.callFirst_('buildFailureMessage', arguments).result;
};
ExpectationFilterChain.prototype.modifyFailureMessage = function(msg) {
var result = this.callFirst_('modifyFailureMessage', arguments).result;
return result || msg;
};
ExpectationFilterChain.prototype.callFirst_ = function(fname, args) {
var prevResult;
if (this.prev_) {
prevResult = this.prev_.callFirst_(fname, args);
if (prevResult.found) {
return prevResult;
}
}
if (this.filter_ && this.filter_[fname]) {
return {
found: true,
result: this.filter_[fname].apply(this.filter_, args)
};
}
return {found: false};
};
return ExpectationFilterChain;
};

View File

@@ -45,10 +45,16 @@ getJasmineRequireObj().buildExpectationResult = function() {
var error = options.error;
if (!error) {
try {
throw new Error(message());
} catch (e) {
error = e;
if (options.errorForStack) {
error = options.errorForStack;
} else if (options.stack) {
error = options;
} else {
try {
throw new Error(message());
} catch (e) {
error = e;
}
}
}
return stackFormatter(error);

80
src/core/Expector.js Normal file
View File

@@ -0,0 +1,80 @@
getJasmineRequireObj().Expector = function(j$) {
function Expector(options) {
this.util = options.util || { buildFailureMessage: function() {} };
this.customEqualityTesters = options.customEqualityTesters || [];
this.actual = options.actual;
this.addExpectationResult = options.addExpectationResult || function(){};
this.filters = new j$.ExpectationFilterChain();
}
Expector.prototype.instantiateMatcher = function(matcherName, matcherFactory, args) {
this.matcherName = matcherName;
this.args = Array.prototype.slice.call(args, 0);
this.expected = this.args.slice(0);
this.args.unshift(this.actual);
var matcher = matcherFactory(this.util, this.customEqualityTesters);
var comparisonFunc = this.filters.selectComparisonFunc(matcher);
return comparisonFunc || matcher.compare;
};
Expector.prototype.buildMessage = function(result) {
var self = this;
if (result.pass) {
return '';
}
var msg = this.filters.buildFailureMessage(result, this.matcherName, this.args, this.util, defaultMessage);
return this.filters.modifyFailureMessage(msg || defaultMessage());
function defaultMessage() {
if (!result.message) {
var args = self.args.slice();
args.unshift(false);
args.unshift(self.matcherName);
return self.util.buildFailureMessage.apply(null, args);
} else if (j$.isFunction_(result.message)) {
return result.message();
} else {
return result.message;
}
}
};
Expector.prototype.compare = function(matcherName, matcherFactory, args) {
var matcherCompare = this.instantiateMatcher(matcherName, matcherFactory, args);
return matcherCompare.apply(null, this.args);
};
Expector.prototype.addFilter = function(filter) {
var result = Object.create(this);
result.filters = this.filters.addFilter(filter);
return result;
};
Expector.prototype.processResult = function(result, errorForStack, actualOverride) {
this.args[0] = actualOverride || this.args[0];
var message = this.buildMessage(result);
if (this.expected.length === 1) {
this.expected = this.expected[0];
}
this.addExpectationResult(
result.pass,
{
matcherName: this.matcherName,
passed: result.pass,
message: message,
error: errorForStack ? undefined : result.error,
errorForStack: errorForStack || undefined,
actual: this.actual,
expected: this.expected // TODO: this may need to be arrayified/sliced
}
);
};
return Expector;
};

View File

@@ -13,18 +13,29 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
}
};
this.originalHandlers = {};
this.installOne_ = function installOne_(errorType) {
this.originalHandlers[errorType] = global.process.listeners(errorType);
global.process.removeAllListeners(errorType);
global.process.on(errorType, onerror);
this.uninstall = function uninstall() {
var errorTypes = Object.keys(this.originalHandlers);
for (var iType = 0; iType < errorTypes.length; iType++) {
var errorType = errorTypes[iType];
global.process.removeListener(errorType, onerror);
for (var i = 0; i < this.originalHandlers[errorType].length; i++) {
global.process.on(errorType, this.originalHandlers[errorType][i]);
}
delete this.originalHandlers[errorType];
}
};
};
this.install = function install() {
if (global.process && global.process.listeners && j$.isFunction_(global.process.on)) {
var originalHandlers = global.process.listeners('uncaughtException');
global.process.removeAllListeners('uncaughtException');
global.process.on('uncaughtException', onerror);
this.uninstall = function uninstall() {
global.process.removeListener('uncaughtException', onerror);
for (var i = 0; i < originalHandlers.length; i++) {
global.process.on('uncaughtException', originalHandlers[i]);
}
};
this.installOne_('uncaughtException');
this.installOne_('unhandledRejection');
} else {
var originalHandler = global.onerror;
global.onerror = onerror;

View File

@@ -233,8 +233,8 @@ getJasmineRequireObj().pp = function(j$) {
if (el.innerHTML === '') {
this.append(el.outerHTML.replace(closingTag, ''));
} else {
var tagEnd = el.outerHTML.indexOf(el.innerHTML);
this.append(el.outerHTML.substring(0, tagEnd));
var tagEnd = el.outerHTML.indexOf('>');
this.append(el.outerHTML.substring(0, tagEnd + 1));
this.append('...' + closingTag);
}
};

View File

@@ -5,26 +5,29 @@ getJasmineRequireObj().QueueRunner = function(j$) {
function once(fn) {
var called = false;
return function() {
return function(arg) {
if (!called) {
called = true;
fn.apply(null, arguments);
// Direct call using single parameter, because cleanup/next does not need more
fn(arg);
}
return null;
};
}
function emptyFn() {}
function QueueRunner(attrs) {
var queueableFns = attrs.queueableFns || [];
this.queueableFns = queueableFns.concat(attrs.cleanupFns || []);
this.firstCleanupIx = queueableFns.length;
this.onComplete = attrs.onComplete || function() {};
this.onComplete = attrs.onComplete || emptyFn;
this.clearStack = attrs.clearStack || function(fn) {fn();};
this.onException = attrs.onException || function() {};
this.onException = attrs.onException || emptyFn;
this.userContext = attrs.userContext || new j$.UserContext();
this.timeout = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout};
this.fail = attrs.fail || function() {};
this.globalErrors = attrs.globalErrors || { pushListener: function() {}, popListener: function() {} };
this.fail = attrs.fail || emptyFn;
this.globalErrors = attrs.globalErrors || { pushListener: emptyFn, popListener: emptyFn };
this.completeOnFirstError = !!attrs.completeOnFirstError;
this.errored = false;
@@ -66,7 +69,9 @@ getJasmineRequireObj().QueueRunner = function(j$) {
next(error);
},
cleanup = once(function cleanup() {
self.clearTimeout(timeoutId);
if (timeoutId !== void 0) {
self.clearTimeout(timeoutId);
}
self.globalErrors.popListener(handleError);
}),
next = once(function next(err) {
@@ -105,12 +110,16 @@ getJasmineRequireObj().QueueRunner = function(j$) {
self.globalErrors.pushListener(handleError);
if (queueableFn.timeout) {
if (queueableFn.timeout !== undefined) {
var timeoutInterval = queueableFn.timeout || j$.DEFAULT_TIMEOUT_INTERVAL;
timeoutId = self.setTimeout(function() {
var error = new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.');
var error = new Error(
'Timeout - Async callback was not invoked within ' + timeoutInterval + 'ms ' +
(queueableFn.timeout ? '(custom timeout)' : '(set by jasmine.DEFAULT_TIMEOUT_INTERVAL)')
);
onException(error);
next();
}, queueableFn.timeout());
}, timeoutInterval);
}
try {
@@ -159,7 +168,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
return;
}
self.errored = result.errored;
self.errored = self.errored || result.errored;
if (this.completeOnFirstError && result.errored) {
this.skipToCleanup(iterativeIndex);

View File

@@ -1,6 +1,7 @@
getJasmineRequireObj().Spec = function(j$) {
function Spec(attrs) {
this.expectationFactory = attrs.expectationFactory;
this.asyncExpectationFactory = attrs.asyncExpectationFactory;
this.resultCallback = attrs.resultCallback || function() {};
this.id = attrs.id;
this.description = attrs.description || '';
@@ -57,6 +58,10 @@ getJasmineRequireObj().Spec = function(j$) {
return this.expectationFactory(actual, this);
};
Spec.prototype.expectAsync = function(actual) {
return this.asyncExpectationFactory(actual, this);
};
Spec.prototype.execute = function(onComplete, excluded) {
var self = this;
@@ -152,8 +157,11 @@ getJasmineRequireObj().Spec = function(j$) {
return this.getSpecName(this);
};
Spec.prototype.addDeprecationWarning = function(msg) {
this.result.deprecationWarnings.push(this.expectationResultFactory({ message: msg }));
Spec.prototype.addDeprecationWarning = function(deprecation) {
if (typeof deprecation === 'string') {
deprecation = { message: deprecation };
}
this.result.deprecationWarnings.push(this.expectationResultFactory(deprecation));
};
var extractCustomPendingMessage = function(e) {
@@ -174,5 +182,6 @@ getJasmineRequireObj().Spec = function(j$) {
};
if (typeof window == void 0 && typeof exports == 'object') {
/* globals exports */
exports.Spec = jasmineRequire.Spec;
}

View File

@@ -120,6 +120,23 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
return spy;
};
this.spyOnAllFunctions = function(obj) {
if (j$.util.isUndefined(obj)) {
throw new Error('spyOnAllFunctions could not find an object to spy upon');
}
for (var prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop) && obj[prop] instanceof Function) {
var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
if ((descriptor.writable || descriptor.set) && descriptor.configurable) {
this.spyOn(obj, prop);
}
}
}
return obj;
};
this.clearSpies = function() {
var spies = currentSpies();
for (var i = spies.length - 1; i >= 0; i--) {

View File

@@ -1,13 +1,14 @@
getJasmineRequireObj().StackTrace = function(j$) {
function StackTrace(rawTrace) {
var lines = rawTrace
function StackTrace(error) {
var lines = error.stack
.split('\n')
.filter(function(line) { return line !== ''; });
if (lines[0].match(/^Error/)) {
this.message = lines.shift();
} else {
this.message = undefined;
var extractResult = extractMessage(error.message, lines);
if (extractResult) {
this.message = extractResult.message;
lines = extractResult.remainder;
}
var parseResult = tryParseFrames(lines);
@@ -75,6 +76,34 @@ getJasmineRequireObj().StackTrace = function(j$) {
}
}
}
function extractMessage(message, stackLines) {
var len = messagePrefixLength(message, stackLines);
if (len > 0) {
return {
message: stackLines.slice(0, len).join('\n'),
remainder: stackLines.slice(len)
};
}
}
function messagePrefixLength(message, stackLines) {
if (!stackLines[0].match(/^Error/)) {
return 0;
}
var messageLines = message.split('\n');
var i;
for (i = 1; i < messageLines.length; i++) {
if (messageLines[i] !== stackLines[i]) {
return 0;
}
}
return messageLines.length;
}
return StackTrace;
};

View File

@@ -5,6 +5,7 @@ getJasmineRequireObj().Suite = function(j$) {
this.parentSuite = attrs.parentSuite;
this.description = attrs.description;
this.expectationFactory = attrs.expectationFactory;
this.asyncExpectationFactory = attrs.asyncExpectationFactory;
this.expectationResultFactory = attrs.expectationResultFactory;
this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
@@ -37,6 +38,10 @@ getJasmineRequireObj().Suite = function(j$) {
return this.expectationFactory(actual, this);
};
Suite.prototype.expectAsync = function(actual) {
return this.asyncExpectationFactory(actual, this);
};
Suite.prototype.getFullName = function() {
var fullName = [];
for (var parentSuite = this; parentSuite; parentSuite = parentSuite.parentSuite) {
@@ -148,8 +153,11 @@ getJasmineRequireObj().Suite = function(j$) {
}
};
Suite.prototype.addDeprecationWarning = function(msg) {
this.result.deprecationWarnings.push(this.expectationResultFactory({ message: msg }));
Suite.prototype.addDeprecationWarning = function(deprecation) {
if (typeof deprecation === 'string') {
deprecation = { message: deprecation };
}
this.result.deprecationWarnings.push(this.expectationResultFactory(deprecation));
};
function isFailure(args) {
@@ -160,5 +168,6 @@ getJasmineRequireObj().Suite = function(j$) {
};
if (typeof window == void 0 && typeof exports == 'object') {
/* globals exports */
exports.Suite = jasmineRequire.Suite;
}

View File

@@ -174,8 +174,11 @@ getJasmineRequireObj().TreeProcessor = function() {
queueRunnerFactory({
onComplete: function () {
var args = Array.prototype.slice.call(arguments, [0]);
node.cleanupBeforeAfter();
nodeComplete(node, node.getResult(), done);
nodeComplete(node, node.getResult(), function() {
done.apply(undefined, args);
});
},
queueableFns: [onStart].concat(wrapChildren(node, segmentNumber)),
userContext: node.sharedUserContext(),

View File

@@ -32,6 +32,7 @@ getJasmineRequireObj().Any = function(j$) {
}
/* jshint -W122 */
/* global Symbol */
if (typeof Symbol != 'undefined' && this.expectedObject == Symbol) {
return typeof other == 'symbol';
}

View File

@@ -19,7 +19,7 @@ getJasmineRequireObj().ArrayContaining = function(j$) {
};
ArrayContaining.prototype.jasmineToString = function () {
return '<jasmine.arrayContaining(' + jasmine.pp(this.sample) +')>';
return '<jasmine.arrayContaining(' + j$.pp(this.sample) +')>';
};
return ArrayContaining;

View File

@@ -0,0 +1,25 @@
getJasmineRequireObj().Empty = function (j$) {
function Empty() {}
Empty.prototype.asymmetricMatch = function (other) {
if (j$.isString_(other) || j$.isArray_(other) || j$.isTypedArray_(other)) {
return other.length === 0;
}
if (j$.isMap(other) || j$.isSet(other)) {
return other.size === 0;
}
if (j$.isObject_(other)) {
return Object.keys(other).length === 0;
}
return false;
};
Empty.prototype.jasmineToString = function () {
return '<jasmine.empty>';
};
return Empty;
};

View File

@@ -0,0 +1,14 @@
getJasmineRequireObj().Falsy = function(j$) {
function Falsy() {}
Falsy.prototype.asymmetricMatch = function(other) {
return !other;
};
Falsy.prototype.jasmineToString = function() {
return '<jasmine.falsy>';
};
return Falsy;
};

View File

@@ -0,0 +1,26 @@
getJasmineRequireObj().NotEmpty = function (j$) {
function NotEmpty() {}
NotEmpty.prototype.asymmetricMatch = function (other) {
if (j$.isString_(other) || j$.isArray_(other) || j$.isTypedArray_(other)) {
return other.length !== 0;
}
if (j$.isMap(other) || j$.isSet(other)) {
return other.size !== 0;
}
if (j$.isObject_(other)) {
return Object.keys(other).length !== 0;
}
return false;
};
NotEmpty.prototype.jasmineToString = function () {
return '<jasmine.notEmpty>';
};
return NotEmpty;
};

View File

@@ -0,0 +1,14 @@
getJasmineRequireObj().Truthy = function(j$) {
function Truthy() {}
Truthy.prototype.asymmetricMatch = function(other) {
return !!other;
};
Truthy.prototype.jasmineToString = function() {
return '<jasmine.truthy>';
};
return Truthy;
};

View File

@@ -101,7 +101,14 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
};
j$.isDomNode = function(obj) {
return obj.nodeType > 0;
// Node is a function, because constructors
return typeof jasmineGlobal.Node !== 'undefined' ?
obj instanceof jasmineGlobal.Node :
obj !== null &&
typeof obj === 'object' &&
typeof obj.nodeType === 'number' &&
typeof obj.nodeName === 'string';
// return obj.nodeType > 0;
};
j$.isMap = function(obj) {
@@ -113,7 +120,11 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
};
j$.isPromise = function(obj) {
return typeof jasmineGlobal.Promise !== 'undefined' && obj.constructor === jasmineGlobal.Promise;
return typeof jasmineGlobal.Promise !== 'undefined' && !!obj && obj.constructor === jasmineGlobal.Promise;
};
j$.isPromiseLike = function(obj) {
return !!obj && j$.isFunction_(obj.then);
};
j$.fnNameFor = function(func) {
@@ -121,8 +132,8 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
return func.name;
}
var matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/) ||
func.toString().match(/^\s*\[object\s*(\w*)Constructor\]/);
var matches = func.toString().match(/^\s*function\s*(\w+)\s*\(/) ||
func.toString().match(/^\s*\[object\s*(\w+)Constructor\]/);
return matches ? matches[1] : '<anonymous>';
};
@@ -148,6 +159,38 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
return new j$.Anything();
};
/**
* Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
* that will succeed if the actual value being compared is `true` or anything truthy.
* @name jasmine.truthy
* @function
*/
j$.truthy = function() {return new j$.Truthy();};
/**
* Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
* that will succeed if the actual value being compared is `null`, `undefined`, `0`, `false` or anything falsey.
* @name jasmine.falsy
* @function
*/
j$.falsy = function() {return new j$.Falsy();};
/**
* Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
* that will succeed if the actual value being compared is empty.
* @name jasmine.empty
* @function
*/
j$.empty = function() {return new j$.Empty();};
/**
* Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
* that will succeed if the actual value being compared is not empty.
* @name jasmine.notEmpty
* @function
*/
j$.notEmpty = function() {return new j$.NotEmpty();};
/**
* Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}),
* that will succeed if the actual value being compared contains at least the keys and values.

View File

@@ -0,0 +1,22 @@
getJasmineRequireObj().toBeRejected = function(j$) {
/**
* Expect a promise to be rejected.
* @function
* @async
* @name async-matchers#toBeRejected
* @example
* await expectAsync(aPromise).toBeRejected();
* @example
* return expectAsync(aPromise).toBeRejected();
*/
return function toBeResolved(util) {
return {
compare: function(actual) {
return actual.then(
function() { return {pass: false}; },
function() { return {pass: true}; }
);
}
};
};
};

View File

@@ -0,0 +1,46 @@
getJasmineRequireObj().toBeRejectedWith = function(j$) {
/**
* Expect a promise to be rejected with a value equal to the expected, using deep equality comparison.
* @function
* @async
* @name async-matchers#toBeRejectedWith
* @param {Object} expected - Value that the promise is expected to be rejected with
* @example
* await expectAsync(aPromise).toBeRejectedWith({prop: 'value'});
* @example
* return expectAsync(aPromise).toBeRejectedWith({prop: 'value'});
*/
return function toBeRejectedWith(util, customEqualityTesters) {
return {
compare: function(actualPromise, expectedValue) {
function prefix(passed) {
return 'Expected a promise ' +
(passed ? 'not ' : '') +
'to be rejected with ' + j$.pp(expectedValue);
}
return actualPromise.then(
function() {
return {
pass: false,
message: prefix(false) + ' but it was resolved.'
};
},
function(actualValue) {
if (util.equals(actualValue, expectedValue, customEqualityTesters)) {
return {
pass: true,
message: prefix(true) + '.'
};
} else {
return {
pass: false,
message: prefix(false) + ' but it was rejected with ' + j$.pp(actualValue) + '.'
};
}
}
);
}
};
};
};

View File

@@ -0,0 +1,22 @@
getJasmineRequireObj().toBeResolved = function(j$) {
/**
* Expect a promise to be resolved.
* @function
* @async
* @name async-matchers#toBeResolved
* @example
* await expectAsync(aPromise).toBeResolved();
* @example
* return expectAsync(aPromise).toBeResolved();
*/
return function toBeResolved(util) {
return {
compare: function(actual) {
return actual.then(
function() { return {pass: true}; },
function() { return {pass: false}; }
);
}
};
};
};

View File

@@ -0,0 +1,46 @@
getJasmineRequireObj().toBeResolvedTo = function(j$) {
/**
* Expect a promise to be resolved to a value equal to the expected, using deep equality comparison.
* @function
* @async
* @name async-matchers#toBeResolvedTo
* @param {Object} expected - Value that the promise is expected to resolve to
* @example
* await expectAsync(aPromise).toBeResolvedTo({prop: 'value'});
* @example
* return expectAsync(aPromise).toBeResolvedTo({prop: 'value'});
*/
return function toBeResolvedTo(util, customEqualityTesters) {
return {
compare: function(actualPromise, expectedValue) {
function prefix(passed) {
return 'Expected a promise ' +
(passed ? 'not ' : '') +
'to be resolved to ' + j$.pp(expectedValue);
}
return actualPromise.then(
function(actualValue) {
if (util.equals(actualValue, expectedValue, customEqualityTesters)) {
return {
pass: true,
message: prefix(true) + '.'
};
} else {
return {
pass: false,
message: prefix(false) + ' but it was resolved to ' + j$.pp(actualValue) + '.'
};
}
},
function() {
return {
pass: false,
message: prefix(false) + ' but it was rejected.'
};
}
);
}
};
};
};

View File

@@ -225,8 +225,14 @@ getJasmineRequireObj().matchersUtil = function(j$) {
});
for (i = 0; i < aLength || i < bLength; i++) {
var formatter = false;
diffBuilder.withPath(i, function() {
result = eq(i < aLength ? a[i] : void 0, i < bLength ? b[i] : void 0, aStack, bStack, customTesters, diffBuilder) && result;
if (i >= bLength) {
diffBuilder.record(a[i], void 0, actualArrayIsLongerFormatter);
result = false;
} else {
result = eq(i < aLength ? a[i] : void 0, i < bLength ? b[i] : void 0, aStack, bStack, customTesters, diffBuilder) && result;
}
});
}
if (!result) {
@@ -452,6 +458,13 @@ getJasmineRequireObj().matchersUtil = function(j$) {
', but was ' + j$.pp(actual) + '.';
}
function actualArrayIsLongerFormatter(actual, expected, path) {
return 'Unexpected ' +
path + (path.depth() ? ' = ' : '') +
j$.pp(actual) +
' in array.';
}
function formatKeyValuePairs(obj) {
var formatted = '';
for (var key in obj) {

View File

@@ -0,0 +1,16 @@
getJasmineRequireObj().requireAsyncMatchers = function(jRequire, j$) {
var availableMatchers = [
'toBeResolved',
'toBeRejected',
'toBeResolvedTo',
'toBeRejectedWith'
],
matchers = {};
for (var i = 0; i < availableMatchers.length; i++) {
var name = availableMatchers[i];
matchers[name] = jRequire[name](j$);
}
return matchers;
};

View File

@@ -21,6 +21,7 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
'toHaveBeenCalledBefore',
'toHaveBeenCalledTimes',
'toHaveBeenCalledWith',
'toHaveClass',
'toMatch',
'toThrow',
'toThrowError',

View File

@@ -1,4 +1,4 @@
getJasmineRequireObj().toBe = function() {
getJasmineRequireObj().toBe = function(j$) {
/**
* {@link expect} the actual value to be `===` to the expected value.
* @function
@@ -7,12 +7,20 @@ getJasmineRequireObj().toBe = function() {
* @example
* expect(thing).toBe(realThing);
*/
function toBe() {
function toBe(util) {
var tip = ' Tip: To check for deep equality, use .toEqual() instead of .toBe().';
return {
compare: function(actual, expected) {
return {
pass: actual === expected
var result = {
pass: actual === expected,
};
if (typeof expected === 'object') {
result.message = util.buildFailureMessage('toBe', result.pass, actual, expected) + tip;
}
return result;
}
};
}

View File

@@ -1,4 +1,4 @@
jasmineRequire.toHaveClass = function(j$) {
getJasmineRequireObj().toHaveClass = function(j$) {
/**
* {@link expect} the actual value to be a DOM element that has the expected class
* @function

View File

@@ -1,4 +1,5 @@
var getJasmineRequireObj = (function (jasmineGlobal) {
/* globals exports, global, module, window */
var jasmineRequire;
if (typeof module !== 'undefined' && module.exports && typeof exports !== 'undefined') {
@@ -36,7 +37,9 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
j$.Env = jRequire.Env(j$);
j$.StackTrace = jRequire.StackTrace(j$);
j$.ExceptionFormatter = jRequire.ExceptionFormatter(j$);
j$.Expectation = jRequire.Expectation();
j$.ExpectationFilterChain = jRequire.ExpectationFilterChain();
j$.Expector = jRequire.Expector(j$);
j$.Expectation = jRequire.Expectation(j$);
j$.buildExpectationResult = jRequire.buildExpectationResult();
j$.JsApiReporter = jRequire.JsApiReporter();
j$.matchersUtil = jRequire.matchersUtil(j$);
@@ -63,7 +66,13 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
j$.ObjectPath = jRequire.ObjectPath(j$);
j$.GlobalErrors = jRequire.GlobalErrors(j$);
j$.Truthy = jRequire.Truthy(j$);
j$.Falsy = jRequire.Falsy(j$);
j$.Empty = jRequire.Empty(j$);
j$.NotEmpty = jRequire.NotEmpty(j$);
j$.matchers = jRequire.requireMatchers(jRequire, j$);
j$.asyncMatchers = jRequire.requireAsyncMatchers(jRequire, j$);
return j$;
};

View File

@@ -63,6 +63,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
* @param {String} description Textual description of what this spec is checking
* @param {implementationCallback} [testFunction] Function that contains the code of your test. If not provided the test will be `pending`.
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async spec.
* @see async
*/
it: function() {
return env.it.apply(env, arguments);
@@ -92,6 +93,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
* @param {String} description Textual description of what this spec is checking.
* @param {implementationCallback} testFunction Function that contains the code of your test.
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async spec.
* @see async
*/
fit: function() {
return env.fit.apply(env, arguments);
@@ -104,6 +106,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
* @global
* @param {implementationCallback} [function] Function that contains the code to setup your specs.
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeEach.
* @see async
*/
beforeEach: function() {
return env.beforeEach.apply(env, arguments);
@@ -116,6 +119,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
* @global
* @param {implementationCallback} [function] Function that contains the code to teardown your specs.
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterEach.
* @see async
*/
afterEach: function() {
return env.afterEach.apply(env, arguments);
@@ -130,6 +134,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
* @global
* @param {implementationCallback} [function] Function that contains the code to setup your specs.
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeAll.
* @see async
*/
beforeAll: function() {
return env.beforeAll.apply(env, arguments);
@@ -144,6 +149,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
* @global
* @param {implementationCallback} [function] Function that contains the code to teardown your specs.
* @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterAll.
* @see async
*/
afterAll: function() {
return env.afterAll.apply(env, arguments);
@@ -161,6 +167,25 @@ getJasmineRequireObj().interface = function(jasmine, env) {
return env.expect(actual);
},
/**
* Create an asynchronous expectation for a spec. Note that the matchers
* that are provided by an asynchronous expectation all return promises
* which must be either returned from the spec or waited for using `await`
* in order for Jasmine to associate them with the correct spec.
* @name expectAsync
* @function
* @global
* @param {Object} actual - Actual computed value to test expectations against.
* @return {async-matchers}
* @example
* await expectAsync(somePromise).toBeResolved();
* @example
* return expectAsync(somePromise).toBeResolved();
*/
expectAsync: function(actual) {
return env.expectAsync(actual);
},
/**
* Mark a spec as pending, expectation results will be ignored.
* @name pending
@@ -210,6 +235,18 @@ getJasmineRequireObj().interface = function(jasmine, env) {
return env.spyOnProperty(obj, methodName, accessType);
},
/**
* Installs spies on all writable and configurable properties of an object.
* @name spyOnAllFunctions
* @function
* @global
* @param {Object} obj - The object upon which to install the {@link Spy}s
* @returns {Object} the spied object
*/
spyOnAllFunctions: function(obj) {
return env.spyOnAllFunctions(obj);
},
jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer()
}),

View File

@@ -112,7 +112,7 @@ getJasmineRequireObj().util = function(j$) {
return false;
}
function errorWithStack() {
util.errorWithStack = function errorWithStack () {
// Don't throw and catch if we don't have to, because it makes it harder
// for users to debug their code with exception breakpoints.
var error = new Error();
@@ -127,10 +127,10 @@ getJasmineRequireObj().util = function(j$) {
} catch (e) {
return e;
}
}
};
function callerFile() {
var trace = new j$.StackTrace(errorWithStack().stack);
var trace = new j$.StackTrace(util.errorWithStack());
return trace.frames[2].file;
}

View File

@@ -51,7 +51,7 @@ jasmineRequire.HtmlReporter = function(j$) {
function HtmlReporter(options) {
var env = options.env || {},
var config = function() { return (options.env && options.env.configuration()) || {}; },
getContainer = options.getContainer,
createElement = options.createElement,
createTextNode = options.createTextNode,
@@ -119,7 +119,7 @@ jasmineRequire.HtmlReporter = function(j$) {
}
symbols.appendChild(createDom('li', {
className: noExpectations(result) ? 'jasmine-empty' : 'jasmine-' + result.status,
className: this.displaySpecInCorrectFormat(result),
id: 'spec_' + result.id,
title: result.fullName
}
@@ -132,13 +132,25 @@ jasmineRequire.HtmlReporter = function(j$) {
addDeprecationWarnings(result);
};
this.displaySpecInCorrectFormat = function(result) {
return noExpectations(result) ? 'jasmine-empty' : this.resultStatus(result.status);
};
this.resultStatus = function(status) {
if(status === 'excluded') {
return config().hideDisabled ? 'jasmine-excluded-no-display' : 'jasmine-excluded';
}
return 'jasmine-' + status;
};
this.jasmineDone = function(doneResult) {
var banner = find('.jasmine-banner');
var alert = find('.jasmine-alert');
var order = doneResult && doneResult.order;
var i;
alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
banner.appendChild(optionsMenu(env));
banner.appendChild(optionsMenu(config()));
if (stateBuilder.specsExecuted < totalSpecsDefined) {
var skippedMessage = 'Ran ' + stateBuilder.specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
@@ -298,7 +310,7 @@ jasmineRequire.HtmlReporter = function(j$) {
}
}
function optionsMenu(env) {
function optionsMenu(config) {
var optionsMenuDom = createDom('div', { className: 'jasmine-run-options' },
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
createDom('div', { className: 'jasmine-payload' },
@@ -322,26 +334,39 @@ jasmineRequire.HtmlReporter = function(j$) {
id: 'jasmine-random-order',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order')),
createDom('div', { className: 'jasmine-hide-disabled' },
createDom('input', {
className: 'jasmine-disabled',
id: 'jasmine-hide-disabled',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-hide-disabled' }, 'hide disabled tests'))
)
);
var failFastCheckbox = optionsMenuDom.querySelector('#jasmine-fail-fast');
failFastCheckbox.checked = env.stoppingOnSpecFailure();
failFastCheckbox.checked = config.failFast;
failFastCheckbox.onclick = function() {
navigateWithNewParam('failFast', !env.stoppingOnSpecFailure());
navigateWithNewParam('failFast', !config.failFast);
};
var throwCheckbox = optionsMenuDom.querySelector('#jasmine-throw-failures');
throwCheckbox.checked = env.throwingExpectationFailures();
throwCheckbox.checked = config.oneFailurePerSpec;
throwCheckbox.onclick = function() {
navigateWithNewParam('throwFailures', !env.throwingExpectationFailures());
navigateWithNewParam('throwFailures', !config.oneFailurePerSpec);
};
var randomCheckbox = optionsMenuDom.querySelector('#jasmine-random-order');
randomCheckbox.checked = env.randomTests();
randomCheckbox.checked = config.random;
randomCheckbox.onclick = function() {
navigateWithNewParam('random', !env.randomTests());
navigateWithNewParam('random', !config.random);
};
var hideDisabled = optionsMenuDom.querySelector('#jasmine-hide-disabled');
hideDisabled.checked = config.hideDisabled;
hideDisabled.onclick = function() {
navigateWithNewParam('hideDisabled', !config.hideDisabled);
};
var optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger'),

View File

@@ -16,6 +16,11 @@ $empty-color: #eff543;
$neutral-color: #bababa;
$jasmine-color: #8a4182;
$passing-mark: "\02022";
$failing-mark: "\d7";
$pending-mark: "*";
$space: "\0020";
$font-size: 11px;
$large-font-size: 14px;
@@ -120,7 +125,7 @@ body {
&:before {
color: $passing-color;
content: "\02022";
content: $passing-mark;
}
}
@@ -129,26 +134,31 @@ body {
&:before {
color: $failing-color;
content: "\d7";
content: $failing-mark;
font-weight: bold;
margin-left: -1px;
}
}
&.jasmine-excluded {
&.jasmine-excluded {
font-size: 14px;
&:before {
color: $neutral-color;
content: "\02022";
content: $passing-mark;
}
}
&.jasmine-excluded-no-display {
font-size: 14px;
display: none;
}
&.jasmine-pending {
line-height: 17px;
&:before {
color: $pending-color;
content: "*";
content: $pending-mark;
}
}
@@ -157,7 +167,7 @@ body {
&:before {
color: $pending-color;
content: "\02022";
content: $passing-mark;
}
}
}
@@ -294,7 +304,31 @@ body {
&.jasmine-excluded a {
color: $neutral-color;
}
}
}
.jasmine-specs {
li {
&.jasmine-passed a:before {
content: $passing-mark + $space;
}
&.jasmine-failed a:before {
content: $failing-mark + $space;
}
&.jasmine-empty a:before {
content: $pending-mark + $space;
}
&.jasmine-pending a:before {
content: $passing-mark + $space;
}
&.jasmine-excluded a:before {
content: $passing-mark + $space;
}
}
}
@@ -332,7 +366,7 @@ body {
color: $text-color;
white-space: pre;
white-space: pre-wrap;
}
.jasmine-result-message span.jasmine-result {

View File

@@ -3,5 +3,4 @@ jasmineRequire.html = function(j$) {
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
j$.QueryString = jasmineRequire.QueryString();
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
j$.matchers.toHaveClass = jasmineRequire.toHaveClass(j$);
};

View File

@@ -1,12 +0,0 @@
#!/bin/bash -e
set -e
git clone https://github.com/jasmine/jasmine.github.io.git
cd jasmine.github.io
export BUNDLE_GEMFILE=$PWD/Gemfile
bundle
bundle exec rake update_edge_jasmine
bundle exec rake phantom