Compare commits

..

201 Commits

Author SHA1 Message Date
Davis W. Frank & Rajan Agaskar
fd91433792 Version 1.3.1 2012-12-03 09:51:08 -08:00
Davis W. Frank & Rajan Agaskar
1f9004eaa3 Re-add pages submodule for release build script
- Use public github url
2012-12-03 09:47:48 -08:00
dev
58e6747930 Fixing test runner failures in IE 6/7/8 whereby HtmlReporter.js bails out as we're using for (reserved keyword) as object property name. Fix is just to quote the name which allows IE6/7/8 to run the tests. I think this might also fix Issue #303 on main repo (https://github.com/pivotal/jasmine/issues/303) 2012-12-03 09:38:57 -08:00
Davis W. Frank & Rajan Agaskar
4c083856be Setup Travis build 2012-12-03 09:38:54 -08:00
Davis W. Frank & Rajan Agaskar
b94522193c Use jasmine-gem for jasmine-core tests 2012-11-28 14:25:39 -08:00
Davis W. Frank & Rajan Agaskar
867de62699 Releasing 1.3
- Allow users to set the pretty-printer's recursion depth
- When pretty-printing objects, don't include inherited properties.
- Change toBeCloseTo matcher to be more consistent
- Added toBeNaN matcher
- Add checkbox to test runner which toggles catching of exceptions duri
- Add config option which stops jasmine from capturing exceptions in a
2012-11-27 13:47:02 -08:00
Rajan Agaskar
74cdc5a04f Merge pull request #290 from maxbrunsfeld/smaller-pretty-print2
smaller, more configurable pretty-printing of objects
2012-10-29 09:32:40 -07:00
Max Brunsfeld
ddbee65aa8 Allow users to set the pretty-printer's recursion depth
Currently, jasmine's pretty printer traverses objects
to 40 levels of nesting. If an object is more deeply
nested than that, an exception is thrown. I find that
after a few levels of nesting, the output becomes
difficult to read. The process of serializing such
deep objects also sometimes crashes the browser or
causes a 'slow script' warning.

This commit exposes a 'MAX_PRETTY_PRINT_DEPTH' option.
It also causes the pretty printer to skip over
parts of an object that are nested to deeply by simply
printing out 'Object' or 'Array', rather than throwing
an exception.
2012-10-28 12:27:26 -07:00
Max Brunsfeld
beeb872a82 When pretty-printing objects, don't include inherited properties.
When making assertions about complex objects, Jasmine's
failure message are sometimes gigantic and difficult
to read because the string representation of an object
contains all of the methods and properties in its
prototype chain. This commit causes the pretty printer
to only display on object's own properties.
2012-10-28 12:27:26 -07:00
Rajan Agaskar
dbcb0b7983 Merge pull request #234 from yopefonic/master
comparison for regExp that compares pattern and modifiers
2012-10-26 19:51:47 -07:00
Joost Elfering
c8436d1d44 adding a check for the sticky regExp option supported by Firefox and accepted by the ES6. Note that the tests for this case are checking for the support of the sticky parameter. the logic is still tested by the other expect statements in browsers that do not support sticky but will never enter that block as creating a regExp with that flag is not allowed. Coverage is still good. See pivotal/jasmine#234 2012-10-27 01:51:19 +01:00
Joost Elfering
639f757f6f added some specs to strengthen the coverage pivotal/jasmine#234 2012-10-27 01:50:34 +01:00
Joost Elfering
d65bdc7e59 resolving issue that was identified via pivotal/jasmine#199 where RegExp objects were not properly compared resulting in non-matching RegExp objects to always return true. a patch to jasmine.Env.equals_ adds an extra step for RexExp objects to be compared. 2012-10-27 01:50:34 +01:00
Rajan Agaskar
a1ed56741b Merge pull request #193 from slackersoft/spy_called_with_messages
less confusing messages for toHaveBeenCalledWith
2012-10-05 17:53:11 -07:00
Rajan Agaskar
7473b455dc Merge pull request #225 from gunnarahlberg/master
spec that to spy on an undefined method throws exception
2012-10-05 17:44:00 -07:00
Rajan Agaskar
b6fb23b069 Merge pull request #254 from jcracknell/nan-matcher
Added toBeNaN matcher
2012-10-05 17:31:36 -07:00
Rajan Agaskar
386e83b53f Merge pull request #280 from ronaldploeger/master
JSDoc @return-tag to 'spyOn' and 'expect' functions
2012-10-05 17:10:51 -07:00
PLOE09
f2b25f1780 Add JSDoc @return-tag to 'spyOn' and 'expect' functions support
code completion in Spket IDE
2012-09-14 16:36:32 +02:00
Davis W. Frank
5ca2888301 Merge pull request #242 from ChrisTM/master
Fix swapped template values in build_standalone_runner.rb.
2012-09-02 22:58:08 -07:00
Davis W. Frank
147cb36760 Merge pull request #269 from kconnor/master
create downloads dir if needed during build_standalone_distribution
2012-09-02 17:42:11 -07:00
Davis W. Frank
107463ad57 Merge pull request #251 from doochik/patch-1
update jsdoc for jasmine.Matchers.prototype.toThrow
2012-09-02 17:40:51 -07:00
Davis W. Frank
39a55d8f10 Merge pull request #257 from kevinoid/no-window-or-exports
Don't assume exports is defined when window is undefined
2012-09-02 17:40:16 -07:00
Rajan Agaskar
4b48dc1069 Merge pull request #260 from rgould/master
Guarantee that afterEach and after blocks are always run
2012-09-01 13:05:41 -07:00
Rajan Agaskar
921f52862f Merge pull request #270 from Wolfy87/patch-1
Wrapped the reserved word, "for", in quotes.
2012-08-15 14:17:29 -07:00
Oliver Caldwell
ea2ffb7b01 Wrapped the reserved word, "for", in quotes.
This stops it throwing errors in IE and other browsers. I think the newer Firefox and Chrome versions are the only browsers to not die when running it.
2012-08-15 21:44:28 +02:00
Kevin Connor
54fbc48eb2 create downloads dir if needed during build_standalone_distribution 2012-08-15 12:41:09 -07:00
Davis W. Frank
06c900ab20 Merge pull request #264 from dburt/master
Change toBeCloseTo matcher to be more consistent
2012-08-12 09:23:15 -07:00
Davis W. Frank
3e070e9db6 Move to an earlier RedCarpet to fix an incompatibility with Rocco. Regen of gh-pages. 2012-08-11 16:53:08 -07:00
Dave Burt
7e04571ec0 Change toBeCloseTo matcher to be more consistent.
It now calculates and compares a difference, rather than rounding
two separate quantities and testing for their equality.
2012-07-31 15:03:55 +10:00
rgould
ddd48f2c88 Regenerate jasmine.js after adding ensured support. 2012-07-24 18:54:36 -04:00
rgould
1c2e50d244 Add 'ensured' blocks to the queue.
This blocks will be run even when a preceeding block sets the abort
flag. This is so that we can support afterEach calls running when the
spec fails due to a timeout.
2012-07-24 18:45:30 -04:00
rgould
d2d60a798d Merge remote-tracking branch 'bigfix/after_waitsFor'
* bigfix/after_waitsFor:
  Test that show that afterEach and after are not being called when a waitsFor times out.
  Test that afterEach is called after a failing spec.
  Consolidate all waitsFor specs in the same describe block.
2012-07-24 16:36:28 -04:00
Kevin Locke
442f3bf872 Don't assume exports is defined when window is undefined
The current code makes the assumption that if window is undefined it is
being run in an environment which supports the CommonJS Modules spec.
This is not the case when Jasmine is being run in rhino or SpiderMonkey
(smjs) without EnvJS.

The fix is simply to check that exports is an object.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2012-07-19 14:10:39 -06:00
James Cracknell
f910df00bb Added toBeNaN matcher 2012-07-12 20:04:14 -06:00
Alexey Androsov
500b856cfa update jsdoc for jasmine.Matchers.prototype.toThrow
expected argument is optional
2012-07-10 15:12:32 +04:00
Rajan Agaskar
dad4865fbf Merge pull request #221 from rupurt/no_try_catch_multi_commit
No try catch multi commit
2012-06-28 09:56:39 -07:00
Alex Kwiatkowski
1771ec3c63 Add checkbox to test runner which toggles catching of exceptions during tests 2012-06-24 00:02:52 -04:00
Alex Kwiatkowski
2385acedd8 Add config option which stops jasmine from capturing exceptions in a test 2012-06-23 23:12:31 -04:00
Christopher Mitchell
4c28bef387 Fix swapped template values in build_standalone_runner.rb.
`example_source_tags` and `example_spec_tags` each returned what the other
should have returned. I noticed this bug because it made the comments in
SpecRunner.html about where to include spec and source files incongruous with
the example tags that followed.
2012-06-16 17:49:43 -07:00
Davis W. Frank
7bbcf51d45 Removed Frank for GHPages generation. Now using Rocco and a Thor task to build it 2012-05-27 13:16:20 -07:00
ragaskar
b6f96bc121 Version 1.2.0
- Bump version
- Update pages submodule
2012-05-14 07:35:47 -07:00
Rajan Agaskar
feebfbba68 Update README.markdown 2012-05-09 09:51:29 -07:00
Rajan Agaskar
8e4bd86865 Merge pull request #220 from moonmaster9000/patch-1
update the copyright and remove the blank "what's here" section.
2012-05-02 10:51:26 -07:00
Gunnar Ahlberg
4f218f7d6a cover spy on on undefined method 2012-05-02 14:11:22 +02:00
Matt Parker
bb1a4428db update the copyright and remove the blank "what's here" section. 2012-04-13 23:30:12 -03:00
Davis W. Frank
079740ca2c Make Thor tasks more visible; Init Pages submodule when not present if about to run tests that require it 2012-04-09 22:21:09 -07:00
ragaskar
fbbccf6ef7 Bump to 1.2.0.rc3 2012-04-04 09:48:00 -07:00
ragaskar
7ad75c13d4 Fix Matchers.any specs in Firefox
- Firefox adds whitespace to the resulting to_string function, necessary
  to remove it for the match to occur correctly.
