Compare commits

...

226 Commits

Author SHA1 Message Date
Gregg Van Hove
8fca3b4c11 Fix links in 3.4 release notes 2019-04-03 17:13:18 -07:00
Gregg Van Hove
e636f5f822 Bump version to 3.4 2019-04-03 17:03:07 -07:00
Gregg Van Hove
74fd0e08e7 No fit in the suite 2019-04-01 21:01:22 -07:00
Gregg Van Hove
618e24b2f8 Handle WebSocket events in IE when detecting Errors
- Fixes #1623
2019-04-01 18:52:27 -07:00
Gregg Van Hove
5c7e25e228 Allow excluded specs in CI without breaking the output 2019-04-01 18:52:01 -07:00
Gregg Van Hove
54af109d40 Merge branch 'wood1986-fix/npm-audit-dependencies-and-fast-glob-only-failed-tests'
- Merges #1672 from @wood1986
2019-03-26 17:12:53 -07:00
wood
873a237e3d Consolidate some dev dependencies and use more maintained versions 2019-03-26 17:12:21 -07:00
Gregg Van Hove
8ca4463e01 Make node execution default and override for browsers 2019-03-25 18:37:50 -07:00
Gregg Van Hove
449eb516cc Fix sauce status codes and try travis built-in node support 2019-03-25 18:33:39 -07:00
Gregg Van Hove
a5df5a6ee9 Use the correct env var from travis for tunnels 2019-03-25 18:12:15 -07:00
Gregg Van Hove
be583232b4 bump dependencies for security fixes 2019-03-25 18:01:13 -07:00
Gregg Van Hove
d389d3c002 Merge branch 'wood1986-features/no-ruby'
- Merges #1658 from @wood1986
- Fixes #883
2019-03-25 17:56:19 -07:00
Gregg Van Hove
994d11d4f3 update node CI script to work with SauceLabs 2019-03-25 17:56:06 -07:00
wood
828d14f48e Use node.js for browser-based CI 2019-03-25 17:55:53 -07:00
Gregg Van Hove
f5663a9076 Merge branch 'johnjbarton-duration'
- Merges #1660 from @johnjbarton
- Fixes #1646
2019-03-14 19:12:39 -07:00
johnjbarton
a8c2399dd8 feat(result.duration): report test duration in ms
Wrap spec start/complete in Timer start/elapsed.
configuration.timeSpecDuration = false will disable feature.

 * Add Suite result.duration, elapsed time in ms

 * Remove timeSpecDuration option.

 * Respond to review, use noopTimer
2019-03-14 09:13:57 -07:00
Gregg Van Hove
7c0f013003 Merge branch 'johnjbarton-noop-timer'
- Merges #1669 from @johnjbarton
2019-03-13 17:34:12 -07:00
johnjbarton
ca2b62b00e refactor(Timer): share htmlReporter noopTimer via Timer.js 2019-03-12 16:26:04 -07:00
Gregg Van Hove
4108deca02 Build distribution for various typo PRs 2019-03-11 17:39:03 -07:00
Gregg Van Hove
def278f90f Merge branch 'typo-suites' of https://github.com/FelixRilling/jasmine into FelixRilling-typo-suites
- Merges #1666 from @FelixRilling
2019-03-11 17:38:29 -07:00
Gregg Van Hove
6bd4a29360 Merge branch 'jsdoc-validation' of https://github.com/FelixRilling/jasmine into FelixRilling-jsdoc-validation
- Merges #1667 from @FelixRilling
2019-03-11 17:37:43 -07:00
Gregg Van Hove
fd037f53a3 Merge branch 'typo-comments' of https://github.com/FelixRilling/jasmine into FelixRilling-typo-comments
- Merges #1665 from @FelixRilling
2019-03-11 17:34:44 -07:00
Gregg Van Hove
348242b712 Merge branch 'FelixRilling-typo-received'
- Merges #1664 from @FelixRilling
- Fixes #1663
2019-03-11 17:32:32 -07:00
Felix Rilling
b74e0abee1 Fixed flipped JSDoc. 2019-03-10 11:17:50 +01:00
Felix Rilling
e33b12b17c Fixed typos in test suite descriptions. 2019-03-10 11:07:40 +01:00
Felix Rilling
dde93ade18 Fixed typos in comments. 2019-03-10 11:04:33 +01:00
Felix Rilling
63f900287c Fixed typo "receieved" to "received", Adapted test. 2019-03-10 10:59:56 +01:00
Gregg Van Hove
239a615770 No longer run Node.js v4 on Travis
- Jasmine should still work in Node.js v4, but the jshint task isn't
  working correctly
