Compare commits
417 Commits
1.0.0rc1
...
v2.0.0.rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be0e6222c5 | ||
|
|
8c696ffc71 | ||
|
|
3dda67fe60 | ||
|
|
66d9b3d690 | ||
|
|
c350694c1b | ||
|
|
25d674f2c5 | ||
|
|
35bc200e31 | ||
|
|
9e886b3972 | ||
|
|
edd7e3932b | ||
|
|
0420e295f4 | ||
|
|
8d295a2612 | ||
|
|
d10b93cd28 | ||
|
|
358b9424b5 | ||
|
|
2571a6fbbb | ||
|
|
00f88edc04 | ||
|
|
98fa58ee49 | ||
|
|
984074ec95 | ||
|
|
6bb8a91301 | ||
|
|
97ce396008 | ||
|
|
051f3499ec | ||
|
|
8f5d0beb8c | ||
|
|
9609aba25f | ||
|
|
30aec66ce5 | ||
|
|
663a58d617 | ||
|
|
3847557bbc | ||
|
|
18c30566bd | ||
|
|
f2306729cd | ||
|
|
2165d71dc5 | ||
|
|
8c1881053c | ||
|
|
61a1f93488 | ||
|
|
d4f78922cd | ||
|
|
04ac41d911 | ||
|
|
75b9dc64af | ||
|
|
2d7fe0b6ce | ||
|
|
44feee57ac | ||
|
|
1394899c3c | ||
|
|
d0825a37a3 | ||
|
|
fc3d08bf40 | ||
|
|
990cc41f45 | ||
|
|
03ffe5ce6a | ||
|
|
1b0b4f22a0 | ||
|
|
a6953df28c | ||
|
|
5e71f3031e | ||
|
|
4ea4ed25ee | ||
|
|
39d40a1cad | ||
|
|
d40e0cebac | ||
|
|
89a54ea2bb | ||
|
|
bc9c857f43 | ||
|
|
24a7f55fa6 | ||
|
|
182cff4bd4 | ||
|
|
5dce5b1272 | ||
|
|
7c17b06856 | ||
|
|
6569176cc9 | ||
|
|
0f803430e4 | ||
|
|
821f13dff5 | ||
|
|
3e2d9baec2 | ||
|
|
f637c1f833 | ||
|
|
82b6904093 | ||
|
|
0daae4d7b4 | ||
|
|
f68657f14e | ||
|
|
c91df21a96 | ||
|
|
5b986c953c | ||
|
|
a932320d6c | ||
|
|
aabf8cec82 | ||
|
|
ccdcb293f4 | ||
|
|
ec7d58fce0 | ||
|
|
7f6b16ccf2 | ||
|
|
34b8bf5fb0 | ||
|
|
179e54b9fb | ||
|
|
09fe7b0540 | ||
|
|
264b1fea50 | ||
|
|
dcf7a0867e | ||
|
|
f5bc9faf63 | ||
|
|
2916a8a1ff | ||
|
|
8ac33ff6c2 | ||
|
|
661a884416 | ||
|
|
7acc6b327a | ||
|
|
e40e0c9170 | ||
|
|
7ae3fa9fef | ||
|
|
e73b9e7902 | ||
|
|
ffdf1eb16d | ||
|
|
d5f1264416 | ||
|
|
579fddc2d2 | ||
|
|
313e607135 | ||
|
|
b6599d52aa | ||
|
|
582ad6512a | ||
|
|
600be098af | ||
|
|
b87eb240b3 | ||
|
|
7055d95584 | ||
|
|
1c87060804 | ||
|
|
b4acdbd90a | ||
|
|
fbb9f53524 | ||
|
|
0ac497db6b | ||
|
|
9e31201f1a | ||
|
|
d53002c63a | ||
|
|
3271dc8838 | ||
|
|
475aacbfbb | ||
|
|
8303c79f26 | ||
|
|
5700ace2c9 | ||
|
|
aca43bd3a3 | ||
|
|
7516bba2b0 | ||
|
|
4f19d34ad7 | ||
|
|
c40b64a24c | ||
|
|
baad5ff01f | ||
|
|
bf2adf55eb | ||
|
|
dd8d3f9788 | ||
|
|
9c4467bac0 | ||
|
|
c017257164 | ||
|
|
2445fb36dc | ||
|
|
eec6d7d23e | ||
|
|
3110da62e5 | ||
|
|
d41b281eb1 | ||
|
|
6feb124853 | ||
|
|
3be247ceb1 | ||
|
|
edc2bfae93 | ||
|
|
01b2fc612c | ||
|
|
d8f6aac2cd | ||
|
|
e7a930a5b3 | ||
|
|
6b2d8da55f | ||
|
|
538b32e401 | ||
|
|
e6e8908f49 | ||
|
|
86dafd5d2d | ||
|
|
aa60d5f00d | ||
|
|
079e6e1e08 | ||
|
|
7706512525 | ||
|
|
e09fd40933 | ||
|
|
6eecc562ff | ||
|
|
cf7bb0269b | ||
|
|
b22bf9a031 | ||
|
|
b7af6abca5 | ||
|
|
d6da13a8dd | ||
|
|
dc4563d45c | ||
|
|
92492c0144 | ||
|
|
d6987a6c84 | ||
|
|
43c8fdd33f | ||
|
|
98ae076f0c | ||
|
|
2c06e36b9b | ||
|
|
5a744884fe | ||
|
|
e6888b840d | ||
|
|
e682d18387 | ||
|
|
10b09ea9f5 | ||
|
|
c53b36a9b2 | ||
|
|
af71f4d2f9 | ||
|
|
83227f2163 | ||
|
|
f865758124 | ||
|
|
3fc79bac9e | ||
|
|
05977203a6 | ||
|
|
5bea864e1c | ||
|
|
a9eaa66da5 | ||
|
|
30bf565e69 | ||
|
|
668dd784ef | ||
|
|
4ad43267ab | ||
|
|
be6b87a31b | ||
|
|
43552494ee | ||
|
|
98c99c4ebb | ||
|
|
4318de4647 | ||
|
|
a526ebf261 | ||
|
|
c2e1327f39 | ||
|
|
234f2a1585 | ||
|
|
c584f182ab | ||
|
|
74f928fd54 | ||
|
|
a1011e7748 | ||
|
|
8b02bf731b | ||
|
|
779dee1211 | ||
|
|
1f5e790c41 | ||
|
|
cd3a0c854b | ||
|
|
f9cbad1512 | ||
|
|
f840458b34 | ||
|
|
34bd1969e7 | ||
|
|
dfed37531e | ||
|
|
08f5a8c98f | ||
|
|
8d94d0bfc5 | ||
|
|
3e5da57cf9 | ||
|
|
e2af08e0a6 | ||
|
|
b6c3999c3a | ||
|
|
6785d1a05c | ||
|
|
e74f09df9c | ||
|
|
f7c9aaa996 | ||
|
|
86994b25db | ||
|
|
9a7c76ea23 | ||
|
|
e3a013ae99 | ||
|
|
ead9aa6d5a | ||
|
|
d9467317a8 | ||
|
|
63ad879c12 | ||
|
|
b95c43ab7c | ||
|
|
3685d3199c | ||
|
|
a34077a8af | ||
|
|
ac55e26870 | ||
|
|
acdc497361 | ||
|
|
b527ccd2fa | ||
|
|
cfa95fcf2c | ||
|
|
ae9ddd74a2 | ||
|
|
26f0f6f213 | ||
|
|
c5ba032d28 | ||
|
|
bbc4c70c91 | ||
|
|
c5c57247f8 | ||
|
|
9990eb7b6e | ||
|
|
b5b50182b2 | ||
|
|
4d106c2b33 | ||
|
|
5e594946bb | ||
|
|
6ac4b686a3 | ||
|
|
fd91433792 | ||
|
|
1f9004eaa3 | ||
|
|
58e6747930 | ||
|
|
4c083856be | ||
|
|
b94522193c | ||
|
|
867de62699 | ||
|
|
74cdc5a04f | ||
|
|
ddbee65aa8 | ||
|
|
beeb872a82 | ||
|
|
dbcb0b7983 | ||
|
|
c8436d1d44 | ||
|
|
639f757f6f | ||
|
|
d65bdc7e59 | ||
|
|
a1ed56741b | ||
|
|
7473b455dc | ||
|
|
b6fb23b069 | ||
|
|
386e83b53f | ||
|
|
f2b25f1780 | ||
|
|
5ca2888301 | ||
|
|
147cb36760 | ||
|
|
107463ad57 | ||
|
|
39a55d8f10 | ||
|
|
4b48dc1069 | ||
|
|
921f52862f | ||
|
|
ea2ffb7b01 | ||
|
|
54fbc48eb2 | ||
|
|
06c900ab20 | ||
|
|
3e070e9db6 | ||
|
|
7e04571ec0 | ||
|
|
ddd48f2c88 | ||
|
|
1c2e50d244 | ||
|
|
d2d60a798d | ||
|
|
442f3bf872 | ||
|
|
f910df00bb | ||
|
|
500b856cfa | ||
|
|
dad4865fbf | ||
|
|
1771ec3c63 | ||
|
|
2385acedd8 | ||
|
|
4c28bef387 | ||
|
|
7bbcf51d45 | ||
|
|
b6f96bc121 | ||
|
|
feebfbba68 | ||
|
|
8e4bd86865 | ||
|
|
4f218f7d6a | ||
|
|
bb1a4428db | ||
|
|
079740ca2c | ||
|
|
fbbccf6ef7 | ||
|
|
7ad75c13d4 | ||
|
|
d46ca4f506 | ||
|
|
ee7af4496c | ||
|
|
e22c4492a5 | ||
|
|
d63836afb4 | ||
|
|
06f1edc197 | ||
|
|
3a6b233a2e | ||
|
|
d15964b7dc | ||
|
|
6e22754c10 | ||
|
|
bab4538404 | ||
|
|
06d191af74 | ||
|
|
ad78d0d0d8 | ||
|
|
733a6a4ae4 | ||
|
|
3e0cad41f5 | ||
|
|
885832e920 | ||
|
|
3a0ada034b | ||
|
|
674197aef8 | ||
|
|
626da5a112 | ||
|
|
a3ccd8b0d3 | ||
|
|
4a1a2123a3 | ||
|
|
c87cf71f4f | ||
|
|
e4c557faae | ||
|
|
6559c5b43a | ||
|
|
912397120b | ||
|
|
551464b8d2 | ||
|
|
8a298e5c0e | ||
|
|
94a153ed15 | ||
|
|
b4439f74d5 | ||
|
|
d70e733f70 | ||
|
|
ac096f9911 | ||
|
|
08d72926ff | ||
|
|
67ec0af254 | ||
|
|
4f2fcff15a | ||
|
|
7158fc2426 | ||
|
|
992367dcbc | ||
|
|
ce886e20e4 | ||
|
|
86b0c80cc9 | ||
|
|
7dff84b1dc | ||
|
|
8c22b26d9c | ||
|
|
ad4f48dcd4 | ||
|
|
de9e2abad5 | ||
|
|
41f496001f | ||
|
|
6b5956724b | ||
|
|
ec24992250 | ||
|
|
83f232237d | ||
|
|
98d32bb4a4 | ||
|
|
c4f27ae377 | ||
|
|
a075c75bce | ||
|
|
a617b59e6a | ||
|
|
917b37481e | ||
|
|
67bbc98faa | ||
|
|
620f7b6e4c | ||
|
|
b722f416c7 | ||
|
|
634a7dc402 | ||
|
|
a4522e4dce | ||
|
|
e113c338d0 | ||
|
|
b81f690a25 | ||
|
|
c06e189699 | ||
|
|
67b6cfb828 | ||
|
|
57e622fb2a | ||
|
|
c0664dd6aa | ||
|
|
b640ce6fc0 | ||
|
|
e9af7834f5 | ||
|
|
0d43ae9c38 | ||
|
|
30431a3958 | ||
|
|
3775919c92 | ||
|
|
a692ff8c95 | ||
|
|
e4e9b51544 | ||
|
|
0b97951766 | ||
|
|
75dd391d57 | ||
|
|
ae24e00c0f | ||
|
|
6b2e45eab5 | ||
|
|
e59171935f | ||
|
|
2ba0aa371c | ||
|
|
c2ed71717f | ||
|
|
09e8822107 | ||
|
|
15763c2eb0 | ||
|
|
3f264cde34 | ||
|
|
f83cb7f766 | ||
|
|
9d5470ff55 | ||
|
|
86b095e5a4 | ||
|
|
4c6dafa3f5 | ||
|
|
3f4adf7715 | ||
|
|
af7f1818b0 | ||
|
|
12f56787b0 | ||
|
|
e88d88e427 | ||
|
|
ba10d178b2 | ||
|
|
da297d0f56 | ||
|
|
7ead5388c2 | ||
|
|
a445a62e7c | ||
|
|
1d65d56a92 | ||
|
|
d875d1d997 | ||
|
|
1fae8f0a31 | ||
|
|
c1f8151bcb | ||
|
|
bd8a3baed1 | ||
|
|
118324b451 | ||
|
|
c30f7d1aa7 | ||
|
|
de7be4b316 | ||
|
|
b02aa9840a | ||
|
|
61de2268fe | ||
|
|
dd32048383 | ||
|
|
32e736aa47 | ||
|
|
38e9af8f68 | ||
|
|
e826fbb170 | ||
|
|
0c77662c5b | ||
|
|
75fb19bc49 | ||
|
|
6ec825f62d | ||
|
|
fc994108db | ||
|
|
70aed2d900 | ||
|
|
ccfa17499f | ||
|
|
ab087ef5f8 | ||
|
|
0ef6582f73 | ||
|
|
a1ba43c864 | ||
|
|
88ee377662 | ||
|
|
f5afe18a6b | ||
|
|
2731716ccb | ||
|
|
4e5083d570 | ||
|
|
b9cbd3c5a0 | ||
|
|
e42026ee84 | ||
|
|
a1f58f8be4 | ||
|
|
ac00d765d2 | ||
|
|
b1dceeacd4 | ||
|
|
5018f0d1c2 | ||
|
|
9704550b33 | ||
|
|
882c287191 | ||
|
|
7d2b900b48 | ||
|
|
f701fdc132 | ||
|
|
eb49fab652 | ||
|
|
e8c8a0bdfd | ||
|
|
e6a080039f | ||
|
|
c485c33a3c | ||
|
|
8fbf3ba859 | ||
|
|
dccafe33b0 | ||
|
|
c1d2718bea | ||
|
|
945a9ba638 | ||
|
|
528b5abeda | ||
|
|
d7cced2e7c | ||
|
|
3be0610572 | ||
|
|
5e90115eaf | ||
|
|
148317eb90 | ||
|
|
45b4e1316c | ||
|
|
aee4c5926c | ||
|
|
f41af6c2d0 | ||
|
|
9f90c4eca5 | ||
|
|
545752ae20 | ||
|
|
c04f1b1fa8 | ||
|
|
fa9741dbda | ||
|
|
560cb2edcb | ||
|
|
9a12b32a3a | ||
|
|
bd15ed6a45 | ||
|
|
fa74051071 | ||
|
|
127fe049d9 | ||
|
|
550e378dc0 | ||
|
|
377703745f | ||
|
|
8ecfd26325 | ||
|
|
2d10cc1404 | ||
|
|
63df354e78 | ||
|
|
dbcabd397e | ||
|
|
a8b0a0ee4f | ||
|
|
60a5d60f42 | ||
|
|
c8d9fc562f | ||
|
|
1530ad25f9 | ||
|
|
b2557e4ebe | ||
|
|
85c265e7c5 | ||
|
|
cc36a1808b | ||
|
|
685344342a | ||
|
|
a4eab045a0 | ||
|
|
cd0346b449 | ||
|
|
f134c6e386 |
14
.gitignore
vendored
@@ -1,6 +1,16 @@
|
||||
.idea/
|
||||
.svn/
|
||||
.DS_Store
|
||||
_site/
|
||||
site/
|
||||
.bundle/
|
||||
.pairs
|
||||
.pairs
|
||||
.rvmrc
|
||||
*.gem
|
||||
.bundle
|
||||
tags
|
||||
Gemfile.lock
|
||||
pkg/*
|
||||
.sass-cache/*
|
||||
src/html/.sass-cache/*
|
||||
node_modules/
|
||||
*.swp
|
||||
|
||||
2
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
||||
[submodule "pages"]
|
||||
path = pages
|
||||
url = git@github.com:pivotal/jasmine.git
|
||||
url = https://github.com/pivotal/jasmine.git
|
||||
|
||||
47
.travis.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
script: $TEST_COMMAND
|
||||
language: ruby
|
||||
rvm: 1.9.3
|
||||
env:
|
||||
global:
|
||||
- USE_SAUCE=true
|
||||
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
|
||||
- TEST_COMMAND="bash travis-core-script.sh"
|
||||
- secure: WSPWhlnC4mWSnSPquX+m1/BCu5ch5NygkaHuM2Nea7lD8oS3XLX8QncZZAsQ4lnNfqoDDuBOizG0AESiqNvE4y6x5qvLLTS6q+ce255ZEMZ71TBdZgDEEvGMEjOPPsVXiXyTQOP1lwOPlrbZvaPgWV7e11KIBab6DfFcQpnvDgo=
|
||||
- secure: SW7CJhZnwaNT749Gdnhvqb5rbXlAOsygUAzh9qhtyvbqXKkmJdBIEsO01YF6pbju1X2twE9JvWCOxeZju43NgQChJlPsGbjY2j3k/TdQeTAJesQe2K7ytwghunI30gjEovtRH0T3w1EmcKPH8yj5eBIcB2OYoJHx8KEC7e68q1g=
|
||||
matrix:
|
||||
include:
|
||||
- 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:
|
||||
- JASMINE_BROWSER="internet explorer"
|
||||
- SAUCE_PLATFORM="Windows 8"
|
||||
- SAUCE_VERSION=10
|
||||
- env:
|
||||
- JASMINE_BROWSER="internet explorer"
|
||||
- SAUCE_PLATFORM="Windows 7"
|
||||
- SAUCE_VERSION=9
|
||||
- env:
|
||||
- JASMINE_BROWSER="internet explorer"
|
||||
- SAUCE_PLATFORM="Windows 7"
|
||||
- SAUCE_VERSION=8
|
||||
- env:
|
||||
- JASMINE_BROWSER="chrome"
|
||||
- SAUCE_PLATFORM="Linux"
|
||||
- SAUCE_VERSION=''
|
||||
- env:
|
||||
- JASMINE_BROWSER="phantomjs"
|
||||
- USE_SAUCE=false
|
||||
111
Contribute.markdown
Normal file
@@ -0,0 +1,111 @@
|
||||
# Developing for Jasmine Core
|
||||
|
||||
We welcome your contributions - Thanks for helping make Jasmine a better project for everyone. Please review the backlog and discussion lists (the main group - [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js) and the developer's list - [http://groups.google.com/group/jasmine-js-dev](http://groups.google.com/group/jasmine-js-dev)) before starting work - what you're looking for may already have been done. If it hasn't, the community can help make your contribution better.
|
||||
|
||||
## General Workflow
|
||||
|
||||
Please submit pull requests via feature branches using the semi-standard workflow of:
|
||||
|
||||
1. Fork it
|
||||
1. Create your feature branch (`git checkout -b my-new-feature`)
|
||||
1. Commit your changes (`git commit -am 'Add some feature'`)
|
||||
1. Push to the branch (`git push origin my-new-feature`)
|
||||
1. Create new Pull Request
|
||||
|
||||
We favor pull requests with very small, single commits with a single purpose.
|
||||
|
||||
## Background
|
||||
|
||||
### Directory Structure
|
||||
|
||||
* `/src` contains all of the source files
|
||||
* `/src/console` - Node.js-specific files
|
||||
* `/src/core` - generic source files
|
||||
* `/src/html` - browser-specific files
|
||||
* `/spec` contains all of the tests
|
||||
* mirrors the source directory
|
||||
* there are some additional files
|
||||
* `/dist` contains the standalone distributions as zip files
|
||||
* `/lib` contains the generated files for distribution as the Jasmine Rubygem and the Python package
|
||||
|
||||
### Self-testing
|
||||
|
||||
Note that Jasmine tests itself. The files in `lib` are loaded first, defining the reference `jasmine`. Then the files in `src` are loaded, defining the reference `j$`. So there are two copies of the code loaded under test.
|
||||
|
||||
The tests should always use `j$` to refer to the objects and functions that are being tested. But the tests can use functions on `jasmine` as needed. _Be careful how you structure any new test code_. Copy the patterns you see in the existing code - this ensures that the code you're testing is not leaking into the `jasmine` reference and vice-versa.
|
||||
|
||||
### `boot.js`
|
||||
|
||||
__This is new for Jasmine 2.0.__
|
||||
|
||||
This file does all of the setup necessary for Jasmine to work. It loads all of the code, creates an `Env`, attaches the global functions, and builds the reporter. It also sets up the execution of the `Env` - for browsers this is in `window.onload`. While the default in `lib` is appropriate for browsers, projects may wish to customize this file.
|
||||
|
||||
For example, for Jasmine development there is a different `dev_boot.js` for Jasmine development that does more work.
|
||||
|
||||
### Compatibility
|
||||
|
||||
* Browser Minimum
|
||||
* IE8
|
||||
* Firefox 3.x
|
||||
* Chrome ??
|
||||
* Safari 5
|
||||
|
||||
## Development
|
||||
|
||||
All source code belongs in `src/`. The `core/` directory contains the bulk of Jasmine's functionality. This code should remain browser- and environment-agnostic. If your feature or fix cannot be, as mentioned above, please degrade gracefully. Any code that should only be in a non-browser environment should live in `src/console/`. Any code that depends on a browser (specifically, it expects `window` to be the global or `document` is present) should live in `src/html/`.
|
||||
|
||||
### Install Dependencies
|
||||
|
||||
Jasmine Core relies on Ruby and Node.js.
|
||||
|
||||
To install the Ruby dependencies, you will need Ruby, Rubygems, and Bundler available. Then:
|
||||
|
||||
$ bundle
|
||||
|
||||
...will install all of the Ruby dependencies.
|
||||
|
||||
To install the Node dependencies, you will need Node.js, Npm, and [Grunt](http://gruntjs.com/), the [grunt-cli](https://github.com/gruntjs/grunt-cli) and ensure that `grunt` is on your path.
|
||||
|
||||
$ npm install --local
|
||||
|
||||
...will install all of the node modules locally. If when you run
|
||||
|
||||
$ grunt
|
||||
|
||||
...you see that JSHint runs your system is ready.
|
||||
|
||||
### How to write new Jasmine code
|
||||
|
||||
Or, How to make a successful pull request
|
||||
|
||||
* _Do not change the public interface_. Lots of projects depend on Jasmine and if you aren't careful you'll break them
|
||||
* _Be environment agnostic_ - server-side developers are just as important as browser developers
|
||||
* _Be browser agnostic_ - if you must rely on browser-specific functionality, please write it in a way that degrades gracefully
|
||||
* _Write specs_ - Jasmine's a testing framework; don't add functionality without test-driving it
|
||||
* _Write code in the style of the rest of the repo_ - Jasmine should look like a cohesive whole
|
||||
* _Ensure the *entire* test suite is green_ in all the big browsers, Node, and JSHint - your contribution shouldn't break Jasmine for other users
|
||||
|
||||
Follow these tips and your pull request, patch, or suggestion is much more likely to be integrated.
|
||||
|
||||
### Running Specs
|
||||
|
||||
Jasmine uses the [Jasmine Ruby gem](http://github.com/pivotal/jasmine-gem) to test itself in browser.
|
||||
|
||||
$ rake jasmine
|
||||
|
||||
...and then visit `http://localhost:8888` to run specs.
|
||||
|
||||
Jasmine uses Node.js with a custom runner to test outside of a browser.
|
||||
|
||||
$ grunt execSpecsInNode
|
||||
|
||||
...and then the results will print to the console. All specs run except those that expect a browser (the specs in `spec/html` are ignored).
|
||||
|
||||
## Before Committing or Submitting a Pull Request
|
||||
|
||||
1. Ensure all specs are green in browser *and* node
|
||||
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
|
||||
|
||||
Note that we use Travis for Continuous Integration. We only accept green pull requests.
|
||||
|
||||
61
GOALS_2.0.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# (Vague) Jasmine 2.0 Goals/(Guidelines)
|
||||
|
||||
1. No globals!
|
||||
* jasmine library is entirely inside `jasmine` namespace
|
||||
* globals required for backwards compatibility should be added in `boot.js` (EG, var describe = jasmine.getCurrentEnv().describe lives in boot.js)
|
||||
1. Don't use properties as getters. Use methods.
|
||||
* Properties aren't encapsulated -- can be mutated, unsafe.
|
||||
1. Reporters get data objects (no methods).
|
||||
* easier to refactor as needed
|
||||
1. More unit tests - fewer nasty integration tests
|
||||
|
||||
## Remaining non-story-able work:
|
||||
* Make a `TODO` list
|
||||
|
||||
### Hard
|
||||
* Finish killing Globals
|
||||
* Guidelines:
|
||||
* New objects can have constructors on `jasmine`
|
||||
* Top level functions can live on `jasmine`
|
||||
* 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_
|
||||
* isDOMNode_
|
||||
* isA_
|
||||
* unimplementedMethod_, used by PrettyPrinter
|
||||
* jasmine.util should be util closure inside of env or something
|
||||
* argsToArray is used for Spies and matching (and can be replaced)
|
||||
* 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 ?
|
||||
|
||||
### Easy
|
||||
|
||||
* 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?)
|
||||
|
||||
## Other Topics
|
||||
|
||||
* Docs
|
||||
* Docco has gone over well. Should we annotate all the sources and then have Pages be more complex, having tutorials and annotated source like Backbone? Are we small enough?
|
||||
* Need examples for:
|
||||
* How to build a Custom Matcher
|
||||
* How to add a custom equality tester
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
15
Gemfile
@@ -1,6 +1,11 @@
|
||||
source :gemcutter
|
||||
source 'https://rubygems.org'
|
||||
gem "rake"
|
||||
gem "jasmine", :git => 'https://github.com/pivotal/jasmine-gem.git'
|
||||
#gem "jasmine", path: "/Users/pivotal/workspace/jasmine-gem"
|
||||
unless ENV["TRAVIS"]
|
||||
group :debug do
|
||||
gem 'debugger'
|
||||
end
|
||||
end
|
||||
|
||||
gem "jekyll", "0.6.2"
|
||||
gem "json_pure", "~>1.4.3"
|
||||
gem "ragaskar-jsdoc_helper"
|
||||
gem "rake", "0.8.7"
|
||||
gemspec
|
||||
|
||||
48
Gruntfile.js
Normal file
@@ -0,0 +1,48 @@
|
||||
module.exports = function(grunt) {
|
||||
var pkg = require("./package.json");
|
||||
global.jasmineVersion = pkg.version;
|
||||
|
||||
grunt.initConfig({
|
||||
pkg: pkg,
|
||||
jshint: require('./grunt/config/jshint.js'),
|
||||
concat: require('./grunt/config/concat.js'),
|
||||
compass: require('./grunt/config/compass.js'),
|
||||
compress: require('./grunt/config/compress.js')
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-compass');
|
||||
grunt.loadNpmTasks('grunt-contrib-compress');
|
||||
|
||||
grunt.loadTasks('grunt/tasks');
|
||||
|
||||
grunt.registerTask('default', ['jshint:all']);
|
||||
|
||||
var version = require('./grunt/tasks/version.js');
|
||||
var standaloneBuilder = require('./grunt/tasks/build_standalone.js');
|
||||
|
||||
grunt.registerTask('build:copyVersionToGem',
|
||||
"Propagates the version from package.json to version.rb",
|
||||
version.copyToGem);
|
||||
|
||||
grunt.registerTask('buildDistribution',
|
||||
'Builds and lints jasmine.js, jasmine-html.js, jasmine.css',
|
||||
[
|
||||
'compass',
|
||||
'jshint:beforeConcat',
|
||||
'concat',
|
||||
'jshint:afterConcat',
|
||||
'build:copyVersionToGem'
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
var spec = require('./grunt/tasks/spec.js');
|
||||
|
||||
grunt.registerTask("execSpecsInNode",
|
||||
"Run Jasmine core specs in Node.js",
|
||||
spec.execSpecsInNode
|
||||
);
|
||||
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2008-2010 Pivotal Labs
|
||||
Copyright (c) 2008-2011 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
<a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a>
|
||||
<a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a> [](https://travis-ci.org/pivotal/jasmine)
|
||||
|
||||
=======
|
||||
**A JavaScript Testing Framework**
|
||||
|
||||
Want to use Jasmine in a project? Go HERE: [http://pivotal.github.com/jasmine/](http://pivotal.github.com/jasmine/)
|
||||
Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on browsers, DOM, or any JavaScript framework. Thus it's suited for websites, [Node.js](http://nodejs.org) projects, or anywhere that JavaScript can run.
|
||||
|
||||
Want to contribute to Jasmine? Read on...
|
||||
Documentation & guides live here: [http://pivotal.github.com/jasmine/](http://pivotal.github.com/jasmine/)
|
||||
|
||||
<i>(More developer docs to come...)</i>
|
||||
## Contributing
|
||||
|
||||
Please read the [contributors' guide](https://github.com/pivotal/jasmine/blob/master/Contribute.markdown)
|
||||
|
||||
## Support
|
||||
We now have a Google Group for support & discussion.
|
||||
|
||||
* Discussion: [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js)
|
||||
* Group email: [jasmine-js@googlegroups.com](jasmine-js@googlegroups.com)
|
||||
* Current build status of Jasmine is visible at [ci.pivotallabs.com](http://ci.pivotallabs.com)
|
||||
* Pivotal Tracker project: [http://www.pivotaltracker.com/projects/10606](http://www.pivotaltracker.com/projects/10606)
|
||||
* Twitter: [@JasmineBDD](http://twitter.com/JasmineBDD)
|
||||
* Search past discussions: [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js)
|
||||
* Send an email to the list: [jasmine-js@googlegroups.com](jasmine-js@googlegroups.com)
|
||||
* View the project backlog at Pivotal Tracker: [http://www.pivotaltracker.com/projects/10606](http://www.pivotaltracker.com/projects/10606)
|
||||
* Follow us on Twitter: [@JasmineBDD](http://twitter.com/JasmineBDD)
|
||||
|
||||
## Maintainers
|
||||
|
||||
* [Davis W. Frank](mailto:dwfrank@pivotallabs.com), Pivotal Labs
|
||||
* [Rajan Agaskar](mailto:rajan@pivotallabs.com), Pivotal Labs
|
||||
* [Christian Williams](mailto:xian@pivotallabs.com), Pivotal Labs
|
||||
* [Christian Williams](mailto:antixian666@gmail.com), Square
|
||||
|
||||
## Developers
|
||||
We welcome your contributions! Jasmine is currently maintained by Davis Frank ([infews](http://github.com/infews)), Rajan Agaskar ([ragaskar](http://github.com/ragaskar)), and Christian Williams ([Xian](http://github.com/Xian)). You can help us by removing all other recipients from your pull request.
|
||||
|
||||
Copyright (c) 2008-2010 Pivotal Labs. This software is licensed under the MIT License.
|
||||
Copyright (c) 2008-2013 Pivotal Labs. This software is licensed under the MIT License.
|
||||
|
||||
191
Rakefile
@@ -1,176 +1,39 @@
|
||||
def jasmine_sources
|
||||
sources = ["src/base.js", "src/util.js", "src/Env.js", "src/Reporter.js", "src/Block.js"]
|
||||
sources += Dir.glob('src/*.js').reject { |f| f == 'src/base.js' || sources.include?(f) }.sort
|
||||
sources
|
||||
require "bundler"
|
||||
Bundler::GemHelper.install_tasks
|
||||
require "json"
|
||||
require "jasmine"
|
||||
|
||||
Dir["#{File.dirname(__FILE__)}/tasks/**/*.rb"].each do |file|
|
||||
require file
|
||||
end
|
||||
|
||||
def jasmine_html_sources
|
||||
["src/html/TrivialReporter.js"]
|
||||
end
|
||||
|
||||
def jasmine_version
|
||||
"#{version_hash['major']}.#{version_hash['minor']}.#{version_hash['build']}"
|
||||
end
|
||||
|
||||
def version_hash
|
||||
require 'json'
|
||||
@version ||= JSON.parse(File.new("src/version.json").read);
|
||||
end
|
||||
|
||||
task :default => 'jasmine:dist'
|
||||
|
||||
def substitute_jasmine_version(filename)
|
||||
contents = File.read(filename)
|
||||
contents = contents.gsub(/##JASMINE_VERSION##/, (jasmine_version))
|
||||
contents = contents.gsub(/[^\n]*REMOVE_THIS_LINE_FROM_BUILD[^\n]*/, '')
|
||||
File.open(filename, 'w') { |f| f.write(contents) }
|
||||
# TODO: Is there better way to invoke this using Jasmine gem???
|
||||
task :core_spec do
|
||||
exec "ruby spec/jasmine_self_test_spec.rb"
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
desc 'Prepares for distribution'
|
||||
task :dist => ['jasmine:build', 'jasmine:doc', 'jasmine:build_example_project', 'jasmine:fill_index_downloads']
|
||||
|
||||
desc 'Check jasmine sources for coding problems'
|
||||
task :lint do
|
||||
passed = true
|
||||
jasmine_sources.each do |src|
|
||||
lines = File.read(src).split(/\n/)
|
||||
lines.each_index do |i|
|
||||
line = lines[i]
|
||||
undefineds = line.scan(/.?undefined/)
|
||||
if undefineds.include?(" undefined") || undefineds.include?("\tundefined")
|
||||
puts "Dangerous undefined at #{src}:#{i}:\n > #{line}"
|
||||
passed = false
|
||||
end
|
||||
|
||||
if line.scan(/window/).length > 0
|
||||
puts "Dangerous window at #{src}:#{i}:\n > #{line}"
|
||||
passed = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
unless passed
|
||||
puts "Lint failed!"
|
||||
exit 1
|
||||
end
|
||||
puts "your tests are here:"
|
||||
puts " http://localhost:#{port}/"
|
||||
end
|
||||
|
||||
desc 'Builds lib/jasmine from source'
|
||||
task :build => :lint do
|
||||
puts 'Building Jasmine from source'
|
||||
desc "Copy examples from Jasmine JS to the gem"
|
||||
task :copy_examples_to_gem do
|
||||
require "fileutils"
|
||||
|
||||
sources = jasmine_sources
|
||||
version = version_hash
|
||||
|
||||
old_jasmine_files = Dir.glob('lib/jasmine*.js')
|
||||
old_jasmine_files.each { |file| File.delete(file) }
|
||||
|
||||
File.open("lib/jasmine.js", 'w') do |jasmine|
|
||||
sources.each do |source_filename|
|
||||
jasmine.puts(File.read(source_filename))
|
||||
end
|
||||
|
||||
jasmine.puts %{
|
||||
jasmine.version_= {
|
||||
"major": #{version['major']},
|
||||
"minor": #{version['minor']},
|
||||
"build": #{version['build']},
|
||||
"revision": #{Time.now.to_i}
|
||||
};
|
||||
}
|
||||
end
|
||||
|
||||
File.open("lib/jasmine-html.js", 'w') do |jasmine_html|
|
||||
jasmine_html_sources.each do |source_filename|
|
||||
jasmine_html.puts(File.read(source_filename))
|
||||
end
|
||||
end
|
||||
|
||||
FileUtils.cp("src/html/jasmine.css", "lib/jasmine.css")
|
||||
end
|
||||
|
||||
task :need_pages_submodule do
|
||||
unless File.exists?('pages/index.html')
|
||||
raise "Jasmine pages submodule isn't present. Run git submodule update --init"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Build jasmine documentation"
|
||||
task :doc => :need_pages_submodule do
|
||||
puts 'Creating Jasmine Documentation'
|
||||
require 'rubygems'
|
||||
require 'jsdoc_helper'
|
||||
|
||||
FileUtils.rm_r "pages/jsdoc", :force => true
|
||||
|
||||
JsdocHelper::Rake::Task.new(:lambda_jsdoc) do |t|
|
||||
t[:files] = jasmine_sources << jasmine_html_sources
|
||||
t[:options] = "-a"
|
||||
t[:out] = "pages/jsdoc"
|
||||
end
|
||||
Rake::Task[:lambda_jsdoc].invoke
|
||||
end
|
||||
|
||||
desc "Build example project"
|
||||
task :build_example_project => :need_pages_submodule do
|
||||
require 'tmpdir'
|
||||
|
||||
temp_dir = File.join(Dir.tmpdir, 'jasmine-standalone-project')
|
||||
puts "Building Example Project in #{temp_dir}"
|
||||
FileUtils.rm_r temp_dir if File.exists?(temp_dir)
|
||||
Dir.mkdir(temp_dir)
|
||||
|
||||
root = File.expand_path(File.dirname(__FILE__))
|
||||
FileUtils.cp_r File.join(root, 'example/.'), File.join(temp_dir)
|
||||
substitute_jasmine_version(File.join(temp_dir, "SpecRunner.html"))
|
||||
|
||||
lib_dir = File.join(temp_dir, "lib/jasmine-#{jasmine_version}")
|
||||
FileUtils.mkdir_p(lib_dir)
|
||||
{
|
||||
"lib/jasmine.js" => "jasmine.js",
|
||||
"lib/jasmine-html.js" => "jasmine-html.js",
|
||||
"src/html/jasmine.css" => "jasmine.css"
|
||||
}.each_pair do |src, dest|
|
||||
FileUtils.cp(File.join(root, src), File.join(lib_dir, dest))
|
||||
end
|
||||
|
||||
dist_dir = File.join(root, 'pages/downloads')
|
||||
zip_file_name = File.join(dist_dir, "jasmine-standalone-#{jasmine_version}.zip")
|
||||
puts "Zipping Example Project and moving to #{zip_file_name}"
|
||||
FileUtils.mkdir(dist_dir) unless File.exist?(dist_dir)
|
||||
if File.exist?(zip_file_name)
|
||||
puts "WARNING!!! #{zip_file_name} already exists!"
|
||||
FileUtils.rm(zip_file_name)
|
||||
end
|
||||
exec "cd #{temp_dir} && zip -r #{zip_file_name} . -x .[a-zA-Z0-9]*"
|
||||
end
|
||||
|
||||
task :fill_index_downloads do
|
||||
require 'digest/sha1'
|
||||
|
||||
download_html = "<!-- START_DOWNLOADS -->\n"
|
||||
download_html += "<table>\n<tr><th/><th>Version</th><th>Size</th><th>Date</th><th>SHA1</th></tr>\n"
|
||||
Dir.glob('pages/downloads/*.zip').sort.reverse.each do |f|
|
||||
sha1 = Digest::SHA1.hexdigest File.read(f)
|
||||
|
||||
fn = f.sub(/^pages\//, '')
|
||||
version = /jasmine-standalone-(.*).zip/.match(f)[1]
|
||||
download_html += "<td class=\"link\"><a href='#{fn}'>#{fn.sub(/downloads\//, '')}</a></td>\n"
|
||||
download_html += "<td class=\"version\">#{version}</td>\n"
|
||||
download_html += "<td class=\"size\">#{File.size(f) / 1024}k</td>\n"
|
||||
download_html += "<td class=\"date\">#{File.mtime(f).strftime("%Y/%m/%d %H:%M:%S %Z")}</td>\n"
|
||||
download_html += "<td class=\"sha\">#{sha1}</td>\n"
|
||||
end
|
||||
download_html += "</table>\n<!-- END_DOWNLOADS -->"
|
||||
|
||||
index_page = File.read('pages/index.html')
|
||||
matcher = /<!-- START_DOWNLOADS -->.*<!-- END_DOWNLOADS -->/m
|
||||
index_page = index_page.sub(matcher, download_html)
|
||||
File.open('pages/index.html', 'w') {|f| f.write(index_page)}
|
||||
puts "rewrote that file"
|
||||
# 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)
|
||||
end
|
||||
end
|
||||
|
||||
task :jasmine => ['jasmine:dist']
|
||||
desc "Run specs via server"
|
||||
task :jasmine => ['jasmine:server']
|
||||
|
||||
47
Release.markdown
Normal file
@@ -0,0 +1,47 @@
|
||||
# How to work on a Jasmine Release
|
||||
|
||||
## Development
|
||||
___Jasmine Core Maintainers Only___
|
||||
|
||||
Follow the instructions in `Contribute.markdown` during development.
|
||||
|
||||
### Git Rules
|
||||
|
||||
Please work on feature branches.
|
||||
|
||||
Please attempt to keep commits to `master` small, but cohesive. If a feature is contained in a bunch of small commits (e.g., it has several wip commits or small work), please squash them when merging back to `master`.
|
||||
|
||||
### Version
|
||||
|
||||
We attempt to stick to [Semantic Versioning](http://semver.org/). Most of the time, development should be against a new minor version - fixing bugs and adding new features that are backwards compatible.
|
||||
|
||||
The current version lives in the file `/package.json`. This file should be set to the version that is _currently_ under development. That is, if version 1.0.0 is the current release then version should be incremented say, to 1.1.0.
|
||||
|
||||
This version is used by both `jasmine.js` and the `jasmine-core` Ruby gem.
|
||||
|
||||
Note that Jasmine should *not* use the "patch" version number. Let downstream projects rev their patch versions as needed, keeping their major and minor version numbers in sync with Jasmine core.
|
||||
|
||||
### Update the Github Pages (as needed)
|
||||
|
||||
___Note: This is going to change right after 2.0___
|
||||
|
||||
Github pages have to exist in a branch called `gh-pages` in order for their app to serve them. This repo adds that branch as a submodule under the `pages` directory. This is a bit of a hack, but it allows us to work with the pages and the source at the same time and with one set of rake tasks.
|
||||
|
||||
If you want to submit changes to this repo and aren't a Pivotal Labs employee, you can fork and work in the `gh-pages` branch. You won't be able to edit the pages in the submodule off of master.
|
||||
|
||||
## Release
|
||||
|
||||
When ready to release - specs are all green and the stories are done:
|
||||
|
||||
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`
|
||||
1. Make sure you add the new ZIP file to git
|
||||
1. Copy version to the Ruby gem with `grunt build:copyVersionToGem`
|
||||
1. __NOTE__: You will likely need to point to a local jasmine gem in order to run tests locally. _Do not_ push this version of the Gemfile.
|
||||
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.
|
||||
|
||||
|
||||
There should be a post to Pivotal Labs blog and a tweet to that link.
|
||||
@@ -1,21 +0,0 @@
|
||||
# Project-specific configuration for CruiseControl.rb
|
||||
Project.configure do |project|
|
||||
|
||||
# Send email notifications about broken and fixed builds to email1@your.site, email2@your.site (default: send to nobody)
|
||||
# project.email_notifier.emails = ['email1@your.site', 'email2@your.site']
|
||||
|
||||
# Set email 'from' field to john@doe.com:
|
||||
# project.email_notifier.from = 'john@doe.com'
|
||||
|
||||
# Build the project by invoking rake task 'custom'
|
||||
project.rake_task = 'jasmine:test:ci:saucelabs'
|
||||
|
||||
# Build the project by invoking shell script "build_my_app.sh". Keep in mind that when the script is invoked,
|
||||
# current working directory is <em>[cruise data]</em>/projects/your_project/work, so if you do not keep build_my_app.sh
|
||||
# in version control, it should be '../build_my_app.sh' instead
|
||||
#project.build_command = 'cp ../saucelabs.yml .'
|
||||
|
||||
# Ping Subversion for new revisions every 5 minutes (default: 30 seconds)
|
||||
# project.scheduler.polling_interval = 5.minutes
|
||||
|
||||
end
|
||||
BIN
dist/jasmine-standalone-2.0.0-alpha.zip
vendored
Normal file
BIN
dist/jasmine-standalone-2.0.0-rc2.zip
vendored
Normal file
@@ -1,27 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Jasmine Test Runner</title>
|
||||
<link rel="stylesheet" type="text/css" href="lib/jasmine-##JASMINE_VERSION##/jasmine.css">
|
||||
<script type="text/javascript" src="lib/jasmine-##JASMINE_VERSION##/jasmine.js"></script>
|
||||
<script type="text/javascript" src="lib/jasmine-##JASMINE_VERSION##/jasmine-html.js"></script>
|
||||
|
||||
<!-- include source files here... -->
|
||||
<script type="text/javascript" src="src/Player.js"></script>
|
||||
<script type="text/javascript" src="src/Song.js"></script>
|
||||
|
||||
<!-- include spec files here... -->
|
||||
<script type="text/javascript" src="spec/SpecHelper.js"></script>
|
||||
<script type="text/javascript" src="spec/PlayerSpec.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="REMOVE_THIS_LINE_FROM_BUILD"><p>You must be trying to look at examples in the Jasmine source tree.</p><p>Please download a distribution version of Jasmine at <a href="http://pivotal.github.com/jasmine/">http://pivotal.github.com/jasmine/</a>.</p></div>
|
||||
<script type="text/javascript">
|
||||
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
|
||||
jasmine.getEnv().execute();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,9 +0,0 @@
|
||||
beforeEach(function() {
|
||||
this.addMatchers({
|
||||
toBePlaying: function(expectedSong) {
|
||||
var player = this.actual;
|
||||
return player.currentlyPlayingSong === expectedSong
|
||||
&& player.isPlaying;
|
||||
}
|
||||
})
|
||||
});
|
||||
10
grunt/config/compass.js
Normal file
@@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
jasmine: {
|
||||
options: {
|
||||
cssDir: 'src/html',
|
||||
sassDir: 'src/html',
|
||||
outputStyle: 'compact',
|
||||
lineComments: false
|
||||
}
|
||||
}
|
||||
};
|
||||
57
grunt/config/compress.js
Normal file
@@ -0,0 +1,57 @@
|
||||
var standaloneLibDir = "lib/jasmine-" + jasmineVersion;
|
||||
|
||||
function root(path) { return "./" + path; }
|
||||
function lib(path) { return root("lib/jasmine-core/" + path); }
|
||||
function dist(path) { return root("dist/" + path); }
|
||||
|
||||
module.exports = {
|
||||
standalone: {
|
||||
options: {
|
||||
archive: root("dist/jasmine-standalone-" + global.jasmineVersion + ".zip")
|
||||
},
|
||||
|
||||
files: [
|
||||
{ src: [ root("MIT.LICENSE") ] },
|
||||
{
|
||||
src: [ "jasmine_favicon.png"],
|
||||
dest: standaloneLibDir,
|
||||
expand: true,
|
||||
cwd: root("images")
|
||||
},
|
||||
{
|
||||
src: [
|
||||
"jasmine.js",
|
||||
"jasmine-html.js",
|
||||
"jasmine.css"
|
||||
],
|
||||
dest: standaloneLibDir,
|
||||
expand: true,
|
||||
cwd: lib("")
|
||||
},
|
||||
{
|
||||
src: [ "boot.js" ],
|
||||
dest: standaloneLibDir,
|
||||
expand: true,
|
||||
cwd: lib("boot")
|
||||
},
|
||||
{
|
||||
src: [ "SpecRunner.html" ],
|
||||
dest: root(""),
|
||||
expand: true,
|
||||
cwd: dist("tmp")
|
||||
},
|
||||
{
|
||||
src: [ "*.js" ],
|
||||
dest: "src",
|
||||
expand: true,
|
||||
cwd: lib("example/src/")
|
||||
},
|
||||
{
|
||||
src: [ "*.js" ],
|
||||
dest: "spec",
|
||||
expand: true,
|
||||
cwd: lib("example/spec/")
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
57
grunt/config/concat.js
Normal file
@@ -0,0 +1,57 @@
|
||||
var grunt = require('grunt');
|
||||
|
||||
function license() {
|
||||
var currentYear = "" + new Date(Date.now()).getFullYear();
|
||||
|
||||
return grunt.template.process(
|
||||
grunt.file.read("grunt/templates/licenseBanner.js.jst"),
|
||||
{ data: { currentYear: currentYear}});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
'jasmine-html': {
|
||||
src: [
|
||||
'src/html/requireHtml.js',
|
||||
'src/html/HtmlReporter.js',
|
||||
'src/html/HtmlSpecFilter.js',
|
||||
'src/html/ResultsNode.js',
|
||||
'src/html/QueryString.js'
|
||||
],
|
||||
dest: 'lib/jasmine-core/jasmine-html.js'
|
||||
},
|
||||
jasmine: {
|
||||
src: [
|
||||
'src/core/requireCore.js',
|
||||
'src/core/matchers/requireMatchers.js',
|
||||
'src/core/base.js',
|
||||
'src/core/util.js',
|
||||
'src/core/Spec.js',
|
||||
'src/core/Env.js',
|
||||
'src/core/JsApiReporter.js',
|
||||
'src/core/PrettyPrinter',
|
||||
'src/core/Suite',
|
||||
'src/core/**/*.js',
|
||||
'src/version.js'
|
||||
],
|
||||
dest: 'lib/jasmine-core/jasmine.js'
|
||||
},
|
||||
boot: {
|
||||
src: ['lib/jasmine-core/boot/boot.js'],
|
||||
dest: 'lib/jasmine-core/boot.js'
|
||||
},
|
||||
console: {
|
||||
src: [
|
||||
'src/console/requireConsole.js',
|
||||
'src/console/ConsoleReporter.js'
|
||||
],
|
||||
dest: 'src/console/console.js'
|
||||
},
|
||||
options: {
|
||||
banner: license(),
|
||||
process: {
|
||||
data: {
|
||||
version: global.jasmineVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
17
grunt/config/jshint.js
Normal file
@@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
beforeConcat: ['src/**/*.js'],
|
||||
afterConcat: [
|
||||
'lib/jasmine-core/jasmine-html.js',
|
||||
'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
|
||||
},
|
||||
all: ['src/**/*.js']
|
||||
};
|
||||
30
grunt/tasks/build_standalone.js
Normal file
@@ -0,0 +1,30 @@
|
||||
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() {
|
||||
var runnerHtml = grunt.template.process(
|
||||
grunt.file.read("grunt/templates/SpecRunner.html.jst"),
|
||||
{ data: { jasmineVersion: global.jasmineVersion }});
|
||||
|
||||
grunt.file.write(standaloneTmpDir("SpecRunner.html"), runnerHtml);
|
||||
}
|
||||
);
|
||||
|
||||
grunt.registerTask("build:cleanSpecRunner",
|
||||
"Deletes the tmp spec runner file",
|
||||
function() {
|
||||
grunt.file.delete(standaloneTmpDir(""));
|
||||
}
|
||||
);
|
||||
|
||||
grunt.registerTask("buildStandaloneDist",
|
||||
"Builds a standalone distribution",
|
||||
[
|
||||
"build:compileSpecRunner",
|
||||
"compress:standalone",
|
||||
"build:cleanSpecRunner"
|
||||
]
|
||||
);
|
||||
11
grunt/tasks/spec.js
Normal file
@@ -0,0 +1,11 @@
|
||||
var shell = require('shelljs');
|
||||
var grunt = require('grunt');
|
||||
|
||||
module.exports = {
|
||||
execSpecsInNode: function() {
|
||||
var exit_code = shell.exec("node spec/node_suite.js --color=true").code;
|
||||
if (exit_code !== 0) {
|
||||
grunt.fail.fatal("Specs Failed", exit_code);
|
||||
}
|
||||
}
|
||||
};
|
||||
14
grunt/tasks/version.js
Normal file
@@ -0,0 +1,14 @@
|
||||
var grunt = require("grunt");
|
||||
|
||||
function gemLib(path) { return './lib/jasmine-core/' + path; }
|
||||
function nodeToRuby(version) { return version.replace('-', '.'); }
|
||||
|
||||
module.exports = {
|
||||
copyToGem: function() {
|
||||
var versionRb = grunt.template.process(
|
||||
grunt.file.read("grunt/templates/version.rb.jst"),
|
||||
{ data: { jasmineVersion: nodeToRuby(global.jasmineVersion) }});
|
||||
|
||||
grunt.file.write(gemLib("version.rb"), versionRb);
|
||||
}
|
||||
};
|
||||
26
grunt/templates/SpecRunner.html.jst
Normal file
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Jasmine Spec Runner v<%= jasmineVersion %></title>
|
||||
|
||||
<link rel="shortcut icon" type="image/png" href="lib/jasmine-<%= jasmineVersion %>/jasmine_favicon.png">
|
||||
<link rel="stylesheet" type="text/css" href="lib/jasmine-<%= jasmineVersion %>/jasmine.css">
|
||||
|
||||
<script type="text/javascript" src="lib/jasmine-<%= jasmineVersion %>/jasmine.js"></script>
|
||||
<script type="text/javascript" src="lib/jasmine-<%= jasmineVersion %>/jasmine-html.js"></script>
|
||||
<script type="text/javascript" src="lib/jasmine-<%= jasmineVersion %>/boot.js"></script>
|
||||
|
||||
<!-- include source files here... -->
|
||||
<script type="text/javascript" src="src/Player.js"></script>
|
||||
<script type="text/javascript" src="src/Song.js"></script>
|
||||
|
||||
<!-- include spec files here... -->
|
||||
<script type="text/javascript" src="spec/SpecHelper.js"></script>
|
||||
<script type="text/javascript" src="spec/PlayerSpec.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
22
grunt/templates/licenseBanner.js.jst
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright (c) 2008-<%= currentYear %> Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
9
grunt/templates/version.rb.jst
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# DO NOT Edit this file. Canonical version of Jasmine lives in the repo's package.json. This file is generated
|
||||
# by a grunt task when the standalone release is built.
|
||||
#
|
||||
module Jasmine
|
||||
module Core
|
||||
VERSION = "<%= jasmineVersion %>"
|
||||
end
|
||||
end
|
||||
|
Before Width: | Height: | Size: 722 B |
BIN
images/fail.png
|
Before Width: | Height: | Size: 2.1 KiB |
BIN
images/go-16.png
|
Before Width: | Height: | Size: 759 B |
BIN
images/go.png
|
Before Width: | Height: | Size: 2.2 KiB |
BIN
images/jasmine_favicon.png
Normal file
|
After Width: | Height: | Size: 905 B |
|
Before Width: | Height: | Size: 802 B |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 768 B |
|
Before Width: | Height: | Size: 1.7 KiB |
27
jasmine-core.gemspec
Normal file
@@ -0,0 +1,27 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
$:.push File.expand_path("../lib", __FILE__)
|
||||
require "jasmine-core/version"
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = "jasmine-core"
|
||||
s.version = Jasmine::Core::VERSION
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.authors = ["Rajan Agaskar", "Davis W. Frank", "Christian Williams"]
|
||||
s.summary = %q{JavaScript BDD framework}
|
||||
s.description = %q{Test your JavaScript without any framework dependencies, in any environment, and with a nice descriptive syntax.}
|
||||
s.email = %q{jasmine-js@googlegroups.com}
|
||||
s.homepage = "http://pivotal.github.com/jasmine"
|
||||
s.rubyforge_project = "jasmine-core"
|
||||
s.license = "MIT"
|
||||
|
||||
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 "sauce-connect"
|
||||
end
|
||||
49
lib/jasmine-core.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
module Jasmine
|
||||
module Core
|
||||
class << self
|
||||
def path
|
||||
File.join(File.dirname(__FILE__), "jasmine-core")
|
||||
end
|
||||
|
||||
def js_files
|
||||
(["jasmine.js"] + Dir.glob(File.join(path, "*.js"))).map { |f| File.basename(f) }.uniq - boot_files
|
||||
end
|
||||
|
||||
SPEC_TYPES = ["core", "html", "node"]
|
||||
|
||||
def core_spec_files
|
||||
spec_files("core")
|
||||
end
|
||||
|
||||
def html_spec_files
|
||||
spec_files("html")
|
||||
end
|
||||
|
||||
def node_spec_files
|
||||
spec_files("node")
|
||||
end
|
||||
|
||||
def boot_files
|
||||
["boot.js"]
|
||||
end
|
||||
|
||||
def boot_dir
|
||||
File.join(path, 'boot')
|
||||
end
|
||||
|
||||
def spec_files(type)
|
||||
raise ArgumentError.new("Unrecognized spec type") unless SPEC_TYPES.include?(type)
|
||||
(Dir.glob(File.join(path, "spec", type, "*.js"))).map { |f| File.join("spec", type, File.basename(f)) }.uniq
|
||||
end
|
||||
|
||||
def css_files
|
||||
Dir.glob(File.join(path, "*.css")).map { |f| File.basename(f) }
|
||||
end
|
||||
|
||||
def images_dir
|
||||
File.join(File.dirname(__FILE__), '../images')
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
131
lib/jasmine-core/boot.js
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
Copyright (c) 2008-2013 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
// Jasmine boot.js for browser runners - exposes external/global interface, builds the Jasmine environment and executes it.
|
||||
(function() {
|
||||
window.jasmine = jasmineRequire.core(jasmineRequire);
|
||||
jasmineRequire.html(jasmine);
|
||||
|
||||
var env = jasmine.getEnv();
|
||||
|
||||
var jasmineInterface = {
|
||||
describe: function(description, specDefinitions) {
|
||||
return env.describe(description, specDefinitions);
|
||||
},
|
||||
|
||||
xdescribe: function(description, specDefinitions) {
|
||||
return env.xdescribe(description, specDefinitions);
|
||||
},
|
||||
|
||||
it: function(desc, func) {
|
||||
return env.it(desc, func);
|
||||
},
|
||||
|
||||
xit: function(desc, func) {
|
||||
return env.xit(desc, func);
|
||||
},
|
||||
|
||||
beforeEach: function(beforeEachFunction) {
|
||||
return env.beforeEach(beforeEachFunction);
|
||||
},
|
||||
|
||||
afterEach: function(afterEachFunction) {
|
||||
return env.afterEach(afterEachFunction);
|
||||
},
|
||||
|
||||
expect: function(actual) {
|
||||
return env.expect(actual);
|
||||
},
|
||||
|
||||
pending: function() {
|
||||
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()
|
||||
})
|
||||
};
|
||||
|
||||
if (typeof window == "undefined" && typeof exports == "object") {
|
||||
extend(exports, jasmineInterface);
|
||||
} else {
|
||||
extend(window, jasmineInterface);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
|
||||
timer: new jasmine.Timer()
|
||||
});
|
||||
|
||||
env.addReporter(jasmineInterface.jsApiReporter);
|
||||
env.addReporter(htmlReporter);
|
||||
|
||||
var specFilter = new jasmine.HtmlSpecFilter({
|
||||
filterString: function() { return queryString.getParam("spec"); }
|
||||
});
|
||||
|
||||
env.specFilter = function(spec) {
|
||||
return specFilter.matches(spec.getFullName());
|
||||
};
|
||||
|
||||
var currentWindowOnload = window.onload;
|
||||
|
||||
window.onload = function() {
|
||||
if (currentWindowOnload) {
|
||||
currentWindowOnload();
|
||||
}
|
||||
htmlReporter.initialize();
|
||||
env.execute();
|
||||
};
|
||||
|
||||
function extend(destination, source) {
|
||||
for (var property in source) destination[property] = source[property];
|
||||
return destination;
|
||||
}
|
||||
|
||||
}());
|
||||
109
lib/jasmine-core/boot/boot.js
Normal file
@@ -0,0 +1,109 @@
|
||||
// Jasmine boot.js for browser runners - exposes external/global interface, builds the Jasmine environment and executes it.
|
||||
(function() {
|
||||
window.jasmine = jasmineRequire.core(jasmineRequire);
|
||||
jasmineRequire.html(jasmine);
|
||||
|
||||
var env = jasmine.getEnv();
|
||||
|
||||
var jasmineInterface = {
|
||||
describe: function(description, specDefinitions) {
|
||||
return env.describe(description, specDefinitions);
|
||||
},
|
||||
|
||||
xdescribe: function(description, specDefinitions) {
|
||||
return env.xdescribe(description, specDefinitions);
|
||||
},
|
||||
|
||||
it: function(desc, func) {
|
||||
return env.it(desc, func);
|
||||
},
|
||||
|
||||
xit: function(desc, func) {
|
||||
return env.xit(desc, func);
|
||||
},
|
||||
|
||||
beforeEach: function(beforeEachFunction) {
|
||||
return env.beforeEach(beforeEachFunction);
|
||||
},
|
||||
|
||||
afterEach: function(afterEachFunction) {
|
||||
return env.afterEach(afterEachFunction);
|
||||
},
|
||||
|
||||
expect: function(actual) {
|
||||
return env.expect(actual);
|
||||
},
|
||||
|
||||
pending: function() {
|
||||
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()
|
||||
})
|
||||
};
|
||||
|
||||
if (typeof window == "undefined" && typeof exports == "object") {
|
||||
extend(exports, jasmineInterface);
|
||||
} else {
|
||||
extend(window, jasmineInterface);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
|
||||
timer: new jasmine.Timer()
|
||||
});
|
||||
|
||||
env.addReporter(jasmineInterface.jsApiReporter);
|
||||
env.addReporter(htmlReporter);
|
||||
|
||||
var specFilter = new jasmine.HtmlSpecFilter({
|
||||
filterString: function() { return queryString.getParam("spec"); }
|
||||
});
|
||||
|
||||
env.specFilter = function(spec) {
|
||||
return specFilter.matches(spec.getFullName());
|
||||
};
|
||||
|
||||
var currentWindowOnload = window.onload;
|
||||
|
||||
window.onload = function() {
|
||||
if (currentWindowOnload) {
|
||||
currentWindowOnload();
|
||||
}
|
||||
htmlReporter.initialize();
|
||||
env.execute();
|
||||
};
|
||||
|
||||
function extend(destination, source) {
|
||||
for (var property in source) destination[property] = source[property];
|
||||
return destination;
|
||||
}
|
||||
|
||||
}());
|
||||
@@ -52,7 +52,7 @@ describe("Player", function() {
|
||||
|
||||
expect(function() {
|
||||
player.resume();
|
||||
}).toThrow("song is already playing");
|
||||
}).toThrowError("song is already playing");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
15
lib/jasmine-core/example/spec/SpecHelper.js
Normal file
@@ -0,0 +1,15 @@
|
||||
beforeEach(function () {
|
||||
jasmine.Expectation.addMatchers({
|
||||
toBePlaying: function () {
|
||||
return {
|
||||
compare: function (actual, expected) {
|
||||
var player = actual;
|
||||
|
||||
return {
|
||||
pass: player.currentlyPlayingSong === expected && player.isPlaying
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
354
lib/jasmine-core/jasmine-html.js
Normal file
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
Copyright (c) 2008-2013 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
jasmineRequire.html = function(j$) {
|
||||
j$.ResultsNode = jasmineRequire.ResultsNode();
|
||||
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
|
||||
j$.QueryString = jasmineRequire.QueryString();
|
||||
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
|
||||
};
|
||||
jasmineRequire.HtmlReporter = function(j$) {
|
||||
|
||||
var noopTimer = {
|
||||
start: function(){},
|
||||
elapsed: function(){ return 0; }
|
||||
};
|
||||
|
||||
function HtmlReporter(options) {
|
||||
var env = options.env || {},
|
||||
getContainer = options.getContainer,
|
||||
createElement = options.createElement,
|
||||
createTextNode = options.createTextNode,
|
||||
onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
|
||||
timer = options.timer || noopTimer,
|
||||
results = [],
|
||||
specsExecuted = 0,
|
||||
failureCount = 0,
|
||||
pendingSpecCount = 0,
|
||||
htmlReporterMain,
|
||||
symbols;
|
||||
|
||||
this.initialize = function() {
|
||||
htmlReporterMain = createDom("div", {className: "html-reporter"},
|
||||
createDom("div", {className: "banner"},
|
||||
createDom("span", {className: "title"}, "Jasmine"),
|
||||
createDom("span", {className: "version"}, j$.version)
|
||||
),
|
||||
createDom("ul", {className: "symbol-summary"}),
|
||||
createDom("div", {className: "alert"}),
|
||||
createDom("div", {className: "results"},
|
||||
createDom("div", {className: "failures"})
|
||||
)
|
||||
);
|
||||
getContainer().appendChild(htmlReporterMain);
|
||||
|
||||
symbols = find(".symbol-summary");
|
||||
};
|
||||
|
||||
var totalSpecsDefined;
|
||||
this.jasmineStarted = function(options) {
|
||||
totalSpecsDefined = options.totalSpecsDefined || 0;
|
||||
timer.start();
|
||||
};
|
||||
|
||||
var summary = createDom("div", {className: "summary"});
|
||||
|
||||
var topResults = new j$.ResultsNode({}, "", null),
|
||||
currentParent = topResults;
|
||||
|
||||
this.suiteStarted = function(result) {
|
||||
currentParent.addChild(result, "suite");
|
||||
currentParent = currentParent.last();
|
||||
};
|
||||
|
||||
this.suiteDone = function(result) {
|
||||
if (currentParent == topResults) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentParent = currentParent.parent;
|
||||
};
|
||||
|
||||
this.specStarted = function(result) {
|
||||
currentParent.addChild(result, "spec");
|
||||
};
|
||||
|
||||
var failures = [];
|
||||
this.specDone = function(result) {
|
||||
if (result.status != "disabled") {
|
||||
specsExecuted++;
|
||||
}
|
||||
|
||||
symbols.appendChild(createDom("li", {
|
||||
className: result.status,
|
||||
id: "spec_" + result.id,
|
||||
title: result.fullName}
|
||||
));
|
||||
|
||||
if (result.status == "failed") {
|
||||
failureCount++;
|
||||
|
||||
var failure =
|
||||
createDom("div", {className: "spec-detail failed"},
|
||||
createDom("a", {className: "description", title: result.fullName, href: specHref(result)}, result.fullName),
|
||||
createDom("div", {className: "messages"})
|
||||
);
|
||||
var messages = failure.childNodes[1];
|
||||
|
||||
for (var i = 0; i < result.failedExpectations.length; i++) {
|
||||
var expectation = result.failedExpectations[i];
|
||||
messages.appendChild(createDom("div", {className: "result-message"}, expectation.message));
|
||||
messages.appendChild(createDom("div", {className: "stack-trace"}, expectation.stack));
|
||||
}
|
||||
|
||||
failures.push(failure);
|
||||
}
|
||||
|
||||
if (result.status == "pending") {
|
||||
pendingSpecCount++;
|
||||
}
|
||||
};
|
||||
|
||||
this.jasmineDone = function() {
|
||||
var banner = find(".banner");
|
||||
banner.appendChild(createDom("span", {className: "duration"}, "finished in " + timer.elapsed() / 1000 + "s"));
|
||||
|
||||
var alert = find(".alert");
|
||||
|
||||
alert.appendChild(createDom("span", { className: "exceptions" },
|
||||
createDom("label", { className: "label", 'for': "raise-exceptions" }, "raise exceptions"),
|
||||
createDom("input", {
|
||||
className: "raise",
|
||||
id: "raise-exceptions",
|
||||
type: "checkbox"
|
||||
})
|
||||
));
|
||||
var checkbox = find("input");
|
||||
|
||||
checkbox.checked = !env.catchingExceptions();
|
||||
checkbox.onclick = onRaiseExceptionsClick;
|
||||
|
||||
if (specsExecuted < totalSpecsDefined) {
|
||||
var skippedMessage = "Ran " + specsExecuted + " of " + totalSpecsDefined + " specs - run all";
|
||||
alert.appendChild(
|
||||
createDom("span", {className: "bar skipped"},
|
||||
createDom("a", {href: "?", title: "Run all specs"}, skippedMessage)
|
||||
)
|
||||
);
|
||||
}
|
||||
var statusBarMessage = "" + pluralize("spec", specsExecuted) + ", " + pluralize("failure", failureCount);
|
||||
if (pendingSpecCount) { statusBarMessage += ", " + pluralize("pending spec", pendingSpecCount); }
|
||||
|
||||
var statusBarClassName = "bar " + ((failureCount > 0) ? "failed" : "passed");
|
||||
alert.appendChild(createDom("span", {className: statusBarClassName}, statusBarMessage));
|
||||
|
||||
var results = find(".results");
|
||||
results.appendChild(summary);
|
||||
|
||||
summaryList(topResults, summary);
|
||||
|
||||
function summaryList(resultsTree, domParent) {
|
||||
var specListNode;
|
||||
for (var i = 0; i < resultsTree.children.length; i++) {
|
||||
var resultNode = resultsTree.children[i];
|
||||
if (resultNode.type == "suite") {
|
||||
var suiteListNode = createDom("ul", {className: "suite", id: "suite-" + resultNode.result.id},
|
||||
createDom("li", {className: "suite-detail"},
|
||||
createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description)
|
||||
)
|
||||
);
|
||||
|
||||
summaryList(resultNode, suiteListNode);
|
||||
domParent.appendChild(suiteListNode);
|
||||
}
|
||||
if (resultNode.type == "spec") {
|
||||
if (domParent.getAttribute("class") != "specs") {
|
||||
specListNode = createDom("ul", {className: "specs"});
|
||||
domParent.appendChild(specListNode);
|
||||
}
|
||||
specListNode.appendChild(
|
||||
createDom("li", {
|
||||
className: resultNode.result.status,
|
||||
id: "spec-" + resultNode.result.id
|
||||
},
|
||||
createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (failures.length) {
|
||||
alert.appendChild(
|
||||
createDom('span', {className: "menu bar spec-list"},
|
||||
createDom("span", {}, "Spec List | "),
|
||||
createDom('a', {className: "failures-menu", href: "#"}, "Failures")));
|
||||
alert.appendChild(
|
||||
createDom('span', {className: "menu bar failure-list"},
|
||||
createDom('a', {className: "spec-list-menu", href: "#"}, "Spec List"),
|
||||
createDom("span", {}, " | Failures ")));
|
||||
|
||||
find(".failures-menu").onclick = function() {
|
||||
setMenuModeTo('failure-list');
|
||||
};
|
||||
find(".spec-list-menu").onclick = function() {
|
||||
setMenuModeTo('spec-list');
|
||||
};
|
||||
|
||||
setMenuModeTo('failure-list');
|
||||
|
||||
var failureNode = find(".failures");
|
||||
for (var i = 0; i < failures.length; i++) {
|
||||
failureNode.appendChild(failures[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return this;
|
||||
|
||||
function find(selector) {
|
||||
return getContainer().querySelector(selector);
|
||||
}
|
||||
|
||||
function createDom(type, attrs, childrenVarArgs) {
|
||||
var el = createElement(type);
|
||||
|
||||
for (var i = 2; i < arguments.length; i++) {
|
||||
var child = arguments[i];
|
||||
|
||||
if (typeof child === 'string') {
|
||||
el.appendChild(createTextNode(child));
|
||||
} else {
|
||||
if (child) {
|
||||
el.appendChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var attr in attrs) {
|
||||
if (attr == "className") {
|
||||
el[attr] = attrs[attr];
|
||||
} else {
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
function pluralize(singular, count) {
|
||||
var word = (count == 1 ? singular : singular + "s");
|
||||
|
||||
return "" + count + " " + word;
|
||||
}
|
||||
|
||||
function specHref(result) {
|
||||
return "?spec=" + encodeURIComponent(result.fullName);
|
||||
}
|
||||
|
||||
function setMenuModeTo(mode) {
|
||||
htmlReporterMain.setAttribute("class", "html-reporter " + mode);
|
||||
}
|
||||
}
|
||||
|
||||
return HtmlReporter;
|
||||
};
|
||||
|
||||
jasmineRequire.HtmlSpecFilter = function() {
|
||||
function HtmlSpecFilter(options) {
|
||||
var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
var filterPattern = new RegExp(filterString);
|
||||
|
||||
this.matches = function(specName) {
|
||||
return filterPattern.test(specName);
|
||||
};
|
||||
}
|
||||
|
||||
return HtmlSpecFilter;
|
||||
};
|
||||
|
||||
jasmineRequire.ResultsNode = function() {
|
||||
function ResultsNode(result, type, parent) {
|
||||
this.result = result;
|
||||
this.type = type;
|
||||
this.parent = parent;
|
||||
|
||||
this.children = [];
|
||||
|
||||
this.addChild = function(result, type) {
|
||||
this.children.push(new ResultsNode(result, type, this));
|
||||
};
|
||||
|
||||
this.last = function() {
|
||||
return this.children[this.children.length - 1];
|
||||
};
|
||||
}
|
||||
|
||||
return ResultsNode;
|
||||
};
|
||||
jasmineRequire.QueryString = function() {
|
||||
function QueryString(options) {
|
||||
|
||||
this.setParam = function(key, value) {
|
||||
var paramMap = queryStringToParamMap();
|
||||
paramMap[key] = value;
|
||||
options.getWindowLocation().search = toQueryString(paramMap);
|
||||
};
|
||||
|
||||
this.getParam = function(key) {
|
||||
return queryStringToParamMap()[key];
|
||||
};
|
||||
|
||||
return this;
|
||||
|
||||
function toQueryString(paramMap) {
|
||||
var qStrPairs = [];
|
||||
for (var prop in paramMap) {
|
||||
qStrPairs.push(encodeURIComponent(prop) + "=" + encodeURIComponent(paramMap[prop]));
|
||||
}
|
||||
return "?" + qStrPairs.join('&');
|
||||
}
|
||||
|
||||
function queryStringToParamMap() {
|
||||
var paramStr = options.getWindowLocation().search.substring(1),
|
||||
params = [],
|
||||
paramMap = {};
|
||||
|
||||
if (paramStr.length > 0) {
|
||||
params = paramStr.split('&');
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var p = params[i].split('=');
|
||||
var value = decodeURIComponent(p[1]);
|
||||
if (value === "true" || value === "false") {
|
||||
value = JSON.parse(value);
|
||||
}
|
||||
paramMap[decodeURIComponent(p[0])] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return QueryString;
|
||||
};
|
||||
54
lib/jasmine-core/jasmine.css
Normal file
@@ -0,0 +1,54 @@
|
||||
body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
|
||||
|
||||
.html-reporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
|
||||
.html-reporter a { text-decoration: none; }
|
||||
.html-reporter a:hover { text-decoration: underline; }
|
||||
.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; }
|
||||
.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; }
|
||||
.html-reporter .banner .version { margin-left: 14px; }
|
||||
.html-reporter #jasmine_content { position: fixed; right: 100%; }
|
||||
.html-reporter .version { color: #aaaaaa; }
|
||||
.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.passed { font-size: 14px; }
|
||||
.html-reporter .symbol-summary li.passed:before { color: #5e7d00; content: "\02022"; }
|
||||
.html-reporter .symbol-summary li.failed { line-height: 9px; }
|
||||
.html-reporter .symbol-summary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
|
||||
.html-reporter .symbol-summary li.disabled { font-size: 14px; }
|
||||
.html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; }
|
||||
.html-reporter .symbol-summary li.pending { line-height: 17px; }
|
||||
.html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; }
|
||||
.html-reporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
|
||||
.html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
|
||||
.html-reporter .bar.failed { background-color: #b03911; }
|
||||
.html-reporter .bar.passed { background-color: #a6b779; }
|
||||
.html-reporter .bar.skipped { background-color: #bababa; }
|
||||
.html-reporter .bar.menu { background-color: #fff; color: #aaaaaa; }
|
||||
.html-reporter .bar.menu a { color: #333333; }
|
||||
.html-reporter .bar a { color: white; }
|
||||
.html-reporter.spec-list .bar.menu.failure-list, .html-reporter.spec-list .results .failures { display: none; }
|
||||
.html-reporter.failure-list .bar.menu.spec-list, .html-reporter.failure-list .summary { display: none; }
|
||||
.html-reporter .running-alert { background-color: #666666; }
|
||||
.html-reporter .results { margin-top: 14px; }
|
||||
.html-reporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
|
||||
.html-reporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
|
||||
.html-reporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
|
||||
.html-reporter.showDetails .summary { display: none; }
|
||||
.html-reporter.showDetails #details { display: block; }
|
||||
.html-reporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
|
||||
.html-reporter .summary { margin-top: 14px; }
|
||||
.html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; }
|
||||
.html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; }
|
||||
.html-reporter .summary li.passed a { color: #5e7d00; }
|
||||
.html-reporter .summary li.failed a { color: #b03911; }
|
||||
.html-reporter .summary li.pending a { color: #ba9d37; }
|
||||
.html-reporter .description + .suite { margin-top: 0; }
|
||||
.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 .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; }
|
||||
2361
lib/jasmine-core/jasmine.js
Normal file
1
lib/jasmine-core/spec
Symbolic link
@@ -0,0 +1 @@
|
||||
../../spec
|
||||
9
lib/jasmine-core/version.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# DO NOT Edit this file. Canonical version of Jasmine lives in the repo's package.json. This file is generated
|
||||
# by a grunt task when the standalone release is built.
|
||||
#
|
||||
module Jasmine
|
||||
module Core
|
||||
VERSION = "2.0.0.rc2"
|
||||
end
|
||||
end
|
||||
@@ -1,182 +0,0 @@
|
||||
jasmine.TrivialReporter = function(doc) {
|
||||
this.document = doc || document;
|
||||
this.suiteDivs = {};
|
||||
this.logRunningSpecs = false;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
|
||||
var el = document.createElement(type);
|
||||
|
||||
for (var i = 2; i < arguments.length; i++) {
|
||||
var child = arguments[i];
|
||||
|
||||
if (typeof child === 'string') {
|
||||
el.appendChild(document.createTextNode(child));
|
||||
} else {
|
||||
if (child) { el.appendChild(child); }
|
||||
}
|
||||
}
|
||||
|
||||
for (var attr in attrs) {
|
||||
if (attr == "className") {
|
||||
el[attr] = attrs[attr];
|
||||
} else {
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
||||
var showPassed, showSkipped;
|
||||
|
||||
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
|
||||
this.createDom('div', { className: 'banner' },
|
||||
this.createDom('div', { className: 'logo' },
|
||||
"Jasmine",
|
||||
this.createDom('span', { className: 'version' }, runner.env.versionString())),
|
||||
this.createDom('div', { className: 'options' },
|
||||
"Show ",
|
||||
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
|
||||
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
|
||||
)
|
||||
),
|
||||
|
||||
this.runnerDiv = this.createDom('div', { className: 'runner running' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
|
||||
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
|
||||
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
|
||||
);
|
||||
|
||||
this.document.body.appendChild(this.outerDiv);
|
||||
|
||||
var suites = runner.suites();
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
var suite = suites[i];
|
||||
var suiteDiv = this.createDom('div', { className: 'suite' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
|
||||
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
|
||||
this.suiteDivs[suite.id] = suiteDiv;
|
||||
var parentDiv = this.outerDiv;
|
||||
if (suite.parentSuite) {
|
||||
parentDiv = this.suiteDivs[suite.parentSuite.id];
|
||||
}
|
||||
parentDiv.appendChild(suiteDiv);
|
||||
}
|
||||
|
||||
this.startedAt = new Date();
|
||||
|
||||
var self = this;
|
||||
showPassed.onchange = function(evt) {
|
||||
if (evt.target.checked) {
|
||||
self.outerDiv.className += ' show-passed';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
|
||||
}
|
||||
};
|
||||
|
||||
showSkipped.onchange = function(evt) {
|
||||
if (evt.target.checked) {
|
||||
self.outerDiv.className += ' show-skipped';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
|
||||
var results = runner.results();
|
||||
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
|
||||
this.runnerDiv.setAttribute("class", className);
|
||||
//do it twice for IE
|
||||
this.runnerDiv.setAttribute("className", className);
|
||||
var specs = runner.specs();
|
||||
var specCount = 0;
|
||||
for (var i = 0; i < specs.length; i++) {
|
||||
if (this.specFilter(specs[i])) {
|
||||
specCount++;
|
||||
}
|
||||
}
|
||||
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
|
||||
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
|
||||
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
|
||||
|
||||
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
|
||||
var results = suite.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.totalCount == 0) { // todo: change this to check results.skipped
|
||||
status = 'skipped';
|
||||
}
|
||||
this.suiteDivs[suite.id].className += " " + status;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
|
||||
if (this.logRunningSpecs) {
|
||||
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
|
||||
var results = spec.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.skipped) {
|
||||
status = 'skipped';
|
||||
}
|
||||
var specDiv = this.createDom('div', { className: 'spec ' + status },
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
|
||||
this.createDom('a', {
|
||||
className: 'description',
|
||||
href: '?spec=' + encodeURIComponent(spec.getFullName()),
|
||||
title: spec.getFullName()
|
||||
}, spec.description));
|
||||
|
||||
|
||||
var resultItems = results.getItems();
|
||||
var messagesDiv = this.createDom('div', { className: 'messages' });
|
||||
for (var i = 0; i < resultItems.length; i++) {
|
||||
var result = resultItems[i];
|
||||
|
||||
if (result.type == 'log') {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
||||
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
||||
|
||||
if (result.trace.stack) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messagesDiv.childNodes.length > 0) {
|
||||
specDiv.appendChild(messagesDiv);
|
||||
}
|
||||
|
||||
this.suiteDivs[spec.suite.id].appendChild(specDiv);
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.log = function() {
|
||||
var console = jasmine.getGlobal().console;
|
||||
if (console && console.log) console.log.apply(console, arguments);
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.getLocation = function() {
|
||||
return this.document.location;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
|
||||
var paramMap = {};
|
||||
var params = this.getLocation().search.substring(1).split('&');
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var p = params[i].split('=');
|
||||
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
||||
}
|
||||
|
||||
if (!paramMap["spec"]) return true;
|
||||
return spec.getFullName().indexOf(paramMap["spec"]) == 0;
|
||||
};
|
||||
166
lib/jasmine.css
@@ -1,166 +0,0 @@
|
||||
body {
|
||||
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
|
||||
}
|
||||
|
||||
|
||||
.jasmine_reporter a:visited, .jasmine_reporter a {
|
||||
color: #303;
|
||||
}
|
||||
|
||||
.jasmine_reporter a:hover, .jasmine_reporter a:active {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.run_spec {
|
||||
float:right;
|
||||
padding-right: 5px;
|
||||
font-size: .8em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.jasmine_reporter {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.banner {
|
||||
color: #303;
|
||||
background-color: #fef;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
float: left;
|
||||
font-size: 1.1em;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.logo .version {
|
||||
font-size: .6em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.runner.running {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
|
||||
.options {
|
||||
text-align: right;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.suite {
|
||||
border: 1px outset gray;
|
||||
margin: 5px 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.suite .suite {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.suite.passed {
|
||||
background-color: #dfd;
|
||||
}
|
||||
|
||||
.suite.failed {
|
||||
background-color: #fdd;
|
||||
}
|
||||
|
||||
.spec {
|
||||
margin: 5px;
|
||||
padding-left: 1em;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.spec.failed, .spec.passed, .spec.skipped {
|
||||
padding-bottom: 5px;
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.spec.failed {
|
||||
background-color: #fbb;
|
||||
border-color: red;
|
||||
}
|
||||
|
||||
.spec.passed {
|
||||
background-color: #bfb;
|
||||
border-color: green;
|
||||
}
|
||||
|
||||
.spec.skipped {
|
||||
background-color: #bbb;
|
||||
}
|
||||
|
||||
.messages {
|
||||
border-left: 1px dashed gray;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.passed {
|
||||
background-color: #cfc;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.failed {
|
||||
background-color: #fbb;
|
||||
}
|
||||
|
||||
.skipped {
|
||||
color: #777;
|
||||
background-color: #eee;
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*.resultMessage {*/
|
||||
/*white-space: pre;*/
|
||||
/*}*/
|
||||
|
||||
.resultMessage span.result {
|
||||
display: block;
|
||||
line-height: 2em;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.resultMessage .mismatch {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.stackTrace {
|
||||
white-space: pre;
|
||||
font-size: .8em;
|
||||
margin-left: 10px;
|
||||
max-height: 5em;
|
||||
overflow: auto;
|
||||
border: 1px inset red;
|
||||
padding: 1em;
|
||||
background: #eef;
|
||||
}
|
||||
|
||||
.finished-at {
|
||||
padding-left: 1em;
|
||||
font-size: .6em;
|
||||
}
|
||||
|
||||
.show-passed .passed,
|
||||
.show-skipped .skipped {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
#jasmine_content {
|
||||
position:fixed;
|
||||
right: 100%;
|
||||
}
|
||||
|
||||
.runner {
|
||||
border: 1px solid gray;
|
||||
display: block;
|
||||
margin: 5px 0;
|
||||
padding: 2px 0 2px 10px;
|
||||
}
|
||||
2421
lib/jasmine.js
13
package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "jasmine-core",
|
||||
"license": "MIT",
|
||||
"version": "2.0.0-rc2",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
1
pages
138
release_notes/20rc1.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# Jasmine Core 2.0 Release Notes
|
||||
|
||||
## Summary
|
||||
|
||||
These notes are for RC1 of Jasmine Core 2.0.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
These changes have breaking interface changes and 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
|
||||
|
||||
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`
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with [Anchorman](http://github.com/infews/anchorman)_
|
||||
|
||||
[mocha]: http://visionmedia.github.io/mocha/
|
||||
[underscore]: http://underscorejs.org/
|
||||
[grunt]: http://gruntjs.com
|
||||
[contrib]: https://github.com/pivotal/jasmine/blob/master/Contribute.markdown
|
||||
[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://pivotal.github.com/jasmine/
|
||||
226
spec/console/ConsoleReporterSpec.js
Normal file
@@ -0,0 +1,226 @@
|
||||
describe("ConsoleReporter", function() {
|
||||
var out;
|
||||
|
||||
beforeEach(function() {
|
||||
out = (function() {
|
||||
var output = "";
|
||||
return {
|
||||
print: function(str) {
|
||||
output += str;
|
||||
},
|
||||
getOutput: function() {
|
||||
return output;
|
||||
},
|
||||
clear: function() {
|
||||
output = "";
|
||||
}
|
||||
};
|
||||
}());
|
||||
});
|
||||
|
||||
it("reports that the suite has started to the console", function() {
|
||||
var reporter = new j$.ConsoleReporter({
|
||||
print: out.print
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
|
||||
expect(out.getOutput()).toEqual("Started\n");
|
||||
});
|
||||
|
||||
it("starts the provided timer when jasmine starts", function() {
|
||||
var timerSpy = jasmine.createSpyObj('timer', ['start']),
|
||||
reporter = new j$.ConsoleReporter({
|
||||
print: out.print,
|
||||
timer: timerSpy
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
|
||||
expect(timerSpy.start).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("reports a passing spec as a dot", function() {
|
||||
var reporter = new j$.ConsoleReporter({
|
||||
print: out.print
|
||||
});
|
||||
|
||||
reporter.specDone({status: "passed"});
|
||||
|
||||
expect(out.getOutput()).toEqual(".");
|
||||
});
|
||||
|
||||
it("does not report a disabled spec", function() {
|
||||
var reporter = new j$.ConsoleReporter({
|
||||
print: out.print
|
||||
});
|
||||
|
||||
reporter.specDone({status: "disabled"});
|
||||
|
||||
expect(out.getOutput()).toEqual("");
|
||||
});
|
||||
|
||||
it("reports a failing spec as an 'F'", function() {
|
||||
var reporter = new j$.ConsoleReporter({
|
||||
print: out.print
|
||||
});
|
||||
|
||||
reporter.specDone({status: "failed"});
|
||||
|
||||
expect(out.getOutput()).toEqual("F");
|
||||
});
|
||||
|
||||
it("reports a pending spec as a '*'", function() {
|
||||
var reporter = new j$.ConsoleReporter({
|
||||
print: out.print
|
||||
});
|
||||
|
||||
reporter.specDone({status: "pending"});
|
||||
|
||||
expect(out.getOutput()).toEqual("*");
|
||||
});
|
||||
|
||||
it("reports a summary when done (singluar spec and time)", function() {
|
||||
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
|
||||
reporter = new j$.ConsoleReporter({
|
||||
print: out.print,
|
||||
timer: timerSpy
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
reporter.specDone({status: "passed"});
|
||||
|
||||
timerSpy.elapsed.and.callReturn(1000);
|
||||
|
||||
out.clear();
|
||||
reporter.jasmineDone();
|
||||
|
||||
expect(out.getOutput()).toMatch(/1 spec, 0 failures/);
|
||||
expect(out.getOutput()).not.toMatch(/0 pending specs/);
|
||||
expect(out.getOutput()).toMatch("Finished in 1 second\n");
|
||||
});
|
||||
|
||||
it("reports a summary when done (pluralized specs and seconds)", function() {
|
||||
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
|
||||
reporter = new j$.ConsoleReporter({
|
||||
print: out.print,
|
||||
timer: timerSpy
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
reporter.specDone({status: "passed"});
|
||||
reporter.specDone({status: "pending"});
|
||||
reporter.specDone({
|
||||
status: "failed",
|
||||
description: "with a failing spec",
|
||||
fullName: "A suite with a failing spec",
|
||||
failedExpectations: [
|
||||
{
|
||||
passed: false,
|
||||
message: "Expected true to be false.",
|
||||
expected: false,
|
||||
actual: true,
|
||||
stack: "foo\nbar\nbaz"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
out.clear();
|
||||
|
||||
timerSpy.elapsed.and.callReturn(100);
|
||||
|
||||
reporter.jasmineDone();
|
||||
|
||||
expect(out.getOutput()).toMatch(/3 specs, 1 failure, 1 pending spec/);
|
||||
expect(out.getOutput()).toMatch("Finished in 0.1 seconds\n");
|
||||
});
|
||||
|
||||
it("reports a summary when done that includes stack traces for a failing suite", function() {
|
||||
var reporter = new j$.ConsoleReporter({
|
||||
print: out.print
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
reporter.specDone({status: "passed"});
|
||||
reporter.specDone({
|
||||
status: "failed",
|
||||
description: "with a failing spec",
|
||||
fullName: "A suite with a failing spec",
|
||||
failedExpectations: [
|
||||
{
|
||||
passed: false,
|
||||
message: "Expected true to be false.",
|
||||
expected: false,
|
||||
actual: true,
|
||||
stack: "foo bar baz"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
out.clear();
|
||||
|
||||
reporter.jasmineDone({});
|
||||
|
||||
expect(out.getOutput()).toMatch(/foo bar baz/);
|
||||
});
|
||||
|
||||
it("calls the onComplete callback when the suite is done", function() {
|
||||
var onComplete = jasmine.createSpy('onComplete'),
|
||||
reporter = new j$.ConsoleReporter({
|
||||
print: out.print,
|
||||
onComplete: onComplete
|
||||
});
|
||||
|
||||
reporter.jasmineDone({});
|
||||
|
||||
expect(onComplete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
describe("with color", function() {
|
||||
|
||||
it("reports that the suite has started to the console", function() {
|
||||
var reporter = new j$.ConsoleReporter({
|
||||
print: out.print,
|
||||
showColors: true
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
|
||||
expect(out.getOutput()).toEqual("Started\n");
|
||||
});
|
||||
|
||||
it("reports a passing spec as a dot", function() {
|
||||
var reporter = new j$.ConsoleReporter({
|
||||
print: out.print,
|
||||
showColors: true
|
||||
});
|
||||
|
||||
reporter.specDone({status: "passed"});
|
||||
|
||||
expect(out.getOutput()).toEqual("\033[32m.\033[0m");
|
||||
});
|
||||
|
||||
it("does not report a disabled spec", function() {
|
||||
var reporter = new j$.ConsoleReporter({
|
||||
print: out.print,
|
||||
showColors: true
|
||||
});
|
||||
|
||||
reporter.specDone({status: 'disabled'});
|
||||
|
||||
expect(out.getOutput()).toEqual("");
|
||||
});
|
||||
|
||||
it("reports a failing spec as an 'F'", function() {
|
||||
var reporter = new j$.ConsoleReporter({
|
||||
print: out.print,
|
||||
showColors: true
|
||||
});
|
||||
|
||||
reporter.specDone({status: 'failed'});
|
||||
|
||||
expect(out.getOutput()).toEqual("\033[31mF\033[0m");
|
||||
});
|
||||
});
|
||||
});
|
||||
45
spec/core/AnySpec.js
Normal file
@@ -0,0 +1,45 @@
|
||||
describe("Any", function() {
|
||||
it("matches a string", function() {
|
||||
var any = new j$.Any(String);
|
||||
|
||||
expect(any.jasmineMatches("foo")).toBe(true);
|
||||
});
|
||||
|
||||
it("matches a number", function() {
|
||||
var any = new j$.Any(Number);
|
||||
|
||||
expect(any.jasmineMatches(1)).toBe(true);
|
||||
});
|
||||
|
||||
it("matches a function", function() {
|
||||
var any = new j$.Any(Function);
|
||||
|
||||
expect(any.jasmineMatches(function(){})).toBe(true);
|
||||
});
|
||||
|
||||
it("matches an Object", function() {
|
||||
var any = new j$.Any(Object);
|
||||
|
||||
expect(any.jasmineMatches({})).toBe(true);
|
||||
});
|
||||
|
||||
it("matches a Boolean", function() {
|
||||
var any = new j$.Any(Boolean);
|
||||
|
||||
expect(any.jasmineMatches(true)).toBe(true);
|
||||
});
|
||||
|
||||
it("matches another constructed object", function() {
|
||||
var Thing = function() {},
|
||||
any = new j$.Any(Thing);
|
||||
|
||||
expect(any.jasmineMatches(new Thing())).toBe(true);
|
||||
});
|
||||
|
||||
it("jasmineToString's itself", function() {
|
||||
var any = new j$.Any(Number);
|
||||
|
||||
expect(any.jasmineToString()).toMatch('<jasmine.any');
|
||||
});
|
||||
|
||||
});
|
||||
105
spec/core/CallTrackerSpec.js
Normal file
@@ -0,0 +1,105 @@
|
||||
describe("CallTracker", function() {
|
||||
it("tracks that it was called when executed", function() {
|
||||
var callTracker = new j$.CallTracker();
|
||||
|
||||
expect(callTracker.any()).toBe(false);
|
||||
|
||||
callTracker.track();
|
||||
|
||||
expect(callTracker.any()).toBe(true);
|
||||
});
|
||||
|
||||
it("tracks that number of times that it is executed", function() {
|
||||
var callTracker = new j$.CallTracker();
|
||||
|
||||
expect(callTracker.count()).toEqual(0);
|
||||
|
||||
callTracker.track();
|
||||
|
||||
expect(callTracker.count()).toEqual(1);
|
||||
});
|
||||
|
||||
it("tracks the params from each execution", function() {
|
||||
var callTracker = new j$.CallTracker();
|
||||
|
||||
callTracker.track({object: void 0, args: []});
|
||||
callTracker.track({object: {}, args: [0, "foo"]});
|
||||
|
||||
expect(callTracker.argsFor(0)).toEqual([]);
|
||||
|
||||
expect(callTracker.argsFor(1)).toEqual([0, "foo"]);
|
||||
});
|
||||
|
||||
it("returns any empty array when there was no call", function() {
|
||||
var callTracker = new j$.CallTracker();
|
||||
|
||||
expect(callTracker.argsFor(0)).toEqual([]);
|
||||
});
|
||||
|
||||
it("allows access for the arguments for all calls", function() {
|
||||
var callTracker = new j$.CallTracker();
|
||||
|
||||
callTracker.track({object: {}, args: []});
|
||||
callTracker.track({object: {}, args: [0, "foo"]});
|
||||
|
||||
expect(callTracker.allArgs()).toEqual([[], [0, "foo"]]);
|
||||
});
|
||||
|
||||
it("tracks the context and arguments for each call", function() {
|
||||
var callTracker = new j$.CallTracker();
|
||||
|
||||
callTracker.track({object: {}, args: []});
|
||||
callTracker.track({object: {}, args: [0, "foo"]});
|
||||
|
||||
expect(callTracker.all()[0]).toEqual({object: {}, args: []});
|
||||
|
||||
expect(callTracker.all()[1]).toEqual({object: {}, args: [0, "foo"]});
|
||||
});
|
||||
|
||||
it("simplifies access to the arguments for the last (most recent) call", function() {
|
||||
var callTracker = new j$.CallTracker();
|
||||
|
||||
callTracker.track();
|
||||
callTracker.track({object: {}, args: [0, "foo"]});
|
||||
|
||||
expect(callTracker.mostRecent()).toEqual({
|
||||
object: {},
|
||||
args: [0, "foo"]
|
||||
});
|
||||
});
|
||||
|
||||
it("returns a useful falsy value when there isn't a last (most recent) call", function() {
|
||||
var callTracker = new j$.CallTracker();
|
||||
|
||||
expect(callTracker.mostRecent()).toBeFalsy();
|
||||
});
|
||||
|
||||
it("simplifies access to the arguments for the first (oldest) call", function() {
|
||||
var callTracker = new j$.CallTracker();
|
||||
|
||||
callTracker.track({object: {}, args: [0, "foo"]});
|
||||
|
||||
expect(callTracker.first()).toEqual({object: {}, args: [0, "foo"]})
|
||||
});
|
||||
|
||||
it("returns a useful falsy value when there isn't a first (oldest) call", function() {
|
||||
var callTracker = new j$.CallTracker();
|
||||
|
||||
expect(callTracker.first()).toBeFalsy();
|
||||
});
|
||||
|
||||
|
||||
it("allows the tracking to be reset", function() {
|
||||
var callTracker = new j$.CallTracker();
|
||||
|
||||
callTracker.track();
|
||||
callTracker.track({object: {}, args: [0, "foo"]});
|
||||
callTracker.reset();
|
||||
|
||||
expect(callTracker.any()).toBe(false);
|
||||
expect(callTracker.count()).toEqual(0);
|
||||
expect(callTracker.argsFor(0)).toEqual([]);
|
||||
expect(callTracker.all()).toEqual([]);
|
||||
expect(callTracker.mostRecent()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
314
spec/core/ClockSpec.js
Normal file
@@ -0,0 +1,314 @@
|
||||
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);
|
||||
|
||||
clock.setTimeout(delayedFn, 0);
|
||||
|
||||
expect(delayedFunctionScheduler.scheduleFunction).not.toHaveBeenCalled();
|
||||
expect(setTimeout).toHaveBeenCalledWith(delayedFn, 0);
|
||||
});
|
||||
|
||||
it("schedules the delayed function with the fake timer", function() {
|
||||
var setTimeout = jasmine.createSpy('setTimeout'),
|
||||
scheduleFunction = jasmine.createSpy('scheduleFunction'),
|
||||
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
|
||||
global = { setTimeout: setTimeout },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
clock = new j$.Clock(global, delayedFunctionScheduler);
|
||||
|
||||
clock.install();
|
||||
clock.setTimeout(delayedFn, 0, 'a', 'b');
|
||||
|
||||
expect(setTimeout).not.toHaveBeenCalled();
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(delayedFn, 0, ['a', 'b']);
|
||||
});
|
||||
|
||||
it("returns an id for the delayed function", function() {
|
||||
var setTimeout = jasmine.createSpy('setTimeout'),
|
||||
scheduleId = 123,
|
||||
scheduleFunction = jasmine.createSpy('scheduleFunction').and.callReturn(scheduleId),
|
||||
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
|
||||
global = { setTimeout: setTimeout },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
clock = new j$.Clock(global, delayedFunctionScheduler),
|
||||
timeoutId;
|
||||
|
||||
clock.install();
|
||||
timeoutId = clock.setTimeout(delayedFn, 0);
|
||||
|
||||
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'),
|
||||
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['removeFunctionWithId']),
|
||||
global = { setTimeout: clearTimeout },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
clock = new j$.Clock(global, delayedFunctionScheduler);
|
||||
|
||||
clock.install();
|
||||
clock.clearTimeout(123);
|
||||
|
||||
expect(clearTimeout).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'),
|
||||
scheduleFunction = jasmine.createSpy('scheduleFunction'),
|
||||
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
|
||||
global = { setInterval: setInterval },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
clock = new j$.Clock(global, delayedFunctionScheduler);
|
||||
|
||||
clock.install();
|
||||
clock.setInterval(delayedFn, 0, 'a', 'b');
|
||||
|
||||
expect(setInterval).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'),
|
||||
scheduleId = 123,
|
||||
scheduleFunction = jasmine.createSpy('scheduleFunction').and.callReturn(scheduleId),
|
||||
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
|
||||
global = { setInterval: setInterval },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
clock = new j$.Clock(global, delayedFunctionScheduler),
|
||||
intervalId;
|
||||
|
||||
clock.install();
|
||||
intervalId = clock.setInterval(delayedFn, 0);
|
||||
|
||||
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 },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
clock = new j$.Clock(global, delayedFunctionScheduler);
|
||||
|
||||
clock.install();
|
||||
clock.clearInterval(123);
|
||||
|
||||
expect(clearInterval).not.toHaveBeenCalled();
|
||||
expect(delayedFunctionScheduler.removeFunctionWithId).toHaveBeenCalledWith(123);
|
||||
});
|
||||
|
||||
it("gives you a friendly reminder if the Clock is not installed and you tick", function() {
|
||||
var clock = new j$.Clock({}, jasmine.createSpyObj('delayedFunctionScheduler', ['tick']));
|
||||
expect(function() {
|
||||
clock.tick(50);
|
||||
}).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);
|
||||
|
||||
setTimeout.apply = null;
|
||||
setInterval.apply = null;
|
||||
|
||||
clock.install();
|
||||
|
||||
clock.setTimeout(fn, 0);
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, []);
|
||||
expect(function() {
|
||||
clock.setTimeout(fn, 0, 'extra');
|
||||
}).toThrow();
|
||||
|
||||
clock.setInterval(fn, 0);
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, [], true);
|
||||
expect(function() {
|
||||
clock.setInterval(fn, 0, 'extra');
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("Clock (acceptance)", function() {
|
||||
it("can run setTimeouts/setIntervals synchronously", function() {
|
||||
var delayedFn1 = jasmine.createSpy('delayedFn1'),
|
||||
delayedFn2 = jasmine.createSpy('delayedFn2'),
|
||||
delayedFn3 = jasmine.createSpy('delayedFn3'),
|
||||
recurring1 = jasmine.createSpy('recurring1'),
|
||||
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
|
||||
clock = new j$.Clock({setTimeout: setTimeout}, delayedFunctionScheduler);
|
||||
|
||||
clock.install();
|
||||
|
||||
clock.setTimeout(delayedFn1, 0, 'some', 'arg');
|
||||
var intervalId = clock.setInterval(recurring1, 50, 'some', 'other', 'args');
|
||||
clock.setTimeout(delayedFn2, 100);
|
||||
clock.setTimeout(delayedFn3, 200);
|
||||
|
||||
expect(delayedFn1).not.toHaveBeenCalled();
|
||||
expect(delayedFn2).not.toHaveBeenCalled();
|
||||
expect(delayedFn3).not.toHaveBeenCalled();
|
||||
|
||||
clock.tick(0);
|
||||
|
||||
expect(delayedFn1).toHaveBeenCalledWith('some', 'arg');
|
||||
expect(delayedFn2).not.toHaveBeenCalled();
|
||||
expect(delayedFn3).not.toHaveBeenCalled();
|
||||
|
||||
clock.tick(50);
|
||||
|
||||
expect(recurring1).toHaveBeenCalledWith('some', 'other', 'args');
|
||||
expect(recurring1.calls.count()).toBe(1);
|
||||
expect(delayedFn2).not.toHaveBeenCalled();
|
||||
expect(delayedFn3).not.toHaveBeenCalled();
|
||||
|
||||
clock.tick(50);
|
||||
|
||||
expect(recurring1.calls.count()).toBe(2);
|
||||
expect(delayedFn2).toHaveBeenCalled();
|
||||
expect(delayedFn3).not.toHaveBeenCalled();
|
||||
|
||||
clock.tick(100);
|
||||
|
||||
expect(recurring1.calls.count()).toBe(4);
|
||||
expect(delayedFn3).toHaveBeenCalled();
|
||||
|
||||
clock.clearInterval(intervalId);
|
||||
clock.tick(50);
|
||||
|
||||
expect(recurring1.calls.count()).toBe(4);
|
||||
});
|
||||
|
||||
it("can clear a previously set timeout", function() {
|
||||
var clearedFn = jasmine.createSpy('clearedFn'),
|
||||
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
|
||||
clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler),
|
||||
timeoutId;
|
||||
|
||||
clock.install();
|
||||
|
||||
timeoutId = clock.setTimeout(clearedFn, 100);
|
||||
expect(clearedFn).not.toHaveBeenCalled();
|
||||
|
||||
clock.clearTimeout(timeoutId);
|
||||
clock.tick(100);
|
||||
|
||||
expect(clearedFn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
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.install();
|
||||
|
||||
clock.tick(100);
|
||||
clock.setTimeout(delayedFn1, 10, ['some', 'arg']);
|
||||
clock.tick(5);
|
||||
expect(delayedFn1).not.toHaveBeenCalled();
|
||||
clock.tick(5);
|
||||
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);
|
||||
|
||||
expect(function() {
|
||||
clock.clearTimeout(123)
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
expect(function() {
|
||||
clock.clearInterval(123)
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
96
spec/core/CustomMatchersSpec.js
Normal file
@@ -0,0 +1,96 @@
|
||||
////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']]);
|
||||
// });
|
||||
//});
|
||||
179
spec/core/DelayedFunctionSchedulerSpec.js
Normal file
@@ -0,0 +1,179 @@
|
||||
describe("DelayedFunctionScheduler", function() {
|
||||
it("schedules a function for later execution", function() {
|
||||
var scheduler = new j$.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn');
|
||||
|
||||
scheduler.scheduleFunction(fn, 0);
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
scheduler.tick(0);
|
||||
|
||||
expect(fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("schedules a string for later execution", function() {
|
||||
var scheduler = new j$.DelayedFunctionScheduler(),
|
||||
strfn = "horrible = true;";
|
||||
|
||||
scheduler.scheduleFunction(strfn, 0);
|
||||
|
||||
scheduler.tick(0);
|
||||
|
||||
expect(horrible).toEqual(true);
|
||||
});
|
||||
|
||||
it("#tick defaults to 0", function() {
|
||||
var scheduler = new j$.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn');
|
||||
|
||||
scheduler.scheduleFunction(fn, 0);
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
scheduler.tick();
|
||||
|
||||
expect(fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("defaults delay to 0", function() {
|
||||
var scheduler = new j$.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn');
|
||||
|
||||
scheduler.scheduleFunction(fn);
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
scheduler.tick(0);
|
||||
|
||||
expect(fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("optionally passes params to scheduled functions", function() {
|
||||
var scheduler = new j$.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn');
|
||||
|
||||
scheduler.scheduleFunction(fn, 0, ['foo', 'bar']);
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
scheduler.tick(0);
|
||||
|
||||
expect(fn).toHaveBeenCalledWith('foo', 'bar');
|
||||
});
|
||||
|
||||
it("scheduled fns can optionally reoccur", function() {
|
||||
var scheduler = new j$.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn');
|
||||
|
||||
scheduler.scheduleFunction(fn, 20, [], true);
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
scheduler.tick(20);
|
||||
|
||||
expect(fn.calls.count()).toBe(1);
|
||||
|
||||
scheduler.tick(40);
|
||||
|
||||
expect(fn.calls.count()).toBe(3);
|
||||
|
||||
scheduler.tick(21);
|
||||
|
||||
expect(fn.calls.count()).toBe(4);
|
||||
|
||||
});
|
||||
|
||||
it("increments scheduled fns ids unless one is passed", function() {
|
||||
var scheduler = new j$.DelayedFunctionScheduler();
|
||||
|
||||
expect(scheduler.scheduleFunction(function() {
|
||||
}, 0)).toBe(1);
|
||||
expect(scheduler.scheduleFunction(function() {
|
||||
}, 0)).toBe(2);
|
||||
expect(scheduler.scheduleFunction(function() {
|
||||
}, 0, [], false, 123)).toBe(123);
|
||||
expect(scheduler.scheduleFunction(function() {
|
||||
}, 0)).toBe(3);
|
||||
});
|
||||
|
||||
it("#removeFunctionWithId removes a previously scheduled function with a given id", function() {
|
||||
var scheduler = new j$.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn'),
|
||||
timeoutKey;
|
||||
|
||||
timeoutKey = scheduler.scheduleFunction(fn, 0);
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
scheduler.removeFunctionWithId(timeoutKey);
|
||||
|
||||
scheduler.tick(0);
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("reset removes scheduled functions", function() {
|
||||
var scheduler = new j$.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn');
|
||||
|
||||
scheduler.scheduleFunction(fn, 0);
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
scheduler.reset();
|
||||
|
||||
scheduler.tick(0);
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("reset resets the returned ids", function() {
|
||||
var scheduler = new j$.DelayedFunctionScheduler();
|
||||
expect(scheduler.scheduleFunction(function() { }, 0)).toBe(1);
|
||||
expect(scheduler.scheduleFunction(function() { }, 0, [], false, 123)).toBe(123);
|
||||
|
||||
scheduler.reset();
|
||||
expect(scheduler.scheduleFunction(function() { }, 0)).toBe(1);
|
||||
expect(scheduler.scheduleFunction(function() { }, 0, [], false, 123)).toBe(123);
|
||||
});
|
||||
|
||||
it("reset resets the current tick time", function() {
|
||||
var scheduler = new j$.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn');
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
scheduler.tick(15);
|
||||
scheduler.reset();
|
||||
|
||||
scheduler.scheduleFunction(fn, 20, [], false, 1, 20);
|
||||
|
||||
scheduler.tick(5);
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("executes recurring functions interleaved with regular functions in the correct order", function() {
|
||||
var scheduler = new j$.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn'),
|
||||
recurringCallCount = 0,
|
||||
recurring = jasmine.createSpy('recurring').and.callFake(function() {
|
||||
recurringCallCount++;
|
||||
if (recurringCallCount < 5) {
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
|
||||
scheduler.scheduleFunction(recurring, 10, [], true);
|
||||
scheduler.scheduleFunction(fn, 50);
|
||||
|
||||
scheduler.tick(60);
|
||||
|
||||
expect(recurring).toHaveBeenCalled();
|
||||
expect(recurring.calls.count()).toBe(6);
|
||||
expect(fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
511
spec/core/EnvSpec.js
Normal file
@@ -0,0 +1,511 @@
|
||||
// TODO: Fix these unit tests!
|
||||
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 = {
|
||||
foo: originalFoo
|
||||
},
|
||||
firstSpec = jasmine.createSpy('firstSpec').and.callFake(function() {
|
||||
env.spyOn(testObj, 'foo');
|
||||
}),
|
||||
secondSpec = jasmine.createSpy('secondSpec').and.callFake(function() {
|
||||
expect(testObj.foo).toBe(originalFoo);
|
||||
});
|
||||
env.describe('test suite', function() {
|
||||
env.it('spec 0', firstSpec);
|
||||
env.it('spec 1', secondSpec);
|
||||
});
|
||||
|
||||
var assertions = function() {
|
||||
expect(firstSpec).toHaveBeenCalled();
|
||||
expect(secondSpec).toHaveBeenCalled();
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions });
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
describe("#spyOn", function() {
|
||||
it("checks for the existance of the object", function() {
|
||||
expect(function() {
|
||||
env.spyOn(void 0, 'pants');
|
||||
}).toThrowError(/could not find an object/);
|
||||
});
|
||||
|
||||
it("checks for the existance of the method", function() {
|
||||
var subject = {};
|
||||
|
||||
expect(function() {
|
||||
env.spyOn(subject, 'pants');
|
||||
}).toThrowError(/method does not exist/);
|
||||
});
|
||||
|
||||
it("checks if it has already been spied upon", function() {
|
||||
var subject = { spiedFunc: function() {} };
|
||||
|
||||
env.spyOn(subject, 'spiedFunc');
|
||||
|
||||
expect(function() {
|
||||
env.spyOn(subject, 'spiedFunc');
|
||||
}).toThrowError(/has already been spied upon/);
|
||||
});
|
||||
|
||||
it("overrides the method on the object and returns the spy", function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
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);
|
||||
|
||||
subject.spiedFunc('foo');
|
||||
|
||||
expect(subject.spiedFunc.calls.any()).toEqual(true);
|
||||
expect(subject.spiedFunc.calls.count()).toEqual(1);
|
||||
expect(subject.spiedFunc.calls.mostRecent().args).toEqual(['foo']);
|
||||
expect(subject.spiedFunc.calls.mostRecent().object).toEqual(subject);
|
||||
expect(originalFunctionWasCalled).toEqual(false);
|
||||
|
||||
subject.spiedFunc('bar');
|
||||
expect(subject.spiedFunc.calls.count()).toEqual(2);
|
||||
expect(subject.spiedFunc.calls.mostRecent().args).toEqual(['bar']);
|
||||
});
|
||||
});
|
||||
|
||||
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() {
|
||||
env.pending();
|
||||
}).toThrow(j$.Spec.pendingSpecExceptionMessage);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// TODO: move these into a separate file
|
||||
describe("Env integration", function() {
|
||||
|
||||
it("Suites execute as expected (no nesting)", function(done) {
|
||||
var env = new j$.Env(),
|
||||
calls = [];
|
||||
|
||||
var assertions = function() {
|
||||
expect(calls).toEqual([
|
||||
"with a spec",
|
||||
"and another spec"
|
||||
]);
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions});
|
||||
|
||||
env.describe("A Suite", function() {
|
||||
env.it("with a spec", function() {
|
||||
calls.push("with a spec");
|
||||
});
|
||||
env.it("and another spec", function() {
|
||||
calls.push("and another spec");
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Nested Suites execute as expected", function(done) {
|
||||
var env = new j$.Env(),
|
||||
calls = [];
|
||||
|
||||
var assertions = function() {
|
||||
expect(calls).toEqual([
|
||||
'an outer spec',
|
||||
'an inner spec',
|
||||
'another inner spec'
|
||||
]);
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions });
|
||||
|
||||
env.describe("Outer suite", function() {
|
||||
env.it("an outer spec", function() {
|
||||
calls.push('an outer spec')
|
||||
});
|
||||
env.describe("Inner suite", function() {
|
||||
env.it("an inner spec", function() {
|
||||
calls.push('an inner spec');
|
||||
});
|
||||
env.it("another inner spec", function() {
|
||||
calls.push('another inner spec');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Multiple top-level Suites execute as expected", function(done) {
|
||||
var env = new j$.Env(),
|
||||
calls = [];
|
||||
|
||||
var assertions = function() {
|
||||
expect(calls).toEqual([
|
||||
'an outer spec',
|
||||
'an inner spec',
|
||||
'another inner spec',
|
||||
'a 2nd outer spec'
|
||||
]);
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions });
|
||||
|
||||
|
||||
env.describe("Outer suite", function() {
|
||||
env.it("an outer spec", function() {
|
||||
calls.push('an outer spec')
|
||||
});
|
||||
env.describe("Inner suite", function() {
|
||||
env.it("an inner spec", function() {
|
||||
calls.push('an inner spec');
|
||||
});
|
||||
env.it("another inner spec", function() {
|
||||
calls.push('another inner spec');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.describe("Another outer suite", function() {
|
||||
env.it("a 2nd outer spec", function() {
|
||||
calls.push('a 2nd outer spec')
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Mock clock can be installed and used in tests", function(done) {
|
||||
var globalSetTimeout = jasmine.createSpy('globalSetTimeout'),
|
||||
delayedFunctionForGlobalClock = jasmine.createSpy('delayedFunctionForGlobalClock'),
|
||||
delayedFunctionForMockClock = jasmine.createSpy('delayedFunctionForMockClock'),
|
||||
env = new j$.Env({global: { setTimeout: globalSetTimeout }});
|
||||
|
||||
var assertions = function() {
|
||||
expect(delayedFunctionForMockClock).toHaveBeenCalled();
|
||||
expect(globalSetTimeout).toHaveBeenCalledWith(delayedFunctionForGlobalClock, 100);
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions });
|
||||
|
||||
env.describe("tests", function() {
|
||||
env.it("test with mock clock", function() {
|
||||
env.clock.install();
|
||||
env.clock.setTimeout(delayedFunctionForMockClock, 100);
|
||||
env.clock.tick(100);
|
||||
});
|
||||
env.it("test without mock clock", function() {
|
||||
env.clock.setTimeout(delayedFunctionForGlobalClock, 100);
|
||||
});
|
||||
});
|
||||
|
||||
expect(globalSetTimeout).not.toHaveBeenCalled();
|
||||
expect(delayedFunctionForMockClock).not.toHaveBeenCalled();
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("should run async specs in order, waiting for them to complete", function(done) {
|
||||
var env = new j$.Env(), mutatedVar;
|
||||
|
||||
env.describe("tests", function() {
|
||||
env.beforeEach(function() {
|
||||
mutatedVar = 2;
|
||||
});
|
||||
|
||||
env.it("async spec", function(underTestCallback) {
|
||||
setTimeout(function() {
|
||||
expect(mutatedVar).toEqual(2);
|
||||
underTestCallback();
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
env.it("after async spec", function() {
|
||||
mutatedVar = 3;
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
describe("with a mock clock", function() {
|
||||
beforeEach(function() {
|
||||
jasmine.getEnv().clock.install();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
jasmine.getEnv().clock.uninstall();
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: something is wrong with this spec
|
||||
it("should report as expected", function(done) {
|
||||
var env = new j$.Env(),
|
||||
reporter = jasmine.createSpyObj('fakeReporter', [
|
||||
"jasmineStarted",
|
||||
"jasmineDone",
|
||||
"suiteStarted",
|
||||
"suiteDone",
|
||||
"specStarted",
|
||||
"specDone"
|
||||
]);
|
||||
|
||||
reporter.jasmineDone.and.callFake(function() {
|
||||
expect(reporter.jasmineStarted).toHaveBeenCalledWith({
|
||||
totalSpecsDefined: 3
|
||||
});
|
||||
var suiteResult = reporter.suiteStarted.calls.first().args[0];
|
||||
expect(suiteResult.description).toEqual("A Suite");
|
||||
expect(reporter.jasmineDone).toHaveBeenCalled();
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.describe("A Suite", function() {
|
||||
env.it("with a top level spec", function() {
|
||||
env.expect(true).toBe(true);
|
||||
});
|
||||
env.describe("with a nested suite", function() {
|
||||
env.xit("with a pending spec", function() {
|
||||
env.expect(true).toBe(true);
|
||||
});
|
||||
env.it("with a spec", function() {
|
||||
env.expect(true).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("should be possible to get full name from a spec", function() {
|
||||
var env = new j$.Env({global: { setTimeout: setTimeout }}),
|
||||
topLevelSpec, nestedSpec, doublyNestedSpec;
|
||||
|
||||
env.describe("my tests", function() {
|
||||
topLevelSpec = env.it("are sometimes top level", function() {
|
||||
});
|
||||
env.describe("are sometimes", function() {
|
||||
nestedSpec = env.it("singly nested", function() {
|
||||
});
|
||||
env.describe("even", function() {
|
||||
doublyNestedSpec = env.it("doubly nested", 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.");
|
||||
});
|
||||
|
||||
it("Custom equality testers should be per spec", function(done) {
|
||||
var env = new j$.Env({global: { setTimeout: setTimeout }}),
|
||||
reporter = jasmine.createSpyObj('fakeReproter', [
|
||||
"jasmineStarted",
|
||||
"jasmineDone",
|
||||
"suiteStarted",
|
||||
"suiteDone",
|
||||
"specStarted",
|
||||
"specDone"
|
||||
]);
|
||||
|
||||
reporter.jasmineDone.and.callFake(function() {
|
||||
var firstSpecResult = reporter.specDone.calls.first().args[0],
|
||||
secondSpecResult = reporter.specDone.calls.mostRecent().args[0];
|
||||
|
||||
expect(firstSpecResult.status).toEqual("passed");
|
||||
expect(secondSpecResult.status).toEqual("failed");
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.describe("testing custom equality testers", function() {
|
||||
env.it("with a custom tester", function() {
|
||||
env.addCustomEqualityTester(function(a, b) { return true; });
|
||||
env.expect("a").toEqual("b");
|
||||
});
|
||||
|
||||
env.it("without a custom tester", function() {
|
||||
env.expect("a").toEqual("b");
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Custom matchers should be per spec", function() {
|
||||
var env = new j$.Env({global: { setTimeout: setTimeout }}),
|
||||
matchers = {
|
||||
toFoo: function() {}
|
||||
},
|
||||
reporter = jasmine.createSpyObj('fakeReproter', [
|
||||
"jasmineStarted",
|
||||
"jasmineDone",
|
||||
"suiteStarted",
|
||||
"suiteDone",
|
||||
"specStarted",
|
||||
"specDone"
|
||||
]);
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.describe("testing custom matchers", function() {
|
||||
env.it("with a custom matcher", function() {
|
||||
env.addMatchers(matchers);
|
||||
expect(env.expect().toFoo).toBeDefined();
|
||||
});
|
||||
|
||||
env.it("without a custom matcher", function() {
|
||||
expect(env.expect().toFoo).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Custom equality testers for toContain should be per spec", function(done) {
|
||||
var env = new j$.Env({global: { setTimeout: setTimeout }}),
|
||||
reporter = jasmine.createSpyObj('fakeReproter', [
|
||||
"jasmineStarted",
|
||||
"jasmineDone",
|
||||
"suiteStarted",
|
||||
"suiteDone",
|
||||
"specStarted",
|
||||
"specDone"
|
||||
]);
|
||||
|
||||
reporter.jasmineDone.and.callFake(function() {
|
||||
var firstSpecResult = reporter.specDone.calls.first().args[0],
|
||||
secondSpecResult = reporter.specDone.calls.mostRecent().args[0];
|
||||
|
||||
expect(firstSpecResult.status).toEqual("passed");
|
||||
expect(secondSpecResult.status).toEqual("failed");
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.describe("testing custom equality testers", function() {
|
||||
env.it("with a custom tester", function() {
|
||||
env.addCustomEqualityTester(function(a, b) { return true; });
|
||||
env.expect(["a"]).toContain("b");
|
||||
});
|
||||
|
||||
env.it("without a custom tester", function() {
|
||||
env.expect("a").toContain("b");
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
56
spec/core/ExceptionFormatterSpec.js
Normal file
@@ -0,0 +1,56 @@
|
||||
describe("ExceptionFormatter", function() {
|
||||
describe("#message", function() {
|
||||
it('formats Firefox exception messages', function() {
|
||||
var sampleFirefoxException = {
|
||||
fileName: 'foo.js',
|
||||
lineNumber: '1978',
|
||||
message: 'you got your foo in my bar',
|
||||
name: 'A Classic Mistake'
|
||||
},
|
||||
exceptionFormatter = new j$.ExceptionFormatter(),
|
||||
message = exceptionFormatter.message(sampleFirefoxException);
|
||||
|
||||
expect(message).toEqual('A Classic Mistake: you got your foo in my bar in foo.js (line 1978)');
|
||||
});
|
||||
|
||||
it('formats Webkit exception messages', function() {
|
||||
var sampleWebkitException = {
|
||||
sourceURL: 'foo.js',
|
||||
line: '1978',
|
||||
message: 'you got your foo in my bar',
|
||||
name: 'A Classic Mistake'
|
||||
},
|
||||
exceptionFormatter = new j$.ExceptionFormatter(),
|
||||
message = exceptionFormatter.message(sampleWebkitException);
|
||||
|
||||
expect(message).toEqual('A Classic Mistake: you got your foo in my bar in foo.js (line 1978)');
|
||||
});
|
||||
|
||||
it('formats V8 exception messages', function() {
|
||||
var sampleV8 = {
|
||||
message: 'you got your foo in my bar',
|
||||
name: 'A Classic Mistake'
|
||||
},
|
||||
exceptionFormatter = new j$.ExceptionFormatter(),
|
||||
message = exceptionFormatter.message(sampleV8);
|
||||
|
||||
expect(message).toEqual('A Classic Mistake: you got your foo in my bar');
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe("#stack", function() {
|
||||
it("formats stack traces from Webkit, Firefox, node.js or IE10+", function() {
|
||||
if (jasmine.getEnv().ieVersion < 10 || jasmine.getEnv().safariVersion < 6) { return; }
|
||||
|
||||
var error;
|
||||
try { throw new Error("an error") } catch(e) { error = e; }
|
||||
|
||||
expect(new j$.ExceptionFormatter().stack(error)).toMatch(/ExceptionFormatterSpec\.js.*\d+/)
|
||||
});
|
||||
|
||||
it("returns null if no Error provided", function() {
|
||||
expect(new j$.ExceptionFormatter().stack()).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
64
spec/core/ExceptionsSpec.js
Normal file
@@ -0,0 +1,64 @@
|
||||
xdescribe('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.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();
|
||||
dont_change = 'oops I changed';
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
expect(dont_change).toEqual('I will never change!');
|
||||
});
|
||||
});
|
||||
|
||||
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 () {
|
||||
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;
|
||||
});
|
||||
});
|
||||
|
||||
suite.execute();
|
||||
expect(ranSecondTest).toBe(true);
|
||||
});
|
||||
|
||||
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 () {
|
||||
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;
|
||||
});
|
||||
|
||||
runner.execute();
|
||||
expect(ranSecondDescribe).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
61
spec/core/ExpectationResultSpec.js
Normal file
@@ -0,0 +1,61 @@
|
||||
describe("buildExpectationResult", function() {
|
||||
it("defaults to passed", function() {
|
||||
var result = j$.buildExpectationResult({passed: 'some-value'});
|
||||
expect(result.passed).toBe('some-value');
|
||||
});
|
||||
|
||||
it("message defaults to Passed for passing specs", function() {
|
||||
var result = j$.buildExpectationResult({passed: true, message: 'some-value'});
|
||||
expect(result.message).toBe('Passed.');
|
||||
});
|
||||
|
||||
it("message returns the message for failing expecations", function() {
|
||||
var result = j$.buildExpectationResult({passed: false, message: 'some-value'});
|
||||
expect(result.message).toBe('some-value');
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
var result = j$.buildExpectationResult(
|
||||
{
|
||||
passed: false,
|
||||
error: fakeError,
|
||||
messageFormatter: messageFormatter
|
||||
});
|
||||
|
||||
expect(messageFormatter).toHaveBeenCalledWith(fakeError);
|
||||
expect(result.message).toEqual('foo');
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
var result = j$.buildExpectationResult(
|
||||
{
|
||||
passed: false,
|
||||
error: fakeError,
|
||||
stackFormatter: stackFormatter
|
||||
});
|
||||
|
||||
expect(stackFormatter).toHaveBeenCalledWith(fakeError);
|
||||
expect(result.stack).toEqual('foo');
|
||||
});
|
||||
|
||||
it("matcherName returns passed matcherName", function() {
|
||||
var result = j$.buildExpectationResult({matcherName: 'some-value'});
|
||||
expect(result.matcherName).toBe('some-value');
|
||||
});
|
||||
|
||||
it("expected returns passed expected", function() {
|
||||
var result = j$.buildExpectationResult({expected: 'some-value'});
|
||||
expect(result.expected).toBe('some-value');
|
||||
});
|
||||
|
||||
it("actual returns passed actual", function() {
|
||||
var result = j$.buildExpectationResult({actual: 'some-value'});
|
||||
expect(result.actual).toBe('some-value');
|
||||
});
|
||||
});
|
||||
320
spec/core/ExpectationSpec.js
Normal file
@@ -0,0 +1,320 @@
|
||||
describe("Expectation", function() {
|
||||
it(".addMatchers makes matchers available to any expectation", function() {
|
||||
var matchers = {
|
||||
toFoo: function() {},
|
||||
toBar: function() {}
|
||||
},
|
||||
expectation;
|
||||
|
||||
j$.Expectation.addMatchers(matchers);
|
||||
|
||||
expectation = new j$.Expectation({});
|
||||
|
||||
expect(expectation.toFoo).toBeDefined();
|
||||
expect(expectation.toBar).toBeDefined();
|
||||
});
|
||||
|
||||
it(".addCoreMatchers makes matchers available to any expectation", function() {
|
||||
var coreMatchers = {
|
||||
toQuux: function() {}
|
||||
},
|
||||
expectation;
|
||||
|
||||
j$.Expectation.addCoreMatchers(coreMatchers);
|
||||
|
||||
expectation = new j$.Expectation({});
|
||||
|
||||
expect(expectation.toQuux).toBeDefined();
|
||||
});
|
||||
|
||||
it(".resetMatchers should keep only core matchers", function() {
|
||||
var matchers = {
|
||||
toFoo: function() {}
|
||||
},
|
||||
coreMatchers = {
|
||||
toQuux: function() {}
|
||||
},
|
||||
expectation;
|
||||
|
||||
j$.Expectation.addCoreMatchers(coreMatchers);
|
||||
j$.Expectation.addMatchers(matchers);
|
||||
j$.Expectation.resetMatchers();
|
||||
|
||||
expectation = new j$.Expectation({});
|
||||
|
||||
expect(expectation.toQuux).toBeDefined();
|
||||
expect(expectation.toFoo).toBeUndefined();
|
||||
});
|
||||
|
||||
it("Factory builds an expectaion/negative expectation", function() {
|
||||
var builtExpectation = j$.Expectation.Factory();
|
||||
|
||||
expect(builtExpectation instanceof j$.Expectation).toBe(true);
|
||||
expect(builtExpectation.not instanceof j$.Expectation).toBe(true);
|
||||
expect(builtExpectation.not.isNot).toBe(true);
|
||||
});
|
||||
|
||||
it("wraps matchers's compare functions, passing in matcher dependencies", function() {
|
||||
var fakeCompare = function() { return { pass: true }; },
|
||||
matcherFactory = jasmine.createSpy("matcher").and.callReturn({ compare: fakeCompare }),
|
||||
matchers = {
|
||||
toFoo: matcherFactory
|
||||
},
|
||||
util = {},
|
||||
customEqualityTesters = ['a'],
|
||||
addExpectationResult = jasmine.createSpy("addExpectationResult"),
|
||||
expectation;
|
||||
|
||||
j$.Expectation.addMatchers(matchers);
|
||||
|
||||
expectation = new j$.Expectation({
|
||||
util: util,
|
||||
customEqualityTesters: customEqualityTesters,
|
||||
actual: "an actual",
|
||||
addExpectationResult: addExpectationResult
|
||||
});
|
||||
|
||||
expectation.toFoo("hello");
|
||||
|
||||
expect(matcherFactory).toHaveBeenCalledWith(util, customEqualityTesters)
|
||||
});
|
||||
|
||||
it("wraps matchers's compare functions, passing the actual and expected", function() {
|
||||
var fakeCompare = jasmine.createSpy('fake-compare').and.callReturn({pass: true}),
|
||||
matchers = {
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: fakeCompare
|
||||
};
|
||||
}
|
||||
},
|
||||
util = {
|
||||
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy("addExpectationResult"),
|
||||
expectation;
|
||||
|
||||
j$.Expectation.addMatchers(matchers);
|
||||
|
||||
expectation = new j$.Expectation({
|
||||
util: util,
|
||||
actual: "an actual",
|
||||
addExpectationResult: addExpectationResult
|
||||
});
|
||||
|
||||
expectation.toFoo("hello");
|
||||
|
||||
expect(fakeCompare).toHaveBeenCalledWith("an actual", "hello");
|
||||
});
|
||||
|
||||
it("reports a passing result to the spec when the comparison passes", function() {
|
||||
var matchers = {
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() { return { pass: true }; }
|
||||
};
|
||||
}
|
||||
},
|
||||
util = {
|
||||
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy("addExpectationResult"),
|
||||
expectation;
|
||||
|
||||
j$.Expectation.addMatchers(matchers);
|
||||
|
||||
expectation = new j$.Expectation({
|
||||
matchers: matchers,
|
||||
util: util,
|
||||
actual: "an actual",
|
||||
addExpectationResult: addExpectationResult
|
||||
});
|
||||
|
||||
expectation.toFoo("hello");
|
||||
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(true, {
|
||||
matcherName: "toFoo",
|
||||
passed: true,
|
||||
message: "",
|
||||
expected: "hello",
|
||||
actual: "an actual"
|
||||
});
|
||||
});
|
||||
|
||||
it("reports a failing result to the spec when the comparison fails", function() {
|
||||
var matchers = {
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() { return { pass: false }; }
|
||||
};
|
||||
}
|
||||
},
|
||||
util = {
|
||||
buildFailureMessage: function() { return ""; }
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy("addExpectationResult"),
|
||||
expectation;
|
||||
|
||||
j$.Expectation.addMatchers(matchers);
|
||||
|
||||
expectation = new j$.Expectation({
|
||||
matchers: matchers,
|
||||
util: util,
|
||||
actual: "an actual",
|
||||
addExpectationResult: addExpectationResult
|
||||
});
|
||||
|
||||
expectation.toFoo("hello");
|
||||
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: "toFoo",
|
||||
passed: false,
|
||||
expected: "hello",
|
||||
actual: "an actual",
|
||||
message: ""
|
||||
});
|
||||
});
|
||||
|
||||
it("reports a failing result and a custom fail message to the spec when the comparison fails", function() {
|
||||
var matchers = {
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return {
|
||||
pass: false,
|
||||
message: "I am a custom message"
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy("addExpectationResult"),
|
||||
expectation;
|
||||
|
||||
j$.Expectation.addMatchers(matchers);
|
||||
|
||||
expectation = new j$.Expectation({
|
||||
matchers: matchers,
|
||||
actual: "an actual",
|
||||
addExpectationResult: addExpectationResult
|
||||
});
|
||||
|
||||
expectation.toFoo("hello");
|
||||
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: "toFoo",
|
||||
passed: false,
|
||||
expected: "hello",
|
||||
actual: "an actual",
|
||||
message: "I am a custom message"
|
||||
});
|
||||
});
|
||||
|
||||
it("reports a passing result to the spec when the comparison fails for a negative expectation", function() {
|
||||
var matchers = {
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() { return { pass: false }; }
|
||||
};
|
||||
}
|
||||
},
|
||||
util = {
|
||||
buildFailureMessage: function() { return ""; }
|
||||
},
|
||||
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,
|
||||
message: "",
|
||||
expected: "hello",
|
||||
actual: actual
|
||||
});
|
||||
});
|
||||
|
||||
it("reports a failing result to the spec when the comparison passes for a negative expectation", function() {
|
||||
var matchers = {
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() { return { pass: true }; }
|
||||
};
|
||||
}
|
||||
},
|
||||
util = {
|
||||
buildFailureMessage: function() { return "default messge"; }
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy("addExpectationResult"),
|
||||
actual = "an actual",
|
||||
expectation;
|
||||
|
||||
j$.Expectation.addMatchers(matchers);
|
||||
|
||||
expectation = new j$.Expectation({
|
||||
matchers: matchers,
|
||||
actual: "an actual",
|
||||
util: util,
|
||||
addExpectationResult: addExpectationResult,
|
||||
isNot: true
|
||||
});
|
||||
|
||||
expectation.toFoo("hello");
|
||||
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: "toFoo",
|
||||
passed: false,
|
||||
expected: "hello",
|
||||
actual: actual,
|
||||
message: "default messge"
|
||||
});
|
||||
});
|
||||
|
||||
it("reports a failing result and a custom fail message to the spec when the comparison passes for a negative expectation", function() {
|
||||
var matchers = {
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return {
|
||||
pass: true,
|
||||
message: "I am 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 am a custom message"
|
||||
});
|
||||
});
|
||||
});
|
||||
215
spec/core/JsApiReporterSpec.js
Normal file
@@ -0,0 +1,215 @@
|
||||
xdescribe('JsApiReporter (integration specs)', function() {
|
||||
describe('results', function() {
|
||||
var reporter, spec1, spec2;
|
||||
var env;
|
||||
var suite, nestedSuite, nestedSpec;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new j$.Env();
|
||||
env.updateInterval = 0;
|
||||
|
||||
suite = env.describe("top-level suite", function() {
|
||||
spec1 = env.it("spec 1", function() {
|
||||
this.expect(true).toEqual(true);
|
||||
|
||||
});
|
||||
|
||||
spec2 = env.it("spec 2", function() {
|
||||
this.expect(true).toEqual(false);
|
||||
});
|
||||
|
||||
nestedSuite = env.describe("nested suite", function() {
|
||||
nestedSpec = env.it("nested spec", function() {
|
||||
expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
reporter = new j$.JsApiReporter({});
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.execute();
|
||||
|
||||
});
|
||||
|
||||
it('results() should return a hash of all results, indexed by spec id', function() {
|
||||
var expectedSpec1Results = {
|
||||
result: "passed"
|
||||
},
|
||||
expectedSpec2Results = {
|
||||
result: "failed"
|
||||
};
|
||||
expect(reporter.results()[spec1.id].result).toEqual('passed');
|
||||
expect(reporter.results()[spec2.id].result).toEqual('failed');
|
||||
});
|
||||
|
||||
it("should return nested suites as children of their parents", function() {
|
||||
expect(reporter.suites()).toEqual([
|
||||
{ id: 0, name: 'top-level suite', type: 'suite',
|
||||
children: [
|
||||
{ id: 0, name: 'spec 1', type: 'spec', children: [ ] },
|
||||
{ id: 1, name: 'spec 2', type: 'spec', children: [ ] },
|
||||
{ id: 1, name: 'nested suite', type: 'suite',
|
||||
children: [
|
||||
{ id: 2, name: 'nested spec', type: 'spec', children: [ ] }
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
describe("#summarizeResult_", function() {
|
||||
it("should summarize a passing result", function() {
|
||||
var result = reporter.results()[spec1.id];
|
||||
var summarizedResult = reporter.summarizeResult_(result);
|
||||
expect(summarizedResult.result).toEqual('passed');
|
||||
expect(summarizedResult.messages.length).toEqual(0);
|
||||
});
|
||||
|
||||
it("should have a stack trace for failing specs", function() {
|
||||
var result = reporter.results()[spec2.id];
|
||||
var summarizedResult = reporter.summarizeResult_(result);
|
||||
expect(summarizedResult.result).toEqual('failed');
|
||||
expect(summarizedResult.messages[0].trace.stack).toEqual(result.messages[0].trace.stack);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("JsApiReporter", function() {
|
||||
|
||||
it("knows when a full environment is started", function() {
|
||||
var reporter = new j$.JsApiReporter({});
|
||||
|
||||
expect(reporter.started).toBe(false);
|
||||
expect(reporter.finished).toBe(false);
|
||||
|
||||
reporter.jasmineStarted();
|
||||
|
||||
expect(reporter.started).toBe(true);
|
||||
expect(reporter.finished).toBe(false);
|
||||
});
|
||||
|
||||
it("knows when a full environment is done", function() {
|
||||
var reporter = new j$.JsApiReporter({});
|
||||
|
||||
expect(reporter.started).toBe(false);
|
||||
expect(reporter.finished).toBe(false);
|
||||
|
||||
reporter.jasmineStarted();
|
||||
reporter.jasmineDone({});
|
||||
|
||||
expect(reporter.finished).toBe(true);
|
||||
});
|
||||
|
||||
it("defaults to 'loaded' status", function() {
|
||||
var reporter = new j$.JsApiReporter({});
|
||||
|
||||
expect(reporter.status()).toEqual('loaded');
|
||||
});
|
||||
|
||||
it("reports 'started' when Jasmine has started", function() {
|
||||
var reporter = new j$.JsApiReporter({});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
|
||||
expect(reporter.status()).toEqual('started');
|
||||
});
|
||||
|
||||
it("reports 'done' when Jasmine is done", function() {
|
||||
var reporter = new j$.JsApiReporter({});
|
||||
|
||||
reporter.jasmineDone({});
|
||||
|
||||
expect(reporter.status()).toEqual('done');
|
||||
});
|
||||
|
||||
it("tracks a suite", function() {
|
||||
var reporter = new j$.JsApiReporter({});
|
||||
|
||||
reporter.suiteStarted({
|
||||
id: 123,
|
||||
description: "A suite"
|
||||
});
|
||||
|
||||
var suites = reporter.suites();
|
||||
|
||||
expect(suites).toEqual({123: {id: 123, description: "A suite"}});
|
||||
|
||||
reporter.suiteDone({
|
||||
id: 123,
|
||||
description: "A suite",
|
||||
status: 'passed'
|
||||
});
|
||||
|
||||
expect(suites).toEqual({123: {id: 123, description: "A suite", status: 'passed'}});
|
||||
});
|
||||
|
||||
describe("#specResults", function() {
|
||||
var reporter, specResult1, specResult2;
|
||||
beforeEach(function() {
|
||||
reporter = new j$.JsApiReporter({});
|
||||
specResult1 = {
|
||||
id: 1,
|
||||
description: "A spec"
|
||||
};
|
||||
specResult2 = {
|
||||
id: 2,
|
||||
description: "Another spec"
|
||||
};
|
||||
|
||||
reporter.specDone(specResult1);
|
||||
reporter.specDone(specResult2);
|
||||
});
|
||||
|
||||
it("should return a slice of results", function() {
|
||||
expect(reporter.specResults(0, 1)).toEqual([specResult1]);
|
||||
expect(reporter.specResults(1, 1)).toEqual([specResult2]);
|
||||
});
|
||||
|
||||
describe("when the results do not exist", function() {
|
||||
it("should return a slice of shorter length", function() {
|
||||
expect(reporter.specResults(0, 3)).toEqual([specResult1, specResult2]);
|
||||
expect(reporter.specResults(2, 3)).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("#executionTime", function() {
|
||||
it("should start the timer when jasmine starts", function() {
|
||||
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
|
||||
reporter = new j$.JsApiReporter({
|
||||
timer: timerSpy
|
||||
});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
expect(timerSpy.start).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should return the time it took the specs to run, in ms", function() {
|
||||
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
|
||||
reporter = new j$.JsApiReporter({
|
||||
timer: timerSpy
|
||||
});
|
||||
|
||||
timerSpy.elapsed.and.callReturn(1000);
|
||||
reporter.jasmineDone();
|
||||
expect(reporter.executionTime()).toEqual(1000);
|
||||
});
|
||||
|
||||
describe("when the specs haven't finished being run", function() {
|
||||
it("should return undefined", function() {
|
||||
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
|
||||
reporter = new j$.JsApiReporter({
|
||||
timer: timerSpy
|
||||
});
|
||||
|
||||
expect(reporter.executionTime()).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
64
spec/core/ObjectContainingSpec.js
Normal file
@@ -0,0 +1,64 @@
|
||||
describe("ObjectContaining", function() {
|
||||
|
||||
it("matches any actual to an empty object", function() {
|
||||
var containing = new j$.ObjectContaining({});
|
||||
|
||||
expect(containing.jasmineMatches("foo")).toBe(true);
|
||||
});
|
||||
|
||||
it("does not match an empty object actual", function() {
|
||||
var containing = new j$.ObjectContaining("foo");
|
||||
|
||||
expect(function() {
|
||||
containing.jasmineMatches({})
|
||||
}).toThrowError(/not 'foo'/)
|
||||
});
|
||||
|
||||
it("matches when the key/value pair is present in the actual", function() {
|
||||
var containing = new j$.ObjectContaining({foo: "fooVal"});
|
||||
|
||||
expect(containing.jasmineMatches({foo: "fooVal", bar: "barVal"})).toBe(true);
|
||||
});
|
||||
|
||||
it("does not match when the key/value pair is not present in the actual", function() {
|
||||
var containing = new j$.ObjectContaining({foo: "fooVal"});
|
||||
|
||||
expect(containing.jasmineMatches({bar: "barVal", quux: "quuxVal"})).toBe(false);
|
||||
});
|
||||
|
||||
it("does not match when the key is present but the value is different in the actual", function() {
|
||||
var containing = new j$.ObjectContaining({foo: "other"});
|
||||
|
||||
expect(containing.jasmineMatches({foo: "fooVal", bar: "barVal"})).toBe(false);
|
||||
});
|
||||
|
||||
it("mismatchValues parameter must return array with mismatched reason", function() {
|
||||
var containing = new j$.ObjectContaining({foo: "other"});
|
||||
|
||||
var mismatchKeys = [];
|
||||
var mismatchValues = [];
|
||||
|
||||
containing.jasmineMatches({foo: "fooVal", bar: "barVal"}, mismatchKeys, mismatchValues);
|
||||
|
||||
expect(mismatchValues.length).toBe(1);
|
||||
expect(mismatchValues[0]).toEqual("'foo' was 'fooVal' in actual, but was 'other' in expected.");
|
||||
});
|
||||
|
||||
it("adds keys in expected but not actual to the mismatchKeys parameter", function() {
|
||||
var containing = new j$.ObjectContaining({foo: "fooVal"});
|
||||
|
||||
var mismatchKeys = [];
|
||||
var mismatchValues = [];
|
||||
|
||||
containing.jasmineMatches({bar: "barVal"}, mismatchKeys, mismatchValues);
|
||||
|
||||
expect(mismatchKeys.length).toBe(1);
|
||||
expect(mismatchKeys[0]).toEqual("expected has key 'foo', but missing from actual.");
|
||||
});
|
||||
|
||||
it("jasmineToString's itself", function() {
|
||||
var containing = new j$.ObjectContaining({});
|
||||
|
||||
expect(containing.jasmineToString()).toMatch("<jasmine.objectContaining");
|
||||
});
|
||||
});
|
||||
125
spec/core/PrettyPrintSpec.js
Normal file
@@ -0,0 +1,125 @@
|
||||
describe("j$.pp", function () {
|
||||
it("should wrap strings in single quotes", function() {
|
||||
expect(j$.pp("some string")).toEqual("'some string'");
|
||||
expect(j$.pp("som' string")).toEqual("'som' string'");
|
||||
});
|
||||
|
||||
it("should stringify primitives properly", function() {
|
||||
expect(j$.pp(true)).toEqual("true");
|
||||
expect(j$.pp(false)).toEqual("false");
|
||||
expect(j$.pp(null)).toEqual("null");
|
||||
expect(j$.pp(jasmine.undefined)).toEqual("undefined");
|
||||
expect(j$.pp(3)).toEqual("3");
|
||||
expect(j$.pp(-3.14)).toEqual("-3.14");
|
||||
});
|
||||
|
||||
it("should stringify arrays properly", function() {
|
||||
expect(j$.pp([1, 2])).toEqual("[ 1, 2 ]");
|
||||
expect(j$.pp([1, 'foo', {}, jasmine.undefined, null])).toEqual("[ 1, 'foo', { }, undefined, null ]");
|
||||
});
|
||||
|
||||
it("should indicate circular array references", function() {
|
||||
var array1 = [1, 2];
|
||||
var array2 = [array1];
|
||||
array1.push(array2);
|
||||
expect(j$.pp(array1)).toEqual("[ 1, 2, [ <circular reference: Array> ] ]");
|
||||
});
|
||||
|
||||
it("should stringify objects properly", function() {
|
||||
expect(j$.pp({foo: 'bar'})).toEqual("{ foo : 'bar' }");
|
||||
expect(j$.pp({foo:'bar', baz:3, nullValue: null, undefinedValue: jasmine.undefined})).toEqual("{ foo : 'bar', baz : 3, nullValue : null, undefinedValue : undefined }");
|
||||
expect(j$.pp({foo: function () {
|
||||
}, bar: [1, 2, 3]})).toEqual("{ foo : Function, bar : [ 1, 2, 3 ] }");
|
||||
});
|
||||
|
||||
it("should not include inherited properties when stringifying an object", function() {
|
||||
var SomeClass = function() {};
|
||||
SomeClass.prototype.foo = "inherited foo";
|
||||
var instance = new SomeClass();
|
||||
instance.bar = "my own bar";
|
||||
expect(j$.pp(instance)).toEqual("{ bar : 'my own bar' }");
|
||||
});
|
||||
|
||||
it("should not recurse objects and arrays more deeply than j$.MAX_PRETTY_PRINT_DEPTH", function() {
|
||||
var originalMaxDepth = j$.MAX_PRETTY_PRINT_DEPTH;
|
||||
var nestedObject = { level1: { level2: { level3: { level4: "leaf" } } } };
|
||||
var nestedArray = [1, [2, [3, [4, "leaf"]]]];
|
||||
|
||||
try {
|
||||
j$.MAX_PRETTY_PRINT_DEPTH = 2;
|
||||
expect(j$.pp(nestedObject)).toEqual("{ level1 : { level2 : Object } }");
|
||||
expect(j$.pp(nestedArray)).toEqual("[ 1, [ 2, Array ] ]");
|
||||
|
||||
j$.MAX_PRETTY_PRINT_DEPTH = 3;
|
||||
expect(j$.pp(nestedObject)).toEqual("{ level1 : { level2 : { level3 : Object } } }");
|
||||
expect(j$.pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, Array ] ] ]");
|
||||
|
||||
j$.MAX_PRETTY_PRINT_DEPTH = 4;
|
||||
expect(j$.pp(nestedObject)).toEqual("{ level1 : { level2 : { level3 : { level4 : 'leaf' } } } }");
|
||||
expect(j$.pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, [ 4, 'leaf' ] ] ] ]");
|
||||
} finally {
|
||||
j$.MAX_PRETTY_PRINT_DEPTH = originalMaxDepth;
|
||||
}
|
||||
});
|
||||
|
||||
it("should stringify RegExp objects properly", function() {
|
||||
expect(j$.pp(/x|y|z/)).toEqual("/x|y|z/");
|
||||
});
|
||||
|
||||
it("should indicate circular object references", function() {
|
||||
var sampleValue = {foo: 'hello'};
|
||||
sampleValue.nested = sampleValue;
|
||||
expect(j$.pp(sampleValue)).toEqual("{ foo : 'hello', nested : <circular reference: Object> }");
|
||||
});
|
||||
|
||||
it("should indicate getters on objects as such", function() {
|
||||
var sampleValue = {id: 1};
|
||||
if (sampleValue.__defineGetter__) {
|
||||
//not supported in IE!
|
||||
sampleValue.__defineGetter__('calculatedValue', function() {
|
||||
throw new Error("don't call me!");
|
||||
});
|
||||
}
|
||||
if (sampleValue.__defineGetter__) {
|
||||
expect(j$.pp(sampleValue)).toEqual("{ id : 1, calculatedValue : <getter> }");
|
||||
}
|
||||
else {
|
||||
expect(j$.pp(sampleValue)).toEqual("{ id : 1 }");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
it('should not do HTML escaping of strings', function() {
|
||||
expect(j$.pp('some <b>html string</b> &', false)).toEqual('\'some <b>html string</b> &\'');
|
||||
});
|
||||
|
||||
it("should abbreviate the global (usually window) object", function() {
|
||||
expect(j$.pp(jasmine.getGlobal())).toEqual("<global>");
|
||||
});
|
||||
|
||||
it("should stringify Date objects properly", function() {
|
||||
var now = new Date();
|
||||
expect(j$.pp(now)).toEqual("Date(" + now.toString() + ")");
|
||||
});
|
||||
|
||||
it("should stringify spy objects properly", function() {
|
||||
var TestObject = {
|
||||
someFunction: function() {}
|
||||
},
|
||||
env = new j$.Env();
|
||||
|
||||
env.spyOn(TestObject, 'someFunction');
|
||||
expect(j$.pp(TestObject.someFunction)).toEqual("spy on someFunction");
|
||||
|
||||
expect(j$.pp(j$.createSpy("something"))).toEqual("spy on something");
|
||||
});
|
||||
|
||||
it("should stringify objects that implement jasmineToString", function () {
|
||||
var obj = {
|
||||
jasmineToString: function () { return "strung"; }
|
||||
};
|
||||
|
||||
expect(j$.pp(obj)).toEqual("strung");
|
||||
});
|
||||
});
|
||||
|
||||
147
spec/core/QueueRunnerSpec.js
Normal file
@@ -0,0 +1,147 @@
|
||||
describe("QueueRunner", function() {
|
||||
|
||||
it("runs all the functions it's passed", function() {
|
||||
var calls = [],
|
||||
fn1 = jasmine.createSpy('fn1'),
|
||||
fn2 = jasmine.createSpy('fn2'),
|
||||
queueRunner = new j$.QueueRunner({
|
||||
fns: [fn1, fn2]
|
||||
});
|
||||
fn1.and.callFake(function() {
|
||||
calls.push('fn1');
|
||||
});
|
||||
fn2.and.callFake(function() {
|
||||
calls.push('fn2');
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
|
||||
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) {});
|
||||
|
||||
var onComplete = jasmine.createSpy('onComplete'),
|
||||
beforeCallback = jasmine.createSpy('beforeCallback'),
|
||||
fnCallback = jasmine.createSpy('fnCallback'),
|
||||
afterCallback = jasmine.createSpy('afterCallback'),
|
||||
fn1 = function(done) {
|
||||
beforeCallback();
|
||||
setTimeout(function() {
|
||||
done()
|
||||
}, 100);
|
||||
},
|
||||
fn2 = function(done) {
|
||||
fnCallback();
|
||||
setTimeout(function() {
|
||||
done()
|
||||
}, 100);
|
||||
},
|
||||
fn3 = function(done) {
|
||||
afterCallback();
|
||||
setTimeout(function() {
|
||||
done()
|
||||
}, 100);
|
||||
},
|
||||
queueRunner = new j$.QueueRunner({
|
||||
fns: [fn1, fn2, fn3],
|
||||
onComplete: onComplete
|
||||
});
|
||||
|
||||
clock.install();
|
||||
|
||||
queueRunner.execute();
|
||||
|
||||
expect(beforeCallback).toHaveBeenCalled();
|
||||
expect(fnCallback).not.toHaveBeenCalled();
|
||||
expect(afterCallback).not.toHaveBeenCalled();
|
||||
expect(onComplete).not.toHaveBeenCalled();
|
||||
|
||||
clock.tick(100);
|
||||
|
||||
expect(fnCallback).toHaveBeenCalled();
|
||||
expect(afterCallback).not.toHaveBeenCalled();
|
||||
expect(onComplete).not.toHaveBeenCalled();
|
||||
|
||||
clock.tick(100);
|
||||
|
||||
expect(afterCallback).toHaveBeenCalled();
|
||||
expect(onComplete).not.toHaveBeenCalled();
|
||||
|
||||
clock.tick(100);
|
||||
|
||||
expect(onComplete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls an exception handler when an exception is thrown in a fn", function() {
|
||||
var fn = function() {
|
||||
throw new Error('fake error');
|
||||
},
|
||||
exceptionCallback = jasmine.createSpy('exception callback'),
|
||||
queueRunner = new j$.QueueRunner({
|
||||
fns: [fn],
|
||||
onException: exceptionCallback
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
|
||||
expect(exceptionCallback).toHaveBeenCalledWith(jasmine.any(Error));
|
||||
});
|
||||
|
||||
it("rethrows an exception if told to", function() {
|
||||
var fn = function() {
|
||||
throw new Error('fake error');
|
||||
},
|
||||
queueRunner = new j$.QueueRunner({
|
||||
fns: [fn],
|
||||
catchException: function(e) { return false; }
|
||||
});
|
||||
|
||||
expect(function() { queueRunner.execute(); }).toThrow();
|
||||
});
|
||||
|
||||
it("continues running the functions even after an exception is thrown in an async spec", function() {
|
||||
var fn = function(done) { throw new Error("error"); },
|
||||
nextFn = jasmine.createSpy("nextFunction");
|
||||
|
||||
queueRunner = new j$.QueueRunner({
|
||||
fns: [fn, nextFn]
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
expect(nextFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls a provided complete callback when done", function() {
|
||||
var fn = jasmine.createSpy('fn'),
|
||||
completeCallback = jasmine.createSpy('completeCallback'),
|
||||
queueRunner = new j$.QueueRunner({
|
||||
fns: [fn],
|
||||
onComplete: completeCallback
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
|
||||
expect(completeCallback).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls a provided stack clearing function when done", function() {
|
||||
var asyncFn = function(done) { done() },
|
||||
afterFn = jasmine.createSpy('afterFn'),
|
||||
completeCallback = jasmine.createSpy('completeCallback'),
|
||||
clearStack = jasmine.createSpy('clearStack'),
|
||||
queueRunner = new j$.QueueRunner({
|
||||
fns: [asyncFn, afterFn],
|
||||
clearStack: clearStack,
|
||||
onComplete: completeCallback
|
||||
});
|
||||
|
||||
clearStack.and.callFake(function(fn) { fn(); });
|
||||
|
||||
queueRunner.execute();
|
||||
expect(afterFn).toHaveBeenCalled();
|
||||
expect(clearStack).toHaveBeenCalledWith(completeCallback);
|
||||
});
|
||||
});
|
||||
40
spec/core/ReportDispatcherSpec.js
Normal file
@@ -0,0 +1,40 @@
|
||||
describe("ReportDispatcher", function() {
|
||||
|
||||
it("builds an interface of requested methods", function() {
|
||||
var dispatcher = new j$.ReportDispatcher(['foo', 'bar', 'baz']);
|
||||
|
||||
expect(dispatcher.foo).toBeDefined();
|
||||
expect(dispatcher.bar).toBeDefined();
|
||||
expect(dispatcher.baz).toBeDefined();
|
||||
});
|
||||
|
||||
it("dispatches requested methods to added reporters", function() {
|
||||
var dispatcher = new j$.ReportDispatcher(['foo', 'bar']),
|
||||
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
|
||||
anotherReporter = jasmine.createSpyObj('reporter', ['foo', 'bar']);
|
||||
|
||||
dispatcher.addReporter(reporter);
|
||||
dispatcher.addReporter(anotherReporter);
|
||||
|
||||
dispatcher.foo(123, 456);
|
||||
|
||||
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
|
||||
expect(anotherReporter.foo).toHaveBeenCalledWith(123, 456);
|
||||
|
||||
dispatcher.bar('a', 'b');
|
||||
|
||||
expect(reporter.bar).toHaveBeenCalledWith('a', 'b');
|
||||
expect(anotherReporter.bar).toHaveBeenCalledWith('a', 'b');
|
||||
});
|
||||
|
||||
it("does not dispatch to a reporter if the reporter doesn't accept the method", function() {
|
||||
var dispatcher = new j$.ReportDispatcher(['foo']),
|
||||
reporter = jasmine.createSpyObj('reporter', ['baz']);
|
||||
|
||||
dispatcher.addReporter(reporter);
|
||||
|
||||
expect(function() {
|
||||
dispatcher.foo(123, 456);
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
308
spec/core/SpecRunningSpec.js
Normal file
@@ -0,0 +1,308 @@
|
||||
// TODO: This should really be part of the Env Integration Spec
|
||||
describe("jasmine spec running", function () {
|
||||
var env;
|
||||
var fakeTimer;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new j$.Env();
|
||||
env.updateInterval = 0;
|
||||
});
|
||||
|
||||
it('should assign spec ids sequentially', function() {
|
||||
var it0, it1, it2, it3, it4;
|
||||
env.describe('test suite', function() {
|
||||
it0 = env.it('spec 0', function() {
|
||||
});
|
||||
it1 = env.it('spec 1', function() {
|
||||
});
|
||||
it2 = env.xit('spec 2', function() {
|
||||
});
|
||||
it3 = env.it('spec 3', function() {
|
||||
});
|
||||
});
|
||||
env.describe('test suite 2', function() {
|
||||
it4 = env.it('spec 4', 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);
|
||||
});
|
||||
|
||||
it('nested suites', function (done) {
|
||||
|
||||
var foo = 0;
|
||||
var bar = 0;
|
||||
var baz = 0;
|
||||
var quux = 0;
|
||||
var nested = env.describe('suite', function () {
|
||||
env.describe('nested', function () {
|
||||
env.it('should run nested suites', function () {
|
||||
foo++;
|
||||
});
|
||||
env.it('should run nested suites', function () {
|
||||
bar++;
|
||||
});
|
||||
});
|
||||
|
||||
env.describe('nested 2', function () {
|
||||
env.it('should run suites following nested suites', function () {
|
||||
baz++;
|
||||
});
|
||||
});
|
||||
|
||||
env.it('should run tests following nested suites', function () {
|
||||
quux++;
|
||||
});
|
||||
});
|
||||
|
||||
expect(foo).toEqual(0);
|
||||
expect(bar).toEqual(0);
|
||||
expect(baz).toEqual(0);
|
||||
expect(quux).toEqual(0);
|
||||
nested.execute(function() {
|
||||
expect(foo).toEqual(1);
|
||||
expect(bar).toEqual(1);
|
||||
expect(baz).toEqual(1);
|
||||
expect(quux).toEqual(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should permit nested describes", function(done) {
|
||||
var actions = [];
|
||||
|
||||
env.beforeEach(function () {
|
||||
actions.push('topSuite beforeEach');
|
||||
});
|
||||
|
||||
env.afterEach(function () {
|
||||
actions.push('topSuite afterEach');
|
||||
});
|
||||
|
||||
env.describe('Something', function() {
|
||||
env.beforeEach(function() {
|
||||
actions.push('outer beforeEach');
|
||||
});
|
||||
|
||||
env.afterEach(function() {
|
||||
actions.push('outer afterEach');
|
||||
});
|
||||
|
||||
env.it('does it 1', function() {
|
||||
actions.push('outer it 1');
|
||||
});
|
||||
|
||||
env.describe('Inner 1', function() {
|
||||
env.beforeEach(function() {
|
||||
actions.push('inner 1 beforeEach');
|
||||
});
|
||||
|
||||
env.afterEach(function() {
|
||||
actions.push('inner 1 afterEach');
|
||||
});
|
||||
|
||||
env.it('does it 2', function() {
|
||||
actions.push('inner 1 it');
|
||||
});
|
||||
});
|
||||
|
||||
env.it('does it 3', function() {
|
||||
actions.push('outer it 2');
|
||||
});
|
||||
|
||||
env.describe('Inner 2', function() {
|
||||
env.beforeEach(function() {
|
||||
actions.push('inner 2 beforeEach');
|
||||
});
|
||||
|
||||
env.afterEach(function() {
|
||||
actions.push('inner 2 afterEach');
|
||||
});
|
||||
|
||||
env.it('does it 2', function() {
|
||||
actions.push('inner 2 it');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var assertions = function() {
|
||||
var expected = [
|
||||
"topSuite beforeEach",
|
||||
"outer beforeEach",
|
||||
"outer it 1",
|
||||
"outer afterEach",
|
||||
"topSuite afterEach",
|
||||
|
||||
"topSuite beforeEach",
|
||||
"outer beforeEach",
|
||||
"inner 1 beforeEach",
|
||||
"inner 1 it",
|
||||
"inner 1 afterEach",
|
||||
"outer afterEach",
|
||||
"topSuite afterEach",
|
||||
|
||||
"topSuite beforeEach",
|
||||
"outer beforeEach",
|
||||
"outer it 2",
|
||||
"outer afterEach",
|
||||
"topSuite afterEach",
|
||||
|
||||
"topSuite beforeEach",
|
||||
"outer beforeEach",
|
||||
"inner 2 beforeEach",
|
||||
"inner 2 it",
|
||||
"inner 2 afterEach",
|
||||
"outer afterEach",
|
||||
"topSuite afterEach"
|
||||
];
|
||||
expect(actions).toEqual(expected);
|
||||
done();
|
||||
}
|
||||
|
||||
env.addReporter({jasmineDone: assertions});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("should run multiple befores and afters in the order they are declared", function(done) {
|
||||
var actions = [];
|
||||
|
||||
env.beforeEach(function () {
|
||||
actions.push('runner beforeEach1');
|
||||
});
|
||||
|
||||
env.afterEach(function () {
|
||||
actions.push('runner afterEach1');
|
||||
});
|
||||
|
||||
env.beforeEach(function () {
|
||||
actions.push('runner beforeEach2');
|
||||
});
|
||||
|
||||
env.afterEach(function () {
|
||||
actions.push('runner afterEach2');
|
||||
});
|
||||
|
||||
env.describe('Something', function() {
|
||||
env.beforeEach(function() {
|
||||
actions.push('beforeEach1');
|
||||
});
|
||||
|
||||
env.afterEach(function() {
|
||||
actions.push('afterEach1');
|
||||
});
|
||||
|
||||
env.beforeEach(function() {
|
||||
actions.push('beforeEach2');
|
||||
});
|
||||
|
||||
env.afterEach(function() {
|
||||
actions.push('afterEach2');
|
||||
});
|
||||
|
||||
env.it('does it 1', function() {
|
||||
actions.push('outer it 1');
|
||||
});
|
||||
});
|
||||
|
||||
var assertions = function() {
|
||||
var expected = [
|
||||
"runner beforeEach1",
|
||||
"runner beforeEach2",
|
||||
"beforeEach1",
|
||||
"beforeEach2",
|
||||
"outer it 1",
|
||||
"afterEach2",
|
||||
"afterEach1",
|
||||
"runner afterEach2",
|
||||
"runner afterEach1"
|
||||
];
|
||||
expect(actions).toEqual(expected);
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({jasmineDone: assertions});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("shouldn't run disabled suites", function(done) {
|
||||
var specInADisabledSuite = jasmine.createSpy("specInADisabledSuite"),
|
||||
suite = env.describe('A Suite', function() {
|
||||
env.xdescribe('with a disabled suite', function(){
|
||||
env.it('spec inside a disabled suite', specInADisabledSuite);
|
||||
});
|
||||
});
|
||||
|
||||
suite.execute(function() {
|
||||
expect(specInADisabledSuite).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should set all pending specs to pending when a suite is run", function(done) {
|
||||
var pendingSpec,
|
||||
suite = env.describe('default current suite', function() {
|
||||
pendingSpec = env.it("I am a pending spec");
|
||||
});
|
||||
|
||||
suite.execute(function() {
|
||||
expect(pendingSpec.status()).toBe("pending");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// TODO: is this useful? It doesn't catch syntax errors
|
||||
xit("should recover gracefully when there are errors in describe functions", function() {
|
||||
var specs = [];
|
||||
var superSimpleReporter = new j$.Reporter();
|
||||
superSimpleReporter.reportSpecResults = function(result) {
|
||||
specs.push("Spec: " + result.fullName);
|
||||
};
|
||||
|
||||
try {
|
||||
env.describe("outer1", function() {
|
||||
env.describe("inner1", function() {
|
||||
env.it("should thingy", function() {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
|
||||
throw new Error("fake error");
|
||||
});
|
||||
|
||||
env.describe("inner2", function() {
|
||||
env.it("should other thingy", function() {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
throw new Error("fake error");
|
||||
|
||||
});
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
env.describe("outer2", function() {
|
||||
env.it("should xxx", function() {
|
||||
this.expect(true).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
env.addReporter(superSimpleReporter);
|
||||
env.execute();
|
||||
|
||||
expect(specs.join('')).toMatch(new RegExp(
|
||||
'Spec: outer1 inner1 should thingy.' +
|
||||
'Spec: outer1 inner1 encountered a declaration exception.' +
|
||||
'Spec: outer1 inner2 should other thingy.' +
|
||||
'Spec: outer1 encountered a declaration exception.' +
|
||||
'Spec: outer2 should xxx.'
|
||||
));
|
||||
|
||||
});
|
||||
});
|
||||
244
spec/core/SpecSpec.js
Normal file
@@ -0,0 +1,244 @@
|
||||
describe("Spec", function() {
|
||||
|
||||
it("#isPendingSpecException returns true for a pending spec exception", function() {
|
||||
var e = new Error(j$.Spec.pendingSpecExceptionMessage);
|
||||
|
||||
expect(j$.Spec.isPendingSpecException(e)).toBe(true);
|
||||
});
|
||||
|
||||
it("#isPendingSpecException returns true for a pending spec exception (even when FF bug is present)", function() {
|
||||
var fakeError = {
|
||||
toString: function() { return "Error: " + j$.Spec.pendingSpecExceptionMessage; }
|
||||
};
|
||||
|
||||
expect(j$.Spec.isPendingSpecException(fakeError)).toBe(true);
|
||||
});
|
||||
|
||||
it("#isPendingSpecException returns true for a pending spec exception", function() {
|
||||
var e = new Error("foo");
|
||||
|
||||
expect(j$.Spec.isPendingSpecException(e)).toBe(false);
|
||||
});
|
||||
|
||||
it("delegates execution to a QueueRunner", function() {
|
||||
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
|
||||
spec = new j$.Spec({
|
||||
description: 'my test',
|
||||
id: 'some-id',
|
||||
fn: function() {},
|
||||
queueRunner: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
|
||||
expect(fakeQueueRunner).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
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,
|
||||
description: 'foo bar',
|
||||
fn: function() {},
|
||||
onStart: startCallback,
|
||||
queueRunner: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
|
||||
expect(startCallback).toHaveBeenCalledWith(spec);
|
||||
});
|
||||
|
||||
it("should call the start callback on execution but before any befores are called", function() {
|
||||
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
|
||||
beforesWereCalled = false,
|
||||
startCallback = jasmine.createSpy('start-callback').and.callFake(function() {
|
||||
expect(beforesWereCalled).toBe(false);
|
||||
}),
|
||||
spec = new j$.Spec({
|
||||
fn: function() {},
|
||||
beforeFns: function() {
|
||||
return [function() {
|
||||
beforesWereCalled = true
|
||||
}]
|
||||
},
|
||||
onStart: startCallback,
|
||||
queueRunner: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
|
||||
expect(startCallback).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("provides all before fns and after fns to be run", function() {
|
||||
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
|
||||
before = jasmine.createSpy('before'),
|
||||
after = jasmine.createSpy('after'),
|
||||
fn = jasmine.createSpy('test body').and.callFake(function() {
|
||||
expect(before).toHaveBeenCalled();
|
||||
expect(after).not.toHaveBeenCalled();
|
||||
}),
|
||||
spec = new j$.Spec({
|
||||
fn: fn,
|
||||
beforeFns: function() {
|
||||
return [before]
|
||||
},
|
||||
afterFns: function() {
|
||||
return [after]
|
||||
},
|
||||
queueRunner: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
|
||||
var allSpecFns = fakeQueueRunner.calls.mostRecent().args[0].fns;
|
||||
expect(allSpecFns).toEqual([before, fn, after]);
|
||||
});
|
||||
|
||||
it("is marked pending if created without a function body", function() {
|
||||
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
|
||||
|
||||
startCallback = jasmine.createSpy('startCallback'),
|
||||
resultCallback = jasmine.createSpy('resultCallback'),
|
||||
spec = new j$.Spec({
|
||||
onStart: startCallback,
|
||||
fn: null,
|
||||
resultCallback: resultCallback,
|
||||
queueRunner: fakeQueueRunner
|
||||
});
|
||||
|
||||
|
||||
expect(spec.status()).toBe('pending');
|
||||
});
|
||||
|
||||
it("can be disabled, but still calls callbacks", function() {
|
||||
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
|
||||
startCallback = jasmine.createSpy('startCallback'),
|
||||
specBody = jasmine.createSpy('specBody'),
|
||||
resultCallback = jasmine.createSpy('resultCallback'),
|
||||
spec = new j$.Spec({
|
||||
onStart:startCallback,
|
||||
fn: specBody,
|
||||
resultCallback: resultCallback,
|
||||
queueRunner: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.disable();
|
||||
|
||||
expect(spec.status()).toBe('disabled');
|
||||
|
||||
spec.execute();
|
||||
|
||||
expect(fakeQueueRunner).not.toHaveBeenCalled();
|
||||
expect(specBody).not.toHaveBeenCalled();
|
||||
|
||||
expect(startCallback).toHaveBeenCalled();
|
||||
expect(resultCallback).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("can be marked pending, but still calls callbacks when executed", function() {
|
||||
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
|
||||
startCallback = jasmine.createSpy('startCallback'),
|
||||
resultCallback = jasmine.createSpy('resultCallback'),
|
||||
spec = new j$.Spec({
|
||||
onStart: startCallback,
|
||||
resultCallback: resultCallback,
|
||||
description: "with a spec",
|
||||
getSpecName: function() {
|
||||
return "a suite with a spec"
|
||||
},
|
||||
queueRunner: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.pend();
|
||||
|
||||
expect(spec.status()).toBe('pending');
|
||||
|
||||
spec.execute();
|
||||
|
||||
expect(fakeQueueRunner).not.toHaveBeenCalled();
|
||||
|
||||
expect(startCallback).toHaveBeenCalled();
|
||||
expect(resultCallback).toHaveBeenCalledWith({
|
||||
id: spec.id,
|
||||
status: 'pending',
|
||||
description: 'with a spec',
|
||||
fullName: 'a suite with a spec',
|
||||
failedExpectations: []
|
||||
});
|
||||
});
|
||||
|
||||
it("should call the done callback on execution complete", function() {
|
||||
var done = jasmine.createSpy('done callback'),
|
||||
spec = new j$.Spec({
|
||||
fn: function() {},
|
||||
catchExceptions: function() { return false; },
|
||||
resultCallback: function() {},
|
||||
queueRunner: function(attrs) { attrs.onComplete(); }
|
||||
});
|
||||
|
||||
spec.execute(done);
|
||||
|
||||
expect(done).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("#status returns pending 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');
|
||||
});
|
||||
|
||||
it("#status returns passed if all expectations in the spec have passed", function() {
|
||||
var spec = new j$.Spec({fn: jasmine.createSpy("spec body")});
|
||||
spec.addExpectationResult(true);
|
||||
expect(spec.status()).toBe('passed');
|
||||
});
|
||||
|
||||
it("#status returns failed if any expectations in the spec have failed", function() {
|
||||
var spec = new j$.Spec({ fn: jasmine.createSpy("spec body") });
|
||||
spec.addExpectationResult(true);
|
||||
spec.addExpectationResult(false);
|
||||
expect(spec.status()).toBe('failed');
|
||||
});
|
||||
|
||||
it("can return its full name", function() {
|
||||
var spec;
|
||||
spec = new j$.Spec({
|
||||
getSpecName: function(passedVal) {
|
||||
// expect(passedVal).toBe(spec); TODO: a exec time, spec is undefined WTF?
|
||||
return 'expected val';
|
||||
}
|
||||
});
|
||||
|
||||
expect(spec.getFullName()).toBe('expected val');
|
||||
});
|
||||
|
||||
describe("when a spec is marked pending during execution", function() {
|
||||
it("should mark the spec as pending", function() {
|
||||
var fakeQueueRunner = function(opts) {
|
||||
opts.onException(new Error(j$.Spec.pendingSpecExceptionMessage));
|
||||
},
|
||||
spec = new j$.Spec({
|
||||
description: 'my test',
|
||||
id: 'some-id',
|
||||
fn: function() { },
|
||||
queueRunner: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
|
||||
expect(spec.status()).toEqual("pending");
|
||||
});
|
||||
});
|
||||
});
|
||||
48
spec/core/SpySpec.js
Normal file
@@ -0,0 +1,48 @@
|
||||
describe('Spies', function () {
|
||||
describe("createSpy", function() {
|
||||
var TestClass;
|
||||
|
||||
beforeEach(function() {
|
||||
TestClass = function() {};
|
||||
TestClass.prototype.someFunction = function() {};
|
||||
TestClass.prototype.someFunction.bob = "test";
|
||||
});
|
||||
|
||||
it("preserves the properties of the spied function", function() {
|
||||
var spy = j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
|
||||
expect(spy.bob).toEqual("test");
|
||||
});
|
||||
|
||||
it("warns the user that we indend to overwrite an existing property", function() {
|
||||
TestClass.prototype.someFunction.and = "turkey";
|
||||
|
||||
expect(function() {
|
||||
j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
}).toThrowError("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
|
||||
});
|
||||
|
||||
it("adds a spyStrategy and callTracker to the spy", function() {
|
||||
var spy = j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
|
||||
expect(spy.and).toEqual(jasmine.any(j$.SpyStrategy));
|
||||
expect(spy.calls).toEqual(jasmine.any(j$.CallTracker));
|
||||
});
|
||||
});
|
||||
|
||||
describe("createSpyObj", function() {
|
||||
it("should create an object with a bunch of spy methods when you call jasmine.createSpyObj()", function() {
|
||||
var spyObj = j$.createSpyObj('BaseName', ['method1', 'method2']);
|
||||
|
||||
expect(spyObj).toEqual({ method1: jasmine.any(Function), method2: jasmine.any(Function)});
|
||||
expect(spyObj.method1.and.identity()).toEqual('BaseName.method1');
|
||||
expect(spyObj.method2.and.identity()).toEqual('BaseName.method2');
|
||||
});
|
||||
|
||||
it("should throw if you do not pass an array argument", function() {
|
||||
expect(function() {
|
||||
j$.createSpyObj('BaseName');
|
||||
}).toThrow("createSpyObj requires a non-empty array of method names to create spies for");
|
||||
});
|
||||
});
|
||||
});
|
||||
101
spec/core/SpyStrategySpec.js
Normal file
@@ -0,0 +1,101 @@
|
||||
describe("SpyStrategy", function() {
|
||||
|
||||
it("defaults its name to unknown", function() {
|
||||
var spyStrategy = new j$.SpyStrategy();
|
||||
|
||||
expect(spyStrategy.identity()).toEqual("unknown");
|
||||
});
|
||||
|
||||
it("takes a name", function() {
|
||||
var spyStrategy = new j$.SpyStrategy({name: "foo"});
|
||||
|
||||
expect(spyStrategy.identity()).toEqual("foo");
|
||||
});
|
||||
|
||||
it("stubs an original function, if provided", function() {
|
||||
var originalFn = jasmine.createSpy("original"),
|
||||
spyStrategy = new j$.SpyStrategy({fn: originalFn});
|
||||
|
||||
spyStrategy.exec();
|
||||
|
||||
expect(originalFn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
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),
|
||||
spyStrategy = new j$.SpyStrategy({fn: originalFn}),
|
||||
returnValue;
|
||||
|
||||
spyStrategy.callThrough();
|
||||
returnValue = spyStrategy.exec("foo");
|
||||
|
||||
expect(originalFn).toHaveBeenCalled();
|
||||
expect(originalFn.calls.mostRecent().args).toEqual(["foo"]);
|
||||
expect(returnValue).toEqual(42);
|
||||
});
|
||||
|
||||
it("can return a specified value when executed", function() {
|
||||
var originalFn = jasmine.createSpy("original"),
|
||||
spyStrategy = new j$.SpyStrategy({fn: originalFn}),
|
||||
returnValue;
|
||||
|
||||
spyStrategy.callReturn(17);
|
||||
returnValue = spyStrategy.exec();
|
||||
|
||||
expect(originalFn).not.toHaveBeenCalled();
|
||||
expect(returnValue).toEqual(17);
|
||||
});
|
||||
|
||||
it("allows an exception to be thrown when executed", function() {
|
||||
var originalFn = jasmine.createSpy("original"),
|
||||
spyStrategy = new j$.SpyStrategy({fn: originalFn});
|
||||
|
||||
spyStrategy.callThrow("bar");
|
||||
|
||||
expect(function() { spyStrategy.exec(); }).toThrow("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),
|
||||
spyStrategy = new j$.SpyStrategy({fn: originalFn}),
|
||||
returnValue;
|
||||
|
||||
spyStrategy.callFake(fakeFn);
|
||||
returnValue = spyStrategy.exec();
|
||||
|
||||
expect(originalFn).not.toHaveBeenCalled();
|
||||
expect(returnValue).toEqual(67);
|
||||
});
|
||||
|
||||
it("allows a return to plan stubbing after another strategy", function() {
|
||||
var originalFn = jasmine.createSpy("original"),
|
||||
fakeFn = jasmine.createSpy("fake").and.callReturn(67),
|
||||
spyStrategy = new j$.SpyStrategy({fn: originalFn}),
|
||||
returnValue;
|
||||
|
||||
spyStrategy.callFake(fakeFn);
|
||||
returnValue = spyStrategy.exec();
|
||||
|
||||
expect(originalFn).not.toHaveBeenCalled();
|
||||
expect(returnValue).toEqual(67);
|
||||
|
||||
spyStrategy.stub();
|
||||
returnValue = spyStrategy.exec();
|
||||
|
||||
expect(returnValue).toEqual(void 0);
|
||||
});
|
||||
|
||||
it("returns the spy after changing the strategy", function(){
|
||||
var spy = {},
|
||||
spyFn = jasmine.createSpy('spyFn').and.callReturn(spy),
|
||||
spyStrategy = new j$.SpyStrategy({getSpy: spyFn});
|
||||
|
||||
expect(spyStrategy.callThrough()).toBe(spy);
|
||||
expect(spyStrategy.callReturn()).toBe(spy);
|
||||
expect(spyStrategy.callThrow()).toBe(spy);
|
||||
expect(spyStrategy.callFake()).toBe(spy);
|
||||
expect(spyStrategy.stub()).toBe(spy);
|
||||
});
|
||||
});
|
||||
230
spec/core/SuiteSpec.js
Normal file
@@ -0,0 +1,230 @@
|
||||
describe("Suite", function() {
|
||||
|
||||
it("keeps its id", function() {
|
||||
var env = new j$.Env(),
|
||||
suite = new j$.Suite({
|
||||
env: env,
|
||||
id: 456,
|
||||
description: "I am a suite"
|
||||
});
|
||||
|
||||
expect(suite.id).toEqual(456);
|
||||
});
|
||||
|
||||
it("returns its full name", function() {
|
||||
var env = new j$.Env(),
|
||||
suite = new j$.Suite({
|
||||
env: env,
|
||||
description: "I am a suite"
|
||||
});
|
||||
|
||||
expect(suite.getFullName()).toEqual("I am a suite");
|
||||
});
|
||||
|
||||
it("returns its full name when it has parent suites", function() {
|
||||
var env = new j$.Env(),
|
||||
parentSuite = new j$.Suite({
|
||||
env: env,
|
||||
description: "I am a parent suite",
|
||||
parentSuite: jasmine.createSpy('pretend top level suite')
|
||||
}),
|
||||
suite = new j$.Suite({
|
||||
env: env,
|
||||
description: "I am a suite",
|
||||
parentSuite: parentSuite
|
||||
});
|
||||
|
||||
expect(suite.getFullName()).toEqual("I am a parent suite I am a suite");
|
||||
});
|
||||
|
||||
it("adds before functions in order of needed execution", function() {
|
||||
var env = new j$.Env(),
|
||||
suite = new j$.Suite({
|
||||
env: env,
|
||||
description: "I am a suite"
|
||||
}),
|
||||
outerBefore = jasmine.createSpy('outerBeforeEach'),
|
||||
innerBefore = jasmine.createSpy('insideBeforeEach');
|
||||
|
||||
suite.beforeEach(outerBefore);
|
||||
suite.beforeEach(innerBefore);
|
||||
|
||||
expect(suite.beforeFns).toEqual([innerBefore, outerBefore]);
|
||||
});
|
||||
|
||||
it("adds after functions in order of needed execution", function() {
|
||||
var env = new j$.Env(),
|
||||
suite = new j$.Suite({
|
||||
env: env,
|
||||
description: "I am a suite"
|
||||
}),
|
||||
outerAfter = jasmine.createSpy('outerAfterEach'),
|
||||
innerAfter = jasmine.createSpy('insideAfterEach');
|
||||
|
||||
suite.afterEach(outerAfter);
|
||||
suite.afterEach(innerAfter);
|
||||
|
||||
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'),
|
||||
suite = new j$.Suite({
|
||||
env: env,
|
||||
description: "with a child suite",
|
||||
queueRunner: fakeQueueRunner
|
||||
});
|
||||
|
||||
suite.disable();
|
||||
|
||||
expect(suite.disabled).toBe(true);
|
||||
|
||||
suite.execute();
|
||||
|
||||
expect(fakeQueueRunner).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("delegates execution of its specs and suites", function() {
|
||||
var env = new j$.Env(),
|
||||
parentSuiteDone = jasmine.createSpy('parent suite done'),
|
||||
fakeQueueRunnerForParent = jasmine.createSpy('fake parent queue runner'),
|
||||
parentSuite = new j$.Suite({
|
||||
env: env,
|
||||
description: "I am a parent suite",
|
||||
queueRunner: fakeQueueRunnerForParent
|
||||
}),
|
||||
fakeQueueRunner = jasmine.createSpy('fake queue runner'),
|
||||
suite = new j$.Suite({
|
||||
env: env,
|
||||
description: "with a child suite",
|
||||
queueRunner: fakeQueueRunner
|
||||
}),
|
||||
fakeSpec1 = {
|
||||
execute: jasmine.createSpy('fakeSpec1')
|
||||
};
|
||||
|
||||
spyOn(suite, "execute");
|
||||
|
||||
parentSuite.addSpec(fakeSpec1);
|
||||
parentSuite.addSuite(suite);
|
||||
|
||||
parentSuite.execute(parentSuiteDone);
|
||||
|
||||
var parentSuiteFns = fakeQueueRunnerForParent.calls.mostRecent().args[0].fns;
|
||||
|
||||
parentSuiteFns[0]();
|
||||
expect(fakeSpec1.execute).toHaveBeenCalled();
|
||||
parentSuiteFns[1]();
|
||||
expect(suite.execute).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls a provided onStart callback when starting", function() {
|
||||
var env = new j$.Env(),
|
||||
suiteStarted = jasmine.createSpy('suiteStarted'),
|
||||
fakeQueueRunner = function(attrs) { attrs.onComplete(); },
|
||||
suite = new j$.Suite({
|
||||
env: env,
|
||||
description: "with a child suite",
|
||||
onStart: suiteStarted,
|
||||
queueRunner: fakeQueueRunner
|
||||
}),
|
||||
fakeSpec1 = {
|
||||
execute: jasmine.createSpy('fakeSpec1')
|
||||
};
|
||||
|
||||
suite.execute();
|
||||
|
||||
expect(suiteStarted).toHaveBeenCalledWith(suite);
|
||||
});
|
||||
|
||||
it("calls a provided onComplete callback when done", function() {
|
||||
var env = new j$.Env(),
|
||||
suiteCompleted = jasmine.createSpy('parent suite done'),
|
||||
fakeQueueRunner = function(attrs) { attrs.onComplete(); },
|
||||
suite = new j$.Suite({
|
||||
env: env,
|
||||
description: "with a child suite",
|
||||
queueRunner: fakeQueueRunner
|
||||
}),
|
||||
fakeSpec1 = {
|
||||
execute: jasmine.createSpy('fakeSpec1')
|
||||
};
|
||||
|
||||
suite.execute(suiteCompleted);
|
||||
|
||||
expect(suiteCompleted).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls a provided result callback when done", function() {
|
||||
var env = new j$.Env(),
|
||||
suiteResultsCallback = jasmine.createSpy('suite result callback'),
|
||||
fakeQueueRunner = function(attrs) { attrs.onComplete(); },
|
||||
suite = new j$.Suite({
|
||||
env: env,
|
||||
description: "with a child suite",
|
||||
queueRunner: fakeQueueRunner,
|
||||
resultCallback: suiteResultsCallback
|
||||
}),
|
||||
fakeSpec1 = {
|
||||
execute: jasmine.createSpy('fakeSpec1')
|
||||
};
|
||||
|
||||
suite.execute();
|
||||
|
||||
expect(suiteResultsCallback).toHaveBeenCalledWith({
|
||||
id: suite.id,
|
||||
status: '',
|
||||
description: "with a child suite",
|
||||
fullName: "with a child suite"
|
||||
});
|
||||
});
|
||||
});
|
||||
13
spec/core/TimerSpec.js
Normal file
@@ -0,0 +1,13 @@
|
||||
describe("Timer", function() {
|
||||
it("reports the time elapsed", function() {
|
||||
var fakeNow = jasmine.createSpy('fake Date.now'),
|
||||
timer = new j$.Timer({now: fakeNow});
|
||||
|
||||
fakeNow.and.callReturn(100);
|
||||
timer.start();
|
||||
|
||||
fakeNow.and.callReturn(200);
|
||||
|
||||
expect(timer.elapsed()).toEqual(100);
|
||||
});
|
||||
});
|
||||
28
spec/core/UtilSpec.js
Normal file
@@ -0,0 +1,28 @@
|
||||
describe("j$.util", function() {
|
||||
describe("isArray_", function() {
|
||||
it("should return true if the argument is an array", function() {
|
||||
expect(j$.isArray_([])).toBe(true);
|
||||
expect(j$.isArray_(['a'])).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false if the argument is not an array", function() {
|
||||
expect(j$.isArray_(undefined)).toBe(false);
|
||||
expect(j$.isArray_({})).toBe(false);
|
||||
expect(j$.isArray_(function() {})).toBe(false);
|
||||
expect(j$.isArray_('foo')).toBe(false);
|
||||
expect(j$.isArray_(5)).toBe(false);
|
||||
expect(j$.isArray_(null)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isUndefined", function() {
|
||||
it("reports if a variable is defined", function() {
|
||||
var a;
|
||||
expect(j$.util.isUndefined(a)).toBe(true);
|
||||
expect(j$.util.isUndefined(undefined)).toBe(true);
|
||||
|
||||
var undefined = "diz be undefined yo";
|
||||
expect(j$.util.isUndefined(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
219
spec/core/matchers/matchersUtilSpec.js
Normal file
@@ -0,0 +1,219 @@
|
||||
describe("matchersUtil", function() {
|
||||
describe("equals", function() {
|
||||
it("passes for literals that are threequal", function() {
|
||||
expect(j$.matchersUtil.equals(null, null)).toBe(true);
|
||||
expect(j$.matchersUtil.equals(void 0, void 0)).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for things that are not equivalent", function() {
|
||||
expect(j$.matchersUtil.equals({a: "foo"}, 1)).toBe(false);
|
||||
});
|
||||
|
||||
it("passes for Strings that are equivalent", function() {
|
||||
expect(j$.matchersUtil.equals("foo", "foo")).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for Strings that are not equivalent", function() {
|
||||
expect(j$.matchersUtil.equals("foo", "bar")).toBe(false);
|
||||
});
|
||||
|
||||
it("passes for Numbers that are equivalent", function() {
|
||||
expect(j$.matchersUtil.equals(123, 123)).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for Numbers that are not equivalent", function() {
|
||||
expect(j$.matchersUtil.equals(123, 456)).toBe(false);
|
||||
});
|
||||
|
||||
it("passes for Dates that are equivalent", function() {
|
||||
expect(j$.matchersUtil.equals(new Date("Jan 1, 1970"), new Date("Jan 1, 1970"))).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for Dates that are not equivalent", function() {
|
||||
expect(j$.matchersUtil.equals(new Date("Jan 1, 1970"), new Date("Feb 3, 1991"))).toBe(false);
|
||||
});
|
||||
|
||||
it("passes for Booleans that are equivalent", function() {
|
||||
expect(j$.matchersUtil.equals(true, true)).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for Booleans that are not equivalent", function() {
|
||||
expect(j$.matchersUtil.equals(true, false)).toBe(false);
|
||||
});
|
||||
|
||||
it("passes for RegExps that are equivalent", function() {
|
||||
expect(j$.matchersUtil.equals(/foo/, /foo/)).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for RegExps that are not equivalent", function() {
|
||||
expect(j$.matchersUtil.equals(/foo/, /bar/)).toBe(false);
|
||||
expect(j$.matchersUtil.equals(new RegExp("foo", "i"), new RegExp("foo"))).toBe(false);
|
||||
});
|
||||
|
||||
it("passes for Arrays that are equivalent", function() {
|
||||
expect(j$.matchersUtil.equals([1, 2], [1, 2])).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for Arrays that are not equivalent", function() {
|
||||
expect(j$.matchersUtil.equals([1, 2], [1, 2, 3])).toBe(false);
|
||||
});
|
||||
|
||||
it("passes for Errors that are the same type and have the same message", function() {
|
||||
expect(j$.matchersUtil.equals(new Error("foo"), new Error("foo"))).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for Errors that are the same type and have different messages", function() {
|
||||
expect(j$.matchersUtil.equals(new Error("foo"), new Error("bar"))).toBe(false);
|
||||
});
|
||||
|
||||
it("passes for Objects that are equivalent (simple case)", function() {
|
||||
expect(j$.matchersUtil.equals({a: "foo"}, {a: "foo"})).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for Objects that are not equivalent (simple case)", function() {
|
||||
expect(j$.matchersUtil.equals({a: "foo"}, {a: "bar"})).toBe(false);
|
||||
});
|
||||
|
||||
it("passes for Objects that are equivalent (deep case)", function() {
|
||||
expect(j$.matchersUtil.equals({a: "foo", b: { c: "bar"}}, {a: "foo", b: { c: "bar"}})).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for Objects that are not equivalent (deep case)", function() {
|
||||
expect(j$.matchersUtil.equals({a: "foo", b: { c: "baz"}}, {a: "foo", b: { c: "bar"}})).toBe(false);
|
||||
});
|
||||
|
||||
it("passes for Objects that are equivalent (with cycles)", function() {
|
||||
var actual = { a: "foo" },
|
||||
expected = { a: "foo" };
|
||||
|
||||
actual.b = actual;
|
||||
expected.b = actual;
|
||||
|
||||
expect(j$.matchersUtil.equals(actual, expected)).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for Objects that are not equivalent (with cycles)", function() {
|
||||
var actual = { a: "foo" },
|
||||
expected = { a: "bar" };
|
||||
|
||||
actual.b = actual;
|
||||
expected.b = actual;
|
||||
|
||||
expect(j$.matchersUtil.equals(actual, expected)).toBe(false);
|
||||
});
|
||||
|
||||
it("fails when comparing an empty object to an empty array (issue #114)", function() {
|
||||
var emptyObject = {},
|
||||
emptyArray = [];
|
||||
|
||||
expect(j$.matchersUtil.equals(emptyObject, emptyArray)).toBe(false);
|
||||
expect(j$.matchersUtil.equals(emptyArray, emptyObject)).toBe(false);
|
||||
});
|
||||
|
||||
it("passes for equivalent frozen objects (GitHub issue #266)", function() {
|
||||
if (jasmine.getEnv().ieVersion < 9) { return; }
|
||||
|
||||
var a = { foo: 1 },
|
||||
b = {foo: 1 };
|
||||
|
||||
Object.freeze(a);
|
||||
Object.freeze(b);
|
||||
|
||||
expect(j$.matchersUtil.equals(a,b)).toBe(true);
|
||||
});
|
||||
|
||||
it("passes when Any is used", function() {
|
||||
var number = 3,
|
||||
anyNumber = new j$.Any(Number);
|
||||
|
||||
expect(j$.matchersUtil.equals(number, anyNumber)).toBe(true);
|
||||
expect(j$.matchersUtil.equals(anyNumber, number)).toBe(true);
|
||||
});
|
||||
|
||||
it("fails when Any is compared to something unexpected", function() {
|
||||
var number = 3,
|
||||
anyString = new j$.Any(String);
|
||||
|
||||
expect(j$.matchersUtil.equals(number, anyString)).toBe(false);
|
||||
expect(j$.matchersUtil.equals(anyString, number)).toBe(false);
|
||||
});
|
||||
|
||||
it("passes when ObjectContaining is used", function() {
|
||||
var obj = {
|
||||
foo: 3,
|
||||
bar: 7
|
||||
};
|
||||
|
||||
expect(j$.matchersUtil.equals(obj, new j$.ObjectContaining({foo: 3}))).toBe(true);
|
||||
});
|
||||
|
||||
it("passes when a custom equality matcher returns true", function() {
|
||||
var tester = function(a, b) { return true; };
|
||||
|
||||
expect(j$.matchersUtil.equals(1, 2, [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);
|
||||
});
|
||||
});
|
||||
|
||||
describe("contains", function() {
|
||||
it("passes when expected is a substring of actual", function() {
|
||||
expect(j$.matchersUtil.contains("ABC", "B")).toBe(true);
|
||||
});
|
||||
|
||||
it("fails when expected is a not substring of actual", function() {
|
||||
expect(j$.matchersUtil.contains("ABC", "X")).toBe(false);
|
||||
});
|
||||
|
||||
it("passes when expected is an element in an actual array", function() {
|
||||
expect(j$.matchersUtil.contains(['foo', 'bar'], 'foo')).toBe(true);
|
||||
});
|
||||
|
||||
it("fails when expected is not an element in an actual array", function() {
|
||||
expect(j$.matchersUtil.contains(['foo', 'bar'], 'baz')).toBe(false);
|
||||
});
|
||||
|
||||
it("passes with mixed-element arrays", function() {
|
||||
expect(j$.matchersUtil.contains(["foo", {some: "bar"}], "foo")).toBe(true);
|
||||
expect(j$.matchersUtil.contains(["foo", {some: "bar"}], {some: "bar"})).toBe(true);
|
||||
});
|
||||
|
||||
it("uses custom equality testers if passed in and actual is an Array", function() {
|
||||
var customTester = function(a, b) {return true;};
|
||||
|
||||
expect(j$.matchersUtil.contains([1, 2], 2, [customTester])).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildMessage", function() {
|
||||
|
||||
it("builds an English sentence for a failure case", function() {
|
||||
var actual = "foo",
|
||||
name = "toBar",
|
||||
message = j$.matchersUtil.buildFailureMessage(name, false, actual);
|
||||
|
||||
expect(message).toEqual("Expected 'foo' to bar.");
|
||||
});
|
||||
|
||||
it("builds an English sentence for a 'not' failure case", function() {
|
||||
var actual = "foo",
|
||||
name = "toBar",
|
||||
isNot = true,
|
||||
message = message = j$.matchersUtil.buildFailureMessage(name, isNot, actual);
|
||||
|
||||
expect(message).toEqual("Expected 'foo' not to bar.");
|
||||
});
|
||||
|
||||
it("builds an English sentence for an arbitrary array of expected arguments", function() {
|
||||
var actual = "foo",
|
||||
name = "toBar",
|
||||
message = j$.matchersUtil.buildFailureMessage(name, false, actual, "quux", "corge");
|
||||
|
||||
expect(message).toEqual("Expected 'foo' to bar 'quux', 'corge'.");
|
||||
});
|
||||
});
|
||||
});
|
||||
51
spec/core/matchers/toBeCloseToSpec.js
Normal file
@@ -0,0 +1,51 @@
|
||||
describe("toBeCloseTo", function() {
|
||||
it("passes when within two decimal places by default", function() {
|
||||
var matcher = j$.matchers.toBeCloseTo(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(0, 0);
|
||||
expect(result.pass).toBe(true);
|
||||
|
||||
result = matcher.compare(0, 0.001);
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("fails when not within two decimal places by default", function() {
|
||||
var matcher = j$.matchers.toBeCloseTo(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(0, 0.01);
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
|
||||
it("accepts an optional precision argument", function() {
|
||||
var matcher = j$.matchers.toBeCloseTo(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(0, 0.1, 0);
|
||||
expect(result.pass).toBe(true);
|
||||
|
||||
result = matcher.compare(0, 0.0001, 3);
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("rounds expected values", function() {
|
||||
var matcher = j$.matchers.toBeCloseTo(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(1.23, 1.229);
|
||||
expect(result.pass).toBe(true);
|
||||
|
||||
result = matcher.compare(1.23, 1.226);
|
||||
expect(result.pass).toBe(true);
|
||||
|
||||
result = matcher.compare(1.23, 1.225);
|
||||
expect(result.pass).toBe(true);
|
||||
|
||||
result = matcher.compare(1.23, 1.2249999);
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare(1.23, 1.234);
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
});
|
||||
18
spec/core/matchers/toBeDefinedSpec.js
Normal file
@@ -0,0 +1,18 @@
|
||||
describe("toBeDefined", function() {
|
||||
it("matches for defined values", function() {
|
||||
var matcher = j$.matchers.toBeDefined(),
|
||||
result;
|
||||
|
||||
|
||||
result = matcher.compare('foo');
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("fails when matching undefined values", function() {
|
||||
var matcher = j$.matchers.toBeDefined(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(void 0);
|
||||
expect(result.pass).toBe(false);
|
||||
})
|
||||
});
|
||||
38
spec/core/matchers/toBeFalsySpec.js
Normal file
@@ -0,0 +1,38 @@
|
||||
describe("toBeFalsy", function() {
|
||||
it("passes for 'falsy' values", function() {
|
||||
var matcher = j$.matchers.toBeFalsy(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(false);
|
||||
expect(result.pass).toBe(true);
|
||||
|
||||
result = matcher.compare(0);
|
||||
expect(result.pass).toBe(true);
|
||||
|
||||
result = matcher.compare('');
|
||||
expect(result.pass).toBe(true);
|
||||
|
||||
result = matcher.compare(null);
|
||||
expect(result.pass).toBe(true);
|
||||
|
||||
result = matcher.compare(void 0);
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for 'truthy' values", function() {
|
||||
var matcher = j$.matchers.toBeFalsy(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(true);
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare(1);
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare("foo");
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare({});
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
});
|
||||
19
spec/core/matchers/toBeGreaterThanSpec.js
Normal file
@@ -0,0 +1,19 @@
|
||||
describe("toBeGreaterThan", function() {
|
||||
it("passes when actual > expected", function() {
|
||||
var matcher = j$.matchers.toBeGreaterThan(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(2, 1);
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("fails when actual <= expected", function() {
|
||||
var matcher = j$.matchers.toBeGreaterThan();
|
||||
|
||||
result = matcher.compare(1, 1);
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare(1, 2);
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
});
|
||||
20
spec/core/matchers/toBeLessThanSpec.js
Normal file
@@ -0,0 +1,20 @@
|
||||
describe("toBeLessThan", function() {
|
||||
it("passes when actual < expected", function() {
|
||||
var matcher = j$.matchers.toBeLessThan(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(1, 2);
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("fails when actual <= expected", function() {
|
||||
var matcher = j$.matchers.toBeLessThan(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(1, 1);
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare(2, 1);
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
});
|
||||
36
spec/core/matchers/toBeNaNSpec.js
Normal file
@@ -0,0 +1,36 @@
|
||||
describe("toBeNaN", function() {
|
||||
it("passes for NaN with a custom .not fail", function() {
|
||||
var matcher = j$.matchers.toBeNaN(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(Number.NaN);
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected actual not to be NaN.");
|
||||
});
|
||||
|
||||
it("fails for anything not a NaN", function() {
|
||||
var matcher = j$.matchers.toBeNaN();
|
||||
|
||||
result = matcher.compare(1);
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare(null);
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare(void 0);
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare('');
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare(Number.POSITIVE_INFINITY);
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
|
||||
it("has a custom message on failure", function() {
|
||||
var matcher = j$.matchers.toBeNaN(),
|
||||
result = matcher.compare(0);
|
||||
|
||||
expect(result.message).toEqual("Expected 0 to be NaN.");
|
||||
});
|
||||
});
|
||||
17
spec/core/matchers/toBeNullSpec.js
Normal file
@@ -0,0 +1,17 @@
|
||||
describe("toBeNull", function() {
|
||||
it("passes for null", function() {
|
||||
var matcher = j$.matchers.toBeNull(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(null);
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for non-null", function() {
|
||||
var matcher = j$.matchers.toBeNull(),
|
||||
result;
|
||||
|
||||
result = matcher.compare('foo');
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
});
|
||||
17
spec/core/matchers/toBeSpec.js
Normal file
@@ -0,0 +1,17 @@
|
||||
describe("toBe", function() {
|
||||
it("passes when actual === expected", function() {
|
||||
var matcher = j$.matchers.toBe(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(1, 1);
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("fails when actual !== expected", function() {
|
||||
var matcher = j$.matchers.toBe(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(1, 2);
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
});
|
||||
38
spec/core/matchers/toBeTruthySpec.js
Normal file
@@ -0,0 +1,38 @@
|
||||
describe("toBeTruthy", function() {
|
||||
it("passes for 'truthy' values", function() {
|
||||
var matcher = j$.matchers.toBeTruthy(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(true);
|
||||
expect(result.pass).toBe(true);
|
||||
|
||||
result = matcher.compare(1);
|
||||
expect(result.pass).toBe(true);
|
||||
|
||||
result = matcher.compare("foo");
|
||||
expect(result.pass).toBe(true);
|
||||
|
||||
result = matcher.compare({});
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("fails for 'falsy' values", function() {
|
||||
var matcher = j$.matchers.toBeTruthy(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(false);
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare(0);
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare('');
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare(null);
|
||||
expect(result.pass).toBe(false);
|
||||
|
||||
result = matcher.compare(void 0);
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
});
|
||||
17
spec/core/matchers/toBeUndefinedSpec.js
Normal file
@@ -0,0 +1,17 @@
|
||||
describe("toBeUndefined", function() {
|
||||
it("passes for undefined values", function() {
|
||||
var matcher = j$.matchers.toBeUndefined(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(void 0);
|
||||
expect(result.pass).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
it("fails when matching defined values", function() {
|
||||
var matcher = j$.matchers.toBeUndefined();
|
||||
|
||||
result = matcher.compare('foo');
|
||||
expect(result.pass).toBe(false);
|
||||
})
|
||||
});
|
||||
24
spec/core/matchers/toContainSpec.js
Normal file
@@ -0,0 +1,24 @@
|
||||
describe("toContain", function() {
|
||||
it("delegates to j$.matchersUtil.contains", function() {
|
||||
var util = {
|
||||
contains: jasmine.createSpy('delegated-contains').and.callReturn(true)
|
||||
},
|
||||
matcher = j$.matchers.toContain(util);
|
||||
|
||||
result = matcher.compare("ABC", "B");
|
||||
expect(util.contains).toHaveBeenCalledWith("ABC", "B", []);
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("delegates to j$.matchersUtil.contains, passing in equality testers if present", function() {
|
||||
var util = {
|
||||
contains: jasmine.createSpy('delegated-contains').and.callReturn(true)
|
||||
},
|
||||
customEqualityTesters = ['a', 'b'],
|
||||
matcher = j$.matchers.toContain(util, customEqualityTesters);
|
||||
|
||||
result = matcher.compare("ABC", "B");
|
||||
expect(util.contains).toHaveBeenCalledWith("ABC", "B", ['a', 'b']);
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
});
|
||||
28
spec/core/matchers/toEqualSpec.js
Normal file
@@ -0,0 +1,28 @@
|
||||
describe("toEqual", function() {
|
||||
it("delegates to equals function", function() {
|
||||
var util = {
|
||||
equals: jasmine.createSpy('delegated-equals').and.callReturn(true)
|
||||
},
|
||||
matcher = j$.matchers.toEqual(util),
|
||||
result;
|
||||
|
||||
result = matcher.compare(1, 1);
|
||||
|
||||
expect(util.equals).toHaveBeenCalledWith(1, 1, []);
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("delegates custom equality testers, if present", function() {
|
||||
var util = {
|
||||
equals: jasmine.createSpy('delegated-equals').and.callReturn(true)
|
||||
},
|
||||
customEqualityTesters = ['a', 'b'],
|
||||
matcher = j$.matchers.toEqual(util, customEqualityTesters),
|
||||
result;
|
||||
|
||||
result = matcher.compare(1, 1);
|
||||
|
||||
expect(util.equals).toHaveBeenCalledWith(1, 1, ['a', 'b']);
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
});
|
||||
46
spec/core/matchers/toHaveBeenCalledSpec.js
Normal file
@@ -0,0 +1,46 @@
|
||||
describe("toHaveBeenCalled", function() {
|
||||
it("passes when the actual was called, with a custom .not fail message", function() {
|
||||
var matcher = j$.matchers.toHaveBeenCalled(),
|
||||
calledSpy = j$.createSpy('called-spy'),
|
||||
result;
|
||||
|
||||
calledSpy();
|
||||
|
||||
result = matcher.compare(calledSpy);
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected spy called-spy not to have been called.");
|
||||
});
|
||||
|
||||
it("fails when the actual was not called", function() {
|
||||
var matcher = j$.matchers.toHaveBeenCalled(),
|
||||
uncalledSpy = j$.createSpy('uncalled spy');
|
||||
|
||||
result = matcher.compare(uncalledSpy);
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
|
||||
it("throws an exception when the actual is not a spy", function() {
|
||||
var matcher = j$.matchers.toHaveBeenCalled(),
|
||||
fn = function() {};
|
||||
|
||||
expect(function() { matcher.compare(fn) }).toThrow(new Error("Expected a spy, but got Function."));
|
||||
});
|
||||
|
||||
it("throws an exception when invoked with any arguments", function() {
|
||||
var matcher = j$.matchers.toHaveBeenCalled(),
|
||||
spy = j$.createSpy('sample spy');
|
||||
|
||||
expect(function() { matcher.compare(spy, 'foo') }).toThrow(new Error("toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith"));
|
||||
});
|
||||
|
||||
it("has a custom message on failure", function() {
|
||||
var matcher = j$.matchers.toHaveBeenCalled(),
|
||||
spy = j$.createSpy('sample-spy'),
|
||||
result;
|
||||
|
||||
result = matcher.compare(spy);
|
||||
|
||||
expect(result.message).toEqual("Expected spy sample-spy to have been called.");
|
||||
});
|
||||
});
|
||||
|
||||
57
spec/core/matchers/toHaveBeenCalledWithSpec.js
Normal file
@@ -0,0 +1,57 @@
|
||||
describe("toHaveBeenCalledWith", function() {
|
||||
it("passes when the actual was called with matching parameters", function() {
|
||||
var util = {
|
||||
contains: jasmine.createSpy('delegated-contains').and.callReturn(true)
|
||||
},
|
||||
matcher = j$.matchers.toHaveBeenCalledWith(util),
|
||||
calledSpy = j$.createSpy('called-spy'),
|
||||
result;
|
||||
|
||||
calledSpy('a', 'b');
|
||||
result = matcher.compare(calledSpy, 'a', 'b');
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("fails when the actual was not called", function() {
|
||||
var util = {
|
||||
contains: jasmine.createSpy('delegated-contains').and.callReturn(false)
|
||||
},
|
||||
matcher = j$.matchers.toHaveBeenCalledWith(util),
|
||||
uncalledSpy = j$.createSpy('uncalled spy'),
|
||||
result;
|
||||
|
||||
result = matcher.compare(uncalledSpy);
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
|
||||
it("fails when the actual was called with different parameters", function() {
|
||||
var util = {
|
||||
contains: jasmine.createSpy('delegated-contains').and.callReturn(false)
|
||||
},
|
||||
matcher = j$.matchers.toHaveBeenCalledWith(util),
|
||||
calledSpy = j$.createSpy('called spy'),
|
||||
result;
|
||||
|
||||
calledSpy('a');
|
||||
result = matcher.compare(calledSpy, 'a', 'b');
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
|
||||
it("throws an exception when the actual is not a spy", function() {
|
||||
var matcher = j$.matchers.toHaveBeenCalledWith(),
|
||||
fn = 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.")
|
||||
});
|
||||
});
|
||||
34
spec/core/matchers/toMatchSpec.js
Normal file
@@ -0,0 +1,34 @@
|
||||
describe("toMatch", function() {
|
||||
it("passes when RegExps are equivalent", function() {
|
||||
var matcher = j$.matchers.toMatch(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(/foo/, /foo/);
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("fails when RegExps are not equivalent", function() {
|
||||
var matcher = j$.matchers.toMatch(),
|
||||
result;
|
||||
|
||||
result = matcher.compare(/bar/, /foo/);
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
|
||||
it("passes when the actual matches the expected string as a pattern", function() {
|
||||
var matcher = j$.matchers.toMatch(),
|
||||
result;
|
||||
|
||||
result = matcher.compare('foosball', 'foo');
|
||||
expect(result.pass).toBe(true);
|
||||
});
|
||||
|
||||
it("fails when the actual matches the expected string as a pattern", function() {
|
||||
var matcher = j$.matchers.toMatch(),
|
||||
result;
|
||||
|
||||
result = matcher.compare('bar', 'foo');
|
||||
expect(result.pass).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
280
spec/core/matchers/toThrowErrorSpec.js
Normal file
@@ -0,0 +1,280 @@
|
||||
describe("toThrowError", function() {
|
||||
it("throws an error when the actual is not a function", function() {
|
||||
var matcher = j$.matchers.toThrowError();
|
||||
|
||||
expect(function() {
|
||||
matcher.compare({});
|
||||
}).toThrow(new Error("Actual is not a Function")); // TODO: this needs to change for self-test
|
||||
});
|
||||
|
||||
it("throws an error when the expected is not an Error, string, or RegExp", function() {
|
||||
var matcher = j$.matchers.toThrowError(),
|
||||
fn = function() {
|
||||
throw new Error("foo");
|
||||
};
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
it("throws an error when the expected error type is not an Error", function() {
|
||||
var matcher = j$.matchers.toThrowError(),
|
||||
fn = function() {
|
||||
throw new Error("foo");
|
||||
};
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
it("throws an error when the expected error message is not a string or RegExp", function() {
|
||||
var matcher = j$.matchers.toThrowError(),
|
||||
fn = function() {
|
||||
throw new Error("foo");
|
||||
};
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
it("fails if actual does not throw at all", function() {
|
||||
var matcher = j$.matchers.toThrowError(),
|
||||
fn = function() {
|
||||
return true;
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn);
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toEqual("Expected function to throw an Error.");
|
||||
});
|
||||
|
||||
it("fails if thrown is not an instanceof Error", function() {
|
||||
var matcher = j$.matchers.toThrowError(),
|
||||
fn = function() {
|
||||
throw 4;
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn);
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toEqual("Expected function to throw an Error, but it threw 4.");
|
||||
});
|
||||
|
||||
it("fails with the correct message if thrown is a falsy value", function() {
|
||||
var matcher = j$.matchers.toThrowError(),
|
||||
fn = function() {
|
||||
throw undefined;
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn);
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toEqual("Expected function to throw an Error, but it threw undefined.");
|
||||
});
|
||||
|
||||
it("passes if thrown is a type of Error, but there is no expected error", function() {
|
||||
var matcher = j$.matchers.toThrowError(),
|
||||
fn = function() {
|
||||
throw new TypeError();
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn);
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected function not to throw an Error, but it threw TypeError.");
|
||||
});
|
||||
|
||||
it("passes if thrown is an Error and the expected is the same message", function() {
|
||||
var matcher = j$.matchers.toThrowError(),
|
||||
fn = function() {
|
||||
throw new Error("foo");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, "foo");
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected function not to throw an exception with message 'foo'.");
|
||||
});
|
||||
|
||||
it("fails if thrown is an Error and the expected is not the same message", function() {
|
||||
var matcher = j$.matchers.toThrowError(),
|
||||
fn = function() {
|
||||
throw new Error("foo");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, "bar");
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toEqual("Expected function to throw an exception with message 'bar', but it threw an exception with message 'foo'.");
|
||||
});
|
||||
|
||||
it("passes if thrown is an Error and the expected is a RegExp that matches the message", function() {
|
||||
var matcher = j$.matchers.toThrowError(),
|
||||
fn = function() {
|
||||
throw new Error("a long message");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, /long/);
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected function not to throw an exception with a message matching /long/.");
|
||||
});
|
||||
|
||||
it("fails if thrown is an Error and the expected is a RegExp that does not match the message", function() {
|
||||
var matcher = j$.matchers.toThrowError(),
|
||||
fn = function() {
|
||||
throw new Error("a long message");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, /foo/);
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toEqual("Expected function to throw an exception with a message matching /foo/, but it threw an exception with message 'a long message'.");
|
||||
});
|
||||
|
||||
it("passes if thrown is an Error and the expected the same Error", function() {
|
||||
var util = {
|
||||
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
|
||||
},
|
||||
matcher = j$.matchers.toThrowError(util),
|
||||
fn = function() {
|
||||
throw new Error();
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, Error);
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected function not to throw Error.");
|
||||
});
|
||||
|
||||
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)
|
||||
},
|
||||
matcher = j$.matchers.toThrowError(util),
|
||||
CustomError = function CustomError(arg) { arg.x },
|
||||
fn = function() {
|
||||
throw new CustomError({ x: 1 });
|
||||
},
|
||||
result;
|
||||
|
||||
CustomError.prototype = new Error();
|
||||
CustomError.prototype.constructor = CustomError;
|
||||
|
||||
result = matcher.compare(fn, CustomError);
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected function not to throw CustomError.");
|
||||
});
|
||||
|
||||
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)
|
||||
},
|
||||
matcher = j$.matchers.toThrowError(util),
|
||||
fn = function() {
|
||||
throw new Error();
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, TypeError);
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toEqual("Expected function to throw TypeError, but it threw Error.");
|
||||
});
|
||||
|
||||
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)
|
||||
},
|
||||
matcher = j$.matchers.toThrowError(util),
|
||||
fn = function() {
|
||||
throw new TypeError("foo");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, TypeError, "foo");
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected function not to throw TypeError with message \"foo\".");
|
||||
});
|
||||
|
||||
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)
|
||||
},
|
||||
matcher = j$.matchers.toThrowError(util),
|
||||
CustomError = function CustomError(arg) { this.message = arg.message },
|
||||
fn = function() {
|
||||
throw new CustomError({message: "foo"});
|
||||
},
|
||||
result;
|
||||
|
||||
CustomError.prototype = new Error();
|
||||
CustomError.prototype.constructor = CustomError;
|
||||
|
||||
result = matcher.compare(fn, CustomError, "foo");
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected function not to throw CustomError with message \"foo\".");
|
||||
});
|
||||
|
||||
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)
|
||||
},
|
||||
matcher = j$.matchers.toThrowError(util),
|
||||
fn = function() {
|
||||
throw new TypeError("foo");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, TypeError, "bar");
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toEqual("Expected function to throw TypeError with message \"bar\", but it threw TypeError with message \"foo\".");
|
||||
});
|
||||
|
||||
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)
|
||||
},
|
||||
matcher = j$.matchers.toThrowError(util),
|
||||
fn = function() {
|
||||
throw new TypeError("foo");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, TypeError, /foo/);
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected function not to throw TypeError with message matching /foo/.");
|
||||
});
|
||||
|
||||
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)
|
||||
},
|
||||
matcher = j$.matchers.toThrowError(util),
|
||||
fn = function() {
|
||||
throw new TypeError("foo");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, TypeError, /bar/);
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toEqual("Expected function to throw TypeError with message matching /bar/, but it threw TypeError with message \"foo\".");
|
||||
});
|
||||
});
|
||||
98
spec/core/matchers/toThrowSpec.js
Normal file
@@ -0,0 +1,98 @@
|
||||
describe("toThrow", function() {
|
||||
it("throws an error when the actual is not a function", function() {
|
||||
var matcher = j$.matchers.toThrow();
|
||||
|
||||
expect(function() {
|
||||
matcher.compare({});
|
||||
}).toThrow(new Error("Actual is not a Function")); // TODO: this needs to change for self-test
|
||||
});
|
||||
|
||||
it("fails if actual does not throw", function() {
|
||||
var matcher = j$.matchers.toThrow(),
|
||||
fn = function() {
|
||||
return true;
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn);
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toEqual("Expected function to throw an exception.");
|
||||
});
|
||||
|
||||
it("passes if it throws but there is no expected", function() {
|
||||
var util = {
|
||||
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
|
||||
},
|
||||
matcher = j$.matchers.toThrow(util),
|
||||
fn = function() {
|
||||
throw 5;
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn);
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected function not to throw, but it threw 5.");
|
||||
});
|
||||
|
||||
it("passes even if what is thrown is falsy", function() {
|
||||
var matcher = j$.matchers.toThrow(),
|
||||
fn = function() {
|
||||
throw undefined;
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn);
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected function not to throw, but it threw undefined.");
|
||||
});
|
||||
|
||||
it("passes if what is thrown is equivalent to what is expected", function() {
|
||||
var util = {
|
||||
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
|
||||
},
|
||||
matcher = j$.matchers.toThrow(util),
|
||||
fn = function() {
|
||||
throw 5;
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, 5);
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected function not to throw 5.");
|
||||
});
|
||||
|
||||
it("fails if what is thrown is not equivalent to what is expected", function() {
|
||||
var util = {
|
||||
equals: jasmine.createSpy('delegated-equal').and.callReturn(false)
|
||||
},
|
||||
matcher = j$.matchers.toThrow(util),
|
||||
fn = function() {
|
||||
throw 5;
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, "foo");
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toEqual("Expected function to throw 'foo', but it threw 5.");
|
||||
});
|
||||
|
||||
it("fails if what is thrown is not equivalent to undefined", function() {
|
||||
var util = {
|
||||
equals: jasmine.createSpy('delegated-equal').and.callReturn(false)
|
||||
},
|
||||
matcher = j$.matchers.toThrow(util),
|
||||
fn = function() {
|
||||
throw 5;
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, void 0);
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toEqual("Expected function to throw undefined, but it threw 5.");
|
||||
});
|
||||
});
|
||||
19
spec/helpers/BrowserFlags.js
Normal file
@@ -0,0 +1,19 @@
|
||||
(function(env) {
|
||||
env.ieVersion = (function() {
|
||||
var userAgent = jasmine.getGlobal().navigator.userAgent;
|
||||
if (!userAgent) { return Number.MAX_VALUE; }
|
||||
|
||||
var match = /MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(userAgent);
|
||||
|
||||
return match ? parseFloat(match[1]) : Number.MAX_VALUE;
|
||||
})();
|
||||
|
||||
env.safariVersion = (function() {
|
||||
var userAgent = jasmine.getGlobal().navigator.userAgent;
|
||||
if (!userAgent) { return Number.MAX_VALUE; }
|
||||
|
||||
var match = /Safari/.exec(userAgent) && /Version\/([0-9]{0,})/.exec(userAgent);
|
||||
|
||||
return match ? parseFloat(match[1]) : Number.MAX_VALUE;
|
||||
})();
|
||||
})(jasmine.getEnv());
|
||||
494
spec/html/HtmlReporterSpec.js
Normal file
@@ -0,0 +1,494 @@
|
||||
describe("New HtmlReporter", function() {
|
||||
// TODO: Figure out why this isn't rendering...
|
||||
it("builds the initial DOM elements, including the title banner", function() {
|
||||
var env = new j$.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() { return container; },
|
||||
reporter = new j$.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
reporter.initialize();
|
||||
|
||||
// Main top-level elements
|
||||
expect(container.querySelector("div.html-reporter")).toBeTruthy();
|
||||
expect(container.querySelector("div.banner")).toBeTruthy();
|
||||
expect(container.querySelector("div.alert")).toBeTruthy();
|
||||
expect(container.querySelector("div.results")).toBeTruthy();
|
||||
|
||||
expect(container.querySelector("ul.symbol-summary")).toBeTruthy();
|
||||
|
||||
// title banner
|
||||
var banner = container.querySelector(".banner");
|
||||
|
||||
var title = banner.querySelector(".title");
|
||||
expect(title.innerHTML).toMatch(/Jasmine/);
|
||||
|
||||
var version = banner.querySelector(".version"),
|
||||
versionText = 'textContent' in version ? version.textContent : version.innerText;
|
||||
expect(versionText).toEqual(j$.version);
|
||||
});
|
||||
|
||||
it("starts the timer when jasmine begins", function() {
|
||||
var env = new jasmine.Env(),
|
||||
startTimerSpy = jasmine.createSpy("start-timer-spy"),
|
||||
reporter = new jasmine.HtmlReporter({
|
||||
env: env,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
timer: { start: startTimerSpy }
|
||||
});
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
|
||||
expect(startTimerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("when a spec is done", function() {
|
||||
it("reports the status symbol of a disabled spec", function() {
|
||||
var env = new j$.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() { return container; },
|
||||
reporter = new j$.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
reporter.initialize();
|
||||
|
||||
reporter.specDone({id: 789, status: "disabled", fullName: "symbols should have titles"});
|
||||
|
||||
var specEl = container.querySelector('.symbol-summary li');
|
||||
expect(specEl.getAttribute("class")).toEqual("disabled");
|
||||
expect(specEl.getAttribute("id")).toEqual("spec_789");
|
||||
expect(specEl.getAttribute("title")).toEqual("symbols should have titles");
|
||||
});
|
||||
|
||||
it("reports the status symbol of a pending spec", function() {
|
||||
var env = new j$.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() { return container; },
|
||||
reporter = new j$.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
reporter.initialize();
|
||||
|
||||
reporter.specDone({id: 789, status: "pending"});
|
||||
|
||||
var specEl = container.querySelector('.symbol-summary li');
|
||||
expect(specEl.getAttribute("class")).toEqual("pending");
|
||||
expect(specEl.getAttribute("id")).toEqual("spec_789");
|
||||
});
|
||||
|
||||
it("reports the status symbol of a passing spec", function() {
|
||||
var env = new j$.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() { return container; },
|
||||
reporter = new j$.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
reporter.initialize();
|
||||
|
||||
reporter.specDone({id: 123, status: "passed"});
|
||||
|
||||
var statuses = container.querySelector(".symbol-summary");
|
||||
var specEl = statuses.querySelector("li");
|
||||
expect(specEl.getAttribute("class")).toEqual("passed");
|
||||
expect(specEl.getAttribute("id")).toEqual("spec_123");
|
||||
});
|
||||
|
||||
it("reports the status symbol of a failing spec", function() {
|
||||
var env = new j$.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() { return container; },
|
||||
reporter = new j$.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
|
||||
reporter.initialize();
|
||||
|
||||
reporter.specDone({
|
||||
id: 345,
|
||||
status: "failed",
|
||||
failedExpectations: []
|
||||
});
|
||||
|
||||
var specEl = container.querySelector(".symbol-summary li");
|
||||
expect(specEl.getAttribute("class")).toEqual("failed");
|
||||
expect(specEl.getAttribute("id")).toEqual("spec_345");
|
||||
});
|
||||
});
|
||||
|
||||
describe("when Jasmine is done", function() {
|
||||
it("reports the run time", function() {
|
||||
var env = new j$.Env(),
|
||||
container = document.createElement("div"),
|
||||
timer = jasmine.createSpyObj('timer', ['start', 'elapsed']),
|
||||
getContainer = function() { return container; },
|
||||
reporter = new j$.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
|
||||
timer: timer
|
||||
});
|
||||
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
|
||||
timer.elapsed.and.callReturn(100);
|
||||
reporter.jasmineDone();
|
||||
|
||||
var duration = container.querySelector(".banner .duration");
|
||||
expect(duration.innerHTML).toMatch(/finished in 0.1s/);
|
||||
});
|
||||
|
||||
it("reports the suite and spec names with status", function() {
|
||||
var env = new j$.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() { return container; },
|
||||
reporter = new j$.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
reporter.suiteStarted({
|
||||
id: 1,
|
||||
description: "A Suite",
|
||||
fullName: "A Suite"
|
||||
});
|
||||
|
||||
var specResult = {
|
||||
id: 123,
|
||||
description: "with a spec",
|
||||
fullName: "A Suite with a spec",
|
||||
status: "passed"
|
||||
};
|
||||
reporter.specStarted(specResult);
|
||||
reporter.specDone(specResult);
|
||||
|
||||
reporter.suiteStarted({
|
||||
id: 2,
|
||||
description: "inner suite",
|
||||
fullName: "A Suite inner suite"
|
||||
});
|
||||
|
||||
var specResult = {
|
||||
id: 124,
|
||||
description: "with another spec",
|
||||
fullName: "A Suite inner suite with another spec",
|
||||
status: "passed"
|
||||
};
|
||||
reporter.specStarted(specResult);
|
||||
reporter.specDone(specResult);
|
||||
|
||||
reporter.suiteDone({id: 2});
|
||||
|
||||
specResult = {
|
||||
id: 209,
|
||||
description: "with a failing spec",
|
||||
fullName: "A Suite inner with a failing spec",
|
||||
status: "failed",
|
||||
failedExpectations: []
|
||||
};
|
||||
reporter.specStarted(specResult);
|
||||
reporter.specDone(specResult);
|
||||
|
||||
reporter.suiteDone({id: 1});
|
||||
|
||||
reporter.jasmineDone({});
|
||||
var summary = container.querySelector(".summary");
|
||||
|
||||
expect(summary.childNodes.length).toEqual(1);
|
||||
|
||||
var outerSuite = summary.childNodes[0];
|
||||
expect(outerSuite.childNodes.length).toEqual(4);
|
||||
|
||||
var classes = [];
|
||||
for (var i = 0; i < outerSuite.childNodes.length; i++) {
|
||||
var node = outerSuite.childNodes[i];
|
||||
classes.push(node.getAttribute("class"));
|
||||
}
|
||||
expect(classes).toEqual(["suite-detail", "specs", "suite", "specs"]);
|
||||
|
||||
var suiteDetail = outerSuite.childNodes[0];
|
||||
var suiteLink = suiteDetail.childNodes[0];
|
||||
expect(suiteLink.innerHTML).toEqual("A Suite");
|
||||
expect(suiteLink.getAttribute('href')).toEqual("?spec=A%20Suite");
|
||||
|
||||
var specs = outerSuite.childNodes[1];
|
||||
var spec = specs.childNodes[0];
|
||||
expect(spec.getAttribute("class")).toEqual("passed");
|
||||
expect(spec.getAttribute("id")).toEqual("spec-123");
|
||||
|
||||
var specLink = spec.childNodes[0];
|
||||
expect(specLink.innerHTML).toEqual("with a spec");
|
||||
expect(specLink.getAttribute("href")).toEqual("?spec=A%20Suite%20with%20a%20spec");
|
||||
// expect(specLink.getAttribute("title")).toEqual("A Suite with a spec");
|
||||
});
|
||||
|
||||
describe("UI for raising/catching exceptions", function() {
|
||||
it("should be unchecked if the env is catching", function() {
|
||||
var env = new j$.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
reporter = new j$.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
createTextNode: function() {
|
||||
return document.createTextNode.apply(document, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var raisingExceptionsUI = container.querySelector(".raise");
|
||||
expect(raisingExceptionsUI.checked).toBe(false);
|
||||
});
|
||||
|
||||
it("should be checked if the env is not catching", function() {
|
||||
var env = new j$.Env(),
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
reporter = new j$.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
createTextNode: function() {
|
||||
return document.createTextNode.apply(document, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
reporter.initialize();
|
||||
env.catchExceptions(false);
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var raisingExceptionsUI = container.querySelector(".raise");
|
||||
expect(raisingExceptionsUI.checked).toBe(true);
|
||||
});
|
||||
|
||||
it("should affect the query param for catching exceptions", function() {
|
||||
var env = new j$.Env(),
|
||||
container = document.createElement("div"),
|
||||
exceptionsClickHandler = jasmine.createSpy("raise exceptions checked"),
|
||||
getContainer = function() {
|
||||
return container;
|
||||
},
|
||||
reporter = new j$.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
onRaiseExceptionsClick: exceptionsClickHandler,
|
||||
createElement: function() {
|
||||
return document.createElement.apply(document, arguments);
|
||||
},
|
||||
createTextNode: function() {
|
||||
return document.createTextNode.apply(document, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
reporter.initialize();
|
||||
reporter.jasmineDone({});
|
||||
|
||||
var input = container.querySelector(".raise");
|
||||
input.click();
|
||||
expect(exceptionsClickHandler).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("and all specs pass", function() {
|
||||
var env, container, reporter;
|
||||
beforeEach(function() {
|
||||
env = new j$.Env();
|
||||
container = document.createElement("div");
|
||||
getContainer = function() { return container; },
|
||||
reporter = new j$.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
reporter.specDone({
|
||||
id: 123,
|
||||
description: "with a spec",
|
||||
fullName: "A Suite with a spec",
|
||||
status: "passed"
|
||||
});
|
||||
reporter.specDone({
|
||||
id: 124,
|
||||
description: "with another spec",
|
||||
fullName: "A Suite inner suite with another spec",
|
||||
status: "passed"
|
||||
});
|
||||
reporter.jasmineDone({});
|
||||
});
|
||||
|
||||
it("reports the specs counts", function() {
|
||||
var alertBars = container.querySelectorAll(".alert .bar");
|
||||
|
||||
expect(alertBars.length).toEqual(1);
|
||||
expect(alertBars[0].getAttribute('class')).toMatch(/passed/);
|
||||
expect(alertBars[0].innerHTML).toMatch(/2 specs, 0 failures/);
|
||||
});
|
||||
|
||||
it("reports no failure details", function() {
|
||||
var specFailure = container.querySelector(".failures");
|
||||
|
||||
expect(specFailure.childNodes.length).toEqual(0);
|
||||
});
|
||||
|
||||
it("reports no pending specs", function() {
|
||||
var alertBar = container.querySelector(".alert .bar");
|
||||
|
||||
expect(alertBar.innerHTML).not.toMatch(/pending spec[s]/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("and there are pending specs", function() {
|
||||
var env, container, reporter;
|
||||
beforeEach(function() {
|
||||
env = new j$.Env();
|
||||
container = document.createElement("div");
|
||||
getContainer = function() { return container; },
|
||||
reporter = new j$.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
reporter.specDone({
|
||||
id: 123,
|
||||
description: "with a spec",
|
||||
fullName: "A Suite with a spec",
|
||||
status: "pending"
|
||||
});
|
||||
reporter.jasmineDone({});
|
||||
});
|
||||
|
||||
it("reports the pending specs count", function() {
|
||||
var alertBar = container.querySelector(".alert .bar");
|
||||
|
||||
expect(alertBar.innerHTML).toMatch(/1 spec, 0 failures, 1 pending spec/);
|
||||
});
|
||||
|
||||
it("reports no failure details", function() {
|
||||
var specFailure = container.querySelector(".failures");
|
||||
|
||||
expect(specFailure.childNodes.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("and some tests fail", function() {
|
||||
var env, container, reporter;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new j$.Env();
|
||||
container = document.createElement("div"),
|
||||
getContainer = function() { return container; },
|
||||
reporter = new j$.HtmlReporter({
|
||||
env: env,
|
||||
getContainer: getContainer,
|
||||
createElement: function() { return document.createElement.apply(document, arguments); },
|
||||
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
|
||||
});
|
||||
reporter.initialize();
|
||||
|
||||
reporter.jasmineStarted({});
|
||||
|
||||
var passingResult = {id: 123, status: "passed"};
|
||||
reporter.specStarted(passingResult);
|
||||
reporter.specDone(passingResult);
|
||||
|
||||
var failingResult = {
|
||||
id: 124,
|
||||
status: "failed",
|
||||
description: "a failing spec",
|
||||
fullName: "a suite with a failing spec",
|
||||
failedExpectations: [
|
||||
{
|
||||
message: "a failure message",
|
||||
stack: "a stack trace"
|
||||
}
|
||||
]
|
||||
};
|
||||
reporter.specStarted(failingResult);
|
||||
reporter.specDone(failingResult);
|
||||
reporter.jasmineDone({});
|
||||
});
|
||||
|
||||
it("reports the specs counts", function() {
|
||||
var alertBar = container.querySelector(".alert .bar");
|
||||
|
||||
expect(alertBar.getAttribute('class')).toMatch(/failed/);
|
||||
expect(alertBar.innerHTML).toMatch(/2 specs, 1 failure/);
|
||||
});
|
||||
|
||||
it("reports failure messages and stack traces", function() {
|
||||
var specFailures = container.querySelector(".failures");
|
||||
|
||||
var failure = specFailures.childNodes[0];
|
||||
expect(failure.getAttribute("class")).toMatch(/failed/);
|
||||
expect(failure.getAttribute("class")).toMatch(/spec-detail/);
|
||||
|
||||
var specLink = failure.childNodes[0];
|
||||
expect(specLink.getAttribute("class")).toEqual("description");
|
||||
expect(specLink.getAttribute("title")).toEqual("a suite with a failing spec");
|
||||
expect(specLink.getAttribute("href")).toEqual("?spec=a%20suite%20with%20a%20failing%20spec");
|
||||
|
||||
var message = failure.childNodes[1].childNodes[0];
|
||||
expect(message.getAttribute("class")).toEqual("result-message");
|
||||
expect(message.innerHTML).toEqual("a failure message");
|
||||
|
||||
var stackTrace = failure.childNodes[1].childNodes[1];
|
||||
expect(stackTrace.getAttribute("class")).toEqual("stack-trace");
|
||||
expect(stackTrace.innerHTML).toEqual("a stack trace");
|
||||
});
|
||||
|
||||
it("allows switching between failure details and the spec summary", function() {
|
||||
var menuBar = container.querySelectorAll(".bar")[1];
|
||||
|
||||
expect(menuBar.getAttribute("class")).not.toMatch(/hidden/);
|
||||
|
||||
var link = menuBar.querySelector('a');
|
||||
expect(link.innerHTML).toEqual("Failures");
|
||||
expect(link.getAttribute("href")).toEqual("#");
|
||||
});
|
||||
|
||||
it("sets the reporter to 'Failures List' mode", function() {
|
||||
var reporterNode = container.querySelector(".html-reporter");
|
||||
expect(reporterNode.getAttribute("class")).toMatch("failure-list");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||