2012-04-04 08:41:59 -07:00
Davis W. Frank
d46ca4f506 correct for 1.2.0.rc2 2012-04-03 15:35:08 -07:00
Davis W. Frank
ee7af4496c Pages updated for 1.2.0.rc1 2012-04-02 18:37:35 -07:00
Davis W. Frank
e22c4492a5 release prep for 1.2.0.rc1 2012-04-02 18:34:59 -07:00
Davis W. Frank
d63836afb4 Fix for copying built Github pages to the submodule properly 2012-04-02 18:33:38 -07:00
Davis W. Frank
06f1edc197 Merge branch 'master' of github.com:pivotal/jasmine 2012-04-01 17:03:06 -07:00
Davis W. Frank
3a6b233a2e Merge pull request #209 from mark-rushakoff/ruby187fix
fix JasmineDev#has_node? for Ruby 1.8.7
2012-04-01 17:02:20 -07:00
Mark Rushakoff
d15964b7dc fix JasmineDev#has_node? for Ruby 1.8.7 2012-04-01 15:44:36 -07:00
Davis W. Frank
6e22754c10 1.2.0.rc1 commit 2012-04-01 13:19:24 -07:00
Davis W. Frank
bab4538404 Fix to name the standalone distribution from the version number 2012-04-01 13:11:53 -07:00
Davis W. Frank
06d191af74 Merge branch 'master' of github.com:pivotal/jasmine 2012-04-01 13:08:55 -07:00
Davis W. Frank
ad78d0d0d8 Fixed bug where version for Ruby gem wasn't correct 2012-04-01 13:08:42 -07:00
Davis W. Frank
733a6a4ae4 Merge pull request #208 from mark-rushakoff/ansicolor-cleanup
Remove remaining references to term-ansicolor
2012-04-01 13:00:57 -07:00
Mark Rushakoff
3e0cad41f5 Remove remaining references to term-ansicolor 2012-04-01 12:30:38 -07:00
Davis W. Frank
885832e920 Forgot to update Contribute to include new Thor tasks 2012-04-01 11:36:29 -07:00
Davis W. Frank
3a0ada034b Move sources order to Ruby, which is where it's used. 2012-04-01 11:28:57 -07:00
Davis W. Frank
674197aef8 Removed TermAnsiColor gem (uses GPL and isn't needed anymore) 2012-04-01 10:51:04 -07:00
Davis W. Frank
626da5a112 Re-implemented all development Rake tasks in Thor. Now actually tested.
Fixes:
* https://www.pivotaltracker.com/story/show/25484287 & https://github.com/pivotal/jasmine/issues/183
* https://www.pivotaltracker.com/story/show/25485401 & https://github.com/pivotal/jasmine/issues/189
* https://www.pivotaltracker.com/story/show/25485953 & https://github.com/pivotal/jasmine/issues/159
2012-04-01 10:47:29 -07:00
gvanhove
a3ccd8b0d3 less confusing messages for toHaveBeenCalledWith 2012-03-02 19:28:15 -08:00
Davis W. Frank
4a1a2123a3 Fixes https://github.com/pivotal/jasmine-gem/issues/65 and https://www.pivotaltracker.com/story/show/24902023 2012-02-25 11:58:54 -08:00
Davis W. Frank
c87cf71f4f Merge pull request #156 from cathoderay/master
fixing typo
2012-01-08 12:46:14 -08:00
Davis W. Frank
e4c557faae Merge pull request #158 from grosser/contribute-markup
fix task list not displaying properly on github for contribute.markdown
2012-01-08 12:45:50 -08:00
Davis W. Frank
6559c5b43a Merge pull request #157 from grosser/license
add license to gemspec so automated tools can pick it up
2012-01-08 12:45:21 -08:00
Davis W. Frank
912397120b Merge pull request #170 from edtsech/patch-1
Remove double negative in docs (not.toNotContain, not.toNotEqual)
2012-01-08 12:41:46 -08:00
Edward Tsech
551464b8d2 Remove double negative in docs (not.toNotContain, not.toNotEqual) 2012-01-04 16:21:54 +01:00
Davis W. Frank
8a298e5c0e Merge pull request #168 from thedeeno/linux_open_browser
add linux support to ``rake spec:browser``
2012-01-03 17:07:17 -08:00
Dane O'Connor
94a153ed15 add linux support to rake spec:browser 2012-01-03 17:12:20 -05:00
Davis W. Frank
b4439f74d5 Merge pull request #100 from gvanhove/objectContaining
Merging after verifying locally that all specs are green (node, browser)
2011-11-18 13:26:04 -08:00
gvanhove
d70e733f70 remove unwanted spaces in it calls, and make the spec counting regex tolerate them if they exist so counts match even when using bad style 2011-11-14 18:43:13 -08:00
gvanhove
ac096f9911 convert objectContaining to use jasmineMatches and jasmineToString 2011-11-14 18:29:30 -08:00
gvanhove
08d72926ff More renaming of hash 2011-11-14 18:29:30 -08:00
gvanhove
67ec0af254 use jasmineMatches for equality testing of complicated matchers 2011-11-14 18:29:30 -08:00
gvanhove
4f2fcff15a Use jasmineToString for printing out complicated matchers 2011-11-14 18:29:30 -08:00
gvanhove
7158fc2426 Rename hashContaining to objectContaining, since this is javascript. Also call the toString from prettyPrinter 2011-11-14 18:26:48 -08:00
gvanhove
992367dcbc New matcher "hashContaining" similar to rspec's hash_including 2011-11-14 18:26:48 -08:00
gvanhove
ce886e20e4 commit updated version into jasmine.js 2011-11-14 18:26:48 -08:00
grosser
86b0c80cc9 fix task list not displaying properly on github for contribute.markdown 2011-11-13 09:18:34 -08:00
grosser
7dff84b1dc add license to gemspec so automated tools can pick it up 2011-11-13 09:12:29 -08:00
Ronald Andreu Kaiser
8c22b26d9c fixing typo 2011-11-11 16:42:50 -02:00
Davis W. Frank & Sean Durham
ad4f48dcd4 Add new HTMLReporter 2011-11-04 14:43:19 -07:00
Davis W. Frank & Rajan Agaskar
de9e2abad5 Use correct name for Davis. 2011-11-04 14:31:15 -07:00
ragaskar
41f496001f Version bump to 1.1.0 2011-09-10 13:51:11 -04:00
ragaskar
6b5956724b Version bump to rc4 2011-09-01 07:26:07 -04:00
Rajan Agaskar
ec24992250 Merge pull request #123 from Osukaru/master
fixed html comments in SpecRunner.html example
2011-09-01 04:23:41 -07:00
Osukaru
83f232237d fixed html comments 2011-08-26 01:22:11 +03:00
Rajan Agaskar
98d32bb4a4 Merge pull request #111 from qfox/patch-1
Add missing semi.
2011-07-21 04:07:52 -07:00
qfox
c4f27ae377 ASI trolling 2011-07-21 00:58:53 -07:00
ragaskar
a075c75bce Version bump to 1.1.0.rc3 2011-07-13 07:23:29 -04:00
ragaskar
a617b59e6a Bump to rc2 2011-06-24 21:34:29 -04:00
ragaskar
917b37481e Update rake 2011-06-24 21:25:06 -04:00
ragaskar
67bbc98faa Bump version 2011-06-24 21:22:19 -04:00
Davis W. Frank
620f7b6e4c Updates to Pages; Updates to docs; 2011-06-23 19:02:17 -07:00
ragaskar
b722f416c7 Write out version.rb on dist build 2011-06-23 07:55:04 -04:00
ragaskar
634a7dc402 Rollback pages submodule bump 2011-06-23 07:32:05 -04:00
Davis W. Frank
a4522e4dce Updated Release readme 2011-06-21 20:19:28 -07:00
Davis W. Frank
e113c338d0 Merge branch 'master' of github.com:pivotal/jasmine 2011-06-21 20:11:10 -07:00
ragaskar
b81f690a25 Require JSON in time for the gemspec 2011-06-21 08:05:41 -04:00
ragaskar
c06e189699 Ignore tags 2011-06-21 08:05:20 -04:00
Davis W. Frank
67b6cfb828 Improve the rake standalone task 2011-06-20 18:27:57 -07:00
Davis W. Frank
57e622fb2a Fix to version structure for "release_candidate" 2011-06-20 18:17:24 -07:00
Davis W. Frank
c0664dd6aa merge 2011-06-20 08:46:37 -07:00
Davis W. Frank
b640ce6fc0 wip on readme for release 2011-06-20 07:32:40 -07:00
ragaskar
e9af7834f5 Better argument handling in Jasmine::Core#spec_files 2011-06-18 09:43:14 -04:00
ragaskar
0d43ae9c38 Give Jasmine::Core access to jasmine specs
[#13128217]
2011-06-18 09:39:23 -04:00
ragaskar
30431a3958 Gem-ize jasmine
[Finishes #13128217]
2011-06-17 21:01:42 -04:00
Davis W. Frank
3775919c92 remove old, commented-out tasks 2011-06-17 08:23:17 -07:00
Davis W. Frank
a692ff8c95 Need HAML in the Gemfile; continued fixes to the Rake tasks 2011-06-17 08:20:22 -07:00
Davis W. Frank
e4e9b51544 rename TrivialConsoleReporter to ConsoleReporter 2011-06-16 22:35:57 -07:00
Davis W. Frank
0b97951766 Better coloring of output of Rake tasks; Turn off colored output in Rake tasks if not on a TTY (not sure if it works in Hudson); Add support to TCR for turning off colors since there is code to calc options but it wasn't used; NOTE: coloring in TCR should be MUCH better tested. 2011-06-16 22:34:11 -07:00
Davis W. Frank
75dd391d57 should fix red build 2011-06-16 08:33:59 -07:00
Davis W. Frank
ae24e00c0f Support for release candidates in the version.json file; propagates up through the version string everywhere: filenames, ZIP, source code 2011-06-15 18:37:12 -07:00
Davis W. Frank
6b2e45eab5 Refactor of standalone build tasks; Better templating of the core runner.html and the example SpecRunner.html 2011-06-15 09:15:40 -07:00
Davis W. Frank
e59171935f breaking up distribution tasks; moving version to a template to have a simpler concat function 2011-06-14 08:30:14 -07:00
Davis W. Frank
2ba0aa371c Refactor how the distribution is built 2011-06-13 08:23:10 -07:00
Davis W. Frank
c2ed71717f Remove link to github page from Runner 2011-06-11 16:51:16 -07:00
Davis W. Frank
09e8822107 WIP on new Contribution docs 2011-06-11 16:47:12 -07:00
Davis W. Frank
15763c2eb0 Output number of expected specs for browser, node before running specs. NOTE: We distribution tasks still broken. 2011-06-11 15:59:34 -07:00
Davis W. Frank
3f264cde34 fix so that all specs are pulled into runner.html 2011-06-11 14:48:41 -07:00
Davis W. Frank
f83cb7f766 Runner.html is now generated (ensures all source & specs get tested); beginnings of refactoring of Rake tasks. 2011-06-09 19:24:51 -07:00
Davis W. Frank
9d5470ff55 removing expectation count from TCR to match browser reporter 2011-06-08 18:36:58 -07:00
Davis W. Frank
86b095e5a4 Src & Spec dirs now have same structure; console/, core/, and html/ 2011-06-08 18:30:35 -07:00
Davis W. Frank
4c6dafa3f5 OCD 2011-06-08 08:36:03 -07:00
Davis W. Frank
3f4adf7715 Removed dead code 2011-06-08 08:29:39 -07:00
Davis W. Frank
af7f1818b0 Revert back to the old jasmine.css 2011-06-05 21:55:51 -07:00
Davis W. Frank
12f56787b0 Move building single-file JS to use a JSON file with initial priority files 2011-06-05 21:55:32 -07:00
Davis W. Frank
e88d88e427 Move all core files into src/core.
Move Browser & Node specs to test against lib/jasmine.js instead of the separate source. Yes, this makes development a little harder but it's better to test that jasmine.js was built correctly.
2011-06-05 21:28:26 -07:00
Davis W. Frank
ba10d178b2 Better stack trace on exception. Better results if exception is due to true exception 2011-06-01 21:14:59 -07:00
Davis W. Frank
da297d0f56 And what I meant was *this* commit was pulling in the fixes to TrivialConsoleReporter 2011-05-25 08:28:16 -07:00
Davis W. Frank
7ead5388c2 merge in fixes to TrivialConsoleReporter: correct # of specs, no longer limited by column length 2011-05-25 08:14:18 -07:00
Davis W. Frank
a445a62e7c TrivialConsoleReporter now reports the correct number of specs that were executed. TCR is still very heavily mocked instead of using testing an actual Jasmine environment. But now at least the numbers are correct. 2011-05-16 18:28:46 -07:00
Davis W. Frank
1d65d56a92 TrivialConsoleReporter refactor & fixes. No longer limitied to 50 columns of dots. 2011-05-16 08:08:12 -07:00
ragaskar
d875d1d997 Don't run TrivialConsoleReporter specs if TrivialConsoleReporter is not loaded 2011-05-06 23:18:57 -04:00
ragaskar
1fae8f0a31 Rebuild main jasmine lib 2011-05-06 23:08:49 -04:00
ragaskar
c1f8151bcb Add png suitable for favicon 2011-05-06 22:40:53 -04:00
ragaskar
bd8a3baed1 Remove unused image files 2011-05-06 22:30:48 -04:00
ragaskar
118324b451 Don't show 'Jasmine waiting for...' console messages unless jasmine.VERBOSE is set to true 2011-05-06 19:07:00 -04:00
ragaskar
c30f7d1aa7 Fail with an error if node is not installed when running rake spec 2011-05-06 18:34:42 -04:00
ragaskar
de7be4b316 ignore rvmrc 2011-05-06 18:32:58 -04:00
Davis W. Frank
b02aa9840a fixed bad merge of gvanhove's describe exception fix 2011-04-17 21:44:41 -07:00
Davis W. Frank
61de2268fe toBeCloseTo matcher merged in 2011-04-17 21:18:41 -07:00
gvanhove
dd32048383 Failure messages for toHaveBeenCalledWith print out the name of the spy 2011-04-17 20:55:32 -07:00
gvanhove
32e736aa47 commit updated version into jasmine.js 2011-04-17 20:55:32 -07:00
Steve Conover
38e9af8f68 integrating TrivialConsoleReporter into node_suite.js, deleting some code pulled over from jasmine-node 2011-04-17 20:50:57 -07:00
Carl Jackson & Davis W. Frank
e826fbb170 More README edits for the Contributor guide 2011-03-09 13:31:03 -08:00
Carl Jackson & Davis W. Frank
0c77662c5b One more README tweak 2011-03-09 13:15:33 -08:00
Davis W. Frank
75fb19bc49 README changes 2011-03-09 08:16:47 -08:00
Davis W. Frank
6ec825f62d Updating docs. Version goes to 1.1.0 2011-03-08 18:39:13 -08:00
Davis W. Frank
fc994108db Update Rakefile a bit. Added more rake tasks to run specs. 2011-03-08 18:38:46 -08:00
Davis W. Frank
70aed2d900 move all "assertion" to "expectation" 2011-03-08 18:37:44 -08:00
Davis W. Frank
ccfa17499f Merge remote branch 'sconover/trivial_console_reporter' into work 2011-03-07 22:35:25 -08:00
Davis W. Frank
ab087ef5f8 Pendantic terminology 2011-03-07 22:34:58 -08:00
Davis W. Frank
0ef6582f73 Merging in sconover/jshint 2011-03-07 22:30:43 -08:00
Steve Conover
a1ba43c864 call back when done 2011-02-28 23:58:06 -08:00
Steve Conover
88ee377662 integrated trivial console into a real-world situation and dicovered a couple mistakes/misses 2011-02-28 23:18:53 -08:00
Steve Conover
f5afe18a6b semicolon fixes subsequent to jshint run 2011-02-28 22:56:04 -08:00
Steve Conover
2731716ccb making this consistent 2011-02-28 22:39:16 -08:00
Steve Conover
4e5083d570 style rf 2011-02-28 22:36:31 -08:00
Steve Conover
b9cbd3c5a0 integration test - failure scenario 2011-02-28 22:30:03 -08:00
Steve Conover
e42026ee84 rename *node to *console 2011-02-28 21:15:57 -08:00
Steve Conover
a1f58f8be4 rf 2011-02-28 21:15:57 -08:00
Steve Conover
ac00d765d2 integration tests - passing scenarios 2011-02-28 21:15:57 -08:00
Steve Conover
b1dceeacd4 stack traces 2011-02-28 21:15:57 -08:00
Steve Conover
5018f0d1c2 spec failure - description 2011-02-28 21:15:57 -08:00
Steve Conover
9704550b33 rf 2011-02-28 21:15:56 -08:00
Steve Conover
882c287191 specs/assertions/failures 2011-02-28 21:15:56 -08:00
Steve Conover
7d2b900b48 remember suite results as suites finish 2011-02-28 21:15:56 -08:00
Steve Conover
f701fdc132 needful 2011-02-28 21:15:56 -08:00
Steve Conover
eb49fab652 print elapsed time in summary 2011-02-28 21:15:56 -08:00
Steve Conover
e8c8a0bdfd run result - passed green, failed red 2011-02-28 21:15:56 -08:00
Steve Conover
e6a080039f print started when the test run starts 2011-02-28 21:15:56 -08:00
Steve Conover
c485c33a3c skipped specs mean yellow star 2011-02-28 21:15:56 -08:00
Steve Conover
8fbf3ba859 newline at 50 characters 2011-02-28 21:15:56 -08:00
Steve Conover
dccafe33b0 style reform 2011-02-28 21:15:56 -08:00
Steve Conover
c1d2718bea red F, duh 2011-02-28 21:15:55 -08:00
Steve Conover
945a9ba638 failing spec makes a red dot 2011-02-28 21:15:55 -08:00
Steve Conover
528b5abeda beginning of trivial node reporter, based on jasmine-node. jshint rules exclude bad escapements WRT ansi colors, beacuse that's ok. 2011-02-28 21:15:55 -08:00
Davis W. Frank
d7cced2e7c How to for release 2011-02-27 14:22:53 -08:00
Davis W. Frank
3be0610572 adding latest pages 2011-02-27 14:00:45 -08:00
Davis W. Frank
5e90115eaf removing incorrectlt added submodule 2011-02-27 12:33:47 -08:00
Davis W. Frank
148317eb90 1.0.2, finishing to Frank for static pages 2011-02-27 12:26:38 -08:00
Davis W. Frank
45b4e1316c updating for new pages 2011-02-27 10:36:13 -08:00
Davis W. Frank
aee4c5926c .gitmodules 2011-02-27 09:48:17 -08:00
Steve Conover
f41af6c2d0 jshint passes - run 'node jshint/run.js'. running jshint with a couple jshint options and workarounds to allow certain jasmine-specific styles. many actual style problems are fixed. the jshint run is integrated into rake jasmine:lint. 2011-02-26 15:07:59 -08:00
Steve Conover
9f90c4eca5 initial jshint commit. including the library, made a runner for jasmine. 2011-02-26 11:23:25 -08:00
Steve Conover
545752ae20 semicolons 2011-02-26 11:01:33 -08:00
Steve Conover
c04f1b1fa8 node spec/node_suite.js runs all dom-independent jasmine specs. basic commonjs support for jasmine along the way. node_suite.js and runner.html are both green. 2011-02-26 10:53:55 -08:00
Davis W. Frank
fa9741dbda removed old ghpages dir 2011-02-25 08:14:48 -08:00
Davis W. Frank
560cb2edcb wip 2011-02-25 08:10:34 -08:00
Davis W. Frank
9a12b32a3a swapping ignore from Jekyll to staticmatic 2011-01-25 13:23:01 -08:00
Christian Williams
bd15ed6a45 Really? "File.exist?", not "File.exists?"? Whatever. 2010-11-09 13:10:40 -05:00
Christian Williams
fa74051071 Don't commit Gemfile.lock. 2010-11-09 09:48:30 -05:00
John Firebaugh
dbcabd397e Test that show that afterEach and after are not being called when a waitsFor times out. 2010-09-29 08:25:58 -07:00
John Firebaugh
a8b0a0ee4f Test that afterEach is called after a failing spec. 2010-09-29 08:19:43 -07:00
John Firebaugh
60a5d60f42 Consolidate all waitsFor specs in the same describe block. 2010-09-28 20:43:50 -07:00
129 changed files with 11947 additions and 1407 deletions

12
.gitignore vendored
View File

@@ -1,6 +1,14 @@
.idea/
.svn/
.DS_Store
_site/
site/
.bundle/
.pairs
.pairs
.rvmrc
*.gem
.bundle
tags
Gemfile.lock
pkg/*
.sass-cache/*
src/html/.sass-cache/*

2
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "pages"]
path = pages
url = git@github.com:pivotal/jasmine.git
url = https://github.com/pivotal/jasmine.git

1
.rspec Normal file
View File

@@ -0,0 +1 @@
--color

9
.travis.yml Normal file
View File

@@ -0,0 +1,9 @@
# before_script:
# - "sh -e /etc/init.d/xvfb start"
before_install:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"#
script: "DISPLAY=:99.0 bundle exec rake jasmine_core_spec"
rvm:
- "1.9.3"

45
Contribute.markdown Normal file
View File

@@ -0,0 +1,45 @@
# Developing for Jasmine Core
## How to Contribute
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.
## 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
* _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.
## Environment
Ruby, RubyGems and Rake are used in order to script the various file interactions. You will need to run on a system that supports Ruby in order to run Jasmine's specs.
Node.js is used to run most of the specs (the HTML-independent code) and should be present. Additionally, the JS Hint project scrubs the source code as part of the spec process.
## 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/`.
Please respect the code patterns as possible. For example, using `jasmine.getGlobal()` to get the global object so as to remain environment agnostic.
## Running Specs
As in all good projects, the `spec/` directory mirrors `src/` and follows the same rules. The browser runner will include and attempt to run all specs. The node runner will exclude any html-dependent specs (those in `spec/html/`).
You will notice that all specs are run against the built `jasmine.js` instead of the component source files. This is intentional as a way to ensure that the concatenation code is working correctly.
Please ensure all specs are green before committing or issuing a pull request.
There are Thor tasks to help with getting green - run `thor list` to see them all. Here are the key tasks:
* `thor jasmine_dev:execute_specs` outputs the expected number of specs that should be run and attempts to run in browser and Node
* `thor jasmine_dev:execute_specs_in_browser` opens `spec/runner.html` in the default browser on MacOS. Please run this in at least Firefox and Chrome before committing
* `thor jasmine_dev:execute_specs_in_node` runs all the Jasmine specs in Node.js - it will complain if Node is not installed
* `thor jasmine_dev:js_hint` runs all the files through JSHint and will complain about potential viable issues with your code. Fix them.

15
Gemfile
View File

@@ -1,6 +1,11 @@
source :gemcutter
source :rubygems
gem "rake"
gem "jasmine", git: 'https://github.com/pivotal/jasmine-gem.git'
gem "jekyll", "0.6.2"
gem "json_pure", "~>1.4.3"
gem "ragaskar-jsdoc_helper"
gem "rake", "0.8.7"
unless ENV["TRAVIS"]
group :debug do
gem 'debugger'
end
end
gemspec

View File

@@ -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

View File

@@ -1,28 +1,25 @@
<a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a>
<a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a> <a title="Build at Travis CI" href="http://travis-ci.org/#!/pivotal/jasmine"><img src="https://secure.travis-ci.org/pivotal/jasmine.png" /></a>
=======
**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>
## 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-2012 Pivotal Labs. This software is licensed under the MIT License.

224
Rakefile
View File

@@ -1,182 +1,80 @@
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 "tilt"
Dir["#{File.dirname(__FILE__)}/tasks/**/*.rb"].each do |file|
require file
end
def jasmine_html_sources
["src/html/TrivialReporter.js"]
desc "Run all Jasmine JS specs"
task :jasmine_specs do
jasmine_dev = JasmineDev.new
return unless jasmine_dev.node_installed?
system "thor jasmine_dev:execute_specs"
puts "\n\033[33m>>> DEPRECATED <<< Run Jasmine's JavaScript specs with 'thor jasmine_dev:execute_specs'\n\033[0m"
end
def jasmine_version
"#{version_hash['major']}.#{version_hash['minor']}.#{version_hash['build']}"
desc "Run all Jasmine core tests (JavaScript and dev tasks)"
task :spec => :require_pages_submodule do
jasmine_dev = JasmineDev.new
return unless jasmine_dev.node_installed?
system "rspec"
end
def version_hash
require 'json'
@version ||= JSON.parse(File.new("src/version.json").read);
task :require_pages_submodule do
jasmine_dev = JasmineDev.new
unless jasmine_dev.pages_submodule_installed?
puts 'Installing the Github pages submodule:'
system 'git submodule update --init'
puts 'Now continuing...'
end
end
task :default => 'jasmine:dist'
desc "View full development tasks"
task :list_dev_tasks do
puts "Jasmine uses Thor for command line tasks for development. Here is the command set:"
system "thor list"
end
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) }
require "jasmine"
require 'rspec'
require 'rspec/core/rake_task'
desc "Run all examples"
RSpec::Core::RakeTask.new(:jasmine_core_spec) do |t|
t.pattern = 'spec/jasmine_self_test_spec.rb'
end
namespace :jasmine do
task :server do
port = ENV['JASMINE_PORT'] || 8888
Jasmine.load_configuration_from_yaml(File.join(Dir.pwd, 'spec', 'jasmine.yml'))
config = Jasmine.config
server = Jasmine::Server.new(8888, 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'].to_json},
"minor": #{version['minor'].to_json},
"build": #{version['build'].to_json},
"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
downloads_file = 'pages/download.html.md'
task :need_pages_submodule do
unless File.exists?(downloads_file)
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"
# JsdocHelper bug: template must be relative to the JsdocHelper gem, ick
t[:template] = File.join("../".*(100), Dir::getwd, "jsdoc-template")
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",
"MIT.LICENSE" => "MIT.LICENSE"
}.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"
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]
prerelease = /\.rc/.match(f)
download_html += prerelease ? "<tr class=\"rc\">\n" : "<tr>\n"
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"
download_html += "</tr>\n"
end
download_html += "<!-- END_DOWNLOADS -->"
downloads_page = File.read(downloads_file)
matcher = /<!-- START_DOWNLOADS -->.*<!-- END_DOWNLOADS -->/m
downloads_page = downloads_page.sub(matcher, download_html)
File.open(downloads_file, 'w') {|f| f.write(downloads_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']

42
Release.markdown Normal file
View File

@@ -0,0 +1,42 @@
# 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), please squash them when merging back to `master`.
### Version
We attempt to stick to [Semantic Versioning](). 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 `src/version.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)
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.
The pages are built with [Frank](https://github.com/blahed/frank). All the source for these pages live in the `pages/pages_source` directory.
## Release
When ready to release - specs are all green and the stories are done:
1. Update the version in `version.json` to a release candidate - add a `release_candidate` property with a value of 1
1. Update any comments on the public interfaces
1. Update any links or top-level landing page for the Github Pages
1. `thor jasmine_dev:release_prep` - updates the version, builds the `.js` files, builds the standalone release, and builds the Github pages
1. `rake release` - tags the repo with the version, builds the `jasmine-core` gem, pushes the gem to Rubygems.org
There should be a post to Pivotal Labs blog and a tweet to that link.

29
config.rb Normal file
View File

@@ -0,0 +1,29 @@
#
# Compass configuration file - for building Jasmine's 'final CSS files
#
# Require any additional compass plugins here.
# Set this to the root of your project when deployed:
http_path = "/"
css_dir = "src/html"
sass_dir = "src/html"
images_dir = "images"
javascripts_dir = "javascripts"
# You can select your preferred output style here (can be overridden via the command line):
# output_style = :expanded or :nested or :compact or :compressed
output_style = :compact
# To enable relative paths to assets via compass helper functions. Uncomment:
# relative_assets = true
# To disable debugging comments that display the original location of your selectors. Uncomment:
line_comments = false
# If you prefer the indented syntax, you might want to regenerate this
# project again passing --syntax sass, or you can uncomment this:
# preferred_syntax = :sass
# and then run:
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass

View File

@@ -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&nbsp;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

View 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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 759 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

BIN
images/jasmine_favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 768 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

32
jasmine-core.gemspec Normal file
View File

@@ -0,0 +1,32 @@
# -*- 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 "tilt"
s.add_development_dependency "sass"
s.add_development_dependency "compass"
s.add_development_dependency "ragaskar-jsdoc_helper"
s.add_development_dependency "rspec"
s.add_development_dependency "fuubar"
s.add_development_dependency "awesome_print"
s.add_development_dependency "thor"
s.add_development_dependency "nokogiri"
s.add_development_dependency "redcarpet", "1.7"
s.add_development_dependency "rocco"
s.add_development_dependency "rdiscount"
end

1
jasmine_dev.thor Normal file
View File

@@ -0,0 +1 @@
require "#{File.expand_path(File.dirname(__FILE__))}/tasks/jasmine_dev"

5919
jshint/jshint.js Executable file

File diff suppressed because it is too large Load Diff

99
jshint/run.js Normal file
View File

@@ -0,0 +1,99 @@
var fs = require("fs");
var util = require("util");
var path = require("path");
var JSHINT = require("./jshint").JSHINT;
// DWF TODO: Standardize this?
function isExcluded(fullPath) {
var fileName = path.basename(fullPath);
var excludeFiles = ["json2.js", "jshint.js", "publish.js", "node_suite.js", "jasmine.js", "jasmine-html.js"];
for (var i = 0; i < excludeFiles.length; i++) {
if (fileName == excludeFiles[i]) {
return true;
}
}
return false;
}
// DWF TODO: This function could/should be re-written
function allJasmineJsFiles(rootDir) {
var files = [];
fs.readdirSync(rootDir).filter(function(filename) {
var fullPath = rootDir + "/" + filename;
if (fs.statSync(fullPath).isDirectory() && !fullPath.match(/pages/)) {
var subDirFiles = allJasmineJsFiles(fullPath);
if (subDirFiles.length > 0) {
files = files.concat();
return true;
}
} else {
if (fullPath.match(/\.js$/) && !isExcluded(fullPath)) {
files.push(fullPath);
return true;
}
}
return false;
});
return files;
}
var jasmineJsFiles = allJasmineJsFiles(".");
jasmineJsFiles.reverse(); //cheap way to do the stuff in src stuff first
var jasmineJsHintConfig = {
forin:true, //while it's possible that we could be
//considering unwanted prototype methods, mostly
//we're doing this because the jsobjects are being
//used as maps.
loopfunc:true //we're fine with functions defined inside loops (setTimeout functions, etc)
};
var jasmineGlobals = {};
//jasmine.undefined is a jasmine-ism, let's let it go...
function removeJasmineUndefinedErrors(errors) {
var keepErrors = [];
for (var i = 0; i < errors.length; i++) {
if (!(errors[i] &&
errors[i].raw &&
errors[i].evidence &&
( errors[i].evidence.match(/jasmine\.undefined/) ||
errors[i].evidence.match(/diz be undefined yo/) )
)) {
keepErrors.push(errors[i]);
}
}
return keepErrors;
}
(function() {
var ansi = {
green: '\033[32m',
red: '\033[31m',
yellow: '\033[33m',
none: '\033[0m'
};
for (var i = 0; i < jasmineJsFiles.length; i++) {
var file = jasmineJsFiles[i];
JSHINT(fs.readFileSync(file, "utf8"), jasmineJsHintConfig);
var errors = JSHINT.data().errors || [];
errors = removeJasmineUndefinedErrors(errors);
if (errors.length >= 1) {
console.log(ansi.red + "Jasmine JSHint failure: " + ansi.none);
console.log(file);
console.log(errors);
process.exit(1);
}
}
console.log(ansi.green + "Jasmine JSHint PASSED." + ansi.none);
})();

36
lib/jasmine-core.rb Normal file
View File

@@ -0,0 +1,36 @@
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
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 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
end
end
end

View File

@@ -0,0 +1,54 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Jasmine Spec Runner</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-1.1.0.rc1/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine-1.1.0.rc1/jasmine.css">
<script type="text/javascript" src="lib/jasmine-1.1.0.rc1/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-1.1.0.rc1/jasmine-html.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="spec/SpecHelper.js"></script>
<script type="text/javascript" src="spec/PlayerSpec.js"></script>
<!-- include source files here... -->
<script type="text/javascript" src="src/Player.js"></script>
<script type="text/javascript" src="src/Song.js"></script>
<script type="text/javascript">
(function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var trivialReporter = new jasmine.TrivialReporter();
jasmineEnv.addReporter(trivialReporter);
jasmineEnv.specFilter = function(spec) {
return trivialReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
execJasmine();
};
function execJasmine() {
jasmineEnv.execute();
}
})();
</script>
</head>
<body>
</body>
</html>

View File

@@ -2,8 +2,8 @@ beforeEach(function() {
this.addMatchers({
toBePlaying: function(expectedSong) {
var player = this.actual;
return player.currentlyPlayingSong === expectedSong
&& player.isPlaying;
return player.currentlyPlayingSong === expectedSong &&
player.isPlaying;
}
})
});
});

View File

@@ -0,0 +1,681 @@
jasmine.HtmlReporterHelpers = {};
jasmine.HtmlReporterHelpers.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.HtmlReporterHelpers.getSpecStatus = function(child) {
var results = child.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.skipped) {
status = 'skipped';
}
return status;
};
jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) {
var parentDiv = this.dom.summary;
var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite';
var parent = child[parentSuite];
if (parent) {
if (typeof this.views.suites[parent.id] == 'undefined') {
this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views);
}
parentDiv = this.views.suites[parent.id].element;
}
parentDiv.appendChild(childElement);
};
jasmine.HtmlReporterHelpers.addHelpers = function(ctor) {
for(var fn in jasmine.HtmlReporterHelpers) {
ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn];
}
};
jasmine.HtmlReporter = function(_doc) {
var self = this;
var doc = _doc || window.document;
var reporterView;
var dom = {};
// Jasmine Reporter Public Interface
self.logRunningSpecs = false;
self.reportRunnerStarting = function(runner) {
var specs = runner.specs() || [];
if (specs.length == 0) {
return;
}
createReporterDom(runner.env.versionString());
doc.body.appendChild(dom.reporter);
setExceptionHandling();
reporterView = new jasmine.HtmlReporter.ReporterView(dom);
reporterView.addSpecs(specs, self.specFilter);
};
self.reportRunnerResults = function(runner) {
reporterView && reporterView.complete();
};
self.reportSuiteResults = function(suite) {
reporterView.suiteComplete(suite);
};
self.reportSpecStarting = function(spec) {
if (self.logRunningSpecs) {
self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
}
};
self.reportSpecResults = function(spec) {
reporterView.specComplete(spec);
};
self.log = function() {
var console = jasmine.getGlobal().console;
if (console && console.log) {
if (console.log.apply) {
console.log.apply(console, arguments);
} else {
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
}
}
};
self.specFilter = function(spec) {
if (!focusedSpecName()) {
return true;
}
return spec.getFullName().indexOf(focusedSpecName()) === 0;
};
return self;
function focusedSpecName() {
var specName;
(function memoizeFocusedSpec() {
if (specName) {
return;
}
var paramMap = [];
var params = jasmine.HtmlReporter.parameters(doc);
for (var i = 0; i < params.length; i++) {
var p = params[i].split('=');
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
}
specName = paramMap.spec;
})();
return specName;
}
function createReporterDom(version) {
dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' },
dom.banner = self.createDom('div', { className: 'banner' },
self.createDom('span', { className: 'title' }, "Jasmine "),
self.createDom('span', { className: 'version' }, version)),
dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
dom.alert = self.createDom('div', {className: 'alert'},
self.createDom('span', { className: 'exceptions' },
self.createDom('label', { className: 'label', 'for': 'no_try_catch' }, 'No try/catch'),
self.createDom('input', { id: 'no_try_catch', type: 'checkbox' }))),
dom.results = self.createDom('div', {className: 'results'},
dom.summary = self.createDom('div', { className: 'summary' }),
dom.details = self.createDom('div', { id: 'details' }))
);
}
function noTryCatch() {
return window.location.search.match(/catch=false/);
}
function searchWithCatch() {
var params = jasmine.HtmlReporter.parameters(window.document);
var removed = false;
var i = 0;
while (!removed && i < params.length) {
if (params[i].match(/catch=/)) {
params.splice(i, 1);
removed = true;
}
i++;
}
if (jasmine.CATCH_EXCEPTIONS) {
params.push("catch=false");
}
return params.join("&");
}
function setExceptionHandling() {
var chxCatch = document.getElementById('no_try_catch');
if (noTryCatch()) {
chxCatch.setAttribute('checked', true);
jasmine.CATCH_EXCEPTIONS = false;
}
chxCatch.onclick = function() {
window.location.search = searchWithCatch();
};
}
};
jasmine.HtmlReporter.parameters = function(doc) {
var paramStr = doc.location.search.substring(1);
var params = [];
if (paramStr.length > 0) {
params = paramStr.split('&');
}
return params;
}
jasmine.HtmlReporter.sectionLink = function(sectionName) {
var link = '?';
var params = [];
if (sectionName) {
params.push('spec=' + encodeURIComponent(sectionName));
}
if (!jasmine.CATCH_EXCEPTIONS) {
params.push("catch=false");
}
if (params.length > 0) {
link += params.join("&");
}
return link;
};
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);
jasmine.HtmlReporter.ReporterView = function(dom) {
this.startedAt = new Date();
this.runningSpecCount = 0;
this.completeSpecCount = 0;
this.passedCount = 0;
this.failedCount = 0;
this.skippedCount = 0;
this.createResultsMenu = function() {
this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'},
this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'),
' | ',
this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing'));
this.summaryMenuItem.onclick = function() {
dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, '');
};
this.detailsMenuItem.onclick = function() {
showDetails();
};
};
this.addSpecs = function(specs, specFilter) {
this.totalSpecCount = specs.length;
this.views = {
specs: {},
suites: {}
};
for (var i = 0; i < specs.length; i++) {
var spec = specs[i];
this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views);
if (specFilter(spec)) {
this.runningSpecCount++;
}
}
};
this.specComplete = function(spec) {
this.completeSpecCount++;
if (isUndefined(this.views.specs[spec.id])) {
this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom);
}
var specView = this.views.specs[spec.id];
switch (specView.status()) {
case 'passed':
this.passedCount++;
break;
case 'failed':
this.failedCount++;
break;
case 'skipped':
this.skippedCount++;
break;
}
specView.refresh();
this.refresh();
};
this.suiteComplete = function(suite) {
var suiteView = this.views.suites[suite.id];
if (isUndefined(suiteView)) {
return;
}
suiteView.refresh();
};
this.refresh = function() {
if (isUndefined(this.resultsMenu)) {
this.createResultsMenu();
}
// currently running UI
if (isUndefined(this.runningAlert)) {
this.runningAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "runningAlert bar" });
dom.alert.appendChild(this.runningAlert);
}
this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);
// skipped specs UI
if (isUndefined(this.skippedAlert)) {
this.skippedAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "skippedAlert bar" });
}
this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
if (this.skippedCount === 1 && isDefined(dom.alert)) {
dom.alert.appendChild(this.skippedAlert);
}
// passing specs UI
if (isUndefined(this.passedAlert)) {
this.passedAlert = this.createDom('span', { href: jasmine.HtmlReporter.sectionLink(), className: "passingAlert bar" });
}
this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);
// failing specs UI
if (isUndefined(this.failedAlert)) {
this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"});
}
this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount);
if (this.failedCount === 1 && isDefined(dom.alert)) {
dom.alert.appendChild(this.failedAlert);
dom.alert.appendChild(this.resultsMenu);
}
// summary info
this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount);
this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing";
};
this.complete = function() {
dom.alert.removeChild(this.runningAlert);
this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
if (this.failedCount === 0) {
dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount)));
} else {
showDetails();
}
dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"));
};
return this;
function showDetails() {
if (dom.reporter.className.search(/showDetails/) === -1) {
dom.reporter.className += " showDetails";
}
}
function isUndefined(obj) {
return typeof obj === 'undefined';
}
function isDefined(obj) {
return !isUndefined(obj);
}
function specPluralizedFor(count) {
var str = count + " spec";
if (count > 1) {
str += "s"
}
return str;
}
};
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView);
jasmine.HtmlReporter.SpecView = function(spec, dom, views) {
this.spec = spec;
this.dom = dom;
this.views = views;
this.symbol = this.createDom('li', { className: 'pending' });
this.dom.symbolSummary.appendChild(this.symbol);
this.summary = this.createDom('div', { className: 'specSummary' },
this.createDom('a', {
className: 'description',
href: jasmine.HtmlReporter.sectionLink(this.spec.getFullName()),
title: this.spec.getFullName()
}, this.spec.description)
);
this.detail = this.createDom('div', { className: 'specDetail' },
this.createDom('a', {
className: 'description',
href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
title: this.spec.getFullName()
}, this.spec.getFullName())
);
};
jasmine.HtmlReporter.SpecView.prototype.status = function() {
return this.getSpecStatus(this.spec);
};
jasmine.HtmlReporter.SpecView.prototype.refresh = function() {
this.symbol.className = this.status();
switch (this.status()) {
case 'skipped':
break;
case 'passed':
this.appendSummaryToSuiteDiv();
break;
case 'failed':
this.appendSummaryToSuiteDiv();
this.appendFailureDetail();
break;
}
};
jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() {
this.summary.className += ' ' + this.status();
this.appendToSummary(this.spec, this.summary);
};
jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() {
this.detail.className += ' ' + this.status();
var resultItems = this.spec.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) {
this.detail.appendChild(messagesDiv);
this.dom.details.appendChild(this.detail);
}
};
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) {
this.suite = suite;
this.dom = dom;
this.views = views;
this.element = this.createDom('div', { className: 'suite' },
this.createDom('a', { className: 'description', href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()) }, this.suite.description)
);
this.appendToSummary(this.suite, this.element);
};
jasmine.HtmlReporter.SuiteView.prototype.status = function() {
return this.getSpecStatus(this.suite);
};
jasmine.HtmlReporter.SuiteView.prototype.refresh = function() {
this.element.className += " " + this.status();
};
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView);
/* @deprecated Use jasmine.HtmlReporter instead
*/
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', { id: 'TrivialReporter', className: 'jasmine_reporter' },
this.createDom('div', { className: 'banner' },
this.createDom('div', { className: 'logo' },
this.createDom('span', { className: 'title' }, "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.onclick = function(evt) {
if (showPassed.checked) {
self.outerDiv.className += ' show-passed';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
}
};
showSkipped.onclick = function(evt) {
if (showSkipped.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) {
if (console.log.apply) {
console.log.apply(console, arguments);
} else {
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
}
}
};
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;
};

View File

@@ -0,0 +1,82 @@
body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
#HTMLReporter a { text-decoration: none; }
#HTMLReporter a:hover { text-decoration: underline; }
#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; }
#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; }
#HTMLReporter #jasmine_content { position: fixed; right: 100%; }
#HTMLReporter .version { color: #aaaaaa; }
#HTMLReporter .banner { margin-top: 14px; }
#HTMLReporter .duration { color: #aaaaaa; float: right; }
#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; }
#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
#HTMLReporter .symbolSummary li.passed { font-size: 14px; }
#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; }
#HTMLReporter .symbolSummary li.failed { line-height: 9px; }
#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
#HTMLReporter .symbolSummary li.skipped { font-size: 14px; }
#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
#HTMLReporter .symbolSummary li.pending { line-height: 11px; }
#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
#HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
#HTMLReporter .runningAlert { background-color: #666666; }
#HTMLReporter .skippedAlert { background-color: #aaaaaa; }
#HTMLReporter .skippedAlert:first-child { background-color: #333333; }
#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; }
#HTMLReporter .passingAlert { background-color: #a6b779; }
#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; }
#HTMLReporter .failingAlert { background-color: #cf867e; }
#HTMLReporter .failingAlert:first-child { background-color: #b03911; }
#HTMLReporter .results { margin-top: 14px; }
#HTMLReporter #details { display: none; }
#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; }
#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
#HTMLReporter.showDetails .summary { display: none; }
#HTMLReporter.showDetails #details { display: block; }
#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
#HTMLReporter .summary { margin-top: 14px; }
#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; }
#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; }
#HTMLReporter .summary .specSummary.failed a { color: #b03911; }
#HTMLReporter .description + .suite { margin-top: 0; }
#HTMLReporter .suite { margin-top: 14px; }
#HTMLReporter .suite a { color: #333333; }
#HTMLReporter #details .specDetail { margin-bottom: 28px; }
#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; }
#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; }
#HTMLReporter .resultMessage span.result { display: block; }
#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ }
#TrivialReporter a:visited, #TrivialReporter a { color: #303; }
#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; }
#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; }
#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; }
#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; }
#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; }
#TrivialReporter .runner.running { background-color: yellow; }
#TrivialReporter .options { text-align: right; font-size: .8em; }
#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; }
#TrivialReporter .suite .suite { margin: 5px; }
#TrivialReporter .suite.passed { background-color: #dfd; }
#TrivialReporter .suite.failed { background-color: #fdd; }
#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; }
#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; }
#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; }
#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; }
#TrivialReporter .spec.skipped { background-color: #bbb; }
#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; }
#TrivialReporter .passed { background-color: #cfc; display: none; }
#TrivialReporter .failed { background-color: #fbb; }
#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; }
#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; }
#TrivialReporter .resultMessage .mismatch { color: black; }
#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; }
#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; }
#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; }
#TrivialReporter #jasmine_content { position: fixed; right: 100%; }
#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; }

File diff suppressed because it is too large Load Diff

1
lib/jasmine-core/spec Symbolic link
View File

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

View File

@@ -0,0 +1,6 @@
module Jasmine
module Core
VERSION = "1.3.1"
end
end

View File

@@ -1,188 +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' },
this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "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.onclick = function(evt) {
if (showPassed.checked) {
self.outerDiv.className += ' show-passed';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
}
};
showSkipped.onclick = function(evt) {
if (showSkipped.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) {
if (console.log.apply) {
console.log.apply(console, arguments);
} else {
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
}
}
};
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;
};

View File

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

2
pages

Submodule pages updated: 366a658e43...dae7b20e1c

View File

@@ -0,0 +1,451 @@
describe("ConsoleReporter", function() {
//keep these literal. otherwise the test loses value as a test.
function green(str) {
return '\033[32m' + str + '\033[0m';
}
function red(str) {
return '\033[31m' + str + '\033[0m';
}
function yellow(str) {
return '\033[33m' + str + '\033[0m';
}
function prefixGreen(str) {
return '\033[32m' + str;
}
function prefixRed(str) {
return '\033[31m' + str;
}
var newline = "\n";
var passingSpec = {
results: function() {
return {
passed: function() {
return true;
}
};
}
},
failingSpec = {
results: function() {
return {
passed: function() {
return false;
}
};
}
},
skippedSpec = {
results: function() {
return {skipped: true};
}
},
passingRun = {
specs: function() {
return [null, null, null];
},
results: function() {
return {failedCount: 0, items_: [null, null, null]};
}
},
failingRun = {
specs: function() {
return [null, null, null];
},
results: function() {
return {
failedCount: 7, items_: [null, null, null]};
}
};
function repeatedlyInvoke(f, times) {
for (var i = 0; i < times; i++) f(times + 1);
}
function repeat(thing, times) {
var arr = [];
for (var i = 0; i < times; i++) arr.push(thing);
return arr;
}
function simulateRun(reporter, specResults, suiteResults, finalRunner, startTime, endTime) {
reporter.reportRunnerStarting();
for (var i = 0; i < specResults.length; i++) {
reporter.reportSpecResults(specResults[i]);
}
for (i = 0; i < suiteResults.length; i++) {
reporter.reportSuiteResults(suiteResults[i]);
}
reporter.runnerStartTime = startTime;
reporter.now = function() {
return endTime;
};
reporter.reportRunnerResults(finalRunner);
}
var reporter, out, done;
beforeEach(function() {
out = (function() {
var output = "";
return {
print:function(str) {
output += str;
},
getOutput:function() {
return output;
},
clear: function() {
output = "";
}
};
})();
done = false;
reporter = new jasmine.ConsoleReporter(out.print, function(runner) {
done = true
});
});
describe('Integration', function() {
it("prints the proper output under a pass scenario - small numbers.", function() {
simulateRun(reporter,
repeat(passingSpec, 3),
[],
{
specs: function() {
return [null, null, null];
},
results:function() {
return {
items_: [null, null, null],
totalCount: 7,
failedCount: 0
};
}
},
1000,
1777
);
var output = out.getOutput();
expect(output).toMatch(/^Started/);
expect(output).toMatch(/\.\.\./);
expect(output).toMatch(/3 specs, 0 failures/);
});
it("prints the proper output under a pass scenario. large numbers.", function() {
simulateRun(reporter,
repeat(passingSpec, 57),
[],
{
specs: function() {
return [null, null, null];
},
results:function() {
return {
items_: [null, null, null],
totalCount: 7,
failedCount: 0
};
}
},
1000,
1777);
var output = out.getOutput();
expect(output).toMatch(/^Started/);
expect(output).toMatch(/\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\./);
expect(output).toMatch(/3 specs, 0 failures/);
});
it("prints the proper output under a failure scenario.", function() {
simulateRun(reporter,
[failingSpec, passingSpec, failingSpec],
[
{description:"The oven",
results:function() {
return {
items_:[
{failedCount:2,
description:"heats up",
items_:[
{trace:{stack:"stack trace one\n second line"}},
{trace:{stack:"stack trace two"}}
]}
]
};
}},
{description:"The washing machine",
results:function() {
return {
items_:[
{failedCount:2,
description:"washes clothes",
items_:[
{trace:{stack:"stack trace one"}}
]}
]
};
}}
],
{
specs: function() {
return [null, null, null];
},
results:function() {
return {
items_: [null, null, null],
totalCount: 7,
failedCount: 2
};
}
},
1000,
1777);
var output = out.getOutput();
expect(output).toMatch(/^Started/);
expect(output).toMatch(/F\.F/);
expect(output).toMatch(/The oven heats up\n stack trace one\n second line\n stack trace two/);
expect(output).toMatch(/The washing machine washes clothes\n stack trace one/);
expect(output).toMatch(/3 specs, 2 failures/);
});
});
describe('When a Jasmine environment executes', function() {
beforeEach(function() {
reporter.reportRunnerStarting();
});
it("should print 'Started' to the console", function() {
expect(out.getOutput()).toEqual("Started" + newline);
});
describe('when a spec reports', function() {
beforeEach(function() {
out.clear();
});
it("prints a green dot if the spec passes", function() {
reporter.reportSpecResults(passingSpec);
expect(out.getOutput()).toMatch(/\./);
});
it("prints a red dot if the spec fails", function() {
reporter.reportSpecResults(failingSpec);
expect(out.getOutput()).toMatch(/F/);
});
it("prints a yellow star if the spec was skipped", function() {
reporter.reportSpecResults(skippedSpec);
expect(out.getOutput()).toMatch(/\*/);
});
});
describe('when a suite reports', function() {
var emptyResults;
beforeEach(function() {
emptyResults = function() {
return {
items_:[]
};
};
});
it("remembers suite results", function() {
reporter.reportSuiteResults({description: "Oven", results: emptyResults});
reporter.reportSuiteResults({description: "Mixer", results: emptyResults});
expect(reporter.suiteResults[0].description).toEqual('Oven');
expect(reporter.suiteResults[1].description).toEqual('Mixer');
});
it("creates a description out of the current suite and any parent suites", function() {
var grandparentSuite = {
description: "My house",
results: emptyResults
};
var parentSuite = {
description: "kitchen",
parentSuite: grandparentSuite,
results: emptyResults
};
reporter.reportSuiteResults({ description: "oven", parentSuite: parentSuite, results: emptyResults });
expect(reporter.suiteResults[0].description).toEqual("My house kitchen oven");
});
it("gathers failing spec results from the suite - the spec must have a description.", function() {
reporter.reportSuiteResults({description:"Oven",
results: function() {
return {
items_:[
{ failedCount: 0, description: "specOne" },
{ failedCount: 99, description: "specTwo" },
{ failedCount: 0, description: "specThree" },
{ failedCount: 88, description: "specFour" },
{ failedCount: 3 }
]
};
}});
expect(reporter.suiteResults[0].failedSpecResults).
toEqual([
{ failedCount: 99, description: "specTwo" },
{ failedCount: 88, description: "specFour" }
]);
});
});
describe('and finishes', function() {
describe('when reporting spec failure information', function() {
it("prints suite and spec descriptions together as a sentence", function() {
reporter.suiteResults = [
{description:"The oven", failedSpecResults:[
{description:"heats up", items_:[]},
{description:"cleans itself", items_:[]}
]},
{description:"The mixer", failedSpecResults:[
{description:"blends things together", items_:[]}
]}
];
reporter.reportRunnerResults(failingRun);
expect(out.getOutput()).toContain("The oven heats up");
expect(out.getOutput()).toContain("The oven cleans itself");
expect(out.getOutput()).toContain("The mixer blends things together");
});
it("prints stack trace of spec failure", function() {
reporter.suiteResults = [
{description:"The oven", failedSpecResults:[
{description:"heats up",
items_:[
{trace:{stack:"stack trace one"}},
{trace:{stack:"stack trace two"}}
]}
]}
];
reporter.reportRunnerResults(failingRun);
expect(out.getOutput()).toContain("The oven heats up");
expect(out.getOutput()).toContain("stack trace one");
expect(out.getOutput()).toContain("stack trace two");
});
});
describe('when reporting the execution time', function() {
it("prints the full finished message", function() {
reporter.now = function() {
return 1000;
};
reporter.reportRunnerStarting();
reporter.now = function() {
return 1777;
};
reporter.reportRunnerResults(failingRun);
expect(out.getOutput()).toContain("Finished in 0.777 seconds");
});
it("prints round time numbers correctly", function() {
function run(startTime, endTime) {
out.clear();
reporter.runnerStartTime = startTime;
reporter.now = function() {
return endTime;
};
reporter.reportRunnerResults(passingRun);
}
run(1000, 11000);
expect(out.getOutput()).toContain("10 seconds");
run(1000, 2000);
expect(out.getOutput()).toContain("1 seconds");
run(1000, 1100);
expect(out.getOutput()).toContain("0.1 seconds");
run(1000, 1010);
expect(out.getOutput()).toContain("0.01 seconds");
run(1000, 1001);
expect(out.getOutput()).toContain("0.001 seconds");
});
});
describe("when reporting the results summary", function() {
it("prints statistics in green if there were no failures", function() {
reporter.reportRunnerResults({
specs: function() {
return [null, null, null];
},
results:function() {
return {items_: [null, null, null], totalCount: 7, failedCount: 0};
}
});
expect(out.getOutput()).
toContain("3 specs, 0 failures");
});
it("prints statistics in red if there was a failure", function() {
reporter.reportRunnerResults({
specs: function() {
return [null, null, null];
},
results:function() {
return {items_: [null, null, null], totalCount: 7, failedCount: 3};
}
});
expect(out.getOutput()).
toContain("3 specs, 3 failures");
});
it("handles pluralization with 1's ones appropriately", function() {
reporter.reportRunnerResults({
specs: function() {
return [null];
},
results:function() {
return {items_: [null], totalCount: 1, failedCount: 1};
}
});
expect(out.getOutput()).
toContain("1 spec, 1 failure");
});
});
describe("done callback", function() {
it("calls back when done", function() {
expect(done).toBeFalsy();
reporter.reportRunnerResults({
specs: function() {
return [null, null, null];
},
results:function() {
return {items_: [null, null, null], totalCount: 7, failedCount: 0};
}
});
expect(done).toBeTruthy();
});
});
});
});
});

View File

@@ -64,9 +64,10 @@ describe("jasmine.Env", function() {
"major": 1,
"minor": 9,
"build": 7,
"release_candidate": "1",
"revision": 8
};
expect(env.versionString()).toEqual("1.9.7 revision 8");
expect(env.versionString()).toEqual("1.9.7.rc1 revision 8");
});
it("should return a nice string when version is unknown", function() {
@@ -108,7 +109,7 @@ describe("jasmine.Env", function() {
it("should give custom equality testers precedence", function() {
expect(env.equals_('abc', 'abc')).toBeFalsy();
var o = new Object();
var o = {};
expect(env.equals_(o, o)).toBeFalsy();
});
});

175
spec/core/ExceptionsSpec.js Normal file
View File

@@ -0,0 +1,175 @@
describe('Exceptions:', function() {
var env;
beforeEach(function() {
env = new jasmine.Env();
env.updateInterval = 0;
});
it('jasmine.formatException formats Firefox exception messages as expected', function() {
var sampleFirefoxException = {
fileName: 'foo.js',
line: '1978',
message: 'you got your foo in my bar',
name: 'A Classic Mistake'
};
var expected = 'A Classic Mistake: you got your foo in my bar in foo.js (line 1978)';
expect(jasmine.util.formatException(sampleFirefoxException)).toEqual(expected);
});
it('jasmine.formatException formats Webkit exception messages as expected', function() {
var sampleWebkitException = {
sourceURL: 'foo.js',
lineNumber: '1978',
message: 'you got your foo in my bar',
name: 'A Classic Mistake'
};
var expected = 'A Classic Mistake: you got your foo in my bar in foo.js (line 1978)';
expect(jasmine.util.formatException(sampleWebkitException)).toEqual(expected);
});
describe('with break on exception', function() {
it('should not catch the exception', function() {
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!';
var oldCatch = jasmine.CATCH_EXCEPTIONS;
jasmine.CATCH_EXCEPTIONS = false;
try {
suite.execute();
dont_change = 'oops I changed';
}
catch (e) {}
finally {
jasmine.CATCH_EXCEPTIONS = oldCatch;
}
expect(dont_change).toEqual('I will never change!');
});
});
describe("with catch on exception", function() {
it('should handle exceptions thrown, but continue', function() {
var fakeTimer = new jasmine.FakeTimer();
env.setTimeout = fakeTimer.setTimeout;
env.clearTimeout = fakeTimer.clearTimeout;
env.setInterval = fakeTimer.setInterval;
env.clearInterval = fakeTimer.clearInterval;
//we run two exception tests to make sure we continue after throwing an exception
var 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('fake error 1');
});
env.it('should be another test that fails because it throws an exception', function() {
this.runs(function () {
throw new Error('fake error 2');
});
this.runs(function () {
this.expect(true).toEqual(true);
});
});
env.it('should be a passing test that runs after exceptions are thrown', function() {
this.expect(true).toEqual(true);
});
env.it('should be another test that fails because it throws an exception after a wait', function() {
this.runs(function () {
var foo = 'foo';
});
this.waits(250);
this.runs(function () {
throw new Error('fake error 3');
});
});
env.it('should be a passing test that runs after exceptions are thrown from a async test', function() {
this.expect(true).toEqual(true);
});
});
var runner = env.currentRunner();
suite.execute();
fakeTimer.tick(2500);
var suiteResults = suite.results();
var specResults = suiteResults.getItems();
expect(suiteResults.passed()).toEqual(false);
//
expect(specResults.length).toEqual(5);
expect(specResults[0].passed()).toMatch(false);
var blockResults = specResults[0].getItems();
expect(blockResults[0].passed()).toEqual(false);
expect(blockResults[0].message).toMatch(/fake error 1/);
expect(specResults[1].passed()).toEqual(false);
blockResults = specResults[1].getItems();
expect(blockResults[0].passed()).toEqual(false);
expect(blockResults[0].message).toMatch(/fake error 2/);
expect(blockResults[1].passed()).toEqual(true);
expect(specResults[2].passed()).toEqual(true);
expect(specResults[3].passed()).toEqual(false);
blockResults = specResults[3].getItems();
expect(blockResults[0].message).toMatch(/fake error 3/);
expect(specResults[4].passed()).toEqual(true);
});
it("should handle exceptions thrown directly in top-level describe blocks and continue", function () {
var suite = env.describe("a top level describe block 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");
});
suite.execute();
var suiteResults = suite.results();
var specResults = suiteResults.getItems();
expect(suiteResults.passed()).toEqual(false);
expect(specResults.length).toEqual(2);
expect(specResults[1].description).toMatch(/encountered a declaration exception/);
});
it("should handle exceptions thrown directly in nested describe blocks and continue", function () {
var suite = env.describe("a top level describe", function () {
env.describe("a mid-level describe that throws an exception", function () {
env.it("is a test that should pass", function () {
this.expect(true).toEqual(true);
});
throw new Error("a mid-level error");
});
});
suite.execute();
var suiteResults = suite.results();
var specResults = suiteResults.getItems();
expect(suiteResults.passed()).toEqual(false);
expect(specResults.length).toEqual(1);
var nestedSpecResults = specResults[0].getItems();
expect(nestedSpecResults.length).toEqual(2);
expect(nestedSpecResults[1].description).toMatch(/encountered a declaration exception/);
});
});
});

View File

@@ -21,7 +21,7 @@ describe('jasmine.jsApiReporter', function() {
nestedSuite = env.describe("nested suite", function() {
nestedSpec = env.it("nested spec", function() {
expect(true).toEqual(true);
})
});
});
spec3 = env.it("spec 3", function() {

View File

@@ -18,7 +18,7 @@ describe("jasmine.Matchers", function() {
toFail: function() {
return !lastResult().passed();
}
})
});
});
function match(value) {
@@ -68,20 +68,25 @@ describe("jasmine.Matchers", function() {
expect((match(['a', 'b']).toEqual(['a', jasmine.undefined]))).toFail();
expect((match(['a', 'b']).toEqual(['a', 'b', jasmine.undefined]))).toFail();
expect((match(new String("cat")).toEqual("cat"))).toPass();
expect((match(new String("cat")).toNotEqual("cat"))).toFail();
expect((match("cat").toEqual("cat"))).toPass();
expect((match("cat").toNotEqual("cat"))).toFail();
expect((match(new Number(5)).toEqual(5))).toPass();
expect((match(new Number('5')).toEqual(5))).toPass();
expect((match(new Number(5)).toNotEqual(5))).toFail();
expect((match(new Number('5')).toNotEqual(5))).toFail();
});
expect((match(5).toEqual(5))).toPass();
expect((match(parseInt('5', 10)).toEqual(5))).toPass();
expect((match(5).toNotEqual(5))).toFail();
expect((match(parseInt('5', 10)).toNotEqual(5))).toFail();
it("toEqual with DOM nodes", function() {
var nodeA = document.createElement('div');
var nodeB = document.createElement('div');
expect((match(nodeA).toEqual(nodeA))).toPass();
expect((match(nodeA).toEqual(nodeB))).toFail();
expect((match(/1/i).toEqual(/1/i))).toPass();
expect((match(/1/i).toNotEqual(/1/i))).toFail();
expect((match(/[abc]/gm).toEqual(/1/i))).toFail();
expect((match(/[abc]/gm).toNotEqual(/1/i))).toPass();
// only test if the browser supports the sticky option on a regExp see pull #234
if (RegExp.prototype.sticky !== undefined) {
var sticky_regexp = new RegExp("[abc]", "y");
expect((match(sticky_regexp).toEqual(/1/i))).toFail();
expect((match(sticky_regexp).toNotEqual(/1/i))).toPass();
}
});
it("toEqual to build an Expectation Result", function() {
@@ -288,6 +293,29 @@ describe("jasmine.Matchers", function() {
expect(result.actual).toEqual(actual);
});
it("toBeNaN", function() {
expect(match(Number.NaN).toBeNaN()).toPass();
expect(match(0).toBeNaN()).toFail();
expect(match(1).toBeNaN()).toFail();
expect(match(null).toBeNaN()).toFail();
expect(match(Number.POSITIVE_INFINITY).toBeNaN()).toFail();
expect(match(Number.NEGATIVE_INFINITY).toBeNaN()).toFail();
expect(match('NaN').toBeNaN()).toFail();
});
it("toBeNaN to build an ExpectationResult", function() {
var actual = 'a';
var matcher = match(actual);
matcher.toBeNaN();
var result = lastResult();
expect(result.matcherName).toEqual("toBeNaN");
expect(result.passed()).toFail();
expect(result.message).toMatch("Expected 'a' to be NaN.");
expect(result.actual).toMatch(actual);
});
it("toBeFalsy", function() {
expect(match(false).toBeFalsy()).toPass();
expect(match(true).toBeFalsy()).toFail();
@@ -348,15 +376,44 @@ describe("jasmine.Matchers", function() {
expect(match("foo").toEqual(jasmine.any(Object))).toFail();
expect(match({someObj:'foo'}).toEqual(jasmine.any(Object))).toPass();
expect(match({someObj:'foo'}).toEqual(jasmine.any(Function))).toFail();
expect(match(function() {
}).toEqual(jasmine.any(Object))).toFail();
expect(match(
function() {
}).toEqual(jasmine.any(Object))).toFail();
expect(match(["foo", "goo"]).toEqual(["foo", jasmine.any(String)])).toPass();
expect(match(function() {
}).toEqual(jasmine.any(Function))).toPass();
expect(match(
function() {
}).toEqual(jasmine.any(Function))).toPass();
expect(match(["a", function() {
}]).toEqual(["a", jasmine.any(Function)])).toPass();
});
describe("toEqual with an object implementing jasmineMatches", function () {
var matcher;
beforeEach(function () {
matcher = {
jasmineMatches: jasmine.createSpy("jasmineMatches")
};
});
describe("on the left side", function () {
it("uses the jasmineMatches function", function () {
matcher.jasmineMatches.andReturn(false);
expect(match(matcher).toEqual("foo")).toFail();
matcher.jasmineMatches.andReturn(true);
expect(match(matcher).toEqual("foo")).toPass();
});
});
describe("on the right side", function () {
it("uses the jasmineMatches function", function () {
matcher.jasmineMatches.andReturn(false);
expect(match("foo").toEqual(matcher)).toFail();
matcher.jasmineMatches.andReturn(true);
expect(match("foo").toEqual(matcher)).toPass();
});
});
});
it("toEqual handles circular objects ok", function() {
expect(match({foo: "bar", baz: jasmine.undefined}).toEqual({foo: "bar", baz: jasmine.undefined})).toPass();
expect(match({foo:['bar','baz','quux']}).toEqual({foo:['bar','baz','quux']})).toPass();
@@ -471,6 +528,52 @@ describe("jasmine.Matchers", function() {
expect(result.expected).toEqual(expected);
});
describe("toBeCloseTo", function() {
it("returns 'true' iff actual and expected are equal within 2 decimal points of precision", function() {
expect(0).toBeCloseTo(0);
expect(1).toBeCloseTo(1);
expect(1).not.toBeCloseTo(1.1);
expect(1).not.toBeCloseTo(1.01);
expect(1).toBeCloseTo(1.001);
expect(1.23).toBeCloseTo(1.234);
expect(1.23).toBeCloseTo(1.233);
expect(1.23).toBeCloseTo(1.232);
expect(1.23).not.toBeCloseTo(1.24);
expect(-1.23).toBeCloseTo(-1.234);
expect(-1.23).not.toBeCloseTo(-1.24);
});
it("expects close numbers to 'be close' and further numbers not to", function() {
expect(1.225).not.toBeCloseTo(1.234); // difference is 0.009
expect(1.225).toBeCloseTo(1.224); // difference is 0.001
});
it("accepts an optional precision argument", function() {
expect(1).toBeCloseTo(1.1, 0);
expect(1.2).toBeCloseTo(1.23, 1);
expect(1.234).toBeCloseTo(1.2343, 3);
expect(1.234).not.toBeCloseTo(1.233, 3);
});
it("rounds", function() {
expect(1.23).toBeCloseTo(1.229);
expect(1.23).toBeCloseTo(1.226);
expect(1.23).toBeCloseTo(1.225);
expect(1.23).not.toBeCloseTo(1.2249999);
expect(1.23).toBeCloseTo(1.234);
expect(1.23).toBeCloseTo(1.2349999);
expect(1.23).not.toBeCloseTo(1.235);
expect(-1.23).toBeCloseTo(-1.234);
expect(-1.23).not.toBeCloseTo(-1.235);
expect(-1.23).not.toBeCloseTo(-1.236);
});
});
describe("toThrow", function() {
describe("when code block throws an exception", function() {
var throwingFn;
@@ -500,7 +603,7 @@ describe("jasmine.Matchers", function() {
describe("and matcher is inverted with .not", function() {
it("should match any exception", function() {
expect(match(throwingFn).not.toThrow()).toFail();
expect(lastResult().message).toMatch(/Expected function not to throw an exception/);
expect(lastResult().message).toMatch(/Expected function not to throw an exception/);
});
it("should match exceptions specified by message", function() {
@@ -540,8 +643,9 @@ describe("jasmine.Matchers", function() {
describe("when code block does not throw an exception", function() {
it("should fail (or pass when inverted with .not)", function() {
expect(match(function() {
}).toThrow()).toFail();
expect(match(
function() {
}).toThrow()).toFail();
expect(lastResult().message).toEqual('Expected function to throw an exception.');
});
});
@@ -596,21 +700,25 @@ describe("jasmine.Matchers", function() {
function shouldThrowAnExceptionWhenInvokedOnANonSpy(methodName) {
return function() {
expect(function() {
match(TestClass.normalFunction)[methodName]();
}).toThrow('Expected a spy, but got Function.');
expect(
function() {
match(TestClass.normalFunction)[methodName]();
}).toThrow('Expected a spy, but got Function.');
expect(function() {
match(jasmine.undefined)[methodName]();
}).toThrow('Expected a spy, but got undefined.');
expect(
function() {
match(jasmine.undefined)[methodName]();
}).toThrow('Expected a spy, but got undefined.');
expect(function() {
match({some:'object'})[methodName]();
}).toThrow('Expected a spy, but got { some : \'object\' }.');
expect(
function() {
match({some:'object'})[methodName]();
}).toThrow('Expected a spy, but got { some : \'object\' }.');
expect(function() {
match("<b>")[methodName]();
}).toThrow('Expected a spy, but got \'<b>\'.');
expect(
function() {
match("<b>")[methodName]();
}).toThrow('Expected a spy, but got \'<b>\'.');
};
}
@@ -623,9 +731,10 @@ describe("jasmine.Matchers", function() {
});
it("should throw an exception when invoked with any arguments", function() {
expect(function() {
match(TestClass.normalFunction).toHaveBeenCalled("unwanted argument");
}).toThrow('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
expect(
function() {
match(TestClass.normalFunction).toHaveBeenCalled("unwanted argument");
}).toThrow('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
});
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('toHaveBeenCalled'));
@@ -651,9 +760,10 @@ describe("jasmine.Matchers", function() {
});
it("should throw an exception when invoked with any arguments", function() {
expect(function() {
match(TestClass.normalFunction).wasNotCalled("unwanted argument");
}).toThrow('wasNotCalled does not take arguments');
expect(
function() {
match(TestClass.normalFunction).wasNotCalled("unwanted argument");
}).toThrow('wasNotCalled does not take arguments');
});
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('wasNotCalled'));
@@ -701,7 +811,13 @@ describe("jasmine.Matchers", function() {
TestClass.spyFunction('d', 'e', 'f');
var expected = match(TestClass.spyFunction);
expect(expected.toHaveBeenCalledWith('a', 'b')).toFail();
expect(lastResult().message).toEqual("Expected spy to have been called with [ 'a', 'b' ] but was called with [ [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] ]");
expect(lastResult().message).toEqual("Expected spy My spy to have been called with [ 'a', 'b' ] but actual calls were [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ]");
});
it("should return a decent message when it hasn't been called", function() {
var expected = match(TestClass.spyFunction);
expect(expected.toHaveBeenCalledWith('a', 'b')).toFail();
expect(lastResult().message).toEqual("Expected spy My spy to have been called with [ 'a', 'b' ] but it was never called.");
});
it("should return a decent message when inverted", function() {
@@ -709,7 +825,7 @@ describe("jasmine.Matchers", function() {
TestClass.spyFunction('d', 'e', 'f');
var expected = match(TestClass.spyFunction);
expect(expected.not.toHaveBeenCalledWith('a', 'b', 'c')).toFail();
expect(lastResult().message).toEqual("Expected spy not to have been called with [ 'a', 'b', 'c' ] but was called with [ [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] ]");
expect(lastResult().message).toEqual("Expected spy My spy not to have been called with [ 'a', 'b', 'c' ] but it was.");
});
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('toHaveBeenCalledWith'));
@@ -787,6 +903,252 @@ describe("jasmine.Matchers", function() {
});
});
describe("ObjectContaining", function () {
describe("with an empty object", function () {
var containing;
beforeEach(function () {
containing = new jasmine.Matchers.ObjectContaining({});
});
it("matches everything", function () {
expect(containing.jasmineMatches("foo", [], [])).toBe(true);
});
it("says it didn't expect to contain anything", function () {
expect(containing.jasmineToString()).toEqual("<jasmine.objectContaining({ })>");
});
});
describe("with an object with items in it", function () {
var containing, mismatchKeys, mismatchValues;
beforeEach(function () {
mismatchKeys = [];
mismatchValues = [];
containing = new jasmine.Matchers.ObjectContaining({foo: "fooVal", bar: "barVal"});
});
it("doesn't match an empty object", function () {
expect(containing.jasmineMatches({}, mismatchKeys, mismatchValues)).toBe(false);
});
it("doesn't match an object with none of the specified options", function () {
expect(containing.jasmineMatches({baz:"stuff"}, mismatchKeys, mismatchValues)).toBe(false);
});
it("adds a message for each missing key", function () {
containing.jasmineMatches({foo: "fooVal"}, mismatchKeys, mismatchValues);
expect(mismatchKeys.length).toEqual(1);
});
it("doesn't match an object when the values are different", function () {
expect(containing.jasmineMatches({foo:"notFoo", bar:"notBar"}, mismatchKeys, mismatchValues)).toBe(false);
});
it("adds a message when values don't match", function () {
containing.jasmineMatches({foo: "fooVal", bar: "notBar"}, mismatchKeys, mismatchValues);
expect(mismatchValues.length).toEqual(1);
});
it("doesn't match an object with only one of the values matching", function () {
expect(containing.jasmineMatches({foo:"notFoo", bar:"barVal"}, mismatchKeys, mismatchValues)).toBe(false);
});
it("matches when all the values are the same", function () {
expect(containing.jasmineMatches({foo: "fooVal", bar: "barVal"}, mismatchKeys, mismatchValues)).toBe(true);
});
it("matches when there are additional values", function () {
expect(containing.jasmineMatches({foo: "fooVal", bar: "barVal", baz: "bazVal"}, mismatchKeys, mismatchValues)).toBe(true);
});
it("doesn't modify missingKeys or missingValues when match is successful", function () {
containing.jasmineMatches({foo: "fooVal", bar: "barVal"}, mismatchKeys, mismatchValues);
expect(mismatchKeys.length).toEqual(0);
expect(mismatchValues.length).toEqual(0);
});
it("says what it expects to contain", function () {
expect(containing.jasmineToString()).toEqual("<jasmine.objectContaining(" + jasmine.pp({foo:"fooVal", bar:"barVal"}) + ")>");
});
});
describe("in real life", function () {
var method;
beforeEach(function () {
method = jasmine.createSpy("method");
method({a:"b", c:"d"});
});
it("works correctly for positive matches", function () {
expect(method).toHaveBeenCalledWith(jasmine.objectContaining({a:"b"}));
});
it("works correctly for negative matches", function () {
expect(method).not.toHaveBeenCalledWith(jasmine.objectContaining({z:"x"}));
});
});
});
describe("Matchers.Any", function () {
var any;
describe(".jasmineToString", function () {
describe("with Object", function () {
it("says it's looking for an object", function () {
any = jasmine.any(Object);
expect(any.jasmineToString().replace(/\n/g, "")).toMatch(/<jasmine\.any\(function Object.*\)>/);
});
});
describe("with Function", function () {
it("says it's looking for a function", function () {
any = jasmine.any(Function);
expect(any.jasmineToString().replace(/\n/g, "")).toMatch(/<jasmine\.any\(function Function.*\)>/);
});
});
describe("with String", function () {
it("says it's looking for a string", function () {
any = jasmine.any(String);
expect(any.jasmineToString().replace(/\n/g, "")).toMatch(/<jasmine\.any\(function String.*\)>/);
});
});
describe("with Number", function () {
it("says it's looking for a number", function () {
any = jasmine.any(Number);
expect(any.jasmineToString().replace(/\n/g, "")).toMatch(/<jasmine\.any\(function Number.*\)>/);
});
});
describe("with some other defined 'class'", function () {
it("says it's looking for an object", function () {
function MyClass () {}
any = jasmine.any(MyClass);
expect(any.jasmineToString().replace("\n", "")).toMatch(/<jasmine\.any\(function MyClass.*\)>/);
});
});
});
describe(".jasmineMatches", function () {
describe("with Object", function () {
beforeEach(function () {
any = jasmine.any(Object);
});
it("matches an empty object", function () {
expect(any.jasmineMatches({})).toEqual(true);
});
it("matches a newed up object", function () {
expect(any.jasmineMatches(new Object())).toEqual(true);
});
it("doesn't match a string", function () {
expect(any.jasmineMatches("")).toEqual(false);
});
it("doesn't match a number", function () {
expect(any.jasmineMatches(123)).toEqual(false);
});
it("doesn't match a function", function () {
expect(any.jasmineMatches(function () {})).toEqual(false);
});
});
describe("with Function", function () {
beforeEach(function () {
any = jasmine.any(Function);
});
it("doesn't match an object", function () {
expect(any.jasmineMatches({})).toEqual(false);
});
it("doesn't match a string", function () {
expect(any.jasmineMatches("")).toEqual(false);
});
it("doesn't match a number", function () {
expect(any.jasmineMatches(123)).toEqual(false);
});
it("matches a function", function () {
expect(any.jasmineMatches(function () {})).toEqual(true);
});
});
describe("with Number", function () {
beforeEach(function () {
any = jasmine.any(Number);
});
it("doesn't match an object", function () {
expect(any.jasmineMatches({})).toEqual(false);
});
it("doesn't match a string", function () {
expect(any.jasmineMatches("")).toEqual(false);
});
it("matches a number", function () {
expect(any.jasmineMatches(123)).toEqual(true);
});
it("doesn't match a function", function () {
expect(any.jasmineMatches(function () {})).toEqual(false);
});
});
describe("with String", function () {
beforeEach(function () {
any = jasmine.any(String);
});
it("doesn't match an object", function () {
expect(any.jasmineMatches({})).toEqual(false);
});
it("matches a string", function () {
expect(any.jasmineMatches("")).toEqual(true);
});
it("doesn't match a number", function () {
expect(any.jasmineMatches(123)).toEqual(false);
});
it("doesn't match a function", function () {
expect(any.jasmineMatches(function () {})).toEqual(false);
});
});
describe("with some defined 'class'", function () {
function MyClass () {}
beforeEach(function () {
any = jasmine.any(MyClass);
});
it("doesn't match an object", function () {
expect(any.jasmineMatches({})).toEqual(false);
});
it("doesn't match a string", function () {
expect(any.jasmineMatches("")).toEqual(false);
});
it("doesn't match a number", function () {
expect(any.jasmineMatches(123)).toEqual(false);
});
it("doesn't match a function", function () {
expect(any.jasmineMatches(function () {})).toEqual(false);
});
it("matches an instance of the defined class", function () {
expect(any.jasmineMatches(new MyClass())).toEqual(true);
});
});
});
});
describe("all matchers", function() {
it("should return null, for future-proofing, since we might eventually allow matcher chaining", function() {
expect(match(true).toBe(true)).toBeUndefined();

View File

@@ -18,9 +18,9 @@ describe("jasmine.MultiReporter", function() {
delegate[methodName] = jasmine.createSpy(methodName);
this.actual[methodName]("whatever argument");
return delegate[methodName].wasCalled
&& delegate[methodName].mostRecentCall.args.length == 1
&& delegate[methodName].mostRecentCall.args[0] == "whatever argument";
return delegate[methodName].wasCalled &&
delegate[methodName].mostRecentCall.args.length == 1 &&
delegate[methodName].mostRecentCall.args[0] == "whatever argument";
}
});

View File

@@ -32,6 +32,36 @@ describe("jasmine.pp", 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(jasmine.pp(instance)).toEqual("{ bar : 'my own bar' }");
});
it("should not recurse objects and arrays more deeply than jasmine.MAX_PRETTY_PRINT_DEPTH", function() {
var originalMaxDepth = jasmine.MAX_PRETTY_PRINT_DEPTH;
var nestedObject = { level1: { level2: { level3: { level4: "leaf" } } } };
var nestedArray = [1, [2, [3, [4, "leaf"]]]];
try {
jasmine.MAX_PRETTY_PRINT_DEPTH = 2;
expect(jasmine.pp(nestedObject)).toEqual("{ level1 : { level2 : Object } }");
expect(jasmine.pp(nestedArray)).toEqual("[ 1, [ 2, Array ] ]");
jasmine.MAX_PRETTY_PRINT_DEPTH = 3;
expect(jasmine.pp(nestedObject)).toEqual("{ level1 : { level2 : { level3 : Object } } }");
expect(jasmine.pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, Array ] ] ]");
jasmine.MAX_PRETTY_PRINT_DEPTH = 4;
expect(jasmine.pp(nestedObject)).toEqual("{ level1 : { level2 : { level3 : { level4 : 'leaf' } } } }");
expect(jasmine.pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, [ 4, 'leaf' ] ] ] ]");
} finally {
jasmine.MAX_PRETTY_PRINT_DEPTH = originalMaxDepth;
}
});
it("should stringify RegExp objects properly", function() {
expect(jasmine.pp(/x|y|z/)).toEqual("/x|y|z/");
});
@@ -58,12 +88,6 @@ describe("jasmine.pp", function () {
}
});
it("should stringify HTML nodes properly", function() {
var sampleNode = document.createElement('div');
sampleNode.innerHTML = 'foo<b>bar</b>';
expect(jasmine.pp(sampleNode)).toEqual("HTMLNode");
expect(jasmine.pp({foo: sampleNode})).toEqual("{ foo : HTMLNode }");
});
it('should not do HTML escaping of strings', function() {
expect(jasmine.pp('some <b>html string</b> &', false)).toEqual('\'some <b>html string</b> &\'');
@@ -89,5 +113,12 @@ describe("jasmine.pp", function () {
expect(jasmine.pp(jasmine.createSpy("something"))).toEqual("spy on something");
});
it("should stringify objects that implement jasmineToString", function () {
var obj = {
jasmineToString: function () { return "strung"; }
};
expect(jasmine.pp(obj)).toEqual("strung");
});
});

View File

@@ -105,6 +105,19 @@ describe('RunnerTest', function() {
expect(runnerResults.totalCount).toEqual(3);
expect(runnerResults.passedCount).toEqual(3);
});
it('should run after a failing spec', function () {
var afterEach = jasmine.createSpy();
env.afterEach(afterEach);
env.describe('suite', function () {
env.it('fails', function () {
this.explodes();
});
}).execute();
expect(afterEach).toHaveBeenCalled();
});
});

View File

@@ -54,7 +54,7 @@ describe("jasmine spec running", function () {
this.expect(foo).toEqual('baz');
});
specWithMultipleExpectations = env.it('spec with multiple assertions').runs(function () {
specWithMultipleExpectations = env.it('spec with multiple expectations').runs(function () {
var foo = 'bar';
var baz = 'quux';
@@ -398,6 +398,123 @@ describe("jasmine spec running", function () {
expect(timeoutSpec.results().getItems()[0].message).toEqual('timeout: timed out after 500 msec waiting for something to happen');
expect(subsequentSpecRan).toEqual(true);
});
it("runs afterEach after timing out", function() {
var afterEach = jasmine.createSpy('afterEach');
env.describe('foo', function () {
env.afterEach(afterEach);
env.it('waitsFor', function () {
this.waitsFor(100, function() {
return false;
});
});
}).execute();
fakeTimer.tick(500);
expect(afterEach).toHaveBeenCalled();
});
it("runs single-spec after functions after timing out", function() {
var after = jasmine.createSpy('after');
env.describe('foo', function () {
env.it('waitsFor', function () {
this.after(after);
this.waitsFor(100, function() {
return false;
});
});
}).execute();
fakeTimer.tick(500);
expect(after).toHaveBeenCalled();
});
describe('with consecutive calls', function () {
var foo;
beforeEach(function () {
foo = 0;
});
it('exits immediately (does not stack) if the latchFunction times out', function () {
var reachedFirstWaitsFor = false;
var reachedSecondWaitsFor = false;
env.describe('suite that waits', function () {
env.it('should stack timeouts', function() {
this.waitsFor(500, function () {
reachedFirstWaitsFor = true;
return false;
});
this.waitsFor(500, function () {
reachedSecondWaitsFor = true;
});
this.runs(function () {
foo++;
});
});
});
expect(reachedFirstWaitsFor).toEqual(false);
env.execute();
expect(reachedFirstWaitsFor).toEqual(true);
expect(foo).toEqual(0);
expect(reachedSecondWaitsFor).toEqual(false);
fakeTimer.tick(500);
expect(reachedSecondWaitsFor).toEqual(false);
expect(foo).toEqual(0);
fakeTimer.tick(500);
expect(reachedSecondWaitsFor).toEqual(false);
expect(foo).toEqual(0);
});
it('stacks latchFunctions', function () {
var firstWaitsResult = false;
var secondWaitsResult = false;
var waitsSuite = env.describe('suite that waits', function () {
env.it('spec with waitsFors', function() {
this.waitsFor(600, function () {
fakeTimer.setTimeout(function () {
firstWaitsResult = true;
}, 300);
return firstWaitsResult;
});
this.waitsFor(600, function () {
fakeTimer.setTimeout(function () {
secondWaitsResult = true;
}, 300);
return secondWaitsResult;
});
this.runs(function () {
foo++;
});
});
});
expect(firstWaitsResult).toEqual(false);
expect(secondWaitsResult).toEqual(false);
waitsSuite.execute();
expect(firstWaitsResult).toEqual(false);
expect(secondWaitsResult).toEqual(false);
expect(foo).toEqual(0);
fakeTimer.tick(300);
expect(firstWaitsResult).toEqual(true);
expect(secondWaitsResult).toEqual(false);
expect(foo).toEqual(0);
fakeTimer.tick(300);
expect(firstWaitsResult).toEqual(true);
expect(secondWaitsResult).toEqual(true);
expect(foo).toEqual(1);
});
});
});
it("testSpecAfter", function() {
@@ -579,90 +696,6 @@ describe("jasmine spec running", function () {
expect(quux).toEqual(1);
});
describe('#waitsFor should allow consecutive calls', function () {
var foo;
beforeEach(function () {
foo = 0;
});
it('exits immediately (does not stack) if the latchFunction times out', function () {
var reachedFirstWaitsFor = false;
var reachedSecondWaitsFor = false;
env.describe('suite that waits', function () {
env.it('should stack timeouts', function() {
this.waitsFor(500, function () {
reachedFirstWaitsFor = true;
return false;
});
this.waitsFor(500, function () {
reachedSecondWaitsFor = true;
});
this.runs(function () {
foo++;
});
});
});
expect(reachedFirstWaitsFor).toEqual(false);
env.execute();
expect(reachedFirstWaitsFor).toEqual(true);
expect(foo).toEqual(0);
expect(reachedSecondWaitsFor).toEqual(false);
fakeTimer.tick(500);
expect(reachedSecondWaitsFor).toEqual(false);
expect(foo).toEqual(0);
fakeTimer.tick(500);
expect(reachedSecondWaitsFor).toEqual(false);
expect(foo).toEqual(0);
});
it('stacks latchFunctions', function () {
var firstWaitsResult = false;
var secondWaitsResult = false;
var waitsSuite = env.describe('suite that waits', function () {
env.it('spec with waitsFors', function() {
this.waitsFor(600, function () {
fakeTimer.setTimeout(function () {
firstWaitsResult = true;
}, 300);
return firstWaitsResult;
});
this.waitsFor(600, function () {
fakeTimer.setTimeout(function () {
secondWaitsResult = true;
}, 300);
return secondWaitsResult;
});
this.runs(function () {
foo++;
});
});
});
expect(firstWaitsResult).toEqual(false);
expect(secondWaitsResult).toEqual(false);
waitsSuite.execute();
expect(firstWaitsResult).toEqual(false);
expect(secondWaitsResult).toEqual(false);
expect(foo).toEqual(0);
fakeTimer.tick(300);
expect(firstWaitsResult).toEqual(true);
expect(secondWaitsResult).toEqual(false);
expect(foo).toEqual(0);
fakeTimer.tick(300);
expect(firstWaitsResult).toEqual(true);
expect(secondWaitsResult).toEqual(true);
expect(foo).toEqual(1);
});
});
it("#beforeEach should be able to eval runs and waits blocks", function () {
var foo = 0;
var bar = 0;
@@ -1225,6 +1258,9 @@ describe("jasmine spec running", function () {
this.expect(true).toEqual(true);
});
});
throw new Error("fake error");
});
} catch(e) {
}
@@ -1240,14 +1276,16 @@ describe("jasmine spec running", function () {
expect(specs.join('')).toMatch(new RegExp(
'Spec: outer1 inner1 should thingy.' +
'Result: Passed.' +
'Spec: outer1 encountered a declaration exception.' +
'Result: Error: fake error.*' +
'Spec: outer1 inner2 should other thingy.' +
'Result: Passed.' +
'Spec: outer2 should xxx.' +
'Result: Passed.'
));
'Result: Passed.' +
'Spec: outer1 inner1 encountered a declaration exception.' +
'Result: Error: fake error.*' +
'Spec: outer1 inner2 should other thingy.' +
'Result: Passed.' +
'Spec: outer1 encountered a declaration exception.' +
'Result: Error: fake error.*' +
'Spec: outer2 should xxx.' +
'Result: Passed.'
));
});
});

View File

@@ -38,7 +38,7 @@ describe('Spec', function () {
it('getFullName returns suite & spec description', function () {
var spec = new jasmine.Spec(env, suite, 'spec 1');
expect(spec.getFullName()).toEqual('suite 1 spec 1.')
expect(spec.getFullName()).toEqual('suite 1 spec 1.');
});
describe('results', function () {

View File

@@ -165,6 +165,21 @@ describe('Spies', function () {
expect(exception).toBeDefined();
});
it('to spy on an undefined method throws exception', function() {
var TestClass = {
someFunction : function() {
}
};
function efunc() {
this.spyOn(TestClass, 'someOtherFunction');
};
expect(function() {
efunc();
}).toThrow('someOtherFunction() method does not exist');
});
it('should be able to reset a spy', function() {
var TestClass = { someFunction: function() {} };
this.spyOn(TestClass, 'someFunction');

View File

@@ -25,7 +25,6 @@ describe("jasmine.util", function() {
it("should return true if the argument is an array", function() {
expect(jasmine.isArray_([])).toBe(true);
expect(jasmine.isArray_(['a'])).toBe(true);
expect(jasmine.isArray_(new Array())).toBe(true);
});
it("should return false if the argument is not an array", function() {

View File

@@ -10,6 +10,37 @@ describe('WaitsForBlock', function () {
onComplete = jasmine.createSpy("onComplete");
});
describe("jasmine.VERBOSE", function() {
var jasmineVerboseOriginal;
beforeEach(function() {
jasmineVerboseOriginal = jasmine.VERBOSE;
spyOn(env.reporter, 'log');
});
it('do not show information if jasmine.VERBOSE is set to false', function () {
jasmine.VERBOSE = false;
var latchFunction = function() {
return true;
};
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
expect(env.reporter.log).not.toHaveBeenCalled();
block.execute(onComplete);
expect(env.reporter.log).not.toHaveBeenCalled();
jasmine.VERBOSE = jasmineVerboseOriginal;
});
it('show information if jasmine.VERBOSE is set to true', function () {
jasmine.VERBOSE = true;
var latchFunction = function() {
return true;
};
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
expect(env.reporter.log).not.toHaveBeenCalled();
block.execute(onComplete);
expect(env.reporter.log).toHaveBeenCalled();
jasmine.VERBOSE = jasmineVerboseOriginal;
});
});
it('onComplete should be called if the latchFunction returns true', function () {
var latchFunction = function() {
return true;
@@ -84,4 +115,4 @@ describe('WaitsForBlock', function () {
expect(onComplete).toHaveBeenCalled();
});
});
});
});

View File

@@ -0,0 +1,209 @@
describe("HtmlReporter", function() {
var env;
var htmlReporter;
var body;
var fakeDocument;
beforeEach(function() {
env = new jasmine.Env();
env.updateInterval = 0;
body = document.createElement("body");
fakeDocument = { body: body, location: { search: "" } };
htmlReporter = new jasmine.HtmlReporter(fakeDocument);
});
function fakeSpec(name) {
return {
getFullName: function() {
return name;
}
};
}
function findElements(divs, withClass) {
var els = [];
for (var i = 0; i < divs.length; i++) {
if (divs[i].className == withClass) els.push(divs[i]);
}
return els;
}
function findElement(divs, withClass) {
var els = findElements(divs, withClass);
if (els.length > 0) {
return els[0];
}
throw new Error("couldn't find div with class " + withClass);
}
it("should run only specs beginning with spec parameter", function() {
fakeDocument.location.search = "?spec=run%20this";
expect(htmlReporter.specFilter(fakeSpec("run this"))).toBeTruthy();
expect(htmlReporter.specFilter(fakeSpec("not the right spec"))).toBeFalsy();
expect(htmlReporter.specFilter(fakeSpec("not run this"))).toBeFalsy();
});
describe("running without any specs", function() {
var runner;
beforeEach(function() {
runner = env.currentRunner();
env.addReporter(htmlReporter);
});
it("should not error", function() {
var exec = function() {
runner.execute();
};
expect(exec).not.toThrow();
});
});
describe('Matcher reporting', function() {
var getResultMessageDiv = function(body) {
var divs = body.getElementsByTagName("div");
for (var i = 0; i < divs.length; i++) {
if (divs[i].className.match(/resultMessage/)) {
return divs[i];
}
}
};
var runner, spec, fakeTimer;
beforeEach(function() {
fakeTimer = new jasmine.FakeTimer();
env.setTimeout = fakeTimer.setTimeout;
env.clearTimeout = fakeTimer.clearTimeout;
env.setInterval = fakeTimer.setInterval;
env.clearInterval = fakeTimer.clearInterval;
runner = env.currentRunner();
var suite = new jasmine.Suite(env, 'some suite');
runner.add(suite);
spec = new jasmine.Spec(env, suite, 'some spec');
suite.add(spec);
fakeDocument.location.search = "?";
env.addReporter(htmlReporter);
});
describe('toContain', function() {
it('should show actual and expected', function() {
spec.runs(function() {
this.expect('foo').toContain('bar');
});
runner.execute();
fakeTimer.tick(0);
var resultEl = getResultMessageDiv(body);
expect(resultEl.innerHTML).toMatch(/foo/);
expect(resultEl.innerHTML).toMatch(/bar/);
});
});
});
describe("failure messages (integration)", function() {
var spec, results, expectationResult;
it("should add the failure message to the DOM (non-toEquals matchers)", function() {
env.describe("suite", function() {
env.it("will have log messages", function() {
this.expect('a').toBeNull();
});
});
env.addReporter(htmlReporter);
env.execute();
var divs = body.getElementsByTagName("div");
var errorDiv = findElement(divs, 'resultMessage fail');
expect(errorDiv.innerHTML).toMatch(/Expected 'a' to be null/);
});
it("should add the failure message to the DOM (non-toEquals matchers) html escaping", function() {
env.describe("suite", function() {
env.it("will have log messages", function() {
this.expect('1 < 2').toBeNull();
});
});
env.addReporter(htmlReporter);
env.execute();
var divs = body.getElementsByTagName("div");
var errorDiv = findElement(divs, 'resultMessage fail');
expect(errorDiv.innerHTML).toMatch(/Expected '1 &lt; 2' to be null/);
});
});
describe("log messages", function() {
it("should appear in the report of a failed spec", function() {
env.describe("suite", function() {
env.it("will have log messages", function() {
this.log("this is a", "multipart log message");
this.expect(true).toBeFalsy();
});
});
env.addReporter(htmlReporter);
env.execute();
var divs = body.getElementsByTagName("div");
var errorDiv = findElement(divs, 'specDetail failed');
expect(errorDiv.innerHTML).toMatch("this is a multipart log message");
});
xit("should work on IE without console.log.apply", function() {
});
});
describe("duplicate example names", function() {
it("should report failures correctly", function() {
var suite1 = env.describe("suite", function() {
env.it("will have log messages", function() {
this.log("this one fails!");
this.expect(true).toBeFalsy();
});
});
var suite2 = env.describe("suite", function() {
env.it("will have log messages", function() {
this.log("this one passes!");
this.expect(true).toBeTruthy();
});
});
env.addReporter(htmlReporter);
env.execute();
var divs = body.getElementsByTagName("div");
var failedSpecDiv = findElement(divs, 'specDetail failed');
expect(failedSpecDiv.className).toEqual('specDetail failed');
expect(failedSpecDiv.innerHTML).toContain("this one fails!");
expect(failedSpecDiv.innerHTML).not.toContain("this one passes!");
});
});
describe('#reportSpecStarting', function() {
beforeEach(function() {
env.describe("suite 1", function() {
env.it("spec 1", function() {
});
});
spyOn(htmlReporter, 'log').andCallThrough();
});
it('DOES NOT log running specs by default', function() {
env.addReporter(htmlReporter);
env.execute();
expect(htmlReporter.log).not.toHaveBeenCalled();
});
it('logs running specs when log_running_specs is true', function() {
htmlReporter.logRunningSpecs = true;
env.addReporter(htmlReporter);
env.execute();
expect(htmlReporter.log).toHaveBeenCalledWith('>> Jasmine Running suite 1 spec 1...');
});
});
});

View File

@@ -0,0 +1,38 @@
describe("MatchersSpec - HTML Dependent", function () {
var env, spec;
beforeEach(function() {
env = new jasmine.Env();
env.updateInterval = 0;
var suite = env.describe("suite", function() {
spec = env.it("spec", function() {
});
});
spyOn(spec, 'addMatcherResult');
this.addMatchers({
toPass: function() {
return lastResult().passed();
},
toFail: function() {
return !lastResult().passed();
}
});
});
function match(value) {
return spec.expect(value);
}
function lastResult() {
return spec.addMatcherResult.mostRecentCall.args[0];
}
it("toEqual with DOM nodes", function() {
var nodeA = document.createElement('div');
var nodeB = document.createElement('div');
expect((match(nodeA).toEqual(nodeA))).toPass();
expect((match(nodeA).toEqual(nodeB))).toFail();
});
});

View File

@@ -0,0 +1,8 @@
describe("jasmine.pp (HTML Dependent)", function () {
it("should stringify HTML nodes properly", function() {
var sampleNode = document.createElement('div');
sampleNode.innerHTML = 'foo<b>bar</b>';
expect(jasmine.pp(sampleNode)).toEqual("HTMLNode");
expect(jasmine.pp({foo: sampleNode})).toEqual("{ foo : HTMLNode }");
});
});

View File

@@ -31,7 +31,9 @@ describe("TrivialReporter", function() {
function findElement(divs, withClass) {
var els = findElements(divs, withClass);
if (els.length > 0) return els[0];
if (els.length > 0) {
return els[0];
}
throw new Error("couldn't find div with class " + withClass);
}
@@ -96,7 +98,6 @@ describe("TrivialReporter", function() {
});
});
describe("failure messages (integration)", function () {
var spec, results, expectationResult;

39
spec/jasmine.yml Normal file
View File

@@ -0,0 +1,39 @@
jasmine_dir:
- 'src'
#This 'magic' inclusion order allows the travis build to pass.
#TODO: search for the correct files to include to prevent
jasmine_files:
- 'core/base.js'
- 'core/util.js'
- 'core/Reporter.js'
#end of known dependencies
- 'core/Env.js'
- 'core/Block.js'
- 'core/JsApiReporter.js'
- 'core/Matchers.js'
- 'core/mock-timeout.js'
- 'core/MultiReporter.js'
- 'core/NestedResults.js'
- 'core/PrettyPrinter.js'
- 'core/Queue.js'
- 'core/Runner.js'
- 'core/Spec.js'
- 'core/Suite.js'
- 'core/WaitsBlock.js'
- 'core/WaitsForBlock.js'
- 'html/HtmlReporterHelpers.js'
- 'html/HtmlReporter.js'
- '**/*.js'
jasmine_css_files:
- 'html/jasmine.css'
src_files:
stylesheets:
helpers:
- 'helpers/**/*.js'
spec_files:
- '**/*[Ss]pec.js'
src_dir:
spec_dir:
- 'spec'

View File

@@ -0,0 +1,23 @@
require 'jasmine'
Jasmine.load_configuration_from_yaml(File.join(Dir.pwd, 'spec', 'jasmine.yml'))
config = Jasmine.config
server = Jasmine::Server.new(config.port, Jasmine::Application.app(config))
driver = Jasmine::SeleniumDriver.new(config.browser, "#{config.host}:#{config.port}/")
t = Thread.new do
begin
server.start
rescue ChildProcess::TimeoutError
end
# # ignore bad exits
end
t.abort_on_exception = true
Jasmine::wait_for_listener(config.port, "jasmine server")
puts "jasmine server started."
results_processor = Jasmine::ResultsProcessor.new(config)
results = Jasmine::Runners::HTTP.new(driver, results_processor, config.result_batch_size).run
formatter = Jasmine::RspecFormatter.new
formatter.format_results(results)

127
spec/node_suite.js Normal file
View File

@@ -0,0 +1,127 @@
var fs = require('fs');
var util = require('util');
var path = require('path');
// yes, really keep this here to keep us honest, but only for jasmine's own runner! [xw]
// undefined = "diz be undefined yo";
var jasmineGlobals = require('../lib/jasmine-core/jasmine.js');
for (var k in jasmineGlobals) {
global[k] = jasmineGlobals[k];
}
require('../src/console/ConsoleReporter.js');
/*
Pulling in code from jasmine-node.
We can't just depend on jasmine-node because it has its own jasmine that it uses.
*/
global.window = {
setTimeout: setTimeout,
clearTimeout: clearTimeout,
setInterval: setInterval,
clearInterval: clearInterval
};
delete global.window;
function noop() {
}
jasmine.executeSpecs = function(specs, done, isVerbose, showColors) {
for (var i = 0, len = specs.length; i < len; ++i) {
var filename = specs[i];
require(filename.replace(/\.\w+$/, ""));
}
var jasmineEnv = jasmine.getEnv();
var consoleReporter = new jasmine.ConsoleReporter(util.print, done, showColors);
jasmineEnv.addReporter(consoleReporter);
jasmineEnv.execute();
};
jasmine.getAllSpecFiles = function(dir, matcher) {
var specs = [];
if (fs.statSync(dir).isFile() && dir.match(matcher)) {
specs.push(dir);
} else {
var files = fs.readdirSync(dir);
for (var i = 0, len = files.length; i < len; ++i) {
var filename = dir + '/' + files[i];
if (fs.statSync(filename).isFile() && filename.match(matcher)) {
specs.push(filename);
} else if (fs.statSync(filename).isDirectory()) {
var subfiles = this.getAllSpecFiles(filename, matcher);
subfiles.forEach(function(result) {
specs.push(result);
});
}
}
}
return specs;
};
function now() {
return new Date().getTime();
}
jasmine.asyncSpecWait = function() {
var wait = jasmine.asyncSpecWait;
wait.start = now();
wait.done = false;
(function innerWait() {
waits(10);
runs(function() {
if (wait.start + wait.timeout < now()) {
expect('timeout waiting for spec').toBeNull();
} else if (wait.done) {
wait.done = false;
} else {
innerWait();
}
});
})();
};
jasmine.asyncSpecWait.timeout = 4 * 1000;
jasmine.asyncSpecDone = function() {
jasmine.asyncSpecWait.done = true;
};
for (var key in jasmine) {
exports[key] = jasmine[key];
}
/*
End jasmine-node runner
*/
var isVerbose = false;
var showColors = true;
process.argv.forEach(function(arg) {
switch (arg) {
case '--color': showColors = true; break;
case '--noColor': showColors = false; break;
case '--verbose': isVerbose = true; break;
}
});
var specs = jasmine.getAllSpecFiles(__dirname, new RegExp(".js$"));
var domIndependentSpecs = [];
for (var i = 0; i < specs.length; i++) {
if (fs.readFileSync(specs[i], "utf8").indexOf("document.createElement") < 0) {
domIndependentSpecs.push(specs[i]);
}
}
jasmine.executeSpecs(domIndependentSpecs, function(runner, log) {
if (runner.results().failedCount === 0) {
process.exit(0);
} else {
process.exit(1);
}
}, isVerbose, showColors);

View File

@@ -2,79 +2,85 @@
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Jasmine Test Runner</title>
<title>Jasmine Spec Runner: Jasmine Core</title>
<link rel="shortcut icon" type="image/png" href="../images/jasmine_favicon.png">
<link href="../lib/jasmine-core/jasmine.css" rel="stylesheet"/>
<script type="text/javascript" src="../lib/jasmine-core/jasmine.js"></script>
<script type="text/javascript">
// yes, really keep this here to keep us honest, but only for jasmine's own runner! [xw]
undefined = "diz be undefined yo";
</script>
<script type="text/javascript" src="../src/base.js"></script>
<script type="text/javascript" src="../src/util.js"></script>
<script type="text/javascript" src="../src/Env.js"></script>
<script type="text/javascript" src="../src/Reporter.js"></script>
<script type="text/javascript" src="../src/Block.js"></script>
<script type="text/javascript" src="../src/JsApiReporter.js"></script>
<script type="text/javascript" src="../src/Matchers.js"></script>
<script type="text/javascript" src="../src/mock-timeout.js"></script>
<script type="text/javascript" src="../src/MultiReporter.js"></script>
<script type="text/javascript" src="../src/NestedResults.js"></script>
<script type="text/javascript" src="../src/PrettyPrinter.js"></script>
<script type="text/javascript" src="../src/Queue.js"></script>
<script type="text/javascript" src="../src/Runner.js"></script>
<script type="text/javascript" src="../src/Spec.js"></script>
<script type="text/javascript" src="../src/Suite.js"></script>
<script type="text/javascript" src="../src/WaitsBlock.js"></script>
<script type="text/javascript" src="../src/WaitsForBlock.js"></script>
<script type="text/javascript" src="../src/html/TrivialReporter.js"></script>
<script type="text/javascript" src="suites/BaseSpec.js"></script>
<script type="text/javascript" src="suites/CustomMatchersSpec.js"></script>
<script type="text/javascript" src="suites/EnvSpec.js"></script>
<script type="text/javascript" src="suites/ExceptionsSpec.js"></script>
<script type="text/javascript" src="suites/JsApiReporterSpec.js"></script>
<script type="text/javascript" src="suites/MatchersSpec.js"></script>
<script type="text/javascript" src="suites/MockClockSpec.js"></script>
<script type="text/javascript" src="suites/MultiReporterSpec.js"></script>
<script type="text/javascript" src="suites/NestedResultsSpec.js"></script>
<script type="text/javascript" src="suites/PrettyPrintSpec.js"></script>
<script type="text/javascript" src="suites/ReporterSpec.js"></script>
<script type="text/javascript" src="suites/RunnerSpec.js"></script>
<script type="text/javascript" src="suites/QueueSpec.js"></script>
<script type="text/javascript" src="suites/SpecSpec.js"></script>
<script type="text/javascript" src="suites/SpecRunningSpec.js"></script>
<script type="text/javascript" src="suites/SpySpec.js"></script>
<script type="text/javascript" src="suites/SuiteSpec.js"></script>
<script type="text/javascript" src="suites/TrivialReporterSpec.js"></script>
<script type="text/javascript" src="suites/WaitsForBlockSpec.js"></script>
<!-- include source files here... -->
<script type="text/javascript" src=".././src/html/HtmlReporterHelpers.js"></script>
<script type="text/javascript" src=".././src/html/HtmlReporter.js"></script>
<script type="text/javascript" src=".././src/html/HtmlReporterHelpers.js"></script>
<script type="text/javascript" src=".././src/html/ReporterView.js"></script>
<script type="text/javascript" src=".././src/html/SpecView.js"></script>
<script type="text/javascript" src=".././src/html/SuiteView.js"></script>
<script type="text/javascript" src=".././src/html/TrivialReporter.js"></script>
<script type="text/javascript" src=".././src/console/ConsoleReporter.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src=".././spec/core/BaseSpec.js"></script>
<script type="text/javascript" src=".././spec/core/CustomMatchersSpec.js"></script>
<script type="text/javascript" src=".././spec/core/EnvSpec.js"></script>
<script type="text/javascript" src=".././spec/core/ExceptionsSpec.js"></script>
<script type="text/javascript" src=".././spec/core/JsApiReporterSpec.js"></script>
<script type="text/javascript" src=".././spec/core/MatchersSpec.js"></script>
<script type="text/javascript" src=".././spec/core/MockClockSpec.js"></script>
<script type="text/javascript" src=".././spec/core/MultiReporterSpec.js"></script>
<script type="text/javascript" src=".././spec/core/NestedResultsSpec.js"></script>
<script type="text/javascript" src=".././spec/core/PrettyPrintSpec.js"></script>
<script type="text/javascript" src=".././spec/core/QueueSpec.js"></script>
<script type="text/javascript" src=".././spec/core/ReporterSpec.js"></script>
<script type="text/javascript" src=".././spec/core/RunnerSpec.js"></script>
<script type="text/javascript" src=".././spec/core/SpecRunningSpec.js"></script>
<script type="text/javascript" src=".././spec/core/SpecSpec.js"></script>
<script type="text/javascript" src=".././spec/core/SpySpec.js"></script>
<script type="text/javascript" src=".././spec/core/SuiteSpec.js"></script>
<script type="text/javascript" src=".././spec/core/UtilSpec.js"></script>
<script type="text/javascript" src=".././spec/core/WaitsForBlockSpec.js"></script>
<script type="text/javascript" src=".././spec/html/HTMLReporterSpec.js"></script>
<script type="text/javascript" src=".././spec/html/MatchersHtmlSpec.js"></script>
<script type="text/javascript" src=".././spec/html/PrettyPrintHtmlSpec.js"></script>
<script type="text/javascript" src=".././spec/html/TrivialReporterSpec.js"></script>
<script type="text/javascript" src=".././spec/console/ConsoleReporterSpec.js"></script>
<script type="text/javascript">
(function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var trivialReporter = new jasmine.TrivialReporter();
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(trivialReporter);
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.specFilter = function(spec) {
return trivialReporter.specFilter(spec);
return htmlReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function() {
jasmineEnv.execute();
if (currentWindowOnload) {
currentWindowOnload();
}
execJasmine();
};
function execJasmine() {
jasmineEnv.execute();
}
})();
</script>
<link href="../src/html/jasmine.css" rel="stylesheet"/>
</head>
<body>
</body>
</html>
</html>

51
spec/spec_helper.rb Normal file
View File

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

View File

@@ -1,107 +0,0 @@
describe('Exceptions:', function() {
var env;
beforeEach(function() {
env = new jasmine.Env();
env.updateInterval = 0;
});
it('jasmine.formatException formats Firefox exception messages as expected', function() {
var sampleFirefoxException = {
fileName: 'foo.js',
line: '1978',
message: 'you got your foo in my bar',
name: 'A Classic Mistake'
};
var expected = 'A Classic Mistake: you got your foo in my bar in foo.js (line 1978)';
expect(jasmine.util.formatException(sampleFirefoxException)).toEqual(expected);
});
it('jasmine.formatException formats Webkit exception messages as expected', function() {
var sampleWebkitException = {
sourceURL: 'foo.js',
lineNumber: '1978',
message: 'you got your foo in my bar',
name: 'A Classic Mistake'
};
var expected = 'A Classic Mistake: you got your foo in my bar in foo.js (line 1978)';
expect(jasmine.util.formatException(sampleWebkitException)).toEqual(expected);
});
it('should handle exceptions thrown, but continue', function() {
var fakeTimer = new jasmine.FakeTimer();
env.setTimeout = fakeTimer.setTimeout;
env.clearTimeout = fakeTimer.clearTimeout;
env.setInterval = fakeTimer.setInterval;
env.clearInterval = fakeTimer.clearInterval;
//we run two exception tests to make sure we continue after throwing an exception
var 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('fake error 1');
});
env.it('should be another test that fails because it throws an exception', function() {
this.runs(function () {
throw new Error('fake error 2');
});
this.runs(function () {
this.expect(true).toEqual(true);
});
});
env.it('should be a passing test that runs after exceptions are thrown', function() {
this.expect(true).toEqual(true);
});
env.it('should be another test that fails because it throws an exception after a wait', function() {
this.runs(function () {
var foo = 'foo';
});
this.waits(250);
this.runs(function () {
throw new Error('fake error 3');
});
});
env.it('should be a passing test that runs after exceptions are thrown from a async test', function() {
this.expect(true).toEqual(true);
});
});
var runner = env.currentRunner();
suite.execute();
fakeTimer.tick(2500);
var suiteResults = suite.results();
var specResults = suiteResults.getItems();
expect(suiteResults.passed()).toEqual(false);
//
expect(specResults.length).toEqual(5);
expect(specResults[0].passed()).toMatch(false);
var blockResults = specResults[0].getItems();
expect(blockResults[0].passed()).toEqual(false);
expect(blockResults[0].message).toMatch(/fake error 1/);
expect(specResults[1].passed()).toEqual(false);
var blockResults = specResults[1].getItems();
expect(blockResults[0].passed()).toEqual(false);
expect(blockResults[0].message).toMatch(/fake error 2/),
expect(blockResults[1].passed()).toEqual(true);
expect(specResults[2].passed()).toEqual(true);
expect(specResults[3].passed()).toEqual(false);
blockResults = specResults[3].getItems();
expect(blockResults[0].message).toMatch(/fake error 3/);
expect(specResults[4].passed()).toEqual(true);
});
});

View File

@@ -0,0 +1,33 @@
require 'spec_helper.rb'
describe "Build Jasmine task" do
let(:jasmine_core_dir) { "#{Dir.tmpdir}/jasmine-core" }
let(:jasmine_dev) { JasmineDev.new }
before do
reset_dir jasmine_core_dir
@output = capture_output { jasmine_dev.build_distribution jasmine_core_dir }
end
it "should say that JSHint is running" do
@output.should match(/Running JSHint/)
@output.should match(/Jasmine JSHint PASSED/)
end
it "should tell the developer it is building the distribution" do
@output.should match(/Building Jasmine distribution/)
end
it "should build jasmine.js in the destination directory" do
File.exist?("#{jasmine_core_dir}/jasmine.js").should be_true
end
it "should build jasmine-html.js in the destination directory" do
File.exist?("#{jasmine_core_dir}/jasmine-html.js").should be_true
end
it "should build jasmine.css" do
File.exist?("#{jasmine_core_dir}/jasmine.css").should be_true
end
end

View File

@@ -0,0 +1,60 @@
require 'spec_helper.rb'
describe "Build Github Pages task" do
let(:pages_dir) { File.join(Dir.tmpdir, 'pages') }
let(:jasmine_dev) { JasmineDev.new }
before do
reset_dir pages_dir
end
describe "when the Github pages submodule is not present" do
before do
jasmine_dev.should_receive(:has_pages_submodule?).and_return(false)
@output = capture_output { jasmine_dev.build_github_pages pages_dir }
end
it "should tell the user the task is running" do
@output.should match(/Building Github Pages/)
end
it "should prompt the user to install the submodule" do
@output.should match(/Submodule for Github Pages isn't present/)
end
end
describe "when the Github pages submodule is present" do
before do
jasmine_dev.should_receive(:has_pages_submodule?).and_return(true)
@output = capture_output { jasmine_dev.build_github_pages pages_dir }
end
it "should tell the user the task is running" do
@output.should match(/Building Github Pages/)
end
it "should copy the latest jasmine files to the pages dir" do
['jasmine.js', 'jasmine.css', 'jasmine-html.js'].each do |lib_file|
source = File.read(File.join(project_root, 'lib', 'jasmine-core', lib_file))
dest = File.read(File.join(pages_dir, 'lib', lib_file))
source.should == dest
end
end
it "should build a new page" do
@output.should match(/rocco/)
File.exist?(File.join(pages_dir, 'introduction.html')).should be_true
end
it "should copy the rocco output to index.html" do
introduction = File.read(File.join(pages_dir, 'introduction.html'))
index = File.read(File.join(pages_dir, 'index.html'))
index.should == introduction
end
end
end

View File

@@ -0,0 +1,109 @@
require 'spec_helper.rb'
describe "Standalone Distribution tasks" do
let(:jasmine_dev) { JasmineDev.new }
let(:standalone_temp_dir) { File.join(Dir.tmpdir, 'jasmine_test') }
let(:download_dir) { File.join(standalone_temp_dir, 'download')}
describe "build_standalone_distribution" do
before do
reset_dir standalone_temp_dir
reset_dir download_dir
Dir.should_receive(:tmpdir).any_number_of_times.and_return(standalone_temp_dir)
@standalone_staging_dir = File.join(standalone_temp_dir, 'jasmine_standalone')
@version_dir = File.join(@standalone_staging_dir, "jasmine-standalone-#{jasmine_version}")
@lib_dir = File.join(@version_dir, 'lib')
@source_dir = File.join(@version_dir, 'src')
@spec_dir = File.join(@version_dir, 'spec')
@output = capture_output { jasmine_dev.build_standalone_distribution download_dir }
end
it "should build the distribution" do
@output.should match(/Building Jasmine distribution/)
end
it "should tell the developer the task has started" do
@output.should match(/Building standalone distribution/)
end
it "should copy the lib directory to the staging directory, under a versioned directory" do
lib_dir_files = Dir.glob(File.join(standalone_temp_dir, 'jasmine_standalone', '**', '*'))
staged_lib_files = %w{ jasmine.js jasmine-html.js jasmine.css MIT.LICENSE }
staged_lib_files.each do |filename|
lib_dir_files.should include(File.join(@lib_dir, "jasmine-#{jasmine_version}", filename))
end
end
it "should copy the sample project source to the staging directory" do
File.exist?(File.join(@source_dir, 'Player.js')).should be_true
File.exist?(File.join(@source_dir, 'Song.js')).should be_true
end
it "should copy the sample project specs to the staging directory" do
File.exist?(File.join(@spec_dir, 'PlayerSpec.js')).should be_true
File.exist?(File.join(@spec_dir, 'SpecHelper.js')).should be_true
end
it "should copy a build SpecRunner.html to the staging directory" do
File.exist?(File.join(@version_dir, 'SpecRunner.html')).should be_true
end
it "should zip up the contents of the staging directory" do
File.exist?(File.join(@standalone_staging_dir, "jasmine-standalone-#{jasmine_version}.zip")).should be_true
end
it "should copy the zip file to the pages sub directory" do
File.exist?(File.join(download_dir, "jasmine-standalone-#{jasmine_version}.zip")).should be_true
end
describe "when the zip file is unzipped" do
before do
@out_directory = File.join(standalone_temp_dir, 'unzip')
reset_dir @out_directory
FileUtils.cp File.join(@standalone_staging_dir, "jasmine-standalone-#{jasmine_version}.zip"),
@out_directory
Dir.chdir @out_directory do
system("unzip -qq jasmine-standalone-#{jasmine_version}.zip")
end
end
describe "the distirbution" do
before do
Dir.chdir @out_directory do
@files = Dir.glob(File.join('**', '*'))
end
end
it "should include the correct root files" do
@files.should include('SpecRunner.html')
end
it "should include the correct lib files" do
%w{ jasmine.js jasmine-html.js jasmine.css MIT.LICENSE }.each do |file|
@files.should include(File.join('lib', "jasmine-#{jasmine_version}", file))
end
end
it "should include the correct src files" do
%w{Player.js Song.js}.each do |file|
@files.should include(File.join('src', file))
end
end
it "should include the correct spec files" do
%w{PlayerSpec.js SpecHelper.js}.each do |file|
@files.should include(File.join('spec', file))
end
end
end
end
end
end

View File

@@ -0,0 +1,63 @@
require 'spec_helper.rb'
describe "Build Standalone runner HTML task" do
let(:jasmine_dev) { JasmineDev.new }
let(:standalone_temp_dir) { "#{Dir.tmpdir}/jasmine_test" }
describe "build_standalone_runner" do
before do
reset_dir standalone_temp_dir
Dir.should_receive(:tmpdir).any_number_of_times.and_return(standalone_temp_dir)
@standalone_staging_dir = File.join(standalone_temp_dir, 'jasmine_standalone')
@version_dir = File.join(@standalone_staging_dir, "jasmine-standalone-#{jasmine_version}")
@output = capture_output { jasmine_dev.build_standalone_runner }
end
it "should tell the developer the task has started" do
@output.should match(/Building standalone runner HTML/)
end
it "should copy a build SpecRunner.html to the staging directory" do
File.exist?(File.join(@version_dir, 'SpecRunner.html')).should be_true
end
describe "should build the file that has HTML that" do
before do
html = File.read(File.join(@version_dir, 'SpecRunner.html'))
@runner = Nokogiri(html)
end
it "should have the favicon tag" do
favicon_tag = @runner.css('link')[0]
favicon_tag['href'].should match("lib/jasmine-#{jasmine_version}/jasmine_favicon.png")
end
it "should have the stylesheet" do
css_tag = @runner.css('link')[1]
css_tag['href'].should match("lib/jasmine-#{jasmine_version}/jasmine.css")
end
it "should have the jasmine script tags" do
script_sources = @runner.css('script').collect {|tag| tag['src']}
script_sources.should include("lib/jasmine-#{jasmine_version}/jasmine.js")
script_sources.should include("lib/jasmine-#{jasmine_version}/jasmine-html.js")
end
it "should have the example source files" do
script_sources = @runner.css('script').collect {|tag| tag['src']}
script_sources.should include('src/Player.js')
script_sources.should include('src/Song.js')
end
it "should have the example source files" do
script_sources = @runner.css('script').collect {|tag| tag['src']}
script_sources.should include('spec/SpecHelper.js')
script_sources.should include('spec/PlayerSpec.js')
end
end
end
end

View File

@@ -0,0 +1,26 @@
require 'spec_helper.rb'
describe "Spec counting task" do
let(:jasmine_dev) { JasmineDev.new }
before do
@output = capture_output { jasmine_dev.count_specs }
end
it "should tell the developer that the specs are being counted" do
@output.should match(/Counting specs/)
end
it "should report the number of specs that will run in node" do
@output.should match(/\d+ \e\[0mspecs for Node.js/)
end
it "should report the number of specs that will run in the browser" do
@output.should match(/\d+ \e\[0mspecs for Browser/)
end
it "should remind the developer to check the count" do
@output.should match(/Please verify/)
end
end

View File

@@ -0,0 +1,81 @@
require 'spec_helper.rb'
describe "Spec tasks" do
let(:jasmine_dev) { JasmineDev.new }
describe "execute_specs_in_node" do
describe "when Node.js is not present" do
before do
jasmine_dev.should_receive(:has_node?).and_return(false)
@output = capture_output { jasmine_dev.execute_specs_in_node }
end
it "should prompt the user to install Node" do
@output.should match(/Node\.js is required/)
end
end
describe "when Node.js is present" do
before do
jasmine_dev.should_receive(:has_node?).and_return(true)
@output = capture_output { jasmine_dev.execute_specs_in_node }
end
it "should build the distribution" do
@output.should match(/Building Jasmine distribution/)
end
it "should tell the developer that the specs are being counted" do
@output.should match(/Counting specs/)
end
it "should tell the user that the specs are running in Node.js" do
@output.should match(/specs via Node/)
@output.should match(/Started/)
@output.should match(/\d+ specs, 0 failures/)
end
end
end
describe "execute_specs_in_browser" do
before do
jasmine_dev.should_receive(:run)
@output = capture_output { jasmine_dev.execute_specs_in_browser }
end
it "should build the distribution" do
@output.should match(/Building Jasmine distribution/)
end
it "should tell the developer that the specs are being counted" do
@output.should match(/Counting specs/)
end
it "should tell the user that the specs are running in the broswer" do
@output.should match(/specs via the default web browser/)
end
end
describe "execute_specs" do
before do
@output = capture_output { jasmine_dev.execute_specs }
end
it "should build the distribution" do
@output.should match(/Building Jasmine distribution/)
end
it "should tell the developer that the specs are being counted" do
@output.should match(/Counting specs/)
end
it "should tell the user that the specs are running in Node.js" do
@output.should match(/specs via Node/)
end
it "should tell the user that the specs are running in the broswer" do
@output.should match(/specs via the default web browser/)
end
end
end

39
spec/tasks/jshint_spec.rb Normal file
View File

@@ -0,0 +1,39 @@
require 'spec_helper.rb'
describe "JSHint task" do
let(:tmp_dir) { "#{Dir.tmpdir}/jasmine_tasks_test" }
let(:jasmine_dev) { JasmineDev.new }
before do
reset_dir tmp_dir
end
describe "when Node is not present" do
before do
jasmine_dev.should_receive(:has_node?).and_return(false)
@output = capture_output { jasmine_dev.js_hint }
end
it "should not tell the user that lint is running" do
@output.should_not match(/Running JSHint/)
end
it "should prompt the user to install Node" do
@output.should match(/Node\.js is required/)
end
end
describe "when Node is present" do
before do
jasmine_dev.should_receive(:has_node?).and_return(true)
@output = capture_output { jasmine_dev.js_hint }
end
it "should tell the user that lint is running" do
@output.should match(/Running JSHint/)
@output.should match(/Jasmine JSHint PASSED/)
end
end
end

View File

@@ -0,0 +1,39 @@
require 'spec_helper.rb'
describe "Release task" do
let(:jasmine_dev) { JasmineDev.new }
describe "when the pages submodule is not present" do
before do
jasmine_dev.should_receive(:has_pages_submodule?).and_return(false)
@output = capture_output { jasmine_dev.release_prep }
end
it "should tell the user the task is running" do
@output.should match(/Building Release/)
end
it "should prompt the user to install the submodule" do
@output.should match(/Submodule for Github Pages isn't present/)
end
end
describe "when the pages submodule is present" do
before do
JasmineDev.any_instance.should_receive(:write_version_files)
JasmineDev.any_instance.should_receive(:build_distribution)
JasmineDev.any_instance.should_receive(:build_standalone_distribution)
JasmineDev.any_instance.should_receive(:build_github_pages)
jasmine_dev.should_receive(:has_pages_submodule?).and_return(true)
@output = capture_output { jasmine_dev.release_prep }
end
it "should tell the user the task is running" do
@output.should match(/Building Release/)
end
end
end

View File

@@ -0,0 +1,55 @@
require 'spec_helper.rb'
describe "Version tasks" do
let(:jasmine_dev) { JasmineDev.new }
describe "write_version_files" do
before do
@output = capture_output { jasmine_dev.write_version_files }
end
it "should tell the user that the task has started" do
@output.should match(/Building version files/)
end
it "should build the version.js file" do
js_version = File.read(File.join(project_root, 'src', 'version.js'))
js_version.should match(%Q{"build": #{jasmine_version_object["build"]}})
js_version.should match(%Q{"minor": #{jasmine_version_object["minor"]}})
js_version.should match(%Q{"build": #{jasmine_version_object["build"]}})
if jasmine_version_object["release_candidate"]
js_version.should match(%Q{"release_candidate": #{jasmine_version_object["release_candidate"]}})
end
js_version.should match(/"revision": \d+/)
end
it "should build the jasmine-core ruby gem version" do
ruby_version = File.read(File.join(project_root, 'lib', 'jasmine-core', 'version.rb'))
ruby_version.should match(%Q{VERSION = "#{jasmine_version}"})
end
end
describe "display_version" do
describe "when Node.js is not present" do
before do
@output = capture_output { jasmine_dev.display_version }
end
it "should display a version header" do
@output.should match(/Current version/)
end
it "should display the current version Object" do
@output.should match(/Display version: \e\[33m\d+\.\d+\.\d+/)
end
it "should display the current version string" do
@output.should match(/\{ "major": \d+, "minor": \d+, "build": \d+/)
end
end
end
end

View File

@@ -0,0 +1,49 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title><%= title %></title>
<%= favicon %>
<%= jasmine_tags %>
<!-- include source files here... -->
<%= source_tags %>
<!-- include spec files here... -->
<%= spec_file_tags %>
<script type="text/javascript">
(function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.specFilter = function(spec) {
return htmlReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
execJasmine();
};
function execJasmine() {
jasmineEnv.execute();
}
})();
</script>
</head>
<body>
</body>
</html>

View File

@@ -0,0 +1 @@
<script type="text/javascript" src="<%= file %>"></script>

View File

@@ -0,0 +1,177 @@
jasmine.ConsoleReporter = function(print, doneCallback, showColors) {
//inspired by mhevery's jasmine-node reporter
//https://github.com/mhevery/jasmine-node
doneCallback = doneCallback || function() {};
var ansi = {
green: '\033[32m',
red: '\033[31m',
yellow: '\033[33m',
none: '\033[0m'
},
language = {
spec: "spec",
failure: "failure"
};
function coloredStr(color, str) {
return showColors ? (ansi[color] + str + ansi.none) : str;
}
function greenStr(str) {
return coloredStr("green", str);
}
function redStr(str) {
return coloredStr("red", str);
}
function yellowStr(str) {
return coloredStr("yellow", str);
}
function newline() {
print("\n");
}
function started() {
print("Started");
newline();
}
function greenDot() {
print(greenStr("."));
}
function redF() {
print(redStr("F"));
}
function yellowStar() {
print(yellowStr("*"));
}
function plural(str, count) {
return count == 1 ? str : str + "s";
}
function repeat(thing, times) {
var arr = [];
for (var i = 0; i < times; i++) {
arr.push(thing);
}
return arr;
}
function indent(str, spaces) {
var lines = (str || '').split("\n");
var newArr = [];
for (var i = 0; i < lines.length; i++) {
newArr.push(repeat(" ", spaces).join("") + lines[i]);
}
return newArr.join("\n");
}
function specFailureDetails(suiteDescription, specDescription, stackTraces) {
newline();
print(suiteDescription + " " + specDescription);
newline();
for (var i = 0; i < stackTraces.length; i++) {
print(indent(stackTraces[i], 2));
newline();
}
}
function finished(elapsed) {
newline();
print("Finished in " + elapsed / 1000 + " seconds");
}
function summary(colorF, specs, failed) {
newline();
print(colorF(specs + " " + plural(language.spec, specs) + ", " +
failed + " " + plural(language.failure, failed)));
newline();
newline();
}
function greenSummary(specs, failed) {
summary(greenStr, specs, failed);
}
function redSummary(specs, failed) {
summary(redStr, specs, failed);
}
function fullSuiteDescription(suite) {
var fullDescription = suite.description;
if (suite.parentSuite) fullDescription = fullSuiteDescription(suite.parentSuite) + " " + fullDescription;
return fullDescription;
}
this.now = function() {
return new Date().getTime();
};
this.reportRunnerStarting = function() {
this.runnerStartTime = this.now();
started();
};
this.reportSpecStarting = function() { /* do nothing */
};
this.reportSpecResults = function(spec) {
var results = spec.results();
if (results.skipped) {
yellowStar();
} else if (results.passed()) {
greenDot();
} else {
redF();
}
};
this.suiteResults = [];
this.reportSuiteResults = function(suite) {
var suiteResult = {
description: fullSuiteDescription(suite),
failedSpecResults: []
};
suite.results().items_.forEach(function(spec) {
if (spec.failedCount > 0 && spec.description) suiteResult.failedSpecResults.push(spec);
});
this.suiteResults.push(suiteResult);
};
function eachSpecFailure(suiteResults, callback) {
for (var i = 0; i < suiteResults.length; i++) {
var suiteResult = suiteResults[i];
for (var j = 0; j < suiteResult.failedSpecResults.length; j++) {
var failedSpecResult = suiteResult.failedSpecResults[j];
var stackTraces = [];
for (var k = 0; k < failedSpecResult.items_.length; k++) stackTraces.push(failedSpecResult.items_[k].trace.stack);
callback(suiteResult.description, failedSpecResult.description, stackTraces);
}
}
}
this.reportRunnerResults = function(runner) {
newline();
eachSpecFailure(this.suiteResults, function(suiteDescription, specDescription, stackTraces) {
specFailureDetails(suiteDescription, specDescription, stackTraces);
});
finished(this.now() - this.runnerStartTime);
var results = runner.results();
var summaryFunction = results.failedCount === 0 ? greenSummary : redSummary;
summaryFunction(runner.specs().length, results.failedCount);
doneCallback(runner);
};
};

View File

@@ -12,11 +12,16 @@ jasmine.Block = function(env, func, spec) {
this.spec = spec;
};
jasmine.Block.prototype.execute = function(onComplete) {
try {
jasmine.Block.prototype.execute = function(onComplete) {
if (!jasmine.CATCH_EXCEPTIONS) {
this.func.apply(this.spec);
} catch (e) {
this.spec.fail(e);
}
else {
try {
this.func.apply(this.spec);
} catch (e) {
this.spec.fail(e);
}
}
onComplete();
};
};

View File

@@ -51,12 +51,17 @@ jasmine.Env.prototype.version = function () {
* @returns string containing jasmine version build info, if set.
*/
jasmine.Env.prototype.versionString = function() {
if (jasmine.version_) {
var version = this.version();
return version.major + "." + version.minor + "." + version.build + " revision " + version.revision;
} else {
if (!jasmine.version_) {
return "version unknown";
}
var version = this.version();
var versionString = version.major + "." + version.minor + "." + version.build;
if (version.release_candidate) {
versionString += ".rc" + version.release_candidate;
}
versionString += " revision " + version.revision;
return versionString;
};
/**
@@ -104,14 +109,14 @@ jasmine.Env.prototype.describe = function(description, specDefinitions) {
declarationError = e;
}
this.currentSuite = parentSuite;
if (declarationError) {
this.it("encountered a declaration exception", function() {
throw declarationError;
});
}
this.currentSuite = parentSuite;
return suite;
};
@@ -163,6 +168,25 @@ jasmine.Env.prototype.xit = function(desc, func) {
};
};
jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) {
if (a.source != b.source)
mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/");
if (a.ignoreCase != b.ignoreCase)
mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier");
if (a.global != b.global)
mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier");
if (a.multiline != b.multiline)
mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier");
if (a.sticky != b.sticky)
mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier");
return (mismatchValues.length === 0);
};
jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
return true;
@@ -172,7 +196,7 @@ jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchVal
b.__Jasmine_been_here_before__ = a;
var hasKey = function(obj, keyName) {
return obj != null && obj[keyName] !== jasmine.undefined;
return obj !== null && obj[keyName] !== jasmine.undefined;
};
for (var property in b) {
@@ -198,7 +222,7 @@ jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchVal
delete a.__Jasmine_been_here_before__;
delete b.__Jasmine_been_here_before__;
return (mismatchKeys.length == 0 && mismatchValues.length == 0);
return (mismatchKeys.length === 0 && mismatchValues.length === 0);
};
jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
@@ -225,11 +249,19 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
return a.getTime() == b.getTime();
}
if (a instanceof jasmine.Matchers.Any) {
if (a.jasmineMatches) {
return a.jasmineMatches(b);
}
if (b.jasmineMatches) {
return b.jasmineMatches(a);
}
if (a instanceof jasmine.Matchers.ObjectContaining) {
return a.matches(b);
}
if (b instanceof jasmine.Matchers.Any) {
if (b instanceof jasmine.Matchers.ObjectContaining) {
return b.matches(a);
}
@@ -241,6 +273,10 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
return (a == b);
}
if (a instanceof RegExp && b instanceof RegExp) {
return this.compareRegExps_(a, b, mismatchKeys, mismatchValues);
}
if (typeof a === "object" && typeof b === "object") {
return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
}

View File

@@ -104,7 +104,7 @@ jasmine.Matchers.prototype.toEqual = function(expected) {
/**
* toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
* @param expected
* @deprecated as of 1.0. Use not.toNotEqual() instead.
* @deprecated as of 1.0. Use not.toEqual() instead.
*/
jasmine.Matchers.prototype.toNotEqual = function(expected) {
return !this.env.equals_(this.actual, expected);
@@ -150,6 +150,17 @@ jasmine.Matchers.prototype.toBeNull = function() {
return (this.actual === null);
};
/**
* Matcher that compares the actual to NaN.
*/
jasmine.Matchers.prototype.toBeNaN = function() {
this.message = function() {
return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ];
};
return (this.actual !== this.actual);
};
/**
* Matcher that boolean not-nots the actual.
*/
@@ -227,18 +238,14 @@ jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function() {
if (this.actual.callCount == 0) {
// todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
return [
"Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
"Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
];
var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was.";
var positiveMessage = "";
if (this.actual.callCount === 0) {
positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.";
} else {
return [
"Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
"Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
];
positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but actual calls were " + jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g, '')
}
return [positiveMessage, invertedMessage];
};
return this.env.contains_(this.actual.argsForCall, expectedArgs);
@@ -258,7 +265,7 @@ jasmine.Matchers.prototype.wasNotCalledWith = function() {
return [
"Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
"Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
]
];
};
return !this.env.contains_(this.actual.argsForCall, expectedArgs);
@@ -277,7 +284,7 @@ jasmine.Matchers.prototype.toContain = function(expected) {
* Matcher that checks that the expected item is NOT an element in the actual Array.
*
* @param {Object} expected
* @deprecated as of 1.0. Use not.toNotContain() instead.
* @deprecated as of 1.0. Use not.toContain() instead.
*/
jasmine.Matchers.prototype.toNotContain = function(expected) {
return !this.env.contains_(this.actual, expected);
@@ -291,10 +298,24 @@ jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
return this.actual > expected;
};
/**
* Matcher that checks that the expected item is equal to the actual item
* up to a given level of decimal precision (default 2).
*
* @param {Number} expected
* @param {Number} precision, as number of decimal places
*/
jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
if (!(precision === 0)) {
precision = precision || 2;
}
return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2);
};
/**
* Matcher that checks that the expected exception was thrown by the actual.
*
* @param {String} expected
* @param {String} [expected]
*/
jasmine.Matchers.prototype.toThrow = function(expected) {
var result = false;
@@ -315,7 +336,7 @@ jasmine.Matchers.prototype.toThrow = function(expected) {
this.message = function() {
if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
return ["Expected function " + not + "to throw", expected ? expected.message || expected : " an exception", ", but it threw", exception.message || exception].join(' ');
return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' ');
} else {
return "Expected function to throw an exception.";
}
@@ -328,7 +349,7 @@ jasmine.Matchers.Any = function(expectedClass) {
this.expectedClass = expectedClass;
};
jasmine.Matchers.Any.prototype.matches = function(other) {
jasmine.Matchers.Any.prototype.jasmineMatches = function(other) {
if (this.expectedClass == String) {
return typeof other == 'string' || other instanceof String;
}
@@ -348,7 +369,36 @@ jasmine.Matchers.Any.prototype.matches = function(other) {
return other instanceof this.expectedClass;
};
jasmine.Matchers.Any.prototype.toString = function() {
jasmine.Matchers.Any.prototype.jasmineToString = function() {
return '<jasmine.any(' + this.expectedClass + ')>';
};
jasmine.Matchers.ObjectContaining = function (sample) {
this.sample = sample;
};
jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
mismatchKeys = mismatchKeys || [];
mismatchValues = mismatchValues || [];
var env = jasmine.getEnv();
var hasKey = function(obj, keyName) {
return obj != null && obj[keyName] !== jasmine.undefined;
};
for (var property in this.sample) {
if (!hasKey(other, property) && hasKey(this.sample, property)) {
mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
}
else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) {
mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual.");
}
}
return (mismatchKeys.length === 0 && mismatchValues.length === 0);
};
jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () {
return "<jasmine.objectContaining(" + jasmine.pp(this.sample) + ")>";
};

View File

@@ -11,10 +11,6 @@ jasmine.PrettyPrinter = function() {
* @param value
*/
jasmine.PrettyPrinter.prototype.format = function(value) {
if (this.ppNestLevel_ > 40) {
throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
}
this.ppNestLevel_++;
try {
if (value === jasmine.undefined) {
@@ -23,8 +19,8 @@ jasmine.PrettyPrinter.prototype.format = function(value) {
this.emitScalar('null');
} else if (value === jasmine.getGlobal()) {
this.emitScalar('<global>');
} else if (value instanceof jasmine.Matchers.Any) {
this.emitScalar(value.toString());
} else if (value.jasmineToString) {
this.emitScalar(value.jasmineToString());
} else if (typeof value === 'string') {
this.emitString(value);
} else if (jasmine.isSpy(value)) {
@@ -57,8 +53,10 @@ jasmine.PrettyPrinter.prototype.format = function(value) {
jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
for (var property in obj) {
if (!obj.hasOwnProperty(property)) continue;
if (property == '__Jasmine_been_here_before__') continue;
fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) != null) : false);
fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
obj.__lookupGetter__(property) !== null) : false);
}
};
@@ -83,6 +81,11 @@ jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
};
jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
this.append("Array");
return;
}
this.append('[ ');
for (var i = 0; i < array.length; i++) {
if (i > 0) {
@@ -94,6 +97,11 @@ jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
};
jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
this.append("Object");
return;
}
var self = this;
this.append('{ ');
var first = true;

View File

@@ -1,5 +1,9 @@
jasmine.Queue = function(env) {
this.env = env;
// parallel to blocks. each true value in this array means the block will
// get executed even if we abort
this.ensured = [];
this.blocks = [];
this.running = false;
this.index = 0;
@@ -7,15 +11,30 @@ jasmine.Queue = function(env) {
this.abort = false;
};
jasmine.Queue.prototype.addBefore = function(block) {
jasmine.Queue.prototype.addBefore = function(block, ensure) {
if (ensure === jasmine.undefined) {
ensure = false;
}
this.blocks.unshift(block);
this.ensured.unshift(ensure);
};
jasmine.Queue.prototype.add = function(block) {
jasmine.Queue.prototype.add = function(block, ensure) {
if (ensure === jasmine.undefined) {
ensure = false;
}
this.blocks.push(block);
this.ensured.push(ensure);
};
jasmine.Queue.prototype.insertNext = function(block) {
jasmine.Queue.prototype.insertNext = function(block, ensure) {
if (ensure === jasmine.undefined) {
ensure = false;
}
this.ensured.splice((this.index + this.offset + 1), 0, ensure);
this.blocks.splice((this.index + this.offset + 1), 0, block);
this.offset++;
};
@@ -39,7 +58,7 @@ jasmine.Queue.prototype.next_ = function() {
while (goAgain) {
goAgain = false;
if (self.index < self.blocks.length && !this.abort) {
if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) {
var calledSynchronously = true;
var completedSynchronously = false;

View File

@@ -74,4 +74,4 @@ jasmine.Runner.prototype.topLevelSuites = function() {
jasmine.Runner.prototype.results = function() {
return this.queue.results();
};
};

View File

@@ -120,7 +120,8 @@ jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessag
jasmine.Spec.prototype.fail = function (e) {
var expectationResult = new jasmine.ExpectationResult({
passed: false,
message: e ? jasmine.util.formatException(e) : 'Exception'
message: e ? jasmine.util.formatException(e) : 'Exception',
trace: { stack: e.stack }
});
this.results_.addResult(expectationResult);
};
@@ -153,7 +154,7 @@ jasmine.Spec.prototype.finish = function(onComplete) {
jasmine.Spec.prototype.after = function(doAfter) {
if (this.queue.isRunning()) {
this.queue.add(new jasmine.Block(this.env, doAfter, this));
this.queue.add(new jasmine.Block(this.env, doAfter, this), true);
} else {
this.afterCallbacks.unshift(doAfter);
}
@@ -191,15 +192,15 @@ jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
}
for (i = 0; i < this.afterCallbacks.length; i++) {
this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true);
}
for (suite = this.suite; suite; suite = suite.parentSuite) {
for (i = 0; i < suite.after_.length; i++) {
this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true);
}
}
for (i = 0; i < runner.after_.length; i++) {
this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true);
}
};

View File

@@ -79,4 +79,4 @@ jasmine.Suite.prototype.execute = function(onComplete) {
this.queue.start(function () {
self.finish(onComplete);
});
};
};

View File

@@ -6,7 +6,9 @@ jasmine.WaitsBlock = function(env, timeout, spec) {
jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
jasmine.WaitsBlock.prototype.execute = function (onComplete) {
this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
if (jasmine.VERBOSE) {
this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
}
this.env.setTimeout(function () {
onComplete();
}, this.timeout);

View File

@@ -21,7 +21,9 @@ jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
if (jasmine.VERBOSE) {
this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
}
var latchFunctionResult;
try {
latchFunctionResult = this.latchFunction.apply(this.spec);
@@ -49,4 +51,4 @@ jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
self.execute(onComplete);
}, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
}
};
};

106
src/base.js → src/core/base.js Executable file → Normal file
View File

@@ -1,10 +1,12 @@
var isCommonJS = typeof window == "undefined" && typeof exports == "object";
/**
* Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
*
* @namespace
*/
var jasmine = {};
if (isCommonJS) exports.jasmine = jasmine;
/**
* @private
*/
@@ -20,17 +22,35 @@ jasmine.unimplementedMethod_ = function() {
*/
jasmine.undefined = jasmine.___undefined___;
/**
* Show diagnostic messages in the console if set to true
*
*/
jasmine.VERBOSE = false;
/**
* Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
*
*/
jasmine.DEFAULT_UPDATE_INTERVAL = 250;
/**
* Maximum levels of nesting that will be included when an object is pretty-printed
*/
jasmine.MAX_PRETTY_PRINT_DEPTH = 40;
/**
* Default timeout interval in milliseconds for waitsFor() blocks.
*/
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
/**
* By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite.
* Set to false to let the exception bubble up in the browser.
*
*/
jasmine.CATCH_EXCEPTIONS = true;
jasmine.getGlobal = function() {
function getGlobal() {
return this;
@@ -72,7 +92,7 @@ jasmine.MessageResult = function(values) {
jasmine.MessageResult.prototype.toString = function() {
var text = "";
for(var i = 0; i < this.values.length; i++) {
for (var i = 0; i < this.values.length; i++) {
if (i > 0) text += " ";
if (jasmine.isString_(this.values[i])) {
text += this.values[i];
@@ -89,9 +109,10 @@ jasmine.ExpectationResult = function(params) {
this.passed_ = params.passed;
this.expected = params.expected;
this.actual = params.actual;
this.message = this.passed_ ? 'Passed.' : params.message;
this.trace = this.passed_ ? '' : new Error(this.message);
var trace = (params.trace || new Error(this.message));
this.trace = this.passed_ ? '' : trace;
};
jasmine.ExpectationResult.prototype.toString = function () {
@@ -106,7 +127,8 @@ jasmine.ExpectationResult.prototype.passed = function () {
* Getter for the Jasmine environment. Ensures one gets created
*/
jasmine.getEnv = function() {
return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
return env;
};
/**
@@ -116,7 +138,7 @@ jasmine.getEnv = function() {
* @returns {Boolean}
*/
jasmine.isArray_ = function(value) {
return jasmine.isA_("Array", value);
return jasmine.isA_("Array", value);
};
/**
@@ -169,7 +191,7 @@ jasmine.pp = function(value) {
* @returns {Boolean}
*/
jasmine.isDomNode = function(obj) {
return obj['nodeType'] > 0;
return obj.nodeType > 0;
};
/**
@@ -186,6 +208,21 @@ jasmine.any = function(clazz) {
return new jasmine.Matchers.Any(clazz);
};
/**
* Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the
* attributes on the object.
*
* @example
* // don't care about any other attributes than foo.
* expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"});
*
* @param sample {Object} sample
* @returns matchable object for the sample
*/
jasmine.objectContaining = function (sample) {
return new jasmine.Matchers.ObjectContaining(sample);
};
/**
* Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
*
@@ -405,7 +442,7 @@ jasmine.isSpy = function(putativeSpy) {
* @param {Array} methodNames array of names of methods to make spies
*/
jasmine.createSpyObj = function(baseName, methodNames) {
if (!jasmine.isArray_(methodNames) || methodNames.length == 0) {
if (!jasmine.isArray_(methodNames) || methodNames.length === 0) {
throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
}
var obj = {};
@@ -438,11 +475,12 @@ jasmine.log = function() {
* @see jasmine.createSpy
* @param obj
* @param methodName
* @returns a Jasmine spy that can be chained with all spy methods
* @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods
*/
var spyOn = function(obj, methodName) {
return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
};
if (isCommonJS) exports.spyOn = spyOn;
/**
* Creates a Jasmine spec that will be added to the current suite.
@@ -460,6 +498,7 @@ var spyOn = function(obj, methodName) {
var it = function(desc, func) {
return jasmine.getEnv().it(desc, func);
};
if (isCommonJS) exports.it = it;
/**
* Creates a <em>disabled</em> Jasmine spec.
@@ -472,6 +511,7 @@ var it = function(desc, func) {
var xit = function(desc, func) {
return jasmine.getEnv().xit(desc, func);
};
if (isCommonJS) exports.xit = xit;
/**
* Starts a chain for a Jasmine expectation.
@@ -480,10 +520,12 @@ var xit = function(desc, func) {
* jasmine.Matchers functions.
*
* @param {Object} actual Actual value to test against and expected value
* @return {jasmine.Matchers}
*/
var expect = function(actual) {
return jasmine.getEnv().currentSpec.expect(actual);
};
if (isCommonJS) exports.expect = expect;
/**
* Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
@@ -493,6 +535,7 @@ var expect = function(actual) {
var runs = function(func) {
jasmine.getEnv().currentSpec.runs(func);
};
if (isCommonJS) exports.runs = runs;
/**
* Waits a fixed time period before moving to the next block.
@@ -503,6 +546,7 @@ var runs = function(func) {
var waits = function(timeout) {
jasmine.getEnv().currentSpec.waits(timeout);
};
if (isCommonJS) exports.waits = waits;
/**
* Waits for the latchFunction to return true before proceeding to the next block.
@@ -514,6 +558,7 @@ var waits = function(timeout) {
var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
};
if (isCommonJS) exports.waitsFor = waitsFor;
/**
* A function that is called before each spec in a suite.
@@ -525,6 +570,7 @@ var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout
var beforeEach = function(beforeEachFunction) {
jasmine.getEnv().beforeEach(beforeEachFunction);
};
if (isCommonJS) exports.beforeEach = beforeEach;
/**
* A function that is called after each spec in a suite.
@@ -536,6 +582,7 @@ var beforeEach = function(beforeEachFunction) {
var afterEach = function(afterEachFunction) {
jasmine.getEnv().afterEach(afterEachFunction);
};
if (isCommonJS) exports.afterEach = afterEach;
/**
* Defines a suite of specifications.
@@ -555,6 +602,7 @@ var afterEach = function(afterEachFunction) {
var describe = function(description, specDefinitions) {
return jasmine.getEnv().describe(description, specDefinitions);
};
if (isCommonJS) exports.describe = describe;
/**
* Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
@@ -565,25 +613,33 @@ var describe = function(description, specDefinitions) {
var xdescribe = function(description, specDefinitions) {
return jasmine.getEnv().xdescribe(description, specDefinitions);
};
if (isCommonJS) exports.xdescribe = xdescribe;
// Provide the XMLHttpRequest class for IE 5.x-6.x:
jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
try {
function tryIt(f) {
try {
return f();
} catch(e) {
}
return null;
}
var xhr = tryIt(function() {
return new ActiveXObject("Msxml2.XMLHTTP.6.0");
} catch(e) {
}
try {
return new ActiveXObject("Msxml2.XMLHTTP.3.0");
} catch(e) {
}
try {
return new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
}
try {
return new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
}
throw new Error("This browser does not support XMLHttpRequest.");
}) ||
tryIt(function() {
return new ActiveXObject("Msxml2.XMLHTTP.3.0");
}) ||
tryIt(function() {
return new ActiveXObject("Msxml2.XMLHTTP");
}) ||
tryIt(function() {
return new ActiveXObject("Microsoft.XMLHTTP");
});
if (!xhr) throw new Error("This browser does not support XMLHttpRequest.");
return xhr;
} : XMLHttpRequest;

0
src/mock-timeout.js → src/core/mock-timeout.js Executable file → Normal file
View File

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