2019-02-11 13:38:00 -08:00
Gregg Van Hove
92d5957a59 Attempt to skip jshint for node.js v4 2019-02-11 09:46:36 -08:00
Gregg Van Hove
4991f2a713 Merge branch 'print_global_error_type' of https://github.com/jbunton-atlassian/jasmine into jbunton-atlassian-print_global_error_type
- Merges #1632 from @jbunton-atlassian
2019-02-11 09:02:16 -08:00
Gregg Van Hove
0d6db64eb1 Merge branch 'onerror' of https://github.com/johnjbarton/jasmine into johnjbarton-onerror
- Merges #1644 from @jognjbarton
2019-01-30 17:38:27 -08:00
Gregg Van Hove
489fb79d6e fall back to older jshint for older node 2019-01-09 11:08:32 -08:00
Gregg Van Hove
eba8c775f3 update npm dependencies 2019-01-08 17:47:53 -08:00
johnjbarton
c36a005893 Support Error.stack in globalErrors.
See https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror#window.onerror
2019-01-03 16:14:23 -08:00
Gregg Van Hove
37dfe50d99 Stop treating objects with a nodeType as if they are DOM Nodes
- Fixes #1638
2018-12-17 17:10:53 -08:00
Gregg Van Hove
c67a5b830c Fix 3.0 breaking changes list to include note about Spy identity 2018-12-11 17:56:17 -08:00
James Bunton
d803bd12a6 When catching a global error in Node.js, print the type of error 2018-12-11 08:32:45 +11:00
Gregg Van Hove
a621d05fa7 Merge branch 'Havunen-fix-to-equal-ie'
- Merges #1621 from @Havunen
- Fixes #1618
2018-12-03 17:45:06 -08:00
Sampo Kivistö
473f5cd359 Re-use attr variable 2018-11-04 10:44:54 +02:00
Sampo Kivistö
a81e9626df Fixes issue where PhantomJS 2 and IE 10 - 11 crashed when reporting SVG element equality 2018-11-04 10:31:33 +02:00
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
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
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
Gregg Van Hove
516fe68759 Merge branch '3.0-features' 2018-02-06 11:22:41 -08:00
Gregg Van Hove
d4b76a4d3b version bump to 3.0 2018-02-06 09:33:49 -08:00
Gregg Van Hove
764d58a7f5 Merge branch 'master' into 3.0-features
- cleaning up 2.99 deprecations
2018-02-06 09:31:51 -08:00
Gregg Van Hove
274011ed03 Merge branch 'master' into 3.0-features 2018-02-02 16:33:38 -08:00
Gregg Van Hove
42e00b3bc5 Remove node modules from python wheel, and update languages
[finishes #87860474]
2018-01-31 14:23:32 -08:00
Gregg Van Hove
0eca06a33b Now pass a navigation helper to HtmlReporter instead of click handlers 2018-01-30 14:30:28 -08:00
Gregg Van Hove
84953ec210 stop spec on failure should not default to true 2018-01-30 11:48:25 -08:00
Gregg Van Hove
e15f273f06 Replace old "catch exceptions" logic with proper fail fast with error reporting
- Option is called stopOnSpecFailure

[#85966014]
- See #414
- See jasmine/jasmine-npm#16
2018-01-30 11:36:56 -08:00
Gregg Van Hove
e908b67b19 Move explicit fail spec out of mock clock context and re-add the afterAll for IEs 2018-01-29 17:05:54 -08:00
Gregg Van Hove
46cc48ccfa Detect an Error passed to done and add an expectation failure
- See #567
2018-01-29 16:46:30 -08:00
Gregg Van Hove
262a2fe674 Generate compiled jasmine.js for async reporters work 2018-01-29 14:02:02 -08:00
Gregg Van Hove
50cd6fdd68 Allow reporter callbacks to be asynchronous
[finishes #154673961]
- Fixes #842

Signed-off-by: Elenore Bastian <ebastian@pivotal.io>
2018-01-29 11:55:41 -08:00
Gregg Van Hove
341c6df6ea Fix HTML reporter display for excluded specs 2018-01-29 10:00:15 -08:00
Elenore Bastian
3df9cc26d4 Update css for new reporter status
Signed-off-by: Gregg Van Hove <gvanhove@pivotal.io>
2018-01-26 15:27:35 -08:00
Gregg Van Hove
6b156ca6d1 Unify status for xdescribe and xit
- Ensure *All's only execute if at least one child will run
- Specs will report a status of `excluded` instead of disabled

[finishes #153967580]
- #1418

Signed-off-by: Elenore Bastian <ebastian@pivotal.io>
2018-01-25 16:17:31 -08:00
Elenore Bastian
07996b567f Suite level errors are reported in failures list
[#150118881]

Signed-off-by: Gregg Van Hove <gvanhove@pivotal.io>
2018-01-23 15:39:11 -08:00
Gregg Van Hove
9a96396f65 Generate jasmine.js for suite reporting changes
Signed-off-by: Elenore Bastian <ebastian@pivotal.io>
2018-01-23 14:38:40 -08:00
Elenore Bastian
12a47f05bf Suite level errors all report the same way (on suiteDone)
- For `beforeAll`, `afterAll`, and declaration errors

[#150118881] #1409

Signed-off-by: Gregg Van Hove <gvanhove@pivotal.io>
2018-01-23 10:15:28 -08:00
Gregg Van Hove
414e03bded Setup createSpy in all specs where needed and finish renaming params
Signed-off-by: Elenore Bastian <ebastian@pivotal.io>
2018-01-22 14:21:52 -08:00
Gregg Van Hove
038ab87252 Merge branch 'custom-spy-strategy' into 3.0-features 2018-01-22 12:12:59 -08:00
Gregg Van Hove
f20f78f82b Don't clobber previous custom plans with later plans
[finishes #37288941]
2018-01-22 12:10:24 -08:00
Gregg Van Hove
e2a191b116 Refactor QueueRunner and remove references to functions that Jasmine is done with
[finishes #56030214]
2018-01-11 17:20:13 -08:00
Steve Gravrock
cf2f922e30 Merge branch 'master' into 3.0-features 2018-01-10 15:28:55 -08:00
Steve Gravrock
170a6dce76 Made naming somewhat less confusing 2018-01-10 09:00:09 -08:00
Steve Gravrock
4934e420b2 Allow adding custom spy strategies
[#37288941]
2018-01-10 08:59:19 -08:00
Steve Gravrock
1085914a76 Extracted a SpyFactory to slim Env down a bit 2018-01-09 13:32:28 -08:00
Steve Gravrock
6f119c4e5a Moved createSpy to env so it can be stateful 2018-01-09 10:16:02 -08:00
Steve Gravrock
298b5ba127 Moved createSpyObj to env so it can be stateful 2018-01-09 09:53:45 -08:00
Steve Gravrock
16e07a0e99 Add the ability to specify the strategy to use for a spy based on which parameters are passed
[Finishes #92260826]
2018-01-03 08:49:34 -08:00
Steve Gravrock
f38527ff15 Removed IE 8 compatibility cruft from HtmlReporterSpec 2017-12-19 11:29:21 -08:00
Steve Gravrock
d742ada71d Added links to re-run the suites containing a failing spec
[Finishes #25508053]
2017-12-19 11:29:18 -08:00
Steve Gravrock
ef9f82a17d Merge branch 'master' into 3.0-features 2017-12-18 09:48:17 -08:00
Gregg Van Hove
bdbaebc045 Update contributing for new naming of jasmineUnderTest 2017-12-11 17:24:38 -08:00
Steve Gravrock
2d33765cbf Dogfood the toHaveClass matcher
[#153567695]
2017-12-11 16:00:29 -08:00
Steve Gravrock
bb0992bf5f Added a toHaveClass matcher
[#153567695]
2017-12-11 15:59:59 -08:00
Steve Gravrock
ac5d8708b9 More informative pretty-printing of DOM elements
[Finishes ##153562618]
2017-12-11 08:25:13 -08:00
Steve Gravrock
eb93d38294 Allow jasmine-npm to handle its own load errors
[Fixes #153466462]
2017-12-08 09:17:10 -08:00
sjolicoeur
d90e20eb15 Added matchers: truthy, falsy, empty and notEmpty 2017-12-07 17:49:16 -08:00
Steve Gravrock
d16aa550cb Treat random= as a no-op rather than disabling randomization
[#109197518]
2017-12-01 08:45:58 -08:00
Steve Gravrock
2200dd084d Fixed build 2017-12-01 08:34:12 -08:00
Steve Gravrock
98ead94c51 Fixed spec failure on Chrome 2017-12-01 08:28:55 -08:00
Gregg Van Hove
21655a82c9 Use prototype for spy strategy for better memory management
- Also convert `identity` to a property from a method
2017-11-30 17:30:20 -08:00
Steve Gravrock
a63172f53f expect(null).toEqual(jasmine.any(Object)) no longer passes
[Finishes #153181443]
Fixes #1255.
2017-11-29 08:10:01 -08:00
Steve Gravrock
9619acf91f Extracted the predicate version of toThrowError into its own matcher
This simplifies the signature of each matcher to something that jsdoc
can actually handle.

[Finishes #20622765]
2017-11-28 14:30:06 -08:00
Gregg Van Hove
b7e4c1e779 Remove console.js altogether
[#80410262]
2017-11-21 17:27:21 -08:00
Gregg Van Hove
e5ada1d010 Add safari 10 and update readme to include edge 2017-11-20 17:24:52 -08:00
Steve Gravrock
d35b65cf79 Set version to 3.0.0-pre 2017-11-17 14:28:20 -08:00
Steve Gravrock
db615e4186 Determine overall status in core, not reporters
[#92261606]
[#78679648]
2017-11-17 14:24:12 -08:00
Steve Gravrock
5906a2c05c Filter Jasmine frames from stack traces
[Finishes #2644992]
2017-11-13 15:49:01 -08:00
Steve Gravrock
59ad217954 Fixed bad travis.yml merge
Re-removed IE 8, IE 9, and Node 0.12.x from the testing matrix
2017-11-10 10:47:08 -08:00
Steve Gravrock
b0ec95c472 Merge branch 'master' into 3.0-features 2017-11-10 10:26:14 -08:00
Steve Gravrock
a42f28c734 Removed checks for PhantomJS 1
v2 has been out for a long time, and v1 can no longer be easily installed.
2017-11-09 07:04:06 -08:00
Steve Gravrock
d58f3dac56 Test against multiple Node versions on Travis 2017-11-08 09:17:55 -08:00
Steve Gravrock
676689b063 Test against Node 4.x, not 0.10.x 2017-11-08 09:11:41 -08:00
Steve Gravrock
aaf226b9e3 Removed spec guards for versions of Safari we no longer support 2017-11-08 08:30:35 -08:00
Steve Gravrock
419470e9df Removed support for IE <10
[#150527985]
2017-11-08 08:30:22 -08:00
Steve Gravrock
1526d5e2a8 Treat afterAll errors at any level as failures
[Finishes #152492514]
2017-11-07 20:48:23 -08:00
Steve Gravrock
a3cb010971 Removed remaining traces of the obsolete console reporter
[#80410262]
2017-11-07 20:09:04 -08:00
Steve Gravrock
278ef9228b Removed obsolete console reporter from core
Anyone who was still using this should use the one in jasmine-npm
instead.

[Finishes #80410262]
2017-11-07 12:25:47 -08:00
Steve Gravrock
82eeed3c85 Improved reporting of load errors and afterAll errors
- Pass file and line number to reporters when present
- Show file and line number in the HTML reporter when present
- Visually separate adjacent errors in the HTML reporter

[#24901981]
2017-11-04 10:28:42 -07:00
Steve Gravrock
ae9b95269c Load error handling doesn't depend on browser features, so test it everywher
[#24901981]
2017-11-02 18:17:40 -07:00
Steve Gravrock
26a7bc6acf Report loading errors as loading errors, not afterAll errors
[#24901981]
2017-11-01 14:09:29 -07:00
Steve Gravrock
7b8edcb401 HTML reporter reports overall failure if there are any global errors
[#24901981]
2017-11-01 11:44:58 -07:00
Steve Gravrock
395b2b2d97 Test against Edge 2017-10-31 21:50:42 -07:00
Steve Gravrock
bd250f27c7 Fail if error events (e.g. syntax errors) occur during loading
[#24901981]
2017-10-31 21:16:00 -07:00
Steve Gravrock
12ed3bfacd Allow use of a predicate function to validate thrown exceptions
[Finishes #20622765]
2017-10-30 08:51:25 -07:00
Steve Gravrock
324ad0073e Refactored toThrowMatching to facilitate adding more strategies
* Extracted sub-matchers for the two major existing strategies
  (matching all errors, and matching by type and/or message)
* Reduced the use of mutable state
2017-10-30 08:51:25 -07:00
Steve Gravrock
9f7a6ef061 Check truthiness of toThrowError args, not arg count
This enables some useful simplifications at the cost of making it
impossible (for now) to expect a function to throw an error with a falsy
message.

[#20622765]
2017-10-30 08:51:25 -07:00
sgravrock
908583c49b Point CodeClimate at the right repo 2017-10-30 08:51:25 -07:00
Steve Gravrock
e31db20ec7 Default to running tests in random order
[Finishes #109197518]
2017-10-27 08:50:40 -07:00
147 changed files with 9939 additions and 3694 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

@@ -1,19 +1,16 @@
language: ruby
cache: bundler
sudo: false
rvm: 2.2.2
language: node_js
node_js:
- "11"
- "10"
- "8"
script: $TEST_COMMAND
env:
global:
- USE_SAUCE=true
- USE_SAUCE=false
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="firefox"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- TEST_COMMAND="npm test"
- secure: WSPWhlnC4mWSnSPquX+m1/BCu5ch5NygkaHuM2Nea7lD8oS3XLX8QncZZAsQ4lnNfqoDDuBOizG0AESiqNvE4y6x5qvLLTS6q+ce255ZEMZ71TBdZgDEEvGMEjOPPsVXiXyTQOP1lwOPlrbZvaPgWV7e11KIBab6DfFcQpnvDgo=
- secure: SW7CJhZnwaNT749Gdnhvqb5rbXlAOsygUAzh9qhtyvbqXKkmJdBIEsO01YF6pbju1X2twE9JvWCOxeZju43NgQChJlPsGbjY2j3k/TdQeTAJesQe2K7ytwghunI30gjEovtRH0T3w1EmcKPH8yj5eBIcB2OYoJHx8KEC7e68q1g=
@@ -23,53 +20,55 @@ addons:
matrix:
include:
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh v0.12.18"
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="firefox"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh v4"
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh v8"
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh v9"
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.12"
- SAUCE_BROWSER_VERSION=10
- env:
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.11"
- SAUCE_BROWSER_VERSION=9
- env:
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- 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
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="MicrosoftEdge"
- SAUCE_OS="Windows 10"
- SAUCE_BROWSER_VERSION="15"
- env:
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 8.1"
- SAUCE_BROWSER_VERSION=11
- env:
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 8"
- SAUCE_BROWSER_VERSION=10
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 7"
- SAUCE_BROWSER_VERSION=9
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 7"
- SAUCE_BROWSER_VERSION=8
- env:
- USE_SAUCE=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="chrome"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="phantomjs"
- USE_SAUCE=false
- env:
- USE_SAUCE=false
- JASMINE_BROWSER="phantomjs"
- TEST_COMMAND="bash travis-docs-script.sh"

View File

@@ -1,9 +1,9 @@
source 'https://rubygems.org'
gem "jasmine", :git => 'https://github.com/jasmine/jasmine-gem.git', :tag => 'v2.99.0'
gem "jasmine", :git => 'https://github.com/jasmine/jasmine-gem.git'
# gem "jasmine", path: "../jasmine-gem"
gemspec
gem "jasmine_selenium_runner", :github => 'jasmine/jasmine_selenium_runner', :tag => 'v2.4.0'
gem "jasmine_selenium_runner", :github => 'jasmine/jasmine_selenium_runner'
gem "anchorman"

View File

@@ -6,15 +6,16 @@ module.exports = function(grunt) {
pkg: pkg,
jshint: require('./grunt/config/jshint.js'),
concat: require('./grunt/config/concat.js'),
compass: require('./grunt/config/compass.js'),
compress: require('./grunt/config/compress.js')
sass: require('./grunt/config/sass.js'),
compress: require('./grunt/config/compress.js'),
cssUrlEmbed: require('./grunt/config/cssUrlEmbed.js')
});
require('load-grunt-tasks')(grunt);
grunt.loadTasks('grunt/tasks');
grunt.registerTask('default', ['jshint:all']);
grunt.registerTask('default', ['jshint:all', 'sass:dist', "cssUrlEmbed"]);
var version = require('./grunt/tasks/version.js');
@@ -25,11 +26,11 @@ module.exports = function(grunt) {
grunt.registerTask('buildDistribution',
'Builds and lints jasmine.js, jasmine-html.js, jasmine.css',
[
'compass',
'sass:dist',
"cssUrlEmbed",
'jshint:beforeConcat',
'concat',
'jshint:afterConcat',
'build:copyVersionToGem'
'jshint:afterConcat'
]
);

View File

@@ -1,4 +1,5 @@
recursive-include . *.py
prune node_modules
include lib/jasmine-core/*.js
include lib/jasmine-core/*.css
include images/*.png

View File

@@ -1,17 +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**
# 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
@@ -52,7 +52,7 @@ Add the following to your HTML file:
## Supported environments
Jasmine tests itself across many browsers (Safari, Chrome, Firefox, PhantomJS, and new Internet Explorer) as well as node. To see the exact version tests are run against look at our [.travis.yml](https://github.com/jasmine/jasmine/blob/master/.travis.yml)
Jasmine tests itself across many browsers (Safari, Chrome, Firefox, PhantomJS, Microsoft Edge, and new Internet Explorer) as well as nodejs. To see the exact version tests are run against look at our [.travis.yml](https://github.com/jasmine/jasmine/blob/master/.travis.yml)
## Support
@@ -75,4 +75,8 @@ Jasmine tests itself across many browsers (Safari, Chrome, Firefox, PhantomJS, a
* [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)

208
ci.js Normal file
View File

@@ -0,0 +1,208 @@
const path = require("path"),
fs = require('fs'),
port = 5555,
colors = {
"passed" : "\x1B[32m",
"failed": "\x1B[31m",
"pending": "\x1B[33m",
"excluded": "\x1B[0m",
"none": "\x1B[0m"
},
symbols = {
"passed" : ".",
"failed": "F",
"pending": "*",
"excluded": "",
"none": ""
},
host = `http://localhost:${port}`,
useSauce = process.env.USE_SAUCE === 'true';
let driver, server;
function pageGenerator() {
const ejs = require("ejs"),
fg = require("fast-glob"),
templatePath = path.resolve(__dirname, 'spec/support/index.html.ejs'),
template = ejs.compile(fs.readFileSync(templatePath).toString()),
patterns = [
"lib/jasmine-core/jasmine.js",
"lib/jasmine-core/json2.js",
"lib/jasmine-core/jasmine-html.js",
"lib/jasmine-core/boot.js",
"src/core/requireCore.js",
"src/core/base.js",
"src/core/util.js",
"src/core/Spec.js",
"src/core/Env.js",
"src/**/*.js",
"spec/helpers/*.js",
"spec/**/*[Ss]pec.js"
],
ignore = [
"spec/helpers/nodeDefineJasmineUnderTest.js",
"spec/npmPackage/**/*",
"lib/jasmine-core/node_boot.js"
];
return function toHtml() {
const files = fg.sync(patterns, {ignore});
return template({files});
}
}
function buildWebdriver() {
const webdriver = require("selenium-webdriver"),
Capability = webdriver.Capability;
if (useSauce) {
const username = process.env['SAUCE_USERNAME'],
accessKey = process.env['SAUCE_ACCESS_KEY'];
return new webdriver.Builder()
.withCapabilities({
name: `jasmine-core ${new Date().toISOString()}`,
[Capability.PLATFORM]: process.env['SAUCE_OS'],
[Capability.BROWSER_NAME]: process.env['JASMINE_BROWSER'],
[Capability.VERSION]: process.env['SAUCE_BROWSER_VERSION'],
build: `Core ${process.env['TRAVIS_BUILD_NUMBER'] || 'Ran locally'}`,
tags: ['Jasmine-Core'],
"tunnel-identifier": process.env['TRAVIS_JOB_NUMBER'] ? process.env['TRAVIS_JOB_NUMBER'].toString() : null
})
.usingServer(`http://${username}:${accessKey}@localhost:4445/wd/hub`)
.build();
} else {
return new webdriver.Builder()
.forBrowser(process.env["JASMINE_BROWSER"] || "firefox")
.build();
}
}
async function resultsWithoutCircularReferences(driver, resultType, index, batchSize) {
return await driver.executeScript(
`var results = jsApiReporter.${resultType}Results(${index}, ${batchSize});\n` +
'for (var i = 0; i < results.length; i++) {\n' +
'var expectations = results[i].failedExpectations;\n' +
'if (results[i].passedExpectations) {\n' +
'expectations = expectations.concat(results[i].passedExpectations);\n' +
'}\n' +
'for (var j = 0; j < expectations.length; j++) {\n' +
'var expectation = expectations[j];\n' +
"try { JSON.stringify(expectation.expected); } catch (e) { expectation.expected = '<circular expected>'; }\n" +
"try { JSON.stringify(expectation.actual); } catch (e) { expectation.actual = '<circular actual>'; }\n" +
'}\n' +
'}\n' +
'return results;'
);
}
function flatten(arr) {
return Array.prototype.concat.apply([], arr);
}
async function getResults(driver) {
const batchSize = 50,
specResults = [],
failedSuiteResults = [];
let index = 0,
slice = [];
do {
slice = await resultsWithoutCircularReferences(driver, 'spec', index, batchSize);
specResults.push(slice);
index += batchSize;
} while (slice.length === batchSize);
index = 0;
do {
slice = await resultsWithoutCircularReferences(driver, 'suite', index, batchSize);
failedSuiteResults.push(slice.filter(function(suite) { return suite.status === 'failed' }));
index += batchSize;
} while (slice.length === batchSize);
return {specResults: flatten(specResults), failedSuiteResults: flatten(failedSuiteResults)};
}
(async function () {
await new Promise(resolve => {
console.log("Creating an express app for browers to run the tests...")
const express = require("express"),
app = express(),
html = pageGenerator();
app.use(express.static(__dirname));
app.get("/", (req, res) => res.send(html()));
server = app.listen(port, resolve);
});
console.log("Running the tests in browser...")
driver = buildWebdriver();
await driver.get(`${host}/?throwFailures=false&failFast=false&random=true`)
await new Promise(resolve => {
const intervalId = setInterval(async () => {
const isFinished = await driver.executeScript("return jsApiReporter && jsApiReporter.finished")
if (isFinished) {
clearInterval(intervalId)
resolve();
}
}, 500)
});
const {specResults, failedSuiteResults} = await getResults(driver);
console.log(specResults.map(spec => `${colors[spec.status]}${symbols[spec.status]}`).join("") + colors["none"]);
const result = specResults.reduce((result, spec) => {
result[spec.status] = [...result[spec.status], spec];
return result;
}, {pending: [], failed: [], passed: [], excluded: []});
if (result.pending.length) {
console.log(`${colors["pending"]}Pending:`);
result.pending.forEach((spec, index) => {
console.log(`${colors["none"]}${index}) ${spec.fullName}`)
console.group();
console.log(`${colors["pending"]}${spec.pendingReason || "no reason given"}`);
console.groupEnd();
console.log();
});
}
if (result.failed.length) {
console.log(`${colors["failed"]}Failed:`);
result["failed"].forEach((spec, index) => {
console.log(`${colors["none"]}${index}) ${spec.fullName}`)
console.group();
spec.failedExpectations.forEach((expect) => {
console.log(`${colors["none"]}Message:`);
console.group();
console.log(`${colors["failed"]}${expect.message}`);
console.groupEnd();
console.log(`${colors["none"]}Stack:`);
console.group();
console.log(`${colors["failed"]}${expect.stack}`);
console.groupEnd();
console.groupEnd();
})
console.groupEnd();
console.log();
});
}
const details = await driver.executeScript(`
return {
overallStatus: jsApiReporter.runDetails.overallStatus,
executionTime: jsApiReporter.executionTime(),
random: jsApiReporter.runDetails.order.random,
seed: jsApiReporter.runDetails.order.seed
}`);
console.log(`${colors["none"]}${specResults.length} spec(s), ${result.failed.length} failure(s), ${result.pending.length} pending spec(s)`);
console.log(`Finished in ${details.executionTime / 1000} second(s)`);
console.log(`Randomized with seed ${details.seed} ( ${host}/?random=${details.random}&seed=${details.seed} )`);
process.exitCode = details.overallStatus === 'passed' ? 0 : 1;
if (useSauce) {
driver.executeScript(`sauce:job-result=${process.exitCode === 0}`);
}
})().finally(() => {
return Promise.all([driver.close(), new Promise(resolve => server.close(resolve))]);
});

View File

@@ -1,11 +0,0 @@
module.exports = {
jasmine: {
options: {
cssDir: 'lib/jasmine-core/',
sassDir: 'src/html',
outputStyle: 'compact',
noLineComments: true,
bundleExec: true
}
}
};

View File

@@ -2,7 +2,6 @@ var standaloneLibDir = "lib/jasmine-" + jasmineVersion;
function root(path) { return "./" + path; }
function libJasmineCore(path) { return root("lib/jasmine-core/" + path); }
function libConsole() { return "lib/console/" }
function dist(path) { return root("dist/" + path); }
module.exports = {
@@ -29,14 +28,6 @@ module.exports = {
expand: true,
cwd: libJasmineCore("")
},
{
src: [
"console.js"
],
dest: standaloneLibDir,
expand: true,
cwd: libConsole()
},
{
src: [ "boot.js" ],
dest: standaloneLibDir,

View File

@@ -15,7 +15,8 @@ module.exports = {
'src/html/HtmlReporter.js',
'src/html/HtmlSpecFilter.js',
'src/html/ResultsNode.js',
'src/html/QueryString.js'
'src/html/QueryString.js',
'src/html/**/*.js'
],
dest: 'lib/jasmine-core/jasmine-html.js'
},
@@ -44,13 +45,6 @@ module.exports = {
src: ['lib/jasmine-core/boot/node_boot.js'],
dest: 'lib/jasmine-core/node_boot.js'
},
console: {
src: [
'src/console/requireConsole.js',
'src/console/ConsoleReporter.js'
],
dest: 'lib/console/console.js'
},
options: {
banner: license(),
process: {

View File

@@ -0,0 +1,7 @@
module.exports = {
encodeWithBaseDir: {
files: {
"lib/jasmine-core/jasmine.css": ["lib/jasmine-core/jasmine.css"]
}
}
};

14
grunt/config/sass.js Normal file
View File

@@ -0,0 +1,14 @@
const sass = require('node-sass');
module.exports = {
options: {
implementation: sass,
outputStyle: 'compact',
sourceComments: false
},
dist: {
files: {
"lib/jasmine-core/jasmine.css": "src/html/jasmine.scss"
}
}
};

View File

@@ -1,190 +0,0 @@
/*
Copyright (c) 2008-2018 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
function getJasmineRequireObj() {
if (typeof module !== 'undefined' && module.exports) {
return exports;
} else {
window.jasmineRequire = window.jasmineRequire || {};
return window.jasmineRequire;
}
}
getJasmineRequireObj().console = function(jRequire, j$) {
j$.ConsoleReporter = jRequire.ConsoleReporter();
};
getJasmineRequireObj().ConsoleReporter = function() {
var noopTimer = {
start: function(){},
elapsed: function(){ return 0; }
};
function ConsoleReporter(options) {
var print = options.print,
showColors = options.showColors || false,
onComplete = options.onComplete || function() {},
timer = options.timer || noopTimer,
specCount,
failureCount,
failedSpecs = [],
pendingCount,
ansi = {
green: '\x1B[32m',
red: '\x1B[31m',
yellow: '\x1B[33m',
none: '\x1B[0m'
},
failedSuites = [];
print('ConsoleReporter is deprecated and will be removed in a future version.');
this.jasmineStarted = function() {
specCount = 0;
failureCount = 0;
pendingCount = 0;
print('Started');
printNewline();
timer.start();
};
this.jasmineDone = function() {
printNewline();
for (var i = 0; i < failedSpecs.length; i++) {
specFailureDetails(failedSpecs[i]);
}
if(specCount > 0) {
printNewline();
var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' +
failureCount + ' ' + plural('failure', failureCount);
if (pendingCount) {
specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount);
}
print(specCounts);
} else {
print('No specs found');
}
printNewline();
var seconds = timer.elapsed() / 1000;
print('Finished in ' + seconds + ' ' + plural('second', seconds));
printNewline();
for(i = 0; i < failedSuites.length; i++) {
suiteFailureDetails(failedSuites[i]);
}
onComplete(failureCount === 0);
};
this.specDone = function(result) {
specCount++;
if (result.status == 'pending') {
pendingCount++;
print(colored('yellow', '*'));
return;
}
if (result.status == 'passed') {
print(colored('green', '.'));
return;
}
if (result.status == 'failed') {
failureCount++;
failedSpecs.push(result);
print(colored('red', 'F'));
}
};
this.suiteDone = function(result) {
if (result.failedExpectations && result.failedExpectations.length > 0) {
failureCount++;
failedSuites.push(result);
}
};
return this;
function printNewline() {
print('\n');
}
function colored(color, str) {
return showColors ? (ansi[color] + str + ansi.none) : str;
}
function plural(str, count) {
return count == 1 ? str : str + 's';
}
function repeat(thing, times) {
var arr = [];
for (var i = 0; i < times; i++) {
arr.push(thing);
}
return arr;
}
function indent(str, spaces) {
var lines = (str || '').split('\n');
var newArr = [];
for (var i = 0; i < lines.length; i++) {
newArr.push(repeat(' ', spaces).join('') + lines[i]);
}
return newArr.join('\n');
}
function specFailureDetails(result) {
printNewline();
print(result.fullName);
for (var i = 0; i < result.failedExpectations.length; i++) {
var failedExpectation = result.failedExpectations[i];
printNewline();
print(indent(failedExpectation.message, 2));
print(indent(failedExpectation.stack, 2));
}
printNewline();
}
function suiteFailureDetails(result) {
for (var i = 0; i < result.failedExpectations.length; i++) {
printNewline();
print(colored('red', 'An error was thrown in an afterAll'));
printNewline();
print(colored('red', 'AfterAll ' + result.failedExpectations[i].message));
}
printNewline();
}
}
return ConsoleReporter;
};

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2018 Pivotal Labs
Copyright (c) 2008-2019 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -73,18 +73,21 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
var filterSpecs = !!queryString.getParam("spec");
var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
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");
env.randomizeTests(random);
if (random !== undefined && random !== "") {
config.random = random;
}
var seed = queryString.getParam("seed");
if (seed) {
env.seed(seed);
config.seed = seed;
}
/**
@@ -93,9 +96,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var htmlReporter = new jasmine.HtmlReporter({
env: env,
onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); },
onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); },
onRandomClick: function() { queryString.navigateWithNewParam("random", !env.randomTests()); },
navigateWithNewParam: function(key, value) { return queryString.navigateWithNewParam(key, value); },
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
@@ -117,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,18 +51,21 @@
var filterSpecs = !!queryString.getParam("spec");
var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
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");
env.randomizeTests(random);
if (random !== undefined && random !== "") {
config.random = random;
}
var seed = queryString.getParam("seed");
if (seed) {
env.seed(seed);
config.seed = seed;
}
/**
@@ -71,9 +74,7 @@
*/
var htmlReporter = new jasmine.HtmlReporter({
env: env,
onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); },
onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); },
onRandomClick: function() { queryString.navigateWithNewParam("random", !env.randomTests()); },
navigateWithNewParam: function(key, value) { return queryString.navigateWithNewParam(key, value); },
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
@@ -95,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,10 +1,7 @@
module.exports = function(jasmineRequire) {
var jasmine = jasmineRequire.core(jasmineRequire);
var consoleFns = require('../console/console.js');
consoleFns.console(consoleFns, jasmine);
var env = jasmine.getEnv();
var env = jasmine.getEnv({suppressLoadErrors: true});
var jasmineInterface = jasmineRequire.interface(jasmine, env);

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2018 Pivotal Labs
Copyright (c) 2008-2019 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -28,12 +28,6 @@ jasmineRequire.html = function(j$) {
};
jasmineRequire.HtmlReporter = function(j$) {
var noopTimer = {
start: function() {},
elapsed: function() { return 0; }
};
function ResultsStateBuilder() {
this.topResults = new j$.ResultsNode({}, '', null);
this.currentParent = this.topResults;
@@ -48,9 +42,14 @@ jasmineRequire.HtmlReporter = function(j$) {
};
ResultsStateBuilder.prototype.suiteDone = function(result) {
this.currentParent.updateResult(result);
if (this.currentParent !== this.topResults) {
this.currentParent = this.currentParent.parent;
}
if (result.status === 'failed') {
this.failureCount++;
}
};
ResultsStateBuilder.prototype.specStarted = function(result) {
@@ -59,7 +58,7 @@ jasmineRequire.HtmlReporter = function(j$) {
ResultsStateBuilder.prototype.specDone = function(result) {
this.currentParent.addChild(result, 'spec');
if (result.status !== 'disabled') {
if (result.status !== 'excluded') {
this.specsExecuted++;
}
@@ -75,20 +74,16 @@ 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,
onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
onThrowExpectationsClick = options.onThrowExpectationsClick || function() {},
onRandomClick = options.onRandomClick || function() {},
navigateWithNewParam = options.navigateWithNewParam || function() {},
addToExistingQueryString = options.addToExistingQueryString || defaultQueryString,
filterSpecs = options.filterSpecs,
timer = options.timer || noopTimer,
results = [],
timer = options.timer || j$.noopTimer,
htmlReporterMain,
symbols,
failedSuites = [],
deprecationWarnings = [];
this.initialize = function() {
@@ -122,11 +117,11 @@ jasmineRequire.HtmlReporter = function(j$) {
};
this.suiteDone = function(result) {
if (result.status == 'failed') {
failedSuites.push(result);
}
stateBuilder.suiteDone(result);
if (result.status === 'failed') {
failures.push(failureDom(result));
}
addDeprecationWarnings(result);
};
@@ -147,93 +142,38 @@ 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
}
));
if (result.status == 'failed') {
var failure =
createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
createDom('div', {className: 'jasmine-description'},
createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName)
),
createDom('div', {className: 'jasmine-messages'})
);
var messages = failure.childNodes[1];
for (var i = 0; i < result.failedExpectations.length; i++) {
var expectation = result.failedExpectations[i];
messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message));
messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
}
failures.push(failure);
if (result.status === 'failed') {
failures.push(failureDom(result));
}
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(
createDom('div', { className: 'jasmine-run-options' },
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
createDom('div', { className: 'jasmine-payload' },
createDom('div', { className: 'jasmine-exceptions' },
createDom('input', {
className: 'jasmine-raise',
id: 'jasmine-raise-exceptions',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')),
createDom('div', { className: 'jasmine-throw-failures' },
createDom('input', {
className: 'jasmine-throw',
id: 'jasmine-throw-failures',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')),
createDom('div', { className: 'jasmine-random-order' },
createDom('input', {
className: 'jasmine-random',
id: 'jasmine-random-order',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
)
));
var raiseCheckbox = find('#jasmine-raise-exceptions');
raiseCheckbox.checked = !env.catchingExceptions();
raiseCheckbox.onclick = onRaiseExceptionsClick;
var throwCheckbox = find('#jasmine-throw-failures');
throwCheckbox.checked = env.throwingExpectationFailures();
throwCheckbox.onclick = onThrowExpectationsClick;
var randomCheckbox = find('#jasmine-random-order');
randomCheckbox.checked = env.randomTests();
randomCheckbox.onclick = onRandomClick;
var optionsMenu = find('.jasmine-run-options'),
optionsTrigger = optionsMenu.querySelector('.jasmine-trigger'),
optionsPayload = optionsMenu.querySelector('.jasmine-payload'),
isOpen = /\bjasmine-open\b/;
optionsTrigger.onclick = function() {
if (isOpen.test(optionsPayload.className)) {
optionsPayload.className = optionsPayload.className.replace(isOpen, '');
} else {
optionsPayload.className += ' jasmine-open';
}
};
banner.appendChild(optionsMenu(config()));
if (stateBuilder.specsExecuted < totalSpecsDefined) {
var skippedMessage = 'Ran ' + stateBuilder.specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
@@ -245,15 +185,22 @@ jasmineRequire.HtmlReporter = function(j$) {
);
}
var statusBarMessage = '';
var statusBarClassName = 'jasmine-bar ';
var statusBarClassName = 'jasmine-overall-result jasmine-bar ';
var globalFailures = (doneResult && doneResult.failedExpectations) || [];
var failed = stateBuilder.failureCount + globalFailures.length > 0;
if (totalSpecsDefined > 0) {
if (totalSpecsDefined > 0 || failed) {
statusBarMessage += pluralize('spec', stateBuilder.specsExecuted) + ', ' + pluralize('failure', stateBuilder.failureCount);
if (stateBuilder.pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', stateBuilder.pendingSpecCount); }
statusBarClassName += (stateBuilder.failureCount > 0) ? 'jasmine-failed' : 'jasmine-passed';
}
if (doneResult.overallStatus === 'passed') {
statusBarClassName += ' jasmine-passed ';
} else if (doneResult.overallStatus === 'incomplete') {
statusBarClassName += ' jasmine-incomplete ';
statusBarMessage = 'Incomplete: ' + doneResult.incompleteReason + ', ' + statusBarMessage;
} else {
statusBarClassName += 'jasmine-skipped';
statusBarMessage += 'No specs found';
statusBarClassName += ' jasmine-failed ';
}
var seedBar;
@@ -267,19 +214,24 @@ jasmineRequire.HtmlReporter = function(j$) {
alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage, seedBar));
var errorBarClassName = 'jasmine-bar jasmine-errored';
var errorBarMessagePrefix = 'AfterAll ';
var afterAllMessagePrefix = 'AfterAll ';
for(var i = 0; i < failedSuites.length; i++) {
var failedSuite = failedSuites[i];
for(var j = 0; j < failedSuite.failedExpectations.length; j++) {
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failedSuite.failedExpectations[j].message));
}
for(i = 0; i < globalFailures.length; i++) {
alert.appendChild(createDom('span', {className: errorBarClassName}, globalFailureMessage(globalFailures[i])));
}
var globalFailures = (doneResult && doneResult.failedExpectations) || [];
for(i = 0; i < globalFailures.length; i++) {
var failure = globalFailures[i];
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failure.message));
function globalFailureMessage(failure) {
if (failure.globalErrorType === 'load') {
var prefix = 'Error during loading: ' + failure.message;
if (failure.filename) {
return prefix + ' in ' + failure.filename + ' line ' + failure.lineno;
} else {
return prefix;
}
} else {
return afterAllMessagePrefix + failure.message;
}
}
addDeprecationWarnings(doneResult);
@@ -295,47 +247,6 @@ jasmineRequire.HtmlReporter = function(j$) {
summaryList(stateBuilder.topResults, summary);
function summaryList(resultsTree, domParent) {
var specListNode;
for (var i = 0; i < resultsTree.children.length; i++) {
var resultNode = resultsTree.children[i];
if (filterSpecs && !hasActiveSpec(resultNode)) {
continue;
}
if (resultNode.type == 'suite') {
var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id},
createDom('li', {className: 'jasmine-suite-detail'},
createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
)
);
summaryList(resultNode, suiteListNode);
domParent.appendChild(suiteListNode);
}
if (resultNode.type == 'spec') {
if (domParent.getAttribute('class') != 'jasmine-specs') {
specListNode = createDom('ul', {className: 'jasmine-specs'});
domParent.appendChild(specListNode);
}
var specDescription = resultNode.result.description;
if(noExpectations(resultNode.result)) {
specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
}
if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
}
specListNode.appendChild(
createDom('li', {
className: 'jasmine-' + resultNode.result.status,
id: 'spec-' + resultNode.result.id
},
createDom('a', {href: specHref(resultNode.result)}, specDescription)
)
);
}
}
}
if (failures.length) {
alert.appendChild(
createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'},
@@ -364,6 +275,166 @@ jasmineRequire.HtmlReporter = function(j$) {
return this;
function failureDom(result) {
var failure =
createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
failureDescription(result, stateBuilder.currentParent),
createDom('div', {className: 'jasmine-messages'})
);
var messages = failure.childNodes[1];
for (var i = 0; i < result.failedExpectations.length; i++) {
var expectation = result.failedExpectations[i];
messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message));
messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
}
return failure;
}
function summaryList(resultsTree, domParent) {
var specListNode;
for (var i = 0; i < resultsTree.children.length; i++) {
var resultNode = resultsTree.children[i];
if (filterSpecs && !hasActiveSpec(resultNode)) {
continue;
}
if (resultNode.type === 'suite') {
var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id},
createDom('li', {className: 'jasmine-suite-detail jasmine-' + resultNode.result.status},
createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
)
);
summaryList(resultNode, suiteListNode);
domParent.appendChild(suiteListNode);
}
if (resultNode.type === 'spec') {
if (domParent.getAttribute('class') !== 'jasmine-specs') {
specListNode = createDom('ul', {className: 'jasmine-specs'});
domParent.appendChild(specListNode);
}
var specDescription = resultNode.result.description;
if(noExpectations(resultNode.result)) {
specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
}
if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
}
specListNode.appendChild(
createDom('li', {
className: 'jasmine-' + resultNode.result.status,
id: 'spec-' + resultNode.result.id
},
createDom('a', {href: specHref(resultNode.result)}, specDescription)
)
);
}
}
}
function optionsMenu(config) {
var optionsMenuDom = createDom('div', { className: 'jasmine-run-options' },
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
createDom('div', { className: 'jasmine-payload' },
createDom('div', { className: 'jasmine-stop-on-failure' },
createDom('input', {
className: 'jasmine-fail-fast',
id: 'jasmine-fail-fast',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-fail-fast' }, 'stop execution on spec failure')),
createDom('div', { className: 'jasmine-throw-failures' },
createDom('input', {
className: 'jasmine-throw',
id: 'jasmine-throw-failures',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')),
createDom('div', { className: 'jasmine-random-order' },
createDom('input', {
className: 'jasmine-random',
id: 'jasmine-random-order',
type: 'checkbox'
}),
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 = config.failFast;
failFastCheckbox.onclick = function() {
navigateWithNewParam('failFast', !config.failFast);
};
var throwCheckbox = optionsMenuDom.querySelector('#jasmine-throw-failures');
throwCheckbox.checked = config.oneFailurePerSpec;
throwCheckbox.onclick = function() {
navigateWithNewParam('throwFailures', !config.oneFailurePerSpec);
};
var randomCheckbox = optionsMenuDom.querySelector('#jasmine-random-order');
randomCheckbox.checked = config.random;
randomCheckbox.onclick = function() {
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'),
optionsPayload = optionsMenuDom.querySelector('.jasmine-payload'),
isOpen = /\bjasmine-open\b/;
optionsTrigger.onclick = function() {
if (isOpen.test(optionsPayload.className)) {
optionsPayload.className = optionsPayload.className.replace(isOpen, '');
} else {
optionsPayload.className += ' jasmine-open';
}
};
return optionsMenuDom;
}
function failureDescription(result, suite) {
var wrapper = createDom('div', {className: 'jasmine-description'},
createDom('a', {title: result.description, href: specHref(result)}, result.description)
);
var suiteLink;
while (suite && suite.parent) {
wrapper.insertBefore(createTextNode(' > '), wrapper.firstChild);
suiteLink = createDom('a', {href: suiteHref(suite)}, suite.result.description);
wrapper.insertBefore(suiteLink, wrapper.firstChild);
suite = suite.parent;
}
return wrapper;
}
function suiteHref(suite) {
var els = [];
while (suite && suite.parent) {
els.unshift(suite.result.description);
suite = suite.parent;
}
return addToExistingQueryString('spec', els.join(' '));
}
function addDeprecationWarnings(result) {
if (result && result.deprecationWarnings) {
for(var i = 0; i < result.deprecationWarnings.length; i++) {
@@ -442,7 +513,7 @@ jasmineRequire.HtmlReporter = function(j$) {
}
function hasActiveSpec(resultNode) {
if (resultNode.type == 'spec' && resultNode.result.status != 'disabled') {
if (resultNode.type == 'spec' && resultNode.result.status != 'excluded') {
return true;
}
@@ -487,6 +558,10 @@ jasmineRequire.ResultsNode = function() {
this.last = function() {
return this.children[this.children.length - 1];
};
this.updateResult = function(result) {
this.result = result;
};
}
return ResultsNode;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2018 Pivotal Labs
Copyright (c) 2008-2019 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -23,10 +23,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
module.exports = function(jasmineRequire) {
var jasmine = jasmineRequire.core(jasmineRequire);
var consoleFns = require('../console/console.js');
consoleFns.console(consoleFns, jasmine);
var env = jasmine.getEnv();
var env = jasmine.getEnv({suppressLoadErrors: true});
var jasmineInterface = jasmineRequire.interface(jasmine, env);

View File

@@ -4,6 +4,6 @@
#
module Jasmine
module Core
VERSION = "2.99.2"
VERSION = "3.4.0"
end
end

View File

@@ -1,7 +1,7 @@
{
"name": "jasmine-core",
"license": "MIT",
"version": "2.99.2",
"version": "3.4.0",
"repository": {
"type": "git",
"url": "https://github.com/jasmine/jasmine.git"
@@ -16,19 +16,25 @@
"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",
"grunt": "^1.0.1",
"grunt-cli": "^1.2.0",
"grunt-contrib-compass": "^1.1.1",
"ejs": "^2.5.5",
"express": "^4.16.4",
"fast-glob": "^2.2.6",
"grunt": "^1.0.4",
"grunt-cli": "^1.3.2",
"grunt-contrib-compress": "^1.3.0",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-jshint": "^1.0.0",
"jasmine": "^2.5.0",
"load-grunt-tasks": "^0.4.0",
"shelljs": "^0.7.0",
"temp": "~0.8.1"
"grunt-contrib-jshint": "^2.0.0",
"grunt-css-url-embed": "^1.11.1",
"grunt-sass": "^3.0.2",
"jasmine": "^3.3.1",
"jsdom": "^13.1.0",
"load-grunt-tasks": "^4.0.0",
"node-sass": "^4.11.0",
"selenium-webdriver": "^3.6.0",
"shelljs": "^0.8.3",
"temp": "^0.9.0"
}
}

91
release_notes/3.0.md Normal file
View File

@@ -0,0 +1,91 @@
# Jasmine-Core 3.0 Release Notes
## Summary
Jasmine 3.0 is a major release of Jasmine, and as such includes some breaking changes in addition to various new features.
There is also a 2.99 release of Jasmine that will present deprecation warnings for suites that will encounter different behavior in 3.0.
## Breaking Changes
* 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-npm/issues/16)
* Detect an Error passed to `done` and add an expectation failure
- Fixes [#567](https://github.com/jasmine/jasmine/issues/567)
* Unify status for xdescribe and xit
- Ensure *All's only execute if at least one child will run
- Specs will report a status of `excluded` instead of disabled
- Fixes [#1418](https://github.com/jasmine/jasmine/issues/1418)
* Suite level errors all report the same way (on suiteDone)
* Refactor QueueRunner and remove references to functions that Jasmine is done with
* expect(null).toEqual(jasmine.any(Object)) no longer passes
- Fixes [#1255](https://github.com/jasmine/jasmine/issues/1255)
* Default to running tests in random order
* The `identity` of a Jasmnine Spy is now a property and no longer a method
* 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
* Allow reporter callbacks to be asynchronous
- Fixes [#842](https://github.com/jasmine/jasmine/issues/842)
* Allow adding custom spy strategies
* Add the ability to specify the strategy to use for a spy based on which parameters are passed
* Added links to re-run the suites containing a failing spec
* Added a toHaveClass matcher
* More informative pretty-printing of DOM elements
* Allow jasmine-npm to handle its own load errors
* Treat random= as a no-op rather than disabling randomization
* Use prototype for spy strategy for better memory management
* Remove console.js altogether
* Add safari 10 and update readme to include edge
* Determine overall status in core, not reporters
* Filter Jasmine frames from stack traces
* Treat afterAll errors at any level as failures
* Improved reporting of load errors and afterAll errors
- Pass file and line number to reporters when present
- Show file and line number in the HTML reporter when present
- Visually separate adjacent errors in the HTML reporter
* Report loading errors as loading errors, not afterAll errors
* HTML reporter reports overall failure if there are any global errors
* Fail if error events (e.g. syntax errors) occur during loading
* Allow use of a predicate function to validate thrown exceptions
* Check truthiness of toThrowError args, not arg count
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

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)_

49
release_notes/3.4.0.md Normal file
View File

@@ -0,0 +1,49 @@
# Jasmine Core 3.4 Release Notes
## Summary
This is a maintenance release of Jasmine with a number of new features and fixes
## Changes
* Handle WebSocket events in IE when detecting Errors
- Fixes [#1623](https://github.com/jasmine/jasmine/issues/1623)
* bump dependencies for security fixes
- Merges [#1672](https://github.com/jasmine/jasmine/issues/1672) from @wood1986
* Make node execution default and override for browsers
- Merges [#1658](https://github.com/jasmine/jasmine/issues/1658) from @wood1986
- Fixes [#883](https://github.com/jasmine/jasmine/issues/883)
* feat(result.duration): report test duration in ms
- Merges [#1660](https://github.com/jasmine/jasmine/issues/1660) from @johnjbarton
- Fixes [#1646](https://github.com/jasmine/jasmine/issues/1646)
* refactor(Timer): share htmlReporter noopTimer via Timer.js
- Merges [#1669](https://github.com/jasmine/jasmine/issues/1669) from @johnjbarton
* Fix various typos
- Merges [#1666](https://github.com/jasmine/jasmine/issues/1666) from @FelixRilling
- Merges [#1667](https://github.com/jasmine/jasmine/issues/1667) from @FelixRilling
- Merges [#1665](https://github.com/jasmine/jasmine/issues/1665) from @FelixRilling
- Merges [#1664](https://github.com/jasmine/jasmine/issues/1664) from @FelixRilling
- Fixes [#1663](https://github.com/jasmine/jasmine/issues/1663)
* When catching a global error in Node.js, print the type of error
- Merges [#1632](https://github.com/jasmine/jasmine/issues/1632) from @jbunton-atlassian
* Support Error.stack in globalErrors.
- Merges [#1644](https://github.com/jasmine/jasmine/issues/1644) from @johnjbarton
* Stop treating objects with a `nodeType` as if they are DOM Nodes
- Fixes [#1638](https://github.com/jasmine/jasmine/issues/1638)
* Fixes issue where PhantomJS 2 and IE 10 - 11 crashed when reporting SVG element equality
- Merges [#1621](https://github.com/jasmine/jasmine/issues/1621) from @Havunen
- Fixes [#1618](https://github.com/jasmine/jasmine/issues/1618)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

View File

@@ -23,9 +23,6 @@ setup(
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',

View File

@@ -1,270 +0,0 @@
describe("ConsoleReporter", function() {
var out;
beforeEach(function() {
out = (function() {
var output = "";
return {
print: function(str) {
output += str;
},
getOutput: function() {
return output.replace('ConsoleReporter is deprecated and will be removed in a future version.', '');
},
clear: function() {
output = "";
}
};
}());
});
it("reports that the suite has started to the console", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.jasmineStarted();
expect(out.getOutput()).toEqual("Started\n");
});
it("starts the provided timer when jasmine starts", function() {
var timerSpy = jasmine.createSpyObj('timer', ['start']),
reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
timer: timerSpy
});
reporter.jasmineStarted();
expect(timerSpy.start).toHaveBeenCalled();
});
it("reports a passing spec as a dot", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.specDone({status: "passed"});
expect(out.getOutput()).toEqual(".");
});
it("does not report a disabled spec", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.specDone({status: "disabled"});
expect(out.getOutput()).toEqual("");
});
it("reports a failing spec as an 'F'", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.specDone({status: "failed"});
expect(out.getOutput()).toEqual("F");
});
it("reports a pending spec as a '*'", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.specDone({status: "pending"});
expect(out.getOutput()).toEqual("*");
});
it("alerts user if there are no specs", function(){
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.jasmineStarted();
out.clear();
reporter.jasmineDone();
expect(out.getOutput()).toMatch(/No specs found/);
});
it("reports a summary when done (singular spec and time)", function() {
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
timer: timerSpy
});
reporter.jasmineStarted();
reporter.specDone({status: "passed"});
timerSpy.elapsed.and.returnValue(1000);
out.clear();
reporter.jasmineDone();
expect(out.getOutput()).toMatch(/1 spec, 0 failures/);
expect(out.getOutput()).not.toMatch(/0 pending specs/);
expect(out.getOutput()).toMatch("Finished in 1 second\n");
});
it("reports a summary when done (pluralized specs and seconds)", function() {
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
timer: timerSpy
});
reporter.jasmineStarted();
reporter.specDone({status: "passed"});
reporter.specDone({status: "pending"});
reporter.specDone({
status: "failed",
description: "with a failing spec",
fullName: "A suite with a failing spec",
failedExpectations: [
{
passed: false,
message: "Expected true to be false.",
expected: false,
actual: true,
stack: "foo\nbar\nbaz"
}
]
});
out.clear();
timerSpy.elapsed.and.returnValue(100);
reporter.jasmineDone();
expect(out.getOutput()).toMatch(/3 specs, 1 failure, 1 pending spec/);
expect(out.getOutput()).toMatch("Finished in 0.1 seconds\n");
});
it("reports a summary when done that includes stack traces for a failing suite", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.jasmineStarted();
reporter.specDone({status: "passed"});
reporter.specDone({
status: "failed",
description: "with a failing spec",
fullName: "A suite with a failing spec",
failedExpectations: [
{
passed: false,
message: "Expected true to be false.",
expected: false,
actual: true,
stack: "foo bar baz"
}
]
});
out.clear();
reporter.jasmineDone();
expect(out.getOutput()).toMatch(/true to be false/);
expect(out.getOutput()).toMatch(/foo bar baz/);
});
describe('onComplete callback', function(){
var onComplete, reporter;
beforeEach(function() {
onComplete = jasmine.createSpy('onComplete');
reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
onComplete: onComplete
});
reporter.jasmineStarted();
});
it("is called when the suite is done", function() {
reporter.jasmineDone();
expect(onComplete).toHaveBeenCalledWith(true);
});
it('calls it with false if there are spec failures', function() {
reporter.specDone({status: "failed", failedExpectations: []});
reporter.jasmineDone();
expect(onComplete).toHaveBeenCalledWith(false);
});
it('calls it with false if there are suite failures', function() {
reporter.specDone({status: "passed"});
reporter.suiteDone({failedExpectations: [{ message: 'bananas' }] });
reporter.jasmineDone();
expect(onComplete).toHaveBeenCalledWith(false);
});
});
describe("with color", function() {
it("reports that the suite has started to the console", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
showColors: true
});
reporter.jasmineStarted();
expect(out.getOutput()).toEqual("Started\n");
});
it("reports a passing spec as a dot", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
showColors: true
});
reporter.specDone({status: "passed"});
expect(out.getOutput()).toEqual("\x1B[32m.\x1B[0m");
});
it("does not report a disabled spec", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
showColors: true
});
reporter.specDone({status: 'disabled'});
expect(out.getOutput()).toEqual("");
});
it("reports a failing spec as an 'F'", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
showColors: true
});
reporter.specDone({status: 'failed'});
expect(out.getOutput()).toEqual("\x1B[31mF\x1B[0m");
});
it("displays all afterAll exceptions", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
showColors: true
});
reporter.suiteDone({ failedExpectations: [{ message: 'After All Exception' }] });
reporter.suiteDone({ failedExpectations: [{ message: 'Some Other Exception' }] });
reporter.jasmineDone();
expect(out.getOutput()).toMatch(/After All Exception/);
expect(out.getOutput()).toMatch(/Some Other Exception/);
});
});
});

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

@@ -411,50 +411,6 @@ describe("Clock", function() {
clock.tick(50);
}).toThrow();
});
it("on IE < 9, fails if extra args are passed to fake clock", function() {
//fail, because this would break in IE9.
var fakeSetTimeout = jasmine.createSpy('setTimeout'),
fakeSetInterval = jasmine.createSpy('setInterval'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction']),
fn = jasmine.createSpy('fn'),
fakeGlobal = {
setTimeout: fakeSetTimeout,
setInterval: fakeSetInterval
},
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new jasmineUnderTest.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate),
timeout = new clock.FakeTimeout();
fakeSetTimeout.apply = null;
fakeSetInterval.apply = null;
clock.install();
clock.setTimeout(fn, 0);
if (!NODE_JS) {
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, []);
} else {
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, [], false, timeout);
}
expect(function() {
clock.setTimeout(fn, 0, 'extra');
}).toThrow();
clock.setInterval(fn, 0);
if (!NODE_JS) {
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, [], true);
} else {
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, [], true, timeout);
}
expect(function() {
clock.setInterval(fn, 0, 'extra');
}).toThrow();
});
});
describe("Clock (acceptance)", function() {
@@ -713,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(),
@@ -47,17 +69,105 @@ describe("ExceptionFormatter", function() {
});
describe("#stack", function() {
it("formats stack traces from Webkit, Firefox, node.js or IE10+", function() {
if (jasmine.getEnv().ieVersion < 10 || jasmine.getEnv().safariVersion < 6) { return; }
it("formats stack traces", function() {
var error;
try { throw new Error("an error") } catch(e) { error = e; }
expect(new jasmineUnderTest.ExceptionFormatter().stack(error)).toMatch(/ExceptionFormatterSpec\.js.*\d+/)
});
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' +
' at fn3 (http://localhost:8888/__jasmine__/jasmine.js:4320:20)\n' +
' at fn4 (http://localhost:8888/__spec__/core/UtilSpec.js:110:19)\n'
};
var subject = new jasmineUnderTest.ExceptionFormatter({
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
});
var result = subject.stack(error);
expect(result).toEqual('Error: nope\n' +
' at fn1 (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at <Jasmine>\n' +
' at fn4 (http://localhost:8888/__spec__/core/UtilSpec.js:110:19)'
);
});
it("filters Jasmine stack frames from Webkit style traces", function() {
var error = {
stack: 'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
'fn1@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
'fn2@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28'
};
var subject = new jasmineUnderTest.ExceptionFormatter({
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
});
var result = subject.stack(error);
expect(result).toEqual(
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
'<Jasmine>\n' +
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28'
);
});
it("filters Jasmine stack frames in this environment", function() {
var error, i;
try { throw new Error("an error"); } catch(e) { error = e; }
var subject = new jasmineUnderTest.ExceptionFormatter({
jasmineFile: jasmine.util.jasmineFile()
});
var result = subject.stack(error);
var lines = result.split('\n');
if (lines[0].match(/an error/)) {
lines.shift();
}
expect(lines[0]).toMatch(/ExceptionFormatterSpec.js/);
expect(lines[1]).toMatch(/<Jasmine>/);
// Node has some number of additional frames below Jasmine.
for (i = 2; i < lines.length; i++) {
expect(lines[i]).not.toMatch(/jasmine.js/);
}
});
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

@@ -5,64 +5,42 @@ describe('Exceptions:', function() {
env = new jasmineUnderTest.Env();
});
describe('with break on exception', function() {
it('should not catch the exception', function() {
env.catchExceptions(false);
env.describe('suite for break on exceptions', function() {
env.it('should break when an exception is thrown', function() {
throw new Error('I should hit a breakpoint!');
});
it('should handle exceptions thrown, but continue', function(done) {
var secondTest = jasmine.createSpy('second test');
env.describe('Suite for handles exceptions', function () {
env.it('should be a test that fails because it throws an exception', function() {
throw new Error();
});
var spy = jasmine.createSpy('spy');
try {
env.execute();
spy();
}
catch (e) {}
expect(spy).not.toHaveBeenCalled();
env.it('should be a passing test that runs after exceptions are thrown from a async test', secondTest);
});
var expectations = function() {
expect(secondTest).toHaveBeenCalled();
done();
};
env.addReporter({ jasmineDone: expectations });
env.execute();
});
describe("with catch on exception", function() {
it('should handle exceptions thrown, but continue', function(done) {
var secondTest = jasmine.createSpy('second test');
env.describe('Suite for handles exceptions', function () {
env.it('should be a test that fails because it throws an exception', function() {
throw new Error();
});
env.it('should be a passing test that runs after exceptions are thrown from a async test', secondTest);
it("should handle exceptions thrown directly in top-level describe blocks and continue", function(done) {
var secondDescribe = jasmine.createSpy("second describe");
env.describe("a suite that throws an exception", function () {
env.it("is a test that should pass", function () {
this.expect(true).toEqual(true);
});
var expectations = function() {
expect(secondTest).toHaveBeenCalled();
done();
};
env.addReporter({ jasmineDone: expectations });
env.execute();
throw new Error("top level error");
});
env.describe("a suite that doesn't throw an exception", secondDescribe);
it("should handle exceptions thrown directly in top-level describe blocks and continue", function(done) {
var secondDescribe = jasmine.createSpy("second describe");
env.describe("a suite that throws an exception", function () {
env.it("is a test that should pass", function () {
this.expect(true).toEqual(true);
});
var expectations = function() {
expect(secondDescribe).toHaveBeenCalled();
done();
};
throw new Error("top level error");
});
env.describe("a suite that doesn't throw an exception", secondDescribe);
var expectations = function() {
expect(secondDescribe).toHaveBeenCalled();
done();
};
env.addReporter({ jasmineDone: expectations });
env.execute();
});
env.addReporter({ jasmineDone: expectations });
env.execute();
});
});

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'),
@@ -101,10 +101,42 @@ describe("GlobalErrors", function() {
addedListener(new Error('bar'));
expect(handler).toHaveBeenCalledWith(new Error('bar'));
expect(handler.calls.argsFor(0)[0].jasmineMessage).toBe('Uncaught exception: Error: bar');
errors.uninstall();
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(1)[1];
addedListener(new Error('bar'));
expect(handler).toHaveBeenCalledWith(new Error('bar'));
expect(handler.calls.argsFor(0)[0].jasmineMessage).toBe('Unhandled promise rejection: Error: bar');
errors.uninstall();
expect(fakeGlobal.process.removeListener).toHaveBeenCalledWith('unhandledRejection', addedListener);
expect(fakeGlobal.process.on).toHaveBeenCalledWith('unhandledRejection', 'foo');
});
});

View File

@@ -192,7 +192,7 @@ describe("JsApiReporter", function() {
};
suiteResult2 = {
id: 2,
status: 'finished'
status: 'passed'
};
reporter.suiteStarted(suiteStarted1);
@@ -209,7 +209,7 @@ describe("JsApiReporter", function() {
expect(reporter.suiteResults(1, 1)).toEqual([suiteResult2]);
});
it("returns nothing for out of bounds indicies", function() {
it("returns nothing for out of bounds indices", function() {
expect(reporter.suiteResults(0, 3)).toEqual([suiteResult1, suiteResult2]);
expect(reporter.suiteResults(2, 3)).toEqual([]);
});

View File

@@ -23,7 +23,7 @@ describe("jasmineUnderTest.pp", function () {
expect(jasmineUnderTest.pp(set)).toEqual("Set( 1, 2 )");
});
it("should truncate sets with more elments than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
it("should truncate sets with more elements than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
jasmine.getEnv().requireFunctioningSets();
var originalMaxSize = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
@@ -48,7 +48,7 @@ describe("jasmineUnderTest.pp", function () {
expect(jasmineUnderTest.pp(map)).toEqual("Map( [ 1, 2 ] )");
});
it("should truncate maps with more elments than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
it("should truncate maps with more elements than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
jasmine.getEnv().requireFunctioningMaps();
var originalMaxSize = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
@@ -132,6 +132,10 @@ describe("jasmineUnderTest.pp", function () {
}, bar: [1, 2, 3]})).toEqual("Object({ foo: Function, bar: [ 1, 2, 3 ] })");
});
it("should stringify objects that almost look like DOM nodes", function() {
expect(jasmineUnderTest.pp({nodeType: 1})).toEqual("Object({ nodeType: 1 })");
});
it("should truncate objects with too many keys", function () {
var originalMaxLength = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
var long = {a: 1, b: 2, c: 3};
@@ -268,12 +272,17 @@ describe("jasmineUnderTest.pp", function () {
},
env = new jasmineUnderTest.Env();
var spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() {return [];}});
var spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() {return [];},
createSpy: function(name, originalFn) {
return jasmineUnderTest.Spy(name, originalFn);
}
});
spyRegistry.spyOn(TestObject, 'someFunction');
expect(jasmineUnderTest.pp(TestObject.someFunction)).toEqual("spy on someFunction");
expect(jasmineUnderTest.pp(jasmineUnderTest.createSpy("something"))).toEqual("spy on something");
expect(jasmineUnderTest.pp(env.createSpy("something"))).toEqual("spy on something");
});
it("should stringify objects that implement jasmineToString", function () {
@@ -298,11 +307,7 @@ describe("jasmineUnderTest.pp", function () {
toString: function () { return Object.prototype.toString.call(this); }
};
if (jasmine.getEnv().ieVersion < 9) {
expect(jasmineUnderTest.pp(objFromOtherContext)).toEqual("Object({ foo: 'bar' })");
} else {
expect(jasmineUnderTest.pp(objFromOtherContext)).toEqual("Object({ foo: 'bar', toString: Function })");
}
expect(jasmineUnderTest.pp(objFromOtherContext)).toEqual("Object({ foo: 'bar', toString: Function })");
});
it("should stringify objects have have a toString that isn't a function", function() {
@@ -310,11 +315,7 @@ describe("jasmineUnderTest.pp", function () {
toString: "foo"
};
if (jasmine.getEnv().ieVersion < 9) {
expect(jasmineUnderTest.pp(obj)).toEqual("Object({ })");
} else {
expect(jasmineUnderTest.pp(obj)).toEqual("Object({ toString: 'foo' })");
}
expect(jasmineUnderTest.pp(obj)).toEqual("Object({ toString: 'foo' })");
});
it("should stringify objects from anonymous constructors with custom toString", function () {
@@ -327,8 +328,6 @@ describe("jasmineUnderTest.pp", function () {
});
it("should handle objects with null prototype", function() {
if (jasmine.getEnv().ieVersion < 9) { return; }
var obj = Object.create(null);
obj.foo = 'bar';

View File

@@ -135,9 +135,55 @@ describe("QueueRunner", function() {
expect(queueableFn2.fn).toHaveBeenCalled();
});
it("explicitly fails an async function when next is called with an Error and moves to the next function", function() {
var err = new Error('foo'),
queueableFn1 = { fn: function(done) {
setTimeout(function() { done(err); }, 100);
} },
queueableFn2 = { fn: jasmine.createSpy('fn2') },
failFn = jasmine.createSpy('fail'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn1, queueableFn2],
fail: failFn
});
queueRunner.execute();
expect(failFn).not.toHaveBeenCalled();
expect(queueableFn2.fn).not.toHaveBeenCalled();
jasmine.clock().tick(100);
expect(failFn).toHaveBeenCalledWith(err);
expect(queueableFn2.fn).toHaveBeenCalled();
});
it("does not cause an explicit fail if execution is being stopped", function() {
var err = new jasmineUnderTest.StopExecutionError('foo'),
queueableFn1 = { fn: function(done) {
setTimeout(function() { done(err); }, 100);
} },
queueableFn2 = { fn: jasmine.createSpy('fn2') },
failFn = jasmine.createSpy('fail'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn1, queueableFn2],
fail: failFn
});
queueRunner.execute();
expect(failFn).not.toHaveBeenCalled();
expect(queueableFn2.fn).not.toHaveBeenCalled();
jasmine.clock().tick(100);
expect(failFn).not.toHaveBeenCalled();
expect(queueableFn2.fn).toHaveBeenCalled();
});
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'),
@@ -258,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') },
@@ -419,20 +465,6 @@ describe("QueueRunner", function() {
expect(onExceptionCallback).toHaveBeenCalledWith(jasmine.any(Error));
});
it("rethrows an exception if told to", function() {
var queueableFn = { fn: function() {
throw new Error('fake error');
} },
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn],
catchException: function(e) { return false; }
});
expect(function() {
queueRunner.execute();
}).toThrowError('fake error');
});
it("continues running the functions even after an exception is thrown in an async spec", function() {
var queueableFn = { fn: function(done) { throw new Error("error"); } },
nextQueueableFn = { fn: jasmine.createSpy("nextFunction") },
@@ -449,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() {
@@ -522,6 +557,24 @@ describe("QueueRunner", function() {
expect(nextQueueableFn.fn).not.toHaveBeenCalled();
expect(cleanupFn.fn).toHaveBeenCalled();
});
it("skips to cleanup functions when next is called with an Error", function() {
var queueableFn = { fn: function(done) {
done(new Error('nope'));
} },
nextQueueableFn = { fn: jasmine.createSpy('nextFunction') },
cleanupFn = { fn: jasmine.createSpy('cleanup') },
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn, nextQueueableFn],
cleanupFns: [cleanupFn],
completeOnFirstError: true,
});
queueRunner.execute();
jasmine.clock().tick();
expect(nextQueueableFn.fn).not.toHaveBeenCalled();
expect(cleanupFn.fn).toHaveBeenCalled();
});
});
});

View File

@@ -9,70 +9,131 @@ describe("ReportDispatcher", function() {
});
it("dispatches requested methods to added reporters", function() {
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar']),
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar'], queueRunnerFactory),
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
anotherReporter = jasmine.createSpyObj('reporter', ['foo', 'bar']);
anotherReporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
completeCallback = jasmine.createSpy('complete');
dispatcher.addReporter(reporter);
dispatcher.addReporter(anotherReporter);
dispatcher.foo(123, 456);
dispatcher.foo(123, 456, completeCallback);
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
queueableFns: [{fn: jasmine.any(Function)}, {fn: jasmine.any(Function)}],
isReporter: true
}));
var fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
fns[0].fn();
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
expect(reporter.foo.calls.mostRecent().object).toBe(reporter);
fns[1].fn();
expect(anotherReporter.foo).toHaveBeenCalledWith(123, 456);
expect(anotherReporter.foo.calls.mostRecent().object).toBe(anotherReporter);
dispatcher.bar('a', 'b');
queueRunnerFactory.calls.reset();
dispatcher.bar('a', 'b', completeCallback);
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
queueableFns: [{fn: jasmine.any(Function)}, {fn: jasmine.any(Function)}],
isReporter: true
}));
fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
fns[0].fn();
expect(reporter.bar).toHaveBeenCalledWith('a', 'b');
fns[1].fn();
expect(anotherReporter.bar).toHaveBeenCalledWith('a', 'b');
});
it("does not dispatch to a reporter if the reporter doesn't accept the method", function() {
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo']),
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
dispatcher = new jasmineUnderTest.ReportDispatcher(['foo'], queueRunnerFactory),
reporter = jasmine.createSpyObj('reporter', ['baz']);
dispatcher.addReporter(reporter);
expect(function() {
dispatcher.foo(123, 456);
}).not.toThrow();
dispatcher.foo(123, 456);
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
queueableFns: []
}));
});
it("allows providing a fallback reporter in case there's no other report", function() {
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar']),
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']);
it("allows providing a fallback reporter in case there's no other reporter", function() {
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar'], queueRunnerFactory),
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
completeCallback = jasmine.createSpy('complete');
dispatcher.provideFallbackReporter(reporter);
dispatcher.foo(123, 456);
dispatcher.foo(123, 456, completeCallback);
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
queueableFns: [{fn: jasmine.any(Function)}],
isReporter: true
}));
var fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
fns[0].fn();
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
});
it("does not call fallback reporting methods when another report is provided", function() {
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar']),
it("does not call fallback reporting methods when another reporter is provided", function() {
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar'], queueRunnerFactory),
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
fallbackReporter = jasmine.createSpyObj('otherReporter', ['foo', 'bar']);
fallbackReporter = jasmine.createSpyObj('otherReporter', ['foo', 'bar']),
completeCallback = jasmine.createSpy('complete');
dispatcher.provideFallbackReporter(fallbackReporter);
dispatcher.addReporter(reporter);
dispatcher.foo(123, 456);
dispatcher.foo(123, 456, completeCallback);
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
queueableFns: [{fn: jasmine.any(Function)}],
isReporter: true
}));
var fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
fns[0].fn();
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
expect(fallbackReporter.foo).not.toHaveBeenCalledWith(123, 456);
});
it("allows registered reporters to be cleared", function() {
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar']),
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar'], queueRunnerFactory),
reporter1 = jasmine.createSpyObj('reporter1', ['foo', 'bar']),
reporter2 = jasmine.createSpyObj('reporter2', ['foo', 'bar']);
reporter2 = jasmine.createSpyObj('reporter2', ['foo', 'bar']),
completeCallback = jasmine.createSpy('complete');
dispatcher.addReporter(reporter1);
dispatcher.foo(123);
dispatcher.foo(123, completeCallback);
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
queueableFns: [{fn: jasmine.any(Function)}],
isReporter: true
}));
var fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
fns[0].fn();
expect(reporter1.foo).toHaveBeenCalledWith(123);
dispatcher.clearReporters();
dispatcher.addReporter(reporter2);
dispatcher.bar(456);
dispatcher.bar(456, completeCallback);
expect(queueRunnerFactory).toHaveBeenCalledWith(jasmine.objectContaining({
queueableFns: [{fn: jasmine.any(Function)}],
isReporter: true
}));
fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
fns[0].fn();
expect(reporter1.bar).not.toHaveBeenCalled();
expect(reporter2.bar).toHaveBeenCalledWith(456);
});

View File

@@ -55,6 +55,7 @@ describe("Spec", function() {
spec.execute();
fakeQueueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
// TODO: due to some issue with the Pretty Printer, this line fails, but the other two pass.
// This means toHaveBeenCalledWith on IE8 will always be broken.
@@ -82,6 +83,7 @@ describe("Spec", function() {
spec.execute();
fakeQueueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(startCallback).toHaveBeenCalled();
});
@@ -104,8 +106,8 @@ describe("Spec", function() {
spec.execute();
var options = fakeQueueRunner.calls.mostRecent().args[0];
expect(options.queueableFns).toEqual([before, queueableFn]);
expect(options.cleanupFns).toEqual([after]);
expect(options.queueableFns).toEqual([{fn: jasmine.any(Function)}, before, queueableFn]);
expect(options.cleanupFns).toEqual([after, {fn: jasmine.any(Function)}]);
});
it("tells the queue runner that it's a leaf node", function() {
@@ -140,9 +142,8 @@ describe("Spec", function() {
expect(spec.status()).toBe('pending');
});
it("can be disabled, but still calls callbacks", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner')
.and.callFake(function(attrs) { attrs.onComplete(); }),
it("can be excluded at execution time by a parent", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
startCallback = jasmine.createSpy('startCallback'),
specBody = jasmine.createSpy('specBody'),
resultCallback = jasmine.createSpy('resultCallback'),
@@ -153,46 +154,26 @@ describe("Spec", function() {
queueRunnerFactory: fakeQueueRunner
});
spec.disable();
spec.execute('cally-back', true);
expect(spec.status()).toBe('disabled');
spec.execute();
expect(fakeQueueRunner).toHaveBeenCalled();
expect(fakeQueueRunner).toHaveBeenCalledWith(jasmine.objectContaining({
onComplete: jasmine.any(Function),
queueableFns: [{fn: jasmine.any(Function)}],
cleanupFns: [{fn: jasmine.any(Function)}]
}));
expect(specBody).not.toHaveBeenCalled();
var args = fakeQueueRunner.calls.mostRecent().args[0];
args.queueableFns[0].fn();
expect(startCallback).toHaveBeenCalled();
args.cleanupFns[0].fn();
expect(resultCallback).toHaveBeenCalled();
});
it("can be disabled at execution time by a parent", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner')
.and.callFake(function(attrs) { attrs.onComplete(); }),
startCallback = jasmine.createSpy('startCallback'),
specBody = jasmine.createSpy('specBody'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
onStart:startCallback,
queueableFn: { fn: specBody },
resultCallback: resultCallback,
queueRunnerFactory: fakeQueueRunner
});
spec.execute(undefined, false);
expect(spec.result.status).toBe('disabled');
expect(fakeQueueRunner).toHaveBeenCalled();
expect(specBody).not.toHaveBeenCalled();
expect(startCallback).toHaveBeenCalled();
expect(resultCallback).toHaveBeenCalled();
expect(spec.result.status).toBe('excluded');
});
it("can be marked pending, but still calls callbacks when executed", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner')
.and.callFake(function(attrs) { attrs.onComplete(); }),
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
startCallback = jasmine.createSpy('startCallback'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
@@ -214,7 +195,10 @@ describe("Spec", function() {
expect(fakeQueueRunner).toHaveBeenCalled();
var args = fakeQueueRunner.calls.mostRecent().args[0];
args.queueableFns[0].fn();
expect(startCallback).toHaveBeenCalled();
args.cleanupFns[0].fn('things');
expect(resultCallback).toHaveBeenCalledWith({
id: spec.id,
status: 'pending',
@@ -223,8 +207,9 @@ describe("Spec", function() {
failedExpectations: [],
passedExpectations: [],
deprecationWarnings: [],
pendingReason: ''
});
pendingReason: '',
duration: null,
}, 'things');
});
it("should call the done callback on execution complete", function() {
@@ -241,6 +226,39 @@ describe("Spec", function() {
expect(done).toHaveBeenCalled();
});
it("should call the done callback with an error if the spec is failed", function() {
var done = jasmine.createSpy('done callback'),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} },
catchExceptions: function() { return false; },
resultCallback: function() {},
queueRunnerFactory: function(attrs) {
spec.result.status = 'failed';
attrs.onComplete();
}
});
spec.execute(done);
expect(done).toHaveBeenCalledWith(jasmine.any(jasmineUnderTest.StopExecutionError));
});
it("should report the duration of the test", function() {
var done = jasmine.createSpy('done callback'),
timer = jasmine.createSpyObj('timer', {'start': null, elapsed: 77000}),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy("spec body")},
catchExceptions: function() { return false; },
resultCallback: function() {},
queueRunnerFactory: function(attrs) {
attrs.onComplete();
},
timer: timer,
});
spec.execute(done);
expect(spec.result.duration).toBe(77000);
});
it("#status returns passing by default", function() {
var spec = new jasmineUnderTest.Spec({queueableFn: { fn: jasmine.createSpy("spec body")} });
expect(spec.status()).toBe('passed');
@@ -260,11 +278,12 @@ describe("Spec", function() {
});
it("keeps track of passed and failed expectations", function() {
var resultCallback = jasmine.createSpy('resultCallback'),
var fakeQueueRunner = jasmine.createSpy('queueRunner'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy("spec body") },
expectationResultFactory: function (data) { return data; },
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
queueRunnerFactory: fakeQueueRunner,
resultCallback: resultCallback
});
spec.addExpectationResult(true, 'expectation1');
@@ -272,19 +291,21 @@ describe("Spec", function() {
spec.execute();
fakeQueueRunner.calls.mostRecent().args[0].cleanupFns[0].fn();
expect(resultCallback.calls.first().args[0].passedExpectations).toEqual(['expectation1']);
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual(['expectation2']);
});
it("throws an ExpectationFailed error upon receiving a failed expectation when 'throwOnExpectationFailure' is set", function() {
var resultCallback = jasmine.createSpy('resultCallback'),
var fakeQueueRunner = jasmine.createSpy('queueRunner'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} },
expectationResultFactory: function(data) { return data; },
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
resultCallback: resultCallback,
throwOnExpectationFailure: true
});
queueableFn: { fn: function() {} },
expectationResultFactory: function(data) { return data; },
queueRunnerFactory: fakeQueueRunner,
resultCallback: resultCallback,
throwOnExpectationFailure: true
});
spec.addExpectationResult(true, 'passed');
expect(function() {
@@ -293,6 +314,7 @@ describe("Spec", function() {
spec.execute();
fakeQueueRunner.calls.mostRecent().args[0].cleanupFns[0].fn();
expect(resultCallback.calls.first().args[0].passedExpectations).toEqual(['passed']);
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual(['failed']);
});
@@ -359,17 +381,20 @@ describe("Spec", function() {
});
it("should log a failure when handling an exception", function() {
var resultCallback = jasmine.createSpy('resultCallback'),
var fakeQueueRunner = jasmine.createSpy('queueRunner'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} },
expectationResultFactory: function(data) { return data; },
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
queueRunnerFactory: fakeQueueRunner,
resultCallback: resultCallback
});
spec.onException('foo');
spec.execute();
var args = fakeQueueRunner.calls.mostRecent().args[0];
args.cleanupFns[0].fn();
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([{
error: 'foo',
matcherName: '',
@@ -380,63 +405,20 @@ describe("Spec", function() {
});
it("should not log an additional failure when handling an ExpectationFailed error", function() {
var resultCallback = jasmine.createSpy('resultCallback'),
var fakeQueueRunner = jasmine.createSpy('queueRunner'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} },
expectationResultFactory: function(data) { return data; },
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
queueRunnerFactory: fakeQueueRunner,
resultCallback: resultCallback
});
spec.onException(new jasmineUnderTest.errors.ExpectationFailed());
spec.execute();
var args = fakeQueueRunner.calls.mostRecent().args[0];
args.cleanupFns[0].fn();
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([]);
});
it("retrieves a result with updated status", function() {
var spec = new jasmineUnderTest.Spec({ queueableFn: { fn: function() {} } });
expect(spec.getResult().status).toBe('passed');
});
it("retrives a result with disabled status", function() {
var spec = new jasmineUnderTest.Spec({ queueableFn: { fn: function() {} } });
spec.disable();
expect(spec.getResult().status).toBe('disabled');
});
it("retrives a result with pending status", function() {
var spec = new jasmineUnderTest.Spec({ queueableFn: { fn: function() {} } });
spec.pend();
expect(spec.getResult().status).toBe('pending');
});
it("should not be executable when disabled", function() {
var spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} }
});
spec.disable();
expect(spec.isExecutable()).toBe(false);
});
it("should be executable when pending", function() {
var spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} }
});
spec.pend();
expect(spec.isExecutable()).toBe(true);
});
it("should be executable when not disabled or pending", function() {
var spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} }
});
expect(spec.isExecutable()).toBe(true);
});
});

View File

@@ -1,7 +1,11 @@
describe("SpyRegistry", function() {
function createSpy(name, originalFn) {
return jasmineUnderTest.Spy(name, originalFn);
}
describe("#spyOn", function() {
it("checks for the existence of the object", function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry();
var spyRegistry = new jasmineUnderTest.SpyRegistry({createSpy: createSpy});
expect(function() {
spyRegistry.spyOn(void 0, 'pants');
}).toThrowError(/could not find an object/);
@@ -43,7 +47,10 @@ describe("SpyRegistry", function() {
it("checks if it has already been spied upon", function() {
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() { return spies; },
createSpy: createSpy
}),
subject = { spiedFunc: function() {} };
spyRegistry.spyOn(subject, 'spiedFunc');
@@ -54,9 +61,6 @@ describe("SpyRegistry", function() {
});
it("checks if it can be spied upon", function() {
// IE 8 doesn't support `definePropery` on non-DOM nodes
if (jasmine.getEnv().ieVersion < 9) { return; }
var scope = {};
function myFunc() {
@@ -84,7 +88,7 @@ describe("SpyRegistry", function() {
it("overrides the method on the object and returns the spy", function() {
var originalFunctionWasCalled = false,
spyRegistry = new jasmineUnderTest.SpyRegistry(),
spyRegistry = new jasmineUnderTest.SpyRegistry({createSpy: createSpy}),
subject = { spiedFunc: function() { originalFunctionWasCalled = true; } };
var spy = spyRegistry.spyOn(subject, 'spiedFunc');
@@ -94,9 +98,6 @@ describe("SpyRegistry", function() {
});
describe("#spyOnProperty", function() {
// IE 8 doesn't support `definePropery` on non-DOM nodes
if (jasmine.getEnv().ieVersion < 9) { return; }
it("checks for the existence of the object", function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry();
expect(function() {
@@ -137,7 +138,7 @@ describe("SpyRegistry", function() {
});
it("checks if it has already been spied upon", function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
var spyRegistry = new jasmineUnderTest.SpyRegistry({createSpy: createSpy}),
subject = {};
Object.defineProperty(subject, 'spiedProp', {
@@ -176,7 +177,7 @@ describe("SpyRegistry", function() {
});
it("overrides the property getter on the object and returns the spy", function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
var spyRegistry = new jasmineUnderTest.SpyRegistry({createSpy: createSpy}),
subject = {},
returnValue = 1;
@@ -195,7 +196,7 @@ describe("SpyRegistry", function() {
});
it("overrides the property setter on the object and returns the spy", function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
var spyRegistry = new jasmineUnderTest.SpyRegistry({createSpy: createSpy}),
subject = {},
returnValue = 1;
@@ -213,10 +214,104 @@ 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 = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() { return spies; },
createSpy: createSpy
}),
originalFunction = function() {},
subject = { spiedFunc: originalFunction };
@@ -228,7 +323,10 @@ describe("SpyRegistry", function() {
it("restores the original functions, even when that spy has been replace and re-spied upon", function() {
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() { return spies; },
createSpy: createSpy
}),
originalFunction = function() {},
subject = { spiedFunc: originalFunction };
@@ -246,11 +344,11 @@ describe("SpyRegistry", function() {
});
it("does not add a property that the spied-upon object didn't originally have", function() {
// IE 8 doesn't support `Object.create`
if (jasmine.getEnv().ieVersion < 9) { return; }
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() { return spies; },
createSpy: createSpy
}),
originalFunction = function() {},
subjectParent = {spiedFunc: originalFunction};
@@ -266,11 +364,11 @@ describe("SpyRegistry", function() {
});
it("restores the original function when it\'s inherited and cannot be deleted", function() {
// IE 8 doesn't support `Object.create` or `Object.defineProperty`
if (jasmine.getEnv().ieVersion < 9) { return; }
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() { return spies; },
createSpy: createSpy
}),
originalFunction = function() {},
subjectParent = {spiedFunc: originalFunction};
@@ -297,6 +395,7 @@ describe("SpyRegistry", function() {
global = new FakeWindow(),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() { return spies; },
createSpy: createSpy,
global: global
});
@@ -309,11 +408,11 @@ describe("SpyRegistry", function() {
describe('spying on properties', function() {
it("restores the original properties on the spied-upon objects", function() {
// IE 8 doesn't support `definePropery` on non-DOM nodes
if (jasmine.getEnv().ieVersion < 9) { return; }
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() { return spies; },
createSpy: createSpy
}),
originalReturn = 1,
subject = {};
@@ -329,11 +428,11 @@ describe("SpyRegistry", function() {
});
it("does not add a property that the spied-upon object didn't originally have", function() {
// IE 8 doesn't support `Object.create`
if (jasmine.getEnv().ieVersion < 9) { return; }
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() { return spies; },
createSpy: createSpy
}),
originalReturn = 1,
subjectParent = {};

View File

@@ -1,4 +1,10 @@
describe('Spies', function () {
var env;
beforeEach(function() {
env = new jasmineUnderTest.Env();
});
describe("createSpy", function() {
var TestClass;
@@ -9,28 +15,40 @@ describe('Spies', function () {
});
it("preserves the properties of the spied function", function() {
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
var spy = env.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
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";
expect(function() {
jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
env.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
}).toThrowError("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
});
it("adds a spyStrategy and callTracker to the spy", function() {
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
var spy = env.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
expect(spy.and).toEqual(jasmine.any(jasmineUnderTest.SpyStrategy));
expect(spy.calls).toEqual(jasmine.any(jasmineUnderTest.CallTracker));
});
it("tracks the argument of calls", function () {
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
var spy = env.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
var trackSpy = spyOn(spy.calls, "track");
spy("arg");
@@ -39,7 +57,7 @@ describe('Spies', function () {
});
it("tracks the context of calls", function () {
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
var spy = env.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
var trackSpy = spyOn(spy.calls, "track");
var contextObject = { spyMethod: spy };
@@ -49,7 +67,7 @@ describe('Spies', function () {
});
it("tracks the return value of calls", function () {
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
var spy = env.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
var trackSpy = spyOn(spy.calls, "track");
spy.and.returnValue("return value");
@@ -71,7 +89,7 @@ describe('Spies', function () {
for (var arity = 0; arity < functions.length; arity++) {
var someFunction = functions[arity],
spy = jasmineUnderTest.createSpy(someFunction.name, someFunction);
spy = env.createSpy(someFunction.name, someFunction);
expect(spy.length).toEqual(arity);
}
@@ -80,48 +98,92 @@ describe('Spies', function () {
describe("createSpyObj", function() {
it("should create an object with spy methods and corresponding return values when you call jasmine.createSpyObj() with an object", function () {
var spyObj = jasmineUnderTest.createSpyObj('BaseName', {'method1': 42, 'method2': 'special sauce' });
var spyObj = env.createSpyObj('BaseName', {'method1': 42, 'method2': 'special sauce' });
expect(spyObj.method1()).toEqual(42);
expect(spyObj.method1.and.identity()).toEqual('BaseName.method1');
expect(spyObj.method1.and.identity).toEqual('BaseName.method1');
expect(spyObj.method2()).toEqual('special sauce');
expect(spyObj.method2.and.identity()).toEqual('BaseName.method2');
expect(spyObj.method2.and.identity).toEqual('BaseName.method2');
});
it("should create an object with a bunch of spy methods when you call jasmine.createSpyObj()", function() {
var spyObj = jasmineUnderTest.createSpyObj('BaseName', ['method1', 'method2']);
var spyObj = env.createSpyObj('BaseName', ['method1', 'method2']);
expect(spyObj).toEqual({ method1: jasmine.any(Function), method2: jasmine.any(Function)});
expect(spyObj.method1.and.identity()).toEqual('BaseName.method1');
expect(spyObj.method2.and.identity()).toEqual('BaseName.method2');
expect(spyObj.method1.and.identity).toEqual('BaseName.method1');
expect(spyObj.method2.and.identity).toEqual('BaseName.method2');
});
it("should allow you to omit the baseName", function() {
var spyObj = jasmineUnderTest.createSpyObj(['method1', 'method2']);
var spyObj = env.createSpyObj(['method1', 'method2']);
expect(spyObj).toEqual({ method1: jasmine.any(Function), method2: jasmine.any(Function)});
expect(spyObj.method1.and.identity()).toEqual('unknown.method1');
expect(spyObj.method2.and.identity()).toEqual('unknown.method2');
expect(spyObj.method1.and.identity).toEqual('unknown.method1');
expect(spyObj.method2.and.identity).toEqual('unknown.method2');
});
it("should throw if you do not pass an array or object argument", function() {
expect(function() {
jasmineUnderTest.createSpyObj('BaseName');
env.createSpyObj('BaseName');
}).toThrow("createSpyObj requires a non-empty array or object of method names to create spies for");
});
it("should throw if you pass an empty array argument", function() {
expect(function() {
jasmineUnderTest.createSpyObj('BaseName', []);
env.createSpyObj('BaseName', []);
}).toThrow("createSpyObj requires a non-empty array or object of method names to create spies for");
});
it("should throw if you pass an empty object argument", function() {
expect(function() {
jasmineUnderTest.createSpyObj('BaseName', {});
env.createSpyObj('BaseName', {});
}).toThrow("createSpyObj requires a non-empty array or object of method names to create spies for");
});
});
it("can use different strategies for different arguments", function() {
var spy = env.createSpy('foo');
spy.and.returnValue(42);
spy.withArgs('baz', 'grault').and.returnValue(-1);
spy.withArgs('thud').and.returnValue('bob');
expect(spy('foo')).toEqual(42);
expect(spy('baz', 'grault')).toEqual(-1);
expect(spy('thud')).toEqual('bob');
expect(spy('baz', 'grault', 'waldo')).toEqual(42);
});
it("uses custom equality testers when selecting a strategy", function() {
var spy = env.createSpy('foo');
spy.and.returnValue(42);
spy.withArgs(jasmineUnderTest.any(String)).and.returnValue(-1);
expect(spy('foo')).toEqual(-1);
expect(spy({})).toEqual(42);
});
it("can reconfigure an argument-specific strategy", function() {
var spy = env.createSpy('foo');
spy.withArgs('foo').and.returnValue(42);
spy.withArgs('foo').and.returnValue(17);
expect(spy('foo')).toEqual(17);
});
describe("When withArgs is used without a base strategy", function() {
it("uses the matching strategy", function() {
var spy = env.createSpy('foo');
spy.withArgs('baz').and.returnValue(-1);
expect(spy('baz')).toEqual(-1);
});
it("throws if the args don't match", function() {
var spy = env.createSpy('foo');
spy.withArgs('bar').and.returnValue(-1);
expect(function() { spy('baz', {qux: 42}); }).toThrowError('Spy \'foo\' received a call with arguments [ \'baz\', Object({ qux: 42 }) ] but all configured strategies specify other arguments.');
});
});
});

View File

@@ -3,13 +3,13 @@ describe("SpyStrategy", function() {
it("defaults its name to unknown", function() {
var spyStrategy = new jasmineUnderTest.SpyStrategy();
expect(spyStrategy.identity()).toEqual("unknown");
expect(spyStrategy.identity).toEqual("unknown");
});
it("takes a name", function() {
var spyStrategy = new jasmineUnderTest.SpyStrategy({name: "foo"});
expect(spyStrategy.identity()).toEqual("foo");
expect(spyStrategy.identity).toEqual("foo");
});
it("stubs an original function, if provided", function() {
@@ -27,7 +27,7 @@ describe("SpyStrategy", function() {
returnValue;
spyStrategy.callThrough();
returnValue = spyStrategy.exec("foo");
returnValue = spyStrategy.exec(null, ["foo"]);
expect(originalFn).toHaveBeenCalled();
expect(originalFn.calls.mostRecent().args).toEqual(["foo"]);
@@ -110,6 +110,49 @@ describe("SpyStrategy", function() {
})
});
it("allows a custom strategy to be used", function() {
var plan = jasmine.createSpy('custom strategy')
.and.returnValue('custom strategy result'),
customStrategy = jasmine.createSpy('custom strategy')
.and.returnValue(plan),
originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({
fn: originalFn,
customStrategies: {
doSomething: customStrategy
}
});
spyStrategy.doSomething(1, 2, 3);
expect(customStrategy).toHaveBeenCalledWith(1, 2, 3);
expect(spyStrategy.exec(null, ['some', 'args']))
.toEqual('custom strategy result');
expect(plan).toHaveBeenCalledWith('some', 'args');
});
it("throws an error if a custom strategy doesn't return a function", function() {
var originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({
fn: originalFn,
customStrategies: {
doSomething: function() { return 'not a function' }
}
});
expect(function() { spyStrategy.doSomething(1, 2, 3) }).toThrowError('Spy strategy must return a function');
});
it("does not allow custom strategies to overwrite existing methods", function() {
var spyStrategy = new jasmineUnderTest.SpyStrategy({
fn: function() {},
customStrategies: {
exec: function() {}
}
});
expect(spyStrategy.exec).toBe(jasmineUnderTest.SpyStrategy.prototype.exec);
});
it('throws an error when a non-function is passed to callFake strategy', function() {
var originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}),

207
spec/core/StackTraceSpec.js Normal file
View File

@@ -0,0 +1,207 @@
describe("StackTrace", function() {
it("understands Chrome/IE/Edge style traces", function() {
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(error);
expect(result.message).toEqual('Error: nope');
expect(result.style).toEqual('v8');
expect(result.frames).toEqual([
{
raw: ' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
func: 'UserContext.<anonymous>',
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
line: 115
},
{
raw: ' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
func: 'QueueRunner.run',
file: 'http://localhost:8888/__jasmine__/jasmine.js',
line: 4320
}
]);
});
it("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 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');
expect(result.frames).toEqual([
{
raw: ' at /somewhere/jasmine/lib/jasmine-core/jasmine.js:4255:9',
func: undefined,
file: '/somewhere/jasmine/lib/jasmine-core/jasmine.js',
line: 4255
},
{
raw: ' at QueueRunner.complete [as onComplete] (/somewhere/jasmine/lib/jasmine-core/jasmine.js:579:9)',
func: 'QueueRunner.complete [as onComplete]',
file: '/somewhere/jasmine/lib/jasmine-core/jasmine.js',
line: 579
},
{
raw: ' at Immediate.<anonymous> (/somewhere/jasmine/lib/jasmine-core/jasmine.js:4314:12)',
func: 'Immediate.<anonymous>',
file: '/somewhere/jasmine/lib/jasmine-core/jasmine.js',
line: 4314
},
{
raw: ' at runCallback (timers.js:672:20)',
func: 'runCallback',
file: 'timers.js',
line: 672
}
]);
});
it("understands Safari/Firefox/Phantom-OS X style traces", function() {
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');
expect(result.frames).toEqual([
{
raw: 'http://localhost:8888/__spec__/core/UtilSpec.js:115:28',
func: undefined,
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
line: 115
},
{
raw: 'run@http://localhost:8888/__jasmine__/jasmine.js:4320:27',
func: 'run',
file: 'http://localhost:8888/__jasmine__/jasmine.js',
line: 4320
}
]);
});
it("does not mistake gibberish for Safari/Firefox/Phantom-OS X style traces", function() {
var error = {
message: 'nope',
stack: 'randomcharsnotincludingwhitespace'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.style).toBeNull();
expect(result.frames).toEqual([
{ raw: error.stack }
]);
});
it("understands Phantom-Linux style traces", function() {
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(error);
expect(result.message).toBeFalsy();
expect(result.style).toEqual('v8');
expect(result.frames).toEqual([
{
raw: ' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
func: 'UserContext.<anonymous>',
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
line: 115
},
{
raw: ' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
func: 'QueueRunner.run',
file: 'http://localhost:8888/__jasmine__/jasmine.js',
line: 4320
}
]);
});
it("ignores blank lines", function() {
var error = {
message: 'nope',
stack:
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.frames).toEqual([
{
raw: ' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
func: 'UserContext.<anonymous>',
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
line: 115
}
]);
});
it("omits properties except 'raw' for frames that are not understood", function() {
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(error);
expect(result.style).toEqual('v8');
expect(result.frames).toEqual([
{
raw: ' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
func: 'UserContext.<anonymous>',
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
line: 115
},
{
raw: ' but this is quite unexpected'
},
{
raw: ' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
func: 'QueueRunner.run',
file: 'http://localhost:8888/__jasmine__/jasmine.js',
line: 4320
}
]);
});
});

View File

@@ -67,11 +67,10 @@ describe("Suite", function() {
expect(suite.afterFns).toEqual([innerAfter, outerAfter]);
});
it('has a status of failed if any afterAll expectations have failed', function() {
it('has a status of failed if any expectations have failed', function() {
var suite = new jasmineUnderTest.Suite({
expectationResultFactory: function() { return 'hi'; }
});
suite.addChild({ result: { status: 'done' } });
suite.addExpectationResult(false);
expect(suite.status()).toBe('failed');
@@ -80,7 +79,7 @@ describe("Suite", function() {
it("retrieves a result with updated status", function() {
var suite = new jasmineUnderTest.Suite({});
expect(suite.getResult().status).toBe('finished');
expect(suite.getResult().status).toBe('passed');
});
it("retrieves a result with pending status", function() {
@@ -90,41 +89,11 @@ describe("Suite", function() {
expect(suite.getResult().status).toBe('pending');
});
it("is executable if not pending", function() {
var suite = new jasmineUnderTest.Suite({});
expect(suite.isExecutable()).toBe(true);
});
it("is not executable if pending", function() {
var suite = new jasmineUnderTest.Suite({});
suite.pend();
expect(suite.isExecutable()).toBe(false);
});
it("tells all children about expectation failures, even if one throws", function() {
var suite = new jasmineUnderTest.Suite({}),
child1 = { addExpectationResult: jasmine.createSpy('child1#expectationResult'), result: {} },
child2 = { addExpectationResult: jasmine.createSpy('child2#expectationResult'), result: {} };
suite.addChild(child1);
suite.addChild(child2);
child1.addExpectationResult.and.throwError('foo');
suite.addExpectationResult('stuff');
expect(child1.addExpectationResult).toHaveBeenCalledWith('stuff');
expect(child2.addExpectationResult).toHaveBeenCalledWith('stuff');
});
it("throws an ExpectationFailed when receiving a failed expectation in an afterAll when throwOnExpectationFailure is set", function() {
it("throws an ExpectationFailed when receiving a failed expectation when throwOnExpectationFailure is set", function() {
var suite = new jasmineUnderTest.Suite({
expectationResultFactory: function(data) { return data; },
throwOnExpectationFailure: true
});
suite.addChild({ result: { status: 'done' } });
expect(function() {
suite.addExpectationResult(false, 'failed');
@@ -134,15 +103,27 @@ describe("Suite", function() {
expect(suite.result.failedExpectations).toEqual(['failed']);
});
it("does not add an additional failure when an expectation fails in an afterAll", function(){
it("does not add an additional failure when an expectation fails", function(){
var suite = new jasmineUnderTest.Suite({});
suite.addChild({ result: { status: 'done' } });
suite.onException(new jasmineUnderTest.errors.ExpectationFailed());
expect(suite.getResult().failedExpectations).toEqual([]);
});
it("calls timer to compute duration", function(){
var env = new jasmineUnderTest.Env(),
suite = new jasmineUnderTest.Suite({
env: env,
id: 456,
description: "I am a suite",
timer: jasmine.createSpyObj('timer', {'start': null, elapsed: 77000}),
});
suite.startTimer();
suite.endTimer();
expect(suite.getResult().duration).toEqual(77000);
});
describe('#sharedUserContext', function() {
beforeEach(function() {
this.suite = new jasmineUnderTest.Suite({});

View File

@@ -8,27 +8,24 @@ describe("TreeProcessor", function() {
this.canBeReentered = function() {
return !attrs.noReenter;
};
this.isExecutable = function() {
return attrs.executable !== false;
};
this.markedPending = attrs.markedPending || false;
this.sharedUserContext = function() {
return attrs.userContext || {};
};
this.getResult = jasmine.createSpy(this.id + '#execute');
this.beforeAllFns = attrs.beforeAllFns || [];
this.afterAllFns = attrs.afterAllFns || [];
this.cleanupBeforeAfter = function() { };
}
function Leaf(attrs) {
attrs = attrs || {};
this.id = 'leaf' + leafNumber++;
this.isExecutable = function() {
return attrs.executable !== false;
};
this.markedPending = attrs.markedPending || false;
this.execute = jasmine.createSpy(this.id + '#execute');
}
it("processes a single executable leaf", function() {
it("processes a single leaf", function() {
var leaf = new Leaf(),
processor = new jasmineUnderTest.TreeProcessor({ tree: leaf, runnableIds: [leaf.id] }),
result = processor.processTree();
@@ -36,20 +33,22 @@ describe("TreeProcessor", function() {
expect(result.valid).toBe(true);
expect(result[leaf.id]).toEqual({
executable: true,
excluded: false,
willExecute: true,
segments: jasmine.any(Array)
});
});
it("processes a single non-executable leaf", function() {
var leaf = new Leaf({ executable: false }),
it("processes a single pending leaf", function() {
var leaf = new Leaf({ markedPending: true }),
processor = new jasmineUnderTest.TreeProcessor({ tree: leaf, runnableIds: [leaf.id] }),
result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[leaf.id]).toEqual({
executable: false,
excluded: false,
willExecute: false,
segments: jasmine.any(Array)
});
});
@@ -62,7 +61,26 @@ describe("TreeProcessor", function() {
expect(result.valid).toBe(true);
expect(result[leaf.id]).toEqual({
executable: false,
excluded: true,
willExecute: false,
segments: jasmine.any(Array)
});
});
it("processes a single excluded leaf", function() {
var leaf = new Leaf(),
processor = new jasmineUnderTest.TreeProcessor({
tree: leaf,
runnableIds: [leaf.id],
excludeNode: function(node) { return true; }
}),
result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[leaf.id]).toEqual({
excluded: true,
willExecute: false,
segments: jasmine.any(Array)
});
});
@@ -76,18 +94,20 @@ describe("TreeProcessor", function() {
expect(result.valid).toBe(true);
expect(result[parent.id]).toEqual({
executable: true,
excluded: false,
willExecute: true,
segments: jasmine.any(Array)
});
expect(result[leaf.id]).toEqual({
executable: true,
excluded: false,
willExecute: true,
segments: jasmine.any(Array)
});
});
it("processes a tree with a single non-executable leaf, with the root specified", function() {
var leaf = new Leaf({ executable: false }),
it("processes a tree with a single pending leaf, with the root specified", function() {
var leaf = new Leaf({ markedPending: true }),
parent = new Node({ children: [leaf] }),
processor = new jasmineUnderTest.TreeProcessor({ tree: parent, runnableIds: [parent.id] }),
result = processor.processTree();
@@ -95,61 +115,77 @@ describe("TreeProcessor", function() {
expect(result.valid).toBe(true);
expect(result[parent.id]).toEqual({
executable: false,
excluded: false,
willExecute: false,
segments: jasmine.any(Array)
});
expect(result[leaf.id]).toEqual({
executable: false,
excluded: false,
willExecute: false,
segments: jasmine.any(Array)
});
});
it("processes a complicated tree with the root specified", function() {
var nonExecutable = new Leaf({ executable: false }),
executable = new Leaf({ executable: true }),
parent = new Node({ children: [nonExecutable, executable] }),
var pendingLeaf = new Leaf({ markedPending: true }),
executableLeaf = new Leaf({ markedPending: false }),
parent = new Node({ children: [pendingLeaf, executableLeaf] }),
childless = new Node(),
childOfDisabled = new Leaf({ executable: true }),
disabledNode = new Node({ executable: false, children: [childOfDisabled] }),
root = new Node({ children: [parent, childless, disabledNode] }),
childOfPending = new Leaf({ markedPending: true }),
pendingNode = new Node({ markedPending: true, children: [childOfPending] }),
parentOfPendings = new Node({ markedPending: false, children: [childless, pendingNode] }),
root = new Node({ children: [parent, parentOfPendings] }),
processor = new jasmineUnderTest.TreeProcessor({ tree: root, runnableIds: [root.id] }),
result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[root.id]).toEqual({
executable: true,
excluded: false,
willExecute: true,
segments: jasmine.any(Array)
});
expect(result[parentOfPendings.id]).toEqual({
excluded: false,
willExecute: false,
segments: jasmine.any(Array)
});
expect(result[childless.id]).toEqual({
executable: false,
excluded: false,
willExecute: false,
segments: jasmine.any(Array)
});
expect(result[nonExecutable.id]).toEqual({
executable: false,
expect(result[pendingLeaf.id]).toEqual({
excluded: false,
willExecute: false,
segments: jasmine.any(Array)
});
expect(result[executable.id]).toEqual({
executable: true,
expect(result[executableLeaf.id]).toEqual({
excluded: false,
willExecute: true,
segments: jasmine.any(Array)
});
expect(result[parent.id]).toEqual({
executable: true,
excluded: false,
willExecute: true,
segments: jasmine.any(Array)
});
expect(result[disabledNode.id]).toEqual({
executable: false,
expect(result[pendingNode.id]).toEqual({
excluded: false,
willExecute: false,
segments: jasmine.any(Array)
});
expect(result[childOfDisabled.id]).toEqual({
executable: false,
expect(result[childOfPending.id]).toEqual({
excluded: false,
willExecute: false,
segments: jasmine.any(Array)
});
});
@@ -218,7 +254,7 @@ describe("TreeProcessor", function() {
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn('foo');
expect(leaf.execute).toHaveBeenCalledWith('foo', true);
expect(leaf.execute).toHaveBeenCalledWith('foo', false);
});
it("runs a node with no children", function() {
@@ -248,19 +284,20 @@ describe("TreeProcessor", function() {
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn(nodeDone);
expect(nodeStart).toHaveBeenCalledWith(node);
expect(queueRunner).toHaveBeenCalledWith({
onComplete: jasmine.any(Function),
queueableFns: [],
queueableFns: [{ fn: jasmine.any(Function) }],
userContext: { node: 'context' },
onException: jasmine.any(Function)
});
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn('foo');
expect(nodeStart).toHaveBeenCalledWith(node, 'foo');
node.getResult.and.returnValue({ my: 'result' });
queueRunner.calls.mostRecent().args[0].onComplete();
expect(nodeComplete).toHaveBeenCalledWith(node, { my: 'result' });
expect(nodeDone).toHaveBeenCalled();
expect(nodeComplete).toHaveBeenCalledWith(node, { my: 'result' }, jasmine.any(Function));
});
it("runs a node with children", function() {
@@ -282,25 +319,56 @@ describe("TreeProcessor", function() {
queueableFns[0].fn(nodeDone);
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns.length).toBe(2);
expect(queueableFns.length).toBe(3);
queueableFns[0].fn('foo');
expect(leaf1.execute).toHaveBeenCalledWith('foo', true);
queueableFns[1].fn('foo');
expect(leaf1.execute).toHaveBeenCalledWith('foo', false);
queueableFns[1].fn('bar');
expect(leaf2.execute).toHaveBeenCalledWith('bar', true);
queueableFns[2].fn('bar');
expect(leaf2.execute).toHaveBeenCalledWith('bar', false);
});
it("runs a disabled node", function() {
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], executable: false }),
node = new Node({ children: [leaf1] }),
root = new Node({ children: [node] }),
queueRunner = jasmine.createSpy('queueRunner'),
nodeStart = jasmine.createSpy('nodeStart'),
nodeComplete = jasmine.createSpy('nodeComplete'),
processor = new jasmineUnderTest.TreeProcessor({
tree: root,
runnableIds: [node.id],
runnableIds: [],
queueRunnerFactory: queueRunner,
nodeStart: nodeStart,
nodeComplete: nodeComplete
@@ -312,18 +380,19 @@ describe("TreeProcessor", function() {
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
queueableFns[0].fn(nodeDone);
expect(nodeStart).toHaveBeenCalledWith(node);
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns.length).toBe(1);
expect(queueableFns.length).toBe(2);
queueableFns[0].fn('foo');
expect(leaf1.execute).toHaveBeenCalledWith('foo', false);
queueableFns[0].fn('bar');
expect(nodeStart).toHaveBeenCalledWith(node, 'bar');
queueableFns[1].fn('foo');
expect(leaf1.execute).toHaveBeenCalledWith('foo', true);
node.getResult.and.returnValue({ im: 'disabled' });
queueRunner.calls.mostRecent().args[0].onComplete();
expect(nodeComplete).toHaveBeenCalledWith(node, { im: 'disabled' });
expect(nodeComplete).toHaveBeenCalledWith(node, { im: 'disabled' }, jasmine.any(Function));
});
it("runs beforeAlls for a node with children", function() {
@@ -348,7 +417,7 @@ describe("TreeProcessor", function() {
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns).toEqual(['beforeAll1', 'beforeAll2', { fn: jasmine.any(Function) }]);
expect(queueableFns).toEqual([{ fn: jasmine.any(Function) }, 'beforeAll1', 'beforeAll2', { fn: jasmine.any(Function) }]);
});
it("runs afterAlls for a node with children", function() {
@@ -373,7 +442,7 @@ describe("TreeProcessor", function() {
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns).toEqual([{ fn: jasmine.any(Function) }, 'afterAll1', 'afterAll2']);
expect(queueableFns).toEqual([{ fn: jasmine.any(Function) }, { fn: jasmine.any(Function) }, 'afterAll1', 'afterAll2']);
});
it("does not run beforeAlls or afterAlls for a node with no children", function() {
@@ -397,16 +466,16 @@ describe("TreeProcessor", function() {
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns).toEqual([]);
expect(queueableFns).toEqual([{fn: jasmine.any(Function)}]);
});
it("does not run beforeAlls or afterAlls for a disabled node", function() {
var leaf = new Leaf(),
it("does not run beforeAlls or afterAlls for a node with only pending children", function() {
var leaf = new Leaf({ markedPending: true }),
node = new Node({
children: [leaf],
beforeAllFns: ['before'],
afterAllFns: ['after'],
executable: false
markedPending: false
}),
root = new Node({ children: [node] }),
queueRunner = jasmine.createSpy('queueRunner'),
@@ -424,7 +493,7 @@ describe("TreeProcessor", function() {
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns).toEqual([{ fn: jasmine.any(Function) }]);
expect(queueableFns).toEqual([{ fn: jasmine.any(Function) }, { fn: jasmine.any(Function) }]);
});
it("runs leaves in the order specified", function() {
@@ -451,7 +520,7 @@ describe("TreeProcessor", function() {
expect(leaf1.execute).toHaveBeenCalled();
});
it("runs specified leaves before non-specified leaves", function() {
it("runs specified leaves before non-specified leaves within a parent node", function() {
var specified = new Leaf(),
nonSpecified = new Leaf(),
root = new Node({ children: [nonSpecified, specified] }),
@@ -468,11 +537,11 @@ describe("TreeProcessor", function() {
queueableFns[0].fn();
expect(nonSpecified.execute).not.toHaveBeenCalled();
expect(specified.execute).toHaveBeenCalledWith(undefined, true);
expect(specified.execute).toHaveBeenCalledWith(undefined, false);
queueableFns[1].fn();
expect(nonSpecified.execute).toHaveBeenCalledWith(undefined, false);
expect(nonSpecified.execute).toHaveBeenCalledWith(undefined, true);
});
it("runs nodes and leaves with a specified order", function() {
@@ -493,7 +562,7 @@ describe("TreeProcessor", function() {
expect(specifiedLeaf.execute).not.toHaveBeenCalled();
var nodeQueueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
nodeQueueableFns[0].fn();
nodeQueueableFns[1].fn();
expect(childLeaf.execute).toHaveBeenCalled();
@@ -522,8 +591,8 @@ describe("TreeProcessor", function() {
expect(queueableFns.length).toBe(5);
queueableFns[0].fn();
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(2);
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
expect(leaf1.execute).toHaveBeenCalled();
queueableFns[1].fn();
@@ -531,8 +600,8 @@ describe("TreeProcessor", function() {
queueableFns[2].fn();
expect(queueRunner.calls.count()).toBe(3);
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(2);
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
expect(leaf2.execute).toHaveBeenCalled();
queueableFns[3].fn();
@@ -540,8 +609,8 @@ describe("TreeProcessor", function() {
queueableFns[4].fn();
expect(queueRunner.calls.count()).toBe(4);
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(2);
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
expect(leaf3.execute).toHaveBeenCalled();
});
@@ -567,12 +636,12 @@ describe("TreeProcessor", function() {
queueableFns[0].fn();
expect(queueRunner.calls.count()).toBe(2);
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(2);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
expect(queueRunner.calls.count()).toBe(3);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
expect(leaf1.execute).toHaveBeenCalled();
queueableFns[1].fn();
@@ -580,12 +649,12 @@ describe("TreeProcessor", function() {
queueableFns[2].fn();
expect(queueRunner.calls.count()).toBe(4);
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(2);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
expect(queueRunner.calls.count()).toBe(5);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
expect(leaf2.execute).toHaveBeenCalled();
queueableFns[3].fn();
@@ -593,12 +662,12 @@ describe("TreeProcessor", function() {
queueableFns[4].fn();
expect(queueRunner.calls.count()).toBe(6);
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(2);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
expect(queueRunner.calls.count()).toBe(7);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
queueRunner.calls.mostRecent().args[0].queueableFns[1].fn();
expect(leaf3.execute).toHaveBeenCalled();
});
@@ -625,11 +694,11 @@ describe("TreeProcessor", function() {
queueableFns[1].fn();
var childFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(childFns.length).toBe(2);
childFns[0].fn();
expect(childFns.length).toBe(3);
childFns[1].fn();
expect(leaf2.execute).toHaveBeenCalled();
childFns[1].fn();
childFns[2].fn();
expect(leaf3.execute).toHaveBeenCalled();
});
@@ -691,7 +760,7 @@ describe("TreeProcessor", function() {
expect(leaf11.execute).toHaveBeenCalled();
});
it("runs nodes in a custom order when orderChildren is overrided", function() {
it("runs nodes in a custom order when orderChildren is overridden", function() {
var leaf1 = new Leaf(),
leaf2 = new Leaf(),
leaf3 = new Leaf(),

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;
@@ -43,9 +142,6 @@ describe("jasmineUnderTest.util", function() {
});
describe("getPropertyDescriptor", function() {
// IE 8 doesn't support `definePropery` on non-DOM nodes
if (jasmine.getEnv().ieVersion < 9) { return; }
it("get property descriptor from object", function() {
var obj = {prop: 1},
actual = jasmineUnderTest.util.getPropertyDescriptor(obj, 'prop'),
@@ -94,6 +190,15 @@ describe("jasmineUnderTest.util", function() {
expect(jasmineUnderTest.util.objectDifference(a, b)).toEqual({x: 1});
expect(jasmineUnderTest.util.objectDifference(b, a)).toEqual({y: 2});
})
})
});
});
describe("jasmineFile", function() {
it("returns the file containing jasmine.util", function() {
// Chrome sometimes reports foo.js as foo.js/, so tolerate
// a trailing slash if present.
expect(jasmineUnderTest.util.jasmineFile()).toMatch(/util.js\/?$/);
expect(jasmine.util.jasmineFile()).toMatch(/jasmine.js\/?$/);
});
});
});

View File

@@ -68,10 +68,17 @@ describe("Any", function() {
expect(any.asymmetricMatch(new Thing())).toBe(true);
});
it("does not treat null as an Object", function() {
var any = new jasmineUnderTest.Any(Object);
expect(any.asymmetricMatch(null)).toBe(false);
});
it("jasmineToString's itself", function() {
var any = new jasmineUnderTest.Any(Number);
expect(any.jasmineToString()).toEqual('<jasmine.any(Number)>');
expect(any.jasmineToString()).toEqual('<jasmine.any(Number)>');
});
describe("when called without an argument", function() {

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

@@ -57,9 +57,6 @@ describe("ObjectContaining", function() {
});
it("matches defined properties", function(){
// IE 8 doesn't support `definePropery` on non-DOM nodes
if (jasmine.getEnv().ieVersion < 9) { return; }
var containing = new jasmineUnderTest.ObjectContaining({ foo: "fooVal" });
var definedPropertyObject = {};

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);
});
});

30
spec/core/baseSpec.js Normal file
View File

@@ -0,0 +1,30 @@
describe('base helpers', function() {
describe('isError_', function() {
it("correctly handles WebSocket events", function(done) {
if (typeof jasmine.getGlobal().WebSocket === 'undefined') {
done();
return;
}
var obj = (function() {
var sock = new WebSocket('ws://localhost');
var event;
sock.onerror = function(e) {
event = e
};
return function() { return event };
})();
var left = 20;
var int = setInterval(function() {
if (obj() || left === 0) {
var result = jasmineUnderTest.isError_(obj());
expect(result).toBe(false);
done();
} else {
left--;
}
}, 100);
});
});
});

View File

@@ -4,6 +4,7 @@ describe("Custom Matchers (Integration)", function() {
beforeEach(function() {
env = new jasmineUnderTest.Env();
env.configure({random: false});
});
it("allows adding more matchers local to a spec", function(done) {
@@ -120,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

@@ -0,0 +1,138 @@
describe('Custom Spy Strategies (Integration)', function() {
var env;
beforeEach(function() {
env = new jasmineUnderTest.Env();
env.configure({random: false});
});
it('allows adding more strategies local to a suite', function(done) {
var plan = jasmine.createSpy('custom strategy plan')
.and.returnValue(42);
var strategy = jasmine.createSpy('custom strategy')
.and.returnValue(plan);
env.describe('suite defining a custom spy strategy', function() {
env.beforeEach(function() {
env.addSpyStrategy('frobnicate', strategy);
});
env.it('spec in the suite', function() {
var spy = env.createSpy('something').and.frobnicate(17);
expect(spy(1, 2, 3)).toEqual(42);
expect(strategy).toHaveBeenCalledWith(17);
expect(plan).toHaveBeenCalledWith(1, 2, 3);
});
});
env.it('spec without custom strategy defined', function() {
expect(env.createSpy('something').and.frobnicate).toBeUndefined();
});
function jasmineDone(result) {
expect(result.overallStatus).toEqual('passed');
done();
}
env.addReporter({ jasmineDone: jasmineDone });
env.execute();
});
it('allows adding more strategies local to a spec', function(done) {
var plan = jasmine.createSpy('custom strategy plan')
.and.returnValue(42);
var strategy = jasmine.createSpy('custom strategy')
.and.returnValue(plan);
env.it('spec defining a custom spy strategy', function() {
env.addSpyStrategy('frobnicate', strategy);
var spy = env.createSpy('something').and.frobnicate(17);
expect(spy(1, 2, 3)).toEqual(42);
expect(strategy).toHaveBeenCalledWith(17);
expect(plan).toHaveBeenCalledWith(1, 2, 3);
});
env.it('spec without custom strategy defined', function() {
expect(env.createSpy('something').and.frobnicate).toBeUndefined();
});
function jasmineDone(result) {
expect(result.overallStatus).toEqual('passed');
done();
}
env.addReporter({ jasmineDone: jasmineDone });
env.execute();
});
it('allows using custom strategies on a per-argument basis', function(done) {
var plan = jasmine.createSpy('custom strategy plan')
.and.returnValue(42);
var strategy = jasmine.createSpy('custom strategy')
.and.returnValue(plan);
env.it('spec defining a custom spy strategy', function() {
env.addSpyStrategy('frobnicate', strategy);
var spy = env.createSpy('something')
.and.returnValue('no args return')
.withArgs(1, 2, 3).and.frobnicate(17);
expect(spy()).toEqual('no args return');
expect(plan).not.toHaveBeenCalled();
expect(spy(1, 2, 3)).toEqual(42);
expect(plan).toHaveBeenCalledWith(1, 2, 3);
});
env.it('spec without custom strategy defined', function() {
expect(env.createSpy('something').and.frobnicate).toBeUndefined();
});
function jasmineDone(result) {
expect(result.overallStatus).toEqual('passed');
done();
}
env.addReporter({ jasmineDone: jasmineDone });
env.execute();
});
it('allows multiple custom strategies to be used', function(done) {
var plan1 = jasmine.createSpy('plan 1').and.returnValue(42),
strategy1 = jasmine.createSpy('strat 1').and.returnValue(plan1),
plan2 = jasmine.createSpy('plan 2').and.returnValue(24),
strategy2 = jasmine.createSpy('strat 2').and.returnValue(plan2),
specDone = jasmine.createSpy('specDone');
env.beforeEach(function() {
env.addSpyStrategy('frobnicate', strategy1);
env.addSpyStrategy('jiggle', strategy2);
});
env.it('frobnicates', function() {
plan1.calls.reset();
plan2.calls.reset();
var spy = env.createSpy('spy').and.frobnicate();
expect(spy()).toEqual(42);
expect(plan1).toHaveBeenCalled();
expect(plan2).not.toHaveBeenCalled();
});
env.it('jiggles', function() {
plan1.calls.reset();
plan2.calls.reset();
var spy = env.createSpy('spy').and.jiggle();
expect(spy()).toEqual(24);
expect(plan1).not.toHaveBeenCalled();
expect(plan2).toHaveBeenCalled();
});
function jasmineDone(result) {
expect(result.overallStatus).toEqual('passed');
expect(specDone.calls.count()).toBe(2);
done();
}
env.addReporter({ jasmineDone: jasmineDone, specDone: specDone });
env.execute();
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,10 @@
describe("jasmine spec running", function () {
describe("spec running", function () {
var env;
beforeEach(function() {
jasmine.getEnv().registerIntegrationMatchers();
env = new jasmineUnderTest.Env();
env.configure({random: false});
});
it('should assign spec ids sequentially', function() {
@@ -600,18 +602,16 @@ describe("jasmine spec running", function () {
it("should recover gracefully when there are errors in describe functions", function(done) {
var specs = [],
reporter = jasmine.createSpyObj(['specDone', 'jasmineDone']);
reporter = jasmine.createSpyObj(['specDone', 'suiteDone', 'jasmineDone']);
reporter.specDone.and.callFake(function(result) {
specs.push(result.fullName);
});
reporter.jasmineDone.and.callFake(function() {
expect(specs).toContain('outer1 inner1 should thingy');
expect(specs).toContain('outer1 inner1 encountered a declaration exception');
expect(specs).toContain('outer1 inner2 should other thingy');
expect(specs).toContain('outer1 encountered a declaration exception');
expect(specs).toContain('outer2 should xxx');
expect(specs).toEqual(['outer1 inner1 should thingy', 'outer1 inner2 should other thingy', 'outer2 should xxx']);
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('outer1 inner1', [/inner error/]);
expect(reporter.suiteDone).toHaveFailedExpectationsForRunnable('outer1', [/outer error/]);
done();
});
@@ -622,7 +622,7 @@ describe("jasmine spec running", function () {
this.expect(true).toEqual(true);
});
throw new Error("fake error");
throw new Error("inner error");
});
env.describe("inner2", function() {
@@ -631,7 +631,7 @@ describe("jasmine spec running", function () {
});
});
throw new Error("fake error");
throw new Error("outer error");
});
}).not.toThrow();
@@ -740,8 +740,7 @@ describe("jasmine spec running", function () {
it("should run the tests in a consistent order when a seed is supplied", function(done) {
var actions = [];
env.randomizeTests(true);
env.seed('123456');
env.configure({random: true, seed: '123456'});
env.beforeEach(function () {
actions.push('topSuite beforeEach');
@@ -865,7 +864,7 @@ describe("jasmine spec running", function () {
});
});
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
var assertions = function() {
expect(actions).toEqual([
@@ -900,7 +899,7 @@ describe("jasmine spec running", function () {
});
});
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
var assertions = function() {
expect(actions).toEqual([
@@ -932,7 +931,7 @@ describe("jasmine spec running", function () {
});
});
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
var assertions = function() {
expect(actions).toEqual([
@@ -946,5 +945,184 @@ describe("jasmine 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.describe('wrapper', function() {
env.it('fails', function() {
actions.push('fails');
env.expect(1).toBe(2);
});
});
env.describe('holder', function() {
env.it('does not run', function() {
actions.push('does not run');
});
});
env.configure({random: false, failFast: true});
var assertions = function() {
expect(actions).toEqual(['fails']);
done();
};
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 = {},
@@ -156,8 +156,6 @@ describe("matchersUtil", function() {
});
it("passes for equivalent frozen objects (GitHub issue #266)", function() {
if (jasmine.getEnv().ieVersion < 9) { return; }
var a = { foo: 1 },
b = {foo: 1 };
@@ -201,10 +199,6 @@ describe("matchersUtil", function() {
if (isNotRunningInBrowser()) {
return;
}
// iframe.contentWindow.eval isn't supported in ie8
if (jasmine.getEnv().ieVersion < 9) {
return;
}
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.contentWindow.eval('window.testObject = {}');
@@ -217,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);
@@ -366,8 +360,6 @@ describe("matchersUtil", function() {
});
it("passes for null prototype objects with same properties", function () {
if (jasmine.getEnv().ieVersion < 9) { return; }
var objA = Object.create(null),
objB = Object.create(null);
@@ -378,8 +370,6 @@ describe("matchersUtil", function() {
});
it("fails for null prototype objects with different properties", function () {
if (jasmine.getEnv().ieVersion < 9) { return; }
var objA = Object.create(null),
objB = Object.create(null);
@@ -535,9 +525,6 @@ describe("matchersUtil", function() {
});
describe("when running in an environment with array polyfills", function() {
// IE 8 doesn't support `definePropery` on non-DOM nodes
if (jasmine.getEnv().ieVersion < 9) { return; }
var findIndexDescriptor = Object.getOwnPropertyDescriptor(Array.prototype, 'findIndex');
if (!findIndexDescriptor) {
return;

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);
});
@@ -299,22 +299,7 @@ describe("toEqual", function() {
expect(compareEquals(actual, expected).message).toEqual(message);
});
function constructorIsNotEnumerable() {
// in IE8, the constructor property is not enumerable, even if it is an
// own property of the object.
// Objects that differ only by an own `constructor` property are thus
// considered equal in IE8.
for (var key in {constructor: 1}) {
return false;
}
return true;
}
it("reports mismatches between objects with their own constructor property", function () {
if (constructorIsNotEnumerable()) {
return;
}
function Foo() {}
function Bar() {}
@@ -326,10 +311,6 @@ describe("toEqual", function() {
});
it("reports mismatches between an object with a real constructor and one with its own constructor property", function () {
if (constructorIsNotEnumerable()) {
return;
}
function Foo() {}
function Bar() {}
@@ -589,50 +570,152 @@ 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')},
message = 'Expected $.a = HTMLNode to equal HTMLNode.';
beforeEach(function() {
this.nonBrowser = isNotRunningInBrowser();
if (this.nonBrowser) {
var JSDOM = require('jsdom').JSDOM;
var dom = new JSDOM();
jasmineUnderTest.getGlobal().Node = dom.window.Node;
this.doc = dom.window.document;
} else {
this.doc = document;
}
});
expect(compareEquals(actual, expected).message).toEqual(message);
});
afterEach(function() {
if (this.nonBrowser) {
delete jasmineUnderTest.getGlobal().Node;
}
});
it('reports mismatches between DOM nodes with different content', function() {
if(isNotRunningInBrowser()) {
return;
}
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>.';
var nodeA = document.createElement('div'),
nodeB = document.createElement('div');
expect(compareEquals(actual, expected).message).toEqual(message);
});
nodeA.innerText = 'foo'
nodeB.innerText = 'bar'
it('reports mismatches between DOM nodes with different content', function() {
var nodeA = this.doc.createElement('div'),
nodeB = this.doc.createElement('div');
var actual = {a: nodeA},
nodeA.setAttribute('thing', 'foo');
nodeB.setAttribute('thing', 'bar');
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = HTMLNode to equal HTMLNode.';
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;
}
it("reports mismatches between SVG nodes", function () {
var nodeA = this.doc.createElementNS('http://www.w3.org/2000/svg', 'svg'),
nodeB = this.doc.createElementNS('http://www.w3.org/2000/svg', 'svg');
var actual = {a: document.createElement('div')},
nodeA.setAttribute('height', '50');
nodeB.setAttribute('height', '30');
var rect = this.doc.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute('width', '50');
nodeA.appendChild(rect);
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = <svg height="50">...</svg> to equal <svg height="30">.';
expect(compareEquals(actual, expected).message).toEqual(message);
});
it("reports whole DOM node when attribute contains > character", function () {
var nodeA = this.doc.createElement('div'),
nodeB = this.doc.createElement('div');
nodeA.setAttribute('thing', '>>>');
nodeB.setAttribute('thing', 'bar');
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = <div thing=">>>"> to equal <div thing="bar">.';
expect(compareEquals(actual, expected).message).toEqual(message);
});
it('reports no content when DOM node has multiple empty text nodes', function () {
var nodeA = this.doc.createElement('div'),
nodeB = this.doc.createElement('div');
nodeA.appendChild(this.doc.createTextNode(''));
nodeA.appendChild(this.doc.createTextNode(''));
nodeA.appendChild(this.doc.createTextNode(''));
nodeA.appendChild(this.doc.createTextNode(''));
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = <div> to equal <div>.';
expect(compareEquals(actual, expected).message).toEqual(message);
});
it('reports content when DOM node has non empty text node', function () {
var nodeA = this.doc.createElement('div'),
nodeB = this.doc.createElement('div');
nodeA.appendChild(this.doc.createTextNode('Hello Jasmine!'));
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = <div>...</div> to equal <div>.';
expect(compareEquals(actual, expected).message).toEqual(message);
});
it('reports empty DOM attributes', function () {
var nodeA = this.doc.createElement('div'),
nodeB = this.doc.createElement('div');
nodeA.setAttribute('contenteditable', '');
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = <div contenteditable> to equal <div>.';
expect(compareEquals(actual, expected).message).toEqual(message);
});
it('reports 0 attr value as non empty DOM attribute', function () {
var nodeA = this.doc.createElement('div'),
nodeB = this.doc.createElement('div');
nodeA.setAttribute('contenteditable', 0);
expect(nodeA.isEqualNode(nodeB)).toBe(false);
var actual = {a: nodeA},
expected = {a: nodeB},
message = 'Expected $.a = <div contenteditable="0"> to equal <div>.';
expect(compareEquals(actual, expected).message).toEqual(message);
});
it("reports mismatches between a DOM node and a bare Object", function() {
var actual = {a: this.doc.createElement('div')},
expected = {a: {}},
message = 'Expected $.a = HTMLNode to equal Object({ }).';
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() {
@@ -677,7 +760,7 @@ describe("toEqual", function() {
boolean: false,
notDefined: 0,
aNull: void 0
}
};
var expected = {
foo: [
@@ -694,7 +777,7 @@ describe("toEqual", function() {
boolean: true,
notDefined: void 0,
aNull: null
}
};
var message =
'Expected $.foo[0].bar = 1 to equal 2.\n' +
@@ -709,19 +792,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);
});
@@ -731,7 +814,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);
});
@@ -744,7 +858,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);
});
@@ -755,27 +869,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);
});
@@ -786,9 +920,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);
});
@@ -797,7 +931,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

@@ -2,14 +2,14 @@ describe("toHaveBeenCalledBefore", function() {
it("throws an exception when the actual is not a spy", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
fn = function() {},
secondSpy = jasmineUnderTest.createSpy('second spy');
secondSpy = new jasmineUnderTest.Env().createSpy('second spy');
expect(function() { matcher.compare(fn, secondSpy) }).toThrowError(Error, /Expected a spy, but got Function./);
});
it("throws an exception when the expected is not a spy", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
firstSpy = jasmineUnderTest.createSpy('first spy'),
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
fn = function() {};
expect(function() { matcher.compare(firstSpy, fn) }).toThrowError(Error, /Expected a spy, but got Function./);
@@ -17,8 +17,8 @@ describe("toHaveBeenCalledBefore", function() {
it("fails when the actual was not called", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
firstSpy = jasmineUnderTest.createSpy('first spy'),
secondSpy = jasmineUnderTest.createSpy('second spy');
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
secondSpy = new jasmineUnderTest.Env().createSpy('second spy');
secondSpy();
@@ -29,8 +29,8 @@ describe("toHaveBeenCalledBefore", function() {
it("fails when the expected was not called", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
firstSpy = jasmineUnderTest.createSpy('first spy'),
secondSpy = jasmineUnderTest.createSpy('second spy');
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
secondSpy = new jasmineUnderTest.Env().createSpy('second spy');
firstSpy();
@@ -41,8 +41,8 @@ describe("toHaveBeenCalledBefore", function() {
it("fails when the actual is called after the expected", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
firstSpy = jasmineUnderTest.createSpy('first spy'),
secondSpy = jasmineUnderTest.createSpy('second spy'),
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
secondSpy = new jasmineUnderTest.Env().createSpy('second spy'),
result;
secondSpy();
@@ -55,8 +55,8 @@ describe("toHaveBeenCalledBefore", function() {
it("fails when the actual is called before and after the expected", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
firstSpy = jasmineUnderTest.createSpy('first spy'),
secondSpy = jasmineUnderTest.createSpy('second spy'),
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
secondSpy = new jasmineUnderTest.Env().createSpy('second spy'),
result;
firstSpy();
@@ -70,8 +70,8 @@ describe("toHaveBeenCalledBefore", function() {
it("fails when the expected is called before and after the actual", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
firstSpy = jasmineUnderTest.createSpy('first spy'),
secondSpy = jasmineUnderTest.createSpy('second spy'),
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
secondSpy = new jasmineUnderTest.Env().createSpy('second spy'),
result;
secondSpy();
@@ -85,8 +85,8 @@ describe("toHaveBeenCalledBefore", function() {
it("passes when the actual is called before the expected", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
firstSpy = jasmineUnderTest.createSpy('first spy'),
secondSpy = jasmineUnderTest.createSpy('second spy'),
firstSpy = new jasmineUnderTest.Env().createSpy('first spy'),
secondSpy = new jasmineUnderTest.Env().createSpy('second spy'),
result;
firstSpy();

View File

@@ -1,7 +1,7 @@
describe("toHaveBeenCalled", function() {
it("passes when the actual was called, with a custom .not fail message", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalled(),
calledSpy = jasmineUnderTest.createSpy('called-spy'),
calledSpy = new jasmineUnderTest.Env().createSpy('called-spy'),
result;
calledSpy();
@@ -13,7 +13,7 @@ describe("toHaveBeenCalled", function() {
it("fails when the actual was not called", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalled(),
uncalledSpy = jasmineUnderTest.createSpy('uncalled spy'),
uncalledSpy = new jasmineUnderTest.Env().createSpy('uncalled spy'),
result;
result = matcher.compare(uncalledSpy);
@@ -29,14 +29,14 @@ describe("toHaveBeenCalled", function() {
it("throws an exception when invoked with any arguments", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalled(),
spy = jasmineUnderTest.createSpy('sample spy');
spy = new jasmineUnderTest.Env().createSpy('sample spy');
expect(function() { matcher.compare(spy, 'foo') }).toThrowError(Error, /Does not take arguments, use toHaveBeenCalledWith/);
});
it("has a custom message on failure", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalled(),
spy = jasmineUnderTest.createSpy('sample-spy'),
spy = new jasmineUnderTest.Env().createSpy('sample-spy'),
result;
result = matcher.compare(spy);

View File

@@ -1,14 +1,14 @@
describe("toHaveBeenCalledTimes", function() {
it("passes when the actual 0 matches the expected 0 ", function () {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
calledSpy = jasmineUnderTest.createSpy('called-spy'),
calledSpy = new jasmineUnderTest.Env().createSpy('called-spy'),
result;
result = matcher.compare(calledSpy, 0);
expect(result.pass).toBeTruthy();
});
it("passes when the actual matches the expected", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
calledSpy = jasmineUnderTest.createSpy('called-spy'),
calledSpy = new jasmineUnderTest.Env().createSpy('called-spy'),
result;
calledSpy();
@@ -18,7 +18,7 @@ describe("toHaveBeenCalledTimes", function() {
it("fails when expected numbers is not supplied", function(){
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
spy = jasmineUnderTest.createSpy('spy'),
spy = new jasmineUnderTest.Env().createSpy('spy'),
result;
spy();
@@ -29,7 +29,7 @@ describe("toHaveBeenCalledTimes", function() {
it("fails when the actual was called less than the expected", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
uncalledSpy = jasmineUnderTest.createSpy('uncalled spy'),
uncalledSpy = new jasmineUnderTest.Env().createSpy('uncalled spy'),
result;
result = matcher.compare(uncalledSpy, 2);
@@ -38,7 +38,7 @@ describe("toHaveBeenCalledTimes", function() {
it("fails when the actual was called more than expected", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
uncalledSpy = jasmineUnderTest.createSpy('uncalled spy'),
uncalledSpy = new jasmineUnderTest.Env().createSpy('uncalled spy'),
result;
uncalledSpy();
@@ -59,7 +59,7 @@ describe("toHaveBeenCalledTimes", function() {
it("has a custom message on failure that tells it was called only once", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
spy = jasmineUnderTest.createSpy('sample-spy'),
spy = new jasmineUnderTest.Env().createSpy('sample-spy'),
result;
spy();
spy();
@@ -72,7 +72,7 @@ describe("toHaveBeenCalledTimes", function() {
it("has a custom message on failure that tells how many times it was called", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
spy = jasmineUnderTest.createSpy('sample-spy'),
spy = new jasmineUnderTest.Env().createSpy('sample-spy'),
result;
spy();
spy();

View File

@@ -5,7 +5,7 @@ describe("toHaveBeenCalledWith", function() {
contains: jasmine.createSpy('delegated-contains').and.returnValue(true)
},
matcher = jasmineUnderTest.matchers.toHaveBeenCalledWith(util),
calledSpy = jasmineUnderTest.createSpy('called-spy'),
calledSpy = new jasmineUnderTest.Env().createSpy('called-spy'),
result;
calledSpy('a', 'b');
@@ -21,7 +21,7 @@ describe("toHaveBeenCalledWith", function() {
},
customEqualityTesters = [function() { return true; }],
matcher = jasmineUnderTest.matchers.toHaveBeenCalledWith(util, customEqualityTesters),
calledSpy = jasmineUnderTest.createSpy('called-spy');
calledSpy = new jasmineUnderTest.Env().createSpy('called-spy');
calledSpy('a', 'b');
matcher.compare(calledSpy, 'a', 'b');
@@ -34,7 +34,7 @@ describe("toHaveBeenCalledWith", function() {
contains: jasmine.createSpy('delegated-contains').and.returnValue(false)
},
matcher = jasmineUnderTest.matchers.toHaveBeenCalledWith(util),
uncalledSpy = jasmineUnderTest.createSpy('uncalled spy'),
uncalledSpy = new jasmineUnderTest.Env().createSpy('uncalled spy'),
result;
result = matcher.compare(uncalledSpy);
@@ -47,7 +47,7 @@ describe("toHaveBeenCalledWith", function() {
contains: jasmine.createSpy('delegated-contains').and.returnValue(false)
},
matcher = jasmineUnderTest.matchers.toHaveBeenCalledWith(util),
calledSpy = jasmineUnderTest.createSpy('called spy'),
calledSpy = new jasmineUnderTest.Env().createSpy('called spy'),
result;
calledSpy('a');

View File

@@ -0,0 +1,61 @@
describe('toHaveClass', function() {
beforeEach(function() {
this.createElementWithClassName = function(className) {
var el = this.doc.createElement('div');
el.className = className;
return el;
};
if (typeof document !== 'undefined') {
this.doc = document;
} else {
var JSDOM = require('jsdom').JSDOM;
var dom = new JSDOM();
this.doc = dom.window.document;
}
});
it('fails for a DOM element that lacks the expected class', function() {
var matcher = jasmineUnderTest.matchers.toHaveClass(),
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 = this.createElementWithClassName('foo bar baz');
expect(matcher.compare(el, 'foo').pass).toBe(true);
expect(matcher.compare(el, 'bar').pass).toBe(true);
expect(matcher.compare(el, 'bar').pass).toBe(true);
});
it('fails for a DOM element that only has other classes', function() {
var matcher = jasmineUnderTest.matchers.toHaveClass(),
el = this.createElementWithClassName('foo bar');
expect(matcher.compare(el, 'fo').pass).toBe(false);
});
it('throws an exception when actual is not a DOM element', function() {
var matcher = jasmineUnderTest.matchers.toHaveClass();
expect(function() {
matcher.compare('x', 'foo');
}).toThrowError("'x' is not a DOM element");
expect(function() {
matcher.compare(undefined, 'foo');
}).toThrowError('undefined is not a DOM element');
var textNode = this.doc.createTextNode('');
expect(function() {
matcher.compare(textNode, 'foo')
}).toThrowError('HTMLNode is not a DOM element');
expect(function() {
matcher.compare({classList: ''}, 'foo');
}).toThrowError("Object({ classList: '' }) is not a DOM element");
});
});

View File

@@ -79,7 +79,7 @@ describe("toThrowError", function() {
});
it("passes if thrown is an instanceof Error regardless of global that contains its constructor", function() {
if (isNotRunningInBrowser() || jasmine.getEnv().phantomVersion < 2 || jasmine.getEnv().ieVersion < 10) {
if (isNotRunningInBrowser()) {
return;
}
@@ -92,7 +92,7 @@ describe("toThrowError", function() {
iframeDocument.body.appendChild(iframeDocument.createElement("script"))
.textContent = "function method() { throw new Error('foo'); }";
} else {
// older IE
// IE 10 and older
iframeDocument.write("<html><head><script>function method() { throw new Error('foo'); }</script></head></html>");
}

View File

@@ -0,0 +1,73 @@
describe("toThrowMatching", function() {
it("throws an error when the actual is not a function", function() {
var matcher = jasmineUnderTest.matchers.toThrowMatching();
expect(function() {
matcher.compare({}, function() { return true; });
}).toThrowError(/Actual is not a Function/);
});
it("throws an error when the expected is not a function", function() {
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
fn = function() {
throw new Error("foo");
};
expect(function() {
matcher.compare(fn, 1);
}).toThrowError(/Predicate is not a Function/);
});
it("fails if actual does not throw at all", function() {
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
fn = function() {
return true;
},
result;
result = matcher.compare(fn, function() { return true; });
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw an exception.");
});
it("fails with the correct message if thrown is a falsy value", function() {
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
fn = function() {
throw undefined;
},
result;
result = matcher.compare(fn, function() { return false; });
expect(result.pass).toBe(false);
expect(result.message()).toEqual("Expected function to throw an exception matching a predicate, but it threw undefined.");
});
it("passes if the argument is a function that returns true when called with the error", function() {
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
predicate = function(e) { return e.message === "nope" },
fn = function() {
throw new TypeError("nope");
},
result;
result = matcher.compare(fn, predicate);
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected function not to throw an exception matching a predicate.");
});
it("fails if the argument is a function that returns false when called with the error", function() {
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
predicate = function(e) { return e.message === "oh no" },
fn = function() {
throw new TypeError("nope");
},
result;
result = matcher.compare(fn, predicate);
expect(result.pass).toBe(false);
expect(result.message()).toEqual("Expected function to throw an exception matching a predicate, but it threw TypeError with message 'nope'.");
});
});

View File

@@ -8,20 +8,8 @@
return match ? parseFloat(match[1]) : void 0;
}
env.ieVersion = browserVersion(function(userAgent) {
return /MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(userAgent);
});
env.safariVersion = browserVersion(function(userAgent) {
return /Safari/.exec(userAgent) && /Version\/([0-9]{0,})/.exec(userAgent);
});
env.firefoxVersion = browserVersion(function(userAgent) {
return /Firefox\/([0-9]{0,})/.exec(userAgent);
});
env.phantomVersion = browserVersion(function(userAgent) {
return /PhantomJS\/([0-9]{0,})/.exec(userAgent);
});
})(jasmine.getEnv());

View File

@@ -3,5 +3,4 @@
// to the Jasmine source files (and not jasmine.js). So re-require
window.jasmineUnderTest = jasmineRequire.core(jasmineRequire);
jasmineRequire.html(jasmineUnderTest);
jasmineRequire.console(jasmineRequire, jasmineUnderTest);
})();

View File

@@ -0,0 +1,43 @@
(function(env) {
env.registerIntegrationMatchers = function() {
jasmine.addMatchers({
toHaveFailedExpectationsForRunnable: function (util, customeEqualityTesters) {
return {
compare: function (actual, fullName, expectedFailures) {
var foundRunnable = false, expectations = true, foundFailures = [];
for (var i = 0; i < actual.calls.count(); i++) {
var args = actual.calls.argsFor(i)[0];
if (args.fullName === fullName) {
foundRunnable = true;
for (var j = 0; j < args.failedExpectations.length; j++) {
foundFailures.push(args.failedExpectations[j].message);
}
for (var j = 0; j < expectedFailures.length; j++) {
var failure = foundFailures[j];
var expectedFailure = expectedFailures[j];
if (Object.prototype.toString.call(expectedFailure) === '[object RegExp]') {
expectations = expectations && expectedFailure.test(failure);
} else {
expectations = expectations && failure === expectedFailure;
}
}
break;
}
}
return {
pass: foundRunnable && expectations,
message: !foundRunnable ? 'The runnable "' + fullName + '" never finished' :
'Expected runnable "' + fullName + '" to have failures ' + jasmine.pp(expectedFailures) + ' but it had ' + jasmine.pp(foundFailures)
};
}
};
}
});
};
})(jasmine.getEnv());

View File

@@ -1,8 +1,6 @@
(function() {
var path = require("path"),
fs = require("fs");
var glob = require("glob");
fg = require("fast-glob");
var jasmineUnderTestRequire = require(path.join(__dirname, "../../src/core/requireCore.js"));
@@ -16,18 +14,15 @@
}
function getSourceFiles() {
var src_files = ['core/**/*.js', 'console/**/*.js', 'version.js'];
src_files.forEach(function(file) {
var filePath = path.join(__dirname, "../../", 'src/', file);
glob.sync(filePath).forEach(function(resolvedFile) {
require(resolvedFile);
});
var src_files = ['core/**/*.js', 'version.js'].map(function(file) {
return path.join(__dirname, "../../", 'src/', file);
});
fg.sync(src_files).forEach(function(resolvedFile) {
require(resolvedFile);
});
}
extend(jasmineUnderTestRequire, require(path.join(__dirname,"../../src/console/requireConsole.js")));
getSourceFiles();
global.jasmineUnderTest = jasmineUnderTestRequire.core(jasmineUnderTestRequire);
jasmineUnderTestRequire.console(jasmineUnderTestRequire, jasmineUnderTest);
})();

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

@@ -1,4 +1,4 @@
describe("New HtmlReporter", function() {
describe("HtmlReporter", function() {
it("builds the initial DOM elements, including the title banner", function() {
var env = new jasmineUnderTest.Env(),
container = document.createElement("div"),
@@ -26,9 +26,8 @@ describe("New HtmlReporter", function() {
expect(title.getAttribute('href')).toEqual('http://jasmine.github.io/');
expect(title.getAttribute('target')).toEqual('_blank');
var version = banner.querySelector(".jasmine-version"),
versionText = 'textContent' in version ? version.textContent : version.innerText;
expect(versionText).toEqual(jasmineUnderTest.version);
var version = banner.querySelector(".jasmine-version");
expect(version.textContent).toEqual(jasmineUnderTest.version);
});
it("builds a single reporter even if initialized multiple times", function() {
@@ -93,7 +92,7 @@ describe("New HtmlReporter", function() {
expect(specEl.getAttribute("class")).toEqual("jasmine-empty");
});
it("reports the status symbol of a disabled spec", function() {
it("reports the status symbol of a excluded spec", function() {
var env = new jasmineUnderTest.Env(),
container = document.createElement("div"),
getContainer = function() { return container; },
@@ -104,11 +103,10 @@ describe("New HtmlReporter", function() {
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
});
reporter.initialize();
reporter.specDone({id: 789, status: "disabled", fullName: "symbols should have titles", passedExpectations: [], failedExpectations: []});
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-disabled");
expect(specEl.getAttribute("class")).toEqual("jasmine-excluded");
expect(specEl.getAttribute("id")).toEqual("spec_789");
expect(specEl.getAttribute("title")).toEqual("symbols should have titles");
});
@@ -178,36 +176,6 @@ describe("New HtmlReporter", function() {
});
});
describe("when there are suite failures", function () {
it("displays the exceptions in their own alert bars", 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); }
});
reporter.initialize();
reporter.jasmineStarted({});
reporter.suiteDone({ status: 'failed', failedExpectations: [{ message: 'My After All Exception' }] });
reporter.suiteDone({ status: 'failed', failedExpectations: [{ message: 'My Other Exception' }] });
reporter.jasmineDone({ failedExpectations: [{ message: 'Global After All Failure' }, { message: 'Other Global' }] });
var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
expect(alertBars.length).toEqual(5);
expect(alertBars[1].innerHTML).toMatch(/My After All Exception/);
expect(alertBars[1].getAttribute("class")).toEqual('jasmine-bar jasmine-errored');
expect(alertBars[2].innerHTML).toMatch(/My Other Exception/);
expect(alertBars[3].innerHTML).toMatch(/Global After All Failure/);
expect(alertBars[4].innerHTML).toMatch(/Other Global/);
});
});
describe('when there are deprecation warnings', function() {
it('displays the messages in their own alert bars', function() {
var env = new jasmineUnderTest.Env(),
@@ -306,7 +274,7 @@ describe("New HtmlReporter", function() {
reporter.jasmineStarted({});
timer.elapsed.and.returnValue(100);
reporter.jasmineDone();
reporter.jasmineDone({});
var duration = container.querySelector(".jasmine-alert .jasmine-duration");
expect(duration.innerHTML).toMatch(/finished in 0.1s/);
@@ -360,7 +328,12 @@ describe("New HtmlReporter", function() {
reporter.specStarted(specResult);
reporter.specDone(specResult);
reporter.suiteDone({id: 2});
reporter.suiteDone({
id: 2,
status: 'things',
description: "inner suite",
fullName: "A Suite inner suite"
});
specResult = {
id: 209,
@@ -373,7 +346,12 @@ describe("New HtmlReporter", function() {
reporter.specStarted(specResult);
reporter.specDone(specResult);
reporter.suiteDone({id: 1});
reporter.suiteDone({
id: 1,
status: 'things',
description: "A Suite",
fullName: "A Suite"
});
reporter.jasmineDone({});
var summary = container.querySelector(".jasmine-summary");
@@ -388,7 +366,7 @@ describe("New HtmlReporter", function() {
var node = outerSuite.childNodes[i];
classes.push(node.getAttribute("class"));
}
expect(classes).toEqual(["jasmine-suite-detail", "jasmine-specs", "jasmine-suite", "jasmine-specs"]);
expect(classes).toEqual(["jasmine-suite-detail jasmine-things", "jasmine-specs", "jasmine-suite", "jasmine-specs"]);
var suiteDetail = outerSuite.childNodes[0];
var suiteLink = suiteDetail.childNodes[0];
@@ -403,7 +381,6 @@ describe("New HtmlReporter", function() {
var specLink = spec.childNodes[0];
expect(specLink.innerHTML).toEqual("with a spec");
expect(specLink.getAttribute("href")).toEqual("?foo=bar&spec=A Suite with a spec");
// expect(specLink.getAttribute("title")).toEqual("A Suite with a spec");
});
it("has an options menu", function() {
@@ -429,43 +406,78 @@ describe("New HtmlReporter", function() {
var trigger = container.querySelector('.jasmine-run-options .jasmine-trigger'),
payload = container.querySelector('.jasmine-run-options .jasmine-payload');
expect(payload.className).not.toContain('jasmine-open');
expect(payload).not.toHaveClass('jasmine-open');
trigger.onclick();
expect(payload.className).toContain('jasmine-open');
expect(payload).toHaveClass('jasmine-open');
trigger.onclick();
expect(payload.className).not.toContain('jasmine-open');
expect(payload).not.toHaveClass('jasmine-open');
});
describe("UI for raising/catching exceptions", function() {
it("should be unchecked if the env is catching", function() {
describe("when there are global errors", function() {
it("displays the exceptions in their own alert bars", function(){
var env = new jasmineUnderTest.Env(),
container = document.createElement("div"),
getContainer = function() {
return container;
},
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);
}
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
});
reporter.initialize();
reporter.jasmineDone({});
var raisingExceptionsUI = container.querySelector(".jasmine-raise");
expect(raisingExceptionsUI.checked).toBe(false);
reporter.jasmineStarted({});
reporter.jasmineDone({ failedExpectations: [
{ message: 'Global After All Failure', globalErrorType: 'afterAll' },
{ message: 'Your JS is borken', globalErrorType: 'load' }
] });
var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
expect(alertBars.length).toEqual(3);
expect(alertBars[1].getAttribute("class")).toEqual('jasmine-bar jasmine-errored');
expect(alertBars[1].innerHTML).toMatch(/AfterAll Global After All Failure/);
expect(alertBars[2].innerHTML).toMatch(/Error during loading: Your JS is borken/);
expect(alertBars[2].innerHTML).not.toMatch(/line/);
});
it("should be checked if the env is not catching", function() {
it("displays file and line information if available", 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); }
});
reporter.initialize();
reporter.jasmineStarted({});
reporter.jasmineDone({ failedExpectations: [
{
message: 'Your JS is borken',
globalErrorType: 'load',
filename: 'some/file.js',
lineno: 42
}
] });
var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
expect(alertBars.length).toEqual(2);
expect(alertBars[1].innerHTML).toMatch(/Error during loading: Your JS is borken in some\/file.js line 42/);
});
});
describe("UI for stop on spec failure", function() {
it("should be unchecked for full execution", function() {
var env = new jasmineUnderTest.Env(),
container = document.createElement("div"),
getContainer = function() {
@@ -483,24 +495,49 @@ describe("New HtmlReporter", function() {
});
reporter.initialize();
env.catchExceptions(false);
reporter.jasmineDone({});
var raisingExceptionsUI = container.querySelector(".jasmine-raise");
expect(raisingExceptionsUI.checked).toBe(true);
var stopOnFailureUI = container.querySelector(".jasmine-fail-fast");
expect(stopOnFailureUI.checked).toBe(false);
});
it("should affect the query param for catching exceptions", function() {
it("should be checked if stopping short", function() {
var env = new jasmineUnderTest.Env(),
container = document.createElement("div"),
exceptionsClickHandler = jasmine.createSpy("raise exceptions checked"),
getContainer = function() {
return container;
},
reporter = new jasmineUnderTest.HtmlReporter({
env: env,
getContainer: getContainer,
onRaiseExceptionsClick: exceptionsClickHandler,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
env.configure({failFast: true});
reporter.initialize();
reporter.jasmineDone({});
var stopOnFailureUI = container.querySelector(".jasmine-fail-fast");
expect(stopOnFailureUI.checked).toBe(true);
});
it("should navigate and turn the setting on", function() {
var env = new jasmineUnderTest.Env(),
container = document.createElement("div"),
navigationHandler = jasmine.createSpy('navigate'),
getContainer = function() {
return container;
},
reporter = new jasmineUnderTest.HtmlReporter({
env: env,
navigateWithNewParam: navigationHandler,
getContainer: getContainer,
createElement: function() {
return document.createElement.apply(document, arguments);
},
@@ -512,9 +549,40 @@ describe("New HtmlReporter", function() {
reporter.initialize();
reporter.jasmineDone({});
var input = container.querySelector(".jasmine-raise");
input.click();
expect(exceptionsClickHandler).toHaveBeenCalled();
var stopOnFailureUI = container.querySelector(".jasmine-fail-fast");
stopOnFailureUI.click();
expect(navigationHandler).toHaveBeenCalledWith('failFast', true);
});
it("should navigate and turn the setting off", function() {
var env = new jasmineUnderTest.Env(),
container = document.createElement("div"),
navigationHandler = jasmine.createSpy('navigate'),
getContainer = function() {
return container;
},
reporter = new jasmineUnderTest.HtmlReporter({
env: env,
navigateWithNewParam: navigationHandler,
getContainer: getContainer,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
env.configure({failFast: true});
reporter.initialize();
reporter.jasmineDone({});
var stopOnFailureUI = container.querySelector(".jasmine-fail-fast");
stopOnFailureUI.click();
expect(navigationHandler).toHaveBeenCalledWith('failFast', false);
});
});
@@ -560,7 +628,7 @@ describe("New HtmlReporter", function() {
}
});
env.throwOnExpectationFailure(true);
env.configure({oneFailurePerSpec: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -569,17 +637,17 @@ describe("New HtmlReporter", function() {
expect(throwingExpectationsUI.checked).toBe(true);
});
it("should affect the query param for throw expectation failures", function() {
it("should navigate and change the setting to on", function() {
var env = new jasmineUnderTest.Env(),
container = document.createElement("div"),
throwingExceptionHandler = jasmine.createSpy('throwingExceptions'),
navigateHandler = jasmine.createSpy('navigate'),
getContainer = function() {
return container;
},
reporter = new jasmineUnderTest.HtmlReporter({
env: env,
getContainer: getContainer,
onThrowExpectationsClick: throwingExceptionHandler,
navigateWithNewParam: navigateHandler,
createElement: function() {
return document.createElement.apply(document, arguments);
},
@@ -594,10 +662,115 @@ describe("New HtmlReporter", function() {
var throwingExpectationsUI = container.querySelector(".jasmine-throw");
throwingExpectationsUI.click();
expect(throwingExceptionHandler).toHaveBeenCalled();
expect(navigateHandler).toHaveBeenCalledWith('throwFailures', true);
});
it("should navigate and change the setting to off", function() {
var env = new jasmineUnderTest.Env(),
container = document.createElement("div"),
navigateHandler = jasmine.createSpy('navigate'),
getContainer = function() {
return container;
},
reporter = new jasmineUnderTest.HtmlReporter({
env: env,
getContainer: getContainer,
navigateWithNewParam: navigateHandler,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
env.configure({oneFailurePerSpec: true});
reporter.initialize();
reporter.jasmineDone({});
var throwingExpectationsUI = container.querySelector(".jasmine-throw");
throwingExpectationsUI.click();
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(),
@@ -616,6 +789,7 @@ describe("New HtmlReporter", function() {
}
});
env.configure({random: false});
reporter.initialize();
reporter.jasmineDone({});
@@ -640,7 +814,7 @@ describe("New HtmlReporter", function() {
}
});
env.randomizeTests(true);
env.configure({random: true});
reporter.initialize();
reporter.jasmineDone({});
@@ -648,17 +822,17 @@ describe("New HtmlReporter", function() {
expect(randomUI.checked).toBe(true);
});
it("should affect the query param for random tests", function() {
it("should navigate and change the setting to on", function() {
var env = new jasmineUnderTest.Env(),
container = document.createElement("div"),
randomHandler = jasmine.createSpy('randomHandler'),
navigateHandler = jasmine.createSpy('navigate'),
getContainer = function() {
return container;
},
reporter = new jasmineUnderTest.HtmlReporter({
env: env,
getContainer: getContainer,
onRandomClick: randomHandler,
navigateWithNewParam: navigateHandler,
createElement: function() {
return document.createElement.apply(document, arguments);
},
@@ -667,13 +841,43 @@ describe("New HtmlReporter", function() {
}
});
env.configure({random: false});
reporter.initialize();
reporter.jasmineDone({});
var randomUI = container.querySelector(".jasmine-random");
randomUI.click();
expect(randomHandler).toHaveBeenCalled();
expect(navigateHandler).toHaveBeenCalledWith('random', true);
});
it("should navigate and change the setting to off", function() {
var env = new jasmineUnderTest.Env(),
container = document.createElement("div"),
navigateHandler = jasmine.createSpy('navigate'),
getContainer = function() {
return container;
},
reporter = new jasmineUnderTest.HtmlReporter({
env: env,
getContainer: getContainer,
navigateWithNewParam: navigateHandler,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
env.configure({random: true});
reporter.initialize();
reporter.jasmineDone({});
var randomUI = container.querySelector(".jasmine-random");
randomUI.click();
expect(navigateHandler).toHaveBeenCalledWith('random', false);
});
it("should show the seed bar if randomizing", function() {
@@ -702,8 +906,7 @@ describe("New HtmlReporter", function() {
});
var seedBar = container.querySelector(".jasmine-seed-bar");
var seedBarText = 'textContent' in seedBar ? seedBar.textContent : seedBar.innerText;
expect(seedBarText).toBe(', randomized with seed 424242');
expect(seedBar.textContent).toBe(', randomized with seed 424242');
var seedLink = container.querySelector(".jasmine-seed-bar a");
expect(seedLink.getAttribute('href')).toBe('?seed=424242');
});
@@ -726,7 +929,7 @@ describe("New HtmlReporter", function() {
});
reporter.initialize();
reporter.jasmineDone();
reporter.jasmineDone({});
var seedBar = container.querySelector(".jasmine-seed-bar");
expect(seedBar).toBeNull();
@@ -752,27 +955,6 @@ describe("New HtmlReporter", function() {
});
});
it("shows a message if no specs are run", function(){
var env, container, reporter;
env = new jasmineUnderTest.Env();
container = document.createElement("div");
var 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); }
});
reporter.initialize();
reporter.jasmineStarted({});
reporter.jasmineDone({});
var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
expect(alertBars[0].getAttribute('class')).toMatch(/jasmine-skipped/);
expect(alertBars[0].innerHTML).toMatch(/No specs found/);
});
describe("and all specs pass", function() {
var env, container, reporter;
beforeEach(function() {
@@ -811,7 +993,6 @@ describe("New HtmlReporter", function() {
var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
expect(alertBars.length).toEqual(1);
expect(alertBars[0].getAttribute('class')).toMatch(/jasmine-passed/);
expect(alertBars[0].innerHTML).toMatch(/2 specs, 0 failures/);
});
@@ -828,7 +1009,7 @@ describe("New HtmlReporter", function() {
});
});
describe("and there are disabled specs", function() {
describe("and there are excluded specs", function() {
var env, container, reporter, reporterConfig, specStatus;
beforeEach(function() {
env = new jasmineUnderTest.Env();
@@ -841,9 +1022,9 @@ describe("New HtmlReporter", function() {
};
specStatus = {
id: 123,
description: "with a disabled spec",
fullName: "A Suite with a disabled spec",
status: "disabled",
description: "with a excluded spec",
fullName: "A Suite with a excluded spec",
status: "excluded",
passedExpectations: [],
failedExpectations: []
};
@@ -860,10 +1041,10 @@ describe("New HtmlReporter", function() {
reporter.jasmineDone({});
});
it("shows the disabled spec in the spec list", function() {
it("shows the excluded spec in the spec list", function() {
var specList = container.querySelector(".jasmine-summary");
expect(specList.innerHTML).toContain('with a disabled spec');
expect(specList.innerHTML).toContain('with a excluded spec');
});
});
@@ -878,7 +1059,7 @@ describe("New HtmlReporter", function() {
reporter.jasmineDone({});
});
it("doesn't show the disabled spec in the spec list", function() {
it("doesn't show the excluded spec in the spec list", function() {
var specList = container.querySelector(".jasmine-summary");
expect(specList.innerHTML).toEqual('');
@@ -940,7 +1121,7 @@ describe("New 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,
@@ -951,16 +1132,24 @@ describe("New HtmlReporter", function() {
reporter.initialize();
reporter.jasmineStarted({ totalSpecsDefined: 1 });
reporter.suiteStarted({
id: 1,
description: "A suite"
});
reporter.suiteStarted({
id: 2,
description: "inner suite"
});
var passingResult = {id: 123, status: "passed", passedExpectations: [{passed: true}], failedExpectations: []};
reporter.specStarted(passingResult);
reporter.specDone(passingResult);
var passingSpecResult = {id: 123, status: "passed", passedExpectations: [{passed: true}], failedExpectations: []};
reporter.specStarted(passingSpecResult);
reporter.specDone(passingSpecResult);
var failingResult = {
var failingSpecResult = {
id: 124,
status: "failed",
description: "a failing spec",
fullName: "a suite with a failing spec",
fullName: "a suite inner suite a failing spec",
passedExpectations: [],
failedExpectations: [
{
@@ -969,39 +1158,83 @@ describe("New HtmlReporter", function() {
}
]
};
reporter.specStarted(failingResult);
reporter.specDone(failingResult);
var passingSuiteResult = {
id: 1,
description: "A suite"
};
var failingSuiteResult = {
id: 2,
description: 'a suite',
fullName: 'a suite',
status: 'failed',
failedExpectations: [{ message: 'My After All Exception' }]
};
reporter.specStarted(failingSpecResult);
reporter.specDone(failingSpecResult);
reporter.suiteDone(passingSuiteResult);
reporter.suiteDone(failingSuiteResult);
reporter.suiteDone(passingSuiteResult);
reporter.jasmineDone({});
});
it("reports the specs counts", function() {
var alertBar = container.querySelector(".jasmine-alert .jasmine-bar");
expect(alertBar.getAttribute('class')).toMatch(/jasmine-failed/);
expect(alertBar.innerHTML).toMatch(/2 specs, 1 failure/);
expect(alertBar.innerHTML).toMatch(/2 specs, 2 failure/);
});
it("reports failure messages and stack traces", function() {
var specFailures = container.querySelector(".jasmine-failures");
var failure = specFailures.childNodes[0];
expect(failure.getAttribute("class")).toMatch(/jasmine-failed/);
expect(failure.getAttribute("class")).toMatch(/jasmine-spec-detail/);
expect(specFailures.childNodes.length).toEqual(2);
var specDiv = failure.childNodes[0];
var specFailure = specFailures.childNodes[0];
expect(specFailure.getAttribute("class")).toMatch(/jasmine-failed/);
expect(specFailure.getAttribute("class")).toMatch(/jasmine-spec-detail/);
var specDiv = specFailure.childNodes[0];
expect(specDiv.getAttribute("class")).toEqual("jasmine-description");
var specLink = specDiv.childNodes[0];
expect(specLink.getAttribute("title")).toEqual("a suite with a failing spec");
expect(specLink.getAttribute("href")).toEqual("?foo=bar&spec=a suite with a failing spec");
var message = failure.childNodes[1].childNodes[0];
var message = specFailure.childNodes[1].childNodes[0];
expect(message.getAttribute("class")).toEqual("jasmine-result-message");
expect(message.innerHTML).toEqual("a failure message");
var stackTrace = failure.childNodes[1].childNodes[1];
var stackTrace = specFailure.childNodes[1].childNodes[1];
expect(stackTrace.getAttribute("class")).toEqual("jasmine-stack-trace");
expect(stackTrace.innerHTML).toEqual("a stack trace");
var suiteFailure = specFailures.childNodes[0];
expect(suiteFailure.getAttribute("class")).toMatch(/jasmine-failed/);
expect(suiteFailure.getAttribute("class")).toMatch(/jasmine-spec-detail/);
var suiteDiv = suiteFailure.childNodes[0];
expect(suiteDiv.getAttribute("class")).toEqual("jasmine-description");
var suiteMessage = suiteFailure.childNodes[1].childNodes[0];
expect(suiteMessage.getAttribute("class")).toEqual("jasmine-result-message");
expect(suiteMessage.innerHTML).toEqual("a failure message");
var suiteStackTrace = suiteFailure.childNodes[1].childNodes[1];
expect(suiteStackTrace.getAttribute("class")).toEqual("jasmine-stack-trace");
expect(suiteStackTrace.innerHTML).toEqual("a stack trace");
});
it('provides links to focus on a failure and each containing suite', function() {
var description = container.querySelector('.jasmine-failures .jasmine-description');
var links = description.querySelectorAll('a');
expect(description.textContent).toEqual('A suite > inner suite > a failing spec');
expect(links.length).toEqual(3);
expect(links[0].textContent).toEqual('A suite');
expect(links[0].getAttribute('href')).toMatch(/\?foo=bar&spec=A suite/);
expect(links[1].textContent).toEqual('inner suite');
expect(links[1].getAttribute('href')).toMatch(/\?foo=bar&spec=A suite inner suite/);
expect(links[2].textContent).toEqual('a failing spec');
expect(links[2].getAttribute('href')).toMatch(/\?foo=bar&spec=a suite inner suite a failing spec/);
});
it("allows switching between failure details and the spec summary", function() {
@@ -1020,4 +1253,83 @@ describe("New HtmlReporter", function() {
});
});
});
describe("The overall result bar", function() {
describe("When the jasmineDone event's overallStatus is 'passed'", function() {
it("has class jasmine-passed", 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); }
});
reporter.initialize();
reporter.jasmineStarted({});
reporter.jasmineDone({
overallStatus: 'passed',
failedExpectations: []
});
var alertBar = container.querySelector(".jasmine-overall-result");
expect(alertBar).toHaveClass("jasmine-passed");
});
});
describe("When the jasmineDone event's overallStatus is 'failed'", function() {
it("has class jasmine-failed", 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); }
});
reporter.initialize();
reporter.jasmineStarted({});
reporter.jasmineDone({
overallStatus: 'failed',
failedExpectations: []
});
var alertBar = container.querySelector(".jasmine-overall-result");
expect(alertBar).toHaveClass("jasmine-failed");
});
});
describe("When the jasmineDone event's overallStatus is 'incomplete'", function() {
it("has class jasmine-incomplete", 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); }
});
reporter.initialize();
reporter.jasmineStarted({});
reporter.jasmineDone({
overallStatus: 'incomplete',
incompleteReason: 'because nope',
failedExpectations: []
});
var alertBar = container.querySelector(".jasmine-overall-result");
expect(alertBar).toHaveClass("jasmine-incomplete");
expect(alertBar.textContent).toContain("Incomplete: because nope");
});
});
});
});

View File

@@ -1,15 +1,34 @@
describe("jasmineUnderTest.pp (HTML Dependent)", function () {
it("should stringify HTML nodes properly", function() {
var sampleNode = document.createElement('div');
sampleNode.innerHTML = 'foo<b>bar</b>';
it("should stringify non-element HTML nodes properly", function() {
var sampleNode = document.createTextNode("");
expect(jasmineUnderTest.pp(sampleNode)).toEqual("HTMLNode");
expect(jasmineUnderTest.pp({foo: sampleNode})).toEqual("Object({ foo: HTMLNode })");
});
it("should stringify empty HTML elements as their opening tags", function () {
var simple = document.createElement('div');
simple.className = 'foo';
expect(jasmineUnderTest.pp(simple)).toEqual('<div class="foo">');
});
it("should stringify non-empty HTML elements as tags with placeholders", function() {
var nonEmpty = document.createElement('div');
nonEmpty.className = 'foo';
nonEmpty.innerHTML = '<p>Irrelevant</p>';
expect(jasmineUnderTest.pp(nonEmpty)).toEqual('<div class="foo">...</div>');
});
it("should print Firefox's wrapped native objects correctly", function() {
if(jasmine.getEnv().firefoxVersion) {
try { new CustomEvent(); } catch(e) { var err = e; };
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

@@ -1,12 +1,17 @@
describe('Spy Registry browser-specific behavior', function() {
function createSpy(name, originalFn) {
return jasmineUnderTest.Spy(name, originalFn);
}
it('can spy on and unspy window.onerror', function() {
requireWriteableOnerror();
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() { return spies; },
global: window
}),
currentSpies: function() { return spies; },
createSpy: createSpy,
global: window
}),
originalHandler = window.onerror;
try {

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

@@ -28,7 +28,7 @@ describe('Printing a big object', function(){
return object;
}
it('takes a resonable amount of time', function(){
it('takes a reasonable amount of time', function(){
bigObject = generateObject(0);
expect(jasmineUnderTest.pp(bigObject)).toMatch(/cycle/);
});

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>Jasmine suite</title>
<link rel="shortcut icon" href="images/jasmine_favicon.png" type="image/png" />
<link rel="stylesheet" href="lib/jasmine-core/jasmine.css" type="text/css" media="screen" />
<% files.forEach(function(file) { %>
<script src="<%= file %>" type="text/javascript"></script>
<% }) %>
<body>
</body>
</html>

View File

@@ -2,7 +2,6 @@
"spec_dir": "spec",
"spec_files": [
"core/**/*.js",
"console/**/*.js",
"npmPackage/**/*.js"
],
"helpers": [
@@ -11,6 +10,8 @@
"helpers/checkForSet.js",
"helpers/checkForSymbol.js",
"helpers/checkForTypedArrays.js",
"helpers/integrationMatchers.js",
"helpers/promises.js",
"helpers/nodeDefineJasmineUnderTest.js"
],
"random": true

View File

@@ -13,7 +13,7 @@ src_files:
- 'core/PrettyPrinter.js'
- 'core/Suite.js'
- 'core/**/*.js'
- 'html/**.js'
- 'html/**/*.js'
- '**/*.js'
stylesheets:
helpers:
@@ -23,6 +23,8 @@ helpers:
- 'helpers/checkForSet.js'
- 'helpers/checkForSymbol.js'
- 'helpers/checkForTypedArrays.js'
- 'helpers/integrationMatchers.js'
- 'helpers/promises.js'
- 'helpers/defineJasmineUnderTest.js'
spec_files:
- '**/*[Ss]pec.js'

View File

@@ -1,155 +0,0 @@
getJasmineRequireObj().ConsoleReporter = function() {
var noopTimer = {
start: function(){},
elapsed: function(){ return 0; }
};
function ConsoleReporter(options) {
var print = options.print,
showColors = options.showColors || false,
onComplete = options.onComplete || function() {},
timer = options.timer || noopTimer,
specCount,
failureCount,
failedSpecs = [],
pendingCount,
ansi = {
green: '\x1B[32m',
red: '\x1B[31m',
yellow: '\x1B[33m',
none: '\x1B[0m'
},
failedSuites = [];
print('ConsoleReporter is deprecated and will be removed in a future version.');
this.jasmineStarted = function() {
specCount = 0;
failureCount = 0;
pendingCount = 0;
print('Started');
printNewline();
timer.start();
};
this.jasmineDone = function() {
printNewline();
for (var i = 0; i < failedSpecs.length; i++) {
specFailureDetails(failedSpecs[i]);
}
if(specCount > 0) {
printNewline();
var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' +
failureCount + ' ' + plural('failure', failureCount);
if (pendingCount) {
specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount);
}
print(specCounts);
} else {
print('No specs found');
}
printNewline();
var seconds = timer.elapsed() / 1000;
print('Finished in ' + seconds + ' ' + plural('second', seconds));
printNewline();
for(i = 0; i < failedSuites.length; i++) {
suiteFailureDetails(failedSuites[i]);
}
onComplete(failureCount === 0);
};
this.specDone = function(result) {
specCount++;
if (result.status == 'pending') {
pendingCount++;
print(colored('yellow', '*'));
return;
}
if (result.status == 'passed') {
print(colored('green', '.'));
return;
}
if (result.status == 'failed') {
failureCount++;
failedSpecs.push(result);
print(colored('red', 'F'));
}
};
this.suiteDone = function(result) {
if (result.failedExpectations && result.failedExpectations.length > 0) {
failureCount++;
failedSuites.push(result);
}
};
return this;
function printNewline() {
print('\n');
}
function colored(color, str) {
return showColors ? (ansi[color] + str + ansi.none) : str;
}
function plural(str, count) {
return count == 1 ? str : str + 's';
}
function repeat(thing, times) {
var arr = [];
for (var i = 0; i < times; i++) {
arr.push(thing);
}
return arr;
}
function indent(str, spaces) {
var lines = (str || '').split('\n');
var newArr = [];
for (var i = 0; i < lines.length; i++) {
newArr.push(repeat(' ', spaces).join('') + lines[i]);
}
return newArr.join('\n');
}
function specFailureDetails(result) {
printNewline();
print(result.fullName);
for (var i = 0; i < result.failedExpectations.length; i++) {
var failedExpectation = result.failedExpectations[i];
printNewline();
print(indent(failedExpectation.message, 2));
print(indent(failedExpectation.stack, 2));
}
printNewline();
}
function suiteFailureDetails(result) {
for (var i = 0; i < result.failedExpectations.length; i++) {
printNewline();
print(colored('red', 'An error was thrown in an afterAll'));
printNewline();
print(colored('red', 'AfterAll ' + result.failedExpectations[i].message));
}
printNewline();
}
}
return ConsoleReporter;
};

View File

@@ -1,12 +0,0 @@
function getJasmineRequireObj() {
if (typeof module !== 'undefined' && module.exports) {
return exports;
} else {
window.jasmineRequire = window.jasmineRequire || {};
return window.jasmineRequire;
}
}
getJasmineRequireObj().console = function(jRequire, j$) {
j$.ConsoleReporter = jRequire.ConsoleReporter();
};

View File

@@ -1,5 +1,6 @@
getJasmineRequireObj().Clock = function() {
/* global process */
var NODE_JS = typeof process !== 'undefined' && process.versions && typeof process.versions.node === 'string';
/**
@@ -65,7 +66,7 @@ getJasmineRequireObj().Clock = function() {
* The clock will be {@link Clock#install|install}ed before the function is called and {@link Clock#uninstall|uninstall}ed in a `finally` after the function completes.
* @name Clock#withMock
* @function
* @param {closure} Function The function to be called.
* @param {Function} closure The function to be called.
*/
self.withMock = function(closure) {
this.install();
@@ -87,22 +88,10 @@ getJasmineRequireObj().Clock = function() {
};
self.setTimeout = function(fn, delay, params) {
if (legacyIE()) {
if (arguments.length > 2) {
throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill');
}
return timer.setTimeout(fn, delay);
}
return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]);
};
self.setInterval = function(fn, delay, params) {
if (legacyIE()) {
if (arguments.length > 2) {
throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill');
}
return timer.setInterval(fn, delay);
}
return Function.prototype.apply.apply(timer.setInterval, [global, arguments]);
};
@@ -137,11 +126,6 @@ getJasmineRequireObj().Clock = function() {
global.clearInterval === realTimingFunctions.clearInterval;
}
function legacyIE() {
//if these methods are polyfilled, apply will be present
return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply;
}
function replace(dest, source) {
for (var prop in source) {
dest[prop] = source[prop];

View File

@@ -147,6 +147,7 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
}
funcToRun.funcToCall.apply(null, funcToRun.params || []);
});
deletedKeys = [];
} while (scheduledLookup.length > 0 &&
// checking first if we're out of time prevents setTimeout(0)
// scheduled in a funcToRun from forcing an extra iteration

View File

@@ -11,15 +11,11 @@ getJasmineRequireObj().Env = function(j$) {
var self = this;
var global = options.global || j$.getGlobal();
var hasExecuted = false;
var totalSpecsDefined = 0;
var catchExceptions = true;
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 = {};
@@ -27,9 +23,61 @@ getJasmineRequireObj().Env = function(j$) {
var currentSpec = null;
var currentlyExecutingSuites = [];
var currentDeclarationSuite = null;
var throwOnExpectationFailure = false;
var random = false;
var seed = null;
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];
@@ -39,63 +87,93 @@ getJasmineRequireObj().Env = function(j$) {
return currentSpec || currentSuite();
};
var globalErrors = null;
var installGlobalErrors = function() {
if (globalErrors) {
return;
}
globalErrors = new j$.GlobalErrors();
globalErrors.install();
};
if (!options.suppressLoadErrors) {
installGlobalErrors();
globalErrors.pushListener(function(message, filename, lineno, colNo, err) {
topSuite.result.failedExpectations.push({
passed: false,
globalErrorType: 'load',
message: message,
stack: err && err.stack,
filename: filename,
lineno: lineno
});
});
}
/**
* This represents the available reporter callback for an object passed to {@link Env#addReporter}.
* @interface Reporter
* Configure your jasmine environment
* @name Env#configure
* @argument {Configuration} configuration
* @function
*/
var reporter = new j$.ReportDispatcher([
/**
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
* @function
* @name Reporter#jasmineStarted
* @param {JasmineStartedInfo} suiteInfo Information about the full Jasmine suite that is being run
*/
'jasmineStarted',
/**
* When the entire suite has finished execution `jasmineDone` is called
* @function
* @name Reporter#jasmineDone
* @param {JasmineDoneInfo} suiteInfo Information about the full Jasmine suite that just finished running.
*/
'jasmineDone',
/**
* `suiteStarted` is invoked when a `describe` starts to run
* @function
* @name Reporter#suiteStarted
* @param {SuiteResult} result Information about the individual {@link describe} being run
*/
'suiteStarted',
/**
* `suiteDone` is invoked when all of the child specs and suites for a given suite have been run
*
* While jasmine doesn't require any specific functions, not defining a `suiteDone` will make it impossible for a reporter to know when a suite has failures in an `afterAll`.
* @function
* @name Reporter#suiteDone
* @param {SuiteResult} result
*/
'suiteDone',
/**
* `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions)
* @function
* @name Reporter#specStarted
* @param {SpecResult} result Information about the individual {@link it} being run
*/
'specStarted',
/**
* `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run.
*
* While jasmine doesn't require any specific functions, not defining a `specDone` will make it impossible for a reporter to know when a spec has failed.
* @function
* @name Reporter#specDone
* @param {SpecResult} result
*/
'specDone'
]);
this.configure = function(configuration) {
if (configuration.specFilter) {
config.specFilter = configuration.specFilter;
}
var globalErrors = new j$.GlobalErrors();
if (configuration.hasOwnProperty('random')) {
config.random = !!configuration.random;
}
this.specFilter = function() {
return true;
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');
}
runnableResources[currentRunnable().id].customSpyStrategies[name] = fn;
};
this.addCustomEqualityTester = function(tester) {
@@ -116,6 +194,7 @@ getJasmineRequireObj().Env = function(j$) {
};
j$.Expectation.addCoreMatchers(j$.matchers);
j$.Expectation.addAsyncCoreMatchers(j$.asyncMatchers);
var nextSpecId = 0;
var getNextSpecId = function() {
@@ -128,7 +207,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,
@@ -141,8 +220,21 @@ 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: {}};
var resources = {spies: [], customEqualityTesters: [], customMatchers: {}, customSpyStrategies: {}};
if(runnableResources[parentRunnableId]){
resources.customEqualityTesters = j$.util.clone(runnableResources[parentRunnableId].customEqualityTesters);
@@ -196,67 +288,116 @@ getJasmineRequireObj().Env = function(j$) {
return buildExpectationResult(attrs);
};
// TODO: fix this naming, and here's where the value comes in
this.catchExceptions = function(value) {
catchExceptions = !!value;
if (!catchExceptions) {
this.deprecated('The catchExceptions option is deprecated and will be replaced with stopOnSpecFailure in Jasmine 3.0');
}
return catchExceptions;
};
this.catchingExceptions = function() {
return catchExceptions;
};
var maximumSpecCallbackDepth = 20;
var currentSpecCallbackDepth = 0;
var catchException = function(e) {
return j$.Spec.isPendingSpecException(e) || catchExceptions;
};
/**
* 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) {
this.deprecated('Setting stopOnSpecFailure directly is deprecated, please use the failFast option in `configure`');
this.configure({failFast: !!value});
};
this.stoppingOnSpecFailure = function() {
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.deprecated = function(msg) {
this.hidingDisabled = function(value) {
this.deprecated('Getting hidingDisabled directly from Env is deprecated, please check the hideDisabled option from `configuration`');
return config.hideDisabled;
};
/**
* @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) {
options.catchException = catchException;
var queueRunnerFactory = function(options, args) {
var failFast = false;
if (options.isLeaf) {
failFast = config.oneFailurePerSpec;
} else if (!options.isReporter) {
failFast = config.failFast;
}
options.clearStack = options.clearStack || clearStack;
options.timeout = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout};
options.fail = self.fail;
options.globalErrors = globalErrors;
options.completeOnFirstError = throwOnExpectationFailure && options.isLeaf;
options.completeOnFirstError = failFast;
options.onException = options.onException || function(e) {
(currentRunnable() || topSuite).onException(e);
};
options.deprecated = self.deprecated;
new j$.QueueRunner(options).execute();
new j$.QueueRunner(options).execute(args);
};
var topSuite = new j$.Suite({
@@ -264,6 +405,7 @@ getJasmineRequireObj().Env = function(j$) {
id: getNextSuiteId(),
description: 'Jasmine__TopLevel__Suite',
expectationFactory: expectationFactory,
asyncExpectationFactory: asyncExpectationFactory,
expectationResultFactory: expectationResultFactory
});
defaultResourcesForRunnable(topSuite.id);
@@ -273,12 +415,81 @@ getJasmineRequireObj().Env = function(j$) {
return topSuite;
};
this.execute = function(runnablesToRun) {
if (hasExecuted) {
this.deprecated('Executing the same Jasmine multiple times will no longer work in Jasmine 3.0');
}
/**
* This represents the available reporter callback for an object passed to {@link Env#addReporter}.
* @interface Reporter
* @see custom_reporter
*/
var reporter = new j$.ReportDispatcher([
/**
* `jasmineStarted` is called after all of the specs have been loaded, but just before execution starts.
* @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',
/**
* When the entire suite has finished execution `jasmineDone` is called
* @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',
/**
* `suiteStarted` is invoked when a `describe` starts to run
* @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',
/**
* `suiteDone` is invoked when all of the child specs and suites for a given suite have been run
*
* While jasmine doesn't require any specific functions, not defining a `suiteDone` will make it impossible for a reporter to know when a suite has failures in an `afterAll`.
* @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',
/**
* `specStarted` is invoked when an `it` starts to run (including associated `beforeEach` functions)
* @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',
/**
* `specDone` is invoked when an `it` and its associated `beforeEach` and `afterEach` functions have been run.
*
* While jasmine doesn't require any specific functions, not defining a `specDone` will make it impossible for a reporter to know when a spec has failed.
* @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);
hasExecuted = true;
this.execute = function(runnablesToRun) {
var self = this;
installGlobalErrors();
if(!runnablesToRun) {
if (focusedRunnables.length) {
@@ -289,32 +500,39 @@ getJasmineRequireObj().Env = function(j$) {
}
var order = new j$.Order({
random: random,
seed: seed
random: config.random,
seed: config.seed
});
var processor = new j$.TreeProcessor({
tree: topSuite,
runnableIds: runnablesToRun,
queueRunnerFactory: queueRunnerFactory,
nodeStart: function(suite) {
nodeStart: function(suite, next) {
currentlyExecutingSuites.push(suite);
defaultResourcesForRunnable(suite.id, suite.parentSuite.id);
reporter.suiteStarted(suite.result);
reporter.suiteStarted(suite.result, next);
suite.startTimer();
},
nodeComplete: function(suite, result) {
nodeComplete: function(suite, result, next) {
if (suite !== currentSuite()) {
throw new Error('Tried to complete the wrong suite');
}
if (!suite.markedPending) {
clearResourcesForRunnable(suite.id);
}
clearResourcesForRunnable(suite.id);
currentlyExecutingSuites.pop();
reporter.suiteDone(result);
if (result.status === 'failed') {
hasFailures = true;
}
suite.endTimer();
reporter.suiteDone(result, next);
},
orderChildren: function(node) {
return order.sort(node.children);
},
excludeNode: function(spec) {
return !config.specFilter(spec);
}
});
@@ -331,27 +549,42 @@ getJasmineRequireObj().Env = function(j$) {
reporter.jasmineStarted({
totalSpecsDefined: totalSpecsDefined,
order: order
});
}, function() {
currentlyExecutingSuites.push(topSuite);
currentlyExecutingSuites.push(topSuite);
processor.execute(function () {
clearResourcesForRunnable(topSuite.id);
currentlyExecutingSuites.pop();
var overallStatus, incompleteReason;
globalErrors.install();
processor.execute(function() {
clearResourcesForRunnable(topSuite.id);
currentlyExecutingSuites.pop();
globalErrors.uninstall();
if (hasFailures || topSuite.result.failedExpectations.length > 0) {
overallStatus = 'failed';
} else if (focusedRunnables.length > 0) {
overallStatus = 'incomplete';
incompleteReason = 'fit() or fdescribe() was found';
} else if (totalSpecsDefined === 0) {
overallStatus = 'incomplete';
incompleteReason = 'No specs found';
} else {
overallStatus = 'passed';
}
/**
* Information passed to the {@link Reporter#jasmineDone} event.
* @typedef JasmineDoneInfo
* @property {Order} order - Information about the ordering (random or not) of this execution of the suite.
* @property {Expectation[]} failedExpectations - List of expectations that failed in an {@link afterAll} at the global level.
* @property {Expectation[]} deprecationWarnings - List of deprecation warnings that occurred at the global level.
*/
reporter.jasmineDone({
order: order,
failedExpectations: topSuite.result.failedExpectations,
deprecationWarnings: topSuite.result.deprecationWarnings
/**
* Information passed to the {@link Reporter#jasmineDone} event.
* @typedef JasmineDoneInfo
* @property {OverallStatus} overallStatus - The overall result of the suite: '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.
*/
reporter.jasmineDone({
overallStatus: overallStatus,
incompleteReason: incompleteReason,
order: order,
failedExpectations: topSuite.result.failedExpectations,
deprecationWarnings: topSuite.result.deprecationWarnings
}, function() {});
});
});
};
@@ -367,20 +600,47 @@ 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();
};
var spyRegistry = new j$.SpyRegistry({currentSpies: function() {
if(!currentRunnable()) {
throw new Error('Spies must be created in a before function or a spec');
var spyFactory = new j$.SpyFactory(function() {
var runnable = currentRunnable();
if (runnable) {
return runnableResources[runnable.id].customSpyStrategies;
}
return runnableResources[currentRunnable().id].spies;
}});
return {};
});
var spyRegistry = new j$.SpyRegistry({
currentSpies: function() {
if(!currentRunnable()) {
throw new Error('Spies must be created in a before function or a spec');
}
return runnableResources[currentRunnable().id].spies;
},
createSpy: function(name, originalFn) {
return self.createSpy(name, originalFn);
}
});
this.allowRespy = function(allow){
spyRegistry.allowRespy(allow);
@@ -394,6 +654,23 @@ 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);
};
this.createSpyObj = function(baseName, methodNames) {
return spyFactory.createSpyObj(baseName, methodNames);
};
var ensureIsFunction = function(fn, caller) {
if (!j$.isFunction_(fn)) {
throw new Error(caller + ' expects a function argument; received ' + j$.getType_(fn));
@@ -420,8 +697,9 @@ getJasmineRequireObj().Env = function(j$) {
description: description,
parentSuite: currentDeclarationSuite,
expectationFactory: expectationFactory,
asyncExpectationFactory: asyncExpectationFactory,
expectationResultFactory: expectationResultFactory,
throwOnExpectationFailure: throwOnExpectationFailure
throwOnExpectationFailure: config.oneFailurePerSpec
});
return suite;
@@ -453,7 +731,6 @@ getJasmineRequireObj().Env = function(j$) {
var focusedRunnables = [];
this.fdescribe = function(description, specDefinitions) {
this.deprecated('fit and fdescribe will cause your suite to report an \'incomplete\' status in Jasmine 3.0');
ensureIsNotNested('fdescribe');
ensureIsFunction(specDefinitions, 'fdescribe');
var suite = suiteFactory(description);
@@ -479,9 +756,7 @@ getJasmineRequireObj().Env = function(j$) {
}
if (declarationError) {
self.it('encountered a declaration exception', function() {
throw declarationError;
});
suite.onException(declarationError);
}
currentDeclarationSuite = parentSuite;
@@ -516,6 +791,7 @@ getJasmineRequireObj().Env = function(j$) {
id: getNextSpecId(),
beforeAndAfterFns: beforeAndAfterFns(suite),
expectationFactory: expectationFactory,
asyncExpectationFactory: asyncExpectationFactory,
resultCallback: specResultCallback,
getSpecName: function(spec) {
return getSpecName(spec, suite);
@@ -527,27 +803,28 @@ 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,
timer: new j$.Timer(),
});
if (!self.specFilter(spec)) {
spec.disable();
}
return spec;
function specResultCallback(result) {
function specResultCallback(result, next) {
clearResourcesForRunnable(spec.id);
currentSpec = null;
reporter.specDone(result);
if (result.status === 'failed') {
hasFailures = true;
}
reporter.specDone(result, next);
}
function specStarted(spec) {
function specStarted(spec, next) {
currentSpec = spec;
defaultResourcesForRunnable(spec.id, suite.id);
reporter.specStarted(spec.result);
reporter.specStarted(spec.result, next);
}
};
@@ -579,7 +856,6 @@ getJasmineRequireObj().Env = function(j$) {
};
this.fit = function(description, fn, timeout){
this.deprecated('fit and fdescribe will cause your suite to report an \'incomplete\' status in Jasmine 3.0');
ensureIsNotNested('fit');
ensureIsFunctionOrAsync(fn, 'fit');
var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
@@ -597,12 +873,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
});
};
@@ -611,7 +895,7 @@ getJasmineRequireObj().Env = function(j$) {
ensureIsFunctionOrAsync(beforeAllFunction, 'beforeAll');
currentDeclarationSuite.beforeAll({
fn: beforeAllFunction,
timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
timeout: timeout || 0
});
};
@@ -621,7 +905,7 @@ getJasmineRequireObj().Env = function(j$) {
afterEachFunction.isCleanup = true;
currentDeclarationSuite.afterEach({
fn: afterEachFunction,
timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
timeout: timeout || 0
});
};
@@ -630,7 +914,7 @@ getJasmineRequireObj().Env = function(j$) {
ensureIsFunctionOrAsync(afterAllFunction, 'afterAll');
currentDeclarationSuite.afterAll({
fn: afterAllFunction,
timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
timeout: timeout || 0
});
};
@@ -652,11 +936,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);
}
}
@@ -669,7 +953,7 @@ getJasmineRequireObj().Env = function(j$) {
error: error && error.message ? error : null
});
if (self.throwingExpectationFailures()) {
if (config.oneFailurePerSpec) {
throw new Error(message);
}
};

View File

@@ -1,10 +1,18 @@
getJasmineRequireObj().ExceptionFormatter = function() {
function ExceptionFormatter() {
getJasmineRequireObj().ExceptionFormatter = function(j$) {
var ignoredProperties = ['name', 'message', 'stack', 'fileName', 'sourceURL', 'line', 'lineNumber', 'column', 'description', 'jasmineMessage'];
function ExceptionFormatter(options) {
var jasmineFile = (options && options.jasmineFile) || j$.util.jasmineFile();
this.message = function(error) {
var message = '';
if (error.name && error.message) {
if (error.jasmineMessage) {
message += error.jasmineMessage;
} else if (error.name && error.message) {
message += error.name + ': ' + error.message;
} else if (error.message) {
message += error.message;
} else {
message += error.toString() + ' thrown';
}
@@ -21,8 +29,61 @@ getJasmineRequireObj().ExceptionFormatter = function() {
};
this.stack = function(error) {
return error ? error.stack : null;
if (!error || !error.stack) {
return null;
}
var stackTrace = new j$.StackTrace(error);
var lines = filterJasmine(stackTrace);
var result = '';
if (stackTrace.message) {
lines.unshift(stackTrace.message);
}
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);
} else if (result[result.length - 1] !== jasmineMarker) {
result.push(jasmineMarker);
}
});
return result;
}
function formatProperties(error) {
if (!(error instanceof Object)) {
return;
}
var result = {};
var empty = true;
for (var prop in error) {
if (j$.util.arrayContains(ignoredProperties, 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);

Some files were not shown because too many files have changed in this diff Show More