Compare commits

...

110 Commits

Author SHA1 Message Date
Sheel Choksi
04c7db9259 Update built distribution to include latest 2.0.0-rc5 fixes 2013-10-29 17:40:15 -07:00
Sheel Choksi
8585ef69a5 Update clock not installed message to reflect current boot installation process 2013-10-29 17:33:51 -07:00
Sheel Choksi
cb5aea1fcf Fix builds by working around browser timing functions not being successfully overridden 2013-10-29 17:32:04 -07:00
Sheel Choksi
966f76b481 Add in missing clock uninstall 2013-10-29 17:28:41 -07:00
Sheel Choksi
40e3020fdc Build distribution for 2.0.0-rc5 and associated standalone distribution 2013-10-29 14:03:02 -07:00
Sheel Choksi
69549a6ff3 Add in 2.0.0-rc5 release notes 2013-10-29 14:03:01 -07:00
Sheel Choksi
a03fad8911 Move built console.js into lib and include in standalone distribution
[finishes #59679110]
2013-10-29 14:03:01 -07:00
Sheel Choksi
61993cf1fc Expose Jasmine's topSuite [finishes #59774024] 2013-10-29 11:27:12 -07:00
Kyriacos Souroullas and Sheel Choksi
cd9d5284cd Matchers can have a negativeCompare
- Passing in a 'negativeCompare' will cause that function to be used when it is a 'not' assertion
- Otherwise, the reversal of the compare's result will be used instead

[finishes #59703824]
2013-10-28 17:13:18 -07:00
Kyriacos Souroullas and Sheel Choksi
e346e7dcc1 Revert removal of compare nesting
Since we want the user to be able to pass a negative comparison function, the extra layer of wrapping is now needed
2013-10-28 17:13:09 -07:00
Davis W. Frank
dd8a455f91 Adding Code Climate badge to README 2013-10-25 12:25:27 -07:00
Davis W. Frank
9e149d1e0f Move node dev deps forward, add .jshintrc to support latest grunt-contrib-jshint and Code Climate score 2013-10-25 12:23:57 -07:00
Sheel Choksi and Tim Jarratt
797984f173 Add newlines to end of files 2013-10-25 10:57:43 -07:00
Sheel Choksi and Tim Jarratt
29c5c127e5 Refactor Suite.addSpec and .addSuite to .addChild 2013-10-25 10:52:31 -07:00
Sheel Choksi and Tim Jarratt
26581b4c91 Rename Suite.children_ to .children
Also removed some unit tests that were brittle, and already tested by
better, more round-trip tests.
2013-10-25 10:25:50 -07:00
Davis W. Frank
243ff80196 Fixing global leak for 'timer' 2013-10-24 17:17:05 -07:00
Davis W. Frank
284bb0b608 Giving Sheel his due 2013-10-24 16:55:51 -07:00
Sheel Choksi
6453ed656b Suites just have children instead of separating into specs/suites 2013-10-24 16:35:00 -07:00
Sheel Choksi
a1a948b8df Remove completeCallback from suite as its unused 2013-10-24 16:34:34 -07:00
Sheel Choksi
7a4876ecfa Also move function to determine whether specs should catch exceptions into closure 2013-10-24 16:24:55 -07:00
Sheel Choksi
d9ece1f14f Remove version/versionString and currentRunner
- Instead of version/versionString, jasmine.version should be sufficient
- currentRunner was exposing Jasmine's internal top level suite
2013-10-24 15:42:46 -07:00
Sheel Choksi
f1613ce77c Move additional methods from Env prototype to env closure
- Users can no longer spelunk the spec tree from topSuite
- Users no longer have access to currentSuite/currentSpec
- Other miscellaneous (arguably less useful) methods have also been tucked
away into the closure, like suiteFactory
2013-10-24 15:28:01 -07:00
Sheel Choksi
a3424ea265 Remove addCustomEqualityTester and addMatchers from global
These functions are available on the jasmine namespace
2013-10-24 14:00:05 -07:00
Sheel Choksi
ab0b2b783c Move next spec/next suite ids into closure
No longer exposing these from the environment
2013-10-24 13:43:04 -07:00
Sheel Choksi
d0aff9ed02 Use toThrowError instead of toThrow in places where we are expecting an error 2013-10-24 12:15:17 -07:00
Sheel Choksi
a309117758 Remove TODO: should be easier to load polyfill for timeout functions as Jasmine does not get references to these functions until boot.js is loaded 2013-10-24 11:58:21 -07:00
Sheel Choksi
0c6e590a93 A spec without expectations is considered passing
- Specs are passing by default unless told otherwise
- Getting the result.status of a spec before the spec has run is now
  undefined instead of pending

[finishes #59422744]
2013-10-24 11:34:42 -07:00
Sheel Choksi
d06da150de Stop passing in queryString to HTMLReporter, it is unused 2013-10-23 11:06:42 -07:00
Sheel Choksi
39d7ebf28e Remove an extra layer of wrapping for matchers/custom matchers
Helps reduce how nested custom matchers have to be for users as well as
Jasmine internal matchers

[#59161378]
2013-10-20 22:21:56 -07:00
Sheel Choksi
5f429fcb37 Re-enable CustomMatchersSpec and update for current version of custom matchers 2013-10-20 21:58:16 -07:00
Sheel Choksi
b6eb9a4d5e Remove now unused updateInterval that was being set in specs 2013-10-20 17:12:40 -07:00
Sheel Choksi
fdb7df812c Improve error message when a spec doesn't call the async callback within the default time interval 2013-10-19 21:18:06 -07:00
Davis W. Frank
81299860aa Merge pull request #450 from slackersoft/manualClockUninstall
Env no longer automatically uninstalls the clock after each spec
2013-10-18 15:51:10 -07:00
slackersoft
ca6fa6f711 Env no longer automatically uninstalls the clock after each spec
- Behaves more like how we want plugins to behave

[#58281436]
2013-10-16 18:39:03 -07:00
Davis W. Frank
5aaafed4d8 Move clock from global to jasmine; provide a function to access the clock. 2013-10-10 16:24:58 -07:00
Davis W. Frank
c28c124f58 removed addMatchers from the global. This should have been in previous commit 2013-10-10 14:11:44 -07:00
Davis W. Frank
f0a1adb61c Continuing boot change with docs 2013-10-10 12:00:46 -07:00
Davis W. Frank
5ff2aecab8 Moving a documented-up boot.js from the website back into core 2013-10-10 11:59:59 -07:00
Davis W. Frank
8ca8197b4c Make exposure of addMatchers and addCustomEqualityTesters be on jasmine instead of inconsistent. 2013-10-10 11:32:21 -07:00
Davis W. Frank
55716723b5 Adding Compass as a dev dependency in order to build HTMLreporter CSS 2013-10-10 11:27:40 -07:00
Davis W. Frank
3973cc5a71 Merge pull request #443 from kryger/patch-1
Fixed broken link to contributing guide
2013-10-08 07:48:53 -07:00
Lukasz Kryger
95af58ade6 Fixed broken link to contributing guide 2013-10-08 11:33:55 +01:00
slackersoft
6641d64305 Make addCustomEqualityTester available on jasmine global
- User shouldn't have to `jasmine.getEnv()` to add one

[#54582648]
2013-10-06 11:32:38 -07:00
slackersoft
7c1fcd7bb5 Regenerate jasmine.js for QueueRunner fix 2013-10-06 11:32:19 -07:00
slackersoft
e91d0341a4 Revert "Make addCustomEqualityTester available on jasmine global"
Oops, this made it on global object, not `jasmnie`

This reverts commit 144ff174f6.
2013-10-06 11:11:46 -07:00
slackersoft
144ff174f6 Make addCustomEqualityTester available on jasmine global
- User shouldn't have to `jasmine.getEnv()` to add one
2013-10-06 11:05:35 -07:00
Gregg Van Hove and Tim Jarratt
af4bfa8bc4 Env should use the "public" QueueRunner interface 2013-10-04 17:04:22 -07:00
Gregg Van Hove and Tim Jarratt
620e3f5992 Run docs tests under phantomjs 2013-10-04 13:32:56 -07:00
Gregg Van Hove and Tim Jarratt
ea76a30d85 Update standalone distributions
[#30296755]
2013-10-04 12:28:27 -07:00
Gregg Van Hove and Tim Jarratt
adde1b4a5b Doc js files from jasmine.github.io should be part of CI build
[Finish #50572569]
2013-10-04 12:10:38 -07:00
Gregg Van Hove and Tim Jarratt
07e7ad2314 Update jasmine_favicon.png
Using the new image from google drive. It's 32x32px but browsers should
be able to downsize that to 16x16 if they need to

[Finish #57170588]
2013-10-04 10:55:01 -07:00
Davis W. Frank
706180ad01 2.0 rc3 release notes 2013-10-03 16:36:08 -07:00
Davis W. Frank
547c9cfde9 Adding Anchorman back in as a dependency 2013-10-03 16:35:56 -07:00
Gregg Van Hove and Tim Jarratt
d3ec12e62a buildStandaloneDist should also build jasmine.js 2013-10-03 15:28:42 -07:00
Gregg Van Hove and Tim Jarratt
749c15fe07 Bump version to rc3 in jasmine.js 2013-10-03 15:28:26 -07:00
Gregg Van Hove and Tim Jarratt
7e071547f5 Custom matchers fail to behave as expected
If they return false, that should be respected.

Submitted via @tjgrathwell

[Finish #58184156]
close #434
2013-10-03 15:13:27 -07:00
Gregg Van Hove
6354ee17e5 Merge pull request #439 from tjarratt/pull_request_travis
Don't try to use SauceLabs on pull request builds
2013-10-03 12:32:32 -07:00
Gregg Van Hove and Tim Jarratt
255a50baee Update contribution guidelines for pull requests
[Finish #45961121]
2013-10-03 12:30:07 -07:00
Tim Jarratt
520a8c85a2 Don't bother trying to still use firefox 2013-10-03 12:07:57 -07:00
Gregg Van Hove and Tim Jarratt
6de355544f Make firefox with Sauce explicitly the default test
Apparently Travis-ci will create a default test separate from your
matrix includes and this resulted in some testrun duplication.
2013-10-03 11:44:48 -07:00
Gregg Van Hove and Tim Jarratt
95572fb314 Don't try to use SauceLabs on pull request builds 2013-10-03 11:24:57 -07:00
Gregg Van Hove and Tim Jarratt
18e1ab93ea Release for rc3 2013-10-03 09:55:36 -07:00
Davis W. Frank
0c4113e167 Quick fix - Spec needs j$ at execute time 2013-10-02 22:45:33 -07:00
Gregg Van Hove and Tim Jarratt
a563e67015 Move selenium_runner.yml to spec/javascripts/support
- The selenium runner gem should support configurable path as the main
  gem does so we don't need to do this. This workaround is kind of
  gross.
2013-10-02 16:48:13 -07:00
Gregg Van Hove and Tim Jarratt
fab489851e Fix paths for node specs
[#58126010]
2013-10-02 16:41:07 -07:00
Gregg Van Hove and Tim Jarratt
1c19b8e38a Move spec files back out of spec/javascripts
- Jasmine gem allows us to specify a path to jasmine.yml via ENV

[finish #58126010]
2013-10-02 16:32:35 -07:00
Gregg Van Hove and Tim Jarratt
fc258b3d36 Make it easy to copy the title of failing specs
[finish #58121820]
2013-10-02 15:14:41 -07:00
Gregg Van Hove and Tim Jarratt
51dd66a4cc Turn the exceptions spec back on, it still works 2013-10-02 10:24:24 -07:00
Gregg Van Hove and Tim Jarratt
37a3135d6a cleanup whitespace 2013-10-01 16:30:17 -07:00
Gregg Van Hove and Tim Jarratt
cb8ba74937 Don't add periods to the full name of a spec
- Breaks links for spec filters
- Looks strange if users add their own

[fix #58043244] fix #427
2013-10-01 16:28:33 -07:00
Gregg Van Hove and Tim Jarratt
70fb0f0ed5 Update Firefox pretty print test
At some point, firefox changed the exception message.
2013-09-30 15:43:44 -07:00
Sheel Choksi
15889494c5 Update node suites to not rely on previous accidental global j$ and create its own 2013-09-29 14:59:58 -07:00
Sheel Choksi
da33c7823e Add missing var in front of j$ to avoid polluting global namespace
Users should only have 'jasmine' in global namespace, j$ should be
fully internal unless developing for jasmine

As brought up by Morten Maxild
2013-09-29 14:46:55 -07:00
Gregg Van Hove
04e1d8420e Ensure tunnel_identifier is properly quoted for travis builds 2013-09-25 14:24:57 -07:00
Gregg Van Hove and Rajan Agaskar
19b2472761 Really make tunnel_identifier a string.
yay.
2013-09-25 11:24:41 -07:00
Gregg Van Hove and Rajan Agaskar
1fc614ad19 Tunnel identifier must be a string
- Travis provides a float.
2013-09-25 11:03:45 -07:00
Gregg Van Hove and Rajan Agaskar
84692f545c Use jasmine_selenium_runner to run specs via Sauce 2013-09-25 10:45:53 -07:00
Gregg Van Hove and Rajan Agaskar
5017d1a4f1 Make rake jasmine:ci run specs correctly.
- Will replace rake core_specs.
- Remove obsolete dependencies & files -- most of these were for build tasks we
  are no longer using. Notably, rspec and spec_helper were deleted.
2013-09-25 10:11:02 -07:00
Gregg Van Hove and Rajan Agaskar
963cd5e850 Make rake dev dependency 2013-09-24 11:31:21 -07:00
Gregg Van Hove and Rajan Agaskar
527394068e Update specs to use new HTTP Runner interface. 2013-09-24 11:30:50 -07:00
Gregg Van Hove and Rajan Agaskar
5e279a1393 Remove unnecessary Jasmine.configure. 2013-09-20 11:16:40 -07:00
Gregg Van Hove and Rajan Agaskar
8f0f0a607e update self test to work with gem runner interface 2013-09-20 11:09:35 -07:00
Gregg Van Hove and Rajan Agaskar
4891d578e3 Set default rake task 2013-09-19 10:15:15 -07:00
Sheel Choksi
efc384c6d6 Allow Env to take optional spec/suite ids when asked to execute 2013-09-17 19:55:49 -07:00
Sheel Choksi
d60786a06c More clearly differentiate between spec and suite ids 2013-09-17 19:55:48 -07:00
Sheel Choksi
66010d01ec Give reporting symbols a little bit more height
Ensures they don't appear cut off when in the last row
2013-09-16 21:05:24 -07:00
Sheel Choksi
1619067ddd Merge pull request #428 from tjgrathwell/htmlreporter-inline-block-dots
Change HTMLReporter symbols to be inline-block instead of floated
2013-09-16 20:55:49 -07:00
Travis Grathwell
79a75f5bdb HTMLReporter symbols are inline-block rather than floated
On a very large test suite (8000 specs), a significant amount
of time is spent just drawing the spec dots. Some sort of
worse-than-linear artifact that summons itself only when you
have 8000 floated elements trying to hang out together.

This performance penalty is not seen with inline-block.

In Chrome 29:
  Floated dots: 16.795s
  Inline-block dots: 2.774s

Setting the dots to 'display: none;' takes about the same time
as the inline-block figure, so this is probably a low enough bound
(no need for chunked rendering or who knows what).
2013-09-10 19:46:51 -07:00
Sheel Choksi
7158e048a6 Update Jasmine CSS build process
- Update compass configuration to build jasmine.scss into lib
- Remove src/html/jasmine.css (since jasmine.scss builds directly into
    lib now)
- Bump lib/jasmine-core/jasmine.css to be latest from scss
2013-09-09 21:41:24 -07:00
Sheel Choksi
f8f064d12d Update jasmine-performance.yml
Get it back into working condition and more similar to jasmine.yml
2013-09-09 21:41:24 -07:00
Sheel Choksi
8ac085c103 Use jasmine.DEFAULT_TIMEOUT_INTERVAL for async timeout
Allows a user to specify their desired timeout interval for async specs
and change it on a per spec basis (for particularly slow specs, for example).

As pointed out by @Eric-Wright in #422. [finishes #55996798]
2013-09-08 21:41:45 -07:00
Sheel Choksi
03dfea967c Remove unused jasmine.DEFAULT_UPDATE_INTERVAL 2013-09-08 14:18:34 -07:00
Sheel Choksi
f463e1f7aa Consistent 'this' between befores/it/afters
Change the 'this' user functions are called with to be an empty object
instead of the QueueRunner so that if the user puts properties on it,
        they won't conflict.

Also, changes async specs to be called with a proper 'this', as pointed
out by @Eric-Wright in #419 and #420.

[finishes #56030080]
2013-09-07 18:28:03 -07:00
Sheel Choksi
4bff199c2a Rename a spy's callReturn and callThrow
.and.callReturn is now .and.returnValue
.and.callThrow is now .and.throwError

[finishes #56281634]
2013-09-06 21:55:14 -07:00
Sheel Choksi
e3f0389ac2 Change andThrow to always throw an Error
If an error is passed in, it is thrown, otherwise the argument passed
in is wrapped in an Error

[finishes #50607615][closes #372]
2013-09-05 23:05:45 -07:00
Sheel Choksi
be0f7b4117 EnvSpec for timing out async spec fix
Spec still can't work for maximumSpecCallbackDepth = 1 until further
mock clock enhancements. Fixes the specs running twice issue caused by
the previous commit.
2013-09-02 21:48:44 -07:00
Sheel Choksi
edb46a6f7c Fix spec in EnvSpec.js for specs that hang
This spec would hang when maximumSpecCallbackDepth was set to 1
[Fixes #54168730]
2013-09-02 20:39:37 -07:00
Sheel Choksi
a442acb8aa Mock Clock now correctly schedules delayed functions during a 'tick' 2013-09-02 18:50:17 -07:00
Davis W. Frank
fc409f39a1 Workaround and bug exposure for IE8 and PrettyPrinter, which doesn't work well when trying to pretty print the native timer functions on IE. Make Jasmine's suite green and call out for a fix once we re-write the pretty printer. [Finishes #54168708] 2013-09-01 15:38:14 -07:00
Davis W. Frank
ba55cb5e38 Mock clock now less intrusive, replacing global timer funcions only when clock is installed. [Fixes #54168708] 2013-08-27 22:46:01 -07:00
Davis W. Frank
2d4f398dd6 Merge branch 'master' of https://github.com/pivotal/jasmine 2013-08-27 22:43:06 -07:00
Sheel Choksi
5ba6e51e1c Restore custom failure messages for toHaveBeenCalledWith
As pointed out by @tjgrathwell
2013-08-26 23:24:43 -07:00
Davis W. Frank
ba43e37356 Updating GOALS doc after rc2 2013-08-06 08:04:37 -07:00
Sheel Choksi
0f42f2709a Update PrettyPrinter to better check for an Object
Includes test case to fix FF as suggested by @ondras
Fixes #409
2013-08-03 11:49:20 -07:00
Sheel Choksi
4c4317b80e Update BrowserFlags to include Firefox
- DRYs up the browser checking code
- Adds in Firefox as another flag
- Makes it possible to do checks like `if (env.ieVersion)` to target all
IE versions
2013-08-03 11:45:13 -07:00
Davis W. Frank
b4bb99dfdf Merge pull request #410 from martyhines/fix-broken-link
Updated contribute.markdown links
2013-07-31 07:54:42 -07:00
martyhines
d721418490 Updated contribute.markdown links 2013-07-31 10:40:28 -04:00
Davis W. Frank
45fd8df861 Adding ignores for latest RVM/RbEnv convention 2013-07-30 08:08:24 -07:00
Davis W. Frank
0e800ee243 Rename to GitHub convention; Makes this doc available during pull request creation 2013-07-30 08:07:22 -07:00
Davis W. Frank
8a8cc03dea Add release notes & GitHub releases instructions 2013-07-28 20:59:57 -07:00
94 changed files with 1997 additions and 1502 deletions

3
.gitignore vendored
View File

@@ -5,6 +5,8 @@ site/
.bundle/
.pairs
.rvmrc
.ruby-gemset
.ruby-version
*.gem
.bundle
tags
@@ -13,4 +15,5 @@ pkg/*
.sass-cache/*
src/html/.sass-cache/*
node_modules/
sauce_connect.log
*.swp

9
.jshintrc Normal file
View File

@@ -0,0 +1,9 @@
{
"bitwise": true,
"curly": true,
"freeze": true,
"immed": true,
"newcap": true,
"trailing": true,
"loopfunc": true
}

View File

@@ -7,6 +7,9 @@ env:
- USE_SAUCE=true
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="firefox"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- secure: WSPWhlnC4mWSnSPquX+m1/BCu5ch5NygkaHuM2Nea7lD8oS3XLX8QncZZAsQ4lnNfqoDDuBOizG0AESiqNvE4y6x5qvLLTS6q+ce255ZEMZ71TBdZgDEEvGMEjOPPsVXiXyTQOP1lwOPlrbZvaPgWV7e11KIBab6DfFcQpnvDgo=
- secure: SW7CJhZnwaNT749Gdnhvqb5rbXlAOsygUAzh9qhtyvbqXKkmJdBIEsO01YF6pbju1X2twE9JvWCOxeZju43NgQChJlPsGbjY2j3k/TdQeTAJesQe2K7ytwghunI30gjEovtRH0T3w1EmcKPH8yj5eBIcB2OYoJHx8KEC7e68q1g=
matrix:
@@ -14,34 +17,34 @@ matrix:
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh"
- env:
- JASMINE_BROWSER="firefox"
- SAUCE_PLATFORM="Linux"
- SAUCE_VERSION=''
- env:
- JASMINE_BROWSER="safari"
- SAUCE_PLATFORM="OS X 10.8"
- SAUCE_VERSION=6
- env:
- JASMINE_BROWSER="safari"
- SAUCE_PLATFORM="OS X 10.6"
- SAUCE_VERSION=5
- env:
- SAUCE_OS="OS X 10.8"
- SAUCE_BROWSER_VERSION=6
- env:
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.6"
- SAUCE_BROWSER_VERSION=5
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_PLATFORM="Windows 8"
- SAUCE_VERSION=10
- env:
- SAUCE_OS="Windows 8"
- SAUCE_BROWSER_VERSION=10
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_PLATFORM="Windows 7"
- SAUCE_VERSION=9
- env:
- SAUCE_OS="Windows 7"
- SAUCE_BROWSER_VERSION=9
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_PLATFORM="Windows 7"
- SAUCE_VERSION=8
- env:
- SAUCE_OS="Windows 7"
- SAUCE_BROWSER_VERSION=8
- env:
- JASMINE_BROWSER="chrome"
- SAUCE_PLATFORM="Linux"
- SAUCE_VERSION=''
- env:
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- env:
- JASMINE_BROWSER="phantomjs"
- USE_SAUCE=false
- env:
- USE_SAUCE=false
- JASMINE_BROWSER="phantomjs"
- TEST_COMMAND="bash travis-docs-script.sh"

View File

@@ -107,5 +107,10 @@ Jasmine uses Node.js with a custom runner to test outside of a browser.
1. Ensure JSHint is green with `grunt jsHint`
1. Build `jasmine.js` with `grunt buildDistribution` and run all specs again - this ensures that your changes self-test well
## Submitting a Pull Request
1. Revert your changes to `jasmine.js` and `jasmine-html.js`
* We do this because `jasmine.js` and `jasmine-html.js` are auto-generated (as you've seen in the previous steps) and accepting multiple pull requests when this auto-generated file changes causes lots of headaches.
1. When we accept your pull request, we will generate these files as a separate commit and merge the entire branch into master.
Note that we use Travis for Continuous Integration. We only accept green pull requests.

View File

@@ -20,8 +20,6 @@
* Top level (i.e., any `jasmine` property) should only be referenced inside the `Env` constructor
* should better allow any object to get jasmine code (Node-friendly)
* review everything in base.js
* Spies
* break these out into their own tests/file
* Remove isA functions:
* isArray_ - used in matchers and spies
* isString_
@@ -33,11 +31,6 @@
* inherit is only for PrettyPrinter now
* formatException is used only inside Env/spec
* htmlEscape is for messages in matchers - should this be HTML at all?
* Matchers improvements
* unit testable DONE
* better equality (from Underscore) DONE
* refactor equals function so that it just loops & recurses over a list of fns (custom and built-in) - 2.1?
* addCustomMatchers doesn't explode stack
* Pretty printing
* move away from pretty printer and to a JSON.stringify implementation?
* jasmineToString vs. custom toString ?
@@ -47,6 +40,16 @@
* unify params to ctors: options vs. attrs.
* This will be a lot of the TODOs, but clean up & simplify Env.js (is this a 2.1 task?)
### DONE
* Matchers improvements
* unit testable DONE
* better equality (from Underscore) DONE
* addCustomMatchers doesn't explode stack DONE
* refactor equals function so that it just loops & recurses over a list of fns (custom and built-in) - 2.1? (Tracker story)
* Spies
* break these out into their own tests/file DONE
## Other Topics
* Docs

View File

@@ -1,7 +1,6 @@
source 'https://rubygems.org'
gem "rake"
gem "jasmine", :git => 'https://github.com/pivotal/jasmine-gem.git'
#gem "jasmine", path: "/Users/pivotal/workspace/jasmine-gem"
# gem "jasmine", path: "/Users/pivotal/workspace/jasmine-gem"
unless ENV["TRAVIS"]
group :debug do
gem 'debugger'
@@ -9,3 +8,7 @@ unless ENV["TRAVIS"]
end
gemspec
gem "jasmine_selenium_runner", :git => 'https://github.com/jasmine/jasmine_selenium_runner.git'
gem "anchorman"

View File

@@ -1,4 +1,4 @@
<a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a> [![Build Status](https://travis-ci.org/pivotal/jasmine.png?branch=master)](https://travis-ci.org/pivotal/jasmine)
<a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a> [![Build Status](https://travis-ci.org/pivotal/jasmine.png?branch=master)](https://travis-ci.org/pivotal/jasmine) [![Code Climate](https://codeclimate.com/repos/5269970a13d6374b6c01d632/badges/8bc25526da64e02065f4/gpa.png)](https://codeclimate.com/repos/5269970a13d6374b6c01d632/feed)
=======
**A JavaScript Testing Framework**
@@ -9,7 +9,7 @@ Documentation & guides live here: [http://pivotal.github.com/jasmine/](http://pi
## Contributing
Please read the [contributors' guide](https://github.com/pivotal/jasmine/blob/master/Contribute.markdown)
Please read the [contributors' guide](https://github.com/pivotal/jasmine/blob/master/CONTRIBUTING.md)
## Support
@@ -22,6 +22,10 @@ Please read the [contributors' guide](https://github.com/pivotal/jasmine/blob/ma
* [Davis W. Frank](mailto:dwfrank@pivotallabs.com), Pivotal Labs
* [Rajan Agaskar](mailto:rajan@pivotallabs.com), Pivotal Labs
* [Sheel Choksi](mailto:schoksi@pivotallabs.com), Pivotal Labs
### Maintainers Emeritus
* [Christian Williams](mailto:antixian666@gmail.com), Square
Copyright (c) 2008-2013 Pivotal Labs. This software is licensed under the MIT License.

View File

@@ -2,38 +2,16 @@ require "bundler"
Bundler::GemHelper.install_tasks
require "json"
require "jasmine"
Dir["#{File.dirname(__FILE__)}/tasks/**/*.rb"].each do |file|
require file
end
# TODO: Is there better way to invoke this using Jasmine gem???
task :core_spec do
exec "ruby spec/jasmine_self_test_spec.rb"
unless ENV["JASMINE_BROWSER"] == 'phantomjs'
require "jasmine_selenium_runner"
end
load "jasmine/tasks/jasmine.rake"
namespace :jasmine do
task :server do
port = ENV['JASMINE_PORT'] || 8888
jasmine_yml = ENV['JASMINE_YML'] || 'jasmine.yml'
Jasmine.load_configuration_from_yaml(File.join(Dir.pwd, 'spec', jasmine_yml))
config = Jasmine.config
server = Jasmine::Server.new(port, Jasmine::Application.app(config))
server.start
puts "your tests are here:"
puts " http://localhost:#{port}/"
end
desc "Copy examples from Jasmine JS to the gem"
task :copy_examples_to_gem do
require "fileutils"
# copy jasmine's example tree into our generator templates dir
FileUtils.rm_r('generators/jasmine/templates/jasmine-example', :force => true)
FileUtils.cp_r(File.join(Jasmine::Core.path, 'example'), 'generators/jasmine/templates/jasmine-example', :preserve => true)
task :set_env do
ENV['JASMINE_CONFIG_PATH'] ||= 'spec/support/jasmine.yml'
end
end
desc "Run specs via server"
task :jasmine => ['jasmine:server']
task "jasmine:configure" => "jasmine:set_env"

View File

@@ -3,7 +3,7 @@
## Development
___Jasmine Core Maintainers Only___
Follow the instructions in `Contribute.markdown` during development.
Follow the instructions in `CONTRIBUTING.md` during development.
### Git Rules
@@ -33,6 +33,7 @@ If you want to submit changes to this repo and aren't a Pivotal Labs employee, y
When ready to release - specs are all green and the stories are done:
1. Update the release notes in `release_notes` - use the Anchorman gem to generate the markdown file and edit accordingly
1. Update the version in `package.json` to a release candidate
1. Update any links or top-level landing page for the Github Pages
1. Build the standalone distribution with `grunt buildStandaloneDist`
@@ -42,6 +43,7 @@ When ready to release - specs are all green and the stories are done:
1. __NOTE__: You will likely need to push a new jasmine gem with a dependent version right after this release.
1. Push these changes to GitHub and verify that this SHA is green
1. `rake release` - tags the repo with the version, builds the `jasmine-core` gem, pushes the gem to Rubygems.org. In order to release you will have to ensure you have rubygems creds locally.
1. Visit the [Releases page for Jasmine](https://github.com/pivotal/jasmine/releases), find the tag just pushed. Paste in a link to the correct release notes for this release. The link should reference the blob and tag correctly, and the markdown file for the notes. If it is a pre-release, mark it as such.
There should be a post to Pivotal Labs blog and a tweet to that link.

BIN
dist/jasmine-standalone-1.3.1.zip vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
dist/jasmine-standalone-2.0.0-rc3.zip vendored Normal file

Binary file not shown.

BIN
dist/jasmine-standalone-2.0.0-rc5.zip vendored Normal file

Binary file not shown.

View File

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

View File

@@ -1,7 +1,8 @@
var standaloneLibDir = "lib/jasmine-" + jasmineVersion;
function root(path) { return "./" + path; }
function lib(path) { return root("lib/jasmine-core/" + path); }
function libJasmineCore(path) { return root("lib/jasmine-core/" + path); }
function libConsole() { return "lib/console/" }
function dist(path) { return root("dist/" + path); }
module.exports = {
@@ -26,13 +27,21 @@ module.exports = {
],
dest: standaloneLibDir,
expand: true,
cwd: lib("")
cwd: libJasmineCore("")
},
{
src: [
"console.js"
],
dest: standaloneLibDir,
expand: true,
cwd: libConsole()
},
{
src: [ "boot.js" ],
dest: standaloneLibDir,
expand: true,
cwd: lib("boot")
cwd: libJasmineCore("boot")
},
{
src: [ "SpecRunner.html" ],
@@ -44,13 +53,13 @@ module.exports = {
src: [ "*.js" ],
dest: "src",
expand: true,
cwd: lib("example/src/")
cwd: libJasmineCore("example/src/")
},
{
src: [ "*.js" ],
dest: "spec",
expand: true,
cwd: lib("example/spec/")
cwd: libJasmineCore("example/spec/")
}
]
}

View File

@@ -44,7 +44,7 @@ module.exports = {
'src/console/requireConsole.js',
'src/console/ConsoleReporter.js'
],
dest: 'src/console/console.js'
dest: 'lib/console/console.js'
},
options: {
banner: license(),
@@ -54,4 +54,4 @@ module.exports = {
}
}
}
};
};

View File

@@ -5,13 +5,7 @@ module.exports = {
'lib/jasmine-core/jasmine.js'
],
options: {
/* While it's possible that we could be considering unwanted prototype methods, mostly
* we're doing this because the objects are being used as maps.
*/
forin: false,
/* We're fine with functions defined inside loops (setTimeout functions, etc) */
loopfunc: true
jshintrc: '.jshintrc'
},
all: ['src/**/*.js']
};
};

View File

@@ -1,7 +1,7 @@
var grunt = require("grunt");
function standaloneTmpDir(path) { return "dist/tmp/" + path; }
grunt.registerTask("build:compileSpecRunner",
"Processes the spec runner template and writes to a tmp file",
function() {
@@ -23,6 +23,7 @@ grunt.registerTask("build:cleanSpecRunner",
grunt.registerTask("buildStandaloneDist",
"Builds a standalone distribution",
[
"buildDistribution",
"build:compileSpecRunner",
"compress:standalone",
"build:cleanSpecRunner"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 905 B

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -16,12 +16,8 @@ Gem::Specification.new do |s|
s.files = Dir.glob("./lib/**/*") + Dir.glob("./lib/jasmine-core/spec/**/*.js")
s.require_paths = ["lib"]
s.add_development_dependency "json_pure", ">= 1.4.3"
s.add_development_dependency "sass"
s.add_development_dependency "compass"
s.add_development_dependency "rspec"
s.add_development_dependency "fuubar"
s.add_development_dependency "awesome_print"
s.add_development_dependency "nokogiri"
s.add_development_dependency "rake"
s.add_development_dependency "sauce-connect"
s.add_development_dependency "jasmine_selenium_runner"
s.add_development_dependency "compass"
end

View File

@@ -20,13 +20,40 @@ 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.
*/
// Jasmine boot.js for browser runners - exposes external/global interface, builds the Jasmine environment and executes it.
/**
Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
The location of `boot.js` can be specified and/or overridden in `jasmine.yml`.
[jasmine-gem]: http://github.com/pivotal/jasmine-gem
*/
(function() {
/**
* ## Require &amp; Instantiate
*
* Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
*/
window.jasmine = jasmineRequire.core(jasmineRequire);
/**
* Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
*/
jasmineRequire.html(jasmine);
/**
* Create the Jasmine environment. This is used to run all specs in a project.
*/
var env = jasmine.getEnv();
/**
* ## The Global Interface
*
* Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
*/
var jasmineInterface = {
describe: function(description, specDefinitions) {
return env.describe(description, specDefinitions);
@@ -60,41 +87,64 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
return env.pending();
},
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName);
},
clock: env.clock,
setTimeout: env.clock.setTimeout,
clearTimeout: env.clock.clearTimeout,
setInterval: env.clock.setInterval,
clearInterval: env.clock.clearInterval,
jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer()
})
};
/**
* Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
*/
if (typeof window == "undefined" && typeof exports == "object") {
extend(exports, jasmineInterface);
} else {
extend(window, jasmineInterface);
}
/**
* Expose the interface for adding custom equality testers.
*/
jasmine.addCustomEqualityTester = function(tester) {
env.addCustomEqualityTester(tester);
};
/**
* Expose the interface for adding custom expectation matchers
*/
jasmine.addMatchers = function(matchers) {
return env.addMatchers(matchers);
};
/**
* Expose the mock interface for the JavaScript timeout functions
*/
jasmine.clock = function() {
return env.clock;
};
/**
* ## Runner Parameters
*
* More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
*/
var queryString = new jasmine.QueryString({
getWindowLocation: function() { return window.location; }
});
// TODO: move all of catching to raise so we don't break our brains
var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
/**
* ## Reporters
* The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
*/
var htmlReporter = new jasmine.HtmlReporter({
env: env,
queryString: queryString,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
@@ -102,9 +152,15 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
timer: new jasmine.Timer()
});
/**
* The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript.
*/
env.addReporter(jasmineInterface.jsApiReporter);
env.addReporter(htmlReporter);
/**
* Filter which specs will be run by matching the start of the full name against the `spec` query param.
*/
var specFilter = new jasmine.HtmlSpecFilter({
filterString: function() { return queryString.getParam("spec"); }
});
@@ -113,6 +169,19 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
return specFilter.matches(spec.getFullName());
};
/**
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
*/
window.setTimeout = window.setTimeout;
window.setInterval = window.setInterval;
window.clearTimeout = window.clearTimeout;
window.clearInterval = window.clearInterval;
/**
* ## Execution
*
* Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
*/
var currentWindowOnload = window.onload;
window.onload = function() {
@@ -123,6 +192,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
env.execute();
};
/**
* Helper function for readability above.
*/
function extend(destination, source) {
for (var property in source) destination[property] = source[property];
return destination;

View File

@@ -1,10 +1,37 @@
// Jasmine boot.js for browser runners - exposes external/global interface, builds the Jasmine environment and executes it.
/**
Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
The location of `boot.js` can be specified and/or overridden in `jasmine.yml`.
[jasmine-gem]: http://github.com/pivotal/jasmine-gem
*/
(function() {
/**
* ## Require &amp; Instantiate
*
* Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
*/
window.jasmine = jasmineRequire.core(jasmineRequire);
/**
* Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
*/
jasmineRequire.html(jasmine);
/**
* Create the Jasmine environment. This is used to run all specs in a project.
*/
var env = jasmine.getEnv();
/**
* ## The Global Interface
*
* Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
*/
var jasmineInterface = {
describe: function(description, specDefinitions) {
return env.describe(description, specDefinitions);
@@ -38,41 +65,64 @@
return env.pending();
},
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName);
},
clock: env.clock,
setTimeout: env.clock.setTimeout,
clearTimeout: env.clock.clearTimeout,
setInterval: env.clock.setInterval,
clearInterval: env.clock.clearInterval,
jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer()
})
};
/**
* Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
*/
if (typeof window == "undefined" && typeof exports == "object") {
extend(exports, jasmineInterface);
} else {
extend(window, jasmineInterface);
}
/**
* Expose the interface for adding custom equality testers.
*/
jasmine.addCustomEqualityTester = function(tester) {
env.addCustomEqualityTester(tester);
};
/**
* Expose the interface for adding custom expectation matchers
*/
jasmine.addMatchers = function(matchers) {
return env.addMatchers(matchers);
};
/**
* Expose the mock interface for the JavaScript timeout functions
*/
jasmine.clock = function() {
return env.clock;
};
/**
* ## Runner Parameters
*
* More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
*/
var queryString = new jasmine.QueryString({
getWindowLocation: function() { return window.location; }
});
// TODO: move all of catching to raise so we don't break our brains
var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
/**
* ## Reporters
* The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
*/
var htmlReporter = new jasmine.HtmlReporter({
env: env,
queryString: queryString,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
@@ -80,9 +130,15 @@
timer: new jasmine.Timer()
});
/**
* The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript.
*/
env.addReporter(jasmineInterface.jsApiReporter);
env.addReporter(htmlReporter);
/**
* Filter which specs will be run by matching the start of the full name against the `spec` query param.
*/
var specFilter = new jasmine.HtmlSpecFilter({
filterString: function() { return queryString.getParam("spec"); }
});
@@ -91,6 +147,19 @@
return specFilter.matches(spec.getFullName());
};
/**
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
*/
window.setTimeout = window.setTimeout;
window.setInterval = window.setInterval;
window.clearTimeout = window.clearTimeout;
window.clearInterval = window.clearInterval;
/**
* ## Execution
*
* Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
*/
var currentWindowOnload = window.onload;
window.onload = function() {
@@ -101,6 +170,9 @@
env.execute();
};
/**
* Helper function for readability above.
*/
function extend(destination, source) {
for (var property in source) destination[property] = source[property];
return destination;

View File

@@ -26,11 +26,12 @@ jasmineRequire.html = function(j$) {
j$.QueryString = jasmineRequire.QueryString();
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
};
jasmineRequire.HtmlReporter = function(j$) {
var noopTimer = {
start: function(){},
elapsed: function(){ return 0; }
start: function() {},
elapsed: function() { return 0; }
};
function HtmlReporter(options) {
@@ -101,7 +102,8 @@ jasmineRequire.HtmlReporter = function(j$) {
symbols.appendChild(createDom("li", {
className: result.status,
id: "spec_" + result.id,
title: result.fullName}
title: result.fullName
}
));
if (result.status == "failed") {
@@ -109,7 +111,9 @@ jasmineRequire.HtmlReporter = function(j$) {
var failure =
createDom("div", {className: "spec-detail failed"},
createDom("a", {className: "description", title: result.fullName, href: specHref(result)}, result.fullName),
createDom("div", {className: "description"},
createDom("a", {title: result.fullName, href: specHref(result)}, result.fullName)
),
createDom("div", {className: "messages"})
);
var messages = failure.childNodes[1];
@@ -305,6 +309,7 @@ jasmineRequire.ResultsNode = function() {
return ResultsNode;
};
jasmineRequire.QueryString = function() {
function QueryString(options) {

View File

@@ -11,7 +11,7 @@ body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
.html-reporter .banner { margin-top: 14px; }
.html-reporter .duration { color: #aaaaaa; float: right; }
.html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; }
.html-reporter .symbol-summary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
.html-reporter .symbol-summary li { display: inline-block; height: 8px; width: 14px; font-size: 16px; }
.html-reporter .symbol-summary li.passed { font-size: 14px; }
.html-reporter .symbol-summary li.passed:before { color: #5e7d00; content: "\02022"; }
.html-reporter .symbol-summary li.failed { line-height: 9px; }
@@ -48,7 +48,8 @@ body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
.html-reporter .suite { margin-top: 14px; }
.html-reporter .suite a { color: #333333; }
.html-reporter .failures .spec-detail { margin-bottom: 28px; }
.html-reporter .failures .spec-detail .description { display: block; color: white; background-color: #b03911; }
.html-reporter .failures .spec-detail .description { background-color: #b03911; }
.html-reporter .failures .spec-detail .description a { color: white; }
.html-reporter .result-message { padding-top: 14px; color: #333333; white-space: pre; }
.html-reporter .result-message span.result { display: block; }
.html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #dddddd; background: white; white-space: pre; }
.html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }

View File

@@ -30,7 +30,7 @@ function getJasmineRequireObj() {
}
getJasmineRequireObj().core = function(jRequire) {
j$ = {};
var j$ = {};
jRequire.base(j$);
j$.util = jRequire.util();
@@ -48,7 +48,7 @@ getJasmineRequireObj().core = function(jRequire) {
j$.pp = jRequire.pp(j$);
j$.QueueRunner = jRequire.QueueRunner();
j$.ReportDispatcher = jRequire.ReportDispatcher();
j$.Spec = jRequire.Spec();
j$.Spec = jRequire.Spec(j$);
j$.SpyStrategy = jRequire.SpyStrategy();
j$.Suite = jRequire.Suite();
j$.Timer = jRequire.Timer();
@@ -94,7 +94,6 @@ getJasmineRequireObj().base = function(j$) {
throw new Error("unimplemented method");
};
j$.DEFAULT_UPDATE_INTERVAL = 250;
j$.MAX_PRETTY_PRINT_DEPTH = 40;
j$.DEFAULT_TIMEOUT_INTERVAL = 5000;
@@ -143,18 +142,18 @@ getJasmineRequireObj().base = function(j$) {
j$.createSpy = function(name, originalFn) {
var spyStrategy = new j$.SpyStrategy({
name: name,
fn: originalFn,
getSpy: function() { return spy; }
}),
callTracker = new j$.CallTracker(),
spy = function() {
callTracker.track({
object: this,
args: Array.prototype.slice.apply(arguments)
});
return spyStrategy.exec.apply(this, arguments);
};
name: name,
fn: originalFn,
getSpy: function() { return spy; }
}),
callTracker = new j$.CallTracker(),
spy = function() {
callTracker.track({
object: this,
args: Array.prototype.slice.apply(arguments)
});
return spyStrategy.exec.apply(this, arguments);
};
for (var prop in originalFn) {
if (prop === 'and' || prop === 'calls') {
@@ -175,7 +174,7 @@ getJasmineRequireObj().base = function(j$) {
return false;
}
return putativeSpy.and instanceof j$.SpyStrategy &&
putativeSpy.calls instanceof j$.CallTracker;
putativeSpy.calls instanceof j$.CallTracker;
};
j$.createSpyObj = function(baseName, methodNames) {
@@ -195,14 +194,16 @@ getJasmineRequireObj().util = function() {
var util = {};
util.inherit = function(childClass, parentClass) {
var subclass = function() {
var Subclass = function() {
};
subclass.prototype = parentClass.prototype;
childClass.prototype = new subclass();
Subclass.prototype = parentClass.prototype;
childClass.prototype = new Subclass();
};
util.htmlEscape = function(str) {
if (!str) return str;
if (!str) {
return str;
}
return str.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
@@ -210,7 +211,9 @@ getJasmineRequireObj().util = function() {
util.argsToArray = function(args) {
var arrayOfArgs = [];
for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
for (var i = 0; i < args.length; i++) {
arrayOfArgs.push(args[i]);
}
return arrayOfArgs;
};
@@ -221,9 +224,8 @@ getJasmineRequireObj().util = function() {
return util;
};
getJasmineRequireObj().Spec = function() {
getJasmineRequireObj().Spec = function(j$) {
function Spec(attrs) {
this.encounteredExpectations = false;
this.expectationFactory = attrs.expectationFactory;
this.resultCallback = attrs.resultCallback || function() {};
this.id = attrs.id;
@@ -249,13 +251,11 @@ getJasmineRequireObj().Spec = function() {
id: this.id,
description: this.description,
fullName: this.getFullName(),
status: this.status(),
failedExpectations: []
};
}
Spec.prototype.addExpectationResult = function(passed, data) {
this.encounteredExpectations = true;
if (passed) {
return;
}
@@ -279,22 +279,22 @@ getJasmineRequireObj().Spec = function() {
function timeoutable(fn) {
return function(done) {
var timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
onException(new Error('timeout'));
onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
done();
}, 10000]]);
}, j$.DEFAULT_TIMEOUT_INTERVAL]]);
var callDone = function() {
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
done();
};
fn(callDone); //TODO: do we care about more than 1 arg?
fn.call(this, callDone); //TODO: do we care about more than 1 arg?
};
}
var befores = this.beforeFns() || [],
afters = this.afterFns() || [],
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
afters = this.afterFns() || [],
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
var allFns = befores.concat(thisOne).concat(afters);
this.queueRunner({
@@ -304,18 +304,18 @@ getJasmineRequireObj().Spec = function() {
});
function onException(e) {
if (Spec.isPendingSpecException(e)) {
self.pend();
return;
}
if (Spec.isPendingSpecException(e)) {
self.pend();
return;
}
self.addExpectationResult(false, {
matcherName: "",
passed: false,
expected: "",
actual: "",
error: e
});
self.addExpectationResult(false, {
matcherName: "",
passed: false,
expected: "",
actual: "",
error: e
});
}
function complete() {
@@ -341,7 +341,7 @@ getJasmineRequireObj().Spec = function() {
return 'disabled';
}
if (this.markedPending || !this.encounteredExpectations) {
if (this.markedPending) {
return 'pending';
}
@@ -376,17 +376,22 @@ getJasmineRequireObj().Env = function(j$) {
var self = this;
var global = options.global || j$.getGlobal();
var totalSpecsDefined = 0;
var catchExceptions = true;
var realSetTimeout = j$.getGlobal().setTimeout;
var realClearTimeout = j$.getGlobal().clearTimeout;
this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler());
var runnableLookupTable = {};
var spies = [];
this.currentSpec = null;
var currentSpec = null;
var currentSuite = null;
this.reporter = new j$.ReportDispatcher([
var reporter = new j$.ReportDispatcher([
"jasmineStarted",
"jasmineDone",
"suiteStarted",
@@ -395,14 +400,11 @@ getJasmineRequireObj().Env = function(j$) {
"specDone"
]);
this.lastUpdate = 0;
this.specFilter = function() {
return true;
};
this.nextSpecId_ = 0;
this.nextSuiteId_ = 0;
this.equalityTesters_ = [];
var equalityTesters = [];
var customEqualityTesters = [];
this.addCustomEqualityTester = function(tester) {
@@ -411,6 +413,16 @@ getJasmineRequireObj().Env = function(j$) {
j$.Expectation.addCoreMatchers(j$.matchers);
var nextSpecId = 0;
var getNextSpecId = function() {
return 'spec' + nextSpecId++;
};
var nextSuiteId = 0;
var getNextSuiteId = function() {
return 'suite' + nextSuiteId++;
};
var expectationFactory = function(actual, spec) {
return j$.Expectation.Factory({
util: j$.matchersUtil,
@@ -425,32 +437,34 @@ getJasmineRequireObj().Env = function(j$) {
};
var specStarted = function(spec) {
self.currentSpec = spec;
self.reporter.specStarted(spec.result);
currentSpec = spec;
reporter.specStarted(spec.result);
};
var beforeFns = function(currentSuite) {
var beforeFns = function(suite) {
return function() {
var befores = [];
for (var suite = currentSuite; suite; suite = suite.parentSuite) {
while(suite) {
befores = befores.concat(suite.beforeFns);
suite = suite.parentSuite;
}
return befores.reverse();
};
};
var afterFns = function(currentSuite) {
var afterFns = function(suite) {
return function() {
var afters = [];
for (var suite = currentSuite; suite; suite = suite.parentSuite) {
while(suite) {
afters = afters.concat(suite.afterFns);
suite = suite.parentSuite;
}
return afters;
};
};
var getSpecName = function(spec, currentSuite) {
return currentSuite.getFullName() + ' ' + spec.description + '.';
var getSpecName = function(spec, suite) {
return suite.getFullName() + ' ' + spec.description;
};
// TODO: we may just be able to pass in the fn instead of wrapping here
@@ -473,10 +487,6 @@ getJasmineRequireObj().Env = function(j$) {
return catchExceptions;
};
this.catchException = function(e) {
return j$.Spec.isPendingSpecException(e) || catchExceptions;
};
var maximumSpecCallbackDepth = 20;
var currentSpecCallbackDepth = 0;
@@ -490,94 +500,53 @@ getJasmineRequireObj().Env = function(j$) {
}
}
var catchException = function(e) {
return j$.Spec.isPendingSpecException(e) || catchExceptions;
};
var queueRunnerFactory = function(options) {
options.catchException = self.catchException;
options.catchException = catchException;
options.clearStack = options.clearStack || clearStack;
new j$.QueueRunner(options).run(options.fns, 0);
new j$.QueueRunner(options).execute();
};
var totalSpecsDefined = 0;
this.specFactory = function(description, fn, suite) {
totalSpecsDefined++;
var spec = new j$.Spec({
id: self.nextSpecId(),
beforeFns: beforeFns(suite),
afterFns: afterFns(suite),
expectationFactory: expectationFactory,
exceptionFormatter: exceptionFormatter,
resultCallback: specResultCallback,
getSpecName: function(spec) {
return getSpecName(spec, suite);
},
onStart: specStarted,
description: description,
expectationResultFactory: expectationResultFactory,
queueRunner: queueRunnerFactory,
fn: fn,
timer: {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}
});
if (!self.specFilter(spec)) {
spec.disable();
}
return spec;
function removeAllSpies() {
for (var i = 0; i < spies.length; i++) {
var spyEntry = spies[i];
spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
}
spies = [];
}
function specResultCallback(result) {
removeAllSpies();
j$.Expectation.resetMatchers();
customEqualityTesters.length = 0;
self.clock.uninstall();
self.currentSpec = null;
self.reporter.specDone(result);
}
};
var suiteStarted = function(suite) {
self.reporter.suiteStarted(suite.result);
};
var suiteConstructor = j$.Suite;
this.topSuite = new j$.Suite({
var topSuite = new j$.Suite({
env: this,
id: this.nextSuiteId(),
id: getNextSuiteId(),
description: 'Jasmine__TopLevel__Suite',
queueRunner: queueRunnerFactory,
completeCallback: function() {}, // TODO - hook this up
resultCallback: function() {} // TODO - hook this up
});
this.currentSuite = this.topSuite;
runnableLookupTable[topSuite.id] = topSuite;
currentSuite = topSuite;
this.suiteFactory = function(description) {
return new suiteConstructor({
env: self,
id: self.nextSuiteId(),
description: description,
parentSuite: self.currentSuite,
queueRunner: queueRunnerFactory,
onStart: suiteStarted,
resultCallback: function(attrs) {
self.reporter.suiteDone(attrs);
}
});
this.topSuite = function() {
return topSuite;
};
this.execute = function() {
this.reporter.jasmineStarted({
this.execute = function(runnablesToRun) {
runnablesToRun = runnablesToRun || [topSuite.id];
var allFns = [];
for(var i = 0; i < runnablesToRun.length; i++) {
var runnable = runnableLookupTable[runnablesToRun[i]];
allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable));
}
reporter.jasmineStarted({
totalSpecsDefined: totalSpecsDefined
});
this.topSuite.execute(self.reporter.jasmineDone);
queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone});
};
this.addReporter = function(reporterToAdd) {
reporter.addReporter(reporterToAdd);
};
this.addMatchers = function(matchersToAdd) {
j$.Expectation.addMatchers(matchersToAdd);
};
this.spyOn = function(obj, methodName) {
@@ -607,108 +576,133 @@ getJasmineRequireObj().Env = function(j$) {
return spy;
};
}
Env.prototype.addMatchers = function(matchersToAdd) {
j$.Expectation.addMatchers(matchersToAdd);
};
Env.prototype.version = function() {
return j$.version;
};
Env.prototype.expect = function(actual) {
return this.currentSpec.expect(actual);
};
// TODO: move this to closure
Env.prototype.versionString = function() {
console.log("DEPRECATED == use j$.version");
return j$.version;
};
// TODO: move this to closure
Env.prototype.nextSpecId = function() {
return this.nextSpecId_++;
};
// TODO: move this to closure
Env.prototype.nextSuiteId = function() {
return this.nextSuiteId_++;
};
// TODO: move this to closure
Env.prototype.addReporter = function(reporter) {
this.reporter.addReporter(reporter);
};
// TODO: move this to closure
Env.prototype.describe = function(description, specDefinitions) {
var suite = this.suiteFactory(description);
var parentSuite = this.currentSuite;
parentSuite.addSuite(suite);
this.currentSuite = suite;
var declarationError = null;
try {
specDefinitions.call(suite);
} catch (e) {
declarationError = e;
}
if (declarationError) {
this.it("encountered a declaration exception", function() {
throw declarationError;
var suiteFactory = function(description) {
var suite = new j$.Suite({
env: self,
id: getNextSuiteId(),
description: description,
parentSuite: currentSuite,
queueRunner: queueRunnerFactory,
onStart: suiteStarted,
resultCallback: function(attrs) {
reporter.suiteDone(attrs);
}
});
}
this.currentSuite = parentSuite;
runnableLookupTable[suite.id] = suite;
return suite;
};
return suite;
};
this.describe = function(description, specDefinitions) {
var suite = suiteFactory(description);
// TODO: move this to closure
Env.prototype.xdescribe = function(description, specDefinitions) {
var suite = this.describe(description, specDefinitions);
suite.disable();
return suite;
};
var parentSuite = currentSuite;
parentSuite.addChild(suite);
currentSuite = suite;
// TODO: move this to closure
Env.prototype.it = function(description, fn) {
var spec = this.specFactory(description, fn, this.currentSuite);
this.currentSuite.addSpec(spec);
return spec;
};
var declarationError = null;
try {
specDefinitions.call(suite);
} catch (e) {
declarationError = e;
}
// TODO: move this to closure
Env.prototype.xit = function(description, fn) {
var spec = this.it(description, fn);
spec.pend();
return spec;
};
if (declarationError) {
this.it("encountered a declaration exception", function() {
throw declarationError;
});
}
// TODO: move this to closure
Env.prototype.beforeEach = function(beforeEachFunction) {
this.currentSuite.beforeEach(beforeEachFunction);
};
currentSuite = parentSuite;
// TODO: move this to closure
Env.prototype.afterEach = function(afterEachFunction) {
this.currentSuite.afterEach(afterEachFunction);
};
return suite;
};
// TODO: move this to closure
Env.prototype.pending = function() {
throw j$.Spec.pendingSpecExceptionMessage;
};
this.xdescribe = function(description, specDefinitions) {
var suite = this.describe(description, specDefinitions);
suite.disable();
return suite;
};
// TODO: Still needed?
Env.prototype.currentRunner = function() {
return this.topSuite;
};
var specFactory = function(description, fn, suite) {
totalSpecsDefined++;
var spec = new j$.Spec({
id: getNextSpecId(),
beforeFns: beforeFns(suite),
afterFns: afterFns(suite),
expectationFactory: expectationFactory,
exceptionFormatter: exceptionFormatter,
resultCallback: specResultCallback,
getSpecName: function(spec) {
return getSpecName(spec, suite);
},
onStart: specStarted,
description: description,
expectationResultFactory: expectationResultFactory,
queueRunner: queueRunnerFactory,
fn: fn,
timer: {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}
});
runnableLookupTable[spec.id] = spec;
if (!self.specFilter(spec)) {
spec.disable();
}
return spec;
function removeAllSpies() {
for (var i = 0; i < spies.length; i++) {
var spyEntry = spies[i];
spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
}
spies = [];
}
function specResultCallback(result) {
removeAllSpies();
j$.Expectation.resetMatchers();
customEqualityTesters = [];
currentSpec = null;
reporter.specDone(result);
}
};
var suiteStarted = function(suite) {
reporter.suiteStarted(suite.result);
};
this.it = function(description, fn) {
var spec = specFactory(description, fn, currentSuite);
currentSuite.addChild(spec);
return spec;
};
this.xit = function(description, fn) {
var spec = this.it(description, fn);
spec.pend();
return spec;
};
this.expect = function(actual) {
return currentSpec.expect(actual);
};
this.beforeEach = function(beforeEachFunction) {
currentSuite.beforeEach(beforeEachFunction);
};
this.afterEach = function(afterEachFunction) {
currentSuite.afterEach(afterEachFunction);
};
this.pending = function() {
throw j$.Spec.pendingSpecExceptionMessage;
};
}
return Env;
};
@@ -823,6 +817,7 @@ getJasmineRequireObj().Any = function() {
return Any;
};
getJasmineRequireObj().CallTracker = function() {
function CallTracker() {
@@ -889,18 +884,20 @@ getJasmineRequireObj().Clock = function() {
setInterval: setInterval,
clearInterval: clearInterval
},
timer = realTimingFunctions,
installed = false;
installed = false,
timer;
self.install = function() {
installed = true;
replace(global, fakeTimingFunctions);
timer = fakeTimingFunctions;
installed = true;
};
self.uninstall = function() {
delayedFunctionScheduler.reset();
installed = false;
replace(global, realTimingFunctions);
timer = realTimingFunctions;
installed = false;
};
self.setTimeout = function(fn, delay, params) {
@@ -935,7 +932,7 @@ getJasmineRequireObj().Clock = function() {
if (installed) {
delayedFunctionScheduler.tick(millis);
} else {
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
throw new Error("Mock clock is not installed, use jasmine.clock().install()");
}
};
@@ -943,9 +940,13 @@ getJasmineRequireObj().Clock = function() {
function legacyIE() {
//if these methods are polyfilled, apply will be present
//TODO: it may be difficult to load the polyfill before jasmine loads
//(env should be new-ed inside of onload)
return !(global.setTimeout || global.setInterval).apply;
return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply;
}
function replace(dest, source) {
for (var prop in source) {
dest[prop] = source[prop];
}
}
function setTimeout(fn, delay) {
@@ -981,8 +982,8 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
self.tick = function(millis) {
millis = millis || 0;
runFunctionsWithinRange(currentTime, currentTime + millis);
currentTime = currentTime + millis;
runFunctionsWithinRange(currentTime - millis, currentTime);
};
self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) {
@@ -1140,12 +1141,21 @@ getJasmineRequireObj().Expectation = function() {
args.unshift(this.actual);
var result = matcherFactory(this.util, this.customEqualityTesters).compare.apply(null, args);
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) {
result.pass = !result.pass;
matcherCompare = matcher.negativeCompare || defaultNegativeCompare;
}
var result = matcherCompare.apply(null, args);
if (!result.pass) {
if (!result.message) {
args.unshift(this.isNot);
@@ -1323,7 +1333,7 @@ getJasmineRequireObj().pp = function(j$) {
this.emitScalar('Date(' + value + ')');
} else if (value.__Jasmine_been_here_before__) {
this.emitScalar('<circular reference: ' + (j$.isArray_(value) ? 'Array' : 'Object') + '>');
} else if (j$.isArray_(value) || typeof value == 'object') {
} else if (j$.isArray_(value) || j$.isA_('Object', value)) {
value.__Jasmine_been_here_before__ = true;
if (j$.isArray_(value)) {
this.emitArray(value);
@@ -1341,8 +1351,8 @@ getJasmineRequireObj().pp = function(j$) {
PrettyPrinter.prototype.iterateObject = function(obj, fn) {
for (var property in obj) {
if (!obj.hasOwnProperty(property)) continue;
if (property == '__Jasmine_been_here_before__') continue;
if (!obj.hasOwnProperty(property)) { continue; }
if (property == '__Jasmine_been_here_before__') { continue; }
fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) &&
obj.__lookupGetter__(property) !== null) : false);
}
@@ -1433,6 +1443,7 @@ getJasmineRequireObj().QueueRunner = function() {
this.clearStack = attrs.clearStack || function(fn) {fn();};
this.onException = attrs.onException || function() {};
this.catchException = attrs.catchException || function() { return true; };
this.userContext = {};
}
QueueRunner.prototype.execute = function() {
@@ -1461,7 +1472,7 @@ getJasmineRequireObj().QueueRunner = function() {
function attemptSync(fn) {
try {
fn.call(self);
fn.call(self.userContext);
} catch (e) {
handleException(e);
}
@@ -1471,7 +1482,7 @@ getJasmineRequireObj().QueueRunner = function() {
var next = function () { self.run(fns, iterativeIndex + 1); };
try {
fn.call(self, next);
fn.call(self.userContext, next);
} catch (e) {
handleException(e);
next();
@@ -1498,11 +1509,11 @@ getJasmineRequireObj().ReportDispatcher = function() {
for (var i = 0; i < dispatchedMethods.length; i++) {
var method = dispatchedMethods[i];
this[method] = function(m) {
this[method] = (function(m) {
return function() {
dispatch(m, arguments);
};
}(method);
}(method));
}
var reporters = [];
@@ -1550,16 +1561,17 @@ getJasmineRequireObj().SpyStrategy = function() {
return getSpy();
};
this.callReturn = function(value) {
this.returnValue = function(value) {
plan = function() {
return value;
};
return getSpy();
};
this.callThrow = function(something) {
this.throwError = function(something) {
var error = (something instanceof Error) ? something : new Error(something);
plan = function() {
throw something;
throw error;
};
return getSpy();
};
@@ -1585,7 +1597,6 @@ getJasmineRequireObj().Suite = function() {
this.parentSuite = attrs.parentSuite;
this.description = attrs.description;
this.onStart = attrs.onStart || function() {};
this.completeCallback = attrs.completeCallback || function() {}; // TODO: this is unused
this.resultCallback = attrs.resultCallback || function() {};
this.clearStack = attrs.clearStack || function(fn) {fn();};
@@ -1594,9 +1605,7 @@ getJasmineRequireObj().Suite = function() {
this.queueRunner = attrs.queueRunner || function() {};
this.disabled = false;
this.children_ = []; // TODO: rename
this.suites = []; // TODO: needed?
this.specs = []; // TODO: needed?
this.children = [];
this.result = {
id: this.id,
@@ -1628,19 +1637,8 @@ getJasmineRequireObj().Suite = function() {
this.afterFns.unshift(fn);
};
Suite.prototype.addSpec = function(spec) {
this.children_.push(spec);
this.specs.push(spec); // TODO: needed?
};
Suite.prototype.addSuite = function(suite) {
suite.parentSuite = this;
this.children_.push(suite);
this.suites.push(suite); // TODO: needed?
};
Suite.prototype.children = function() {
return this.children_;
Suite.prototype.addChild = function(child) {
this.children.push(child);
};
Suite.prototype.execute = function(onComplete) {
@@ -1650,11 +1648,10 @@ getJasmineRequireObj().Suite = function() {
return;
}
var allFns = [],
children = this.children_;
var allFns = [];
for (var i = 0; i < children.length; i++) {
allFns.push(wrapChildAsAsync(children[i]));
for (var i = 0; i < this.children.length; i++) {
allFns.push(wrapChildAsAsync(this.children[i]));
}
this.onStart(this);
@@ -1676,7 +1673,7 @@ getJasmineRequireObj().Suite = function() {
return function(done) { child.execute(done); };
}
};
return Suite;
};
@@ -1702,6 +1699,7 @@ getJasmineRequireObj().Timer = function() {
return Timer;
};
getJasmineRequireObj().matchersUtil = function(j$) {
// TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter?
@@ -1741,7 +1739,9 @@ getJasmineRequireObj().matchersUtil = function(j$) {
if (expected.length > 0) {
for (var i = 0; i < expected.length; i++) {
if (i > 0) message += ",";
if (i > 0) {
message += ",";
}
message += " " + j$.pp(expected[i]);
}
}
@@ -1756,9 +1756,9 @@ getJasmineRequireObj().matchersUtil = function(j$) {
var result = true;
for (var i = 0; i < customTesters.length; i++) {
result = customTesters[i](a, b);
if (result) {
return true;
var customTesterResult = customTesters[i](a, b);
if (!j$.util.isUndefined(customTesterResult)) {
return customTesterResult;
}
}
@@ -1789,11 +1789,11 @@ getJasmineRequireObj().matchersUtil = function(j$) {
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) return a !== 0 || 1 / a == 1 / b;
if (a === b) { return a !== 0 || 1 / a == 1 / b; }
// A strict comparison is necessary because `null == undefined`.
if (a === null || b === null) return a === b;
if (a === null || b === null) { return a === b; }
var className = Object.prototype.toString.call(a);
if (className != Object.prototype.toString.call(b)) return false;
if (className != Object.prototype.toString.call(b)) { return false; }
switch (className) {
// Strings, numbers, dates, and booleans are compared by value.
case '[object String]':
@@ -1817,14 +1817,14 @@ getJasmineRequireObj().matchersUtil = function(j$) {
a.multiline == b.multiline &&
a.ignoreCase == b.ignoreCase;
}
if (typeof a != 'object' || typeof b != 'object') return false;
if (typeof a != 'object' || typeof b != 'object') { return false; }
// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
var length = aStack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
if (aStack[length] == a) return bStack[length] == b;
if (aStack[length] == a) { return bStack[length] == b; }
}
// Add the first object to the stack of traversed objects.
aStack.push(a);
@@ -1838,7 +1838,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
if (result) {
// Deep compare the contents, ignoring non-numeric properties.
while (size--) {
if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) break;
if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) { break; }
}
}
} else {
@@ -1855,13 +1855,13 @@ getJasmineRequireObj().matchersUtil = function(j$) {
// Count the expected number of properties.
size++;
// Deep compare each member.
if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) break;
if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) { break; }
}
}
// Ensure that both objects contain the same number of properties.
if (result) {
for (key in b) {
if (has(b, key) && !(size--)) break;
if (has(b, key) && !(size--)) { break; }
}
result = !size;
}
@@ -1881,6 +1881,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
}
}
};
getJasmineRequireObj().toBe = function() {
function toBe() {
return {
@@ -2114,21 +2115,26 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
compare: function() {
var args = Array.prototype.slice.call(arguments, 0),
actual = args[0],
expectedArgs = args.slice(1);
expectedArgs = args.slice(1),
result = { pass: false };
if (!j$.isSpy(actual)) {
throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
}
return {
pass: util.contains(actual.calls.allArgs(), expectedArgs)
};
},
message: function(actual) {
return {
affirmative: "Expected spy " + actual.and.identity() + " to have been called.",
negative: "Expected spy " + actual.and.identity() + " not to have been called."
};
if (!actual.calls.any()) {
result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but it was never called.";
return result;
}
if (util.contains(actual.calls.allArgs(), expectedArgs)) {
result.pass = true;
result.message = "Expected spy " + actual.and.identity() + " not to have been called with " + j$.pp(expectedArgs) + " but it was.";
} else {
result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but actual calls were " + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + ".";
}
return result;
}
};
}
@@ -2357,5 +2363,5 @@ getJasmineRequireObj().toThrowError = function(j$) {
};
getJasmineRequireObj().version = function() {
return "2.0.0-rc2";
};
return "2.0.0-rc5";
};

View File

@@ -4,6 +4,6 @@
#
module Jasmine
module Core
VERSION = "2.0.0.rc2"
VERSION = "2.0.0.rc5"
end
end

View File

@@ -1,13 +1,13 @@
{
"name": "jasmine-core",
"license": "MIT",
"version": "2.0.0-rc2",
"version": "2.0.0-rc5",
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-jshint": "~0.2.0",
"grunt-contrib-concat": "~0.1.3",
"grunt-contrib-compass": "~0.1.3",
"grunt-contrib-compress": "~0.4.1",
"shelljs": "~0.1.2"
"grunt-contrib-jshint": "~0.7.0",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-compass": "~0.6.0",
"grunt-contrib-compress": "~0.5.2",
"shelljs": "~0.1.4"
}
}

View File

@@ -135,4 +135,4 @@ _Release Notes generated with [Anchorman](http://github.com/infews/anchorman)_
[travis_jasmine]: http://travis-ci.org/jasmine
[sauce]: http://saucelabs.com
[node_suite]: https://github.com/pivotal/jasmine/blob/master/spec/node_suite.js
[intro]: http://pivotal.github.com/jasmine/
[intro]: http://pivotal.github.com/jasmine/

151
release_notes/20rc3.md Normal file
View File

@@ -0,0 +1,151 @@
# Jasmine Core 2.0 Release Notes
## Summary
These notes are for RC3 of Jasmine Core 2.0.
## Breaking Changes
The [`introduction.js`][intro] page covers the current syntax, highlighting the changes. Here are known breaking interface changes that are not backwards compatible with 1.x.
* New syntax for asynchronous specs
* New syntax for spies
* New interface for reporters
* Better Equality testing
* Easier custom matchers
* Change to `toThrow` matcher
### New syntax for asynchronous specs
Similar to [Mocha][mocha], Jasmine befores, specs, and afters can take an optional "done" callback in order to force asynchronous tests. The next function, whether it's a before, spec or after, will wait until this function is called or if a timeout is reached.
### New syntax for spies
Spies have a slightly modified syntax. The ideas came from a desire to preserve any of the properties on a spied-upon function and some better testing patterns.
### New interface for reporters
The reporter interface has changed. The callbacks are different and more consistent. The objects passed in should only provide what is needed to report results. This enforces an interface to result data so custom reporters will be less coupled to Jasmine implementation. The full suite execution time is also reported.
### Better Equality testing
We have tossed the previous equality code and are now using new code for testing equality. We started with [Underscore.js][underscore]'s `isEqual`, refactored a bit and added some additional tests.
### Easier custom matchers
Custom matchers have always been possible, but this was barely documented and clunky to test. We've changed how matchers are added and tested. Jasmine adds its own matchers by the same mechanism that as custom matchers use. Dogfooding FTW.
### Change to `toThrow` matcher
We've changed the behavior of the `toThrow` matcher, moving some functionality to the `toThrowError` matcher. This should allow more of the requested use cases.
## Other Changes
* Massive refactoring and better testing
* Environment setup now in `boot.js`
* Development & Build moved to Grunt
* Change in how Jasmine is loaded
* Change in how Jasmine is tested
* Better node.js support
* Better Continuous Integration Environment at Travis
* Support matrix updated
* Removed JsDoc Pages
## Massive refactoring and better testing
This is the biggest set of changes. We've touched nearly every file and every object. We've slammed objects back together and pulled out new extractions. We've made the code more consistently styled. We've improved the tests nearly everywhere.
In general, Jasmine is made of smaller, more-loosely-coupled objects, unit-tested with explicit dependencies injected. This made tests easier to write, read, and maintain. We know this has made Jasmine development easier for the core team. We expect (and hope) this makes it easier for the community to extend Jasmine and provide pull requests that make more sense the first time out.
## Environment setup now in `boot.js`
Instantiation and setup of the Jasmine environment, including building reporters, exposing the "global" functions, and executing tests has moved into its own file: `boot.js`. This should make it easier to add custom reporters, configure some objects, or just in general change how you use Jasmine from the outside.
For example, during development, Jasmine uses it's own `devboot.js` to load itself twice - once from `jasmine.js` and once from the source directories.
## Development & Build moved to Grunt
We've moved away from Ruby and embraced Node.js and [Grunt.js][grunt] for the various command line tasks during development. Yes, it's a just a different set of dependencies. But it's less code for the team to maintain - it turns out that JavaScript tools are pretty good at building JavaScript projects. This will make it easier for the community to make sure contributions work in browser and in Node.js before submitting Pull Requests. There is more detail in the [Contributor's Guide][contrib].
## Change in how Jasmine is loaded
We did not want to add new run-time dependencies, yet we needed to be cleaner when loading Jasmine. So we wrote a custom "require" scheme that works in Node.js and in browsers. This only affects pull requests that add files - please be careful in these cases. Again, the [Contributor's Guide][contrib] should help.
## Change in how Jasmine is tested with Jasmine
Writing a custom require system helped enforce self-testing - the built `jasmine.js` testing Jasmine from the source directories. Overall this has improved the stability of the code. When you look at Jasmine's tests, you'll see both `jasmine` and `j$` used. The former, `jasmine`, will always be used to test the code from source, which is loaded into the reference `j$`. Please adhere to this pattern when writing tests for contributions.
## Better node.js support
Node.js is now officially a first-class citizen. For a long time we've made sure tests were green in Node before releasing. But it is now officially part of Jasmine's CI build at [Travis][travis]. For the curious, the [`node_suite.js`][node_suite], is essentially a `boot.js` for Node. An official npm is coming.
## Better Continuous Integration Environment at Travis
The [CI build at Travis][travis_jasmine] now runs the core specs in a build matrix across browsers. It's far from complete on the operating system matrix, but you will see that Jasmine runs against: Firefox, Chrome, Safari 5, Safari 6, Phantom.js, Node.js, and IE versions 8, 9, and 10. Big thanks to [SauceLabs][sauce] for their support of open source projects. We will happily take pull requests for additional OS/Browser combos within the matrix.
## Support Matrix Updated
We're dropping support for IE < 8. Jasmine 1.x remains for projects supporting earlier versions of browsers.
## Removed JsDoc Pages
Comments in code are lies waiting to happen. Jasmine's JsDoc comments were no exception. The comments were out of date, the generated pages were even more out of date, and frankly they were not helpful. So they're gone.
Last year saw the posting of the [`introduction.js`][intro] page to document the real, practical interface for projects to use. This page has received a lot of positive feedback so expect more pages like this one.
## Pull Requests & Issues
The following Pull Requests were merged:
* ObjectContaining wrong filed value error message #[394](https://github.com/pivotal/jasmine/issues/394) from albertandrejev
* Removed unnecessary parameter from `suiteFactory()` call #[397](https://github.com/pivotal/jasmine/issues/397) from valera-rozuvan
* `jasmine.Any` supports `Boolean` #[392](https://github.com/pivotal/jasmine/issues/392) from albertandrejev
* Reporters get execution time #[30](https://github.com/pivotal/jasmine/issues/30)
* `toThrow` matchers handle falsy exceptions #[317](https://github.com/pivotal/jasmine/issues/371)
* Removed deprecated `jasmine.Matchers.pp` #[363](https://github.com/pivotal/jasmine/issues/363) from robinboehm
* Fix for Clock ticking to default to 0 #[340](https://github.com/pivotal/jasmine/issues/340) from Caio Cunha
* Whitespace failures should be easier to understand #[332](https://github.com/pivotal/jasmine/issues/332) from bjornblomqvist
* Fix for more markdown-y image for Build status #[329](https://github.com/pivotal/jasmine/issues/329) from sunliwen
* UTF-8 encoding fixes #[333](https://github.com/pivotal/jasmine/issues/333) from bjornblomqvist
### Fixed in RC3
* Improved the performance of the HTML output with a CSS change #[428](https://github.com/pivotal/jasmine/issues/428) - Thanks @tjgrathwell
* Removed an accidental global pollution of `j$` as a reference to Jasmine. Thanks to Morten Maxild from the mailing list
There were several other pull requests that either had already been fixed, or were good starting points for the various changes above. Thank you for all of the hard work to keep Jasmine awesome.
## Other Bugs & Features
There were a few small changes and fixes that didn't fit into any of the above categories:
* HTML Reporter refactored for simplicity and performance
* Default character encoding on the HTML runner page is UTF-8
* [Escape special regex characters from the spec param](http://www.pivotaltracker.com/story/52731407)
* Favicon returns
* [Clock supports `eval`'d strings as functions](http://www.pivotaltracker.com/story/40853563)
* There should always be stack traces on failures
* Removed references to unused `jasmine.VERBOSE`
* Removed references to unused `jasmine.XmlHttpRequest`
### Fixed in RC3
* There is now a consistent `this` between `beforeEach`, `it` and `afterEach` for a spec
* A spy's strategy now has properties `returnValue` and `throwError` because they are better names
* Make it easy to copy the title of failing specs from the HTML output
* Don't add periods to the full name of a spec fix #[427](https://github.com/pivotal/jasmine/issues/427)
* Allow Env to take optional spec/suite ids when asked to `execute`
* [Mock clock now less intrusive, replacing global timer functions only when clock is installed](http://www.pivotaltracker.com/story/54168708)
* Restore custom failure messages for `toHaveBeenCalledWith`
[mocha]: http://visionmedia.github.io/mocha/
[underscore]: http://underscorejs.org/
[grunt]: http://gruntjs.com
[contrib]: https://github.com/pivotal/jasmine/blob/master/CONTRIBUTING.md
[travis]: http://travis-ci.org
[travis_jasmine]: http://travis-ci.org/jasmine
[sauce]: http://saucelabs.com
[node_suite]: https://github.com/pivotal/jasmine/blob/master/spec/node_suite.js
[intro]: http://jasmine.github.io/2.0/introduction.html
------
_Release Notes generated with [Anchorman](http://github.com/infews/anchorman)_

175
release_notes/20rc5.md Normal file
View File

@@ -0,0 +1,175 @@
# Jasmine Core 2.0 Release Notes
## Summary
These notes are for RC5 of Jasmine Core 2.0.
## Breaking Changes
The [`introduction.js`][intro] page covers the current syntax, highlighting the changes. Here are known breaking interface changes that are not backwards compatible with 1.x.
* New syntax for asynchronous specs
* New syntax for spies
* New interface for reporters
* Better Equality testing
* Easier custom matchers
* Change to `toThrow` matcher
* Clock does not uninstall itself at the end of a spec
* More Jasmine internal variables/functions have been moved into closures
### New syntax for asynchronous specs
Similar to [Mocha][mocha], Jasmine befores, specs, and afters can take an optional "done" callback in order to force asynchronous tests. The next function, whether it's a before, spec or after, will wait until this function is called or if a timeout is reached.
### New syntax for spies
Spies have a slightly modified syntax. The ideas came from a desire to preserve any of the properties on a spied-upon function and some better testing patterns.
### New interface for reporters
The reporter interface has changed. The callbacks are different and more consistent. The objects passed in should only provide what is needed to report results. This enforces an interface to result data so custom reporters will be less coupled to Jasmine implementation. The full suite execution time is also reported.
### Better Equality testing
We have tossed the previous equality code and are now using new code for testing equality. We started with [Underscore.js][underscore]'s `isEqual`, refactored a bit and added some additional tests.
### Easier custom matchers
Custom matchers have always been possible, but this was barely documented and clunky to test. We've changed how matchers are added and tested. Jasmine adds its own matchers by the same mechanism that as custom matchers use. Dogfooding FTW.
### Change to `toThrow` matcher
We've changed the behavior of the `toThrow` matcher, moving some functionality to the `toThrowError` matcher. This should allow more of the requested use cases.
### Clock does not uninstall itself at the end of a spec
After installing the Jasmine Clock, it will stay installed until uninstall is called -- clearing up any ambiguity for when those timing functions will go back to being the actual ones.
## More Jasmine internal variables/functions have been moved into closures
Certain variables/functions like a function to get the next spec id have been moved into closures, making the Jasmine interface cleaner.
## Other Changes
* Massive refactoring and better testing
* Environment setup now in `boot.js`
* Development & Build moved to Grunt
* Change in how Jasmine is loaded
* Change in how Jasmine is tested
* Better node.js support
* Better Continuous Integration Environment at Travis
* Support matrix updated
* Removed JsDoc Pages
* Adding Code Climate for JavaScript
## Massive refactoring and better testing
This is the biggest set of changes. We've touched nearly every file and every object. We've slammed objects back together and pulled out new extractions. We've made the code more consistently styled. We've improved the tests nearly everywhere.
In general, Jasmine is made of smaller, more-loosely-coupled objects, unit-tested with explicit dependencies injected. This made tests easier to write, read, and maintain. We know this has made Jasmine development easier for the core team. We expect (and hope) this makes it easier for the community to extend Jasmine and provide pull requests that make more sense the first time out.
## Environment setup now in `boot.js`
Instantiation and setup of the Jasmine environment, including building reporters, exposing the "global" functions, and executing tests has moved into its own file: `boot.js`. This should make it easier to add custom reporters, configure some objects, or just in general change how you use Jasmine from the outside.
For example, during development, Jasmine uses it's own `devboot.js` to load itself twice - once from `jasmine.js` and once from the source directories.
## Development & Build moved to Grunt
We've moved away from Ruby and embraced Node.js and [Grunt.js][grunt] for the various command line tasks during development. Yes, it's a just a different set of dependencies. But it's less code for the team to maintain - it turns out that JavaScript tools are pretty good at building JavaScript projects. This will make it easier for the community to make sure contributions work in browser and in Node.js before submitting Pull Requests. There is more detail in the [Contributor's Guide][contrib].
## Change in how Jasmine is loaded
We did not want to add new run-time dependencies, yet we needed to be cleaner when loading Jasmine. So we wrote a custom "require" scheme that works in Node.js and in browsers. This only affects pull requests that add files - please be careful in these cases. Again, the [Contributor's Guide][contrib] should help.
## Change in how Jasmine is tested with Jasmine
Writing a custom require system helped enforce self-testing - the built `jasmine.js` testing Jasmine from the source directories. Overall this has improved the stability of the code. When you look at Jasmine's tests, you'll see both `jasmine` and `j$` used. The former, `jasmine`, will always be used to test the code from source, which is loaded into the reference `j$`. Please adhere to this pattern when writing tests for contributions.
## Better node.js support
Node.js is now officially a first-class citizen. For a long time we've made sure tests were green in Node before releasing. But it is now officially part of Jasmine's CI build at [Travis][travis]. For the curious, the [`node_suite.js`][node_suite], is essentially a `boot.js` for Node. An official npm is coming.
## Better Continuous Integration Environment at Travis
The [CI build at Travis][travis_jasmine] now runs the core specs in a build matrix across browsers. It's far from complete on the operating system matrix, but you will see that Jasmine runs against: Firefox, Chrome, Safari 5, Safari 6, Phantom.js, Node.js, and IE versions 8, 9, and 10. Big thanks to [SauceLabs][sauce] for their support of open source projects. We will happily take pull requests for additional OS/Browser combos within the matrix.
## Support Matrix Updated
We're dropping support for IE < 8. Jasmine 1.x remains for projects supporting earlier versions of browsers.
## Removed JsDoc Pages
Comments in code are lies waiting to happen. Jasmine's JsDoc comments were no exception. The comments were out of date, the generated pages were even more out of date, and frankly they were not helpful. So they're gone.
Last year saw the posting of the [`introduction.js`][intro] page to document the real, practical interface for projects to use. This page has received a lot of positive feedback so expect more pages like this one.
## Adding Code Climate for JavaScript
We are running Code Climate for Jasmine. We have some work to do here but it's helping us easily find code hotspots.
## Pull Requests & Issues
The following Pull Requests were merged:
* ObjectContaining wrong filed value error message #[394](https://github.com/pivotal/jasmine/issues/394) from albertandrejev
* Removed unnecessary parameter from `suiteFactory()` call #[397](https://github.com/pivotal/jasmine/issues/397) from valera-rozuvan
* `jasmine.Any` supports `Boolean` #[392](https://github.com/pivotal/jasmine/issues/392) from albertandrejev
* Reporters get execution time #[30](https://github.com/pivotal/jasmine/issues/30)
* `toThrow` matchers handle falsy exceptions #[317](https://github.com/pivotal/jasmine/issues/371)
* Removed deprecated `jasmine.Matchers.pp` #[363](https://github.com/pivotal/jasmine/issues/363) from robinboehm
* Fix for Clock ticking to default to 0 #[340](https://github.com/pivotal/jasmine/issues/340) from Caio Cunha
* Whitespace failures should be easier to understand #[332](https://github.com/pivotal/jasmine/issues/332) from bjornblomqvist
* Fix for more markdown-y image for Build status #[329](https://github.com/pivotal/jasmine/issues/329) from sunliwen
* UTF-8 encoding fixes #[333](https://github.com/pivotal/jasmine/issues/333) from bjornblomqvist
### Fixed in RC3
* Improved the performance of the HTML output with a CSS change #[428](https://github.com/pivotal/jasmine/issues/428) - Thanks @tjgrathwell
* Removed an accidental global pollution of `j$` as a reference to Jasmine. Thanks to Morten Maxild from the mailing list
### Fixed in RC5
* Jasmine global object has a addCustomEqualityTester and addMatchers (no longer directly on global)
* Fixed a global leak of `timer`
* Remove currentRunner from Env (users can use topSuite from Env instead)
* [Specs without expectations are now considered passing](http://www.pivotaltracker.com/story/59422744)
* Improve error message when a spec does not call the async callback within the default time interval
* Allow passing a negativeCompare in a custom matcher for more custom implementations when `.not` is called
* Update favicon to be higher resolution
There were several other pull requests that either had already been fixed, or were good starting points for the various changes above. Thank you for all of the hard work to keep Jasmine awesome.
## Other Bugs & Features
There were a few small changes and fixes that didn't fit into any of the above categories:
* HTML Reporter refactored for simplicity and performance
* Default character encoding on the HTML runner page is UTF-8
* [Escape special regex characters from the spec param](http://www.pivotaltracker.com/story/52731407)
* Favicon returns
* [Clock supports `eval`'d strings as functions](http://www.pivotaltracker.com/story/40853563)
* There should always be stack traces on failures
* Removed references to unused `jasmine.VERBOSE`
* Removed references to unused `jasmine.XmlHttpRequest`
### Fixed in RC3
* There is now a consistent `this` between `beforeEach`, `it` and `afterEach` for a spec
* A spy's strategy now has properties `returnValue` and `throwError` because they are better names
* Make it easy to copy the title of failing specs from the HTML output
* Don't add periods to the full name of a spec fix #[427](https://github.com/pivotal/jasmine/issues/427)
* Allow Env to take optional spec/suite ids when asked to `execute`
* [Mock clock now less intrusive, replacing global timer functions only when clock is installed](http://www.pivotaltracker.com/story/54168708)
* Restore custom failure messages for `toHaveBeenCalledWith`
[mocha]: http://visionmedia.github.io/mocha/
[underscore]: http://underscorejs.org/
[grunt]: http://gruntjs.com
[contrib]: https://github.com/pivotal/jasmine/blob/master/CONTRIBUTING.md
[travis]: http://travis-ci.org
[travis_jasmine]: http://travis-ci.org/jasmine
[sauce]: http://saucelabs.com
[node_suite]: https://github.com/pivotal/jasmine/blob/master/spec/node_suite.js
[intro]: http://jasmine.github.io/2.0/introduction.html
------
_Release Notes generated with [Anchorman](http://github.com/infews/anchorman)_

View File

@@ -90,7 +90,7 @@ describe("ConsoleReporter", function() {
reporter.jasmineStarted();
reporter.specDone({status: "passed"});
timerSpy.elapsed.and.callReturn(1000);
timerSpy.elapsed.and.returnValue(1000);
out.clear();
reporter.jasmineDone();
@@ -127,7 +127,7 @@ describe("ConsoleReporter", function() {
out.clear();
timerSpy.elapsed.and.callReturn(100);
timerSpy.elapsed.and.returnValue(100);
reporter.jasmineDone();

View File

@@ -42,4 +42,4 @@ describe("Any", function() {
expect(any.jasmineToString()).toMatch('<jasmine.any');
});
});
});

View File

@@ -1,41 +1,141 @@
describe("Clock", function() {
it("calls the global setTimeout directly if Clock is not installed", function() {
var setTimeout = jasmine.createSpy('setTimeout'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction']),
global = { setTimeout: setTimeout },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
it("does not replace setTimeout until it is installed", function() {
var fakeSetTimeout = jasmine.createSpy("global setTimeout"),
fakeGlobal = { setTimeout: fakeSetTimeout },
delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["scheduleFunction"]),
delayedFn = jasmine.createSpy("delayedFn"),
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler);
clock.setTimeout(delayedFn, 0);
fakeGlobal.setTimeout(delayedFn, 0);
expect(fakeSetTimeout).toHaveBeenCalledWith(delayedFn, 0);
expect(delayedFunctionScheduler.scheduleFunction).not.toHaveBeenCalled();
expect(setTimeout).toHaveBeenCalledWith(delayedFn, 0);
fakeSetTimeout.calls.reset();
clock.install();
fakeGlobal.setTimeout(delayedFn, 0);
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalled();
expect(fakeSetTimeout).not.toHaveBeenCalled();
});
it("schedules the delayed function with the fake timer", function() {
var setTimeout = jasmine.createSpy('setTimeout'),
it("does not replace clearTimeout until it is installed", function() {
var fakeClearTimeout = jasmine.createSpy("global cleartimeout"),
fakeGlobal = { clearTimeout: fakeClearTimeout },
delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["removeFunctionWithId"]),
delayedFn = jasmine.createSpy("delayedFn"),
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler);
fakeGlobal.clearTimeout("foo");
expect(fakeClearTimeout).toHaveBeenCalledWith("foo");
expect(delayedFunctionScheduler.removeFunctionWithId).not.toHaveBeenCalled();
fakeClearTimeout.calls.reset();
clock.install();
fakeGlobal.clearTimeout("foo");
expect(delayedFunctionScheduler.removeFunctionWithId).toHaveBeenCalled();
expect(fakeClearTimeout).not.toHaveBeenCalled();
});
it("does not replace setInterval until it is installed", function() {
var fakeSetInterval = jasmine.createSpy("global setInterval"),
fakeGlobal = { setInterval: fakeSetInterval },
delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["scheduleFunction"]),
delayedFn = jasmine.createSpy("delayedFn"),
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler);
fakeGlobal.setInterval(delayedFn, 0);
expect(fakeSetInterval).toHaveBeenCalledWith(delayedFn, 0);
expect(delayedFunctionScheduler.scheduleFunction).not.toHaveBeenCalled();
fakeSetInterval.calls.reset();
clock.install();
fakeGlobal.setInterval(delayedFn, 0);
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalled();
expect(fakeSetInterval).not.toHaveBeenCalled();
});
it("does not replace clearInterval until it is installed", function() {
var fakeClearInterval = jasmine.createSpy("global clearinterval"),
fakeGlobal = { clearInterval: fakeClearInterval },
delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["removeFunctionWithId"]),
delayedFn = jasmine.createSpy("delayedFn"),
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler);
fakeGlobal.clearInterval("foo");
expect(fakeClearInterval).toHaveBeenCalledWith("foo");
expect(delayedFunctionScheduler.removeFunctionWithId).not.toHaveBeenCalled();
fakeClearInterval.calls.reset();
clock.install();
fakeGlobal.clearInterval("foo");
expect(delayedFunctionScheduler.removeFunctionWithId).toHaveBeenCalled();
expect(fakeClearInterval).not.toHaveBeenCalled();
});
it("replaces the global timer functions on uninstall", function() {
var fakeSetTimeout = jasmine.createSpy("global setTimeout"),
fakeClearTimeout = jasmine.createSpy("global clearTimeout"),
fakeSetInterval = jasmine.createSpy("global setInterval"),
fakeClearInterval = jasmine.createSpy("global clearInterval"),
fakeGlobal = {
setTimeout: fakeSetTimeout,
clearTimeout: fakeClearTimeout,
setInterval: fakeSetInterval,
clearInterval: fakeClearInterval
},
delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["scheduleFunction", "reset"]),
delayedFn = jasmine.createSpy("delayedFn"),
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler);
clock.install();
clock.uninstall();
fakeGlobal.setTimeout(delayedFn, 0);
fakeGlobal.clearTimeout("foo");
fakeGlobal.setInterval(delayedFn, 10);
fakeGlobal.clearInterval("bar");
expect(fakeSetTimeout).toHaveBeenCalledWith(delayedFn, 0);
expect(fakeClearTimeout).toHaveBeenCalledWith("foo");
expect(fakeSetInterval).toHaveBeenCalledWith(delayedFn, 10);
expect(fakeClearInterval).toHaveBeenCalledWith("bar");
expect(delayedFunctionScheduler.scheduleFunction).not.toHaveBeenCalled();
});
it("schedules the delayed function (via setTimeout) with the fake timer", function() {
var fakeSetTimeout = jasmine.createSpy('setTimeout'),
scheduleFunction = jasmine.createSpy('scheduleFunction'),
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
global = { setTimeout: setTimeout },
delayedFunctionScheduler = { scheduleFunction: scheduleFunction },
fakeGlobal = { setTimeout: fakeSetTimeout },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler);
clock.install();
clock.setTimeout(delayedFn, 0, 'a', 'b');
expect(setTimeout).not.toHaveBeenCalled();
expect(fakeSetTimeout).not.toHaveBeenCalled();
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(delayedFn, 0, ['a', 'b']);
});
it("returns an id for the delayed function", function() {
var setTimeout = jasmine.createSpy('setTimeout'),
var fakeSetTimeout = jasmine.createSpy('setTimeout'),
scheduleId = 123,
scheduleFunction = jasmine.createSpy('scheduleFunction').and.callReturn(scheduleId),
scheduleFunction = jasmine.createSpy('scheduleFunction').and.returnValue(scheduleId),
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
global = { setTimeout: setTimeout },
fakeGlobal = { setTimeout: fakeSetTimeout },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler),
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler),
timeoutId;
clock.install();
@@ -44,67 +144,43 @@ describe("Clock", function() {
expect(timeoutId).toEqual(123);
});
it("calls the global clearTimeout directly if Clock is not installed", function() {
var clearTimeout = jasmine.createSpy('clearTimeout'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['clearTimeout']),
global = { clearTimeout: clearTimeout },
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.clearTimeout(123);
expect(clearTimeout).toHaveBeenCalledWith(123);
});
it("clears the scheduled function with the scheduler", function() {
var clearTimeout = jasmine.createSpy('clearTimeout'),
var fakeClearTimeout = jasmine.createSpy('clearTimeout'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['removeFunctionWithId']),
global = { setTimeout: clearTimeout },
fakeGlobal = { setTimeout: fakeClearTimeout },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler);
clock.install();
clock.clearTimeout(123);
expect(clearTimeout).not.toHaveBeenCalled();
expect(fakeClearTimeout).not.toHaveBeenCalled();
expect(delayedFunctionScheduler.removeFunctionWithId).toHaveBeenCalledWith(123);
});
it("calls the global setInterval directly if Clock is not installed", function() {
var setInterval = jasmine.createSpy('setInterval'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction']),
global = { setInterval: setInterval },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.setInterval(delayedFn, 0);
expect(delayedFunctionScheduler.scheduleFunction).not.toHaveBeenCalled();
expect(setInterval).toHaveBeenCalledWith(delayedFn, 0);
});
it("schedules the delayed function with the fake timer", function() {
var setInterval = jasmine.createSpy('setInterval'),
var fakeSetInterval = jasmine.createSpy('setInterval'),
scheduleFunction = jasmine.createSpy('scheduleFunction'),
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
global = { setInterval: setInterval },
fakeGlobal = { setInterval: fakeSetInterval },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler);
clock.install();
clock.setInterval(delayedFn, 0, 'a', 'b');
expect(setInterval).not.toHaveBeenCalled();
expect(fakeSetInterval).not.toHaveBeenCalled();
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(delayedFn, 0, ['a', 'b'], true);
});
it("returns an id for the delayed function", function() {
var setInterval = jasmine.createSpy('setInterval'),
var fakeSetInterval = jasmine.createSpy('setInterval'),
scheduleId = 123,
scheduleFunction = jasmine.createSpy('scheduleFunction').and.callReturn(scheduleId),
scheduleFunction = jasmine.createSpy('scheduleFunction').and.returnValue(scheduleId),
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
global = { setInterval: setInterval },
fakeGlobal = { setInterval: fakeSetInterval },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler),
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler),
intervalId;
clock.install();
@@ -113,23 +189,12 @@ describe("Clock", function() {
expect(intervalId).toEqual(123);
});
it("calls the global clearInterval directly if Clock is not installed", function() {
var clearInterval = jasmine.createSpy('clearInterval'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['clearInterval']),
global = { clearInterval: clearInterval },
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.clearInterval(123);
expect(clearInterval).toHaveBeenCalledWith(123);
});
it("clears the scheduled function with the scheduler", function() {
var clearInterval = jasmine.createSpy('clearInterval'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['removeFunctionWithId']),
global = { setInterval: clearInterval },
fakeGlobal = { setInterval: clearInterval },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler);
clock.install();
clock.clearInterval(123);
@@ -145,53 +210,20 @@ describe("Clock", function() {
}).toThrow();
});
it("can be uninstalled", function() {
var setTimeout = jasmine.createSpy('setTimeout'),
setInterval = jasmine.createSpy('setInterval'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction', 'tick', 'reset']),
global = { setTimeout: setTimeout, setInterval: setInterval },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.install();
clock.setTimeout(delayedFn, 0);
expect(setTimeout).not.toHaveBeenCalled();
clock.setInterval(delayedFn, 0);
expect(setInterval).not.toHaveBeenCalled();
expect(function() {
clock.tick(0);
}).not.toThrow();
clock.uninstall();
expect(delayedFunctionScheduler.reset).toHaveBeenCalled();
clock.setTimeout(delayedFn, 0);
expect(setTimeout).toHaveBeenCalled();
clock.setInterval(delayedFn, 0);
expect(setInterval).toHaveBeenCalled();
expect(function() {
clock.tick(0);
}).toThrow();
});
it("on IE < 9, fails if extra args are passed to fake clock", function() {
//fail, because this would break in IE9.
var setTimeout = jasmine.createSpy('setTimeout'),
setInterval = jasmine.createSpy('setInterval'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction']),
fn = jasmine.createSpy('fn'),
global = { setTimeout: setTimeout, setInterval: setInterval },
clock = new j$.Clock(global, delayedFunctionScheduler);
var fakeSetTimeout = jasmine.createSpy('setTimeout'),
fakeSetInterval = jasmine.createSpy('setInterval'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction']),
fn = jasmine.createSpy('fn'),
fakeGlobal = {
setTimeout: fakeSetTimeout,
setInterval: fakeSetInterval
},
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler);
setTimeout.apply = null;
setInterval.apply = null;
fakeSetTimeout.apply = null;
fakeSetInterval.apply = null;
clock.install();
@@ -221,8 +253,8 @@ describe("Clock (acceptance)", function() {
clock.install();
clock.setTimeout(delayedFn1, 0, 'some', 'arg');
var intervalId = clock.setInterval(recurring1, 50, 'some', 'other', 'args');
clock.setTimeout(delayedFn1, 0);
var intervalId = clock.setInterval(recurring1, 50);
clock.setTimeout(delayedFn2, 100);
clock.setTimeout(delayedFn3, 200);
@@ -232,13 +264,13 @@ describe("Clock (acceptance)", function() {
clock.tick(0);
expect(delayedFn1).toHaveBeenCalledWith('some', 'arg');
expect(delayedFn1).toHaveBeenCalled();
expect(delayedFn2).not.toHaveBeenCalled();
expect(delayedFn3).not.toHaveBeenCalled();
clock.tick(50);
expect(recurring1).toHaveBeenCalledWith('some', 'other', 'args');
expect(recurring1).toHaveBeenCalled();
expect(recurring1.calls.count()).toBe(1);
expect(delayedFn2).not.toHaveBeenCalled();
expect(delayedFn3).not.toHaveBeenCalled();
@@ -280,7 +312,7 @@ describe("Clock (acceptance)", function() {
it("correctly schedules functions after the Clock has advanced", function() {
var delayedFn1 = jasmine.createSpy('delayedFn1'),
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
clock = new j$.Clock({setTimeout: function(){}}, delayedFunctionScheduler);
clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler);
clock.install();
@@ -292,23 +324,21 @@ describe("Clock (acceptance)", function() {
expect(delayedFn1).toHaveBeenCalled();
});
it("calls the global clearTimeout correctly when not installed", function () {
var delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['clearTimeout']),
global = jasmine.getGlobal(),
clock = new j$.Clock(global, delayedFunctionScheduler);
it("correctly schedules functions while the Clock is advancing", function() {
var delayedFn1 = jasmine.createSpy('delayedFn1'),
delayedFn2 = jasmine.createSpy('delayedFn2'),
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler);
expect(function() {
clock.clearTimeout(123)
}).not.toThrow();
});
delayedFn1.and.callFake(function() { clock.setTimeout(delayedFn2, 0); });
clock.install();
clock.setTimeout(delayedFn1, 5);
it("calls the global clearTimeout correctly when not installed", function () {
var delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['clearTimeout']),
global = jasmine.getGlobal(),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.tick(5);
expect(delayedFn1).toHaveBeenCalled();
expect(delayedFn2).not.toHaveBeenCalled();
expect(function() {
clock.clearInterval(123)
}).not.toThrow();
clock.tick();
expect(delayedFn2).toHaveBeenCalled();
});
});

View File

@@ -1,96 +1,149 @@
////TODO: matchers should be add-able to the env, not to the spec.
//describe("Custom Matchers", function() {
// var env;
// var fakeTimer;
//
// beforeEach(function() {
// env = new jasmine.Env();
// env.updateInterval = 0;
// });
//
// it("should be easy to add more matchers local to a spec, suite, etc.", function() {
// var spec1, spec2, spec1Matcher, spec2Matcher;
// var suite = env.describe('some suite', function() {
// env.beforeEach(function() {
// this.addMatchers({
// matcherForSuite: function(expected) {
// this.message = "matcherForSuite: actual: " + this.actual + "; expected: " + expected;
// return true;
// }
// });
// });
//
// spec1 = env.it('spec with an expectation').runs(function () {
// this.addMatchers({
// matcherForSpec: function(expected) {
// this.message = "matcherForSpec: actual: " + this.actual + "; expected: " + expected;
// return true;
// }
// });
// spec1Matcher = this.expect("xxx");
// });
//
// spec2 = env.it('spec with failing expectation').runs(function () {
// spec2Matcher = this.expect("yyy");
// });
// });
//
// suite.execute();
//
// spec1Matcher.matcherForSuite("expected");
// expect(spec1Matcher.message).toEqual("matcherForSuite: actual: xxx; expected: expected");
// spec1Matcher.matcherForSpec("expected");
// expect(spec1Matcher.message).toEqual("matcherForSpec: actual: xxx; expected: expected");
//
// spec2Matcher.matcherForSuite("expected");
// expect(spec2Matcher.message).toEqual("matcherForSuite: actual: yyy; expected: expected");
// expect(spec2Matcher.matcherForSpec).toBe(jasmine.undefined);
// });
//
// it("should generate messages with the same rules as for regular matchers when this.report() is not called", function() {
// var spec;
// var suite = env.describe('some suite', function() {
// spec = env.it('spec with an expectation').runs(function () {
// this.addMatchers({
// toBeTrue: function() {
// return this.actual === true;
// }
// });
// this.expect(true).toBeTrue();
// this.expect(false).toBeTrue();
// });
// });
//
// suite.execute();
//
// var results = spec.results().getItems();
// expect(results[0].message).toEqual("Passed.");
// expect(results[1].message).toEqual("Expected false to be true.");
// });
//
// it("should pass args", function() {
// var matcherCallArgs = [];
// var spec;
// var suite = env.describe('some suite', function() {
// spec = env.it('spec with an expectation').runs(function () {
// this.addMatchers({
// toBeTrue: function() {
// matcherCallArgs.push(jasmine.util.argsToArray(arguments));
// return this.actual === true;
// }
// });
// this.expect(true).toBeTrue();
// this.expect(false).toBeTrue('arg');
// this.expect(true).toBeTrue('arg1', 'arg2');
// });
// });
//
// suite.execute();
// var results = spec.results().getItems();
// expect(results[0].expected).toEqual(jasmine.undefined);
// expect(results[1].expected).toEqual('arg');
// expect(results[2].expected).toEqual(['arg1', 'arg2']);
//
// expect(matcherCallArgs).toEqual([[], ['arg'], ['arg1', 'arg2']]);
// });
//});
describe("Custom Matchers (Integration)", function() {
var env;
var fakeTimer;
beforeEach(function() {
env = new j$.Env();
});
it("allows adding more matchers local to a spec", function(done) {
env.it('spec defining a custom matcher', function() {
env.addMatchers({
matcherForSpec: function() {
return {
compare: function(actual, expected) {
return { pass: false, message: "matcherForSpec: actual: " + actual + "; expected: " + expected };
}
}
}
});
env.expect("zzz").matcherForSpec("yyy");
});
env.it("spec without custom matcher defined", function() {
expect(env.expect("zzz").matcherForSpec).toBeUndefined();
});
var specDoneSpy = jasmine.createSpy("specDoneSpy");
var expectations = function() {
var firstSpecResult = specDoneSpy.calls.first().args[0];
expect(firstSpecResult.status).toEqual("failed");
expect(firstSpecResult.failedExpectations[0].message).toEqual("matcherForSpec: actual: zzz; expected: yyy");
done();
};
env.addReporter({ specDone:specDoneSpy, jasmineDone: expectations});
env.execute();
});
it("passes the spec if the custom matcher passes", function(done) {
env.addMatchers({
toBeReal: function() {
return { compare: function() { return { pass: true }; } };
}
});
env.it("spec using custom matcher", function() {
env.expect(true).toBeReal();
});
var specExpectations = function(result) {
expect(result.status).toEqual('passed');
};
env.addReporter({ specDone: specExpectations, jasmineDone: done });
env.execute();
});
it("uses the negative compare function for a negative comparison, if provided", function(done) {
env.addMatchers({
toBeReal: function() {
return {
compare: function() { return { pass: true }; },
negativeCompare: function() { return { pass: true }; }
};
}
});
env.it("spec with custom negative comparison matcher", function() {
env.expect(true).not.toBeReal();
});
var specExpectations = function(result) {
expect(result.status).toEqual('passed');
}
env.addReporter({ specDone: specExpectations, jasmineDone: done });
env.execute();
});
it("generates messages with the same rules as built in matchers absent a custom message", function(done) {
env.addMatchers({
toBeReal: function() {
return {
compare: function() {
return { pass: false };
}
}
}
});
env.it('spec with an expectation', function() {
env.expect("a").toBeReal();
});
var specExpectations = function(result) {
expect(result.failedExpectations[0].message).toEqual("Expected 'a' to be real.");
};
env.addReporter({ specDone: specExpectations, jasmineDone: done });
env.execute();
});
it("passes the expected and actual arguments to the comparison function", function(done) {
var argumentSpy = jasmine.createSpy("argument spy").and.returnValue({ pass: true });
env.addMatchers({
toBeReal: function() {
return { compare: argumentSpy };
}
});
env.it('spec with an expectation', function () {
env.expect(true).toBeReal();
env.expect(true).toBeReal("arg");
env.expect(true).toBeReal("arg1", "arg2");
});
var specExpectations = function() {
expect(argumentSpy).toHaveBeenCalledWith(true);
expect(argumentSpy).toHaveBeenCalledWith(true, "arg");
expect(argumentSpy).toHaveBeenCalledWith(true, "arg1", "arg2");
};
env.addReporter({ specDone: specExpectations, jasmineDone: done });
env.execute();
});
it("passes the jasmine utility and current equality matchers to the expectation factory", function(done) {
var matcherFactory = function() { return { compare: function() { return {pass: true}; }}; },
argumentSpy = jasmine.createSpy("argument spy").and.returnValue(matcherFactory),
customEqualityFn = function() { return true; };
env.addCustomEqualityTester(customEqualityFn);
env.addMatchers({
toBeReal: argumentSpy
});
env.it("spec with expectation", function() {
env.expect(true).toBeReal();
});
var specExpectations = function() {
expect(argumentSpy).toHaveBeenCalledWith(j$.matchersUtil, [customEqualityFn]);
};
env.addReporter({ specDone: specExpectations, jasmineDone: done });
env.execute();
});
});

View File

@@ -3,31 +3,8 @@ describe("Env", function() {
var env;
beforeEach(function() {
env = new j$.Env();
env.updateInterval = 0;
});
describe('ids', function() {
it('nextSpecId should return consecutive integers, starting at 0', function() {
expect(env.nextSpecId()).toEqual(0);
expect(env.nextSpecId()).toEqual(1);
expect(env.nextSpecId()).toEqual(2);
});
});
describe("reporting", function() {
var fakeReporter;
beforeEach(function() {
fakeReporter = jasmine.createSpyObj("fakeReporter", ["jasmineStarted"]);
});
it("should allow reporters to be registered", function() {
env.addReporter(fakeReporter);
env.reporter.jasmineStarted();
expect(fakeReporter.jasmineStarted).toHaveBeenCalled();
});
});
it('removes all spies when env is executed', function(done) {
originalFoo = function() {},
testObj = {
@@ -85,11 +62,11 @@ describe("Env", function() {
var subject = { spiedFunc: function() { originalFunctionWasCalled = true; } };
originalFunc = subject.spiedFunc;
var spy = env.spyOn(subject, 'spiedFunc');
expect(subject.spiedFunc).toEqual(spy);
expect(subject.spiedFunc.calls.any()).toEqual(false);
expect(subject.spiedFunc.calls.count()).toEqual(0);
@@ -107,21 +84,6 @@ describe("Env", function() {
});
});
describe("#catchException", function() {
it("returns true if the exception is a pending spec exception", function() {
env.catchExceptions(false);
expect(env.catchException(new Error(j$.Spec.pendingSpecExceptionMessage))).toBe(true);
});
it("returns false if the exception is not a pending spec exception and not catching exceptions", function() {
env.catchExceptions(false);
expect(env.catchException(new Error("external error"))).toBe(false);
expect(env.catchException(new Error(j$.Spec.pendingSpecExceptionMessage))).toBe(true);
});
});
describe("#pending", function() {
it("throws the Pending Spec exception", function() {
expect(function() {
@@ -130,6 +92,12 @@ describe("Env", function() {
});
});
describe("#topSuite", function() {
it("returns the Jasmine top suite for users to traverse the spec tree", function() {
var suite = env.topSuite();
expect(suite.description).toEqual('Jasmine__TopLevel__Suite');
});
});
});
// TODO: move these into a separate file
@@ -236,6 +204,106 @@ describe("Env integration", function() {
env.execute();
});
it("calls associated befores/specs/afters with the same 'this'", function(done) {
var env = new j$.Env();
env.addReporter({jasmineDone: done});
env.describe("tests", function() {
var firstTimeThrough = true, firstSpecContext, secondSpecContext;
env.beforeEach(function() {
if (firstTimeThrough) {
firstSpecContext = this;
} else {
secondSpecContext = this;
}
expect(this).toEqual({});
});
env.it("sync spec", function() {
expect(this).toBe(firstSpecContext);
});
env.it("another sync spec", function() {
expect(this).toBe(secondSpecContext);
});
env.afterEach(function() {
if (firstTimeThrough) {
expect(this).toBe(firstSpecContext);
firstTimeThrough = false;
} else {
expect(this).toBe(secondSpecContext);
}
});
});
env.execute();
});
it("calls associated befores/its/afters with the same 'this' for an async spec", function(done) {
var env = new j$.Env();
env.addReporter({jasmineDone: done});
env.describe("with an async spec", function() {
var specContext;
env.beforeEach(function() {
specContext = this;
expect(this).toEqual({});
});
env.it("sync spec", function(underTestCallback) {
expect(this).toBe(specContext);
underTestCallback();
});
env.afterEach(function() {
expect(this).toBe(specContext);
});
});
env.execute();
});
it("Allows specifying which specs and suites to run", function(done) {
var env = new j$.Env(),
calls = [],
suiteCallback = jasmine.createSpy('suite callback'),
firstSpec,
secondSuite;
var assertions = function() {
expect(calls).toEqual([
'third spec',
'first spec'
]);
expect(suiteCallback).toHaveBeenCalled();
done();
};
env.addReporter({jasmineDone: assertions, suiteDone: suiteCallback});
env.describe("first suite", function() {
firstSpec = env.it("first spec", function() {
calls.push('first spec');
});
env.it("second spec", function() {
calls.push('second spec');
});
});
secondSuite = env.describe("second suite", function() {
env.it("third spec", function() {
calls.push('third spec');
});
});
env.execute([secondSuite.id, firstSpec.id]);
});
it("Mock clock can be installed and used in tests", function(done) {
var globalSetTimeout = jasmine.createSpy('globalSetTimeout'),
delayedFunctionForGlobalClock = jasmine.createSpy('delayedFunctionForGlobalClock'),
@@ -256,6 +324,7 @@ describe("Env integration", function() {
env.clock.install();
env.clock.setTimeout(delayedFunctionForMockClock, 100);
env.clock.tick(100);
env.clock.uninstall();
});
env.it("test without mock clock", function() {
env.clock.setTimeout(delayedFunctionForGlobalClock, 100);
@@ -293,52 +362,37 @@ describe("Env integration", function() {
});
describe("with a mock clock", function() {
beforeEach(function() {
jasmine.getEnv().clock.install();
var originalTimeout;
beforeEach(function() {
originalTimeout = j$.DEFAULT_TIMEOUT_INTERVAL;
jasmine.getEnv().clock.install();
});
afterEach(function() {
jasmine.getEnv().clock.uninstall();
j$.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
});
it("should wait a specified interval before failing specs haven't called done yet", function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [ "specDone" ]);
reporter.specDone.and.callFake(function() {
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({status: 'failed'}));
done();
});
afterEach(function() {
jasmine.getEnv().clock.uninstall();
env.addReporter(reporter);
j$.DEFAULT_TIMEOUT_INTERVAL = 8414;
env.it("async spec that doesn't call done", function(underTestCallback) {
env.expect(true).toBeTruthy();
jasmine.getEnv().clock.tick(8414);
});
it("should not hang on async specs that forget to call done()", function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [
"jasmineStarted",
"jasmineDone",
"suiteStarted",
"suiteDone",
"specStarted",
"specDone"
]);
env.addReporter(reporter);
env.describe("tests", function() {
env.it("async spec that will hang", function(underTestCallback) {
env.expect(true).toBeTruthy();
});
env.it("after async spec", function() {
env.expect(true).toBeTruthy();
});
});
env.execute();
reporter.jasmineDone.and.callFake(function() {
expect(reporter.jasmineStarted).toHaveBeenCalledWith({
totalSpecsDefined: 2
});
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({status: 'passed'}));
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({status: 'failed'}));
done();
});
jasmine.getEnv().clock.tick(60001);
});
env.execute();
});
});
// TODO: something is wrong with this spec
@@ -359,7 +413,6 @@ describe("Env integration", function() {
});
var suiteResult = reporter.suiteStarted.calls.first().args[0];
expect(suiteResult.description).toEqual("A Suite");
expect(reporter.jasmineDone).toHaveBeenCalled();
done();
});
@@ -400,9 +453,9 @@ describe("Env integration", function() {
});
});
expect(topLevelSpec.getFullName()).toBe("my tests are sometimes top level.");
expect(nestedSpec.getFullName()).toBe("my tests are sometimes singly nested.");
expect(doublyNestedSpec.getFullName()).toBe("my tests are sometimes even doubly nested.");
expect(topLevelSpec.getFullName()).toBe("my tests are sometimes top level");
expect(nestedSpec.getFullName()).toBe("my tests are sometimes singly nested");
expect(doublyNestedSpec.getFullName()).toBe("my tests are sometimes even doubly nested");
});
it("Custom equality testers should be per spec", function(done) {

View File

@@ -1,24 +1,22 @@
xdescribe('Exceptions:', function() {
describe('Exceptions:', function() {
var env;
beforeEach(function() {
env = new j$.Env();
env.updateInterval = 0;
});
describe('with break on exception', function() {
it('should not catch the exception', function() {
env.catchExceptions(false);
var suite = env.describe('suite for break on exceptions', function() {
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!');
});
});
var runner = env.currentRunner();
var dont_change = 'I will never change!';
try {
suite.execute();
env.execute();
dont_change = 'oops I changed';
}
catch (e) {}
@@ -29,36 +27,32 @@ xdescribe('Exceptions:', function() {
describe("with catch on exception", function() {
it('should handle exceptions thrown, but continue', function() {
var ranSecondTest = false,
suite = env.describe('Suite for handles exceptions', function () {
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', function() {
ranSecondTest = true;
});
env.it('should be a passing test that runs after exceptions are thrown from a async test', secondTest);
});
suite.execute();
expect(ranSecondTest).toBe(true);
env.execute();
expect(secondTest).toHaveBeenCalled();
});
it("should handle exceptions thrown directly in top-level describe blocks and continue", function () {
var ranSecondDescribe = false, suite, suite2, runner = env.currentRunner();
suite = env.describe("a suite that throws an exception", function () {
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);
});
throw new Error("top level error");
});
suite2 = env.describe("a suite that doesn't throw an exception", function () {
ranSecondDescribe = true;
});
env.describe("a suite that doesn't throw an exception", secondDescribe);
runner.execute();
expect(ranSecondDescribe).toBe(true);
env.execute();
expect(secondDescribe).toHaveBeenCalled();
});
});
});

View File

@@ -16,7 +16,7 @@ describe("buildExpectationResult", function() {
it("delegates message formatting to the provided formatter if there was an Error", function() {
var fakeError = {message: 'foo'},
messageFormatter = jasmine.createSpy("exception message formatter").and.callReturn(fakeError.message);
messageFormatter = jasmine.createSpy("exception message formatter").and.returnValue(fakeError.message);
var result = j$.buildExpectationResult(
{
@@ -31,7 +31,7 @@ describe("buildExpectationResult", function() {
it("delegates stack formatting to the provided formatter if there was an Error", function() {
var fakeError = {stack: 'foo'},
stackFormatter = jasmine.createSpy("stack formatter").and.callReturn(fakeError.stack);
stackFormatter = jasmine.createSpy("stack formatter").and.returnValue(fakeError.stack);
var result = j$.buildExpectationResult(
{

View File

@@ -56,7 +56,7 @@ describe("Expectation", function() {
it("wraps matchers's compare functions, passing in matcher dependencies", function() {
var fakeCompare = function() { return { pass: true }; },
matcherFactory = jasmine.createSpy("matcher").and.callReturn({ compare: fakeCompare }),
matcherFactory = jasmine.createSpy("matcher").and.returnValue({ compare: fakeCompare }),
matchers = {
toFoo: matcherFactory
},
@@ -80,7 +80,7 @@ describe("Expectation", function() {
});
it("wraps matchers's compare functions, passing the actual and expected", function() {
var fakeCompare = jasmine.createSpy('fake-compare').and.callReturn({pass: true}),
var fakeCompare = jasmine.createSpy('fake-compare').and.returnValue({pass: true}),
matchers = {
toFoo: function() {
return {
@@ -317,4 +317,77 @@ describe("Expectation", function() {
message: "I am a custom message"
});
});
});
it("reports a passing result to the spec when the 'not' comparison passes, given a negativeCompare", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: true }; },
negativeCompare: function() { return { pass: true }; }
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
actual = "an actual",
expectation;
j$.Expectation.addMatchers(matchers);
expectation = new j$.Expectation({
matchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(true, {
matcherName: "toFoo",
passed: true,
expected: "hello",
actual: actual,
message: ""
});
});
it("reports a failing result and a custom fail message to the spec when the 'not' comparison fails, given a negativeCompare", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: true }; },
negativeCompare: function() {
return {
pass: false,
message: "I'm a custom message"
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
actual = "an actual",
expectation;
j$.Expectation.addMatchers(matchers);
expectation = new j$.Expectation({
matchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
passed: false,
expected: "hello",
actual: actual,
message: "I'm a custom message"
});
});
});

View File

@@ -6,7 +6,6 @@ xdescribe('JsApiReporter (integration specs)', function() {
beforeEach(function() {
env = new j$.Env();
env.updateInterval = 0;
suite = env.describe("top-level suite", function() {
spec1 = env.it("spec 1", function() {
@@ -196,7 +195,7 @@ describe("JsApiReporter", function() {
timer: timerSpy
});
timerSpy.elapsed.and.callReturn(1000);
timerSpy.elapsed.and.returnValue(1000);
reporter.jasmineDone();
expect(reporter.executionTime()).toEqual(1000);
});

View File

@@ -61,4 +61,4 @@ describe("ObjectContaining", function() {
expect(containing.jasmineToString()).toMatch("<jasmine.objectContaining");
});
});
});

View File

@@ -19,11 +19,37 @@ describe("QueueRunner", function() {
expect(calls).toEqual(['fn1', 'fn2']);
});
it("supports asynchronous functions, only advancing to next function after a done() callback", function() {
//TODO: it would be nice if spy arity could match the fake, so we could do something like:
//createSpy('asyncfn').and.callFake(function(done) {});
it("calls each function with a consistent 'this'-- an empty object", function() {
var fn1 = jasmine.createSpy('fn1'),
fn2 = jasmine.createSpy('fn2'),
fn3 = function(done) { asyncContext = this; done(); },
queueRunner = new j$.QueueRunner({
fns: [fn1, fn2, fn3]
}),
asyncContext;
var onComplete = jasmine.createSpy('onComplete'),
queueRunner.execute();
var context = fn1.calls.first().object;
expect(context).toEqual({});
expect(fn2.calls.first().object).toBe(context);
expect(asyncContext).toBe(context);
});
describe("with an asynchronous function", function() {
beforeEach(function() {
jasmine.clock().install();
});
afterEach(function() {
jasmine.clock().uninstall();
});
it("supports asynchronous functions, only advancing to next function after a done() callback", function() {
//TODO: it would be nice if spy arity could match the fake, so we could do something like:
//createSpy('asyncfn').and.callFake(function(done) {});
var onComplete = jasmine.createSpy('onComplete'),
beforeCallback = jasmine.createSpy('beforeCallback'),
fnCallback = jasmine.createSpy('fnCallback'),
afterCallback = jasmine.createSpy('afterCallback'),
@@ -50,29 +76,28 @@ describe("QueueRunner", function() {
onComplete: onComplete
});
clock.install();
queueRunner.execute();
queueRunner.execute();
expect(beforeCallback).toHaveBeenCalled();
expect(fnCallback).not.toHaveBeenCalled();
expect(afterCallback).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
expect(beforeCallback).toHaveBeenCalled();
expect(fnCallback).not.toHaveBeenCalled();
expect(afterCallback).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
jasmine.clock().tick(100);
clock.tick(100);
expect(fnCallback).toHaveBeenCalled();
expect(afterCallback).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
expect(fnCallback).toHaveBeenCalled();
expect(afterCallback).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
jasmine.clock().tick(100);
clock.tick(100);
expect(afterCallback).toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
expect(afterCallback).toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
jasmine.clock().tick(100);
clock.tick(100);
expect(onComplete).toHaveBeenCalled();
expect(onComplete).toHaveBeenCalled();
});
});
it("calls an exception handler when an exception is thrown in a fn", function() {

View File

@@ -37,4 +37,4 @@ describe("ReportDispatcher", function() {
dispatcher.foo(123, 456);
}).not.toThrow();
});
});
});

View File

@@ -5,7 +5,6 @@ describe("jasmine spec running", function () {
beforeEach(function() {
env = new j$.Env();
env.updateInterval = 0;
});
it('should assign spec ids sequentially', function() {
@@ -25,11 +24,11 @@ describe("jasmine spec running", function () {
});
});
expect(it0.id).toEqual(0);
expect(it1.id).toEqual(1);
expect(it2.id).toEqual(2);
expect(it3.id).toEqual(3);
expect(it4.id).toEqual(4);
expect(it0.id).toEqual('spec0');
expect(it1.id).toEqual('spec1');
expect(it2.id).toEqual('spec2');
expect(it3.id).toEqual('spec3');
expect(it4.id).toEqual('spec4');
});
it('nested suites', function (done) {
@@ -305,4 +304,4 @@ describe("jasmine spec running", function () {
));
});
});
});

View File

@@ -36,7 +36,6 @@ describe("Spec", function() {
it("should call the start callback on execution", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
beforesWereCalled = false,
startCallback = jasmine.createSpy('startCallback'),
spec = new j$.Spec({
id: 123,
@@ -48,7 +47,12 @@ describe("Spec", function() {
spec.execute();
expect(startCallback).toHaveBeenCalledWith(spec);
// 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.
// expect(startCallback).toHaveBeenCalledWith(spec);
expect(startCallback).toHaveBeenCalled();
expect(startCallback.calls.first().object).toEqual(spec);
});
it("should call the start callback on execution but before any befores are called", function() {
@@ -185,18 +189,9 @@ describe("Spec", function() {
expect(done).toHaveBeenCalled();
});
it("#status returns pending by default", function() {
it("#status returns passing by default", function() {
var spec = new j$.Spec({fn: jasmine.createSpy("spec body")});
expect(spec.status()).toEqual('pending');
});
it("#status returns pending if no expectations were encountered", function() {
var specBody = jasmine.createSpy("spec body"),
spec = new j$.Spec({fn: specBody});
spec.execute();
expect(spec.status()).toEqual('pending');
expect(spec.status()).toEqual('passed');
});
it("#status returns passed if all expectations in the spec have passed", function() {

View File

@@ -22,7 +22,7 @@ describe("SpyStrategy", function() {
});
it("allows an original function to be called, passed through the params and returns it's value", function() {
var originalFn = jasmine.createSpy("original").and.callReturn(42),
var originalFn = jasmine.createSpy("original").and.returnValue(42),
spyStrategy = new j$.SpyStrategy({fn: originalFn}),
returnValue;
@@ -39,7 +39,7 @@ describe("SpyStrategy", function() {
spyStrategy = new j$.SpyStrategy({fn: originalFn}),
returnValue;
spyStrategy.callReturn(17);
spyStrategy.returnValue(17);
returnValue = spyStrategy.exec();
expect(originalFn).not.toHaveBeenCalled();
@@ -50,15 +50,25 @@ describe("SpyStrategy", function() {
var originalFn = jasmine.createSpy("original"),
spyStrategy = new j$.SpyStrategy({fn: originalFn});
spyStrategy.callThrow("bar");
spyStrategy.throwError(new TypeError("bar"));
expect(function() { spyStrategy.exec(); }).toThrow("bar");
expect(function() { spyStrategy.exec(); }).toThrowError(TypeError, "bar");
expect(originalFn).not.toHaveBeenCalled();
});
it("allows a non-Error to be thrown, wrapping it into an exception when executed", function() {
var originalFn = jasmine.createSpy("original"),
spyStrategy = new j$.SpyStrategy({fn: originalFn});
spyStrategy.throwError("bar");
expect(function() { spyStrategy.exec(); }).toThrowError(Error, "bar");
expect(originalFn).not.toHaveBeenCalled();
});
it("allows a fake function to be called instead", function() {
var originalFn = jasmine.createSpy("original"),
fakeFn = jasmine.createSpy("fake").and.callReturn(67),
fakeFn = jasmine.createSpy("fake").and.returnValue(67),
spyStrategy = new j$.SpyStrategy({fn: originalFn}),
returnValue;
@@ -71,7 +81,7 @@ describe("SpyStrategy", function() {
it("allows a return to plan stubbing after another strategy", function() {
var originalFn = jasmine.createSpy("original"),
fakeFn = jasmine.createSpy("fake").and.callReturn(67),
fakeFn = jasmine.createSpy("fake").and.returnValue(67),
spyStrategy = new j$.SpyStrategy({fn: originalFn}),
returnValue;
@@ -89,12 +99,12 @@ describe("SpyStrategy", function() {
it("returns the spy after changing the strategy", function(){
var spy = {},
spyFn = jasmine.createSpy('spyFn').and.callReturn(spy),
spyFn = jasmine.createSpy('spyFn').and.returnValue(spy),
spyStrategy = new j$.SpyStrategy({getSpy: spyFn});
expect(spyStrategy.callThrough()).toBe(spy);
expect(spyStrategy.callReturn()).toBe(spy);
expect(spyStrategy.callThrow()).toBe(spy);
expect(spyStrategy.returnValue()).toBe(spy);
expect(spyStrategy.throwError()).toBe(spy);
expect(spyStrategy.callFake()).toBe(spy);
expect(spyStrategy.stub()).toBe(spy);
});

View File

@@ -67,54 +67,6 @@ describe("Suite", function() {
expect(suite.afterFns).toEqual([innerAfter, outerAfter]);
});
it("adds specs", function() {
var env = new j$.Env(),
fakeQueue = {
add: jasmine.createSpy()
},
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueFactory: function() {
return fakeQueue
}
}),
fakeSpec = {};
expect(suite.specs.length).toEqual(0);
suite.addSpec(fakeSpec);
expect(suite.specs.length).toEqual(1);
});
it("adds suites", function() {
var env = new j$.Env(),
fakeQueue = {
add: jasmine.createSpy()
},
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueFactory: function() {
return fakeQueue
}
}),
anotherSuite = new j$.Suite({
env: env,
description: "I am another suite",
queueFactory: function() {
return fakeQueue
}
});
expect(suite.suites.length).toEqual(0);
suite.addSuite(anotherSuite);
expect(suite.suites.length).toEqual(1);
});
it("can be disabled", function() {
var env = new j$.Env(),
fakeQueueRunner = jasmine.createSpy('fake queue runner'),
@@ -154,8 +106,8 @@ describe("Suite", function() {
spyOn(suite, "execute");
parentSuite.addSpec(fakeSpec1);
parentSuite.addSuite(suite);
parentSuite.addChild(fakeSpec1);
parentSuite.addChild(suite);
parentSuite.execute(parentSuiteDone);

View File

@@ -3,10 +3,10 @@ describe("Timer", function() {
var fakeNow = jasmine.createSpy('fake Date.now'),
timer = new j$.Timer({now: fakeNow});
fakeNow.and.callReturn(100);
fakeNow.and.returnValue(100);
timer.start();
fakeNow.and.callReturn(200);
fakeNow.and.returnValue(200);
expect(timer.elapsed()).toEqual(100);
});

View File

@@ -153,10 +153,22 @@ describe("matchersUtil", function() {
expect(j$.matchersUtil.equals(1, 2, [tester])).toBe(true);
});
it("passes for two empty Objects", function () {
expect(j$.matchersUtil.equals({}, {})).toBe(true);
});
describe("when a custom equality matcher is installed that returns 'undefined'", function () {
var tester = function(a, b) { return jasmine.undefined; };
it("passes for two empty Objects", function () {
expect(j$.matchersUtil.equals({}, {}, [tester])).toBe(true);
});
});
it("fails for equivalents when a custom equality matcher returns false", function() {
var tester = function(a, b) { return false; };
expect(j$.matchersUtil.equals(1, 2, [tester])).toBe(false);
expect(j$.matchersUtil.equals(1, 1, [tester])).toBe(false);
});
});

View File

@@ -1,7 +1,7 @@
describe("toContain", function() {
it("delegates to j$.matchersUtil.contains", function() {
var util = {
contains: jasmine.createSpy('delegated-contains').and.callReturn(true)
contains: jasmine.createSpy('delegated-contains').and.returnValue(true)
},
matcher = j$.matchers.toContain(util);
@@ -12,7 +12,7 @@ describe("toContain", function() {
it("delegates to j$.matchersUtil.contains, passing in equality testers if present", function() {
var util = {
contains: jasmine.createSpy('delegated-contains').and.callReturn(true)
contains: jasmine.createSpy('delegated-contains').and.returnValue(true)
},
customEqualityTesters = ['a', 'b'],
matcher = j$.matchers.toContain(util, customEqualityTesters);

View File

@@ -1,7 +1,7 @@
describe("toEqual", function() {
it("delegates to equals function", function() {
var util = {
equals: jasmine.createSpy('delegated-equals').and.callReturn(true)
equals: jasmine.createSpy('delegated-equals').and.returnValue(true)
},
matcher = j$.matchers.toEqual(util),
result;
@@ -14,7 +14,7 @@ describe("toEqual", function() {
it("delegates custom equality testers, if present", function() {
var util = {
equals: jasmine.createSpy('delegated-equals').and.callReturn(true)
equals: jasmine.createSpy('delegated-equals').and.returnValue(true)
},
customEqualityTesters = ['a', 'b'],
matcher = j$.matchers.toEqual(util, customEqualityTesters),

View File

@@ -1,7 +1,7 @@
describe("toHaveBeenCalledWith", function() {
it("passes when the actual was called with matching parameters", function() {
var util = {
contains: jasmine.createSpy('delegated-contains').and.callReturn(true)
contains: jasmine.createSpy('delegated-contains').and.returnValue(true)
},
matcher = j$.matchers.toHaveBeenCalledWith(util),
calledSpy = j$.createSpy('called-spy'),
@@ -11,11 +11,12 @@ describe("toHaveBeenCalledWith", function() {
result = matcher.compare(calledSpy, 'a', 'b');
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected spy called-spy not to have been called with [ 'a', 'b' ] but it was.");
});
it("fails when the actual was not called", function() {
var util = {
contains: jasmine.createSpy('delegated-contains').and.callReturn(false)
contains: jasmine.createSpy('delegated-contains').and.returnValue(false)
},
matcher = j$.matchers.toHaveBeenCalledWith(util),
uncalledSpy = j$.createSpy('uncalled spy'),
@@ -23,20 +24,23 @@ describe("toHaveBeenCalledWith", function() {
result = matcher.compare(uncalledSpy);
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected spy uncalled spy to have been called with [ ] but it was never called.");
});
it("fails when the actual was called with different parameters", function() {
var util = {
contains: jasmine.createSpy('delegated-contains').and.callReturn(false)
contains: jasmine.createSpy('delegated-contains').and.returnValue(false)
},
matcher = j$.matchers.toHaveBeenCalledWith(util),
calledSpy = j$.createSpy('called spy'),
result;
calledSpy('a');
calledSpy('c', 'd');
result = matcher.compare(calledSpy, 'a', 'b');
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected spy called spy to have been called with [ 'a', 'b' ] but actual calls were [ 'a' ], [ 'c', 'd' ].");
});
it("throws an exception when the actual is not a spy", function() {
@@ -45,13 +49,4 @@ describe("toHaveBeenCalledWith", function() {
expect(function() { matcher.compare(fn) }).toThrow(new Error("Expected a spy, but got Function."));
});
it("has a custom message on failure", function() {
var matcher = j$.matchers.toHaveBeenCalledWith(),
spy = j$.createSpy('sample-spy'),
messages = matcher.message(spy);
expect(messages.affirmative).toEqual("Expected spy sample-spy to have been called.")
expect(messages.negative).toEqual("Expected spy sample-spy not to have been called.")
});
});

View File

@@ -4,7 +4,7 @@ describe("toThrowError", function() {
expect(function() {
matcher.compare({});
}).toThrow(new Error("Actual is not a Function")); // TODO: this needs to change for self-test
}).toThrowError("Actual is not a Function");
});
it("throws an error when the expected is not an Error, string, or RegExp", function() {
@@ -15,7 +15,7 @@ describe("toThrowError", function() {
expect(function() {
matcher.compare(fn, 1);
}).toThrow(new Error("Expected is not an Error, string, or RegExp.")); // TODO: this needs to change for self-test
}).toThrowError("Expected is not an Error, string, or RegExp.");
});
it("throws an error when the expected error type is not an Error", function() {
@@ -26,7 +26,7 @@ describe("toThrowError", function() {
expect(function() {
matcher.compare(fn, void 0, "foo");
}).toThrow(new Error("Expected error type is not an Error.")); // TODO: this needs to change for self-test
}).toThrowError("Expected error type is not an Error.");
});
it("throws an error when the expected error message is not a string or RegExp", function() {
@@ -37,7 +37,7 @@ describe("toThrowError", function() {
expect(function() {
matcher.compare(fn, Error, 1);
}).toThrow(new Error("Expected error message is not a string or RegExp.")); // TODO: this needs to change for self-test
}).toThrowError("Expected error message is not a string or RegExp.");
});
it("fails if actual does not throw at all", function() {
@@ -144,7 +144,7 @@ describe("toThrowError", function() {
it("passes if thrown is an Error and the expected the same Error", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
equals: jasmine.createSpy('delegated-equal').and.returnValue(true)
},
matcher = j$.matchers.toThrowError(util),
fn = function() {
@@ -160,7 +160,7 @@ describe("toThrowError", function() {
it("passes if thrown is a custom error that takes arguments and the expected is the same error", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
equals: jasmine.createSpy('delegated-equal').and.returnValue(true)
},
matcher = j$.matchers.toThrowError(util),
CustomError = function CustomError(arg) { arg.x },
@@ -180,7 +180,7 @@ describe("toThrowError", function() {
it("fails if thrown is an Error and the expected is a different Error", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(false)
equals: jasmine.createSpy('delegated-equal').and.returnValue(false)
},
matcher = j$.matchers.toThrowError(util),
fn = function() {
@@ -196,7 +196,7 @@ describe("toThrowError", function() {
it("passes if thrown is a type of Error and it is equal to the expected Error and message", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
equals: jasmine.createSpy('delegated-equal').and.returnValue(true)
},
matcher = j$.matchers.toThrowError(util),
fn = function() {
@@ -212,7 +212,7 @@ describe("toThrowError", function() {
it("passes if thrown is a custom error that takes arguments and it is equal to the expected custom error and message", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
equals: jasmine.createSpy('delegated-equal').and.returnValue(true)
},
matcher = j$.matchers.toThrowError(util),
CustomError = function CustomError(arg) { this.message = arg.message },
@@ -232,7 +232,7 @@ describe("toThrowError", function() {
it("fails if thrown is a type of Error and the expected is a different Error", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(false)
equals: jasmine.createSpy('delegated-equal').and.returnValue(false)
},
matcher = j$.matchers.toThrowError(util),
fn = function() {
@@ -248,7 +248,7 @@ describe("toThrowError", function() {
it("passes if thrown is a type of Error and has the same type as the expected Error and the message matches the exepcted message", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
equals: jasmine.createSpy('delegated-equal').and.returnValue(true)
},
matcher = j$.matchers.toThrowError(util),
fn = function() {
@@ -264,7 +264,7 @@ describe("toThrowError", function() {
it("fails if thrown is a type of Error and the expected is a different Error", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(false)
equals: jasmine.createSpy('delegated-equal').and.returnValue(false)
},
matcher = j$.matchers.toThrowError(util),
fn = function() {

View File

@@ -4,7 +4,8 @@ describe("toThrow", function() {
expect(function() {
matcher.compare({});
}).toThrow(new Error("Actual is not a Function")); // TODO: this needs to change for self-test
matcherComparator({});
}).toThrowError("Actual is not a Function");
});
it("fails if actual does not throw", function() {
@@ -22,7 +23,7 @@ describe("toThrow", function() {
it("passes if it throws but there is no expected", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
equals: jasmine.createSpy('delegated-equal').and.returnValue(true)
},
matcher = j$.matchers.toThrow(util),
fn = function() {
@@ -50,7 +51,7 @@ describe("toThrow", function() {
it("passes if what is thrown is equivalent to what is expected", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
equals: jasmine.createSpy('delegated-equal').and.returnValue(true)
},
matcher = j$.matchers.toThrow(util),
fn = function() {
@@ -66,7 +67,7 @@ describe("toThrow", function() {
it("fails if what is thrown is not equivalent to what is expected", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(false)
equals: jasmine.createSpy('delegated-equal').and.returnValue(false)
},
matcher = j$.matchers.toThrow(util),
fn = function() {
@@ -82,7 +83,7 @@ describe("toThrow", function() {
it("fails if what is thrown is not equivalent to undefined", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(false)
equals: jasmine.createSpy('delegated-equal').and.returnValue(false)
},
matcher = j$.matchers.toThrow(util),
fn = function() {
@@ -95,4 +96,4 @@ describe("toThrow", function() {
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw undefined, but it threw 5.");
});
});
});

View File

@@ -1,19 +1,23 @@
(function(env) {
env.ieVersion = (function() {
function browserVersion(matchFn) {
var userAgent = jasmine.getGlobal().navigator.userAgent;
if (!userAgent) { return Number.MAX_VALUE; }
if (!userAgent) { return void 0; }
var match = /MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(userAgent);
var match = matchFn(userAgent);
return match ? parseFloat(match[1]) : Number.MAX_VALUE;
})();
return match ? parseFloat(match[1]) : void 0;
}
env.safariVersion = (function() {
var userAgent = jasmine.getGlobal().navigator.userAgent;
if (!userAgent) { return Number.MAX_VALUE; }
env.ieVersion = browserVersion(function(userAgent) {
return /MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(userAgent);
});
var match = /Safari/.exec(userAgent) && /Version\/([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);
});
return match ? parseFloat(match[1]) : Number.MAX_VALUE;
})();
})(jasmine.getEnv());

View File

@@ -148,7 +148,7 @@ describe("New HtmlReporter", function() {
reporter.jasmineStarted({});
timer.elapsed.and.callReturn(100);
timer.elapsed.and.returnValue(100);
reporter.jasmineDone();
var duration = container.querySelector(".banner .duration");
@@ -461,8 +461,10 @@ describe("New HtmlReporter", function() {
expect(failure.getAttribute("class")).toMatch(/failed/);
expect(failure.getAttribute("class")).toMatch(/spec-detail/);
var specLink = failure.childNodes[0];
expect(specLink.getAttribute("class")).toEqual("description");
var specDiv = failure.childNodes[0];
expect(specDiv.getAttribute("class")).toEqual("description");
var specLink = specDiv.childNodes[0];
expect(specLink.getAttribute("title")).toEqual("a suite with a failing spec");
expect(specLink.getAttribute("href")).toEqual("?spec=a%20suite%20with%20a%20failing%20spec");

View File

@@ -15,4 +15,4 @@ describe("j$.HtmlSpecFilter", function() {
expect(specFilter.matches("foo")).toBe(true);
expect(specFilter.matches("bar")).toBe(false);
});
});
});

View File

@@ -3,7 +3,6 @@ describe("MatchersSpec - HTML Dependent", function () {
beforeEach(function() {
env = new j$.Env();
env.updateInterval = 0;
var suite = env.describe("suite", function() {
spec = env.it("spec", function() {

View File

@@ -5,4 +5,11 @@ describe("j$.pp (HTML Dependent)", function () {
expect(j$.pp(sampleNode)).toEqual("HTMLNode");
expect(j$.pp({foo: sampleNode})).toEqual("{ foo : HTMLNode }");
});
it("should print Firefox's wrapped native objects correctly", function() {
if(jasmine.getEnv().firefoxVersion) {
try { new CustomEvent(); } catch(e) { var err = e; };
expect(j$.pp(err)).toMatch(/Not enough arguments/);
}
});
});

View File

@@ -40,4 +40,4 @@ describe("QueryString", function() {
expect(queryString.getParam("baz")).toBeFalsy();
});
});
});
});

View File

@@ -59,4 +59,4 @@ describe("ResultsNode", function() {
expect(node.last()).toBe(node.children[node.children.length - 1]);
});
});
});

View File

@@ -1,21 +0,0 @@
jasmine_dir:
- 'src'
jasmine_files:
- 'core/base.js'
- 'core/util.js'
- 'core/Reporter.js'
- 'html/HtmlReporterHelpers.js'
- 'core/ExpectationResult.js'
- '**/*.js'
jasmine_css_files:
- 'html/jasmine.css'
src_files:
stylesheets:
helpers:
spec_files:
- 'performance/performance_test.js'
src_dir:
spec_dir:
- 'spec'

View File

@@ -1,67 +0,0 @@
require 'rubygems'
require 'bundler/setup'
require 'jasmine'
Jasmine.load_configuration_from_yaml(File.join(Dir.pwd, 'spec', 'jasmine.yml'))
config = Jasmine.config
browser = ENV['JASMINE_BROWSER'] || 'firefox'
if ENV['USE_SAUCE'] == 'true'
require 'selenium-webdriver'
unless ENV['TRAVIS_BUILD_NUMBER']
require 'sauce/connect'
# we want Sauce Connect locally, not on Travis
Sauce::Connect.connect!
end
username = ENV['SAUCE_USERNAME']
key = ENV['SAUCE_ACCESS_KEY']
platform = ENV['SAUCE_PLATFORM']
version = ENV['SAUCE_VERSION']
url = "http://#{username}:#{key}@localhost:4445/wd/hub"
config.port = 5555
capabilities = {
:platform => platform,
:version => version,
:build => ENV['TRAVIS_BUILD_NUMBER'],
:tags => [ENV['TRAVIS_RUBY_VERSION'], 'CI'],
:browserName => browser
}
capabilities.merge!('tunnel-identifier' => ENV['TRAVIS_JOB_NUMBER']) if ENV['TRAVIS_JOB_NUMBER']
webdriver = Selenium::WebDriver.for :remote, :url => url, :desired_capabilities => capabilities
end
Jasmine.configure do |config|
config.webdriver = webdriver if webdriver
config.browser = browser if browser
end
server = Jasmine::Server.new(config.port, Jasmine::Application.app(config))
driver = Jasmine::SeleniumDriver.new(config.browser, "#{config.host}:#{config.port}/")
t = Thread.new do
begin
server.start
rescue ChildProcess::TimeoutError
end
# # ignore bad exits
end
t.abort_on_exception = true
Jasmine::wait_for_listener(config.port, "jasmine server")
puts "jasmine server started."
reporter = Jasmine::Reporters::ApiReporter.new(driver, config.result_batch_size)
raw_results = Jasmine::Runners::HTTP.new(driver, reporter).run
results = Jasmine::Results.new(raw_results)
formatter = Jasmine::Formatters::Console.new(results)
puts formatter.failures
puts formatter.summary
exit results.failures.size

View File

@@ -0,0 +1,16 @@
---
use_sauce: <%= ENV['USE_SAUCE'] %>
browser: <%= ENV['JASMINE_BROWSER'] %>
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' %>
tags:
- <%= ENV['TRAVIS_RUBY_VERSION'] || RUBY_VERSION %>
- CI
tunnel_identifier: <%= ENV['TRAVIS_JOB_NUMBER'] ? %Q("#{ENV['TRAVIS_JOB_NUMBER']}") : nil %>
os: <%= ENV['SAUCE_OS'] %>
browser_version: <%= ENV['SAUCE_BROWSER_VERSION'] %>

View File

@@ -6,7 +6,7 @@ var path = require('path');
var jasmineRequire = require('../lib/jasmine-core/jasmine.js');
var jasmine = jasmineRequire.core(jasmineRequire);
var consoleFns = require('../src/console/console.js');
var consoleFns = require('../lib/console/console.js');
extend(jasmineRequire, consoleFns);
jasmineRequire.console(jasmineRequire, jasmine);
@@ -41,20 +41,10 @@ var jasmineInterface = {
return env.expect(actual);
},
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName);
},
clock: env.clock,
setTimeout: env.clock.setTimeout,
clearTimeout: env.clock.clearTimeout,
setInterval: env.clock.setInterval,
clearInterval: env.clock.clearInterval,
jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer()
})
@@ -67,6 +57,18 @@ function extend(destination, source) {
return destination;
}
jasmine.addCustomEqualityTester = function(tester) {
env.addCustomEqualityTester(tester);
};
jasmine.addMatchers = function(matchers) {
return env.addMatchers(matchers);
};
jasmine.clock = function() {
return env.clock;
};
// Jasmine "runner"
function executeSpecs(specs, done, isVerbose, showColors) {
global.jasmine = jasmine;
@@ -141,7 +143,7 @@ var j$require = (function() {
}
}());
var j$ = j$require.core(j$require);
j$ = j$require.core(j$require);
j$require.console(j$require, j$);
// options from command line

View File

@@ -1,49 +0,0 @@
# This file was generated by the `rspec --init` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
# Require this file using `require "spec_helper.rb"` to ensure that it is only
# loaded once.
#
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
RSpec.configure do |config|
config.treat_symbols_as_metadata_keys_with_true_values = true
config.run_all_when_everything_filtered = true
config.filter_run :focus
end
require 'awesome_print'
require 'tmpdir'
require 'nokogiri'
def project_root
File.join(File.expand_path(File.dirname(__FILE__)), '..')
end
def capture_output(capture = true)
if capture
output = StringIO.new
$stdout = output
end
yield
if capture
output.string
end
ensure
$stdout = STDOUT
end
def reset_dir(dir)
FileUtils.rm_r dir if File.exists?(dir)
FileUtils.mkdir_p dir
end
def jasmine_version
version = jasmine_version_object
version_string = "#{version['major']}.#{version['minor']}.#{version['build']}"
version_string += ".rc#{version['release_candidate']}" if version['release_candidate']
version_string
end
def jasmine_version_object
@version_object ||= JSON.parse(File.read(File.join(JasmineDev.project_root, 'src', 'version.json')))
end

View File

@@ -39,20 +39,10 @@
return env.pending();
},
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName);
},
clock: env.clock,
setTimeout: env.clock.setTimeout,
clearTimeout: env.clock.clearTimeout,
setInterval: env.clock.setInterval,
clearInterval: env.clock.clearInterval,
jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer()
})
@@ -64,6 +54,18 @@
extend(window, jasmineInterface);
}
jasmine.addCustomEqualityTester = function(tester) {
env.addCustomEqualityTester(tester);
};
jasmine.addMatchers = function(matchers) {
return env.addMatchers(matchers);
};
jasmine.clock = function() {
return env.clock;
};
var queryString = new jasmine.QueryString({
getWindowLocation: function() { return window.location; }
});
@@ -74,7 +76,6 @@
var htmlReporter = new jasmine.HtmlReporter({
env: env,
queryString: queryString,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
@@ -93,6 +94,11 @@
return specFilter.matches(spec.getFullName());
};
window.setTimeout = window.setTimeout;
window.setInterval = window.setInterval;
window.clearTimeout = window.clearTimeout;
window.clearInterval = window.clearInterval;
var currentWindowOnload = window.onload;
window.onload = function() {

View File

@@ -0,0 +1,14 @@
src_dir:
- 'src'
src_files:
- '**/*.js'
boot_dir: 'spec/support'
boot_files:
- 'dev_boot.js'
helpers:
- 'helpers/**/*.js'
spec_files:
- 'performance/performance_test.js'
spec_dir: spec

View File

@@ -22,7 +22,6 @@ helpers:
- 'helpers/**/*.js'
spec_files:
- '**/*[Ss]pec.js'
spec_dir:
- 'spec'
spec_dir: spec

View File

@@ -33,4 +33,4 @@ getJasmineRequireObj().Any = function() {
};
return Any;
};
};

View File

@@ -13,18 +13,20 @@ getJasmineRequireObj().Clock = function() {
setInterval: setInterval,
clearInterval: clearInterval
},
timer = realTimingFunctions,
installed = false;
installed = false,
timer;
self.install = function() {
installed = true;
replace(global, fakeTimingFunctions);
timer = fakeTimingFunctions;
installed = true;
};
self.uninstall = function() {
delayedFunctionScheduler.reset();
installed = false;
replace(global, realTimingFunctions);
timer = realTimingFunctions;
installed = false;
};
self.setTimeout = function(fn, delay, params) {
@@ -59,7 +61,7 @@ getJasmineRequireObj().Clock = function() {
if (installed) {
delayedFunctionScheduler.tick(millis);
} else {
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
throw new Error("Mock clock is not installed, use jasmine.clock().install()");
}
};
@@ -67,9 +69,13 @@ getJasmineRequireObj().Clock = function() {
function legacyIE() {
//if these methods are polyfilled, apply will be present
//TODO: it may be difficult to load the polyfill before jasmine loads
//(env should be new-ed inside of onload)
return !(global.setTimeout || global.setInterval).apply;
return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply;
}
function replace(dest, source) {
for (var prop in source) {
dest[prop] = source[prop];
}
}
function setTimeout(fn, delay) {

View File

@@ -7,8 +7,8 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
self.tick = function(millis) {
millis = millis || 0;
runFunctionsWithinRange(currentTime, currentTime + millis);
currentTime = currentTime + millis;
runFunctionsWithinRange(currentTime - millis, currentTime);
};
self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) {

View File

@@ -5,17 +5,22 @@ getJasmineRequireObj().Env = function(j$) {
var self = this;
var global = options.global || j$.getGlobal();
var totalSpecsDefined = 0;
var catchExceptions = true;
var realSetTimeout = j$.getGlobal().setTimeout;
var realClearTimeout = j$.getGlobal().clearTimeout;
this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler());
var runnableLookupTable = {};
var spies = [];
this.currentSpec = null;
var currentSpec = null;
var currentSuite = null;
this.reporter = new j$.ReportDispatcher([
var reporter = new j$.ReportDispatcher([
"jasmineStarted",
"jasmineDone",
"suiteStarted",
@@ -24,14 +29,11 @@ getJasmineRequireObj().Env = function(j$) {
"specDone"
]);
this.lastUpdate = 0;
this.specFilter = function() {
return true;
};
this.nextSpecId_ = 0;
this.nextSuiteId_ = 0;
this.equalityTesters_ = [];
var equalityTesters = [];
var customEqualityTesters = [];
this.addCustomEqualityTester = function(tester) {
@@ -40,6 +42,16 @@ getJasmineRequireObj().Env = function(j$) {
j$.Expectation.addCoreMatchers(j$.matchers);
var nextSpecId = 0;
var getNextSpecId = function() {
return 'spec' + nextSpecId++;
};
var nextSuiteId = 0;
var getNextSuiteId = function() {
return 'suite' + nextSuiteId++;
};
var expectationFactory = function(actual, spec) {
return j$.Expectation.Factory({
util: j$.matchersUtil,
@@ -54,32 +66,34 @@ getJasmineRequireObj().Env = function(j$) {
};
var specStarted = function(spec) {
self.currentSpec = spec;
self.reporter.specStarted(spec.result);
currentSpec = spec;
reporter.specStarted(spec.result);
};
var beforeFns = function(currentSuite) {
var beforeFns = function(suite) {
return function() {
var befores = [];
for (var suite = currentSuite; suite; suite = suite.parentSuite) {
while(suite) {
befores = befores.concat(suite.beforeFns);
suite = suite.parentSuite;
}
return befores.reverse();
};
};
var afterFns = function(currentSuite) {
var afterFns = function(suite) {
return function() {
var afters = [];
for (var suite = currentSuite; suite; suite = suite.parentSuite) {
while(suite) {
afters = afters.concat(suite.afterFns);
suite = suite.parentSuite;
}
return afters;
};
};
var getSpecName = function(spec, currentSuite) {
return currentSuite.getFullName() + ' ' + spec.description + '.';
var getSpecName = function(spec, suite) {
return suite.getFullName() + ' ' + spec.description;
};
// TODO: we may just be able to pass in the fn instead of wrapping here
@@ -102,10 +116,6 @@ getJasmineRequireObj().Env = function(j$) {
return catchExceptions;
};
this.catchException = function(e) {
return j$.Spec.isPendingSpecException(e) || catchExceptions;
};
var maximumSpecCallbackDepth = 20;
var currentSpecCallbackDepth = 0;
@@ -119,94 +129,53 @@ getJasmineRequireObj().Env = function(j$) {
}
}
var catchException = function(e) {
return j$.Spec.isPendingSpecException(e) || catchExceptions;
};
var queueRunnerFactory = function(options) {
options.catchException = self.catchException;
options.catchException = catchException;
options.clearStack = options.clearStack || clearStack;
new j$.QueueRunner(options).run(options.fns, 0);
new j$.QueueRunner(options).execute();
};
var totalSpecsDefined = 0;
this.specFactory = function(description, fn, suite) {
totalSpecsDefined++;
var spec = new j$.Spec({
id: self.nextSpecId(),
beforeFns: beforeFns(suite),
afterFns: afterFns(suite),
expectationFactory: expectationFactory,
exceptionFormatter: exceptionFormatter,
resultCallback: specResultCallback,
getSpecName: function(spec) {
return getSpecName(spec, suite);
},
onStart: specStarted,
description: description,
expectationResultFactory: expectationResultFactory,
queueRunner: queueRunnerFactory,
fn: fn,
timer: {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}
});
if (!self.specFilter(spec)) {
spec.disable();
}
return spec;
function removeAllSpies() {
for (var i = 0; i < spies.length; i++) {
var spyEntry = spies[i];
spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
}
spies = [];
}
function specResultCallback(result) {
removeAllSpies();
j$.Expectation.resetMatchers();
customEqualityTesters.length = 0;
self.clock.uninstall();
self.currentSpec = null;
self.reporter.specDone(result);
}
};
var suiteStarted = function(suite) {
self.reporter.suiteStarted(suite.result);
};
var suiteConstructor = j$.Suite;
this.topSuite = new j$.Suite({
var topSuite = new j$.Suite({
env: this,
id: this.nextSuiteId(),
id: getNextSuiteId(),
description: 'Jasmine__TopLevel__Suite',
queueRunner: queueRunnerFactory,
completeCallback: function() {}, // TODO - hook this up
resultCallback: function() {} // TODO - hook this up
});
this.currentSuite = this.topSuite;
runnableLookupTable[topSuite.id] = topSuite;
currentSuite = topSuite;
this.suiteFactory = function(description) {
return new suiteConstructor({
env: self,
id: self.nextSuiteId(),
description: description,
parentSuite: self.currentSuite,
queueRunner: queueRunnerFactory,
onStart: suiteStarted,
resultCallback: function(attrs) {
self.reporter.suiteDone(attrs);
}
});
this.topSuite = function() {
return topSuite;
};
this.execute = function() {
this.reporter.jasmineStarted({
this.execute = function(runnablesToRun) {
runnablesToRun = runnablesToRun || [topSuite.id];
var allFns = [];
for(var i = 0; i < runnablesToRun.length; i++) {
var runnable = runnableLookupTable[runnablesToRun[i]];
allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable));
}
reporter.jasmineStarted({
totalSpecsDefined: totalSpecsDefined
});
this.topSuite.execute(self.reporter.jasmineDone);
queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone});
};
this.addReporter = function(reporterToAdd) {
reporter.addReporter(reporterToAdd);
};
this.addMatchers = function(matchersToAdd) {
j$.Expectation.addMatchers(matchersToAdd);
};
this.spyOn = function(obj, methodName) {
@@ -236,108 +205,133 @@ getJasmineRequireObj().Env = function(j$) {
return spy;
};
}
Env.prototype.addMatchers = function(matchersToAdd) {
j$.Expectation.addMatchers(matchersToAdd);
};
Env.prototype.version = function() {
return j$.version;
};
Env.prototype.expect = function(actual) {
return this.currentSpec.expect(actual);
};
// TODO: move this to closure
Env.prototype.versionString = function() {
console.log("DEPRECATED == use j$.version");
return j$.version;
};
// TODO: move this to closure
Env.prototype.nextSpecId = function() {
return this.nextSpecId_++;
};
// TODO: move this to closure
Env.prototype.nextSuiteId = function() {
return this.nextSuiteId_++;
};
// TODO: move this to closure
Env.prototype.addReporter = function(reporter) {
this.reporter.addReporter(reporter);
};
// TODO: move this to closure
Env.prototype.describe = function(description, specDefinitions) {
var suite = this.suiteFactory(description);
var parentSuite = this.currentSuite;
parentSuite.addSuite(suite);
this.currentSuite = suite;
var declarationError = null;
try {
specDefinitions.call(suite);
} catch (e) {
declarationError = e;
}
if (declarationError) {
this.it("encountered a declaration exception", function() {
throw declarationError;
var suiteFactory = function(description) {
var suite = new j$.Suite({
env: self,
id: getNextSuiteId(),
description: description,
parentSuite: currentSuite,
queueRunner: queueRunnerFactory,
onStart: suiteStarted,
resultCallback: function(attrs) {
reporter.suiteDone(attrs);
}
});
}
this.currentSuite = parentSuite;
runnableLookupTable[suite.id] = suite;
return suite;
};
return suite;
};
this.describe = function(description, specDefinitions) {
var suite = suiteFactory(description);
// TODO: move this to closure
Env.prototype.xdescribe = function(description, specDefinitions) {
var suite = this.describe(description, specDefinitions);
suite.disable();
return suite;
};
var parentSuite = currentSuite;
parentSuite.addChild(suite);
currentSuite = suite;
// TODO: move this to closure
Env.prototype.it = function(description, fn) {
var spec = this.specFactory(description, fn, this.currentSuite);
this.currentSuite.addSpec(spec);
return spec;
};
var declarationError = null;
try {
specDefinitions.call(suite);
} catch (e) {
declarationError = e;
}
// TODO: move this to closure
Env.prototype.xit = function(description, fn) {
var spec = this.it(description, fn);
spec.pend();
return spec;
};
if (declarationError) {
this.it("encountered a declaration exception", function() {
throw declarationError;
});
}
// TODO: move this to closure
Env.prototype.beforeEach = function(beforeEachFunction) {
this.currentSuite.beforeEach(beforeEachFunction);
};
currentSuite = parentSuite;
// TODO: move this to closure
Env.prototype.afterEach = function(afterEachFunction) {
this.currentSuite.afterEach(afterEachFunction);
};
return suite;
};
// TODO: move this to closure
Env.prototype.pending = function() {
throw j$.Spec.pendingSpecExceptionMessage;
};
this.xdescribe = function(description, specDefinitions) {
var suite = this.describe(description, specDefinitions);
suite.disable();
return suite;
};
// TODO: Still needed?
Env.prototype.currentRunner = function() {
return this.topSuite;
};
var specFactory = function(description, fn, suite) {
totalSpecsDefined++;
var spec = new j$.Spec({
id: getNextSpecId(),
beforeFns: beforeFns(suite),
afterFns: afterFns(suite),
expectationFactory: expectationFactory,
exceptionFormatter: exceptionFormatter,
resultCallback: specResultCallback,
getSpecName: function(spec) {
return getSpecName(spec, suite);
},
onStart: specStarted,
description: description,
expectationResultFactory: expectationResultFactory,
queueRunner: queueRunnerFactory,
fn: fn,
timer: {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}
});
runnableLookupTable[spec.id] = spec;
if (!self.specFilter(spec)) {
spec.disable();
}
return spec;
function removeAllSpies() {
for (var i = 0; i < spies.length; i++) {
var spyEntry = spies[i];
spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
}
spies = [];
}
function specResultCallback(result) {
removeAllSpies();
j$.Expectation.resetMatchers();
customEqualityTesters = [];
currentSpec = null;
reporter.specDone(result);
}
};
var suiteStarted = function(suite) {
reporter.suiteStarted(suite.result);
};
this.it = function(description, fn) {
var spec = specFactory(description, fn, currentSuite);
currentSuite.addChild(spec);
return spec;
};
this.xit = function(description, fn) {
var spec = this.it(description, fn);
spec.pend();
return spec;
};
this.expect = function(actual) {
return currentSpec.expect(actual);
};
this.beforeEach = function(beforeEachFunction) {
currentSuite.beforeEach(beforeEachFunction);
};
this.afterEach = function(afterEachFunction) {
currentSuite.afterEach(afterEachFunction);
};
this.pending = function() {
throw j$.Spec.pendingSpecExceptionMessage;
};
}
return Env;
};

View File

@@ -22,12 +22,21 @@ getJasmineRequireObj().Expectation = function() {
args.unshift(this.actual);
var result = matcherFactory(this.util, this.customEqualityTesters).compare.apply(null, args);
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) {
result.pass = !result.pass;
matcherCompare = matcher.negativeCompare || defaultNegativeCompare;
}
var result = matcherCompare.apply(null, args);
if (!result.pass) {
if (!result.message) {
args.unshift(this.isNot);

View File

@@ -29,7 +29,7 @@ getJasmineRequireObj().pp = function(j$) {
this.emitScalar('Date(' + value + ')');
} else if (value.__Jasmine_been_here_before__) {
this.emitScalar('<circular reference: ' + (j$.isArray_(value) ? 'Array' : 'Object') + '>');
} else if (j$.isArray_(value) || typeof value == 'object') {
} else if (j$.isArray_(value) || j$.isA_('Object', value)) {
value.__Jasmine_been_here_before__ = true;
if (j$.isArray_(value)) {
this.emitArray(value);
@@ -47,8 +47,8 @@ getJasmineRequireObj().pp = function(j$) {
PrettyPrinter.prototype.iterateObject = function(obj, fn) {
for (var property in obj) {
if (!obj.hasOwnProperty(property)) continue;
if (property == '__Jasmine_been_here_before__') continue;
if (!obj.hasOwnProperty(property)) { continue; }
if (property == '__Jasmine_been_here_before__') { continue; }
fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) &&
obj.__lookupGetter__(property) !== null) : false);
}

View File

@@ -6,6 +6,7 @@ getJasmineRequireObj().QueueRunner = function() {
this.clearStack = attrs.clearStack || function(fn) {fn();};
this.onException = attrs.onException || function() {};
this.catchException = attrs.catchException || function() { return true; };
this.userContext = {};
}
QueueRunner.prototype.execute = function() {
@@ -34,7 +35,7 @@ getJasmineRequireObj().QueueRunner = function() {
function attemptSync(fn) {
try {
fn.call(self);
fn.call(self.userContext);
} catch (e) {
handleException(e);
}
@@ -44,7 +45,7 @@ getJasmineRequireObj().QueueRunner = function() {
var next = function () { self.run(fns, iterativeIndex + 1); };
try {
fn.call(self, next);
fn.call(self.userContext, next);
} catch (e) {
handleException(e);
next();

View File

@@ -5,11 +5,11 @@ getJasmineRequireObj().ReportDispatcher = function() {
for (var i = 0; i < dispatchedMethods.length; i++) {
var method = dispatchedMethods[i];
this[method] = function(m) {
this[method] = (function(m) {
return function() {
dispatch(m, arguments);
};
}(method);
}(method));
}
var reporters = [];

View File

@@ -1,6 +1,5 @@
getJasmineRequireObj().Spec = function() {
getJasmineRequireObj().Spec = function(j$) {
function Spec(attrs) {
this.encounteredExpectations = false;
this.expectationFactory = attrs.expectationFactory;
this.resultCallback = attrs.resultCallback || function() {};
this.id = attrs.id;
@@ -26,13 +25,11 @@ getJasmineRequireObj().Spec = function() {
id: this.id,
description: this.description,
fullName: this.getFullName(),
status: this.status(),
failedExpectations: []
};
}
Spec.prototype.addExpectationResult = function(passed, data) {
this.encounteredExpectations = true;
if (passed) {
return;
}
@@ -56,22 +53,22 @@ getJasmineRequireObj().Spec = function() {
function timeoutable(fn) {
return function(done) {
var timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
onException(new Error('timeout'));
onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
done();
}, 10000]]);
}, j$.DEFAULT_TIMEOUT_INTERVAL]]);
var callDone = function() {
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
done();
};
fn(callDone); //TODO: do we care about more than 1 arg?
fn.call(this, callDone); //TODO: do we care about more than 1 arg?
};
}
var befores = this.beforeFns() || [],
afters = this.afterFns() || [],
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
afters = this.afterFns() || [],
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
var allFns = befores.concat(thisOne).concat(afters);
this.queueRunner({
@@ -81,18 +78,18 @@ getJasmineRequireObj().Spec = function() {
});
function onException(e) {
if (Spec.isPendingSpecException(e)) {
self.pend();
return;
}
if (Spec.isPendingSpecException(e)) {
self.pend();
return;
}
self.addExpectationResult(false, {
matcherName: "",
passed: false,
expected: "",
actual: "",
error: e
});
self.addExpectationResult(false, {
matcherName: "",
passed: false,
expected: "",
actual: "",
error: e
});
}
function complete() {
@@ -118,7 +115,7 @@ getJasmineRequireObj().Spec = function() {
return 'disabled';
}
if (this.markedPending || !this.encounteredExpectations) {
if (this.markedPending) {
return 'pending';
}

View File

@@ -21,16 +21,17 @@ getJasmineRequireObj().SpyStrategy = function() {
return getSpy();
};
this.callReturn = function(value) {
this.returnValue = function(value) {
plan = function() {
return value;
};
return getSpy();
};
this.callThrow = function(something) {
this.throwError = function(something) {
var error = (something instanceof Error) ? something : new Error(something);
plan = function() {
throw something;
throw error;
};
return getSpy();
};

View File

@@ -5,7 +5,6 @@ getJasmineRequireObj().Suite = function() {
this.parentSuite = attrs.parentSuite;
this.description = attrs.description;
this.onStart = attrs.onStart || function() {};
this.completeCallback = attrs.completeCallback || function() {}; // TODO: this is unused
this.resultCallback = attrs.resultCallback || function() {};
this.clearStack = attrs.clearStack || function(fn) {fn();};
@@ -14,9 +13,7 @@ getJasmineRequireObj().Suite = function() {
this.queueRunner = attrs.queueRunner || function() {};
this.disabled = false;
this.children_ = []; // TODO: rename
this.suites = []; // TODO: needed?
this.specs = []; // TODO: needed?
this.children = [];
this.result = {
id: this.id,
@@ -48,19 +45,8 @@ getJasmineRequireObj().Suite = function() {
this.afterFns.unshift(fn);
};
Suite.prototype.addSpec = function(spec) {
this.children_.push(spec);
this.specs.push(spec); // TODO: needed?
};
Suite.prototype.addSuite = function(suite) {
suite.parentSuite = this;
this.children_.push(suite);
this.suites.push(suite); // TODO: needed?
};
Suite.prototype.children = function() {
return this.children_;
Suite.prototype.addChild = function(child) {
this.children.push(child);
};
Suite.prototype.execute = function(onComplete) {
@@ -70,11 +56,10 @@ getJasmineRequireObj().Suite = function() {
return;
}
var allFns = [],
children = this.children_;
var allFns = [];
for (var i = 0; i < children.length; i++) {
allFns.push(wrapChildAsAsync(children[i]));
for (var i = 0; i < this.children.length; i++) {
allFns.push(wrapChildAsAsync(this.children[i]));
}
this.onStart(this);
@@ -96,7 +81,7 @@ getJasmineRequireObj().Suite = function() {
return function(done) { child.execute(done); };
}
};
return Suite;
};

View File

@@ -15,4 +15,4 @@ getJasmineRequireObj().Timer = function() {
}
return Timer;
};
};

View File

@@ -3,7 +3,6 @@ getJasmineRequireObj().base = function(j$) {
throw new Error("unimplemented method");
};
j$.DEFAULT_UPDATE_INTERVAL = 250;
j$.MAX_PRETTY_PRINT_DEPTH = 40;
j$.DEFAULT_TIMEOUT_INTERVAL = 5000;
@@ -52,18 +51,18 @@ getJasmineRequireObj().base = function(j$) {
j$.createSpy = function(name, originalFn) {
var spyStrategy = new j$.SpyStrategy({
name: name,
fn: originalFn,
getSpy: function() { return spy; }
}),
callTracker = new j$.CallTracker(),
spy = function() {
callTracker.track({
object: this,
args: Array.prototype.slice.apply(arguments)
});
return spyStrategy.exec.apply(this, arguments);
};
name: name,
fn: originalFn,
getSpy: function() { return spy; }
}),
callTracker = new j$.CallTracker(),
spy = function() {
callTracker.track({
object: this,
args: Array.prototype.slice.apply(arguments)
});
return spyStrategy.exec.apply(this, arguments);
};
for (var prop in originalFn) {
if (prop === 'and' || prop === 'calls') {
@@ -84,7 +83,7 @@ getJasmineRequireObj().base = function(j$) {
return false;
}
return putativeSpy.and instanceof j$.SpyStrategy &&
putativeSpy.calls instanceof j$.CallTracker;
putativeSpy.calls instanceof j$.CallTracker;
};
j$.createSpyObj = function(baseName, methodNames) {

View File

@@ -37,7 +37,9 @@ getJasmineRequireObj().matchersUtil = function(j$) {
if (expected.length > 0) {
for (var i = 0; i < expected.length; i++) {
if (i > 0) message += ",";
if (i > 0) {
message += ",";
}
message += " " + j$.pp(expected[i]);
}
}
@@ -52,9 +54,9 @@ getJasmineRequireObj().matchersUtil = function(j$) {
var result = true;
for (var i = 0; i < customTesters.length; i++) {
result = customTesters[i](a, b);
if (result) {
return true;
var customTesterResult = customTesters[i](a, b);
if (!j$.util.isUndefined(customTesterResult)) {
return customTesterResult;
}
}
@@ -85,11 +87,11 @@ getJasmineRequireObj().matchersUtil = function(j$) {
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) return a !== 0 || 1 / a == 1 / b;
if (a === b) { return a !== 0 || 1 / a == 1 / b; }
// A strict comparison is necessary because `null == undefined`.
if (a === null || b === null) return a === b;
if (a === null || b === null) { return a === b; }
var className = Object.prototype.toString.call(a);
if (className != Object.prototype.toString.call(b)) return false;
if (className != Object.prototype.toString.call(b)) { return false; }
switch (className) {
// Strings, numbers, dates, and booleans are compared by value.
case '[object String]':
@@ -113,14 +115,14 @@ getJasmineRequireObj().matchersUtil = function(j$) {
a.multiline == b.multiline &&
a.ignoreCase == b.ignoreCase;
}
if (typeof a != 'object' || typeof b != 'object') return false;
if (typeof a != 'object' || typeof b != 'object') { return false; }
// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
var length = aStack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
if (aStack[length] == a) return bStack[length] == b;
if (aStack[length] == a) { return bStack[length] == b; }
}
// Add the first object to the stack of traversed objects.
aStack.push(a);
@@ -134,7 +136,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
if (result) {
// Deep compare the contents, ignoring non-numeric properties.
while (size--) {
if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) break;
if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) { break; }
}
}
} else {
@@ -151,13 +153,13 @@ getJasmineRequireObj().matchersUtil = function(j$) {
// Count the expected number of properties.
size++;
// Deep compare each member.
if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) break;
if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) { break; }
}
}
// Ensure that both objects contain the same number of properties.
if (result) {
for (key in b) {
if (has(b, key) && !(size--)) break;
if (has(b, key) && !(size--)) { break; }
}
result = !size;
}
@@ -176,4 +178,4 @@ getJasmineRequireObj().matchersUtil = function(j$) {
return typeof obj === 'function';
}
}
};
};

View File

@@ -5,21 +5,26 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
compare: function() {
var args = Array.prototype.slice.call(arguments, 0),
actual = args[0],
expectedArgs = args.slice(1);
expectedArgs = args.slice(1),
result = { pass: false };
if (!j$.isSpy(actual)) {
throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
}
return {
pass: util.contains(actual.calls.allArgs(), expectedArgs)
};
},
message: function(actual) {
return {
affirmative: "Expected spy " + actual.and.identity() + " to have been called.",
negative: "Expected spy " + actual.and.identity() + " not to have been called."
};
if (!actual.calls.any()) {
result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but it was never called.";
return result;
}
if (util.contains(actual.calls.allArgs(), expectedArgs)) {
result.pass = true;
result.message = "Expected spy " + actual.and.identity() + " not to have been called with " + j$.pp(expectedArgs) + " but it was.";
} else {
result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but actual calls were " + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + ".";
}
return result;
}
};
}

View File

@@ -8,7 +8,7 @@ function getJasmineRequireObj() {
}
getJasmineRequireObj().core = function(jRequire) {
j$ = {};
var j$ = {};
jRequire.base(j$);
j$.util = jRequire.util();
@@ -26,7 +26,7 @@ getJasmineRequireObj().core = function(jRequire) {
j$.pp = jRequire.pp(j$);
j$.QueueRunner = jRequire.QueueRunner();
j$.ReportDispatcher = jRequire.ReportDispatcher();
j$.Spec = jRequire.Spec();
j$.Spec = jRequire.Spec(j$);
j$.SpyStrategy = jRequire.SpyStrategy();
j$.Suite = jRequire.Suite();
j$.Timer = jRequire.Timer();

View File

@@ -3,14 +3,16 @@ getJasmineRequireObj().util = function() {
var util = {};
util.inherit = function(childClass, parentClass) {
var subclass = function() {
var Subclass = function() {
};
subclass.prototype = parentClass.prototype;
childClass.prototype = new subclass();
Subclass.prototype = parentClass.prototype;
childClass.prototype = new Subclass();
};
util.htmlEscape = function(str) {
if (!str) return str;
if (!str) {
return str;
}
return str.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
@@ -18,7 +20,9 @@ getJasmineRequireObj().util = function() {
util.argsToArray = function(args) {
var arrayOfArgs = [];
for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
for (var i = 0; i < args.length; i++) {
arrayOfArgs.push(args[i]);
}
return arrayOfArgs;
};

View File

@@ -1,8 +1,8 @@
jasmineRequire.HtmlReporter = function(j$) {
var noopTimer = {
start: function(){},
elapsed: function(){ return 0; }
start: function() {},
elapsed: function() { return 0; }
};
function HtmlReporter(options) {
@@ -73,7 +73,8 @@ jasmineRequire.HtmlReporter = function(j$) {
symbols.appendChild(createDom("li", {
className: result.status,
id: "spec_" + result.id,
title: result.fullName}
title: result.fullName
}
));
if (result.status == "failed") {
@@ -81,7 +82,9 @@ jasmineRequire.HtmlReporter = function(j$) {
var failure =
createDom("div", {className: "spec-detail failed"},
createDom("a", {className: "description", title: result.fullName, href: specHref(result)}, result.fullName),
createDom("div", {className: "description"},
createDom("a", {title: result.fullName, href: specHref(result)}, result.fullName)
),
createDom("div", {className: "messages"})
);
var messages = failure.childNodes[1];

View File

@@ -16,4 +16,4 @@ jasmineRequire.ResultsNode = function() {
}
return ResultsNode;
};
};

View File

@@ -93,11 +93,9 @@ body {
margin: $line-height 0;
li {
display: block;
float: left;
height: $line-height / 2;
display: inline-block;
height: ($line-height / 2) + 1;
width: $line-height;
margin-bottom: $line-height / 2;
font-size: 16px;
@@ -290,13 +288,11 @@ body {
margin-bottom: $line-height * 2;
.description {
//line-height: $line-height * 2;
display: block;
color: white;
background-color: $failing-color;
//font-size: $large-font-size;
a {
color: white;
}
}
}
}
@@ -305,7 +301,7 @@ body {
padding-top: $line-height;
color: $text-color;
white-space: pre;
}

View File

@@ -1,107 +0,0 @@
/* line 24, _HTMLReporter.scss */
body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
/* line 31, _HTMLReporter.scss */
.html-reporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
/* line 38, _HTMLReporter.scss */
.html-reporter a { text-decoration: none; }
/* line 41, _HTMLReporter.scss */
.html-reporter a:hover { text-decoration: underline; }
/* line 46, _HTMLReporter.scss */
.html-reporter p, .html-reporter h1, .html-reporter h2, .html-reporter h3, .html-reporter h4, .html-reporter h5, .html-reporter h6 { margin: 0; line-height: 14px; }
/* line 58, _HTMLReporter.scss */
.html-reporter .banner, .html-reporter .symbol-summary, .html-reporter .summary, .html-reporter .result-message, .html-reporter .spec .description, .html-reporter .spec-detail .description, .html-reporter .alert .bar, .html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; }
/* line 63, _HTMLReporter.scss */
.html-reporter .banner .version { margin-left: 14px; }
/* line 69, _HTMLReporter.scss */
.html-reporter #jasmine_content { position: fixed; right: 100%; }
/* line 74, _HTMLReporter.scss */
.html-reporter .version { color: #aaaaaa; }
/* line 80, _HTMLReporter.scss */
.html-reporter .banner { margin-top: 14px; }
/* line 84, _HTMLReporter.scss */
.html-reporter .duration { color: #aaaaaa; float: right; }
/* line 91, _HTMLReporter.scss */
.html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; }
/* line 95, _HTMLReporter.scss */
.html-reporter .symbol-summary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
/* line 104, _HTMLReporter.scss */
.html-reporter .symbol-summary li.passed { font-size: 14px; }
/* line 107, _HTMLReporter.scss */
.html-reporter .symbol-summary li.passed:before { color: #5e7d00; content: "\02022"; }
/* line 113, _HTMLReporter.scss */
.html-reporter .symbol-summary li.failed { line-height: 9px; }
/* line 116, _HTMLReporter.scss */
.html-reporter .symbol-summary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
/* line 124, _HTMLReporter.scss */
.html-reporter .symbol-summary li.disabled { font-size: 14px; }
/* line 127, _HTMLReporter.scss */
.html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; }
/* line 133, _HTMLReporter.scss */
.html-reporter .symbol-summary li.pending { line-height: 17px; }
/* line 135, _HTMLReporter.scss */
.html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; }
/* line 143, _HTMLReporter.scss */
.html-reporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
/* line 152, _HTMLReporter.scss */
.html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
/* line 159, _HTMLReporter.scss */
.html-reporter .bar.failed { background-color: #b03911; }
/* line 163, _HTMLReporter.scss */
.html-reporter .bar.passed { background-color: #a6b779; }
/* line 167, _HTMLReporter.scss */
.html-reporter .bar.skipped { background-color: #bababa; }
/* line 171, _HTMLReporter.scss */
.html-reporter .bar.menu { background-color: #fff; color: #aaaaaa; }
/* line 175, _HTMLReporter.scss */
.html-reporter .bar.menu a { color: #333333; }
/* line 180, _HTMLReporter.scss */
.html-reporter .bar a { color: white; }
/* line 188, _HTMLReporter.scss */
.html-reporter.spec-list .bar.menu.failure-list, .html-reporter.spec-list .results .failures { display: none; }
/* line 195, _HTMLReporter.scss */
.html-reporter.failure-list .bar.menu.spec-list, .html-reporter.failure-list .summary { display: none; }
/* line 200, _HTMLReporter.scss */
.html-reporter .running-alert { background-color: #666666; }
/* line 206, _HTMLReporter.scss */
.html-reporter .results { margin-top: 14px; }
/* line 214, _HTMLReporter.scss */
.html-reporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
/* line 218, _HTMLReporter.scss */
.html-reporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
/* line 223, _HTMLReporter.scss */
.html-reporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
/* line 228, _HTMLReporter.scss */
.html-reporter.showDetails .summary { display: none; }
/* line 232, _HTMLReporter.scss */
.html-reporter.showDetails #details { display: block; }
/* line 237, _HTMLReporter.scss */
.html-reporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
/* line 244, _HTMLReporter.scss */
.html-reporter .summary { margin-top: 14px; }
/* line 247, _HTMLReporter.scss */
.html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; }
/* line 253, _HTMLReporter.scss */
.html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; }
/* line 260, _HTMLReporter.scss */
.html-reporter .summary li.passed a { color: #5e7d00; }
/* line 264, _HTMLReporter.scss */
.html-reporter .summary li.failed a { color: #b03911; }
/* line 268, _HTMLReporter.scss */
.html-reporter .summary li.pending a { color: #ba9d37; }
/* line 274, _HTMLReporter.scss */
.html-reporter .description + .suite { margin-top: 0; }
/* line 278, _HTMLReporter.scss */
.html-reporter .suite { margin-top: 14px; }
/* line 281, _HTMLReporter.scss */
.html-reporter .suite a { color: #333333; }
/* line 289, _HTMLReporter.scss */
.html-reporter .failures .spec-detail { margin-bottom: 28px; }
/* line 292, _HTMLReporter.scss */
.html-reporter .failures .spec-detail .description { display: block; color: white; background-color: #b03911; }
/* line 304, _HTMLReporter.scss */
.html-reporter .result-message { padding-top: 14px; color: #333333; white-space: pre; }
/* line 312, _HTMLReporter.scss */
.html-reporter .result-message span.result { display: block; }
/* line 316, _HTMLReporter.scss */
.html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }

View File

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

View File

@@ -1,3 +1,3 @@
getJasmineRequireObj().version = function() {
return "<%= version %>";
};
};

View File

@@ -1,12 +1,14 @@
#!/bin/bash -e
export DISPLAY=:99.0
/etc/init.d/xvfb start
if [ $USE_SAUCE == true ]
then
if [ $TRAVIS_SECURE_ENV_VARS == true ]
then
curl https://gist.github.com/santiycr/5139565/raw/sauce_connect_setup.sh | bash
else
echo "skipping tests since we can't use sauce"
exit 0
fi
fi
bundle exec rake core_spec
bundle exec rake jasmine:ci

3
travis-docs-script.sh Normal file
View File

@@ -0,0 +1,3 @@
git clone https://github.com/jasmine/jasmine.github.io.git
bundle exec rake jasmine:ci JASMINE_CONFIG_PATH=jasmine.github.io/2.0/spec/support/jasmine.yml