Compare commits

...

293 Commits

Author SHA1 Message Date
Davis W. Frank and Sheel Choksi
be0e6222c5 Bumping to 2.0.0-rc2 due to an old, yanked 2.0.0-rc1 2013-07-28 17:55:29 -07:00
Davis W. Frank and Sheel Choksi
8c696ffc71 Release prep for 2.0.0-rc1 2013-07-28 17:31:24 -07:00
Davis W. Frank and Sheel Choksi
3dda67fe60 Building jasmine.js with last change. I'm sorry. 2013-07-28 17:03:12 -07:00
Davis W. Frank and Sheel Choksi
66d9b3d690 Moving call depth down to a lower number to increase CI stability at the expense of performance. 2013-07-28 17:01:49 -07:00
Davis W. Frank
c350694c1b Small release note edits 2013-07-27 14:41:38 -07:00
Davis W. Frank
25d674f2c5 Merge branch 'master' of https://github.com/pivotal/jasmine 2013-07-27 11:51:37 -07:00
Davis W. Frank
35bc200e31 First pass at 2.0rc1 release notes 2013-07-27 11:51:32 -07:00
JR Boyens
9e886b3972 Don't test for stack traces in Safari 5 2013-07-26 17:49:52 -07:00
JR Boyens
edd7e3932b Newer Firefoxen dislike large callback depths; tweak down to keep maximum recursion errors at bay 2013-07-26 17:26:17 -07:00
JR Boyens
0420e295f4 Resolve node issues 2013-07-26 16:44:48 -07:00
JR Boyens
8d295a2612 Move more things out to the core_script 2013-07-26 12:35:24 -07:00
JR Boyens
d10b93cd28 Add node specs to the Travis build 2013-07-26 12:28:11 -07:00
JR Boyens
358b9424b5 If specs fail in node, they should exit with a non-zero exit code 2013-07-26 12:14:01 -07:00
JR Boyens
2571a6fbbb First pass at Release Notes for 2.0 2013-07-26 12:01:42 -07:00
JR Boyens
00f88edc04 [Finishes #52731407] Escape special regex characters from the spec param 2013-07-26 11:28:15 -07:00
JR Boyens
98fa58ee49 Async timeout support 2013-07-26 11:27:40 -07:00
Colin O'Byrne and JR Boyens
984074ec95 small QueueRunner refactors 2013-07-24 17:38:26 -07:00
Colin O'Byrne and JR Boyens
6bb8a91301 inline the specConstructor 2013-07-24 15:20:15 -07:00
Colin O'Byrne and JR Boyens
97ce396008 Build distribution; fix test in FF 2013-07-24 14:41:55 -07:00
Colin O'Byrne and JR Boyens
051f3499ec Revert "[Finishes #45476285] Add timeout support to async tests"
This reverts commit 8f5d0beb8c.

Async timeout support is just not ready for prime time.
2013-07-24 14:39:06 -07:00
Colin O'Byrne and JR Boyens
8f5d0beb8c [Finishes #45476285] Add timeout support to async tests 2013-07-23 17:07:02 -07:00
Colin O'Byrne and JR Boyens
9609aba25f [Finishes #52959947] Warn user about spy conflicts; Refactor spy tests to more reflect responsibilities and removed duplicate tests 2013-07-23 17:00:30 -07:00
Colin O'Byrne and JR Boyens
30aec66ce5 [Finishes #14177231] copy properties onto spy 2013-07-22 14:54:43 -07:00
Colin O'Byrne and JR Boyens
663a58d617 [Finishes #51528655] spies should support and.stub() 2013-07-22 14:39:06 -07:00
Davis W. Frank & Sheel Choksi
3847557bbc Squashed spy refactor and new spy syntax
Jasmine spies now have a 'and' property which allows the user to
change the spy's execution strategy-- such as '.and.callReturn(4)'
and a 'calls' property which allows inspection of the calls a spy
has received.

* This is a breaking change *

There is a CallTracker that keeps track of all calls and arguments
and a SpyStrategy which determines what the spy should do when it
is called.
2013-07-22 14:29:52 -07:00
Colin O'Byrne and JR Boyens
18c30566bd Move from global to Env 2013-07-22 14:29:52 -07:00
Colin O'Byrne and JR Boyens
f2306729cd Improve isIE check to allow us to check for a minimum version 2013-07-22 14:22:38 -07:00
Colin O'Byrne and JR Boyens
2165d71dc5 Update matrix for Safari 5 2013-07-22 14:04:23 -07:00
Greg Cobb and JR Boyens
8c1881053c Resolve remaining test issues 2013-07-22 11:57:47 -07:00
Sheel Choksi
61a1f93488 Older IE fixes
Still not green, but getting close. Summary of Older IE discrepancies:
- Older IE doesn't have apply/call on the timing functions
- Older IE doesn't allow applying falsy arguments
- Older IE doesn't allow setting onclick to undefined values
- Older IE doesn't have text property on dom nodes
2013-07-21 19:44:47 -07:00
Sheel Choksi
d4f78922cd Update built distribution, it's a few commits behind 2013-07-21 18:36:12 -07:00
Sheel Choksi
04ac41d911 Fix phantomjs by using fnNameFor
Phantomjs's execptions toString include a ': ' at the end, so instead
use the exception's name property
2013-07-21 15:34:44 -07:00
Sheel Choksi
75b9dc64af Add in Safari version number since that seems to get Sauce to run it 2013-07-21 12:34:35 -07:00
Davis W. Frank
2d7fe0b6ce Merge pull request #388 from sheelc/html_self_test
Have Jasmine HTML use the source files in specs
2013-07-21 10:33:26 -07:00
Davis W. Frank
44feee57ac Merge pull request #394 from albertandrejev/ObjectContaing-message
ObjectContaining wrong filed value error message
2013-07-21 10:30:45 -07:00
Davis W. Frank
1394899c3c Even more explanation. Closes #396. 2013-07-21 08:27:01 -07:00
Davis W. Frank
d0825a37a3 Cleaning up with latest command line tools 2013-07-21 07:53:50 -07:00
Davis W. Frank
fc3d08bf40 Merge pull request #397 from valera-rozuvan/remove_unnecessary_parameter_to_function_call
Removed unnecessary parameter from suiteFactory() call.
2013-07-21 07:41:22 -07:00
JR Boyens
990cc41f45 Remove debugger statement 2013-07-19 18:55:07 -07:00
JR Boyens
03ffe5ce6a DRY up some sopping wet code 2013-07-19 18:51:05 -07:00
Greg Cobb and JR Boyens
1b0b4f22a0 Fix IE10 2013-07-19 17:34:04 -07:00
Greg Cobb and JR Boyens
a6953df28c Add corrected tunnel identifier 2013-07-19 15:13:41 -07:00
Greg Cobb and JR Boyens
5e71f3031e Update broken travis.yml 2013-07-19 15:04:40 -07:00
Greg Cobb and JR Boyens
4ea4ed25ee Revert previous change 2013-07-19 14:29:35 -07:00
Greg Cobb and JR Boyens
39d40a1cad Come on Travis... build it 2013-07-19 14:14:24 -07:00
Greg Cobb and JR Boyens
d40e0cebac Use Sauce Labs to test Jasmine against a metric ton of browsers 2013-07-19 11:29:12 -07:00
Greg Cobb and JR Boyens
89a54ea2bb Hacking the Gibson 2013-07-18 17:29:33 -07:00
Greg Cobb and JR Boyens
bc9c857f43 Valid YAML again 2013-07-18 17:12:39 -07:00
Greg Cobb and JR Boyens
24a7f55fa6 DEBIAN env variable is defined on the OS X host as well 2013-07-18 17:11:10 -07:00
Greg Cobb and JR Boyens
182cff4bd4 Build matrix tweak 2013-07-18 17:05:05 -07:00
Greg Cobb and JR Boyens
5dce5b1272 Try multi-language OS X build 2013-07-18 16:57:01 -07:00
Greg Cobb and JR Boyens
7c17b06856 Make chromedriver executable 2013-07-18 16:42:48 -07:00
Greg Cobb and JR Boyens
6569176cc9 Run specs on multiple browsers 2013-07-18 16:32:33 -07:00
Greg Cobb and JR Boyens
0f803430e4 Testing out travis changes 2013-07-18 15:30:04 -07:00
Greg Cobb and JR Boyens
821f13dff5 Don't refer to window for the sake of Node specs 2013-07-18 13:59:25 -07:00
Greg Cobb and JR Boyens
3e2d9baec2 [Finishes #40853563] Allowed the DelayedFunctionScheduler to support strings that are eval'd 2013-07-18 13:57:51 -07:00
Greg Cobb and JR Boyens
f637c1f833 Add images dir 2013-07-18 10:07:47 -07:00
Greg Cobb and JR Boyens
82b6904093 [Finishes #52810607] separate out the build standalone tasks 2013-07-18 09:51:27 -07:00
Greg Cobb and JR Boyens
0daae4d7b4 Update examples for 2.0 2013-07-16 10:00:16 -07:00
Sheel Choksi
f68657f14e Have Jasmine HTML use the source files in specs
Similar to the changes in Jasmine core and console, this gets the
HTML specs of Jasmine using j$ instead of jasmine so that they use
the source files instead of the built distribution
2013-07-13 23:36:29 -07:00
Sheel Choksi
c91df21a96 Detailed error messages in toThrow/toThrowError
- included what was thrown for failure messages in toThrow and toThrowError
- fixed typo from 'execption' to 'exception' in toThrowError failure messages
- clarified failure messages in toThrowError to include specific error types

[Fixes #52680709]
2013-07-12 23:24:50 -07:00
Sheel Choksi
5b986c953c Remove symlinked boot.js from spec/support
[Finishes #52810587]
2013-07-11 21:29:28 -07:00
Sheel Choksi
a932320d6c Merge pull request #401 from sheelc/async_queue_runner
Async queue runner fixes
2013-07-10 21:00:24 -07:00
Sheel Choksi
aabf8cec82 Specs/Suites wait for an async spec to finish
Go back to having all suites and specs run asynchronously so that
they properly wait for any async specs that there might be
2013-07-10 20:52:18 -07:00
Sheel Choksi
ccdcb293f4 Add back in forgotten 'env' to Env integration specs
As pointed out by @jdmarshall. Fixes #399
2013-07-07 21:56:26 -07:00
Sheel Choksi
ec7d58fce0 QueueRunner continues running functions in async case
Continue running functions even if an async spec throws an
exception during the synchronous portion of the spec
2013-07-07 21:56:26 -07:00
Davis W. Frank and Sheel Choksi
7f6b16ccf2 Only clear stack when QueueRunner is done with its functions 2013-07-03 15:20:45 -07:00
Sheel Choksi
34b8bf5fb0 Remove Env's calculation of executionTime
[#45659879]
2013-07-03 14:12:19 -07:00
Davis W. Frank and Sheel Choksi
179e54b9fb Refactor suite timing out of Env and into each Reporter
[finishes #45659879]
2013-07-03 09:30:05 -07:00
Davis W. Frank and Sheel Choksi
09fe7b0540 Have QueueRunner run specs iteratively if possible, fallback to recursion for async specs
This prevents the stack from growing as large for the normal cases and is giving a significant speedup for the performance suite
2013-07-02 16:37:38 -07:00
Davis W. Frank and Sheel Choksi
264b1fea50 Merge the node performance suite into the node suite
The node performance suite can be run with node: `node
spec/node_suite.js --perf`
2013-07-02 16:37:38 -07:00
Davis W. Frank and Sheel Choksi
dcf7a0867e Test asynchronous parts of Jasmine asynchronously 2013-07-02 16:37:38 -07:00
Davis W. Frank and Sheel Choksi
f5bc9faf63 Rename for stack-clearing post spec run to be more clear; use the real setTimeout when clearing stack 2013-07-02 09:51:41 -07:00
Davis W. Frank and Sheel Choksi
2916a8a1ff Cleaning up explicit dependencies 2013-07-01 15:56:29 -07:00
Valera Rozuvan
8ac33ff6c2 Removed unnecessary parameter from suiteFactory() call. 2013-07-01 14:02:25 +03:00
Davis W. Frank
661a884416 Merge pull request #392 from albertandrejev/jasmine.Any
jasmine.any Boolean support
2013-06-21 10:07:35 -07:00
Albert Andrejev
7acc6b327a ObjectContaining wrong filed value error message 2013-06-21 15:16:41 +03:00
Albert Andrejev
e40e0c9170 jasmine.any Boolean support 2013-06-21 15:07:55 +03:00
Davis W. Frank
7ae3fa9fef Fixed some specs that were not referring to the correct instance of Jasmine 2013-06-10 22:45:04 -07:00
Davis W. Frank
e73b9e7902 Merge pull request #384 from sheelc/apireporter_execution_time
Add execution time elapsed to JsApiReporter
2013-06-09 20:52:10 -07:00
Sheel Choksi
ffdf1eb16d Add execution time elapsed to JsApiReporter
Since this information is desired in ConsoleReporter, HtmlReporter,
and now JsApiReporter, the executionTime is passed through in
jasmineDone from Env instead of making each reporter compute it.

Fixes #30, [Finishes #45659879]
2013-06-09 12:09:06 -07:00
Davis W. Frank
d5f1264416 Merge pull request #383 from sheelc/remove_format_exception
Remove unused formatException from util
2013-06-09 10:13:11 -07:00
Sheel Choksi
579fddc2d2 Remove unused formatException from util
The ExceptionFormatter is used instead of formatException from jasmine util
2013-06-08 21:46:16 -07:00
Davis W. Frank
313e607135 Merge pull request #369 from sheelc/query-selectors
Query selectors
2013-06-07 07:38:11 -07:00
Davis W. Frank
b6599d52aa Merge pull request #358 from sheelc/safari_exception_fix
Fix spec to throw error, ensuring a stack property
2013-06-07 07:37:39 -07:00
pivotalprivate
582ad6512a Merge pull request #379 from sheelc/toThrowError_fixup
Fix up refactoring mistake in toThrowError
2013-06-05 09:54:12 -07:00
Sheel Choksi
600be098af Fix up my refactoring mistake in toThrowError
strengthen the associated tests to protect against it in the future
2013-06-04 19:49:11 -07:00
Davis W. Frank
b87eb240b3 Merge pull request #378 from sheelc/toThrowError_modifications
Avoid instantiating passed in errorType in toThrowError
2013-06-03 21:24:38 -07:00
Sheel Choksi
7055d95584 Avoid instantiating passed in errorType in toThrowError
since the passed in errorType could be a custom user function,
we instead detect if its an instanceof Error by using a Surrogate
(inspired by Backbone's use of surrogacy)
2013-06-03 21:05:27 -07:00
Sheel Choksi
1c87060804 Fix spec to throw error, ensuring a stack property
In Safari Mac 6.0.4 (and possibly other versions), a new error does
not have the stack property. Throwing the error and then catching it
ensures that the stack property has the correct value.

This fix gets the specs to run green in Safari.
2013-06-03 19:25:37 -07:00
Sheel Choksi
b4acdbd90a Remove use of getElementsByTagName and getElementsByClassName
Replace calls to these functions with querySelector and querySelectorAll
2013-06-03 19:24:53 -07:00
Davis W. Frank
fbb9f53524 Fixing red build. Not sure why, but this spec was green in Chrome and Node.js 2013-06-03 10:31:52 -07:00
Davis W. Frank
0ac497db6b Simplifying toThrow:
- It still supports no expected, which means that something was thrown
- Expected value is now tested via equality in order to pass

Adding toThrowError:
- toThrowError() passes if an Error type was thrown
- toThrowError(String) & toThrowError(RegExp) compare Expected to the Error message
- toThrowError(Error constructor) compares Expected to the constructor of what was thrown
- toThrowError(Error constructor, String) & toThrowError(Error constructor, RegExp) compares both the Error and the message

Also, equality now handles Errors, enforcing the message as part of the equality.
2013-06-03 09:24:43 -07:00
Davis W. Frank
9e31201f1a Breaking out Spies into their own source file 2013-06-03 08:22:45 -07:00
Davis W. Frank
d53002c63a Matchers & Matchers specs now broken up into individual files. There is now a requireMatchers jasmineRequire function to attach matchers properly. 2013-06-02 22:22:25 -07:00
Davis W. Frank
3271dc8838 Last commit did not include self-test with Any and ObjectContaining in separate files. Fixed. 2013-06-02 22:16:30 -07:00
Davis W. Frank
475aacbfbb [Finishes #50607273] - added specs to cover the cases from GitHub issue #371 2013-05-29 20:16:12 -07:00
Davis W. Frank
8303c79f26 Adding spec to cover equality of frozen objects, per GitHub issue #266 2013-05-29 12:32:01 -07:00
Davis W. Frank
5700ace2c9 Squashed matchers refactor - matchers now unit-testable apart from Expectation and Spec. 2013-05-28 16:54:01 -07:00
Davis W. Frank
aca43bd3a3 Squashed commit of work to make Jasmine a collection of isolated modules. Note now that in our test suite, "jasmine" now always refers to the build jasmine loaded from jasmine.js and "j$" always refers to the code in the src directories.
Also, dev_boot.js is now a copy of boot.js and has additional changes to load jasmine the second time, into the j$ reference.
2013-05-28 14:09:20 -07:00
Davis W. Frank
7516bba2b0 Updating gem source to secure version 2013-05-21 11:47:47 -07:00
Davis W. Frank
4f19d34ad7 Merge pull request #363 from robinboehm/remove-deprecated-matcherspp
Remove deprecated jasmine.Matchers.pp function.
2013-05-12 11:35:02 -07:00
Robin Böhm
c40b64a24c Remove deprecated jasmine.Matchers.pp function. Marked deprecated at may 2010. 2013-05-12 09:37:07 +02:00
Davis W. Frank
baad5ff01f Merge pull request #356 from sheelc/spec_titles
Add titles to specs in HtmlReporter
2013-04-28 23:11:40 -07:00
Sheel Choksi
bf2adf55eb Add titles to specs in HtmlReporter
Each spec symbol contains a title, which is the full name of the
spec it represents.

[Finishes #48420677]
2013-04-28 21:35:12 -07:00
Davis W. Frank
dd8d3f9788 Fix [#48420035] 2013-04-20 08:27:38 -07:00
Rajan Agaskar
9c4467bac0 Merge pull request #347 from sheelc/regex-exception-matching
Regex exception matching
2013-04-08 18:16:09 -07:00
Sheel Choksi
c017257164 add in regex matching for toThrow matcher 2013-04-07 16:15:07 -07:00
Sheel Choksi
2445fb36dc simplify failure message logic in the toThrow matcher 2013-04-06 22:06:14 -07:00
Sheel Choksi
eec6d7d23e update lib/jasmine-core/jasmine.js to make 'grunt execSpecsinNode' pass again 2013-04-06 22:03:31 -07:00
Davis W. Frank
3110da62e5 Update Contribute.markdown 2013-04-01 11:35:22 -07:00
pivotalprivate
d41b281eb1 Update Contribute.markdown
Adding link for how to get grunt-cli installed
2013-04-01 11:32:57 -07:00
Davis W. Frank
6feb124853 Remove JSDocs from everywhere in the Repo - source code, GHPages, etc. We're not using them and the stale docs were confusing. Fixes #338 Fixes #99 2013-03-26 23:11:24 -07:00
Davis W. Frank
3be247ceb1 Merge branch 'master' of https://github.com/pivotal/jasmine 2013-03-24 09:42:14 -07:00
Davis W. Frank
edc2bfae93 All Jasmine file manipulation/development moved from Thor to Grunt. Thor has been removed completely. Run grunt --help to see available tasks.
Canonical Jasmine version now lives in `package.json` (Node formatted) and is copied into Jasmine source (JavaScript and Ruby)

Jasmine distribution now has MIT license and Pivotal Labs copyright at the top of each distributed file.
2013-03-24 09:41:42 -07:00
Davis W. Frank
01b2fc612c Merge pull request #340 from CaioToOn/fix-clock-settimeout
DelayedFunctionScheduler tick, setTimeout/Interval delay defaults to 0
2013-03-13 15:47:09 -07:00
Caio Cunha
d8f6aac2cd Added spec for #tick default delay 2013-03-13 11:00:30 -03:00
Caio Cunha
e7a930a5b3 DelayedFunctionScheduler tick, setTimeout/Interval delay defaults to 0
If ommited or null, delay for refered methods will default to 0. This
will make setTimeout and setInterval methods to behave as expected by
[HTML5 specs](http://www.w3.org/TR/html51/webappapis.html#timers):

"Let timeout [delay] be the second argument to the method, or zero if the
argument was omitted."

This commit also fixes an issue with tick() being called without arguments,
that causes the scheduler to break and stop working after this call.
2013-03-13 10:55:46 -03:00
Dan Hansen and Davis W. Frank
6b2d8da55f Cleanup Gruntfile so that all tasks are registered at the top level
[Finishes #45559005]
2013-03-04 16:43:48 -08:00
Dan Hansen and Davis W. Frank
538b32e401 Default character encoding is now UTF-8 2013-03-04 16:24:21 -08:00
Davis W. Frank
e6e8908f49 Merge pull request #332 from bjornblomqvist/preserve-whitespace-in-result-message
Fixes #296, Whitespace failures will now be esier to understand.
2013-03-03 22:27:55 -08:00
Davis W. Frank
86dafd5d2d Merge pull request #329 from sunliwen/master
Build status should be updated
2013-03-03 21:14:14 -08:00
Davis W. Frank
aa60d5f00d Update util.js
Removed old jsDoc comments
2013-03-03 21:11:30 -08:00
Davis W. Frank
079e6e1e08 Merge pull request #333 from bjornblomqvist/utf8-fix
fix so that utf-8 characters are rendered correctly in the browser
2013-03-03 21:03:42 -08:00
Dan Hansen and Davis W. Frank
7706512525 Delegate to originalJasmine for the version string in test 2013-03-03 16:19:56 -08:00
Dan Hansen and Davis W. Frank
e09fd40933 Move to grunt for building all distribution files.
* canonical version number of jasmine-core is now is package.json
* `grunt buildDistribution` builds jasmine.js, jasmine-html.js, jasmine.css and outputs them to the dist dir
* `grunt buildStandaloneDist` builds the example spec runner files and compresses them to dist/jasmine-VERSION.zip
* `grunt compass` compiles jasmine.css
* jasmine.Env handling of version is backwards compatible, but uses the version string directly (and nicely deprecated)
* Ruby/thor tasks that did the above deleted
2013-03-03 16:04:38 -08:00
Dan Hansen and Davis W. Frank
6eecc562ff This spec is for a case where FF *sometimes* loses it's exception
message property. Fixed the spec using a double so that the test will
run green on non-FF environments.
2013-03-01 14:32:58 -08:00
Dan Hansen and Davis W. Frank
cf7bb0269b Added grunt to project.
Move from embedded "fork" of jsHint to using grunt's jsHint module.
Cleaned ALL jsHint errors.
Added jasmine.util.isUndefined as alternative to extra careful protection against undefined clobbering
2013-03-01 14:28:18 -08:00
Dan Hansen and Davis W. Frank
b22bf9a031 Protect against a FF bug: Exceptions don't always have a message property even though they were instantiated with one. Using Error#toString alleviates this 2013-03-01 10:43:09 -08:00
Dan Hansen and Davis W. Frank
b7af6abca5 Support pending specs with:
- xit
- it with a null function body ( it("should be pending");
- calling pending() inside a spec
- having a spec without any expectations

Pending and Filtered specs now call Reporter interface specStarted so that reporting acts as expected.
Pending and Filtered spec names are present and styled in the HTML reporter

Using xit used to disable a spec. Disabling is now just when a spec is filtered out at run time (usually w/ the reporter).

Suites are still disabled with xdescribe and means its specs are never executed.
2013-03-01 10:41:25 -08:00
Dan Hansen and Davis W. Frank
d6da13a8dd Attempt at normalizing error stacks across browsers.
Failed expectations now have a `stack` property, remove `trace.stack`
2013-02-27 16:37:31 -08:00
Dan Hansen and Davis W. Frank
dc4563d45c Require jasmine gem in the rakefile 2013-02-27 10:30:03 -08:00
Dan Hansen and Davis W. Frank
92492c0144 Env#addMatchers is no longer exposed on spec, it is exposed globally in boot.js. 2013-02-26 16:41:46 -08:00
Dan Hansen and Davis W. Frank
d6987a6c84 Cleanup 2013-02-26 13:39:06 -08:00
Dan Hansen and Davis W. Frank
43c8fdd33f Update travis yml to use the new build script 2013-02-26 12:50:50 -08:00
Dan Hansen and Davis W. Frank
98ae076f0c * JsApiReporter - better inteface for getting spec results (it's a slice!)
* Removed RSpec dependency from running self_test/CI - includes using new Jasmine::Formatter::Console from the gem
*
2013-02-26 12:24:59 -08:00
Dan Hansen and Davis W. Frank
2c06e36b9b Fix for default state of exceptionCatching from HTML ui 2013-02-26 12:21:02 -08:00
Darwin
5a744884fe fix so that utf-8 characters are rendered correctly in the browser 2013-02-26 15:58:01 +01:00
Darwin
e6888b840d Fixes #296, Whitespace failures will now be esier to understand. 2013-02-26 12:41:19 +01:00
Dan Hansen
e682d18387 When filtering spec, match against the full name of the spec 2013-02-22 14:36:46 -08:00
Dan Hansen and Davis W. Frank
10b09ea9f5 Moved dependencies out of HtmlReporter and into boot.js - QueryString for spec filtering and UI around raising exceptions checkbox; New object for handling spec filtering for browsers; 2013-02-19 15:29:50 -08:00
Dan Hansen and Davis W. Frank
c53b36a9b2 Fix Build: Firefox doesn't hoist function definitions in for loops 2013-02-19 15:26:08 -08:00
Dan Hansen and Davis W. Frank
af71f4d2f9 Remove vestiges of old HTMLReporter 2013-02-19 13:45:25 -08:00
Dan Hansen and Davis W. Frank
83227f2163 Merge branch '2_0'
src/html/HtmlReporter.js
2013-02-19 12:09:33 -08:00
Dan Hansen and Davis W. Frank
f865758124 Updated jasmine.js 2013-02-19 11:52:16 -08:00
Davis W. Frank
3fc79bac9e * Removed old Queue & Runner in favor of Suite using the new QueueRunner
* New reporter interface across all reporters
* xdescribe & xit now store disabled specs
* Rewrite of HtmlReporter to support new interface and be more performant
2013-02-19 11:45:05 -08:00
Davis W. Frank
05977203a6 Cleanup of Exception formatting (incl. better Browser support re:
toString;
NestedResults is dead, remove it from jasmine.yml
2013-02-19 11:37:13 -08:00
Sun, Liwen
5bea864e1c Update README.markdown 2013-02-16 21:17:37 +08:00
Davis W. Frank
a9eaa66da5 removing the exception formatter from the util namespace 2012-12-09 09:29:05 -08:00
Davis W. Frank
30bf565e69 removing jasmine.VERBOSE - not used 2012-12-08 12:02:42 -08:00
Davis W. Frank
668dd784ef Remove jasmine.util.extend 2012-12-08 11:48:11 -08:00
Davis W. Frank & Rajan Agaskar
4ad43267ab Update immediate goals.
- This commit should get rebased out before merging to master
2012-12-07 17:51:17 -08:00
Davis W. Frank & Rajan Agaskar
be6b87a31b Remove obsolete NestedResults 2012-12-07 17:37:20 -08:00
Rajan Agaskar
43552494ee Remove jasmine.CATCH_EXCEPTIONS
- HTMLReporters should be rewritten to make this sort of thing easier.
- Fix HTMLReporter try/catch switch
- We can't really call resultCallback & throw, so that's been reverted
  for now.
2012-12-07 17:26:59 -08:00
Rajan Agaskar
98c99c4ebb Remove obsolete MessageResult
- jasmine.log is no longer supported.
2012-12-07 16:44:41 -08:00
Rajan Agaskar
4318de4647 Remove obsolete bindOriginal, timing bindings.
- Handled by boot now.
2012-12-07 16:40:58 -08:00
Davis W. Frank & Rajan Agaskar
a526ebf261 Re-add async support (achieved via done callbacks)
- TODO: pull out queueRunner into a new object.
2012-12-07 16:36:24 -08:00
Davis W. Frank & Rajan Agaskar
c2e1327f39 Permit HTMLReporter to render every 250ms
- This is necessary for the user to see spec results fill-in
  progressively.
- There is a slight performance loss. 250 - 500ms seems to deliver the
  same amount of loss. This is still at parity with Jasmine 1.x
2012-12-07 14:49:19 -08:00
Davis W. Frank & Rajan Agaskar
234f2a1585 Reintroduce fn that clears stack occasionally
- setTimeout will clear stack, prevent overflow. We run this once every
  thousand specs.
- Browser users will probably want a time-based clear rather than spec
  count based clear, as a thousand tests is typically quite slow. The
  reporter should provide this.
2012-12-07 14:49:14 -08:00
Davis W. Frank & Rajan Agaskar
c584f182ab Fix getFullName on spec.
- Fixes specFiltering on nested specs
2012-12-07 11:32:52 -08:00
Davis W. Frank & Rajan Agaskar
74f928fd54 Re-add Mock Clock behavior as global 'clock'
- Use clock.install, clock.tick...
- Add unit coverage.
- Fixes old bug in function scheduler
2012-12-07 10:04:47 -08:00
Davis W. Frank & Rajan Agaskar
a1011e7748 Rewrite Spec & allow Jasmine to be namespaced
- THere seems to be a performance regression. Large test suites may
  throw
- Regressions: Mock Clock won't install correctly, async specs are
  temporarily not supported.
- Async spec runs/waits interface is gone. Blocks are gone.
- Move most global usage into jasmine.Env constructor.
- Remove optional 'Jasmine running' from HtmlReporter -- caused
  NS_FACTORY_ERROR in firefox when tested
2012-12-06 09:10:24 -08:00
Vikki
8b02bf731b Make all tests use syntax compatible with IE6/7/8 2012-12-04 09:15:40 -08:00
Davis W. Frank & Rajan Agaskar
779dee1211 Remove results from Queue
- consequently, Runner & Suite no longer have results.
- Results come back to reporters from Spec, we should not have a need to
  walk them later via suite/runner (in fact, no reporter used results on
  suite/runner -- only bad tests)
- Remove/clean up tests relying on #results
- Remove integration tests that duplicate already tested behavior
2012-12-03 15:57:16 -08:00
Davis W. Frank & Rajan Agaskar
1f5e790c41 Remove Matchers report code cruft.
- Code that used reportWasCalled was removed previously.
2012-12-03 15:46:29 -08:00
Davis W. Frank & Rajan Agaskar
cd3a0c854b buildExpectationResult now returns a data object.
- Meant for passing to reporters.
2012-12-03 15:46:29 -08:00
Davis W. Frank & Rajan Agaskar
f9cbad1512 Fix mistaken toFail() expect usage
- It looks like toEqual got globally replaced where it shouldn't have
  been
2012-12-03 15:46:29 -08:00
Davis W. Frank & Rajan Agaskar
f840458b34 Encapsulate ExpectationResult 2012-12-03 15:46:29 -08:00
Davis W. Frank & Rajan Agaskar
34bd1969e7 Add performance smoke suite 2012-12-03 15:46:29 -08:00
Davis W. Frank & Rajan Agaskar
dfed37531e Add unit coverage for ExpectationResult 2012-12-03 15:46:29 -08:00
Davis W. Frank & Rajan Agaskar
08f5a8c98f Track abstract goals for Jasmine 2.0 2012-12-03 15:46:28 -08:00
Davis W. Frank & Rajan Agaskar
8d94d0bfc5 Move ExpectationResult into its own file 2012-12-03 15:46:28 -08:00
Rajan Agaskar
3e5da57cf9 Remove jasmine.XmlHttpRequest
- Cruft left over from when jasmine offered an "include" function
2012-12-03 15:46:28 -08:00
Davis W. Frank & Rajan Agaskar
e2af08e0a6 Move most jasmine global usage into boot.
- thor build scripts broken for now.
2012-12-03 15:46:26 -08:00
Davis W. Frank & Rajan Agaskar
b6c3999c3a Version 1.3.1 2012-12-03 15:40:01 -08:00
Davis W. Frank & Rajan Agaskar
6785d1a05c Re-add pages submodule for release build script
- Use public github url
2012-12-03 15:40:00 -08:00
dev
e74f09df9c 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 15:40:00 -08:00
Davis W. Frank & Rajan Agaskar
f7c9aaa996 Setup Travis build 2012-12-03 15:40:00 -08:00
Davis W. Frank & Rajan Agaskar
86994b25db Use jasmine-gem for jasmine-core tests 2012-12-03 15:40:00 -08:00
Davis W. Frank & Rajan Agaskar
9a7c76ea23 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-12-03 15:40:00 -08:00
Max Brunsfeld
e3a013ae99 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-12-03 15:40:00 -08:00
Max Brunsfeld
ead9aa6d5a 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-12-03 15:40:00 -08:00
Joost Elfering
d9467317a8 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-12-03 15:40:00 -08:00
Joost Elfering
63ad879c12 added some specs to strengthen the coverage pivotal/jasmine#234 2012-12-03 15:40:00 -08:00
Joost Elfering
b95c43ab7c 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-12-03 15:40:00 -08:00
gvanhove
3685d3199c less confusing messages for toHaveBeenCalledWith 2012-12-03 15:40:00 -08:00
Gunnar Ahlberg
a34077a8af cover spy on on undefined method 2012-12-03 15:40:00 -08:00
James Cracknell
ac55e26870 Added toBeNaN matcher 2012-12-03 15:40:00 -08:00
PLOE09
acdc497361 Add JSDoc @return-tag to 'spyOn' and 'expect' functions support
code completion in Spket IDE
2012-12-03 15:40:00 -08:00
Christopher Mitchell
b527ccd2fa 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-12-03 15:40:00 -08:00
Kevin Connor
cfa95fcf2c create downloads dir if needed during build_standalone_distribution 2012-12-03 15:40:00 -08:00
Alexey Androsov
ae9ddd74a2 update jsdoc for jasmine.Matchers.prototype.toThrow
expected argument is optional
2012-12-03 15:40:00 -08:00
Kevin Locke
26f0f6f213 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-12-03 15:40:00 -08:00
rgould
c5ba032d28 Regenerate jasmine.js after adding ensured support. 2012-12-03 15:39:59 -08:00
rgould
bbc4c70c91 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-12-03 15:39:59 -08:00
John Firebaugh
c5c57247f8 Test that show that afterEach and after are not being called when a waitsFor times out. 2012-12-03 15:39:59 -08:00
John Firebaugh
9990eb7b6e Test that afterEach is called after a failing spec. 2012-12-03 15:39:59 -08:00
John Firebaugh
b5b50182b2 Consolidate all waitsFor specs in the same describe block. 2012-12-03 15:39:59 -08:00
Oliver Caldwell
4d106c2b33 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-12-03 15:39:59 -08:00
Dave Burt
5e594946bb 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-12-03 15:39:59 -08:00
Davis W. Frank
6ac4b686a3 Move to an earlier RedCarpet to fix an incompatibility with Rocco. Regen of gh-pages. 2012-12-03 15:39:59 -08:00
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
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
191 changed files with 12120 additions and 17489 deletions

4
.gitignore vendored
View File

@@ -10,3 +10,7 @@ site/
tags
Gemfile.lock
pkg/*
.sass-cache/*
src/html/.sass-cache/*
node_modules/
*.swp

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

47
.travis.yml Normal file
View File

@@ -0,0 +1,47 @@
---
script: $TEST_COMMAND
language: ruby
rvm: 1.9.3
env:
global:
- USE_SAUCE=true
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
- TEST_COMMAND="bash travis-core-script.sh"
- secure: WSPWhlnC4mWSnSPquX+m1/BCu5ch5NygkaHuM2Nea7lD8oS3XLX8QncZZAsQ4lnNfqoDDuBOizG0AESiqNvE4y6x5qvLLTS6q+ce255ZEMZ71TBdZgDEEvGMEjOPPsVXiXyTQOP1lwOPlrbZvaPgWV7e11KIBab6DfFcQpnvDgo=
- secure: SW7CJhZnwaNT749Gdnhvqb5rbXlAOsygUAzh9qhtyvbqXKkmJdBIEsO01YF6pbju1X2twE9JvWCOxeZju43NgQChJlPsGbjY2j3k/TdQeTAJesQe2K7ytwghunI30gjEovtRH0T3w1EmcKPH8yj5eBIcB2OYoJHx8KEC7e68q1g=
matrix:
include:
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh"
- env:
- JASMINE_BROWSER="firefox"
- SAUCE_PLATFORM="Linux"
- SAUCE_VERSION=''
- env:
- JASMINE_BROWSER="safari"
- SAUCE_PLATFORM="OS X 10.8"
- SAUCE_VERSION=6
- env:
- JASMINE_BROWSER="safari"
- SAUCE_PLATFORM="OS X 10.6"
- SAUCE_VERSION=5
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_PLATFORM="Windows 8"
- SAUCE_VERSION=10
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_PLATFORM="Windows 7"
- SAUCE_VERSION=9
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_PLATFORM="Windows 7"
- SAUCE_VERSION=8
- env:
- JASMINE_BROWSER="chrome"
- SAUCE_PLATFORM="Linux"
- SAUCE_VERSION=''
- env:
- JASMINE_BROWSER="phantomjs"
- USE_SAUCE=false

View File

@@ -1,10 +1,80 @@
# Developing for Jasmine Core
## How to Contribute
# Developing for Jasmine Core
We welcome your contributions - Thanks for helping make Jasmine a better project for everyone. Please review the backlog and discussion lists (the main group - [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js) and the developer's list - [http://groups.google.com/group/jasmine-js-dev](http://groups.google.com/group/jasmine-js-dev)) before starting work - what you're looking for may already have been done. If it hasn't, the community can help make your contribution better.
## How to write new Jasmine code
## General Workflow
Please submit pull requests via feature branches using the semi-standard workflow of:
1. Fork it
1. Create your feature branch (`git checkout -b my-new-feature`)
1. Commit your changes (`git commit -am 'Add some feature'`)
1. Push to the branch (`git push origin my-new-feature`)
1. Create new Pull Request
We favor pull requests with very small, single commits with a single purpose.
## Background
### Directory Structure
* `/src` contains all of the source files
* `/src/console` - Node.js-specific files
* `/src/core` - generic source files
* `/src/html` - browser-specific files
* `/spec` contains all of the tests
* mirrors the source directory
* there are some additional files
* `/dist` contains the standalone distributions as zip files
* `/lib` contains the generated files for distribution as the Jasmine Rubygem and the Python package
### Self-testing
Note that Jasmine tests itself. The files in `lib` are loaded first, defining the reference `jasmine`. Then the files in `src` are loaded, defining the reference `j$`. So there are two copies of the code loaded under test.
The tests should always use `j$` to refer to the objects and functions that are being tested. But the tests can use functions on `jasmine` as needed. _Be careful how you structure any new test code_. Copy the patterns you see in the existing code - this ensures that the code you're testing is not leaking into the `jasmine` reference and vice-versa.
### `boot.js`
__This is new for Jasmine 2.0.__
This file does all of the setup necessary for Jasmine to work. It loads all of the code, creates an `Env`, attaches the global functions, and builds the reporter. It also sets up the execution of the `Env` - for browsers this is in `window.onload`. While the default in `lib` is appropriate for browsers, projects may wish to customize this file.
For example, for Jasmine development there is a different `dev_boot.js` for Jasmine development that does more work.
### Compatibility
* Browser Minimum
* IE8
* Firefox 3.x
* Chrome ??
* Safari 5
## Development
All source code belongs in `src/`. The `core/` directory contains the bulk of Jasmine's functionality. This code should remain browser- and environment-agnostic. If your feature or fix cannot be, as mentioned above, please degrade gracefully. Any code that should only be in a non-browser environment should live in `src/console/`. Any code that depends on a browser (specifically, it expects `window` to be the global or `document` is present) should live in `src/html/`.
### Install Dependencies
Jasmine Core relies on Ruby and Node.js.
To install the Ruby dependencies, you will need Ruby, Rubygems, and Bundler available. Then:
$ bundle
...will install all of the Ruby dependencies.
To install the Node dependencies, you will need Node.js, Npm, and [Grunt](http://gruntjs.com/), the [grunt-cli](https://github.com/gruntjs/grunt-cli) and ensure that `grunt` is on your path.
$ npm install --local
...will install all of the node modules locally. If when you run
$ grunt
...you see that JSHint runs your system is ready.
### How to write new Jasmine code
Or, How to make a successful pull request
@@ -12,33 +82,30 @@ Or, How to make a successful pull request
* _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
* _Write code in the style of the rest of the repo_ - Jasmine should look like a cohesive whole
* _Ensure the *entire* test suite is green_ in all the big browsers, Node, and JSHint - your contribution shouldn't break Jasmine for other users
Follow these tips and your pull request, patch, or suggestion is much more likely to be integrated.
## Environment
### Running Specs
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.
Jasmine uses the [Jasmine Ruby gem](http://github.com/pivotal/jasmine-gem) to test itself in browser.
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.
$ rake jasmine
## Development
...and then visit `http://localhost:8888` to run specs.
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/`.
Jasmine uses Node.js with a custom runner to test outside of a browser.
Please respect the code patterns as possible. For example, using `jasmine.getGlobal()` to get the global object so as to remain environment agnostic.
$ grunt execSpecsInNode
## Running Specs
...and then the results will print to the console. All specs run except those that expect a browser (the specs in `spec/html` are ignored).
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/`).
## Before Committing or Submitting a Pull Request
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.
1. Ensure all specs are green in browser *and* node
1. Ensure JSHint is green with `grunt jsHint`
1. Build `jasmine.js` with `grunt buildDistribution` and run all specs again - this ensures that your changes self-test well
Please ensure all specs are green before committing.
There are rake tasks to help with getting green:
* `rake spec` outputs the expected number of specs that should be run and attempts to run in browser and Node
* `rake spec:browser` opens `spec/runner.html` in the default browser on MacOS. Please run this in at least Firefox and Chrome before committing
* `rake spec:node` runs all the Jasmine specs in Node.js - it will complain if Node is not installed
* `rake hint` runs all the files through JSHint and will complain about potential viable issues with your code. Fix them.
Note that we use Travis for Continuous Integration. We only accept green pull requests.

61
GOALS_2.0.md Normal file
View File

@@ -0,0 +1,61 @@
# (Vague) Jasmine 2.0 Goals/(Guidelines)
1. No globals!
* jasmine library is entirely inside `jasmine` namespace
* globals required for backwards compatibility should be added in `boot.js` (EG, var describe = jasmine.getCurrentEnv().describe lives in boot.js)
1. Don't use properties as getters. Use methods.
* Properties aren't encapsulated -- can be mutated, unsafe.
1. Reporters get data objects (no methods).
* easier to refactor as needed
1. More unit tests - fewer nasty integration tests
## Remaining non-story-able work:
* Make a `TODO` list
### Hard
* Finish killing Globals
* Guidelines:
* New objects can have constructors on `jasmine`
* Top level functions can live on `jasmine`
* Top level (i.e., any `jasmine` property) should only be referenced inside the `Env` constructor
* should better allow any object to get jasmine code (Node-friendly)
* review everything in base.js
* Spies
* break these out into their own tests/file
* Remove isA functions:
* isArray_ - used in matchers and spies
* isString_
* isDOMNode_
* isA_
* unimplementedMethod_, used by PrettyPrinter
* jasmine.util should be util closure inside of env or something
* argsToArray is used for Spies and matching (and can be replaced)
* inherit is only for PrettyPrinter now
* formatException is used only inside Env/spec
* htmlEscape is for messages in matchers - should this be HTML at all?
* Matchers improvements
* unit testable DONE
* better equality (from Underscore) DONE
* refactor equals function so that it just loops & recurses over a list of fns (custom and built-in) - 2.1?
* addCustomMatchers doesn't explode stack
* Pretty printing
* move away from pretty printer and to a JSON.stringify implementation?
* jasmineToString vs. custom toString ?
### Easy
* unify params to ctors: options vs. attrs.
* This will be a lot of the TODOs, but clean up & simplify Env.js (is this a 2.1 task?)
## Other Topics
* Docs
* Docco has gone over well. Should we annotate all the sources and then have Pages be more complex, having tutorials and annotated source like Backbone? Are we small enough?
* Need examples for:
* How to build a Custom Matcher
* How to add a custom equality tester

11
Gemfile
View File

@@ -1,4 +1,11 @@
source :rubygems
gem "term-ansicolor", :require => "term/ansicolor"
source 'https://rubygems.org'
gem "rake"
gem "jasmine", :git => 'https://github.com/pivotal/jasmine-gem.git'
#gem "jasmine", path: "/Users/pivotal/workspace/jasmine-gem"
unless ENV["TRAVIS"]
group :debug do
gem 'debugger'
end
end
gemspec

48
Gruntfile.js Normal file
View File

@@ -0,0 +1,48 @@
module.exports = function(grunt) {
var pkg = require("./package.json");
global.jasmineVersion = pkg.version;
grunt.initConfig({
pkg: pkg,
jshint: require('./grunt/config/jshint.js'),
concat: require('./grunt/config/concat.js'),
compass: require('./grunt/config/compass.js'),
compress: require('./grunt/config/compress.js')
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.loadTasks('grunt/tasks');
grunt.registerTask('default', ['jshint:all']);
var version = require('./grunt/tasks/version.js');
var standaloneBuilder = require('./grunt/tasks/build_standalone.js');
grunt.registerTask('build:copyVersionToGem',
"Propagates the version from package.json to version.rb",
version.copyToGem);
grunt.registerTask('buildDistribution',
'Builds and lints jasmine.js, jasmine-html.js, jasmine.css',
[
'compass',
'jshint:beforeConcat',
'concat',
'jshint:afterConcat',
'build:copyVersionToGem'
]
);
var spec = require('./grunt/tasks/spec.js');
grunt.registerTask("execSpecsInNode",
"Run Jasmine core specs in Node.js",
spec.execSpecsInNode
);
};

View File

@@ -1,4 +1,5 @@
<a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a>
<a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a> [![Build Status](https://travis-ci.org/pivotal/jasmine.png?branch=master)](https://travis-ci.org/pivotal/jasmine)
=======
**A JavaScript Testing Framework**
@@ -6,26 +7,21 @@ Jasmine is a Behavior Driven Development testing framework for JavaScript. It do
Documentation & guides live here: [http://pivotal.github.com/jasmine/](http://pivotal.github.com/jasmine/)
## What's Here?
*
## Contributing
Please read the [contributors' guide](https://github.com/pivotal/jasmine/blob/master/Contribute.markdown)
## Support
* 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)
* Check the current build status: [ci.pivotallabs.com](http://ci.pivotallabs.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:antixian666@gmail.com), Square
Copyright (c) 2008-2011 Pivotal Labs. This software is licensed under the MIT License.
Copyright (c) 2008-2013 Pivotal Labs. This software is licensed under the MIT License.

View File

@@ -1,33 +1,39 @@
require "bundler"
Bundler::GemHelper.install_tasks
require "term/ansicolor"
require "json"
require "tilt"
require "jasmine"
Dir["#{File.dirname(__FILE__)}/tasks/**/*.rb"].each do |file|
require file
end
task :default => :spec
task :require_pages_submodule do
raise "Submodule for Github Pages isn't present. Run git submodule update --init" unless pages_submodule_present
# TODO: Is there better way to invoke this using Jasmine gem???
task :core_spec do
exec "ruby spec/jasmine_self_test_spec.rb"
end
task :require_node do
raise "\nNode.js is required to develop code for Jasmine. Please visit http://nodejs.org to install.\n\n" unless node_installed?
namespace :jasmine do
task :server do
port = ENV['JASMINE_PORT'] || 8888
jasmine_yml = ENV['JASMINE_YML'] || 'jasmine.yml'
Jasmine.load_configuration_from_yaml(File.join(Dir.pwd, 'spec', jasmine_yml))
config = Jasmine.config
server = Jasmine::Server.new(port, Jasmine::Application.app(config))
server.start
puts "your tests are here:"
puts " http://localhost:#{port}/"
end
desc "Copy examples from Jasmine JS to the gem"
task :copy_examples_to_gem do
require "fileutils"
# copy jasmine's example tree into our generator templates dir
FileUtils.rm_r('generators/jasmine/templates/jasmine-example', :force => true)
FileUtils.cp_r(File.join(Jasmine::Core.path, 'example'), 'generators/jasmine/templates/jasmine-example', :preserve => true)
end
end
def pages_submodule_present
File.exist?('pages/download.html')
end
def node_installed?
`which node` =~ /node/
end
class String
include Term::ANSIColor
end
Term::ANSIColor.coloring = STDOUT.isatty
desc "Run specs via server"
task :jasmine => ['jasmine:server']

View File

@@ -5,36 +5,43 @@ ___Jasmine Core Maintainers Only___
Follow the instructions in `Contribute.markdown` during development.
### Git Commits
### Git Rules
Please work on feature branches.
Please attempt to keep commits to `master` small, but cohesive. If a feature is contained in a bunch of small commits (e.g., it has several wip commits or small work), please squash them when merging back to `master`.
### Version
We attempt to stick to [Semantic Versioning](). Most of the time, development should be against a new minor version - fixing bugs and adding new features that are backwards compatible.
We attempt to stick to [Semantic Versioning](http://semver.org/). Most of the time, development should be against a new minor version - fixing bugs and adding new features that are backwards compatible.
The current version lives in the file `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.
The current version lives in the file `/package.json`. This file should be set to the version that is _currently_ under development. That is, if version 1.0.0 is the current release then version should be incremented say, to 1.1.0.
This version is used by both `jasmine.js` and the `jasmine-core` Ruby gem.
Note that Jasmine should *not* use the "patch" version number. Let downstream projects rev their patch versions as needed, keeping their major and minor version numbers in sync with Jasmine core.
### Update the Github Pages (as needed)
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.
___Note: This is going to change right after 2.0___
Github pages have to exist in a branch called `gh-pages` in order for their app to serve them. This repo adds that branch as a submodule under the `pages` directory. This is a bit of a hack, but it allows us to work with the pages and the source at the same time and with one set of rake tasks.
If you want to submit changes to this repo and aren't a Pivotal Labs employee, you can fork and work in the `gh-pages` branch. You won't be able to edit the pages in the submodule off of master.
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 an `rc` property with a value of 1
1. Update any comments on the public interfaces
1. `rake doc` - builds the `jsdoc` pages
1. Update the version in `package.json` to a release candidate
1. Update any links or top-level landing page for the Github Pages
1. `rake standalone` - builds the standalone distribution ZIP file
1. `rake build_pages` - builds the Github Pages
1. `rake release` - tags the repo with the version, builds the `jasmine-core` gem, pushes the gem to Rubygems.org
1. Build the standalone distribution with `grunt buildStandaloneDist`
1. Make sure you add the new ZIP file to git
1. Copy version to the Ruby gem with `grunt build:copyVersionToGem`
1. __NOTE__: You will likely need to point to a local jasmine gem in order to run tests locally. _Do not_ push this version of the Gemfile.
1. __NOTE__: You will likely need to push a new jasmine gem with a dependent version right after this release.
1. Push these changes to GitHub and verify that this SHA is green
1. `rake release` - tags the repo with the version, builds the `jasmine-core` gem, pushes the gem to Rubygems.org. In order to release you will have to ensure you have rubygems creds locally.
There should be a post to Pivotal Labs blog and a tweet to that link.

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

Binary file not shown.

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

Binary file not shown.

10
grunt/config/compass.js Normal file
View File

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

57
grunt/config/compress.js Normal file
View File

@@ -0,0 +1,57 @@
var standaloneLibDir = "lib/jasmine-" + jasmineVersion;
function root(path) { return "./" + path; }
function lib(path) { return root("lib/jasmine-core/" + path); }
function dist(path) { return root("dist/" + path); }
module.exports = {
standalone: {
options: {
archive: root("dist/jasmine-standalone-" + global.jasmineVersion + ".zip")
},
files: [
{ src: [ root("MIT.LICENSE") ] },
{
src: [ "jasmine_favicon.png"],
dest: standaloneLibDir,
expand: true,
cwd: root("images")
},
{
src: [
"jasmine.js",
"jasmine-html.js",
"jasmine.css"
],
dest: standaloneLibDir,
expand: true,
cwd: lib("")
},
{
src: [ "boot.js" ],
dest: standaloneLibDir,
expand: true,
cwd: lib("boot")
},
{
src: [ "SpecRunner.html" ],
dest: root(""),
expand: true,
cwd: dist("tmp")
},
{
src: [ "*.js" ],
dest: "src",
expand: true,
cwd: lib("example/src/")
},
{
src: [ "*.js" ],
dest: "spec",
expand: true,
cwd: lib("example/spec/")
}
]
}
};

57
grunt/config/concat.js Normal file
View File

@@ -0,0 +1,57 @@
var grunt = require('grunt');
function license() {
var currentYear = "" + new Date(Date.now()).getFullYear();
return grunt.template.process(
grunt.file.read("grunt/templates/licenseBanner.js.jst"),
{ data: { currentYear: currentYear}});
}
module.exports = {
'jasmine-html': {
src: [
'src/html/requireHtml.js',
'src/html/HtmlReporter.js',
'src/html/HtmlSpecFilter.js',
'src/html/ResultsNode.js',
'src/html/QueryString.js'
],
dest: 'lib/jasmine-core/jasmine-html.js'
},
jasmine: {
src: [
'src/core/requireCore.js',
'src/core/matchers/requireMatchers.js',
'src/core/base.js',
'src/core/util.js',
'src/core/Spec.js',
'src/core/Env.js',
'src/core/JsApiReporter.js',
'src/core/PrettyPrinter',
'src/core/Suite',
'src/core/**/*.js',
'src/version.js'
],
dest: 'lib/jasmine-core/jasmine.js'
},
boot: {
src: ['lib/jasmine-core/boot/boot.js'],
dest: 'lib/jasmine-core/boot.js'
},
console: {
src: [
'src/console/requireConsole.js',
'src/console/ConsoleReporter.js'
],
dest: 'src/console/console.js'
},
options: {
banner: license(),
process: {
data: {
version: global.jasmineVersion
}
}
}
};

17
grunt/config/jshint.js Normal file
View File

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

View File

@@ -0,0 +1,30 @@
var grunt = require("grunt");
function standaloneTmpDir(path) { return "dist/tmp/" + path; }
grunt.registerTask("build:compileSpecRunner",
"Processes the spec runner template and writes to a tmp file",
function() {
var runnerHtml = grunt.template.process(
grunt.file.read("grunt/templates/SpecRunner.html.jst"),
{ data: { jasmineVersion: global.jasmineVersion }});
grunt.file.write(standaloneTmpDir("SpecRunner.html"), runnerHtml);
}
);
grunt.registerTask("build:cleanSpecRunner",
"Deletes the tmp spec runner file",
function() {
grunt.file.delete(standaloneTmpDir(""));
}
);
grunt.registerTask("buildStandaloneDist",
"Builds a standalone distribution",
[
"build:compileSpecRunner",
"compress:standalone",
"build:cleanSpecRunner"
]
);

11
grunt/tasks/spec.js Normal file
View File

@@ -0,0 +1,11 @@
var shell = require('shelljs');
var grunt = require('grunt');
module.exports = {
execSpecsInNode: function() {
var exit_code = shell.exec("node spec/node_suite.js --color=true").code;
if (exit_code !== 0) {
grunt.fail.fatal("Specs Failed", exit_code);
}
}
};

14
grunt/tasks/version.js Normal file
View File

@@ -0,0 +1,14 @@
var grunt = require("grunt");
function gemLib(path) { return './lib/jasmine-core/' + path; }
function nodeToRuby(version) { return version.replace('-', '.'); }
module.exports = {
copyToGem: function() {
var versionRb = grunt.template.process(
grunt.file.read("grunt/templates/version.rb.jst"),
{ data: { jasmineVersion: nodeToRuby(global.jasmineVersion) }});
grunt.file.write(gemLib("version.rb"), versionRb);
}
};

View File

@@ -0,0 +1,26 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Jasmine Spec Runner v<%= jasmineVersion %></title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-<%= jasmineVersion %>/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine-<%= jasmineVersion %>/jasmine.css">
<script type="text/javascript" src="lib/jasmine-<%= jasmineVersion %>/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-<%= jasmineVersion %>/jasmine-html.js"></script>
<script type="text/javascript" src="lib/jasmine-<%= jasmineVersion %>/boot.js"></script>
<!-- include source files here... -->
<script type="text/javascript" src="src/Player.js"></script>
<script type="text/javascript" src="src/Song.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="spec/SpecHelper.js"></script>
<script type="text/javascript" src="spec/PlayerSpec.js"></script>
</head>
<body>
</body>
</html>

View File

@@ -0,0 +1,22 @@
/*
Copyright (c) 2008-<%= currentYear %> Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

View File

@@ -0,0 +1,9 @@
#
# DO NOT Edit this file. Canonical version of Jasmine lives in the repo's package.json. This file is generated
# by a grunt task when the standalone release is built.
#
module Jasmine
module Core
VERSION = "<%= jasmineVersion %>"
end
end

View File

@@ -6,17 +6,22 @@ Gem::Specification.new do |s|
s.name = "jasmine-core"
s.version = Jasmine::Core::VERSION
s.platform = Gem::Platform::RUBY
s.authors = ["Rajan Agaskar", "Davis Frank", "Christian Williams"]
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 "term-ansicolor"
s.add_development_dependency "json_pure", ">= 1.4.3"
s.add_development_dependency "frank"
s.add_development_dependency "ragaskar-jsdoc_helper"
s.add_development_dependency "sass"
s.add_development_dependency "compass"
s.add_development_dependency "rspec"
s.add_development_dependency "fuubar"
s.add_development_dependency "awesome_print"
s.add_development_dependency "nokogiri"
s.add_development_dependency "sauce-connect"
end

View File

@@ -1,17 +0,0 @@
<div align="center">{+new Link().toFile("index.html").withText("Class Index")+}
| {+new Link().toFile("files.html").withText("File Index")+}</div>
<hr />
<h2>Classes</h2>
<ul class="classList">
<for each="thisClass" in="data">
<li>{!
if (thisClass.alias == "_global_") {
output += "<i>"+new Link().toClass(thisClass.alias)+"</i>";
}
else {
output += new Link().toClass(thisClass.alias);
}
!}</li>
</for>
</ul>
<hr />

View File

@@ -1,56 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset={+IO.encoding+}"" />
{! Link.base = ""; /* all generated links will be relative to this */ !}
<title>JsDoc Reference - File Index</title>
<meta name="generator" content="JsDoc Toolkit" />
<style type="text/css">
{+include("static/default.css")+}
</style>
</head>
<body>
{+include("static/header.html")+}
<div id="index">
{+publish.classesIndex+}
</div>
<div id="content">
<h1 class="classTitle">File Index</h1>
<for each="item" in="data">
<div>
<h2>{+new Link().toSrc(item.alias).withText(item.name)+}</h2>
<if test="item.desc">{+resolveLinks(summarize(item.desc))+}</if>
<dl>
<if test="item.author">
<dt class="heading">Author:</dt>
<dd>{+item.author+}</dd>
</if>
<if test="item.version">
<dt class="heading">Version:</dt>
<dd>{+item.version+}</dd>
</if>
{! var locations = item.comment.getTag('location').map(function($){return $.toString().replace(/(^\$ ?| ?\$$)/g, '').replace(/^HeadURL: https:/g, 'http:');}) !}
<if test="locations.length">
<dt class="heading">Location:</dt>
<for each="location" in="locations">
<dd><a href="{+location+}">{+location+}</a></dd>
</for>
</if>
</dl>
</div>
<hr />
</for>
</div>
<div class="fineprint" style="clear:both">
<if test="JSDOC.opt.D.copyright">&copy;{+JSDOC.opt.D.copyright+}<br /></if>
Documentation generated by <a href="http://www.jsdoctoolkit.org/" target="_blankt">JsDoc Toolkit</a> {+JSDOC.VERSION+} on {+new Date()+}
</div>
</body>
</html>

View File

@@ -1,646 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset={+IO.encoding+}" />
<meta name="generator" content="JsDoc Toolkit" />
{! Link.base = "../"; /* all generated links will be relative to this */ !}
<title>JsDoc Reference - {+data.alias+}</title>
<style type="text/css">
{+include("static/default.css")+}
</style>
</head>
<body>
<!-- ============================== header ================================= -->
<!-- begin static/header.html -->
{+include("static/header.html")+}
<!-- end static/header.html -->
<!-- ============================== classes index ============================ -->
<div id="index">
<!-- begin publish.classesIndex -->
{+publish.classesIndex+}
<!-- end publish.classesIndex -->
</div>
<div id="content">
<!-- ============================== class title ============================ -->
<h1 class="classTitle">
{!
var classType = "";
if (data.isBuiltin()) {
classType += "Built-In ";
}
if (data.isNamespace) {
if (data.is('FUNCTION')) {
classType += "Function ";
}
classType += "Namespace ";
}
else {
classType += "Class ";
}
!}
{+classType+}{+data.alias+}
</h1>
<!-- ============================== class summary ========================== -->
<p class="description">
<if test="data.augments.length"><br />Extends
{+
data.augments
.sort()
.map(
function($) { return new Link().toSymbol($); }
)
.join(", ")
+}.<br />
</if>
{+resolveLinks(data.classDesc)+}
<if test="!data.isBuiltin()">{# isn't defined in any file #}
<br /><i>Defined in: </i> {+new Link().toSrc(data.srcFile)+}.
</if>
</p>
<!-- ============================== constructor summary ==================== -->
<if test="!data.isBuiltin() && (data.isNamespace || data.is('CONSTRUCTOR'))">
<table class="summaryTable" cellspacing="0" summary="A summary of the constructor documented in the class {+data.alias+}.">
<caption>{+classType+}Summary</caption>
<thead>
<tr>
<th scope="col">Constructor Attributes</th>
<th scope="col">Constructor Name and Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="attributes">{!
if (data.isPrivate) output += "&lt;private&gt; ";
if (data.isInner) output += "&lt;inner&gt; ";
!}&nbsp;</td>
<td class="nameDescription" {!if (data.comment.getTag("hilited").length){output += 'style="color: red"'}!}>
<div class="fixedFont">
<b>{+ new Link().toSymbol(data.alias).inner('constructor')+}</b><if test="classType != 'Namespace '">{+ makeSignature(data.params) +}</if>
</div>
<div class="description">{+resolveLinks(summarize(data.desc))+}</div>
</td>
</tr>
</tbody>
</table>
</if>
<!-- ============================== properties summary ===================== -->
<if test="data.properties.length">
{! var ownProperties = data.properties.filter(function($){return $.memberOf == data.alias && !$.isNamespace}).sort(makeSortby("name")); !}
<if test="ownProperties.length">
<table class="summaryTable" cellspacing="0" summary="A summary of the fields documented in the class {+data.alias+}.">
<caption>Field Summary</caption>
<thead>
<tr>
<th scope="col">Field Attributes</th>
<th scope="col">Field Name and Description</th>
</tr>
</thead>
<tbody>
<for each="member" in="ownProperties">
<tr>
<td class="attributes">{!
if (member.isPrivate) output += "&lt;private&gt; ";
if (member.isInner) output += "&lt;inner&gt; ";
if (member.isStatic) output += "&lt;static&gt; ";
if (member.isConstant) output += "&lt;constant&gt; ";
!}&nbsp;</td>
<td class="nameDescription">
<div class="fixedFont">
<if test="member.isStatic && member.memberOf != '_global_'">{+member.memberOf+}.</if><b>{+new Link().toSymbol(member.alias).withText(member.name)+}</b>
</div>
<div class="description">{+resolveLinks(summarize(member.desc))+}</div>
</td>
</tr>
</for>
</tbody>
</table>
</if>
<if test="data.inheritsFrom.length">
<dl class="inheritsList">
{!
var borrowedMembers = data.properties.filter(function($) {return $.memberOf != data.alias});
var contributers = [];
borrowedMembers.map(function($) {if (contributers.indexOf($.memberOf) < 0) contributers.push($.memberOf)});
for (var i = 0, l = contributers.length; i < l; i++) {
output +=
"<dt>Fields borrowed from class "+new Link().toSymbol(contributers[i])+": </dt>"
+
"<dd>" +
borrowedMembers
.filter(
function($) { return $.memberOf == contributers[i] }
)
.sort(makeSortby("name"))
.map(
function($) { return new Link().toSymbol($.alias).withText($.name) }
)
.join(", ")
+
"</dd>";
}
!}
</dl>
</if>
</if>
<!-- ============================== methods summary ======================== -->
<if test="data.methods.length">
{! var ownMethods = data.methods.filter(function($){return $.memberOf == data.alias && !$.isNamespace}).sort(makeSortby("name")); !}
<if test="ownMethods.length">
<table class="summaryTable" cellspacing="0" summary="A summary of the methods documented in the class {+data.alias+}.">
<caption>Method Summary</caption>
<thead>
<tr>
<th scope="col">Method Attributes</th>
<th scope="col">Method Name and Description</th>
</tr>
</thead>
<tbody>
<for each="member" in="ownMethods">
<tr>
<td class="attributes">{!
if (member.isPrivate) output += "&lt;private&gt; ";
if (member.isInner) output += "&lt;inner&gt; ";
if (member.isStatic) output += "&lt;static&gt; ";
!}&nbsp;</td>
<td class="nameDescription">
<div class="fixedFont"><if test="member.isStatic && member.memberOf != '_global_'">{+member.memberOf+}.</if><b>{+new Link().toSymbol(member.alias).withText(member.name)+}</b>{+makeSignature(member.params)+}
</div>
<div class="description">{+resolveLinks(summarize(member.desc))+}</div>
</td>
</tr>
</for>
</tbody>
</table>
</if>
<if test="data.inheritsFrom.length">
<dl class="inheritsList">
{!
var borrowedMembers = data.methods.filter(function($) {return $.memberOf != data.alias});
var contributers = [];
borrowedMembers.map(function($) {if (contributers.indexOf($.memberOf) < 0) contributers.push($.memberOf)});
for (var i = 0, l = contributers.length; i < l; i++) {
output +=
"<dt>Methods borrowed from class "+new Link().toSymbol(contributers[i])+": </dt>"
+
"<dd>" +
borrowedMembers
.filter(
function($) { return $.memberOf == contributers[i] }
)
.sort(makeSortby("name"))
.map(
function($) { return new Link().toSymbol($.alias).withText($.name) }
)
.join(", ")
+
"</dd>";
}
!}
</dl>
</if>
</if>
<!-- ============================== events summary ======================== -->
<if test="data.events.length">
{! var ownEvents = data.events.filter(function($){return $.memberOf == data.alias && !$.isNamespace}).sort(makeSortby("name")); !}
<if test="ownEvents.length">
<table class="summaryTable" cellspacing="0" summary="A summary of the events documented in the class {+data.alias+}.">
<caption>Event Summary</caption>
<thead>
<tr>
<th scope="col">Event Attributes</th>
<th scope="col">Event Name and Description</th>
</tr>
</thead>
<tbody>
<for each="member" in="ownEvents">
<tr>
<td class="attributes">{!
if (member.isPrivate) output += "&lt;private&gt; ";
if (member.isInner) output += "&lt;inner&gt; ";
if (member.isStatic) output += "&lt;static&gt; ";
!}&nbsp;</td>
<td class="nameDescription">
<div class="fixedFont"><if test="member.isStatic && member.memberOf != '_global_'">{+member.memberOf+}.</if><b>{+new Link().toSymbol(member.alias).withText(member.name)+}</b>{+makeSignature(member.params)+}
</div>
<div class="description">{+resolveLinks(summarize(member.desc))+}</div>
</td>
</tr>
</for>
</tbody>
</table>
</if>
<if test="data.inheritsFrom.length">
<dl class="inheritsList">
{!
var borrowedMembers = data.events.filter(function($) {return $.memberOf != data.alias});
var contributers = [];
borrowedMembers.map(function($) {if (contributers.indexOf($.memberOf) < 0) contributers.push($.memberOf)});
for (var i = 0, l = contributers.length; i < l; i++) {
output +=
"<dt>Events borrowed from class "+new Link().toSymbol(contributers[i])+": </dt>"
+
"<dd>" +
borrowedMembers
.filter(
function($) { return $.memberOf == contributers[i] }
)
.sort(makeSortby("name"))
.map(
function($) { return new Link().toSymbol($.alias).withText($.name) }
)
.join(", ")
+
"</dd>";
}
!}
</dl>
</if>
</if>
<!-- ============================== constructor details ==================== -->
<if test="!data.isBuiltin() && (data.isNamespace || data.is('CONSTRUCTOR'))">
<div class="details"><a name="constructor"> </a>
<div class="sectionTitle">
{+classType+}Detail
</div>
<div class="fixedFont">{!
if (data.isPrivate) output += "&lt;private&gt; ";
if (data.isInner) output += "&lt;inner&gt; ";
!}
<b>{+ data.alias +}</b><if test="classType != 'Namespace '">{+ makeSignature(data.params) +}</if>
</div>
<div class="description">
{+resolveLinks(data.desc)+}
<if test="data.author"><br /><i>Author: </i>{+data.author+}.</if>
</div>
<if test="data.example.length">
<for each="example" in="data.example">
<pre class="code">{+example+}</pre>
</for>
</if>
<if test="data.params.length">
<dl class="detailList">
<dt class="heading">Parameters:</dt>
<for each="item" in="data.params">
<dt>
{+((item.type)?""+("<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type)+"}</span> ")) : "")+} <b>{+item.name+}</b>
<if test="item.isOptional"><i>Optional<if test="item.defaultValue">, Default: {+item.defaultValue+}</if></i></if>
</dt>
<dd>{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="data.deprecated">
<dl class="detailList">
<dt class="heading">Deprecated:</dt>
<dt>
{+resolveLinks(data.deprecated)+}
</dt>
</dl>
</if>
<if test="data.since">
<dl class="detailList">
<dt class="heading">Since:</dt>
<dd>{+ data.since +}</dd>
</dl>
</if>
<if test="data.exceptions.length">
<dl class="detailList">
<dt class="heading">Throws:</dt>
<for each="item" in="data.exceptions">
<dt>
{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+} <b>{+item.name+}</b>
</dt>
<dd>{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="data.returns.length">
<dl class="detailList">
<dt class="heading">Returns:</dt>
<for each="item" in="data.returns">
<dd>{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+}{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="data.requires.length">
<dl class="detailList">
<dt class="heading">Requires:</dt>
<for each="item" in="data.requires">
<dd>{+ resolveLinks(item) +}</dd>
</for>
</dl>
</if>
<if test="data.see.length">
<dl class="detailList">
<dt class="heading">See:</dt>
<for each="item" in="data.see">
<dd>{+ new Link().toSymbol(item) +}</dd>
</for>
</dl>
</if>
</div>
</if>
<!-- ============================== field details ========================== -->
<if test="defined(ownProperties) && ownProperties.length">
<div class="sectionTitle">
Field Detail
</div>
<for each="member" in="ownProperties">
<a name="{+Link.symbolNameToLinkName(member)+}"> </a>
<div class="fixedFont">{!
if (member.isPrivate) output += "&lt;private&gt; ";
if (member.isInner) output += "&lt;inner&gt; ";
if (member.isStatic) output += "&lt;static&gt; ";
if (member.isConstant) output += "&lt;constant&gt; ";
!}
<if test="member.type"><span class="light">{{+new Link().toSymbol(member.type)+}}</span></if>
<if test="member.isStatic && member.memberOf != '_global_'"><span class="light">{+member.memberOf+}.</span></if><b>{+member.name+}</b>
</div>
<div class="description">
{+resolveLinks(member.desc)+}
<if test="member.srcFile != data.srcFile">
<br />
<i>Defined in: </i> {+new Link().toSrc(member.srcFile)+}.
</if>
<if test="member.author"><br /><i>Author: </i>{+member.author+}.</if>
</div>
<if test="member.example.length">
<for each="example" in="member.example">
<pre class="code">{+example+}</pre>
</for>
</if>
<if test="member.deprecated">
<dl class="detailList">
<dt class="heading">Deprecated:</dt>
<dt>
{+ member.deprecated +}
</dt>
</dl>
</if>
<if test="member.since">
<dl class="detailList">
<dt class="heading">Since:</dt>
<dd>{+ member.since +}</dd>
</dl>
</if>
<if test="member.see.length">
<dl class="detailList">
<dt class="heading">See:</dt>
<for each="item" in="member.see">
<dd>{+ new Link().toSymbol(item) +}</dd>
</for>
</dl>
</if>
<if test="member.defaultValue">
<dl class="detailList">
<dt class="heading">Default Value:</dt>
<dd>
{+resolveLinks(member.defaultValue)+}
</dd>
</dl>
</if>
<if test="!$member_last"><hr /></if>
</for>
</if>
<!-- ============================== method details ========================= -->
<if test="defined(ownMethods) && ownMethods.length">
<div class="sectionTitle">
Method Detail
</div>
<for each="member" in="ownMethods">
<a name="{+Link.symbolNameToLinkName(member)+}"> </a>
<div class="fixedFont">{!
if (member.isPrivate) output += "&lt;private&gt; ";
if (member.isInner) output += "&lt;inner&gt; ";
if (member.isStatic) output += "&lt;static&gt; ";
!}
<if test="member.type"><span class="light">{{+new Link().toSymbol(member.type)+}}</span></if>
<if test="member.isStatic && member.memberOf != '_global_'"><span class="light">{+member.memberOf+}.</span></if><b>{+member.name+}</b>{+makeSignature(member.params)+}
</div>
<div class="description">
{+resolveLinks(member.desc)+}
<if test="member.srcFile != data.srcFile">
<br />
<i>Defined in: </i> {+new Link().toSrc(member.srcFile)+}.
</if>
<if test="member.author"><br /><i>Author: </i>{+member.author+}.</if>
</div>
<if test="member.example.length">
<for each="example" in="member.example">
<pre class="code">{+example+}</pre>
</for>
</if>
<if test="member.params.length">
<dl class="detailList">
<dt class="heading">Parameters:</dt>
<for each="item" in="member.params">
<dt>
{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+}<b>{+item.name+}</b>
<if test="item.isOptional"><i>Optional<if test="item.defaultValue">, Default: {+item.defaultValue+}</if></i></if>
</dt>
<dd>{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="member.deprecated">
<dl class="detailList">
<dt class="heading">Deprecated:</dt>
<dt>
{+member.deprecated+}
</dt>
</dl>
</if>
<if test="member.since">
<dl class="detailList">
<dt class="heading">Since:</dt>
<dd>{+ member.since +}</dd>
</dl>
</dl>
</if>
<if test="member.exceptions.length">
<dl class="detailList">
<dt class="heading">Throws:</dt>
<for each="item" in="member.exceptions">
<dt>
{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+} <b>{+item.name+}</b>
</dt>
<dd>{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="member.returns.length">
<dl class="detailList">
<dt class="heading">Returns:</dt>
<for each="item" in="member.returns">
<dd>{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+}{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="member.requires.length">
<dl class="detailList">
<dt class="heading">Requires:</dt>
<for each="item" in="member.requires">
<dd>{+ resolveLinks(item) +}</dd>
</for>
</dl>
</if>
<if test="member.see.length">
<dl class="detailList">
<dt class="heading">See:</dt>
<for each="item" in="member.see">
<dd>{+ new Link().toSymbol(item) +}</dd>
</for>
</dl>
</if>
<if test="!$member_last"><hr /></if>
</for>
</if>
<!-- ============================== event details ========================= -->
<if test="defined(ownEvents) && ownEvents.length">
<div class="sectionTitle">
Event Detail
</div>
<for each="member" in="ownEvents">
<a name="event:{+Link.symbolNameToLinkName(member)+}"> </a>
<div class="fixedFont">{!
if (member.isPrivate) output += "&lt;private&gt; ";
if (member.isInner) output += "&lt;inner&gt; ";
if (member.isStatic) output += "&lt;static&gt; ";
!}
<if test="member.type"><span class="light">{{+new Link().toSymbol(member.type)+}}</span></if>
<if test="member.isStatic && member.memberOf != '_global_'"><span class="light">{+member.memberOf+}.</span></if><b>{+member.name+}</b>{+makeSignature(member.params)+}
</div>
<div class="description">
{+resolveLinks(member.desc)+}
<if test="member.srcFile != data.srcFile">
<br />
<i>Defined in: </i> {+new Link().toSrc(member.srcFile)+}.
</if>
<if test="member.author"><br /><i>Author: </i>{+member.author+}.</if>
</div>
<if test="member.example.length">
<for each="example" in="member.example">
<pre class="code">{+example+}</pre>
</for>
</if>
<if test="member.params.length">
<dl class="detailList">
<dt class="heading">Parameters:</dt>
<for each="item" in="member.params">
<dt>
{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+}<b>{+item.name+}</b>
<if test="item.isOptional"><i>Optional<if test="item.defaultValue">, Default: {+item.defaultValue+}</if></i></if>
</dt>
<dd>{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="member.deprecated">
<dl class="detailList">
<dt class="heading">Deprecated:</dt>
<dt>
{+member.deprecated+}
</dt>
</dl>
</if>
<if test="member.since">
<dl class="detailList">
<dt class="heading">Since:</dt>
<dd>{+ member.since +}</dd>
</dl>
</dl>
</if>
<if test="member.exceptions.length">
<dl class="detailList">
<dt class="heading">Throws:</dt>
<for each="item" in="member.exceptions">
<dt>
{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+} <b>{+item.name+}</b>
</dt>
<dd>{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="member.returns.length">
<dl class="detailList">
<dt class="heading">Returns:</dt>
<for each="item" in="member.returns">
<dd>{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+}{+resolveLinks(item.desc)+}</dd>
</for>
</dl>
</if>
<if test="member.requires.length">
<dl class="detailList">
<dt class="heading">Requires:</dt>
<for each="item" in="member.requires">
<dd>{+ resolveLinks(item) +}</dd>
</for>
</dl>
</if>
<if test="member.see.length">
<dl class="detailList">
<dt class="heading">See:</dt>
<for each="item" in="member.see">
<dd>{+ new Link().toSymbol(item) +}</dd>
</for>
</dl>
</if>
<if test="!$member_last"><hr /></if>
</for>
</if>
<hr />
</div>
<!-- ============================== footer ================================= -->
<div class="fineprint" style="clear:both">
<if test="JSDOC.opt.D.copyright">&copy;{+JSDOC.opt.D.copyright+}<br /></if>
Documentation generated by <a href="http://www.jsdoctoolkit.org/" target="_blank">JsDoc Toolkit</a> {+JSDOC.VERSION+} on {+new Date()+}
</div>
</body>
</html>

View File

@@ -1,39 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset={+IO.encoding+}"" />
<title>JsDoc Reference - Index</title>
<meta name="generator" content="JsDoc Toolkit" />
<style type="text/css">
{+include("static/default.css")+}
</style>
</head>
<body>
{+include("static/header.html")+}
<div id="index">
{+publish.classesIndex+}
</div>
<div id="content">
<h1 class="classTitle">Class Index</h1>
<for each="thisClass" in="data">
<div>
<h2>{+(new Link().toSymbol(thisClass.alias))+}</h2>
{+resolveLinks(summarize(thisClass.classDesc))+}
</div>
<hr />
</for>
</div>
<div class="fineprint" style="clear:both">
<if test="JSDOC.opt.D.copyright">&copy;{+JSDOC.opt.D.copyright+}<br /></if>
Documentation generated by <a href="http://www.jsdoctoolkit.org/" target="_blankt">JsDoc Toolkit</a> {+JSDOC.VERSION+} on {+new Date()+}
</div>
</body>
</html>

View File

@@ -1,184 +0,0 @@
/** Called automatically by JsDoc Toolkit. */
function publish(symbolSet) {
publish.conf = { // trailing slash expected for dirs
ext: ".html",
outDir: JSDOC.opt.d || SYS.pwd+"../out/jsdoc/",
templatesDir: JSDOC.opt.t || SYS.pwd+"../templates/jsdoc/",
symbolsDir: "symbols/",
srcDir: "symbols/src/"
};
// is source output is suppressed, just display the links to the source file
if (JSDOC.opt.s && defined(Link) && Link.prototype._makeSrcLink) {
Link.prototype._makeSrcLink = function(srcFilePath) {
return "&lt;"+srcFilePath+"&gt;";
}
}
// create the folders and subfolders to hold the output
IO.mkPath((publish.conf.outDir+"symbols/src").split("/"));
// used to allow Link to check the details of things being linked to
Link.symbolSet = symbolSet;
// create the required templates
try {
var classTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"class.tmpl");
var classesTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allclasses.tmpl");
}
catch(e) {
print("Couldn't create the required templates: "+e);
quit();
}
// some ustility filters
function hasNoParent($) {return ($.memberOf == "")}
function isaFile($) {return ($.is("FILE"))}
function isaClass($) {return ($.is("CONSTRUCTOR") || $.isNamespace)}
// get an array version of the symbolset, useful for filtering
var symbols = symbolSet.toArray();
// create the hilited source code files
var files = JSDOC.opt.srcFiles;
for (var i = 0, l = files.length; i < l; i++) {
var file = files[i];
var srcDir = publish.conf.outDir + "symbols/src/";
makeSrcFile(file, srcDir);
}
// get a list of all the classes in the symbolset
var classes = symbols.filter(isaClass).sort(makeSortby("alias"));
// create a class index, displayed in the left-hand column of every class page
Link.base = "../";
publish.classesIndex = classesTemplate.process(classes); // kept in memory
// create each of the class pages
for (var i = 0, l = classes.length; i < l; i++) {
var symbol = classes[i];
symbol.events = symbol.getEvents(); // 1 order matters
symbol.methods = symbol.getMethods(); // 2
var output = "";
output = classTemplate.process(symbol);
IO.saveFile(publish.conf.outDir+"symbols/", symbol.alias+publish.conf.ext, output);
}
// regenerate the index with different relative links, used in the index pages
Link.base = "";
publish.classesIndex = classesTemplate.process(classes);
// create the class index page
try {
var classesindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"index.tmpl");
}
catch(e) { print(e.message); quit(); }
var classesIndex = classesindexTemplate.process(classes);
IO.saveFile(publish.conf.outDir, "index"+publish.conf.ext, classesIndex);
classesindexTemplate = classesIndex = classes = null;
// create the file index page
try {
var fileindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allfiles.tmpl");
}
catch(e) { print(e.message); quit(); }
var documentedFiles = symbols.filter(isaFile); // files that have file-level docs
var allFiles = []; // not all files have file-level docs, but we need to list every one
for (var i = 0; i < files.length; i++) {
allFiles.push(new JSDOC.Symbol(files[i], [], "FILE", new JSDOC.DocComment("/** */")));
}
for (var i = 0; i < documentedFiles.length; i++) {
var offset = files.indexOf(documentedFiles[i].alias);
allFiles[offset] = documentedFiles[i];
}
allFiles = allFiles.sort(makeSortby("name"));
// output the file index page
var filesIndex = fileindexTemplate.process(allFiles);
IO.saveFile(publish.conf.outDir, "files"+publish.conf.ext, filesIndex);
fileindexTemplate = filesIndex = files = null;
}
/** Just the first sentence (up to a full stop). Should not break on dotted variable names. */
function summarize(desc) {
if (typeof desc != "undefined")
return desc.match(/([\w\W]+?\.)[^a-z0-9_$]/i)? RegExp.$1 : desc;
}
/** Make a symbol sorter by some attribute. */
function makeSortby(attribute) {
return function(a, b) {
if (a[attribute] != undefined && b[attribute] != undefined) {
a = a[attribute].toLowerCase();
b = b[attribute].toLowerCase();
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
}
}
/** Pull in the contents of an external file at the given path. */
function include(path) {
var path = publish.conf.templatesDir+path;
return IO.readFile(path);
}
/** Turn a raw source file into a code-hilited page in the docs. */
function makeSrcFile(path, srcDir, name) {
if (JSDOC.opt.s) return;
if (!name) {
name = path.replace(/\.\.?[\\\/]/g, "").replace(/[\\\/]/g, "_");
name = name.replace(/\:/g, "_");
}
var src = {path: path, name:name, charset: IO.encoding, hilited: ""};
if (defined(JSDOC.PluginManager)) {
JSDOC.PluginManager.run("onPublishSrc", src);
}
if (src.hilited) {
IO.saveFile(srcDir, name+publish.conf.ext, src.hilited);
}
}
/** Build output for displaying function parameters. */
function makeSignature(params) {
if (!params) return "()";
var signature = "("
+
params.filter(
function($) {
return $.name.indexOf(".") == -1; // don't show config params in signature
}
).map(
function($) {
return $.name;
}
).join(", ")
+
")";
return signature;
}
/** Find symbol {@link ...} strings in text and turn into html links */
function resolveLinks(str, from) {
str = str.replace(/\{@link ([^} ]+) ?\}/gi,
function(match, symbolName) {
return new Link().toSymbol(symbolName);
}
);
return str;
}

View File

@@ -1,162 +0,0 @@
/* default.css */
body
{
font: 12px "Lucida Grande", Tahoma, Arial, Helvetica, sans-serif;
width: 800px;
}
.header
{
clear: both;
background-color: #ccc;
padding: 8px;
}
h1
{
font-size: 150%;
font-weight: bold;
padding: 0;
margin: 1em 0 0 .3em;
}
hr
{
border: none 0;
border-top: 1px solid #7F8FB1;
height: 1px;
}
pre.code
{
display: block;
padding: 8px;
border: 1px dashed #ccc;
}
#index
{
margin-top: 24px;
float: left;
width: 160px;
position: absolute;
left: 8px;
background-color: #F3F3F3;
padding: 8px;
}
#content
{
margin-left: 190px;
width: 600px;
}
.classList
{
list-style-type: none;
padding: 0;
margin: 0 0 0 8px;
font-family: arial, sans-serif;
font-size: 1em;
overflow: auto;
}
.classList li
{
padding: 0;
margin: 0 0 8px 0;
}
.summaryTable { width: 100%; }
h1.classTitle
{
font-size:170%;
line-height:130%;
}
h2 { font-size: 110%; }
caption, div.sectionTitle
{
background-color: #7F8FB1;
color: #fff;
font-size:130%;
text-align: left;
padding: 2px 6px 2px 6px;
border: 1px #7F8FB1 solid;
}
div.sectionTitle { margin-bottom: 8px; }
.summaryTable thead { display: none; }
.summaryTable td
{
vertical-align: top;
padding: 4px;
border-bottom: 1px #7F8FB1 solid;
border-right: 1px #7F8FB1 solid;
}
/*col#summaryAttributes {}*/
.summaryTable td.attributes
{
border-left: 1px #7F8FB1 solid;
width: 140px;
text-align: right;
}
td.attributes, .fixedFont
{
line-height: 15px;
color: #002EBE;
font-family: "Courier New",Courier,monospace;
font-size: 13px;
}
.summaryTable td.nameDescription
{
text-align: left;
font-size: 13px;
line-height: 15px;
}
.summaryTable td.nameDescription, .description
{
line-height: 15px;
padding: 4px;
padding-left: 4px;
}
.summaryTable { margin-bottom: 8px; }
ul.inheritsList
{
list-style: square;
margin-left: 20px;
padding-left: 0;
}
.detailList {
margin-left: 20px;
line-height: 15px;
}
.detailList dt { margin-left: 20px; }
.detailList .heading
{
font-weight: bold;
padding-bottom: 6px;
margin-left: 0;
}
.light, td.attributes, .light a:link, .light a:visited
{
color: #777;
font-style: italic;
}
.fineprint
{
text-align: right;
font-size: 10px;
}

View File

@@ -1,2 +0,0 @@
<div id="header">
</div>

View File

@@ -1,19 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Generated Javascript Documentation</title>
</head>
<frameset cols="20%,80%">
<frame src="allclasses-frame.html" name="packageFrame" />
<frame src="splash.html" name="classFrame" />
<noframes>
<body>
<p>
This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
</p>
</body>
</noframes>
</frameset>
</html>

View File

@@ -1,35 +0,0 @@
<symbol alias="{+data.alias+}">
<name>{+data.name+}</name>
<memberOf>{+data.memberOf+}</memberOf>
<isStatic>{+data.isStatic+}</isStatic>
<isa>{+data.isa+}</isa>
<desc>{+data.desc+}</desc>
<classDesc>{+data.classDesc+}</classDesc>
<methods><for each="method" in="data.methods">
<method>
<name>{+method.name+}</name>
<memberOf>{+method.memberOf+}</memberOf>
<isStatic>{+method.isStatic+}</isStatic>
<desc>{+method.desc+}</desc>
<params><for each="param" in="method.params">
<param>
<type>{+param.type+}</type>
<name>{+param.name+}</name>
<desc>{+param.desc+}</desc>
<defaultValue>{+param.defaultValue+}</defaultValue>
</param></for>
</params>
</method></for>
</methods>
<properties><for each="property" in="data.properties">
<property>
<name>{+property.name+}</name>
<memberOf>{+property.memberOf+}</memberOf>
<isStatic>{+property.isStatic+}</isStatic>
<desc>{+property.desc+}</desc>
<type>{+property.type+}</type>
</property></for>
</properties>
</symbol>

File diff suppressed because it is too large Load Diff

View File

@@ -1,99 +0,0 @@
var fs = require("fs");
var sys = require("sys");
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);
})();

View File

@@ -6,7 +6,7 @@ module Jasmine
end
def js_files
(["jasmine.js"] + Dir.glob(File.join(path, "*.js"))).map { |f| File.basename(f) }.uniq
(["jasmine.js"] + Dir.glob(File.join(path, "*.js"))).map { |f| File.basename(f) }.uniq - boot_files
end
SPEC_TYPES = ["core", "html", "node"]
@@ -23,6 +23,14 @@ module Jasmine
spec_files("node")
end
def boot_files
["boot.js"]
end
def boot_dir
File.join(path, 'boot')
end
def spec_files(type)
raise ArgumentError.new("Unrecognized spec type") unless SPEC_TYPES.include?(type)
(Dir.glob(File.join(path, "spec", type, "*.js"))).map { |f| File.join("spec", type, File.basename(f)) }.uniq
@@ -31,6 +39,11 @@ module Jasmine
def css_files
Dir.glob(File.join(path, "*.css")).map { |f| File.basename(f) }
end
def images_dir
File.join(File.dirname(__FILE__), '../images')
end
end
end
end

131
lib/jasmine-core/boot.js Normal file
View File

@@ -0,0 +1,131 @@
/*
Copyright (c) 2008-2013 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// Jasmine boot.js for browser runners - exposes external/global interface, builds the Jasmine environment and executes it.
(function() {
window.jasmine = jasmineRequire.core(jasmineRequire);
jasmineRequire.html(jasmine);
var env = jasmine.getEnv();
var jasmineInterface = {
describe: function(description, specDefinitions) {
return env.describe(description, specDefinitions);
},
xdescribe: function(description, specDefinitions) {
return env.xdescribe(description, specDefinitions);
},
it: function(desc, func) {
return env.it(desc, func);
},
xit: function(desc, func) {
return env.xit(desc, func);
},
beforeEach: function(beforeEachFunction) {
return env.beforeEach(beforeEachFunction);
},
afterEach: function(afterEachFunction) {
return env.afterEach(afterEachFunction);
},
expect: function(actual) {
return env.expect(actual);
},
pending: function() {
return env.pending();
},
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName);
},
clock: env.clock,
setTimeout: env.clock.setTimeout,
clearTimeout: env.clock.clearTimeout,
setInterval: env.clock.setInterval,
clearInterval: env.clock.clearInterval,
jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer()
})
};
if (typeof window == "undefined" && typeof exports == "object") {
extend(exports, jasmineInterface);
} else {
extend(window, jasmineInterface);
}
var queryString = new jasmine.QueryString({
getWindowLocation: function() { return window.location; }
});
// TODO: move all of catching to raise so we don't break our brains
var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
var htmlReporter = new jasmine.HtmlReporter({
env: env,
queryString: queryString,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
timer: new jasmine.Timer()
});
env.addReporter(jasmineInterface.jsApiReporter);
env.addReporter(htmlReporter);
var specFilter = new jasmine.HtmlSpecFilter({
filterString: function() { return queryString.getParam("spec"); }
});
env.specFilter = function(spec) {
return specFilter.matches(spec.getFullName());
};
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
htmlReporter.initialize();
env.execute();
};
function extend(destination, source) {
for (var property in source) destination[property] = source[property];
return destination;
}
}());

View File

@@ -0,0 +1,109 @@
// Jasmine boot.js for browser runners - exposes external/global interface, builds the Jasmine environment and executes it.
(function() {
window.jasmine = jasmineRequire.core(jasmineRequire);
jasmineRequire.html(jasmine);
var env = jasmine.getEnv();
var jasmineInterface = {
describe: function(description, specDefinitions) {
return env.describe(description, specDefinitions);
},
xdescribe: function(description, specDefinitions) {
return env.xdescribe(description, specDefinitions);
},
it: function(desc, func) {
return env.it(desc, func);
},
xit: function(desc, func) {
return env.xit(desc, func);
},
beforeEach: function(beforeEachFunction) {
return env.beforeEach(beforeEachFunction);
},
afterEach: function(afterEachFunction) {
return env.afterEach(afterEachFunction);
},
expect: function(actual) {
return env.expect(actual);
},
pending: function() {
return env.pending();
},
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName);
},
clock: env.clock,
setTimeout: env.clock.setTimeout,
clearTimeout: env.clock.clearTimeout,
setInterval: env.clock.setInterval,
clearInterval: env.clock.clearInterval,
jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer()
})
};
if (typeof window == "undefined" && typeof exports == "object") {
extend(exports, jasmineInterface);
} else {
extend(window, jasmineInterface);
}
var queryString = new jasmine.QueryString({
getWindowLocation: function() { return window.location; }
});
// TODO: move all of catching to raise so we don't break our brains
var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
var htmlReporter = new jasmine.HtmlReporter({
env: env,
queryString: queryString,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
timer: new jasmine.Timer()
});
env.addReporter(jasmineInterface.jsApiReporter);
env.addReporter(htmlReporter);
var specFilter = new jasmine.HtmlSpecFilter({
filterString: function() { return queryString.getParam("spec"); }
});
env.specFilter = function(spec) {
return specFilter.matches(spec.getFullName());
};
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
htmlReporter.initialize();
env.execute();
};
function extend(destination, source) {
for (var property in source) destination[property] = source[property];
return destination;
}
}());

View File

@@ -1,54 +0,0 @@
<!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

@@ -52,7 +52,7 @@ describe("Player", function() {
expect(function() {
player.resume();
}).toThrow("song is already playing");
}).toThrowError("song is already playing");
});
});
});
});

View File

@@ -1,9 +1,15 @@
beforeEach(function() {
this.addMatchers({
toBePlaying: function(expectedSong) {
var player = this.actual;
return player.currentlyPlayingSong === expectedSong &&
player.isPlaying;
}
});
beforeEach(function () {
jasmine.Expectation.addMatchers({
toBePlaying: function () {
return {
compare: function (actual, expected) {
var player = actual;
return {
pass: player.currentlyPlayingSong === expected && player.isPlaying
}
}
};
}
});
});

View File

@@ -1,190 +1,354 @@
jasmine.TrivialReporter = function(doc) {
this.document = doc || document;
this.suiteDivs = {};
this.logRunningSpecs = false;
/*
Copyright (c) 2008-2013 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
jasmineRequire.html = function(j$) {
j$.ResultsNode = jasmineRequire.ResultsNode();
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
j$.QueryString = jasmineRequire.QueryString();
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
};
jasmineRequire.HtmlReporter = function(j$) {
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
var el = document.createElement(type);
var noopTimer = {
start: function(){},
elapsed: function(){ return 0; }
};
for (var i = 2; i < arguments.length; i++) {
var child = arguments[i];
function HtmlReporter(options) {
var env = options.env || {},
getContainer = options.getContainer,
createElement = options.createElement,
createTextNode = options.createTextNode,
onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
timer = options.timer || noopTimer,
results = [],
specsExecuted = 0,
failureCount = 0,
pendingSpecCount = 0,
htmlReporterMain,
symbols;
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('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.initialize = function() {
htmlReporterMain = createDom("div", {className: "html-reporter"},
createDom("div", {className: "banner"},
createDom("span", {className: "title"}, "Jasmine"),
createDom("span", {className: "version"}, j$.version)
),
createDom("ul", {className: "symbol-summary"}),
createDom("div", {className: "alert"}),
createDom("div", {className: "results"},
createDom("div", {className: "failures"})
)
);
getContainer().appendChild(htmlReporterMain);
this.document.body.appendChild(this.outerDiv);
symbols = find(".symbol-summary");
};
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);
}
var totalSpecsDefined;
this.jasmineStarted = function(options) {
totalSpecsDefined = options.totalSpecsDefined || 0;
timer.start();
};
this.startedAt = new Date();
var summary = createDom("div", {className: "summary"});
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/, '');
}
};
var topResults = new j$.ResultsNode({}, "", null),
currentParent = topResults;
showSkipped.onclick = function(evt) {
if (showSkipped.checked) {
self.outerDiv.className += ' show-skipped';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
}
};
};
this.suiteStarted = function(result) {
currentParent.addChild(result, "suite");
currentParent = currentParent.last();
};
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));
this.suiteDone = function(result) {
if (currentParent == topResults) {
return;
}
currentParent = currentParent.parent;
};
this.specStarted = function(result) {
currentParent.addChild(result, "spec");
};
var failures = [];
this.specDone = function(result) {
if (result.status != "disabled") {
specsExecuted++;
}
symbols.appendChild(createDom("li", {
className: result.status,
id: "spec_" + result.id,
title: result.fullName}
));
if (result.status == "failed") {
failureCount++;
var failure =
createDom("div", {className: "spec-detail failed"},
createDom("a", {className: "description", title: result.fullName, href: specHref(result)}, result.fullName),
createDom("div", {className: "messages"})
);
var messages = failure.childNodes[1];
for (var i = 0; i < result.failedExpectations.length; i++) {
var expectation = result.failedExpectations[i];
messages.appendChild(createDom("div", {className: "result-message"}, expectation.message));
messages.appendChild(createDom("div", {className: "stack-trace"}, expectation.stack));
}
failures.push(failure);
}
if (result.status == "pending") {
pendingSpecCount++;
}
};
this.jasmineDone = function() {
var banner = find(".banner");
banner.appendChild(createDom("span", {className: "duration"}, "finished in " + timer.elapsed() / 1000 + "s"));
var alert = find(".alert");
alert.appendChild(createDom("span", { className: "exceptions" },
createDom("label", { className: "label", 'for': "raise-exceptions" }, "raise exceptions"),
createDom("input", {
className: "raise",
id: "raise-exceptions",
type: "checkbox"
})
));
var checkbox = find("input");
checkbox.checked = !env.catchingExceptions();
checkbox.onclick = onRaiseExceptionsClick;
if (specsExecuted < totalSpecsDefined) {
var skippedMessage = "Ran " + specsExecuted + " of " + totalSpecsDefined + " specs - run all";
alert.appendChild(
createDom("span", {className: "bar skipped"},
createDom("a", {href: "?", title: "Run all specs"}, skippedMessage)
)
);
}
var statusBarMessage = "" + pluralize("spec", specsExecuted) + ", " + pluralize("failure", failureCount);
if (pendingSpecCount) { statusBarMessage += ", " + pluralize("pending spec", pendingSpecCount); }
var statusBarClassName = "bar " + ((failureCount > 0) ? "failed" : "passed");
alert.appendChild(createDom("span", {className: statusBarClassName}, statusBarMessage));
var results = find(".results");
results.appendChild(summary);
summaryList(topResults, summary);
function summaryList(resultsTree, domParent) {
var specListNode;
for (var i = 0; i < resultsTree.children.length; i++) {
var resultNode = resultsTree.children[i];
if (resultNode.type == "suite") {
var suiteListNode = createDom("ul", {className: "suite", id: "suite-" + resultNode.result.id},
createDom("li", {className: "suite-detail"},
createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description)
)
);
summaryList(resultNode, suiteListNode);
domParent.appendChild(suiteListNode);
}
if (resultNode.type == "spec") {
if (domParent.getAttribute("class") != "specs") {
specListNode = createDom("ul", {className: "specs"});
domParent.appendChild(specListNode);
}
specListNode.appendChild(
createDom("li", {
className: resultNode.result.status,
id: "spec-" + resultNode.result.id
},
createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description)
)
);
}
}
}
if (failures.length) {
alert.appendChild(
createDom('span', {className: "menu bar spec-list"},
createDom("span", {}, "Spec List | "),
createDom('a', {className: "failures-menu", href: "#"}, "Failures")));
alert.appendChild(
createDom('span', {className: "menu bar failure-list"},
createDom('a', {className: "spec-list-menu", href: "#"}, "Spec List"),
createDom("span", {}, " | Failures ")));
find(".failures-menu").onclick = function() {
setMenuModeTo('failure-list');
};
find(".spec-list-menu").onclick = function() {
setMenuModeTo('spec-list');
};
setMenuModeTo('failure-list');
var failureNode = find(".failures");
for (var i = 0; i < failures.length; i++) {
failureNode.appendChild(failures[i]);
}
}
};
return this;
function find(selector) {
return getContainer().querySelector(selector);
}
function createDom(type, attrs, childrenVarArgs) {
var el = createElement(type);
for (var i = 2; i < arguments.length; i++) {
var child = arguments[i];
if (typeof child === 'string') {
el.appendChild(createTextNode(child));
} else {
if (child) {
el.appendChild(child);
}
}
}
for (var attr in attrs) {
if (attr == "className") {
el[attr] = attrs[attr];
} else {
el.setAttribute(attr, attrs[attr]);
}
}
return el;
}
function pluralize(singular, count) {
var word = (count == 1 ? singular : singular + "s");
return "" + count + " " + word;
}
function specHref(result) {
return "?spec=" + encodeURIComponent(result.fullName);
}
function setMenuModeTo(mode) {
htmlReporterMain.setAttribute("class", "html-reporter " + mode);
}
}
if (messagesDiv.childNodes.length > 0) {
specDiv.appendChild(messagesDiv);
}
this.suiteDivs[spec.suite.id].appendChild(specDiv);
return HtmlReporter;
};
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
jasmineRequire.HtmlSpecFilter = function() {
function HtmlSpecFilter(options) {
var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
var filterPattern = new RegExp(filterString);
this.matches = function(specName) {
return filterPattern.test(specName);
};
}
return HtmlSpecFilter;
};
jasmineRequire.ResultsNode = function() {
function ResultsNode(result, type, parent) {
this.result = result;
this.type = type;
this.parent = parent;
this.children = [];
this.addChild = function(result, type) {
this.children.push(new ResultsNode(result, type, this));
};
this.last = function() {
return this.children[this.children.length - 1];
};
}
return ResultsNode;
};
jasmineRequire.QueryString = function() {
function QueryString(options) {
this.setParam = function(key, value) {
var paramMap = queryStringToParamMap();
paramMap[key] = value;
options.getWindowLocation().search = toQueryString(paramMap);
};
this.getParam = function(key) {
return queryStringToParamMap()[key];
};
return this;
function toQueryString(paramMap) {
var qStrPairs = [];
for (var prop in paramMap) {
qStrPairs.push(encodeURIComponent(prop) + "=" + encodeURIComponent(paramMap[prop]));
}
return "?" + qStrPairs.join('&');
}
}
};
jasmine.TrivialReporter.prototype.getLocation = function() {
return this.document.location;
};
function queryStringToParamMap() {
var paramStr = options.getWindowLocation().search.substring(1),
params = [],
paramMap = {};
if (paramStr.length > 0) {
params = paramStr.split('&');
for (var i = 0; i < params.length; i++) {
var p = params[i].split('=');
var value = decodeURIComponent(p[1]);
if (value === "true" || value === "false") {
value = JSON.parse(value);
}
paramMap[decodeURIComponent(p[0])] = value;
}
}
return paramMap;
}
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;
return QueryString;
};

View File

@@ -1,166 +1,54 @@
body {
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
}
body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
.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;
}
.html-reporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
.html-reporter a { text-decoration: none; }
.html-reporter a:hover { text-decoration: underline; }
.html-reporter p, .html-reporter h1, .html-reporter h2, .html-reporter h3, .html-reporter h4, .html-reporter h5, .html-reporter h6 { margin: 0; line-height: 14px; }
.html-reporter .banner, .html-reporter .symbol-summary, .html-reporter .summary, .html-reporter .result-message, .html-reporter .spec .description, .html-reporter .spec-detail .description, .html-reporter .alert .bar, .html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; }
.html-reporter .banner .version { margin-left: 14px; }
.html-reporter #jasmine_content { position: fixed; right: 100%; }
.html-reporter .version { color: #aaaaaa; }
.html-reporter .banner { margin-top: 14px; }
.html-reporter .duration { color: #aaaaaa; float: right; }
.html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; }
.html-reporter .symbol-summary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
.html-reporter .symbol-summary li.passed { font-size: 14px; }
.html-reporter .symbol-summary li.passed:before { color: #5e7d00; content: "\02022"; }
.html-reporter .symbol-summary li.failed { line-height: 9px; }
.html-reporter .symbol-summary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
.html-reporter .symbol-summary li.disabled { font-size: 14px; }
.html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; }
.html-reporter .symbol-summary li.pending { line-height: 17px; }
.html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; }
.html-reporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
.html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
.html-reporter .bar.failed { background-color: #b03911; }
.html-reporter .bar.passed { background-color: #a6b779; }
.html-reporter .bar.skipped { background-color: #bababa; }
.html-reporter .bar.menu { background-color: #fff; color: #aaaaaa; }
.html-reporter .bar.menu a { color: #333333; }
.html-reporter .bar a { color: white; }
.html-reporter.spec-list .bar.menu.failure-list, .html-reporter.spec-list .results .failures { display: none; }
.html-reporter.failure-list .bar.menu.spec-list, .html-reporter.failure-list .summary { display: none; }
.html-reporter .running-alert { background-color: #666666; }
.html-reporter .results { margin-top: 14px; }
.html-reporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
.html-reporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
.html-reporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
.html-reporter.showDetails .summary { display: none; }
.html-reporter.showDetails #details { display: block; }
.html-reporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
.html-reporter .summary { margin-top: 14px; }
.html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; }
.html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; }
.html-reporter .summary li.passed a { color: #5e7d00; }
.html-reporter .summary li.failed a { color: #b03911; }
.html-reporter .summary li.pending a { color: #ba9d37; }
.html-reporter .description + .suite { margin-top: 0; }
.html-reporter .suite { margin-top: 14px; }
.html-reporter .suite a { color: #333333; }
.html-reporter .failures .spec-detail { margin-bottom: 28px; }
.html-reporter .failures .spec-detail .description { display: block; color: white; background-color: #b03911; }
.html-reporter .result-message { padding-top: 14px; color: #333333; white-space: pre; }
.html-reporter .result-message span.result { display: block; }
.html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #dddddd; background: white; white-space: pre; }

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,9 @@
#
# DO NOT Edit this file. Canonical version of Jasmine lives in the repo's package.json. This file is generated
# by a grunt task when the standalone release is built.
#
module Jasmine
module Core
VERSION = "1.1.0.rc4"
VERSION = "2.0.0.rc2"
end
end

13
package.json Normal file
View File

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

1
pages

Submodule pages deleted from a9d577eb45

138
release_notes/20rc1.md Normal file
View File

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

View File

@@ -1,451 +1,226 @@
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;
var out;
beforeEach(function() {
out = (function() {
var output = "";
return {
print:function(str) {
print: function(str) {
output += str;
},
getOutput:function() {
getOutput: function() {
return output;
},
clear: function() {
output = "";
}
};
})();
}());
});
done = false;
reporter = new jasmine.ConsoleReporter(out.print, function(runner) {
done = true
it("reports that the suite has started to the console", function() {
var reporter = new j$.ConsoleReporter({
print: out.print
});
reporter.jasmineStarted();
expect(out.getOutput()).toEqual("Started\n");
});
it("starts the provided timer when jasmine starts", function() {
var timerSpy = jasmine.createSpyObj('timer', ['start']),
reporter = new j$.ConsoleReporter({
print: out.print,
timer: timerSpy
});
reporter.jasmineStarted();
expect(timerSpy.start).toHaveBeenCalled();
});
it("reports a passing spec as a dot", function() {
var reporter = new j$.ConsoleReporter({
print: out.print
});
reporter.specDone({status: "passed"});
expect(out.getOutput()).toEqual(".");
});
it("does not report a disabled spec", function() {
var reporter = new j$.ConsoleReporter({
print: out.print
});
reporter.specDone({status: "disabled"});
expect(out.getOutput()).toEqual("");
});
it("reports a failing spec as an 'F'", function() {
var reporter = new j$.ConsoleReporter({
print: out.print
});
reporter.specDone({status: "failed"});
expect(out.getOutput()).toEqual("F");
});
it("reports a pending spec as a '*'", function() {
var reporter = new j$.ConsoleReporter({
print: out.print
});
reporter.specDone({status: "pending"});
expect(out.getOutput()).toEqual("*");
});
it("reports a summary when done (singluar spec and time)", function() {
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
reporter = new j$.ConsoleReporter({
print: out.print,
timer: timerSpy
});
reporter.jasmineStarted();
reporter.specDone({status: "passed"});
timerSpy.elapsed.and.callReturn(1000);
out.clear();
reporter.jasmineDone();
expect(out.getOutput()).toMatch(/1 spec, 0 failures/);
expect(out.getOutput()).not.toMatch(/0 pending specs/);
expect(out.getOutput()).toMatch("Finished in 1 second\n");
});
it("reports a summary when done (pluralized specs and seconds)", function() {
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
reporter = new j$.ConsoleReporter({
print: out.print,
timer: timerSpy
});
reporter.jasmineStarted();
reporter.specDone({status: "passed"});
reporter.specDone({status: "pending"});
reporter.specDone({
status: "failed",
description: "with a failing spec",
fullName: "A suite with a failing spec",
failedExpectations: [
{
passed: false,
message: "Expected true to be false.",
expected: false,
actual: true,
stack: "foo\nbar\nbaz"
}
]
});
out.clear();
timerSpy.elapsed.and.callReturn(100);
reporter.jasmineDone();
expect(out.getOutput()).toMatch(/3 specs, 1 failure, 1 pending spec/);
expect(out.getOutput()).toMatch("Finished in 0.1 seconds\n");
});
it("reports a summary when done that includes stack traces for a failing suite", function() {
var reporter = new j$.ConsoleReporter({
print: out.print
});
reporter.jasmineStarted();
reporter.specDone({status: "passed"});
reporter.specDone({
status: "failed",
description: "with a failing spec",
fullName: "A suite with a failing spec",
failedExpectations: [
{
passed: false,
message: "Expected true to be false.",
expected: false,
actual: true,
stack: "foo bar baz"
}
]
});
out.clear();
reporter.jasmineDone({});
expect(out.getOutput()).toMatch(/foo bar baz/);
});
it("calls the onComplete callback when the suite is done", function() {
var onComplete = jasmine.createSpy('onComplete'),
reporter = new j$.ConsoleReporter({
print: out.print,
onComplete: onComplete
});
reporter.jasmineDone({});
expect(onComplete).toHaveBeenCalled();
});
describe('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
);
describe("with color", function() {
var output = out.getOutput();
expect(output).toMatch(/^Started/);
expect(output).toMatch(/\.\.\./);
expect(output).toMatch(/3 specs, 0 failures/);
it("reports that the suite has started to the console", function() {
var reporter = new j$.ConsoleReporter({
print: out.print,
showColors: true
});
reporter.jasmineStarted();
expect(out.getOutput()).toEqual("Started\n");
});
it("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);
it("reports a passing spec as a dot", function() {
var reporter = new j$.ConsoleReporter({
print: out.print,
showColors: true
});
var output = out.getOutput();
expect(output).toMatch(/^Started/);
expect(output).toMatch(/\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\./);
expect(output).toMatch(/3 specs, 0 failures/);
reporter.specDone({status: "passed"});
expect(out.getOutput()).toEqual("\033[32m.\033[0m");
});
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);
it("does not report a disabled spec", function() {
var reporter = new j$.ConsoleReporter({
print: out.print,
showColors: true
});
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/);
reporter.specDone({status: 'disabled'});
expect(out.getOutput()).toEqual("");
});
it("reports a failing spec as an 'F'", function() {
var reporter = new j$.ConsoleReporter({
print: out.print,
showColors: true
});
reporter.specDone({status: 'failed'});
expect(out.getOutput()).toEqual("\033[31mF\033[0m");
});
});
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();
});
});
});
});
});
});

45
spec/core/AnySpec.js Normal file
View File

@@ -0,0 +1,45 @@
describe("Any", function() {
it("matches a string", function() {
var any = new j$.Any(String);
expect(any.jasmineMatches("foo")).toBe(true);
});
it("matches a number", function() {
var any = new j$.Any(Number);
expect(any.jasmineMatches(1)).toBe(true);
});
it("matches a function", function() {
var any = new j$.Any(Function);
expect(any.jasmineMatches(function(){})).toBe(true);
});
it("matches an Object", function() {
var any = new j$.Any(Object);
expect(any.jasmineMatches({})).toBe(true);
});
it("matches a Boolean", function() {
var any = new j$.Any(Boolean);
expect(any.jasmineMatches(true)).toBe(true);
});
it("matches another constructed object", function() {
var Thing = function() {},
any = new j$.Any(Thing);
expect(any.jasmineMatches(new Thing())).toBe(true);
});
it("jasmineToString's itself", function() {
var any = new j$.Any(Number);
expect(any.jasmineToString()).toMatch('<jasmine.any');
});
});

View File

@@ -1,27 +0,0 @@
describe("base.js", function() {
describe("jasmine.MessageResult", function() {
it("#toString should pretty-print and concatenate each part of the message", function() {
var values = ["log", "message", 123, {key: "value"}, "FTW!"];
var messageResult = new jasmine.MessageResult(values);
expect(messageResult.toString()).toEqual("log message 123 { key : 'value' } FTW!");
});
});
describe("jasmine.log", function() {
it("should accept n arguments", function() {
spyOn(jasmine.getEnv().currentSpec, 'log');
jasmine.log(1, 2, 3);
expect(jasmine.getEnv().currentSpec.log).toHaveBeenCalledWith(1, 2, 3);
});
});
describe("jasmine.getGlobal", function() {
it("should return the global object", function() {
var globalObject = (function() {
return this;
})();
expect(jasmine.getGlobal()).toBe(globalObject);
});
});
});

View File

@@ -0,0 +1,105 @@
describe("CallTracker", function() {
it("tracks that it was called when executed", function() {
var callTracker = new j$.CallTracker();
expect(callTracker.any()).toBe(false);
callTracker.track();
expect(callTracker.any()).toBe(true);
});
it("tracks that number of times that it is executed", function() {
var callTracker = new j$.CallTracker();
expect(callTracker.count()).toEqual(0);
callTracker.track();
expect(callTracker.count()).toEqual(1);
});
it("tracks the params from each execution", function() {
var callTracker = new j$.CallTracker();
callTracker.track({object: void 0, args: []});
callTracker.track({object: {}, args: [0, "foo"]});
expect(callTracker.argsFor(0)).toEqual([]);
expect(callTracker.argsFor(1)).toEqual([0, "foo"]);
});
it("returns any empty array when there was no call", function() {
var callTracker = new j$.CallTracker();
expect(callTracker.argsFor(0)).toEqual([]);
});
it("allows access for the arguments for all calls", function() {
var callTracker = new j$.CallTracker();
callTracker.track({object: {}, args: []});
callTracker.track({object: {}, args: [0, "foo"]});
expect(callTracker.allArgs()).toEqual([[], [0, "foo"]]);
});
it("tracks the context and arguments for each call", function() {
var callTracker = new j$.CallTracker();
callTracker.track({object: {}, args: []});
callTracker.track({object: {}, args: [0, "foo"]});
expect(callTracker.all()[0]).toEqual({object: {}, args: []});
expect(callTracker.all()[1]).toEqual({object: {}, args: [0, "foo"]});
});
it("simplifies access to the arguments for the last (most recent) call", function() {
var callTracker = new j$.CallTracker();
callTracker.track();
callTracker.track({object: {}, args: [0, "foo"]});
expect(callTracker.mostRecent()).toEqual({
object: {},
args: [0, "foo"]
});
});
it("returns a useful falsy value when there isn't a last (most recent) call", function() {
var callTracker = new j$.CallTracker();
expect(callTracker.mostRecent()).toBeFalsy();
});
it("simplifies access to the arguments for the first (oldest) call", function() {
var callTracker = new j$.CallTracker();
callTracker.track({object: {}, args: [0, "foo"]});
expect(callTracker.first()).toEqual({object: {}, args: [0, "foo"]})
});
it("returns a useful falsy value when there isn't a first (oldest) call", function() {
var callTracker = new j$.CallTracker();
expect(callTracker.first()).toBeFalsy();
});
it("allows the tracking to be reset", function() {
var callTracker = new j$.CallTracker();
callTracker.track();
callTracker.track({object: {}, args: [0, "foo"]});
callTracker.reset();
expect(callTracker.any()).toBe(false);
expect(callTracker.count()).toEqual(0);
expect(callTracker.argsFor(0)).toEqual([]);
expect(callTracker.all()).toEqual([]);
expect(callTracker.mostRecent()).toBeFalsy();
});
});

314
spec/core/ClockSpec.js Normal file
View File

@@ -0,0 +1,314 @@
describe("Clock", function() {
it("calls the global setTimeout directly if Clock is not installed", function() {
var setTimeout = jasmine.createSpy('setTimeout'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction']),
global = { setTimeout: setTimeout },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.setTimeout(delayedFn, 0);
expect(delayedFunctionScheduler.scheduleFunction).not.toHaveBeenCalled();
expect(setTimeout).toHaveBeenCalledWith(delayedFn, 0);
});
it("schedules the delayed function with the fake timer", function() {
var setTimeout = jasmine.createSpy('setTimeout'),
scheduleFunction = jasmine.createSpy('scheduleFunction'),
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
global = { setTimeout: setTimeout },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.install();
clock.setTimeout(delayedFn, 0, 'a', 'b');
expect(setTimeout).not.toHaveBeenCalled();
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(delayedFn, 0, ['a', 'b']);
});
it("returns an id for the delayed function", function() {
var setTimeout = jasmine.createSpy('setTimeout'),
scheduleId = 123,
scheduleFunction = jasmine.createSpy('scheduleFunction').and.callReturn(scheduleId),
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
global = { setTimeout: setTimeout },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler),
timeoutId;
clock.install();
timeoutId = clock.setTimeout(delayedFn, 0);
expect(timeoutId).toEqual(123);
});
it("calls the global clearTimeout directly if Clock is not installed", function() {
var clearTimeout = jasmine.createSpy('clearTimeout'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['clearTimeout']),
global = { clearTimeout: clearTimeout },
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.clearTimeout(123);
expect(clearTimeout).toHaveBeenCalledWith(123);
});
it("clears the scheduled function with the scheduler", function() {
var clearTimeout = jasmine.createSpy('clearTimeout'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['removeFunctionWithId']),
global = { setTimeout: clearTimeout },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.install();
clock.clearTimeout(123);
expect(clearTimeout).not.toHaveBeenCalled();
expect(delayedFunctionScheduler.removeFunctionWithId).toHaveBeenCalledWith(123);
});
it("calls the global setInterval directly if Clock is not installed", function() {
var setInterval = jasmine.createSpy('setInterval'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction']),
global = { setInterval: setInterval },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.setInterval(delayedFn, 0);
expect(delayedFunctionScheduler.scheduleFunction).not.toHaveBeenCalled();
expect(setInterval).toHaveBeenCalledWith(delayedFn, 0);
});
it("schedules the delayed function with the fake timer", function() {
var setInterval = jasmine.createSpy('setInterval'),
scheduleFunction = jasmine.createSpy('scheduleFunction'),
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
global = { setInterval: setInterval },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.install();
clock.setInterval(delayedFn, 0, 'a', 'b');
expect(setInterval).not.toHaveBeenCalled();
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(delayedFn, 0, ['a', 'b'], true);
});
it("returns an id for the delayed function", function() {
var setInterval = jasmine.createSpy('setInterval'),
scheduleId = 123,
scheduleFunction = jasmine.createSpy('scheduleFunction').and.callReturn(scheduleId),
delayedFunctionScheduler = {scheduleFunction: scheduleFunction},
global = { setInterval: setInterval },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler),
intervalId;
clock.install();
intervalId = clock.setInterval(delayedFn, 0);
expect(intervalId).toEqual(123);
});
it("calls the global clearInterval directly if Clock is not installed", function() {
var clearInterval = jasmine.createSpy('clearInterval'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['clearInterval']),
global = { clearInterval: clearInterval },
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.clearInterval(123);
expect(clearInterval).toHaveBeenCalledWith(123);
});
it("clears the scheduled function with the scheduler", function() {
var clearInterval = jasmine.createSpy('clearInterval'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['removeFunctionWithId']),
global = { setInterval: clearInterval },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.install();
clock.clearInterval(123);
expect(clearInterval).not.toHaveBeenCalled();
expect(delayedFunctionScheduler.removeFunctionWithId).toHaveBeenCalledWith(123);
});
it("gives you a friendly reminder if the Clock is not installed and you tick", function() {
var clock = new j$.Clock({}, jasmine.createSpyObj('delayedFunctionScheduler', ['tick']));
expect(function() {
clock.tick(50);
}).toThrow();
});
it("can be uninstalled", function() {
var setTimeout = jasmine.createSpy('setTimeout'),
setInterval = jasmine.createSpy('setInterval'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction', 'tick', 'reset']),
global = { setTimeout: setTimeout, setInterval: setInterval },
delayedFn = jasmine.createSpy('delayedFn'),
clock = new j$.Clock(global, delayedFunctionScheduler);
clock.install();
clock.setTimeout(delayedFn, 0);
expect(setTimeout).not.toHaveBeenCalled();
clock.setInterval(delayedFn, 0);
expect(setInterval).not.toHaveBeenCalled();
expect(function() {
clock.tick(0);
}).not.toThrow();
clock.uninstall();
expect(delayedFunctionScheduler.reset).toHaveBeenCalled();
clock.setTimeout(delayedFn, 0);
expect(setTimeout).toHaveBeenCalled();
clock.setInterval(delayedFn, 0);
expect(setInterval).toHaveBeenCalled();
expect(function() {
clock.tick(0);
}).toThrow();
});
it("on IE < 9, fails if extra args are passed to fake clock", function() {
//fail, because this would break in IE9.
var setTimeout = jasmine.createSpy('setTimeout'),
setInterval = jasmine.createSpy('setInterval'),
delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['scheduleFunction']),
fn = jasmine.createSpy('fn'),
global = { setTimeout: setTimeout, setInterval: setInterval },
clock = new j$.Clock(global, delayedFunctionScheduler);
setTimeout.apply = null;
setInterval.apply = null;
clock.install();
clock.setTimeout(fn, 0);
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, []);
expect(function() {
clock.setTimeout(fn, 0, 'extra');
}).toThrow();
clock.setInterval(fn, 0);
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(fn, 0, [], true);
expect(function() {
clock.setInterval(fn, 0, 'extra');
}).toThrow();
});
});
describe("Clock (acceptance)", function() {
it("can run setTimeouts/setIntervals synchronously", function() {
var delayedFn1 = jasmine.createSpy('delayedFn1'),
delayedFn2 = jasmine.createSpy('delayedFn2'),
delayedFn3 = jasmine.createSpy('delayedFn3'),
recurring1 = jasmine.createSpy('recurring1'),
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
clock = new j$.Clock({setTimeout: setTimeout}, delayedFunctionScheduler);
clock.install();
clock.setTimeout(delayedFn1, 0, 'some', 'arg');
var intervalId = clock.setInterval(recurring1, 50, 'some', 'other', 'args');
clock.setTimeout(delayedFn2, 100);
clock.setTimeout(delayedFn3, 200);
expect(delayedFn1).not.toHaveBeenCalled();
expect(delayedFn2).not.toHaveBeenCalled();
expect(delayedFn3).not.toHaveBeenCalled();
clock.tick(0);
expect(delayedFn1).toHaveBeenCalledWith('some', 'arg');
expect(delayedFn2).not.toHaveBeenCalled();
expect(delayedFn3).not.toHaveBeenCalled();
clock.tick(50);
expect(recurring1).toHaveBeenCalledWith('some', 'other', 'args');
expect(recurring1.calls.count()).toBe(1);
expect(delayedFn2).not.toHaveBeenCalled();
expect(delayedFn3).not.toHaveBeenCalled();
clock.tick(50);
expect(recurring1.calls.count()).toBe(2);
expect(delayedFn2).toHaveBeenCalled();
expect(delayedFn3).not.toHaveBeenCalled();
clock.tick(100);
expect(recurring1.calls.count()).toBe(4);
expect(delayedFn3).toHaveBeenCalled();
clock.clearInterval(intervalId);
clock.tick(50);
expect(recurring1.calls.count()).toBe(4);
});
it("can clear a previously set timeout", function() {
var clearedFn = jasmine.createSpy('clearedFn'),
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler),
timeoutId;
clock.install();
timeoutId = clock.setTimeout(clearedFn, 100);
expect(clearedFn).not.toHaveBeenCalled();
clock.clearTimeout(timeoutId);
clock.tick(100);
expect(clearedFn).not.toHaveBeenCalled();
});
it("correctly schedules functions after the Clock has advanced", function() {
var delayedFn1 = jasmine.createSpy('delayedFn1'),
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
clock = new j$.Clock({setTimeout: function(){}}, delayedFunctionScheduler);
clock.install();
clock.tick(100);
clock.setTimeout(delayedFn1, 10, ['some', 'arg']);
clock.tick(5);
expect(delayedFn1).not.toHaveBeenCalled();
clock.tick(5);
expect(delayedFn1).toHaveBeenCalled();
});
it("calls the global clearTimeout correctly when not installed", function () {
var delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['clearTimeout']),
global = jasmine.getGlobal(),
clock = new j$.Clock(global, delayedFunctionScheduler);
expect(function() {
clock.clearTimeout(123)
}).not.toThrow();
});
it("calls the global clearTimeout correctly when not installed", function () {
var delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['clearTimeout']),
global = jasmine.getGlobal(),
clock = new j$.Clock(global, delayedFunctionScheduler);
expect(function() {
clock.clearInterval(123)
}).not.toThrow();
});
});

View File

@@ -1,97 +1,96 @@
describe("Custom Matchers", function() {
var env;
var fakeTimer;
beforeEach(function() {
env = new jasmine.Env();
env.updateInterval = 0;
});
it("should be easy to add more matchers local to a spec, suite, etc.", function() {
var spec1, spec2, spec1Matcher, spec2Matcher;
var suite = env.describe('some suite', function() {
env.beforeEach(function() {
this.addMatchers({
matcherForSuite: function(expected) {
this.message = "matcherForSuite: actual: " + this.actual + "; expected: " + expected;
return true;
}
});
});
spec1 = env.it('spec with an expectation').runs(function () {
this.addMatchers({
matcherForSpec: function(expected) {
this.message = "matcherForSpec: actual: " + this.actual + "; expected: " + expected;
return true;
}
});
spec1Matcher = this.expect("xxx");
});
spec2 = env.it('spec with failing expectation').runs(function () {
spec2Matcher = this.expect("yyy");
});
});
suite.execute();
spec1Matcher.matcherForSuite("expected");
expect(spec1Matcher.message).toEqual("matcherForSuite: actual: xxx; expected: expected");
spec1Matcher.matcherForSpec("expected");
expect(spec1Matcher.message).toEqual("matcherForSpec: actual: xxx; expected: expected");
spec2Matcher.matcherForSuite("expected");
expect(spec2Matcher.message).toEqual("matcherForSuite: actual: yyy; expected: expected");
expect(spec2Matcher.matcherForSpec).toBe(jasmine.undefined);
});
it("should generate messages with the same rules as for regular matchers when this.report() is not called", function() {
var spec;
var suite = env.describe('some suite', function() {
spec = env.it('spec with an expectation').runs(function () {
this.addMatchers({
toBeTrue: function() {
return this.actual === true;
}
});
this.expect(true).toBeTrue();
this.expect(false).toBeTrue();
});
});
suite.execute();
var passResult = new jasmine.ExpectationResult({passed: true, matcherName: 'toBeTrue',
actual: true, expected: jasmine.undefined, message: "Passed." });
var failResult = new jasmine.ExpectationResult({passed: false, matcherName: 'toBeTrue',
actual: false, expected: jasmine.undefined, message: "Expected false to be true." });
failResult.trace = jasmine.any(Object);
expect(spec.results().getItems()).toEqual([passResult, failResult]);
});
it("should pass args", function() {
var matcherCallArgs = [];
var spec;
var suite = env.describe('some suite', function() {
spec = env.it('spec with an expectation').runs(function () {
this.addMatchers({
toBeTrue: function() {
matcherCallArgs.push(jasmine.util.argsToArray(arguments));
return this.actual === true;
}
});
this.expect(true).toBeTrue();
this.expect(false).toBeTrue('arg');
this.expect(true).toBeTrue('arg1', 'arg2');
});
});
suite.execute();
var results = spec.results().getItems();
expect(results[0].expected).toEqual(jasmine.undefined);
expect(results[1].expected).toEqual('arg');
expect(results[2].expected).toEqual(['arg1', 'arg2']);
expect(matcherCallArgs).toEqual([[], ['arg'], ['arg1', 'arg2']]);
});
});
////TODO: matchers should be add-able to the env, not to the spec.
//describe("Custom Matchers", function() {
// var env;
// var fakeTimer;
//
// beforeEach(function() {
// env = new jasmine.Env();
// env.updateInterval = 0;
// });
//
// it("should be easy to add more matchers local to a spec, suite, etc.", function() {
// var spec1, spec2, spec1Matcher, spec2Matcher;
// var suite = env.describe('some suite', function() {
// env.beforeEach(function() {
// this.addMatchers({
// matcherForSuite: function(expected) {
// this.message = "matcherForSuite: actual: " + this.actual + "; expected: " + expected;
// return true;
// }
// });
// });
//
// spec1 = env.it('spec with an expectation').runs(function () {
// this.addMatchers({
// matcherForSpec: function(expected) {
// this.message = "matcherForSpec: actual: " + this.actual + "; expected: " + expected;
// return true;
// }
// });
// spec1Matcher = this.expect("xxx");
// });
//
// spec2 = env.it('spec with failing expectation').runs(function () {
// spec2Matcher = this.expect("yyy");
// });
// });
//
// suite.execute();
//
// spec1Matcher.matcherForSuite("expected");
// expect(spec1Matcher.message).toEqual("matcherForSuite: actual: xxx; expected: expected");
// spec1Matcher.matcherForSpec("expected");
// expect(spec1Matcher.message).toEqual("matcherForSpec: actual: xxx; expected: expected");
//
// spec2Matcher.matcherForSuite("expected");
// expect(spec2Matcher.message).toEqual("matcherForSuite: actual: yyy; expected: expected");
// expect(spec2Matcher.matcherForSpec).toBe(jasmine.undefined);
// });
//
// it("should generate messages with the same rules as for regular matchers when this.report() is not called", function() {
// var spec;
// var suite = env.describe('some suite', function() {
// spec = env.it('spec with an expectation').runs(function () {
// this.addMatchers({
// toBeTrue: function() {
// return this.actual === true;
// }
// });
// this.expect(true).toBeTrue();
// this.expect(false).toBeTrue();
// });
// });
//
// suite.execute();
//
// var results = spec.results().getItems();
// expect(results[0].message).toEqual("Passed.");
// expect(results[1].message).toEqual("Expected false to be true.");
// });
//
// it("should pass args", function() {
// var matcherCallArgs = [];
// var spec;
// var suite = env.describe('some suite', function() {
// spec = env.it('spec with an expectation').runs(function () {
// this.addMatchers({
// toBeTrue: function() {
// matcherCallArgs.push(jasmine.util.argsToArray(arguments));
// return this.actual === true;
// }
// });
// this.expect(true).toBeTrue();
// this.expect(false).toBeTrue('arg');
// this.expect(true).toBeTrue('arg1', 'arg2');
// });
// });
//
// suite.execute();
// var results = spec.results().getItems();
// expect(results[0].expected).toEqual(jasmine.undefined);
// expect(results[1].expected).toEqual('arg');
// expect(results[2].expected).toEqual(['arg1', 'arg2']);
//
// expect(matcherCallArgs).toEqual([[], ['arg'], ['arg1', 'arg2']]);
// });
//});

View File

@@ -0,0 +1,179 @@
describe("DelayedFunctionScheduler", function() {
it("schedules a function for later execution", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
scheduler.scheduleFunction(fn, 0);
expect(fn).not.toHaveBeenCalled();
scheduler.tick(0);
expect(fn).toHaveBeenCalled();
});
it("schedules a string for later execution", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
strfn = "horrible = true;";
scheduler.scheduleFunction(strfn, 0);
scheduler.tick(0);
expect(horrible).toEqual(true);
});
it("#tick defaults to 0", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
scheduler.scheduleFunction(fn, 0);
expect(fn).not.toHaveBeenCalled();
scheduler.tick();
expect(fn).toHaveBeenCalled();
});
it("defaults delay to 0", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
scheduler.scheduleFunction(fn);
expect(fn).not.toHaveBeenCalled();
scheduler.tick(0);
expect(fn).toHaveBeenCalled();
});
it("optionally passes params to scheduled functions", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
scheduler.scheduleFunction(fn, 0, ['foo', 'bar']);
expect(fn).not.toHaveBeenCalled();
scheduler.tick(0);
expect(fn).toHaveBeenCalledWith('foo', 'bar');
});
it("scheduled fns can optionally reoccur", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
scheduler.scheduleFunction(fn, 20, [], true);
expect(fn).not.toHaveBeenCalled();
scheduler.tick(20);
expect(fn.calls.count()).toBe(1);
scheduler.tick(40);
expect(fn.calls.count()).toBe(3);
scheduler.tick(21);
expect(fn.calls.count()).toBe(4);
});
it("increments scheduled fns ids unless one is passed", function() {
var scheduler = new j$.DelayedFunctionScheduler();
expect(scheduler.scheduleFunction(function() {
}, 0)).toBe(1);
expect(scheduler.scheduleFunction(function() {
}, 0)).toBe(2);
expect(scheduler.scheduleFunction(function() {
}, 0, [], false, 123)).toBe(123);
expect(scheduler.scheduleFunction(function() {
}, 0)).toBe(3);
});
it("#removeFunctionWithId removes a previously scheduled function with a given id", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn'),
timeoutKey;
timeoutKey = scheduler.scheduleFunction(fn, 0);
expect(fn).not.toHaveBeenCalled();
scheduler.removeFunctionWithId(timeoutKey);
scheduler.tick(0);
expect(fn).not.toHaveBeenCalled();
});
it("reset removes scheduled functions", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
scheduler.scheduleFunction(fn, 0);
expect(fn).not.toHaveBeenCalled();
scheduler.reset();
scheduler.tick(0);
expect(fn).not.toHaveBeenCalled();
});
it("reset resets the returned ids", function() {
var scheduler = new j$.DelayedFunctionScheduler();
expect(scheduler.scheduleFunction(function() { }, 0)).toBe(1);
expect(scheduler.scheduleFunction(function() { }, 0, [], false, 123)).toBe(123);
scheduler.reset();
expect(scheduler.scheduleFunction(function() { }, 0)).toBe(1);
expect(scheduler.scheduleFunction(function() { }, 0, [], false, 123)).toBe(123);
});
it("reset resets the current tick time", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
expect(fn).not.toHaveBeenCalled();
scheduler.tick(15);
scheduler.reset();
scheduler.scheduleFunction(fn, 20, [], false, 1, 20);
scheduler.tick(5);
expect(fn).not.toHaveBeenCalled();
});
it("executes recurring functions interleaved with regular functions in the correct order", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn'),
recurringCallCount = 0,
recurring = jasmine.createSpy('recurring').and.callFake(function() {
recurringCallCount++;
if (recurringCallCount < 5) {
expect(fn).not.toHaveBeenCalled();
}
});
scheduler.scheduleFunction(recurring, 10, [], true);
scheduler.scheduleFunction(fn, 50);
scheduler.tick(60);
expect(recurring).toHaveBeenCalled();
expect(recurring.calls.count()).toBe(6);
expect(fn).toHaveBeenCalled();
});
});

View File

@@ -1,12 +1,13 @@
describe("jasmine.Env", function() {
// TODO: Fix these unit tests!
describe("Env", function() {
var env;
beforeEach(function() {
env = new jasmine.Env();
env = new j$.Env();
env.updateInterval = 0;
});
describe('ids', function () {
it('nextSpecId should return consecutive integers, starting at 0', function () {
describe('ids', function() {
it('nextSpecId should return consecutive integers, starting at 0', function() {
expect(env.nextSpecId()).toEqual(0);
expect(env.nextSpecId()).toEqual(1);
expect(env.nextSpecId()).toEqual(2);
@@ -17,143 +18,494 @@ describe("jasmine.Env", function() {
var fakeReporter;
beforeEach(function() {
fakeReporter = jasmine.createSpyObj("fakeReporter", ["log"]);
});
describe('version', function () {
var oldVersion;
beforeEach(function () {
oldVersion = jasmine.version_;
});
afterEach(function () {
jasmine.version_ = oldVersion;
});
it('should raise an error if version is not set', function () {
jasmine.version_ = null;
var exception;
try {
env.version();
}
catch (e) {
exception = e;
}
expect(exception.message).toEqual('Version not set');
});
it("version should return the current version as an int", function() {
jasmine.version_ = {
"major": 1,
"minor": 9,
"build": 7,
"revision": 8
};
expect(env.version()).toEqual({
"major": 1,
"minor": 9,
"build": 7,
"revision": 8
});
});
describe("versionString", function() {
it("should return a stringified version number", function() {
jasmine.version_ = {
"major": 1,
"minor": 9,
"build": 7,
"release_candidate": "1",
"revision": 8
};
expect(env.versionString()).toEqual("1.9.7.rc1 revision 8");
});
it("should return a nice string when version is unknown", function() {
jasmine.version_ = null;
expect(env.versionString()).toEqual("version unknown");
});
});
fakeReporter = jasmine.createSpyObj("fakeReporter", ["jasmineStarted"]);
});
it("should allow reporters to be registered", function() {
env.addReporter(fakeReporter);
env.reporter.log("message");
expect(fakeReporter.log).toHaveBeenCalledWith("message");
env.reporter.jasmineStarted();
expect(fakeReporter.jasmineStarted).toHaveBeenCalled();
});
});
it('removes all spies when env is executed', function(done) {
originalFoo = function() {},
testObj = {
foo: originalFoo
},
firstSpec = jasmine.createSpy('firstSpec').and.callFake(function() {
env.spyOn(testObj, 'foo');
}),
secondSpec = jasmine.createSpy('secondSpec').and.callFake(function() {
expect(testObj.foo).toBe(originalFoo);
});
env.describe('test suite', function() {
env.it('spec 0', firstSpec);
env.it('spec 1', secondSpec);
});
var assertions = function() {
expect(firstSpec).toHaveBeenCalled();
expect(secondSpec).toHaveBeenCalled();
done();
};
env.addReporter({ jasmineDone: assertions });
env.execute();
});
describe("#spyOn", function() {
it("checks for the existance of the object", function() {
expect(function() {
env.spyOn(void 0, 'pants');
}).toThrowError(/could not find an object/);
});
it("checks for the existance of the method", function() {
var subject = {};
expect(function() {
env.spyOn(subject, 'pants');
}).toThrowError(/method does not exist/);
});
it("checks if it has already been spied upon", function() {
var subject = { spiedFunc: function() {} };
env.spyOn(subject, 'spiedFunc');
expect(function() {
env.spyOn(subject, 'spiedFunc');
}).toThrowError(/has already been spied upon/);
});
it("overrides the method on the object and returns the spy", function() {
var originalFunctionWasCalled = false;
var subject = { spiedFunc: function() { originalFunctionWasCalled = true; } };
originalFunc = subject.spiedFunc;
var spy = env.spyOn(subject, 'spiedFunc');
expect(subject.spiedFunc).toEqual(spy);
expect(subject.spiedFunc.calls.any()).toEqual(false);
expect(subject.spiedFunc.calls.count()).toEqual(0);
subject.spiedFunc('foo');
expect(subject.spiedFunc.calls.any()).toEqual(true);
expect(subject.spiedFunc.calls.count()).toEqual(1);
expect(subject.spiedFunc.calls.mostRecent().args).toEqual(['foo']);
expect(subject.spiedFunc.calls.mostRecent().object).toEqual(subject);
expect(originalFunctionWasCalled).toEqual(false);
subject.spiedFunc('bar');
expect(subject.spiedFunc.calls.count()).toEqual(2);
expect(subject.spiedFunc.calls.mostRecent().args).toEqual(['bar']);
});
});
describe("equality testing", function() {
describe("with custom equality testers", function() {
var aObj, bObj, isEqual;
describe("#catchException", function() {
it("returns true if the exception is a pending spec exception", function() {
env.catchExceptions(false);
beforeEach(function() {
env.addEqualityTester(function(a, b) {
aObj = a;
bObj = b;
return isEqual;
});
expect(env.catchException(new Error(j$.Spec.pendingSpecExceptionMessage))).toBe(true);
});
it("returns false if the exception is not a pending spec exception and not catching exceptions", function() {
env.catchExceptions(false);
expect(env.catchException(new Error("external error"))).toBe(false);
expect(env.catchException(new Error(j$.Spec.pendingSpecExceptionMessage))).toBe(true);
});
});
describe("#pending", function() {
it("throws the Pending Spec exception", function() {
expect(function() {
env.pending();
}).toThrow(j$.Spec.pendingSpecExceptionMessage);
});
});
});
// TODO: move these into a separate file
describe("Env integration", function() {
it("Suites execute as expected (no nesting)", function(done) {
var env = new j$.Env(),
calls = [];
var assertions = function() {
expect(calls).toEqual([
"with a spec",
"and another spec"
]);
done();
};
env.addReporter({ jasmineDone: assertions});
env.describe("A Suite", function() {
env.it("with a spec", function() {
calls.push("with a spec");
});
it("should call the custom equality tester with two objects for comparison", function() {
env.equals_("1", "2");
expect(aObj).toEqual("1");
expect(bObj).toEqual("2");
});
describe("when the custom equality tester returns false", function() {
beforeEach(function() {
isEqual = false;
});
it("should give custom equality testers precedence", function() {
expect(env.equals_('abc', 'abc')).toBeFalsy();
var o = {};
expect(env.equals_(o, o)).toBeFalsy();
});
});
describe("when the custom equality tester returns true", function() {
beforeEach(function() {
isEqual = true;
});
it("should give custom equality testers precedence", function() {
expect(env.equals_('abc', 'def')).toBeTruthy();
expect(env.equals_(true, false)).toBeTruthy();
});
});
describe("when the custom equality tester returns undefined", function() {
beforeEach(function() {
isEqual = jasmine.undefined;
});
it("should use normal equality rules", function() {
expect(env.equals_('abc', 'abc')).toBeTruthy();
expect(env.equals_('abc', 'def')).toBeFalsy();
});
describe("even if there are several", function() {
beforeEach(function() {
env.addEqualityTester(function(a, b) { return jasmine.undefined; });
env.addEqualityTester(function(a, b) { return jasmine.undefined; });
});
it("should use normal equality rules", function() {
expect(env.equals_('abc', 'abc')).toBeTruthy();
expect(env.equals_('abc', 'def')).toBeFalsy();
});
});
});
it("should evaluate custom equality testers in the order they are declared", function() {
isEqual = false;
env.addEqualityTester(function(a, b) { return true; });
expect(env.equals_('abc', 'abc')).toBeFalsy();
env.it("and another spec", function() {
calls.push("and another spec");
});
});
env.execute();
});
it("Nested Suites execute as expected", function(done) {
var env = new j$.Env(),
calls = [];
var assertions = function() {
expect(calls).toEqual([
'an outer spec',
'an inner spec',
'another inner spec'
]);
done();
};
env.addReporter({ jasmineDone: assertions });
env.describe("Outer suite", function() {
env.it("an outer spec", function() {
calls.push('an outer spec')
});
env.describe("Inner suite", function() {
env.it("an inner spec", function() {
calls.push('an inner spec');
});
env.it("another inner spec", function() {
calls.push('another inner spec');
});
});
});
env.execute();
});
it("Multiple top-level Suites execute as expected", function(done) {
var env = new j$.Env(),
calls = [];
var assertions = function() {
expect(calls).toEqual([
'an outer spec',
'an inner spec',
'another inner spec',
'a 2nd outer spec'
]);
done();
};
env.addReporter({ jasmineDone: assertions });
env.describe("Outer suite", function() {
env.it("an outer spec", function() {
calls.push('an outer spec')
});
env.describe("Inner suite", function() {
env.it("an inner spec", function() {
calls.push('an inner spec');
});
env.it("another inner spec", function() {
calls.push('another inner spec');
});
});
});
env.describe("Another outer suite", function() {
env.it("a 2nd outer spec", function() {
calls.push('a 2nd outer spec')
});
});
env.execute();
});
it("Mock clock can be installed and used in tests", function(done) {
var globalSetTimeout = jasmine.createSpy('globalSetTimeout'),
delayedFunctionForGlobalClock = jasmine.createSpy('delayedFunctionForGlobalClock'),
delayedFunctionForMockClock = jasmine.createSpy('delayedFunctionForMockClock'),
env = new j$.Env({global: { setTimeout: globalSetTimeout }});
var assertions = function() {
expect(delayedFunctionForMockClock).toHaveBeenCalled();
expect(globalSetTimeout).toHaveBeenCalledWith(delayedFunctionForGlobalClock, 100);
done();
};
env.addReporter({ jasmineDone: assertions });
env.describe("tests", function() {
env.it("test with mock clock", function() {
env.clock.install();
env.clock.setTimeout(delayedFunctionForMockClock, 100);
env.clock.tick(100);
});
env.it("test without mock clock", function() {
env.clock.setTimeout(delayedFunctionForGlobalClock, 100);
});
});
expect(globalSetTimeout).not.toHaveBeenCalled();
expect(delayedFunctionForMockClock).not.toHaveBeenCalled();
env.execute();
});
it("should run async specs in order, waiting for them to complete", function(done) {
var env = new j$.Env(), mutatedVar;
env.describe("tests", function() {
env.beforeEach(function() {
mutatedVar = 2;
});
env.it("async spec", function(underTestCallback) {
setTimeout(function() {
expect(mutatedVar).toEqual(2);
underTestCallback();
done();
}, 0);
});
env.it("after async spec", function() {
mutatedVar = 3;
});
});
env.execute();
});
describe("with a mock clock", function() {
beforeEach(function() {
jasmine.getEnv().clock.install();
});
afterEach(function() {
jasmine.getEnv().clock.uninstall();
});
it("should not hang on async specs that forget to call done()", function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [
"jasmineStarted",
"jasmineDone",
"suiteStarted",
"suiteDone",
"specStarted",
"specDone"
]);
env.addReporter(reporter);
env.describe("tests", function() {
env.it("async spec that will hang", function(underTestCallback) {
env.expect(true).toBeTruthy();
});
env.it("after async spec", function() {
env.expect(true).toBeTruthy();
});
});
env.execute();
reporter.jasmineDone.and.callFake(function() {
expect(reporter.jasmineStarted).toHaveBeenCalledWith({
totalSpecsDefined: 2
});
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({status: 'passed'}));
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({status: 'failed'}));
done();
});
jasmine.getEnv().clock.tick(60001);
});
});
// TODO: something is wrong with this spec
it("should report as expected", function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [
"jasmineStarted",
"jasmineDone",
"suiteStarted",
"suiteDone",
"specStarted",
"specDone"
]);
reporter.jasmineDone.and.callFake(function() {
expect(reporter.jasmineStarted).toHaveBeenCalledWith({
totalSpecsDefined: 3
});
var suiteResult = reporter.suiteStarted.calls.first().args[0];
expect(suiteResult.description).toEqual("A Suite");
expect(reporter.jasmineDone).toHaveBeenCalled();
done();
});
env.addReporter(reporter);
env.describe("A Suite", function() {
env.it("with a top level spec", function() {
env.expect(true).toBe(true);
});
env.describe("with a nested suite", function() {
env.xit("with a pending spec", function() {
env.expect(true).toBe(true);
});
env.it("with a spec", function() {
env.expect(true).toBe(false);
});
});
});
env.execute();
});
it("should be possible to get full name from a spec", function() {
var env = new j$.Env({global: { setTimeout: setTimeout }}),
topLevelSpec, nestedSpec, doublyNestedSpec;
env.describe("my tests", function() {
topLevelSpec = env.it("are sometimes top level", function() {
});
env.describe("are sometimes", function() {
nestedSpec = env.it("singly nested", function() {
});
env.describe("even", function() {
doublyNestedSpec = env.it("doubly nested", function() {
});
});
});
});
expect(topLevelSpec.getFullName()).toBe("my tests are sometimes top level.");
expect(nestedSpec.getFullName()).toBe("my tests are sometimes singly nested.");
expect(doublyNestedSpec.getFullName()).toBe("my tests are sometimes even doubly nested.");
});
it("Custom equality testers should be per spec", function(done) {
var env = new j$.Env({global: { setTimeout: setTimeout }}),
reporter = jasmine.createSpyObj('fakeReproter', [
"jasmineStarted",
"jasmineDone",
"suiteStarted",
"suiteDone",
"specStarted",
"specDone"
]);
reporter.jasmineDone.and.callFake(function() {
var firstSpecResult = reporter.specDone.calls.first().args[0],
secondSpecResult = reporter.specDone.calls.mostRecent().args[0];
expect(firstSpecResult.status).toEqual("passed");
expect(secondSpecResult.status).toEqual("failed");
done();
});
env.addReporter(reporter);
env.describe("testing custom equality testers", function() {
env.it("with a custom tester", function() {
env.addCustomEqualityTester(function(a, b) { return true; });
env.expect("a").toEqual("b");
});
env.it("without a custom tester", function() {
env.expect("a").toEqual("b");
});
});
env.execute();
});
it("Custom matchers should be per spec", function() {
var env = new j$.Env({global: { setTimeout: setTimeout }}),
matchers = {
toFoo: function() {}
},
reporter = jasmine.createSpyObj('fakeReproter', [
"jasmineStarted",
"jasmineDone",
"suiteStarted",
"suiteDone",
"specStarted",
"specDone"
]);
env.addReporter(reporter);
env.describe("testing custom matchers", function() {
env.it("with a custom matcher", function() {
env.addMatchers(matchers);
expect(env.expect().toFoo).toBeDefined();
});
env.it("without a custom matcher", function() {
expect(env.expect().toFoo).toBeUndefined();
});
});
env.execute();
});
it("Custom equality testers for toContain should be per spec", function(done) {
var env = new j$.Env({global: { setTimeout: setTimeout }}),
reporter = jasmine.createSpyObj('fakeReproter', [
"jasmineStarted",
"jasmineDone",
"suiteStarted",
"suiteDone",
"specStarted",
"specDone"
]);
reporter.jasmineDone.and.callFake(function() {
var firstSpecResult = reporter.specDone.calls.first().args[0],
secondSpecResult = reporter.specDone.calls.mostRecent().args[0];
expect(firstSpecResult.status).toEqual("passed");
expect(secondSpecResult.status).toEqual("failed");
done();
});
env.addReporter(reporter);
env.describe("testing custom equality testers", function() {
env.it("with a custom tester", function() {
env.addCustomEqualityTester(function(a, b) { return true; });
env.expect(["a"]).toContain("b");
});
env.it("without a custom tester", function() {
env.expect("a").toContain("b");
});
});
env.execute();
});
});

View File

@@ -0,0 +1,56 @@
describe("ExceptionFormatter", function() {
describe("#message", function() {
it('formats Firefox exception messages', function() {
var sampleFirefoxException = {
fileName: 'foo.js',
lineNumber: '1978',
message: 'you got your foo in my bar',
name: 'A Classic Mistake'
},
exceptionFormatter = new j$.ExceptionFormatter(),
message = exceptionFormatter.message(sampleFirefoxException);
expect(message).toEqual('A Classic Mistake: you got your foo in my bar in foo.js (line 1978)');
});
it('formats Webkit exception messages', function() {
var sampleWebkitException = {
sourceURL: 'foo.js',
line: '1978',
message: 'you got your foo in my bar',
name: 'A Classic Mistake'
},
exceptionFormatter = new j$.ExceptionFormatter(),
message = exceptionFormatter.message(sampleWebkitException);
expect(message).toEqual('A Classic Mistake: you got your foo in my bar in foo.js (line 1978)');
});
it('formats V8 exception messages', function() {
var sampleV8 = {
message: 'you got your foo in my bar',
name: 'A Classic Mistake'
},
exceptionFormatter = new j$.ExceptionFormatter(),
message = exceptionFormatter.message(sampleV8);
expect(message).toEqual('A Classic Mistake: you got your foo in my bar');
});
});
describe("#stack", function() {
it("formats stack traces from Webkit, Firefox, node.js or IE10+", function() {
if (jasmine.getEnv().ieVersion < 10 || jasmine.getEnv().safariVersion < 6) { return; }
var error;
try { throw new Error("an error") } catch(e) { error = e; }
expect(new j$.ExceptionFormatter().stack(error)).toMatch(/ExceptionFormatterSpec\.js.*\d+/)
});
it("returns null if no Error provided", function() {
expect(new j$.ExceptionFormatter().stack()).toBeNull();
});
});
});

View File

@@ -1,149 +1,64 @@
describe('Exceptions:', function() {
xdescribe('Exceptions:', function() {
var env;
beforeEach(function() {
env = new jasmine.Env();
env = new j$.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'
};
describe('with break on exception', function() {
it('should not catch the exception', function() {
env.catchExceptions(false);
var suite = env.describe('suite for break on exceptions', function() {
env.it('should break when an exception is thrown', function() {
throw new Error('I should hit a breakpoint!');
});
});
var runner = env.currentRunner();
var dont_change = 'I will never change!';
var expected = 'A Classic Mistake: you got your foo in my bar in foo.js (line 1978)';
try {
suite.execute();
dont_change = 'oops I changed';
}
catch (e) {}
expect(jasmine.util.formatException(sampleFirefoxException)).toEqual(expected);
expect(dont_change).toEqual('I will never change!');
});
});
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');
describe("with catch on exception", function() {
it('should handle exceptions thrown, but continue', function() {
var ranSecondTest = false,
suite = env.describe('Suite for handles exceptions', function () {
env.it('should be a test that fails because it throws an exception', function() {
throw new Error();
});
this.runs(function () {
this.expect(true).toEqual(true);
env.it('should be a passing test that runs after exceptions are thrown from a async test', function() {
ranSecondTest = true;
});
});
env.it('should be a passing test that runs after exceptions are thrown', 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);
});
suite.execute();
expect(ranSecondTest).toBe(true);
});
var runner = env.currentRunner();
suite.execute();
fakeTimer.tick(2500);
it("should handle exceptions thrown directly in top-level describe blocks and continue", function () {
var ranSecondDescribe = false, suite, suite2, runner = env.currentRunner();
suite = env.describe("a suite that throws an exception", function () {
env.it("is a test that should pass", function () {
this.expect(true).toEqual(true);
});
var suiteResults = suite.results();
var specResults = suiteResults.getItems();
throw new Error("top level error");
});
suite2 = env.describe("a suite that doesn't throw an exception", function () {
ranSecondDescribe = true;
});
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);
runner.execute();
expect(ranSecondDescribe).toBe(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

@@ -0,0 +1,61 @@
describe("buildExpectationResult", function() {
it("defaults to passed", function() {
var result = j$.buildExpectationResult({passed: 'some-value'});
expect(result.passed).toBe('some-value');
});
it("message defaults to Passed for passing specs", function() {
var result = j$.buildExpectationResult({passed: true, message: 'some-value'});
expect(result.message).toBe('Passed.');
});
it("message returns the message for failing expecations", function() {
var result = j$.buildExpectationResult({passed: false, message: 'some-value'});
expect(result.message).toBe('some-value');
});
it("delegates message formatting to the provided formatter if there was an Error", function() {
var fakeError = {message: 'foo'},
messageFormatter = jasmine.createSpy("exception message formatter").and.callReturn(fakeError.message);
var result = j$.buildExpectationResult(
{
passed: false,
error: fakeError,
messageFormatter: messageFormatter
});
expect(messageFormatter).toHaveBeenCalledWith(fakeError);
expect(result.message).toEqual('foo');
});
it("delegates stack formatting to the provided formatter if there was an Error", function() {
var fakeError = {stack: 'foo'},
stackFormatter = jasmine.createSpy("stack formatter").and.callReturn(fakeError.stack);
var result = j$.buildExpectationResult(
{
passed: false,
error: fakeError,
stackFormatter: stackFormatter
});
expect(stackFormatter).toHaveBeenCalledWith(fakeError);
expect(result.stack).toEqual('foo');
});
it("matcherName returns passed matcherName", function() {
var result = j$.buildExpectationResult({matcherName: 'some-value'});
expect(result.matcherName).toBe('some-value');
});
it("expected returns passed expected", function() {
var result = j$.buildExpectationResult({expected: 'some-value'});
expect(result.expected).toBe('some-value');
});
it("actual returns passed actual", function() {
var result = j$.buildExpectationResult({actual: 'some-value'});
expect(result.actual).toBe('some-value');
});
});

View File

@@ -0,0 +1,320 @@
describe("Expectation", function() {
it(".addMatchers makes matchers available to any expectation", function() {
var matchers = {
toFoo: function() {},
toBar: function() {}
},
expectation;
j$.Expectation.addMatchers(matchers);
expectation = new j$.Expectation({});
expect(expectation.toFoo).toBeDefined();
expect(expectation.toBar).toBeDefined();
});
it(".addCoreMatchers makes matchers available to any expectation", function() {
var coreMatchers = {
toQuux: function() {}
},
expectation;
j$.Expectation.addCoreMatchers(coreMatchers);
expectation = new j$.Expectation({});
expect(expectation.toQuux).toBeDefined();
});
it(".resetMatchers should keep only core matchers", function() {
var matchers = {
toFoo: function() {}
},
coreMatchers = {
toQuux: function() {}
},
expectation;
j$.Expectation.addCoreMatchers(coreMatchers);
j$.Expectation.addMatchers(matchers);
j$.Expectation.resetMatchers();
expectation = new j$.Expectation({});
expect(expectation.toQuux).toBeDefined();
expect(expectation.toFoo).toBeUndefined();
});
it("Factory builds an expectaion/negative expectation", function() {
var builtExpectation = j$.Expectation.Factory();
expect(builtExpectation instanceof j$.Expectation).toBe(true);
expect(builtExpectation.not instanceof j$.Expectation).toBe(true);
expect(builtExpectation.not.isNot).toBe(true);
});
it("wraps matchers's compare functions, passing in matcher dependencies", function() {
var fakeCompare = function() { return { pass: true }; },
matcherFactory = jasmine.createSpy("matcher").and.callReturn({ compare: fakeCompare }),
matchers = {
toFoo: matcherFactory
},
util = {},
customEqualityTesters = ['a'],
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
j$.Expectation.addMatchers(matchers);
expectation = new j$.Expectation({
util: util,
customEqualityTesters: customEqualityTesters,
actual: "an actual",
addExpectationResult: addExpectationResult
});
expectation.toFoo("hello");
expect(matcherFactory).toHaveBeenCalledWith(util, customEqualityTesters)
});
it("wraps matchers's compare functions, passing the actual and expected", function() {
var fakeCompare = jasmine.createSpy('fake-compare').and.callReturn({pass: true}),
matchers = {
toFoo: function() {
return {
compare: fakeCompare
};
}
},
util = {
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
j$.Expectation.addMatchers(matchers);
expectation = new j$.Expectation({
util: util,
actual: "an actual",
addExpectationResult: addExpectationResult
});
expectation.toFoo("hello");
expect(fakeCompare).toHaveBeenCalledWith("an actual", "hello");
});
it("reports a passing result to the spec when the comparison passes", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: true }; }
};
}
},
util = {
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
j$.Expectation.addMatchers(matchers);
expectation = new j$.Expectation({
matchers: matchers,
util: util,
actual: "an actual",
addExpectationResult: addExpectationResult
});
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(true, {
matcherName: "toFoo",
passed: true,
message: "",
expected: "hello",
actual: "an actual"
});
});
it("reports a failing result to the spec when the comparison fails", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: false }; }
};
}
},
util = {
buildFailureMessage: function() { return ""; }
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
j$.Expectation.addMatchers(matchers);
expectation = new j$.Expectation({
matchers: matchers,
util: util,
actual: "an actual",
addExpectationResult: addExpectationResult
});
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
passed: false,
expected: "hello",
actual: "an actual",
message: ""
});
});
it("reports a failing result and a custom fail message to the spec when the comparison fails", function() {
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: false,
message: "I am a custom message"
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
expectation;
j$.Expectation.addMatchers(matchers);
expectation = new j$.Expectation({
matchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult
});
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
passed: false,
expected: "hello",
actual: "an actual",
message: "I am a custom message"
});
});
it("reports a passing result to the spec when the comparison fails for a negative expectation", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: false }; }
};
}
},
util = {
buildFailureMessage: function() { return ""; }
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
actual = "an actual",
expectation;
j$.Expectation.addMatchers(matchers);
expectation = new j$.Expectation({
matchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(true, {
matcherName: "toFoo",
passed: true,
message: "",
expected: "hello",
actual: actual
});
});
it("reports a failing result to the spec when the comparison passes for a negative expectation", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: true }; }
};
}
},
util = {
buildFailureMessage: function() { return "default messge"; }
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
actual = "an actual",
expectation;
j$.Expectation.addMatchers(matchers);
expectation = new j$.Expectation({
matchers: matchers,
actual: "an actual",
util: util,
addExpectationResult: addExpectationResult,
isNot: true
});
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
passed: false,
expected: "hello",
actual: actual,
message: "default messge"
});
});
it("reports a failing result and a custom fail message to the spec when the comparison passes for a negative expectation", function() {
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: true,
message: "I am a custom message"
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
actual = "an actual",
expectation;
j$.Expectation.addMatchers(matchers);
expectation = new j$.Expectation({
matchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
passed: false,
expected: "hello",
actual: actual,
message: "I am a custom message"
});
});
});

View File

@@ -1,11 +1,11 @@
describe('jasmine.jsApiReporter', function() {
describe('results', function () {
var reporter, spec1, spec2, spec3, expectedSpec1Results, expectedSpec2Results;
xdescribe('JsApiReporter (integration specs)', function() {
describe('results', function() {
var reporter, spec1, spec2;
var env;
var suite, nestedSuite, nestedSpec;
beforeEach(function() {
env = new jasmine.Env();
env = new j$.Env();
env.updateInterval = 0;
suite = env.describe("top-level suite", function() {
@@ -24,34 +24,24 @@ describe('jasmine.jsApiReporter', function() {
});
});
spec3 = env.it("spec 3", function() {
this.log('some debug message');
});
});
reporter = new jasmine.JsApiReporter();
reporter = new j$.JsApiReporter({});
env.addReporter(reporter);
env.execute();
expectedSpec1Results = {
messages: spec1.results().getItems(),
result: "passed"
};
expectedSpec2Results = {
messages: spec2.results().getItems(),
result: "failed"
};
});
it('resultForSpec() should return the result for the given spec', function () {
expect(reporter.resultsForSpec(spec1.id)).toEqual(expectedSpec1Results);
expect(reporter.resultsForSpec(spec2.id)).toEqual(expectedSpec2Results);
});
it('results() should return a hash of all results, indexed by spec id', function () {
expect(reporter.results()[spec1.id]).toEqual(expectedSpec1Results);
expect(reporter.results()[spec2.id]).toEqual(expectedSpec2Results);
it('results() should return a hash of all results, indexed by spec id', function() {
var expectedSpec1Results = {
result: "passed"
},
expectedSpec2Results = {
result: "failed"
};
expect(reporter.results()[spec1.id].result).toEqual('passed');
expect(reporter.results()[spec2.id].result).toEqual('failed');
});
it("should return nested suites as children of their parents", function() {
@@ -65,7 +55,6 @@ describe('jasmine.jsApiReporter', function() {
{ id: 2, name: 'nested spec', type: 'spec', children: [ ] }
]
},
{ id: 3, name: 'spec 3', type: 'spec', children: [ ] }
]
}
]);
@@ -76,12 +65,7 @@ describe('jasmine.jsApiReporter', function() {
var result = reporter.results()[spec1.id];
var summarizedResult = reporter.summarizeResult_(result);
expect(summarizedResult.result).toEqual('passed');
expect(summarizedResult.messages.length).toEqual(1);
expect(summarizedResult.messages[0].message).toEqual(result.messages[0].message);
expect(summarizedResult.messages[0].passed).toBeTruthy();
expect(summarizedResult.messages[0].type).toEqual('expect');
expect(summarizedResult.messages[0].text).toBeUndefined();
expect(summarizedResult.messages[0].trace.stack).toBeUndefined();
expect(summarizedResult.messages.length).toEqual(0);
});
it("should have a stack trace for failing specs", function() {
@@ -91,13 +75,141 @@ describe('jasmine.jsApiReporter', function() {
expect(summarizedResult.messages[0].trace.stack).toEqual(result.messages[0].trace.stack);
});
it("should have messages for specs with messages", function() {
var result = reporter.results()[spec3.id];
var summarizedResult = reporter.summarizeResult_(result);
expect(summarizedResult.result).toEqual('passed');
expect(summarizedResult.messages[0].type).toEqual('log');
expect(summarizedResult.messages[0].text).toEqual('some debug message');
});
});
});
describe("JsApiReporter", function() {
it("knows when a full environment is started", function() {
var reporter = new j$.JsApiReporter({});
expect(reporter.started).toBe(false);
expect(reporter.finished).toBe(false);
reporter.jasmineStarted();
expect(reporter.started).toBe(true);
expect(reporter.finished).toBe(false);
});
it("knows when a full environment is done", function() {
var reporter = new j$.JsApiReporter({});
expect(reporter.started).toBe(false);
expect(reporter.finished).toBe(false);
reporter.jasmineStarted();
reporter.jasmineDone({});
expect(reporter.finished).toBe(true);
});
it("defaults to 'loaded' status", function() {
var reporter = new j$.JsApiReporter({});
expect(reporter.status()).toEqual('loaded');
});
it("reports 'started' when Jasmine has started", function() {
var reporter = new j$.JsApiReporter({});
reporter.jasmineStarted();
expect(reporter.status()).toEqual('started');
});
it("reports 'done' when Jasmine is done", function() {
var reporter = new j$.JsApiReporter({});
reporter.jasmineDone({});
expect(reporter.status()).toEqual('done');
});
it("tracks a suite", function() {
var reporter = new j$.JsApiReporter({});
reporter.suiteStarted({
id: 123,
description: "A suite"
});
var suites = reporter.suites();
expect(suites).toEqual({123: {id: 123, description: "A suite"}});
reporter.suiteDone({
id: 123,
description: "A suite",
status: 'passed'
});
expect(suites).toEqual({123: {id: 123, description: "A suite", status: 'passed'}});
});
describe("#specResults", function() {
var reporter, specResult1, specResult2;
beforeEach(function() {
reporter = new j$.JsApiReporter({});
specResult1 = {
id: 1,
description: "A spec"
};
specResult2 = {
id: 2,
description: "Another spec"
};
reporter.specDone(specResult1);
reporter.specDone(specResult2);
});
it("should return a slice of results", function() {
expect(reporter.specResults(0, 1)).toEqual([specResult1]);
expect(reporter.specResults(1, 1)).toEqual([specResult2]);
});
describe("when the results do not exist", function() {
it("should return a slice of shorter length", function() {
expect(reporter.specResults(0, 3)).toEqual([specResult1, specResult2]);
expect(reporter.specResults(2, 3)).toEqual([]);
});
});
});
});
describe("#executionTime", function() {
it("should start the timer when jasmine starts", function() {
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
reporter = new j$.JsApiReporter({
timer: timerSpy
});
reporter.jasmineStarted();
expect(timerSpy.start).toHaveBeenCalled();
});
it("should return the time it took the specs to run, in ms", function() {
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
reporter = new j$.JsApiReporter({
timer: timerSpy
});
timerSpy.elapsed.and.callReturn(1000);
reporter.jasmineDone();
expect(reporter.executionTime()).toEqual(1000);
});
describe("when the specs haven't finished being run", function() {
it("should return undefined", function() {
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
reporter = new j$.JsApiReporter({
timer: timerSpy
});
expect(reporter.executionTime()).toBeUndefined();
});
});
});
});

View File

@@ -1,838 +0,0 @@
describe("jasmine.Matchers", 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];
}
function catchException(fn) {
try {
fn.call();
} catch (e) {
return e;
}
throw new Error("expected function to throw an exception");
}
it("toEqual with primitives, objects, dates, etc.", function() {
expect(match(true).toEqual(true)).toPass();
expect(match({foo:'bar'}).toEqual(null)).toFail();
var functionA = function() {
return 'hi';
};
var functionB = function() {
return 'hi';
};
expect(match({foo:functionA}).toEqual({foo:functionB})).toFail();
expect(match({foo:functionA}).toEqual({foo:functionA})).toPass();
expect((match(false).toEqual(true))).toFail();
var circularGraph = {};
circularGraph.referenceToSelf = circularGraph;
expect((match(circularGraph).toEqual(circularGraph))).toPass();
expect((match(new Date(2008, 1, 3, 15, 17, 19, 1234)).toEqual(new Date(2009, 1, 3, 15, 17, 19, 1234)))).toFail();
expect((match(new Date(2008, 1, 3, 15, 17, 19, 1234)).toEqual(new Date(2008, 1, 3, 15, 17, 19, 1234)))).toPass();
expect(match(true).toNotEqual(false)).toPass();
expect((match(true).toNotEqual(true))).toFail();
expect((match(['a', 'b']).toEqual(['a', jasmine.undefined]))).toFail();
expect((match(['a', 'b']).toEqual(['a', 'b', jasmine.undefined]))).toFail();
expect((match("cat").toEqual("cat"))).toPass();
expect((match("cat").toNotEqual("cat"))).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 to build an Expectation Result", function() {
var actual = 'a';
var matcher = match(actual);
var expected = 'b';
matcher.toEqual(expected);
var result = lastResult();
expect(result.matcherName).toEqual("toEqual");
expect(result.passed()).toFail();
expect(result.message).toMatch(jasmine.pp(actual));
expect(result.message).toMatch(jasmine.pp(expected));
expect(result.expected).toEqual(expected);
expect(result.actual).toEqual(actual);
});
it("toNotEqual to build an Expectation Result", function() {
var str = 'a';
var matcher = match(str);
matcher.toNotEqual(str);
var result = lastResult();
expect(result.matcherName).toEqual("toNotEqual");
expect(result.passed()).toFail();
expect(result.message).toMatch(jasmine.pp(str));
expect(result.message).toMatch('not');
expect(result.expected).toEqual(str);
expect(result.actual).toEqual(str);
});
it('toBe should return true only if the expected and actual items === each other', function() {
var a = {};
var b = {};
//noinspection UnnecessaryLocalVariableJS
var c = a;
expect((match(a).toBe(b))).toFail();
expect((match(a).toBe(a))).toPass();
expect((match(a).toBe(c))).toPass();
expect((match(a).toNotBe(b))).toPass();
expect((match(a).toNotBe(a))).toFail();
expect((match(a).toNotBe(c))).toFail();
});
it("toBe to build an ExpectationResult", function() {
var expected = 'b';
var actual = 'a';
var matcher = match(actual);
matcher.toBe(expected);
var result = lastResult();
expect(result.matcherName).toEqual("toBe");
expect(result.passed()).toFail();
expect(result.message).toMatch(jasmine.pp(actual));
expect(result.message).toMatch(jasmine.pp(expected));
expect(result.expected).toEqual(expected);
expect(result.actual).toEqual(actual);
});
it("toNotBe to build an ExpectationResult", function() {
var str = 'a';
var matcher = match(str);
matcher.toNotBe(str);
var result = lastResult();
expect(result.matcherName).toEqual("toNotBe");
expect(result.passed()).toFail();
expect(result.message).toMatch(str);
expect(result.expected).toEqual(str);
expect(result.actual).toEqual(str);
});
it("toMatch and #toNotMatch should perform regular expression matching on strings", function() {
expect((match('foobarbel').toMatch(/bar/))).toPass();
expect((match('foobazbel').toMatch(/bar/))).toFail();
expect((match('foobarbel').toMatch("bar"))).toPass();
expect((match('foobazbel').toMatch("bar"))).toFail();
expect((match('foobarbel').toNotMatch(/bar/))).toFail();
expect((match('foobazbel').toNotMatch(/bar/))).toPass();
expect((match('foobarbel').toNotMatch("bar"))).toFail();
expect((match('foobazbel').toNotMatch("bar"))).toPass();
});
it("toMatch w/ RegExp to build an ExpectationResult", function() {
var actual = 'a';
var matcher = match(actual);
var expected = /b/;
matcher.toMatch(expected);
var result = lastResult();
expect(result.matcherName).toEqual("toMatch");
expect(result.passed()).toFail();
expect(result.message).toMatch(jasmine.pp(actual));
expect(result.message).toMatch(expected.toString());
expect(result.expected).toEqual(expected);
expect(result.actual).toEqual(actual);
});
it("toMatch w/ String to build an ExpectationResult", function() {
var actual = 'a';
var matcher = match(actual);
var expected = 'b';
matcher.toMatch(expected);
var result = lastResult();
expect(result.matcherName).toEqual("toMatch");
expect(result.passed()).toFail();
expect(result.message).toEqual("Expected 'a' to match 'b'.");
expect(result.expected).toEqual(expected);
expect(result.actual).toEqual(actual);
});
it("toNotMatch w/ RegExp to build an ExpectationResult", function() {
var actual = 'a';
var matcher = match(actual);
var expected = /a/;
matcher.toNotMatch(expected);
var result = lastResult();
expect(result.matcherName).toEqual("toNotMatch");
expect(result.passed()).toFail();
expect(result.message).toEqual("Expected 'a' to not match /a/.");
expect(result.expected).toEqual(expected);
expect(result.actual).toEqual(actual);
});
it("toNotMatch w/ String to build an ExpectationResult", function() {
var str = 'a';
var matcher = match(str);
matcher.toNotMatch(str);
var result = lastResult();
expect(result.matcherName).toEqual("toNotMatch");
expect(result.passed()).toFail();
expect(result.message).toEqual("Expected 'a' to not match 'a'.");
expect(result.expected).toEqual(str);
expect(result.actual).toEqual(str);
});
it("toBeDefined", function() {
expect(match('foo').toBeDefined()).toPass();
expect(match(jasmine.undefined).toBeDefined()).toFail();
});
it("toBeDefined to build an ExpectationResult", function() {
var matcher = match(jasmine.undefined);
matcher.toBeDefined();
var result = lastResult();
expect(result.matcherName).toEqual("toBeDefined");
expect(result.passed()).toFail();
expect(result.message).toEqual('Expected undefined to be defined.');
expect(result.actual).toEqual(jasmine.undefined);
});
it("toBeUndefined", function() {
expect(match('foo').toBeUndefined()).toFail();
expect(match(jasmine.undefined).toBeUndefined()).toPass();
});
it("toBeNull", function() {
expect(match(null).toBeNull()).toPass();
expect(match(jasmine.undefined).toBeNull()).toFail();
expect(match("foo").toBeNull()).toFail();
});
it("toBeNull w/ String to build an ExpectationResult", function() {
var actual = 'a';
var matcher = match(actual);
matcher.toBeNull();
var result = lastResult();
expect(result.matcherName).toEqual("toBeNull");
expect(result.passed()).toFail();
expect(result.message).toMatch(jasmine.pp(actual));
expect(result.message).toMatch('null');
expect(result.actual).toEqual(actual);
});
it("toBeNull w/ Object to build an ExpectationResult", function() {
var actual = {a: 'b'};
var matcher = match(actual);
matcher.toBeNull();
var result = lastResult();
expect(result.matcherName).toEqual("toBeNull");
expect(result.passed()).toFail();
expect(result.message).toMatch(jasmine.pp(actual));
expect(result.message).toMatch('null');
expect(result.actual).toEqual(actual);
});
it("toBeFalsy", function() {
expect(match(false).toBeFalsy()).toPass();
expect(match(true).toBeFalsy()).toFail();
expect(match(jasmine.undefined).toBeFalsy()).toPass();
expect(match(0).toBeFalsy()).toPass();
expect(match("").toBeFalsy()).toPass();
});
it("toBeFalsy to build an ExpectationResult", function() {
var actual = 'a';
var matcher = match(actual);
matcher.toBeFalsy();
var result = lastResult();
expect(result.matcherName).toEqual("toBeFalsy");
expect(result.passed()).toFail();
expect(result.message).toMatch(jasmine.pp(actual));
expect(result.message).toMatch('falsy');
expect(result.actual).toEqual(actual);
});
it("toBeTruthy", function() {
expect(match(false).toBeTruthy()).toFail();
expect(match(true).toBeTruthy()).toPass();
expect(match(jasmine.undefined).toBeTruthy()).toFail();
expect(match(0).toBeTruthy()).toFail();
expect(match("").toBeTruthy()).toFail();
expect(match("hi").toBeTruthy()).toPass();
expect(match(5).toBeTruthy()).toPass();
expect(match({foo: 1}).toBeTruthy()).toPass();
});
it("toBeTruthy to build an ExpectationResult", function() {
var matcher = match(false);
matcher.toBeTruthy();
var result = lastResult();
expect(result.matcherName).toEqual("toBeTruthy");
expect(result.passed()).toFail();
expect(result.message).toEqual("Expected false to be truthy.");
expect(result.actual).toFail();
});
it("toEqual", function() {
expect(match(jasmine.undefined).toEqual(jasmine.undefined)).toPass();
expect(match({foo:'bar'}).toEqual({foo:'bar'})).toPass();
expect(match("foo").toEqual({bar: jasmine.undefined})).toFail();
expect(match({foo: jasmine.undefined}).toEqual("goo")).toFail();
expect(match({foo: {bar :jasmine.undefined}}).toEqual("goo")).toFail();
});
it("toEqual with jasmine.any()", function() {
expect(match("foo").toEqual(jasmine.any(String))).toPass();
expect(match(3).toEqual(jasmine.any(Number))).toPass();
expect(match("foo").toEqual(jasmine.any(Function))).toFail();
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(["foo", "goo"]).toEqual(["foo", jasmine.any(String)])).toPass();
expect(match(
function() {
}).toEqual(jasmine.any(Function))).toPass();
expect(match(["a", function() {
}]).toEqual(["a", jasmine.any(Function)])).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();
expect(match({foo: {bar:'baz'}, quux:'corge'}).toEqual({foo:{bar:'baz'}, quux:'corge'})).toPass();
var circularObject = {};
var secondCircularObject = {};
circularObject.field = circularObject;
secondCircularObject.field = secondCircularObject;
expect(match(circularObject).toEqual(secondCircularObject)).toPass();
});
it("toNotEqual as slightly surprising behavior, but is it intentional?", function() {
expect(match({x:"x", y:"y", z:"w"}).toNotEqual({x:"x", y:"y", z:"z"})).toPass();
expect(match({x:"x", y:"y", w:"z"}).toNotEqual({x:"x", y:"y", z:"z"})).toPass();
expect(match({x:"x", y:"y", z:"z"}).toNotEqual({w: "w", x:"x", y:"y", z:"z"})).toPass();
expect(match({w: "w", x:"x", y:"y", z:"z"}).toNotEqual({x:"x", y:"y", z:"z"})).toPass();
});
it("toEqual handles arrays", function() {
expect(match([1, "A"]).toEqual([1, "A"])).toPass();
});
it("toContain and toNotContain", function() {
expect(match('ABC').toContain('A')).toPass();
expect(match('ABC').toContain('X')).toFail();
expect(match(['A', 'B', 'C']).toContain('A')).toPass();
expect(match(['A', 'B', 'C']).toContain('F')).toFail();
expect(match(['A', 'B', 'C']).toNotContain('F')).toPass();
expect(match(['A', 'B', 'C']).toNotContain('A')).toFail();
expect(match(['A', {some:'object'}, 'C']).toContain({some:'object'})).toPass();
expect(match(['A', {some:'object'}, 'C']).toContain({some:'other object'})).toFail();
});
it("toContain to build an ExpectationResult", function() {
var actual = ['a','b','c'];
var matcher = match(actual);
var expected = 'x';
matcher.toContain(expected);
var result = lastResult();
expect(result.matcherName).toEqual("toContain");
expect(result.passed()).toFail();
expect(result.message).toMatch(jasmine.pp(actual));
expect(result.message).toMatch('contain');
expect(result.message).toMatch(jasmine.pp(expected));
expect(result.actual).toEqual(actual);
expect(result.expected).toEqual(expected);
});
it("toNotContain to build an ExpectationResult", function() {
var actual = ['a','b','c'];
var matcher = match(actual);
var expected = 'b';
matcher.toNotContain(expected);
var result = lastResult();
expect(result.matcherName).toEqual("toNotContain");
expect(result.passed()).toFail();
expect(result.message).toMatch(jasmine.pp(actual));
expect(result.message).toMatch('not contain');
expect(result.message).toMatch(jasmine.pp(expected));
expect(result.actual).toEqual(actual);
expect(result.expected).toEqual(expected);
});
it("toBeLessThan should pass if actual is less than expected", function() {
expect(match(37).toBeLessThan(42)).toPass();
expect(match(37).toBeLessThan(-42)).toFail();
expect(match(37).toBeLessThan(37)).toFail();
});
it("toBeLessThan to build an ExpectationResult", function() {
var actual = 3;
var matcher = match(actual);
var expected = 1;
matcher.toBeLessThan(expected);
var result = lastResult();
expect(result.matcherName).toEqual("toBeLessThan");
expect(result.passed()).toFail();
expect(result.message).toMatch(jasmine.pp(actual) + ' to be less than');
expect(result.message).toMatch(jasmine.pp(expected));
expect(result.actual).toEqual(actual);
expect(result.expected).toEqual(expected);
});
it("toBeGreaterThan should pass if actual is greater than expected", function() {
expect(match(37).toBeGreaterThan(42)).toFail();
expect(match(37).toBeGreaterThan(-42)).toPass();
expect(match(37).toBeGreaterThan(37)).toFail();
});
it("toBeGreaterThan to build an ExpectationResult", function() {
var actual = 1;
var matcher = match(actual);
var expected = 3;
matcher.toBeGreaterThan(expected);
var result = lastResult();
expect(result.matcherName).toEqual("toBeGreaterThan");
expect(result.passed()).toFail();
expect(result.message).toMatch(jasmine.pp(actual) + ' to be greater than');
expect(result.message).toMatch(jasmine.pp(expected));
expect(result.actual).toEqual(actual);
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("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;
beforeEach(function() {
throwingFn = function() {
throw new Error("Fake Error");
};
});
it("should match any exception", function() {
expect(match(throwingFn).toThrow()).toPass();
});
it("should match exceptions specified by message", function() {
expect(match(throwingFn).toThrow("Fake Error")).toPass();
expect(match(throwingFn).toThrow("Other Error")).toFail();
expect(lastResult().message).toMatch("Other Error");
});
it("should match exceptions specified by Error", function() {
expect(match(throwingFn).toThrow(new Error("Fake Error"))).toPass();
expect(match(throwingFn).toThrow(new Error("Other Error"))).toFail();
expect(lastResult().message).toMatch("Other Error");
});
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/);
});
it("should match exceptions specified by message", function() {
expect(match(throwingFn).not.toThrow("Fake Error")).toFail();
// expect(lastResult().message).toMatch(/Expected function not to throw Fake Error./);
expect(match(throwingFn).not.toThrow("Other Error")).toPass();
});
it("should match exceptions specified by Error", function() {
expect(match(throwingFn).not.toThrow(new Error("Fake Error"))).toFail();
// expect(lastResult().message).toMatch("Other Error");
expect(match(throwingFn).not.toThrow(new Error("Other Error"))).toPass();
});
});
});
describe("when actual is not a function", function() {
it("should fail with an exception", function() {
var exception = catchException(function() {
match('not-a-function').toThrow();
});
expect(exception).toBeDefined();
expect(exception.message).toEqual('Actual is not a function');
});
describe("and matcher is inverted with .not", function() {
it("should fail with an exception", function() {
var exception = catchException(function() {
match('not-a-function').not.toThrow();
});
expect(exception).toBeDefined();
expect(exception.message).toEqual('Actual is not a 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(lastResult().message).toEqual('Expected function to throw an exception.');
});
});
});
describe(".not.matcher", function() {
it("should invert the sense of any matcher", function() {
expect(match(37).not.toBeGreaterThan(42)).toPass();
expect(match(42).not.toBeGreaterThan(37)).toFail();
expect(match("abc").not.toEqual("def")).toPass();
expect(match("abc").not.toEqual("abc")).toFail();
});
it("should provide an inverted default message", function() {
match(37).not.toBeGreaterThan(42);
expect(lastResult().message).toEqual("Passed.");
match(42).not.toBeGreaterThan(37);
expect(lastResult().message).toEqual("Expected 42 not to be greater than 37.");
});
it("should use the second message when the matcher sets an array of custom messages", function() {
spec.addMatchers({
custom: function() {
this.message = function() {
return ['Expected it was called.', 'Expected it wasn\'t called.'];
};
return this.actual;
}
});
match(true).custom();
expect(lastResult().message).toEqual("Passed.");
match(false).custom();
expect(lastResult().message).toEqual("Expected it was called.");
match(true).not.custom();
expect(lastResult().message).toEqual("Expected it wasn't called.");
match(false).not.custom();
expect(lastResult().message).toEqual("Passed.");
});
});
describe("spy matchers >>", function() {
var TestClass;
beforeEach(function() {
TestClass = {
normalFunction: function() {
},
spyFunction: jasmine.createSpy("My spy")
};
});
function shouldThrowAnExceptionWhenInvokedOnANonSpy(methodName) {
return 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({some:'object'})[methodName]();
}).toThrow('Expected a spy, but got { some : \'object\' }.');
expect(
function() {
match("<b>")[methodName]();
}).toThrow('Expected a spy, but got \'<b>\'.');
};
}
describe("toHaveBeenCalled", function() {
it("should pass if the spy was called", function() {
expect(match(TestClass.spyFunction).toHaveBeenCalled()).toFail();
TestClass.spyFunction();
expect(match(TestClass.spyFunction).toHaveBeenCalled()).toPass();
});
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');
});
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('toHaveBeenCalled'));
});
describe("wasCalled", function() {
it("should alias toHaveBeenCalled", function() {
spyOn(TestClass, 'normalFunction');
TestClass.normalFunction();
expect(TestClass.normalFunction).wasCalled();
});
});
describe("wasNotCalled", function() {
it("should pass iff the spy was not called", function() {
expect(match(TestClass.spyFunction).wasNotCalled()).toPass();
TestClass.spyFunction();
expect(match(TestClass.spyFunction).wasNotCalled()).toFail();
});
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');
});
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('wasNotCalled'));
});
describe("toHaveBeenCalledWith", function() {
it('toHaveBeenCalledWith should return true if it was called with the expected args', function() {
TestClass.spyFunction('a', 'b', 'c');
expect(match(TestClass.spyFunction).toHaveBeenCalledWith('a', 'b', 'c')).toPass();
});
it('should return false if it was not called with the expected args', function() {
TestClass.spyFunction('a', 'b', 'c');
var expected = match(TestClass.spyFunction);
expect(expected.toHaveBeenCalledWith('c', 'b', 'a')).toFail();
var result = lastResult();
expect(result.passed()).toFail();
expect(result.expected).toEqual(['c', 'b', 'a']);
expect(result.actual.mostRecentCall.args).toEqual(['a', 'b', 'c']);
expect(result.message).toContain(jasmine.pp(result.expected));
expect(result.message).toContain(jasmine.pp(result.actual.mostRecentCall.args));
});
it('should return false if it was not called', function() {
var expected = match(TestClass.spyFunction);
expect(expected.toHaveBeenCalledWith('c', 'b', 'a')).toFail();
var result = lastResult();
expect(result.passed()).toFail();
expect(result.expected).toEqual(['c', 'b', 'a']);
expect(result.actual.argsForCall).toEqual([]);
expect(result.message).toContain(jasmine.pp(result.expected));
});
it('should allow matches across multiple calls', function() {
TestClass.spyFunction('a', 'b', 'c');
TestClass.spyFunction('d', 'e', 'f');
var expected = match(TestClass.spyFunction);
expect(expected.toHaveBeenCalledWith('a', 'b', 'c')).toPass();
expect(expected.toHaveBeenCalledWith('d', 'e', 'f')).toPass();
expect(expected.toHaveBeenCalledWith('x', 'y', 'z')).toFail();
});
it("should return a decent message", function() {
TestClass.spyFunction('a', 'b', 'c');
TestClass.spyFunction('d', 'e', 'f');
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 was called with [ [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] ]");
});
it("should return a decent message when inverted", function() {
TestClass.spyFunction('a', 'b', 'c');
TestClass.spyFunction('d', 'e', 'f');
var expected = match(TestClass.spyFunction);
expect(expected.not.toHaveBeenCalledWith('a', 'b', 'c')).toFail();
expect(lastResult().message).toEqual("Expected spy My spy not to have been called with [ 'a', 'b', 'c' ] but was called with [ [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] ]");
});
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('toHaveBeenCalledWith'));
describe("to build an ExpectationResult", function () {
beforeEach(function() {
var currentSuite;
var spec;
currentSuite = env.describe('default current suite', function() {
spec = env.it();
}, spec);
TestClass = { someFunction: function(a, b) {
} };
spec.spyOn(TestClass, 'someFunction');
});
it("should should handle the case of a spy", function() {
TestClass.someFunction('a', 'c');
var matcher = match(TestClass.someFunction);
matcher.toHaveBeenCalledWith('a', 'b');
var result = lastResult();
expect(result.matcherName).toEqual("toHaveBeenCalledWith");
expect(result.passed()).toFail();
expect(result.message).toContain(jasmine.pp(['a', 'b']));
expect(result.message).toContain(jasmine.pp(['a', 'c']));
expect(result.actual).toEqual(TestClass.someFunction);
expect(result.expected).toEqual(['a','b']);
});
});
});
describe("wasCalledWith", function() {
it("should alias toHaveBeenCalledWith", function() {
spyOn(TestClass, 'normalFunction');
TestClass.normalFunction(123);
expect(TestClass.normalFunction).wasCalledWith(123);
});
});
describe("wasNotCalledWith", function() {
it('should return true if the spy was NOT called with the expected args', function() {
TestClass.spyFunction('a', 'b', 'c');
expect(match(TestClass.spyFunction).wasNotCalledWith('c', 'b', 'a')).toPass();
});
it('should return false if it WAS called with the expected args', function() {
TestClass.spyFunction('a', 'b', 'c');
var expected = match(TestClass.spyFunction);
expect(expected.wasNotCalledWith('a', 'b', 'c')).toFail();
var result = lastResult();
expect(result.passed()).toFail();
expect(result.expected).toEqual(['a', 'b', 'c']);
expect(result.actual.mostRecentCall.args).toEqual(['a', 'b', 'c']);
expect(result.message).toContain(jasmine.pp(result.expected));
});
it('should return true if it was not called', function() {
var expected = match(TestClass.spyFunction);
expect(expected.wasNotCalledWith('c', 'b', 'a')).toPass();
});
it('should allow matches across multiple calls', function() {
var expected = match(TestClass.spyFunction);
TestClass.spyFunction('a', 'b', 'c');
TestClass.spyFunction('d', 'e', 'f');
expect(expected.wasNotCalledWith('a', 'b', 'c')).toFail();
expect(expected.wasNotCalledWith('d', 'e', 'f')).toFail();
expect(expected.wasNotCalledWith('x', 'y', 'z')).toPass();
});
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('wasNotCalledWith'));
});
});
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

@@ -1,38 +0,0 @@
describe("MockClock", function () {
beforeEach(function() {
jasmine.Clock.useMock();
});
describe("setTimeout", function () {
it("should mock the clock when useMock is in a beforeEach", function() {
var expected = false;
setTimeout(function() {
expected = true;
}, 30000);
expect(expected).toBe(false);
jasmine.Clock.tick(30001);
expect(expected).toBe(true);
});
});
describe("setInterval", function () {
it("should mock the clock when useMock is in a beforeEach", function() {
var interval = 0;
setInterval(function() {
interval++;
}, 30000);
expect(interval).toEqual(0);
jasmine.Clock.tick(30001);
expect(interval).toEqual(1);
jasmine.Clock.tick(30001);
expect(interval).toEqual(2);
jasmine.Clock.tick(1);
expect(interval).toEqual(2);
});
});
it("shouldn't complain if you call jasmine.Clock.useMock() more than once", function() {
jasmine.Clock.useMock();
});
});

View File

@@ -1,45 +0,0 @@
describe("jasmine.MultiReporter", function() {
var multiReporter, fakeReporter1, fakeReporter2;
beforeEach(function() {
multiReporter = new jasmine.MultiReporter();
fakeReporter1 = jasmine.createSpyObj("fakeReporter1", ["reportSpecResults"]);
fakeReporter2 = jasmine.createSpyObj("fakeReporter2", ["reportSpecResults", "reportRunnerStarting"]);
multiReporter.addReporter(fakeReporter1);
multiReporter.addReporter(fakeReporter2);
});
it("should support all the method calls that jasmine.Reporter supports", function() {
var delegate = {};
multiReporter.addReporter(delegate);
this.addMatchers({
toDelegateMethod: function(methodName) {
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";
}
});
expect(multiReporter).toDelegateMethod('reportRunnerStarting');
expect(multiReporter).toDelegateMethod('reportRunnerResults');
expect(multiReporter).toDelegateMethod('reportSuiteResults');
expect(multiReporter).toDelegateMethod('reportSpecStarting');
expect(multiReporter).toDelegateMethod('reportSpecResults');
expect(multiReporter).toDelegateMethod('log');
});
it("should delegate to any and all subreporters", function() {
multiReporter.reportSpecResults('blah', 'foo');
expect(fakeReporter1.reportSpecResults).toHaveBeenCalledWith('blah', 'foo');
expect(fakeReporter2.reportSpecResults).toHaveBeenCalledWith('blah', 'foo');
});
it("should quietly skip delegating to any subreporters which lack the given method", function() {
multiReporter.reportRunnerStarting('blah', 'foo');
expect(fakeReporter2.reportRunnerStarting).toHaveBeenCalledWith('blah', 'foo');
});
});

View File

@@ -1,54 +0,0 @@
describe('jasmine.NestedResults', function() {
it('#addResult increments counters', function() {
// Leaf case
var results = new jasmine.NestedResults();
results.addResult(new jasmine.ExpectationResult({
matcherName: "foo", passed: true, message: 'Passed.', actual: 'bar', expected: 'bar'}
));
expect(results.getItems().length).toEqual(1);
expect(results.totalCount).toEqual(1);
expect(results.passedCount).toEqual(1);
expect(results.failedCount).toEqual(0);
results.addResult(new jasmine.ExpectationResult({
matcherName: "baz", passed: false, message: 'FAIL.', actual: "corge", expected: "quux"
}));
expect(results.getItems().length).toEqual(2);
expect(results.totalCount).toEqual(2);
expect(results.passedCount).toEqual(1);
expect(results.failedCount).toEqual(1);
});
it('should roll up counts for nested results', function() {
// Branch case
var leafResultsOne = new jasmine.NestedResults();
leafResultsOne.addResult(new jasmine.ExpectationResult({
matcherName: "toSomething", passed: true, message: 'message', actual: '', expected:''
}));
leafResultsOne.addResult(new jasmine.ExpectationResult({
matcherName: "toSomethingElse", passed: false, message: 'message', actual: 'a', expected: 'b'
}));
var leafResultsTwo = new jasmine.NestedResults();
leafResultsTwo.addResult(new jasmine.ExpectationResult({
matcherName: "toSomething", passed: true, message: 'message', actual: '', expected: ''
}));
leafResultsTwo.addResult(new jasmine.ExpectationResult({
matcherName: "toSomethineElse", passed: false, message: 'message', actual: 'c', expected: 'd'
}));
var branchResults = new jasmine.NestedResults();
branchResults.addResult(leafResultsOne);
branchResults.addResult(leafResultsTwo);
expect(branchResults.getItems().length).toEqual(2);
expect(branchResults.totalCount).toEqual(4);
expect(branchResults.passedCount).toEqual(2);
expect(branchResults.failedCount).toEqual(2);
});
});

View File

@@ -0,0 +1,64 @@
describe("ObjectContaining", function() {
it("matches any actual to an empty object", function() {
var containing = new j$.ObjectContaining({});
expect(containing.jasmineMatches("foo")).toBe(true);
});
it("does not match an empty object actual", function() {
var containing = new j$.ObjectContaining("foo");
expect(function() {
containing.jasmineMatches({})
}).toThrowError(/not 'foo'/)
});
it("matches when the key/value pair is present in the actual", function() {
var containing = new j$.ObjectContaining({foo: "fooVal"});
expect(containing.jasmineMatches({foo: "fooVal", bar: "barVal"})).toBe(true);
});
it("does not match when the key/value pair is not present in the actual", function() {
var containing = new j$.ObjectContaining({foo: "fooVal"});
expect(containing.jasmineMatches({bar: "barVal", quux: "quuxVal"})).toBe(false);
});
it("does not match when the key is present but the value is different in the actual", function() {
var containing = new j$.ObjectContaining({foo: "other"});
expect(containing.jasmineMatches({foo: "fooVal", bar: "barVal"})).toBe(false);
});
it("mismatchValues parameter must return array with mismatched reason", function() {
var containing = new j$.ObjectContaining({foo: "other"});
var mismatchKeys = [];
var mismatchValues = [];
containing.jasmineMatches({foo: "fooVal", bar: "barVal"}, mismatchKeys, mismatchValues);
expect(mismatchValues.length).toBe(1);
expect(mismatchValues[0]).toEqual("'foo' was 'fooVal' in actual, but was 'other' in expected.");
});
it("adds keys in expected but not actual to the mismatchKeys parameter", function() {
var containing = new j$.ObjectContaining({foo: "fooVal"});
var mismatchKeys = [];
var mismatchValues = [];
containing.jasmineMatches({bar: "barVal"}, mismatchKeys, mismatchValues);
expect(mismatchKeys.length).toBe(1);
expect(mismatchKeys[0]).toEqual("expected has key 'foo', but missing from actual.");
});
it("jasmineToString's itself", function() {
var containing = new j$.ObjectContaining({});
expect(containing.jasmineToString()).toMatch("<jasmine.objectContaining");
});
});

View File

@@ -1,45 +1,75 @@
describe("jasmine.pp", function () {
describe("j$.pp", function () {
it("should wrap strings in single quotes", function() {
expect(jasmine.pp("some string")).toEqual("'some string'");
expect(jasmine.pp("som' string")).toEqual("'som' string'");
expect(j$.pp("some string")).toEqual("'some string'");
expect(j$.pp("som' string")).toEqual("'som' string'");
});
it("should stringify primitives properly", function() {
expect(jasmine.pp(true)).toEqual("true");
expect(jasmine.pp(false)).toEqual("false");
expect(jasmine.pp(null)).toEqual("null");
expect(jasmine.pp(jasmine.undefined)).toEqual("undefined");
expect(jasmine.pp(3)).toEqual("3");
expect(jasmine.pp(-3.14)).toEqual("-3.14");
expect(j$.pp(true)).toEqual("true");
expect(j$.pp(false)).toEqual("false");
expect(j$.pp(null)).toEqual("null");
expect(j$.pp(jasmine.undefined)).toEqual("undefined");
expect(j$.pp(3)).toEqual("3");
expect(j$.pp(-3.14)).toEqual("-3.14");
});
it("should stringify arrays properly", function() {
expect(jasmine.pp([1, 2])).toEqual("[ 1, 2 ]");
expect(jasmine.pp([1, 'foo', {}, jasmine.undefined, null])).toEqual("[ 1, 'foo', { }, undefined, null ]");
expect(j$.pp([1, 2])).toEqual("[ 1, 2 ]");
expect(j$.pp([1, 'foo', {}, jasmine.undefined, null])).toEqual("[ 1, 'foo', { }, undefined, null ]");
});
it("should indicate circular array references", function() {
var array1 = [1, 2];
var array2 = [array1];
array1.push(array2);
expect(jasmine.pp(array1)).toEqual("[ 1, 2, [ <circular reference: Array> ] ]");
expect(j$.pp(array1)).toEqual("[ 1, 2, [ <circular reference: Array> ] ]");
});
it("should stringify objects properly", function() {
expect(jasmine.pp({foo: 'bar'})).toEqual("{ foo : 'bar' }");
expect(jasmine.pp({foo:'bar', baz:3, nullValue: null, undefinedValue: jasmine.undefined})).toEqual("{ foo : 'bar', baz : 3, nullValue : null, undefinedValue : undefined }");
expect(jasmine.pp({foo: function () {
expect(j$.pp({foo: 'bar'})).toEqual("{ foo : 'bar' }");
expect(j$.pp({foo:'bar', baz:3, nullValue: null, undefinedValue: jasmine.undefined})).toEqual("{ foo : 'bar', baz : 3, nullValue : null, undefinedValue : undefined }");
expect(j$.pp({foo: function () {
}, bar: [1, 2, 3]})).toEqual("{ foo : Function, bar : [ 1, 2, 3 ] }");
});
it("should not include inherited properties when stringifying an object", function() {
var SomeClass = function() {};
SomeClass.prototype.foo = "inherited foo";
var instance = new SomeClass();
instance.bar = "my own bar";
expect(j$.pp(instance)).toEqual("{ bar : 'my own bar' }");
});
it("should not recurse objects and arrays more deeply than j$.MAX_PRETTY_PRINT_DEPTH", function() {
var originalMaxDepth = j$.MAX_PRETTY_PRINT_DEPTH;
var nestedObject = { level1: { level2: { level3: { level4: "leaf" } } } };
var nestedArray = [1, [2, [3, [4, "leaf"]]]];
try {
j$.MAX_PRETTY_PRINT_DEPTH = 2;
expect(j$.pp(nestedObject)).toEqual("{ level1 : { level2 : Object } }");
expect(j$.pp(nestedArray)).toEqual("[ 1, [ 2, Array ] ]");
j$.MAX_PRETTY_PRINT_DEPTH = 3;
expect(j$.pp(nestedObject)).toEqual("{ level1 : { level2 : { level3 : Object } } }");
expect(j$.pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, Array ] ] ]");
j$.MAX_PRETTY_PRINT_DEPTH = 4;
expect(j$.pp(nestedObject)).toEqual("{ level1 : { level2 : { level3 : { level4 : 'leaf' } } } }");
expect(j$.pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, [ 4, 'leaf' ] ] ] ]");
} finally {
j$.MAX_PRETTY_PRINT_DEPTH = originalMaxDepth;
}
});
it("should stringify RegExp objects properly", function() {
expect(jasmine.pp(/x|y|z/)).toEqual("/x|y|z/");
expect(j$.pp(/x|y|z/)).toEqual("/x|y|z/");
});
it("should indicate circular object references", function() {
var sampleValue = {foo: 'hello'};
sampleValue.nested = sampleValue;
expect(jasmine.pp(sampleValue)).toEqual("{ foo : 'hello', nested : <circular reference: Object> }");
expect(j$.pp(sampleValue)).toEqual("{ foo : 'hello', nested : <circular reference: Object> }");
});
it("should indicate getters on objects as such", function() {
@@ -51,37 +81,45 @@ describe("jasmine.pp", function () {
});
}
if (sampleValue.__defineGetter__) {
expect(jasmine.pp(sampleValue)).toEqual("{ id : 1, calculatedValue : <getter> }");
expect(j$.pp(sampleValue)).toEqual("{ id : 1, calculatedValue : <getter> }");
}
else {
expect(jasmine.pp(sampleValue)).toEqual("{ id : 1 }");
expect(j$.pp(sampleValue)).toEqual("{ id : 1 }");
}
});
it('should not do HTML escaping of strings', function() {
expect(jasmine.pp('some <b>html string</b> &', false)).toEqual('\'some <b>html string</b> &\'');
expect(j$.pp('some <b>html string</b> &', false)).toEqual('\'some <b>html string</b> &\'');
});
it("should abbreviate the global (usually window) object", function() {
expect(jasmine.pp(jasmine.getGlobal())).toEqual("<global>");
expect(j$.pp(jasmine.getGlobal())).toEqual("<global>");
});
it("should stringify Date objects properly", function() {
var now = new Date();
expect(jasmine.pp(now)).toEqual("Date(" + now.toString() + ")");
expect(j$.pp(now)).toEqual("Date(" + now.toString() + ")");
});
it("should stringify spy objects properly", function() {
var TestObject = {
someFunction: function() {
}
};
spyOn(TestObject, 'someFunction');
expect(jasmine.pp(TestObject.someFunction)).toEqual("spy on someFunction");
someFunction: function() {}
},
env = new j$.Env();
expect(jasmine.pp(jasmine.createSpy("something"))).toEqual("spy on something");
env.spyOn(TestObject, 'someFunction');
expect(j$.pp(TestObject.someFunction)).toEqual("spy on someFunction");
expect(j$.pp(j$.createSpy("something"))).toEqual("spy on something");
});
it("should stringify objects that implement jasmineToString", function () {
var obj = {
jasmineToString: function () { return "strung"; }
};
expect(j$.pp(obj)).toEqual("strung");
});
});

View File

@@ -0,0 +1,147 @@
describe("QueueRunner", function() {
it("runs all the functions it's passed", function() {
var calls = [],
fn1 = jasmine.createSpy('fn1'),
fn2 = jasmine.createSpy('fn2'),
queueRunner = new j$.QueueRunner({
fns: [fn1, fn2]
});
fn1.and.callFake(function() {
calls.push('fn1');
});
fn2.and.callFake(function() {
calls.push('fn2');
});
queueRunner.execute();
expect(calls).toEqual(['fn1', 'fn2']);
});
it("supports asynchronous functions, only advancing to next function after a done() callback", function() {
//TODO: it would be nice if spy arity could match the fake, so we could do something like:
//createSpy('asyncfn').and.callFake(function(done) {});
var onComplete = jasmine.createSpy('onComplete'),
beforeCallback = jasmine.createSpy('beforeCallback'),
fnCallback = jasmine.createSpy('fnCallback'),
afterCallback = jasmine.createSpy('afterCallback'),
fn1 = function(done) {
beforeCallback();
setTimeout(function() {
done()
}, 100);
},
fn2 = function(done) {
fnCallback();
setTimeout(function() {
done()
}, 100);
},
fn3 = function(done) {
afterCallback();
setTimeout(function() {
done()
}, 100);
},
queueRunner = new j$.QueueRunner({
fns: [fn1, fn2, fn3],
onComplete: onComplete
});
clock.install();
queueRunner.execute();
expect(beforeCallback).toHaveBeenCalled();
expect(fnCallback).not.toHaveBeenCalled();
expect(afterCallback).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
clock.tick(100);
expect(fnCallback).toHaveBeenCalled();
expect(afterCallback).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
clock.tick(100);
expect(afterCallback).toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
clock.tick(100);
expect(onComplete).toHaveBeenCalled();
});
it("calls an exception handler when an exception is thrown in a fn", function() {
var fn = function() {
throw new Error('fake error');
},
exceptionCallback = jasmine.createSpy('exception callback'),
queueRunner = new j$.QueueRunner({
fns: [fn],
onException: exceptionCallback
});
queueRunner.execute();
expect(exceptionCallback).toHaveBeenCalledWith(jasmine.any(Error));
});
it("rethrows an exception if told to", function() {
var fn = function() {
throw new Error('fake error');
},
queueRunner = new j$.QueueRunner({
fns: [fn],
catchException: function(e) { return false; }
});
expect(function() { queueRunner.execute(); }).toThrow();
});
it("continues running the functions even after an exception is thrown in an async spec", function() {
var fn = function(done) { throw new Error("error"); },
nextFn = jasmine.createSpy("nextFunction");
queueRunner = new j$.QueueRunner({
fns: [fn, nextFn]
});
queueRunner.execute();
expect(nextFn).toHaveBeenCalled();
});
it("calls a provided complete callback when done", function() {
var fn = jasmine.createSpy('fn'),
completeCallback = jasmine.createSpy('completeCallback'),
queueRunner = new j$.QueueRunner({
fns: [fn],
onComplete: completeCallback
});
queueRunner.execute();
expect(completeCallback).toHaveBeenCalled();
});
it("calls a provided stack clearing function when done", function() {
var asyncFn = function(done) { done() },
afterFn = jasmine.createSpy('afterFn'),
completeCallback = jasmine.createSpy('completeCallback'),
clearStack = jasmine.createSpy('clearStack'),
queueRunner = new j$.QueueRunner({
fns: [asyncFn, afterFn],
clearStack: clearStack,
onComplete: completeCallback
});
clearStack.and.callFake(function(fn) { fn(); });
queueRunner.execute();
expect(afterFn).toHaveBeenCalled();
expect(clearStack).toHaveBeenCalledWith(completeCallback);
});
});

View File

@@ -1,23 +0,0 @@
describe("jasmine.Queue", function() {
it("should not call itself recursively, so we don't get stack overflow errors", function() {
var queue = new jasmine.Queue(new jasmine.Env());
queue.add(new jasmine.Block(null, function() {}));
queue.add(new jasmine.Block(null, function() {}));
queue.add(new jasmine.Block(null, function() {}));
queue.add(new jasmine.Block(null, function() {}));
var nestCount = 0;
var maxNestCount = 0;
var nextCallCount = 0;
queue.next_ = function() {
nestCount++;
if (nestCount > maxNestCount) maxNestCount = nestCount;
jasmine.Queue.prototype.next_.apply(queue, arguments);
nestCount--;
};
queue.start();
expect(maxNestCount).toEqual(1);
});
});

View File

@@ -0,0 +1,40 @@
describe("ReportDispatcher", function() {
it("builds an interface of requested methods", function() {
var dispatcher = new j$.ReportDispatcher(['foo', 'bar', 'baz']);
expect(dispatcher.foo).toBeDefined();
expect(dispatcher.bar).toBeDefined();
expect(dispatcher.baz).toBeDefined();
});
it("dispatches requested methods to added reporters", function() {
var dispatcher = new j$.ReportDispatcher(['foo', 'bar']),
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
anotherReporter = jasmine.createSpyObj('reporter', ['foo', 'bar']);
dispatcher.addReporter(reporter);
dispatcher.addReporter(anotherReporter);
dispatcher.foo(123, 456);
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
expect(anotherReporter.foo).toHaveBeenCalledWith(123, 456);
dispatcher.bar('a', 'b');
expect(reporter.bar).toHaveBeenCalledWith('a', 'b');
expect(anotherReporter.bar).toHaveBeenCalledWith('a', 'b');
});
it("does not dispatch to a reporter if the reporter doesn't accept the method", function() {
var dispatcher = new j$.ReportDispatcher(['foo']),
reporter = jasmine.createSpyObj('reporter', ['baz']);
dispatcher.addReporter(reporter);
expect(function() {
dispatcher.foo(123, 456);
}).not.toThrow();
});
});

View File

@@ -1,56 +0,0 @@
describe('jasmine.Reporter', function() {
var env;
beforeEach(function() {
env = new jasmine.Env();
env.updateInterval = 0;
});
it('should get called from the test runner', function() {
env.describe('Suite for JSON Reporter with Callbacks', function () {
env.it('should be a test', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
env.it('should be a failing test', function() {
this.runs(function () {
this.expect(false).toEqual(true);
});
});
});
env.describe('Suite for JSON Reporter with Callbacks 2', function () {
env.it('should be a test', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
});
var foo = 0;
var bar = 0;
var baz = 0;
env.addReporter({
reportSpecResults: function() {
foo++;
},
reportSuiteResults: function() {
bar++;
},
reportRunnerResults: function() {
baz++;
}
});
var runner = env.currentRunner();
runner.execute();
expect(foo).toEqual(3); // 'foo was expected to be 3, was ' + foo);
expect(bar).toEqual(2); // 'bar was expected to be 2, was ' + bar);
expect(baz).toEqual(1); // 'baz was expected to be 1, was ' + baz);
});
});

View File

@@ -1,267 +0,0 @@
describe('RunnerTest', function() {
var fakeTimer;
var env;
beforeEach(function() {
env = new jasmine.Env();
env.updateInterval = 0;
fakeTimer = new jasmine.FakeTimer();
env.setTimeout = fakeTimer.setTimeout;
env.clearTimeout = fakeTimer.clearTimeout;
env.setInterval = fakeTimer.setInterval;
env.clearInterval = fakeTimer.clearInterval;
});
describe('beforeEach', function() {
it('should run before each spec for all suites', function () {
var foo;
env.beforeEach(function () {
foo = 0;
});
env.describe('suite 1', function () {
env.it('test 1-1', function() {
foo++;
this.expect(foo).toEqual(1);
});
env.it('test 1-2', function() {
foo++;
this.expect(foo).toEqual(1);
});
});
env.describe('suite 2', function () {
env.it('test 2-1', function() {
foo++;
this.expect(foo).toEqual(1);
});
});
env.currentRunner().execute();
var runnerResults = env.currentRunner().results();
expect(runnerResults.totalCount).toEqual(3);
expect(runnerResults.passedCount).toEqual(3);
});
it('should provide all specs', function () {
var foo;
env.beforeEach(function () {
foo = 0;
});
env.describe('suite 1', function () {
env.it('test 1-1', function() {
foo++;
this.expect(foo).toEqual(1);
});
env.it('test 1-2', function() {
foo++;
this.expect(foo).toEqual(1);
});
});
env.describe('suite 2', function () {
env.it('test 2-1', function() {
foo++;
this.expect(foo).toEqual(1);
});
});
env.currentRunner().execute();
expect(env.currentRunner().specs().length).toEqual(3);
});
});
describe('afterEach', function() {
it('should run after each spec for all suites', function () {
var foo = 3;
env.afterEach(function () {
foo = foo - 1;
});
env.describe('suite 1', function () {
env.it('test 1-1', function() {
this.expect(foo).toEqual(3);
});
env.it('test 1-2', function() {
this.expect(foo).toEqual(2);
});
});
env.describe('suite 2', function () {
env.it('test 2-1', function() {
this.expect(foo).toEqual(1);
});
});
env.currentRunner().execute();
var runnerResults = env.currentRunner().results();
expect(runnerResults.totalCount).toEqual(3);
expect(runnerResults.passedCount).toEqual(3);
});
});
it('should run child suites and specs and generate results when execute is called', function() {
env.describe('one suite description', function () {
env.it('should be a test', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
});
env.describe('another suite description', function () {
env.it('should be another test', function() {
this.runs(function () {
this.expect(true).toEqual(false);
});
});
});
env.currentRunner().execute();
var runnerResults = env.currentRunner().results();
expect(runnerResults.totalCount).toEqual(2);
expect(runnerResults.passedCount).toEqual(1);
expect(runnerResults.failedCount).toEqual(1);
});
it('should ignore suites that have been x\'d', function() {
env.xdescribe('one suite description', function () {
env.it('should be a test', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
});
env.describe('another suite description', function () {
env.it('should be another test', function() {
this.runs(function () {
this.expect(true).toEqual(false);
});
});
});
env.currentRunner().execute();
var runnerResults = env.currentRunner().results();
expect(runnerResults.totalCount).toEqual(1);
expect(runnerResults.passedCount).toEqual(0);
expect(runnerResults.failedCount).toEqual(1);
});
it('should roll up results from all specs', function() {
env.describe('one suite description', function () {
env.it('should be a test', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
});
env.describe('another suite description', function () {
env.it('should be another test', function() {
this.runs(function () {
this.expect(true).toEqual(false);
});
});
});
env.currentRunner().execute();
var results = env.currentRunner().results();
expect(results.totalCount).toEqual(2);
expect(results.passedCount).toEqual(1);
expect(results.failedCount).toEqual(1);
});
describe('reporting', function () {
var fakeReporter;
beforeEach(function () {
fakeReporter = jasmine.createSpyObj("fakeReporter", ["log", "reportRunnerStarting", "reportRunnerResults"]);
env.addReporter(fakeReporter);
});
it('should report runner results when the runner has completed running', function() {
env.describe('one suite description', function () {
env.it('should be a test', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
});
env.describe('another suite description', function () {
env.it('should be another test', function() {
this.waits(200);
this.runs(function () {
this.expect(true).toEqual(false);
});
});
});
env.currentRunner().execute();
expect(fakeReporter.reportRunnerResults).not.toHaveBeenCalled();
fakeTimer.tick(200);
//This blows up the JSApiReporter.
//expect(fakeReporter.reportRunnerResults).toHaveBeenCalledWith(env.currentRunner);
expect(fakeReporter.reportRunnerResults).toHaveBeenCalled();
expect(fakeReporter.reportRunnerResults.mostRecentCall.args[0].results()).toEqual(env.currentRunner().results());
});
});
it("should report when the tests start running", function() {
var fakeReporter = jasmine.createSpyObj("fakeReporter", ["log", "reportRunnerStarting"]);
env.addReporter(fakeReporter);
var runner = new jasmine.Runner(env);
runner.arbitraryVariable = 'foo';
spyOn(runner.queue, 'start');
expect(fakeReporter.reportRunnerStarting).not.toHaveBeenCalled();
runner.execute();
expect(fakeReporter.reportRunnerStarting).toHaveBeenCalled();
var reportedRunner = fakeReporter.reportRunnerStarting.mostRecentCall.args[0];
expect(reportedRunner.arbitraryVariable).toEqual('foo');
expect(runner.queue.start).toHaveBeenCalled();
});
describe("when suites are nested", function() {
var suite1, suite2, suite3;
function suiteNames(suites) {
var suiteDescriptions = [];
for (var i = 0; i < suites.length; i++) {
suiteDescriptions.push(suites[i].getFullName());
}
return suiteDescriptions;
}
beforeEach(function() {
suite1 = env.describe("suite 1", function() {
suite2 = env.describe("suite 2", function() {
});
});
suite3 = env.describe("suite 3", function() {});
});
it("#suites should return a flat array of all suites, including nested suites", function() {
var suites = env.currentRunner().suites();
expect(suiteNames(suites)).toEqual([suite1.getFullName(), suite2.getFullName(), suite3.getFullName()]);
});
it("#topLevelSuites should return a flat array of all top-level suites only", function() {
var suites = env.currentRunner().topLevelSuites();
expect(suiteNames(suites)).toEqual([suite1.getFullName(), suite3.getFullName()]);
});
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,124 +1,244 @@
describe('Spec', function () {
var env, suite;
beforeEach(function() {
env = new jasmine.Env();
env.updateInterval = 0;
suite = new jasmine.Suite(env, 'suite 1');
describe("Spec", function() {
it("#isPendingSpecException returns true for a pending spec exception", function() {
var e = new Error(j$.Spec.pendingSpecExceptionMessage);
expect(j$.Spec.isPendingSpecException(e)).toBe(true);
});
describe('initialization', function () {
it("#isPendingSpecException returns true for a pending spec exception (even when FF bug is present)", function() {
var fakeError = {
toString: function() { return "Error: " + j$.Spec.pendingSpecExceptionMessage; }
};
it('should raise an error if an env is not passed', function () {
try {
new jasmine.Spec();
}
catch (e) {
expect(e.message).toEqual('jasmine.Env() required');
}
});
it('should raise an error if a suite is not passed', function () {
try {
new jasmine.Spec(env);
}
catch (e) {
expect(e.message).toEqual('jasmine.Suite() required');
}
});
it('should assign sequential ids for specs belonging to the same env', function () {
var spec1 = new jasmine.Spec(env, suite);
var spec2 = new jasmine.Spec(env, suite);
var spec3 = new jasmine.Spec(env, suite);
expect(spec1.id).toEqual(0);
expect(spec2.id).toEqual(1);
expect(spec3.id).toEqual(2);
});
expect(j$.Spec.isPendingSpecException(fakeError)).toBe(true);
});
it('getFullName returns suite & spec description', function () {
var spec = new jasmine.Spec(env, suite, 'spec 1');
expect(spec.getFullName()).toEqual('suite 1 spec 1.');
it("#isPendingSpecException returns true for a pending spec exception", function() {
var e = new Error("foo");
expect(j$.Spec.isPendingSpecException(e)).toBe(false);
});
describe('results', function () {
var spec, results;
beforeEach(function () {
spec = new jasmine.Spec(env, suite);
results = spec.results();
expect(results.totalCount).toEqual(0);
spec.runs(function () {
this.expect(true).toEqual(true);
this.expect(true).toEqual(true);
it("delegates execution to a QueueRunner", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
spec = new j$.Spec({
description: 'my test',
id: 'some-id',
fn: function() {},
queueRunner: fakeQueueRunner
});
});
spec.execute();
it('results shows the total number of expectations for each spec after execution', function () {
expect(results.totalCount).toEqual(0);
spec.execute();
expect(results.totalCount).toEqual(2);
});
expect(fakeQueueRunner).toHaveBeenCalled();
});
it('results shows the number of passed expectations for each spec after execution', function () {
expect(results.passedCount).toEqual(0);
spec.execute();
expect(results.passedCount).toEqual(2);
});
it('results shows the number of failed expectations for each spec after execution', function () {
spec.runs(function () {
this.expect(true).toEqual(false);
it("should call the start callback on execution", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
beforesWereCalled = false,
startCallback = jasmine.createSpy('startCallback'),
spec = new j$.Spec({
id: 123,
description: 'foo bar',
fn: function() {},
onStart: startCallback,
queueRunner: fakeQueueRunner
});
expect(results.failedCount).toEqual(0);
spec.execute();
expect(results.failedCount).toEqual(1);
spec.execute();
expect(startCallback).toHaveBeenCalledWith(spec);
});
it("should call the start callback on execution but before any befores are called", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
beforesWereCalled = false,
startCallback = jasmine.createSpy('start-callback').and.callFake(function() {
expect(beforesWereCalled).toBe(false);
}),
spec = new j$.Spec({
fn: function() {},
beforeFns: function() {
return [function() {
beforesWereCalled = true
}]
},
onStart: startCallback,
queueRunner: fakeQueueRunner
});
spec.execute();
expect(startCallback).toHaveBeenCalled();
});
it("provides all before fns and after fns to be run", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
before = jasmine.createSpy('before'),
after = jasmine.createSpy('after'),
fn = jasmine.createSpy('test body').and.callFake(function() {
expect(before).toHaveBeenCalled();
expect(after).not.toHaveBeenCalled();
}),
spec = new j$.Spec({
fn: fn,
beforeFns: function() {
return [before]
},
afterFns: function() {
return [after]
},
queueRunner: fakeQueueRunner
});
spec.execute();
var allSpecFns = fakeQueueRunner.calls.mostRecent().args[0].fns;
expect(allSpecFns).toEqual([before, fn, after]);
});
it("is marked pending if created without a function body", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
startCallback = jasmine.createSpy('startCallback'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({
onStart: startCallback,
fn: null,
resultCallback: resultCallback,
queueRunner: fakeQueueRunner
});
expect(spec.status()).toBe('pending');
});
it("can be disabled, but still calls callbacks", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
startCallback = jasmine.createSpy('startCallback'),
specBody = jasmine.createSpy('specBody'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({
onStart:startCallback,
fn: specBody,
resultCallback: resultCallback,
queueRunner: fakeQueueRunner
});
spec.disable();
expect(spec.status()).toBe('disabled');
spec.execute();
expect(fakeQueueRunner).not.toHaveBeenCalled();
expect(specBody).not.toHaveBeenCalled();
expect(startCallback).toHaveBeenCalled();
expect(resultCallback).toHaveBeenCalled();
});
it("can be marked pending, but still calls callbacks when executed", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
startCallback = jasmine.createSpy('startCallback'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({
onStart: startCallback,
resultCallback: resultCallback,
description: "with a spec",
getSpecName: function() {
return "a suite with a spec"
},
queueRunner: fakeQueueRunner
});
spec.pend();
expect(spec.status()).toBe('pending');
spec.execute();
expect(fakeQueueRunner).not.toHaveBeenCalled();
expect(startCallback).toHaveBeenCalled();
expect(resultCallback).toHaveBeenCalledWith({
id: spec.id,
status: 'pending',
description: 'with a spec',
fullName: 'a suite with a spec',
failedExpectations: []
});
});
it("should call the done callback on execution complete", function() {
var done = jasmine.createSpy('done callback'),
spec = new j$.Spec({
fn: function() {},
catchExceptions: function() { return false; },
resultCallback: function() {},
queueRunner: function(attrs) { attrs.onComplete(); }
});
spec.execute(done);
expect(done).toHaveBeenCalled();
});
it("#status returns pending by default", function() {
var spec = new j$.Spec({fn: jasmine.createSpy("spec body")});
expect(spec.status()).toEqual('pending');
});
it("#status returns pending if no expectations were encountered", function() {
var specBody = jasmine.createSpy("spec body"),
spec = new j$.Spec({fn: specBody});
spec.execute();
expect(spec.status()).toEqual('pending');
});
it("#status returns passed if all expectations in the spec have passed", function() {
var spec = new j$.Spec({fn: jasmine.createSpy("spec body")});
spec.addExpectationResult(true);
expect(spec.status()).toBe('passed');
});
it("#status returns failed if any expectations in the spec have failed", function() {
var spec = new j$.Spec({ fn: jasmine.createSpy("spec body") });
spec.addExpectationResult(true);
spec.addExpectationResult(false);
expect(spec.status()).toBe('failed');
});
it("can return its full name", function() {
var spec;
spec = new j$.Spec({
getSpecName: function(passedVal) {
// expect(passedVal).toBe(spec); TODO: a exec time, spec is undefined WTF?
return 'expected val';
}
});
describe('results.passed', function () {
it('is true if all spec expectations pass', function () {
spec.runs(function () {
this.expect(true).toEqual(true);
expect(spec.getFullName()).toBe('expected val');
});
describe("when a spec is marked pending during execution", function() {
it("should mark the spec as pending", function() {
var fakeQueueRunner = function(opts) {
opts.onException(new Error(j$.Spec.pendingSpecExceptionMessage));
},
spec = new j$.Spec({
description: 'my test',
id: 'some-id',
fn: function() { },
queueRunner: fakeQueueRunner
});
spec.execute();
expect(results.passed()).toEqual(true);
});
it('is false if one spec expectation fails', function () {
spec.runs(function () {
this.expect(true).toEqual(false);
});
spec.execute();
expect(results.passed()).toEqual(false);
});
it('a spec with no expectations will return true', function () {
var specWithoutExpectations = new jasmine.Spec(env, suite);
specWithoutExpectations.runs(function() {
});
specWithoutExpectations.execute();
expect(results.passed()).toEqual(true);
});
it('an unexecuted spec will return true', function () {
expect(results.passed()).toEqual(true);
});
});
it("includes log messages, which may contain arbitary objects", function() {
spec.runs(function() {
this.log("here's some log message", {key: 'value'}, 123);
});
spec.execute();
var items = results.getItems();
expect(items).toEqual([
jasmine.any(jasmine.ExpectationResult),
jasmine.any(jasmine.ExpectationResult),
jasmine.any(jasmine.MessageResult)
]);
var logResult = items[2];
expect(logResult.values).toEqual(["here's some log message", {key: 'value'}, 123]);
expect(spec.status()).toEqual("pending");
});
});
});
});

View File

@@ -1,201 +1,48 @@
describe('Spies', function () {
it('should replace the specified function with a spy object', function() {
var originalFunctionWasCalled = false;
var TestClass = {
someFunction: function() {
originalFunctionWasCalled = true;
}
};
this.spyOn(TestClass, 'someFunction');
describe("createSpy", function() {
var TestClass;
expect(TestClass.someFunction.wasCalled).toEqual(false);
expect(TestClass.someFunction.callCount).toEqual(0);
TestClass.someFunction('foo');
expect(TestClass.someFunction.wasCalled).toEqual(true);
expect(TestClass.someFunction.callCount).toEqual(1);
expect(TestClass.someFunction.mostRecentCall.args).toEqual(['foo']);
expect(TestClass.someFunction.mostRecentCall.object).toEqual(TestClass);
expect(originalFunctionWasCalled).toEqual(false);
beforeEach(function() {
TestClass = function() {};
TestClass.prototype.someFunction = function() {};
TestClass.prototype.someFunction.bob = "test";
});
it("preserves the properties of the spied function", function() {
var spy = j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
TestClass.someFunction('bar');
expect(TestClass.someFunction.callCount).toEqual(2);
expect(TestClass.someFunction.mostRecentCall.args).toEqual(['bar']);
});
it('should allow you to view args for a particular call', function() {
var originalFunctionWasCalled = false;
var TestClass = {
someFunction: function() {
originalFunctionWasCalled = true;
}
};
this.spyOn(TestClass, 'someFunction');
TestClass.someFunction('foo');
TestClass.someFunction('bar');
expect(TestClass.someFunction.calls[0].args).toEqual(['foo']);
expect(TestClass.someFunction.calls[1].args).toEqual(['bar']);
expect(TestClass.someFunction.mostRecentCall.args).toEqual(['bar']);
});
it('should be possible to call through to the original method, or return a specific result', function() {
var originalFunctionWasCalled = false;
var passedArgs;
var passedObj;
var TestClass = {
someFunction: function() {
originalFunctionWasCalled = true;
passedArgs = arguments;
passedObj = this;
return "return value from original function";
}
};
this.spyOn(TestClass, 'someFunction').andCallThrough();
var result = TestClass.someFunction('arg1', 'arg2');
expect(result).toEqual("return value from original function");
expect(originalFunctionWasCalled).toEqual(true);
expect(passedArgs).toEqual(['arg1', 'arg2']);
expect(passedObj).toEqual(TestClass);
expect(TestClass.someFunction.wasCalled).toEqual(true);
});
it('should be possible to return a specific value', function() {
var originalFunctionWasCalled = false;
var TestClass = {
someFunction: function() {
originalFunctionWasCalled = true;
return "return value from original function";
}
};
this.spyOn(TestClass, 'someFunction').andReturn("some value");
originalFunctionWasCalled = false;
var result = TestClass.someFunction('arg1', 'arg2');
expect(result).toEqual("some value");
expect(originalFunctionWasCalled).toEqual(false);
});
it('should be possible to throw a specific error', function() {
var originalFunctionWasCalled = false;
var TestClass = {
someFunction: function() {
originalFunctionWasCalled = true;
return "return value from original function";
}
};
this.spyOn(TestClass, 'someFunction').andThrow(new Error('fake error'));
var exception;
try {
TestClass.someFunction('arg1', 'arg2');
} catch (e) {
exception = e;
}
expect(exception.message).toEqual('fake error');
expect(originalFunctionWasCalled).toEqual(false);
});
it('should be possible to call a specified function', function() {
var originalFunctionWasCalled = false;
var fakeFunctionWasCalled = false;
var passedArgs;
var passedObj;
var TestClass = {
someFunction: function() {
originalFunctionWasCalled = true;
return "return value from original function";
}
};
this.spyOn(TestClass, 'someFunction').andCallFake(function() {
fakeFunctionWasCalled = true;
passedArgs = arguments;
passedObj = this;
return "return value from fake function";
expect(spy.bob).toEqual("test");
});
var result = TestClass.someFunction('arg1', 'arg2');
expect(result).toEqual("return value from fake function");
expect(originalFunctionWasCalled).toEqual(false);
expect(fakeFunctionWasCalled).toEqual(true);
expect(passedArgs).toEqual(['arg1', 'arg2']);
expect(passedObj).toEqual(TestClass);
expect(TestClass.someFunction.wasCalled).toEqual(true);
});
it("warns the user that we indend to overwrite an existing property", function() {
TestClass.prototype.someFunction.and = "turkey";
it('is torn down when this.removeAllSpies is called', function() {
var originalFunctionWasCalled = false;
var TestClass = {
someFunction: function() {
originalFunctionWasCalled = true;
}
};
this.spyOn(TestClass, 'someFunction');
expect(function() {
j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
}).toThrowError("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
});
TestClass.someFunction('foo');
expect(originalFunctionWasCalled).toEqual(false);
it("adds a spyStrategy and callTracker to the spy", function() {
var spy = j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
this.removeAllSpies();
TestClass.someFunction('foo');
expect(originalFunctionWasCalled).toEqual(true);
});
it('calls removeAllSpies during spec finish', function() {
var test = new jasmine.Spec(new jasmine.Env(), {}, 'sample test');
this.spyOn(test, 'removeAllSpies');
test.finish();
expect(test.removeAllSpies).wasCalled();
});
it('throws an exception when some method is spied on twice', function() {
var TestClass = { someFunction: function() {
} };
this.spyOn(TestClass, 'someFunction');
var exception;
try {
this.spyOn(TestClass, 'someFunction');
} catch (e) {
exception = e;
}
expect(exception).toBeDefined();
});
it('should be able to reset a spy', function() {
var TestClass = { someFunction: function() {} };
this.spyOn(TestClass, 'someFunction');
expect(TestClass.someFunction).not.toHaveBeenCalled();
TestClass.someFunction();
expect(TestClass.someFunction).toHaveBeenCalled();
TestClass.someFunction.reset();
expect(TestClass.someFunction).not.toHaveBeenCalled();
expect(TestClass.someFunction.callCount).toEqual(0);
expect(spy.and).toEqual(jasmine.any(j$.SpyStrategy));
expect(spy.calls).toEqual(jasmine.any(j$.CallTracker));
});
});
describe("createSpyObj", function() {
it("should create an object with a bunch of spy methods when you call jasmine.createSpyObj()", function() {
var spyObj = jasmine.createSpyObj('BaseName', ['method1', 'method2']);
var spyObj = j$.createSpyObj('BaseName', ['method1', 'method2']);
expect(spyObj).toEqual({ method1: jasmine.any(Function), method2: jasmine.any(Function)});
expect(spyObj.method1.identity).toEqual('BaseName.method1');
expect(spyObj.method2.identity).toEqual('BaseName.method2');
expect(spyObj.method1.and.identity()).toEqual('BaseName.method1');
expect(spyObj.method2.and.identity()).toEqual('BaseName.method2');
});
it("should throw if you do not pass an array argument", function() {
expect(function() {
jasmine.createSpyObj('BaseName');
}).toThrow('createSpyObj requires a non-empty array of method names to create spies for');
});
it("should throw if you pass an empty array argument", function() {
expect(function() {
jasmine.createSpyObj('BaseName');
}).toThrow('createSpyObj requires a non-empty array of method names to create spies for');
j$.createSpyObj('BaseName');
}).toThrow("createSpyObj requires a non-empty array of method names to create spies for");
});
});
});

View File

@@ -0,0 +1,101 @@
describe("SpyStrategy", function() {
it("defaults its name to unknown", function() {
var spyStrategy = new j$.SpyStrategy();
expect(spyStrategy.identity()).toEqual("unknown");
});
it("takes a name", function() {
var spyStrategy = new j$.SpyStrategy({name: "foo"});
expect(spyStrategy.identity()).toEqual("foo");
});
it("stubs an original function, if provided", function() {
var originalFn = jasmine.createSpy("original"),
spyStrategy = new j$.SpyStrategy({fn: originalFn});
spyStrategy.exec();
expect(originalFn).not.toHaveBeenCalled();
});
it("allows an original function to be called, passed through the params and returns it's value", function() {
var originalFn = jasmine.createSpy("original").and.callReturn(42),
spyStrategy = new j$.SpyStrategy({fn: originalFn}),
returnValue;
spyStrategy.callThrough();
returnValue = spyStrategy.exec("foo");
expect(originalFn).toHaveBeenCalled();
expect(originalFn.calls.mostRecent().args).toEqual(["foo"]);
expect(returnValue).toEqual(42);
});
it("can return a specified value when executed", function() {
var originalFn = jasmine.createSpy("original"),
spyStrategy = new j$.SpyStrategy({fn: originalFn}),
returnValue;
spyStrategy.callReturn(17);
returnValue = spyStrategy.exec();
expect(originalFn).not.toHaveBeenCalled();
expect(returnValue).toEqual(17);
});
it("allows an exception to be thrown when executed", function() {
var originalFn = jasmine.createSpy("original"),
spyStrategy = new j$.SpyStrategy({fn: originalFn});
spyStrategy.callThrow("bar");
expect(function() { spyStrategy.exec(); }).toThrow("bar");
expect(originalFn).not.toHaveBeenCalled();
});
it("allows a fake function to be called instead", function() {
var originalFn = jasmine.createSpy("original"),
fakeFn = jasmine.createSpy("fake").and.callReturn(67),
spyStrategy = new j$.SpyStrategy({fn: originalFn}),
returnValue;
spyStrategy.callFake(fakeFn);
returnValue = spyStrategy.exec();
expect(originalFn).not.toHaveBeenCalled();
expect(returnValue).toEqual(67);
});
it("allows a return to plan stubbing after another strategy", function() {
var originalFn = jasmine.createSpy("original"),
fakeFn = jasmine.createSpy("fake").and.callReturn(67),
spyStrategy = new j$.SpyStrategy({fn: originalFn}),
returnValue;
spyStrategy.callFake(fakeFn);
returnValue = spyStrategy.exec();
expect(originalFn).not.toHaveBeenCalled();
expect(returnValue).toEqual(67);
spyStrategy.stub();
returnValue = spyStrategy.exec();
expect(returnValue).toEqual(void 0);
});
it("returns the spy after changing the strategy", function(){
var spy = {},
spyFn = jasmine.createSpy('spyFn').and.callReturn(spy),
spyStrategy = new j$.SpyStrategy({getSpy: spyFn});
expect(spyStrategy.callThrough()).toBe(spy);
expect(spyStrategy.callReturn()).toBe(spy);
expect(spyStrategy.callThrow()).toBe(spy);
expect(spyStrategy.callFake()).toBe(spy);
expect(spyStrategy.stub()).toBe(spy);
});
});

View File

@@ -1,120 +1,230 @@
describe('Suite', function() {
var fakeTimer;
var env;
describe("Suite", function() {
beforeEach(function() {
env = new jasmine.Env();
env.updateInterval = 0;
fakeTimer = new jasmine.FakeTimer();
env.setTimeout = fakeTimer.setTimeout;
env.clearTimeout = fakeTimer.clearTimeout;
env.setInterval = fakeTimer.setInterval;
env.clearInterval = fakeTimer.clearInterval;
});
describe('Specs', function () {
var suite;
beforeEach(function() {
suite = env.describe('Suite 1', function () {
env.it('Spec 1', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
env.it('Spec 2', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
env.describe('Suite 2', function () {
env.it('Spec 3', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
});
env.it('Spec 4', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
});
});
it('#specs should return all immediate children that are specs.', function () {
var suiteSpecs = suite.specs();
expect(suiteSpecs.length).toEqual(3);
expect(suiteSpecs[0].description).toEqual('Spec 1');
expect(suiteSpecs[1].description).toEqual('Spec 2');
expect(suiteSpecs[2].description).toEqual('Spec 4');
});
it("#suites should return all immediate children that are suites.", function() {
var nestedSuites = suite.suites();
expect(nestedSuites.length).toEqual(1);
expect(nestedSuites[0].description).toEqual('Suite 2');
});
it("#children should return all immediate children including suites and specs.", function() {
var children = suite.children();
expect(children.length).toEqual(4);
expect(children[0].description).toEqual('Spec 1');
expect(children[1].description).toEqual('Spec 2');
expect(children[2].description).toEqual('Suite 2');
expect(children[3].description).toEqual('Spec 4');
});
});
describe('SpecCount', function () {
it('should keep a count of the number of specs that are run', function() {
var suite = env.describe('one suite description', function () {
env.it('should be a test', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
env.it('should be another test', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
env.it('should be a third test', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
it("keeps its id", function() {
var env = new j$.Env(),
suite = new j$.Suite({
env: env,
id: 456,
description: "I am a suite"
});
expect(suite.specs().length).toEqual(3);
});
expect(suite.id).toEqual(456);
});
it('specCount should be correct even with runs/waits blocks', function() {
var suite = env.describe('one suite description', function () {
env.it('should be a test', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
env.it('should be another test', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
this.waits(10);
this.runs(function () {
this.expect(true).toEqual(true);
});
});
env.it('should be a third test', function() {
this.runs(function () {
this.expect(true).toEqual(true);
});
});
it("returns its full name", function() {
var env = new j$.Env(),
suite = new j$.Suite({
env: env,
description: "I am a suite"
});
expect(suite.specs().length).toEqual(3);
expect(suite.getFullName()).toEqual("I am a suite");
});
it("returns its full name when it has parent suites", function() {
var env = new j$.Env(),
parentSuite = new j$.Suite({
env: env,
description: "I am a parent suite",
parentSuite: jasmine.createSpy('pretend top level suite')
}),
suite = new j$.Suite({
env: env,
description: "I am a suite",
parentSuite: parentSuite
});
expect(suite.getFullName()).toEqual("I am a parent suite I am a suite");
});
it("adds before functions in order of needed execution", function() {
var env = new j$.Env(),
suite = new j$.Suite({
env: env,
description: "I am a suite"
}),
outerBefore = jasmine.createSpy('outerBeforeEach'),
innerBefore = jasmine.createSpy('insideBeforeEach');
suite.beforeEach(outerBefore);
suite.beforeEach(innerBefore);
expect(suite.beforeFns).toEqual([innerBefore, outerBefore]);
});
it("adds after functions in order of needed execution", function() {
var env = new j$.Env(),
suite = new j$.Suite({
env: env,
description: "I am a suite"
}),
outerAfter = jasmine.createSpy('outerAfterEach'),
innerAfter = jasmine.createSpy('insideAfterEach');
suite.afterEach(outerAfter);
suite.afterEach(innerAfter);
expect(suite.afterFns).toEqual([innerAfter, outerAfter]);
});
it("adds specs", function() {
var env = new j$.Env(),
fakeQueue = {
add: jasmine.createSpy()
},
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueFactory: function() {
return fakeQueue
}
}),
fakeSpec = {};
expect(suite.specs.length).toEqual(0);
suite.addSpec(fakeSpec);
expect(suite.specs.length).toEqual(1);
});
it("adds suites", function() {
var env = new j$.Env(),
fakeQueue = {
add: jasmine.createSpy()
},
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueFactory: function() {
return fakeQueue
}
}),
anotherSuite = new j$.Suite({
env: env,
description: "I am another suite",
queueFactory: function() {
return fakeQueue
}
});
expect(suite.suites.length).toEqual(0);
suite.addSuite(anotherSuite);
expect(suite.suites.length).toEqual(1);
});
it("can be disabled", function() {
var env = new j$.Env(),
fakeQueueRunner = jasmine.createSpy('fake queue runner'),
suite = new j$.Suite({
env: env,
description: "with a child suite",
queueRunner: fakeQueueRunner
});
suite.disable();
expect(suite.disabled).toBe(true);
suite.execute();
expect(fakeQueueRunner).not.toHaveBeenCalled();
});
it("delegates execution of its specs and suites", function() {
var env = new j$.Env(),
parentSuiteDone = jasmine.createSpy('parent suite done'),
fakeQueueRunnerForParent = jasmine.createSpy('fake parent queue runner'),
parentSuite = new j$.Suite({
env: env,
description: "I am a parent suite",
queueRunner: fakeQueueRunnerForParent
}),
fakeQueueRunner = jasmine.createSpy('fake queue runner'),
suite = new j$.Suite({
env: env,
description: "with a child suite",
queueRunner: fakeQueueRunner
}),
fakeSpec1 = {
execute: jasmine.createSpy('fakeSpec1')
};
spyOn(suite, "execute");
parentSuite.addSpec(fakeSpec1);
parentSuite.addSuite(suite);
parentSuite.execute(parentSuiteDone);
var parentSuiteFns = fakeQueueRunnerForParent.calls.mostRecent().args[0].fns;
parentSuiteFns[0]();
expect(fakeSpec1.execute).toHaveBeenCalled();
parentSuiteFns[1]();
expect(suite.execute).toHaveBeenCalled();
});
it("calls a provided onStart callback when starting", function() {
var env = new j$.Env(),
suiteStarted = jasmine.createSpy('suiteStarted'),
fakeQueueRunner = function(attrs) { attrs.onComplete(); },
suite = new j$.Suite({
env: env,
description: "with a child suite",
onStart: suiteStarted,
queueRunner: fakeQueueRunner
}),
fakeSpec1 = {
execute: jasmine.createSpy('fakeSpec1')
};
suite.execute();
expect(suiteStarted).toHaveBeenCalledWith(suite);
});
it("calls a provided onComplete callback when done", function() {
var env = new j$.Env(),
suiteCompleted = jasmine.createSpy('parent suite done'),
fakeQueueRunner = function(attrs) { attrs.onComplete(); },
suite = new j$.Suite({
env: env,
description: "with a child suite",
queueRunner: fakeQueueRunner
}),
fakeSpec1 = {
execute: jasmine.createSpy('fakeSpec1')
};
suite.execute(suiteCompleted);
expect(suiteCompleted).toHaveBeenCalled();
});
it("calls a provided result callback when done", function() {
var env = new j$.Env(),
suiteResultsCallback = jasmine.createSpy('suite result callback'),
fakeQueueRunner = function(attrs) { attrs.onComplete(); },
suite = new j$.Suite({
env: env,
description: "with a child suite",
queueRunner: fakeQueueRunner,
resultCallback: suiteResultsCallback
}),
fakeSpec1 = {
execute: jasmine.createSpy('fakeSpec1')
};
suite.execute();
expect(suiteResultsCallback).toHaveBeenCalledWith({
id: suite.id,
status: '',
description: "with a child suite",
fullName: "with a child suite"
});
});
});
});

13
spec/core/TimerSpec.js Normal file
View File

@@ -0,0 +1,13 @@
describe("Timer", function() {
it("reports the time elapsed", function() {
var fakeNow = jasmine.createSpy('fake Date.now'),
timer = new j$.Timer({now: fakeNow});
fakeNow.and.callReturn(100);
timer.start();
fakeNow.and.callReturn(200);
expect(timer.elapsed()).toEqual(100);
});
});

View File

@@ -1,39 +1,28 @@
describe("jasmine.util", function() {
describe("extend", function () {
it("should add properies to a destination object ", function() {
var destination = {baz: 'baz'};
jasmine.util.extend(destination, {
foo: 'foo', bar: 'bar'
});
expect(destination).toEqual({foo: 'foo', bar: 'bar', baz: 'baz'});
});
it("should replace properies that already exist on a destination object", function() {
var destination = {foo: 'foo'};
jasmine.util.extend(destination, {
foo: 'bar'
});
expect(destination).toEqual({foo: 'bar'});
jasmine.util.extend(destination, {
foo: null
});
expect(destination).toEqual({foo: null});
});
});
describe("j$.util", function() {
describe("isArray_", function() {
it("should return true if the argument is an array", function() {
expect(jasmine.isArray_([])).toBe(true);
expect(jasmine.isArray_(['a'])).toBe(true);
expect(j$.isArray_([])).toBe(true);
expect(j$.isArray_(['a'])).toBe(true);
});
it("should return false if the argument is not an array", function() {
expect(jasmine.isArray_(undefined)).toBe(false);
expect(jasmine.isArray_({})).toBe(false);
expect(jasmine.isArray_(function() {})).toBe(false);
expect(jasmine.isArray_('foo')).toBe(false);
expect(jasmine.isArray_(5)).toBe(false);
expect(jasmine.isArray_(null)).toBe(false);
expect(j$.isArray_(undefined)).toBe(false);
expect(j$.isArray_({})).toBe(false);
expect(j$.isArray_(function() {})).toBe(false);
expect(j$.isArray_('foo')).toBe(false);
expect(j$.isArray_(5)).toBe(false);
expect(j$.isArray_(null)).toBe(false);
});
});
describe("isUndefined", function() {
it("reports if a variable is defined", function() {
var a;
expect(j$.util.isUndefined(a)).toBe(true);
expect(j$.util.isUndefined(undefined)).toBe(true);
var undefined = "diz be undefined yo";
expect(j$.util.isUndefined(undefined)).toBe(false);
});
});
});

View File

@@ -1,118 +0,0 @@
describe('WaitsForBlock', function () {
var env, suite, timeout, spec, message, onComplete, fakeTimer;
beforeEach(function() {
env = new jasmine.Env();
env.updateInterval = 0;
suite = new jasmine.Suite(env, 'suite 1');
timeout = 1000;
spec = new jasmine.Spec(env, suite);
message = "some error message";
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;
};
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
expect(onComplete).not.toHaveBeenCalled();
block.execute(onComplete);
expect(onComplete).toHaveBeenCalled();
});
it('latchFunction should run in same scope as spec', function () {
var result;
var latchFunction = function() {
result = this.scopedValue;
};
spec.scopedValue = 'foo';
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
block.execute(onComplete);
expect(result).toEqual('foo');
});
it('should fail spec and call onComplete if there is an error in the latchFunction', function() {
var latchFunction = jasmine.createSpy('latchFunction').andThrow('some error');
spyOn(spec, 'fail');
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
block.execute(onComplete);
expect(spec.fail).toHaveBeenCalledWith('some error');
expect(onComplete).toHaveBeenCalled();
});
describe("if latchFunction returns false", function() {
var latchFunction, fakeTimer;
beforeEach(function() {
latchFunction = jasmine.createSpy('latchFunction').andReturn(false);
fakeTimer = new jasmine.FakeTimer();
env.setTimeout = fakeTimer.setTimeout;
env.clearTimeout = fakeTimer.clearTimeout;
env.setInterval = fakeTimer.setInterval;
env.clearInterval = fakeTimer.clearInterval;
});
it('latchFunction should be retried after 10 ms', function () {
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
expect(latchFunction).not.toHaveBeenCalled();
block.execute(onComplete);
expect(latchFunction.callCount).toEqual(1);
fakeTimer.tick(5);
expect(latchFunction.callCount).toEqual(1);
fakeTimer.tick(5);
expect(latchFunction.callCount).toEqual(2);
});
it('onComplete should be called if latchFunction returns true before timeout', function () {
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
expect(onComplete).not.toHaveBeenCalled();
block.execute(onComplete);
expect(onComplete).not.toHaveBeenCalled();
latchFunction.andReturn(true);
fakeTimer.tick(100);
expect(onComplete).toHaveBeenCalled();
});
it('spec should fail with the passed message if the timeout is reached (and not call onComplete)', function () {
spyOn(spec, 'fail');
var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
block.execute(onComplete);
expect(spec.fail).not.toHaveBeenCalled();
fakeTimer.tick(timeout);
expect(spec.fail).toHaveBeenCalled();
var failMessage = spec.fail.mostRecentCall.args[0].message;
expect(failMessage).toMatch(message);
expect(onComplete).toHaveBeenCalled();
});
});
});

View File

@@ -0,0 +1,219 @@
describe("matchersUtil", function() {
describe("equals", function() {
it("passes for literals that are threequal", function() {
expect(j$.matchersUtil.equals(null, null)).toBe(true);
expect(j$.matchersUtil.equals(void 0, void 0)).toBe(true);
});
it("fails for things that are not equivalent", function() {
expect(j$.matchersUtil.equals({a: "foo"}, 1)).toBe(false);
});
it("passes for Strings that are equivalent", function() {
expect(j$.matchersUtil.equals("foo", "foo")).toBe(true);
});
it("fails for Strings that are not equivalent", function() {
expect(j$.matchersUtil.equals("foo", "bar")).toBe(false);
});
it("passes for Numbers that are equivalent", function() {
expect(j$.matchersUtil.equals(123, 123)).toBe(true);
});
it("fails for Numbers that are not equivalent", function() {
expect(j$.matchersUtil.equals(123, 456)).toBe(false);
});
it("passes for Dates that are equivalent", function() {
expect(j$.matchersUtil.equals(new Date("Jan 1, 1970"), new Date("Jan 1, 1970"))).toBe(true);
});
it("fails for Dates that are not equivalent", function() {
expect(j$.matchersUtil.equals(new Date("Jan 1, 1970"), new Date("Feb 3, 1991"))).toBe(false);
});
it("passes for Booleans that are equivalent", function() {
expect(j$.matchersUtil.equals(true, true)).toBe(true);
});
it("fails for Booleans that are not equivalent", function() {
expect(j$.matchersUtil.equals(true, false)).toBe(false);
});
it("passes for RegExps that are equivalent", function() {
expect(j$.matchersUtil.equals(/foo/, /foo/)).toBe(true);
});
it("fails for RegExps that are not equivalent", function() {
expect(j$.matchersUtil.equals(/foo/, /bar/)).toBe(false);
expect(j$.matchersUtil.equals(new RegExp("foo", "i"), new RegExp("foo"))).toBe(false);
});
it("passes for Arrays that are equivalent", function() {
expect(j$.matchersUtil.equals([1, 2], [1, 2])).toBe(true);
});
it("fails for Arrays that are not equivalent", function() {
expect(j$.matchersUtil.equals([1, 2], [1, 2, 3])).toBe(false);
});
it("passes for Errors that are the same type and have the same message", function() {
expect(j$.matchersUtil.equals(new Error("foo"), new Error("foo"))).toBe(true);
});
it("fails for Errors that are the same type and have different messages", function() {
expect(j$.matchersUtil.equals(new Error("foo"), new Error("bar"))).toBe(false);
});
it("passes for Objects that are equivalent (simple case)", function() {
expect(j$.matchersUtil.equals({a: "foo"}, {a: "foo"})).toBe(true);
});
it("fails for Objects that are not equivalent (simple case)", function() {
expect(j$.matchersUtil.equals({a: "foo"}, {a: "bar"})).toBe(false);
});
it("passes for Objects that are equivalent (deep case)", function() {
expect(j$.matchersUtil.equals({a: "foo", b: { c: "bar"}}, {a: "foo", b: { c: "bar"}})).toBe(true);
});
it("fails for Objects that are not equivalent (deep case)", function() {
expect(j$.matchersUtil.equals({a: "foo", b: { c: "baz"}}, {a: "foo", b: { c: "bar"}})).toBe(false);
});
it("passes for Objects that are equivalent (with cycles)", function() {
var actual = { a: "foo" },
expected = { a: "foo" };
actual.b = actual;
expected.b = actual;
expect(j$.matchersUtil.equals(actual, expected)).toBe(true);
});
it("fails for Objects that are not equivalent (with cycles)", function() {
var actual = { a: "foo" },
expected = { a: "bar" };
actual.b = actual;
expected.b = actual;
expect(j$.matchersUtil.equals(actual, expected)).toBe(false);
});
it("fails when comparing an empty object to an empty array (issue #114)", function() {
var emptyObject = {},
emptyArray = [];
expect(j$.matchersUtil.equals(emptyObject, emptyArray)).toBe(false);
expect(j$.matchersUtil.equals(emptyArray, emptyObject)).toBe(false);
});
it("passes for equivalent frozen objects (GitHub issue #266)", function() {
if (jasmine.getEnv().ieVersion < 9) { return; }
var a = { foo: 1 },
b = {foo: 1 };
Object.freeze(a);
Object.freeze(b);
expect(j$.matchersUtil.equals(a,b)).toBe(true);
});
it("passes when Any is used", function() {
var number = 3,
anyNumber = new j$.Any(Number);
expect(j$.matchersUtil.equals(number, anyNumber)).toBe(true);
expect(j$.matchersUtil.equals(anyNumber, number)).toBe(true);
});
it("fails when Any is compared to something unexpected", function() {
var number = 3,
anyString = new j$.Any(String);
expect(j$.matchersUtil.equals(number, anyString)).toBe(false);
expect(j$.matchersUtil.equals(anyString, number)).toBe(false);
});
it("passes when ObjectContaining is used", function() {
var obj = {
foo: 3,
bar: 7
};
expect(j$.matchersUtil.equals(obj, new j$.ObjectContaining({foo: 3}))).toBe(true);
});
it("passes when a custom equality matcher returns true", function() {
var tester = function(a, b) { return true; };
expect(j$.matchersUtil.equals(1, 2, [tester])).toBe(true);
});
it("fails for equivalents when a custom equality matcher returns false", function() {
var tester = function(a, b) { return false; };
expect(j$.matchersUtil.equals(1, 2, [tester])).toBe(false);
});
});
describe("contains", function() {
it("passes when expected is a substring of actual", function() {
expect(j$.matchersUtil.contains("ABC", "B")).toBe(true);
});
it("fails when expected is a not substring of actual", function() {
expect(j$.matchersUtil.contains("ABC", "X")).toBe(false);
});
it("passes when expected is an element in an actual array", function() {
expect(j$.matchersUtil.contains(['foo', 'bar'], 'foo')).toBe(true);
});
it("fails when expected is not an element in an actual array", function() {
expect(j$.matchersUtil.contains(['foo', 'bar'], 'baz')).toBe(false);
});
it("passes with mixed-element arrays", function() {
expect(j$.matchersUtil.contains(["foo", {some: "bar"}], "foo")).toBe(true);
expect(j$.matchersUtil.contains(["foo", {some: "bar"}], {some: "bar"})).toBe(true);
});
it("uses custom equality testers if passed in and actual is an Array", function() {
var customTester = function(a, b) {return true;};
expect(j$.matchersUtil.contains([1, 2], 2, [customTester])).toBe(true);
});
});
describe("buildMessage", function() {
it("builds an English sentence for a failure case", function() {
var actual = "foo",
name = "toBar",
message = j$.matchersUtil.buildFailureMessage(name, false, actual);
expect(message).toEqual("Expected 'foo' to bar.");
});
it("builds an English sentence for a 'not' failure case", function() {
var actual = "foo",
name = "toBar",
isNot = true,
message = message = j$.matchersUtil.buildFailureMessage(name, isNot, actual);
expect(message).toEqual("Expected 'foo' not to bar.");
});
it("builds an English sentence for an arbitrary array of expected arguments", function() {
var actual = "foo",
name = "toBar",
message = j$.matchersUtil.buildFailureMessage(name, false, actual, "quux", "corge");
expect(message).toEqual("Expected 'foo' to bar 'quux', 'corge'.");
});
});
});

View File

@@ -0,0 +1,51 @@
describe("toBeCloseTo", function() {
it("passes when within two decimal places by default", function() {
var matcher = j$.matchers.toBeCloseTo(),
result;
result = matcher.compare(0, 0);
expect(result.pass).toBe(true);
result = matcher.compare(0, 0.001);
expect(result.pass).toBe(true);
});
it("fails when not within two decimal places by default", function() {
var matcher = j$.matchers.toBeCloseTo(),
result;
result = matcher.compare(0, 0.01);
expect(result.pass).toBe(false);
});
it("accepts an optional precision argument", function() {
var matcher = j$.matchers.toBeCloseTo(),
result;
result = matcher.compare(0, 0.1, 0);
expect(result.pass).toBe(true);
result = matcher.compare(0, 0.0001, 3);
expect(result.pass).toBe(true);
});
it("rounds expected values", function() {
var matcher = j$.matchers.toBeCloseTo(),
result;
result = matcher.compare(1.23, 1.229);
expect(result.pass).toBe(true);
result = matcher.compare(1.23, 1.226);
expect(result.pass).toBe(true);
result = matcher.compare(1.23, 1.225);
expect(result.pass).toBe(true);
result = matcher.compare(1.23, 1.2249999);
expect(result.pass).toBe(false);
result = matcher.compare(1.23, 1.234);
expect(result.pass).toBe(true);
});
});

View File

@@ -0,0 +1,18 @@
describe("toBeDefined", function() {
it("matches for defined values", function() {
var matcher = j$.matchers.toBeDefined(),
result;
result = matcher.compare('foo');
expect(result.pass).toBe(true);
});
it("fails when matching undefined values", function() {
var matcher = j$.matchers.toBeDefined(),
result;
result = matcher.compare(void 0);
expect(result.pass).toBe(false);
})
});

View File

@@ -0,0 +1,38 @@
describe("toBeFalsy", function() {
it("passes for 'falsy' values", function() {
var matcher = j$.matchers.toBeFalsy(),
result;
result = matcher.compare(false);
expect(result.pass).toBe(true);
result = matcher.compare(0);
expect(result.pass).toBe(true);
result = matcher.compare('');
expect(result.pass).toBe(true);
result = matcher.compare(null);
expect(result.pass).toBe(true);
result = matcher.compare(void 0);
expect(result.pass).toBe(true);
});
it("fails for 'truthy' values", function() {
var matcher = j$.matchers.toBeFalsy(),
result;
result = matcher.compare(true);
expect(result.pass).toBe(false);
result = matcher.compare(1);
expect(result.pass).toBe(false);
result = matcher.compare("foo");
expect(result.pass).toBe(false);
result = matcher.compare({});
expect(result.pass).toBe(false);
});
});

View File

@@ -0,0 +1,19 @@
describe("toBeGreaterThan", function() {
it("passes when actual > expected", function() {
var matcher = j$.matchers.toBeGreaterThan(),
result;
result = matcher.compare(2, 1);
expect(result.pass).toBe(true);
});
it("fails when actual <= expected", function() {
var matcher = j$.matchers.toBeGreaterThan();
result = matcher.compare(1, 1);
expect(result.pass).toBe(false);
result = matcher.compare(1, 2);
expect(result.pass).toBe(false);
});
});

View File

@@ -0,0 +1,20 @@
describe("toBeLessThan", function() {
it("passes when actual < expected", function() {
var matcher = j$.matchers.toBeLessThan(),
result;
result = matcher.compare(1, 2);
expect(result.pass).toBe(true);
});
it("fails when actual <= expected", function() {
var matcher = j$.matchers.toBeLessThan(),
result;
result = matcher.compare(1, 1);
expect(result.pass).toBe(false);
result = matcher.compare(2, 1);
expect(result.pass).toBe(false);
});
});

View File

@@ -0,0 +1,36 @@
describe("toBeNaN", function() {
it("passes for NaN with a custom .not fail", function() {
var matcher = j$.matchers.toBeNaN(),
result;
result = matcher.compare(Number.NaN);
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected actual not to be NaN.");
});
it("fails for anything not a NaN", function() {
var matcher = j$.matchers.toBeNaN();
result = matcher.compare(1);
expect(result.pass).toBe(false);
result = matcher.compare(null);
expect(result.pass).toBe(false);
result = matcher.compare(void 0);
expect(result.pass).toBe(false);
result = matcher.compare('');
expect(result.pass).toBe(false);
result = matcher.compare(Number.POSITIVE_INFINITY);
expect(result.pass).toBe(false);
});
it("has a custom message on failure", function() {
var matcher = j$.matchers.toBeNaN(),
result = matcher.compare(0);
expect(result.message).toEqual("Expected 0 to be NaN.");
});
});

View File

@@ -0,0 +1,17 @@
describe("toBeNull", function() {
it("passes for null", function() {
var matcher = j$.matchers.toBeNull(),
result;
result = matcher.compare(null);
expect(result.pass).toBe(true);
});
it("fails for non-null", function() {
var matcher = j$.matchers.toBeNull(),
result;
result = matcher.compare('foo');
expect(result.pass).toBe(false);
});
});

View File

@@ -0,0 +1,17 @@
describe("toBe", function() {
it("passes when actual === expected", function() {
var matcher = j$.matchers.toBe(),
result;
result = matcher.compare(1, 1);
expect(result.pass).toBe(true);
});
it("fails when actual !== expected", function() {
var matcher = j$.matchers.toBe(),
result;
result = matcher.compare(1, 2);
expect(result.pass).toBe(false);
});
});

View File

@@ -0,0 +1,38 @@
describe("toBeTruthy", function() {
it("passes for 'truthy' values", function() {
var matcher = j$.matchers.toBeTruthy(),
result;
result = matcher.compare(true);
expect(result.pass).toBe(true);
result = matcher.compare(1);
expect(result.pass).toBe(true);
result = matcher.compare("foo");
expect(result.pass).toBe(true);
result = matcher.compare({});
expect(result.pass).toBe(true);
});
it("fails for 'falsy' values", function() {
var matcher = j$.matchers.toBeTruthy(),
result;
result = matcher.compare(false);
expect(result.pass).toBe(false);
result = matcher.compare(0);
expect(result.pass).toBe(false);
result = matcher.compare('');
expect(result.pass).toBe(false);
result = matcher.compare(null);
expect(result.pass).toBe(false);
result = matcher.compare(void 0);
expect(result.pass).toBe(false);
});
});

View File

@@ -0,0 +1,17 @@
describe("toBeUndefined", function() {
it("passes for undefined values", function() {
var matcher = j$.matchers.toBeUndefined(),
result;
result = matcher.compare(void 0);
expect(result.pass).toBe(true);
});
it("fails when matching defined values", function() {
var matcher = j$.matchers.toBeUndefined();
result = matcher.compare('foo');
expect(result.pass).toBe(false);
})
});

View File

@@ -0,0 +1,24 @@
describe("toContain", function() {
it("delegates to j$.matchersUtil.contains", function() {
var util = {
contains: jasmine.createSpy('delegated-contains').and.callReturn(true)
},
matcher = j$.matchers.toContain(util);
result = matcher.compare("ABC", "B");
expect(util.contains).toHaveBeenCalledWith("ABC", "B", []);
expect(result.pass).toBe(true);
});
it("delegates to j$.matchersUtil.contains, passing in equality testers if present", function() {
var util = {
contains: jasmine.createSpy('delegated-contains').and.callReturn(true)
},
customEqualityTesters = ['a', 'b'],
matcher = j$.matchers.toContain(util, customEqualityTesters);
result = matcher.compare("ABC", "B");
expect(util.contains).toHaveBeenCalledWith("ABC", "B", ['a', 'b']);
expect(result.pass).toBe(true);
});
});

View File

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

View File

@@ -0,0 +1,46 @@
describe("toHaveBeenCalled", function() {
it("passes when the actual was called, with a custom .not fail message", function() {
var matcher = j$.matchers.toHaveBeenCalled(),
calledSpy = j$.createSpy('called-spy'),
result;
calledSpy();
result = matcher.compare(calledSpy);
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected spy called-spy not to have been called.");
});
it("fails when the actual was not called", function() {
var matcher = j$.matchers.toHaveBeenCalled(),
uncalledSpy = j$.createSpy('uncalled spy');
result = matcher.compare(uncalledSpy);
expect(result.pass).toBe(false);
});
it("throws an exception when the actual is not a spy", function() {
var matcher = j$.matchers.toHaveBeenCalled(),
fn = function() {};
expect(function() { matcher.compare(fn) }).toThrow(new Error("Expected a spy, but got Function."));
});
it("throws an exception when invoked with any arguments", function() {
var matcher = j$.matchers.toHaveBeenCalled(),
spy = j$.createSpy('sample spy');
expect(function() { matcher.compare(spy, 'foo') }).toThrow(new Error("toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith"));
});
it("has a custom message on failure", function() {
var matcher = j$.matchers.toHaveBeenCalled(),
spy = j$.createSpy('sample-spy'),
result;
result = matcher.compare(spy);
expect(result.message).toEqual("Expected spy sample-spy to have been called.");
});
});

View File

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

View File

@@ -0,0 +1,34 @@
describe("toMatch", function() {
it("passes when RegExps are equivalent", function() {
var matcher = j$.matchers.toMatch(),
result;
result = matcher.compare(/foo/, /foo/);
expect(result.pass).toBe(true);
});
it("fails when RegExps are not equivalent", function() {
var matcher = j$.matchers.toMatch(),
result;
result = matcher.compare(/bar/, /foo/);
expect(result.pass).toBe(false);
});
it("passes when the actual matches the expected string as a pattern", function() {
var matcher = j$.matchers.toMatch(),
result;
result = matcher.compare('foosball', 'foo');
expect(result.pass).toBe(true);
});
it("fails when the actual matches the expected string as a pattern", function() {
var matcher = j$.matchers.toMatch(),
result;
result = matcher.compare('bar', 'foo');
expect(result.pass).toBe(false);
});
});

View File

@@ -0,0 +1,280 @@
describe("toThrowError", function() {
it("throws an error when the actual is not a function", function() {
var matcher = j$.matchers.toThrowError();
expect(function() {
matcher.compare({});
}).toThrow(new Error("Actual is not a Function")); // TODO: this needs to change for self-test
});
it("throws an error when the expected is not an Error, string, or RegExp", function() {
var matcher = j$.matchers.toThrowError(),
fn = function() {
throw new Error("foo");
};
expect(function() {
matcher.compare(fn, 1);
}).toThrow(new Error("Expected is not an Error, string, or RegExp.")); // TODO: this needs to change for self-test
});
it("throws an error when the expected error type is not an Error", function() {
var matcher = j$.matchers.toThrowError(),
fn = function() {
throw new Error("foo");
};
expect(function() {
matcher.compare(fn, void 0, "foo");
}).toThrow(new Error("Expected error type is not an Error.")); // TODO: this needs to change for self-test
});
it("throws an error when the expected error message is not a string or RegExp", function() {
var matcher = j$.matchers.toThrowError(),
fn = function() {
throw new Error("foo");
};
expect(function() {
matcher.compare(fn, Error, 1);
}).toThrow(new Error("Expected error message is not a string or RegExp.")); // TODO: this needs to change for self-test
});
it("fails if actual does not throw at all", function() {
var matcher = j$.matchers.toThrowError(),
fn = function() {
return true;
},
result;
result = matcher.compare(fn);
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw an Error.");
});
it("fails if thrown is not an instanceof Error", function() {
var matcher = j$.matchers.toThrowError(),
fn = function() {
throw 4;
},
result;
result = matcher.compare(fn);
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw an Error, but it threw 4.");
});
it("fails with the correct message if thrown is a falsy value", function() {
var matcher = j$.matchers.toThrowError(),
fn = function() {
throw undefined;
},
result;
result = matcher.compare(fn);
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw an Error, but it threw undefined.");
});
it("passes if thrown is a type of Error, but there is no expected error", function() {
var matcher = j$.matchers.toThrowError(),
fn = function() {
throw new TypeError();
},
result;
result = matcher.compare(fn);
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected function not to throw an Error, but it threw TypeError.");
});
it("passes if thrown is an Error and the expected is the same message", function() {
var matcher = j$.matchers.toThrowError(),
fn = function() {
throw new Error("foo");
},
result;
result = matcher.compare(fn, "foo");
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected function not to throw an exception with message 'foo'.");
});
it("fails if thrown is an Error and the expected is not the same message", function() {
var matcher = j$.matchers.toThrowError(),
fn = function() {
throw new Error("foo");
},
result;
result = matcher.compare(fn, "bar");
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw an exception with message 'bar', but it threw an exception with message 'foo'.");
});
it("passes if thrown is an Error and the expected is a RegExp that matches the message", function() {
var matcher = j$.matchers.toThrowError(),
fn = function() {
throw new Error("a long message");
},
result;
result = matcher.compare(fn, /long/);
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected function not to throw an exception with a message matching /long/.");
});
it("fails if thrown is an Error and the expected is a RegExp that does not match the message", function() {
var matcher = j$.matchers.toThrowError(),
fn = function() {
throw new Error("a long message");
},
result;
result = matcher.compare(fn, /foo/);
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw an exception with a message matching /foo/, but it threw an exception with message 'a long message'.");
});
it("passes if thrown is an Error and the expected the same Error", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
},
matcher = j$.matchers.toThrowError(util),
fn = function() {
throw new Error();
},
result;
result = matcher.compare(fn, Error);
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected function not to throw Error.");
});
it("passes if thrown is a custom error that takes arguments and the expected is the same error", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
},
matcher = j$.matchers.toThrowError(util),
CustomError = function CustomError(arg) { arg.x },
fn = function() {
throw new CustomError({ x: 1 });
},
result;
CustomError.prototype = new Error();
CustomError.prototype.constructor = CustomError;
result = matcher.compare(fn, CustomError);
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected function not to throw CustomError.");
});
it("fails if thrown is an Error and the expected is a different Error", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(false)
},
matcher = j$.matchers.toThrowError(util),
fn = function() {
throw new Error();
},
result;
result = matcher.compare(fn, TypeError);
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw TypeError, but it threw Error.");
});
it("passes if thrown is a type of Error and it is equal to the expected Error and message", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
},
matcher = j$.matchers.toThrowError(util),
fn = function() {
throw new TypeError("foo");
},
result;
result = matcher.compare(fn, TypeError, "foo");
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected function not to throw TypeError with message \"foo\".");
});
it("passes if thrown is a custom error that takes arguments and it is equal to the expected custom error and message", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
},
matcher = j$.matchers.toThrowError(util),
CustomError = function CustomError(arg) { this.message = arg.message },
fn = function() {
throw new CustomError({message: "foo"});
},
result;
CustomError.prototype = new Error();
CustomError.prototype.constructor = CustomError;
result = matcher.compare(fn, CustomError, "foo");
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected function not to throw CustomError with message \"foo\".");
});
it("fails if thrown is a type of Error and the expected is a different Error", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(false)
},
matcher = j$.matchers.toThrowError(util),
fn = function() {
throw new TypeError("foo");
},
result;
result = matcher.compare(fn, TypeError, "bar");
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw TypeError with message \"bar\", but it threw TypeError with message \"foo\".");
});
it("passes if thrown is a type of Error and has the same type as the expected Error and the message matches the exepcted message", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
},
matcher = j$.matchers.toThrowError(util),
fn = function() {
throw new TypeError("foo");
},
result;
result = matcher.compare(fn, TypeError, /foo/);
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected function not to throw TypeError with message matching /foo/.");
});
it("fails if thrown is a type of Error and the expected is a different Error", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(false)
},
matcher = j$.matchers.toThrowError(util),
fn = function() {
throw new TypeError("foo");
},
result;
result = matcher.compare(fn, TypeError, /bar/);
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw TypeError with message matching /bar/, but it threw TypeError with message \"foo\".");
});
});

View File

@@ -0,0 +1,98 @@
describe("toThrow", function() {
it("throws an error when the actual is not a function", function() {
var matcher = j$.matchers.toThrow();
expect(function() {
matcher.compare({});
}).toThrow(new Error("Actual is not a Function")); // TODO: this needs to change for self-test
});
it("fails if actual does not throw", function() {
var matcher = j$.matchers.toThrow(),
fn = function() {
return true;
},
result;
result = matcher.compare(fn);
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw an exception.");
});
it("passes if it throws but there is no expected", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
},
matcher = j$.matchers.toThrow(util),
fn = function() {
throw 5;
},
result;
result = matcher.compare(fn);
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected function not to throw, but it threw 5.");
});
it("passes even if what is thrown is falsy", function() {
var matcher = j$.matchers.toThrow(),
fn = function() {
throw undefined;
},
result;
result = matcher.compare(fn);
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected function not to throw, but it threw undefined.");
});
it("passes if what is thrown is equivalent to what is expected", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(true)
},
matcher = j$.matchers.toThrow(util),
fn = function() {
throw 5;
},
result;
result = matcher.compare(fn, 5);
expect(result.pass).toBe(true);
expect(result.message).toEqual("Expected function not to throw 5.");
});
it("fails if what is thrown is not equivalent to what is expected", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(false)
},
matcher = j$.matchers.toThrow(util),
fn = function() {
throw 5;
},
result;
result = matcher.compare(fn, "foo");
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw 'foo', but it threw 5.");
});
it("fails if what is thrown is not equivalent to undefined", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.callReturn(false)
},
matcher = j$.matchers.toThrow(util),
fn = function() {
throw 5;
},
result;
result = matcher.compare(fn, void 0);
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw undefined, but it threw 5.");
});
});

View File

@@ -0,0 +1,19 @@
(function(env) {
env.ieVersion = (function() {
var userAgent = jasmine.getGlobal().navigator.userAgent;
if (!userAgent) { return Number.MAX_VALUE; }
var match = /MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(userAgent);
return match ? parseFloat(match[1]) : Number.MAX_VALUE;
})();
env.safariVersion = (function() {
var userAgent = jasmine.getGlobal().navigator.userAgent;
if (!userAgent) { return Number.MAX_VALUE; }
var match = /Safari/.exec(userAgent) && /Version\/([0-9]{0,})/.exec(userAgent);
return match ? parseFloat(match[1]) : Number.MAX_VALUE;
})();
})(jasmine.getEnv());

View File

@@ -0,0 +1,494 @@
describe("New HtmlReporter", function() {
// TODO: Figure out why this isn't rendering...
it("builds the initial DOM elements, including the title banner", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() { return container; },
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
});
reporter.initialize();
// Main top-level elements
expect(container.querySelector("div.html-reporter")).toBeTruthy();
expect(container.querySelector("div.banner")).toBeTruthy();
expect(container.querySelector("div.alert")).toBeTruthy();
expect(container.querySelector("div.results")).toBeTruthy();
expect(container.querySelector("ul.symbol-summary")).toBeTruthy();
// title banner
var banner = container.querySelector(".banner");
var title = banner.querySelector(".title");
expect(title.innerHTML).toMatch(/Jasmine/);
var version = banner.querySelector(".version"),
versionText = 'textContent' in version ? version.textContent : version.innerText;
expect(versionText).toEqual(j$.version);
});
it("starts the timer when jasmine begins", function() {
var env = new jasmine.Env(),
startTimerSpy = jasmine.createSpy("start-timer-spy"),
reporter = new jasmine.HtmlReporter({
env: env,
createElement: function() { return document.createElement.apply(document, arguments); },
timer: { start: startTimerSpy }
});
reporter.jasmineStarted({});
expect(startTimerSpy).toHaveBeenCalled();
});
describe("when a spec is done", function() {
it("reports the status symbol of a disabled spec", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() { return container; },
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
});
reporter.initialize();
reporter.specDone({id: 789, status: "disabled", fullName: "symbols should have titles"});
var specEl = container.querySelector('.symbol-summary li');
expect(specEl.getAttribute("class")).toEqual("disabled");
expect(specEl.getAttribute("id")).toEqual("spec_789");
expect(specEl.getAttribute("title")).toEqual("symbols should have titles");
});
it("reports the status symbol of a pending spec", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() { return container; },
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
});
reporter.initialize();
reporter.specDone({id: 789, status: "pending"});
var specEl = container.querySelector('.symbol-summary li');
expect(specEl.getAttribute("class")).toEqual("pending");
expect(specEl.getAttribute("id")).toEqual("spec_789");
});
it("reports the status symbol of a passing spec", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() { return container; },
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
});
reporter.initialize();
reporter.specDone({id: 123, status: "passed"});
var statuses = container.querySelector(".symbol-summary");
var specEl = statuses.querySelector("li");
expect(specEl.getAttribute("class")).toEqual("passed");
expect(specEl.getAttribute("id")).toEqual("spec_123");
});
it("reports the status symbol of a failing spec", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() { return container; },
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
});
reporter.initialize();
reporter.specDone({
id: 345,
status: "failed",
failedExpectations: []
});
var specEl = container.querySelector(".symbol-summary li");
expect(specEl.getAttribute("class")).toEqual("failed");
expect(specEl.getAttribute("id")).toEqual("spec_345");
});
});
describe("when Jasmine is done", function() {
it("reports the run time", function() {
var env = new j$.Env(),
container = document.createElement("div"),
timer = jasmine.createSpyObj('timer', ['start', 'elapsed']),
getContainer = function() { return container; },
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
timer: timer
});
reporter.initialize();
reporter.jasmineStarted({});
timer.elapsed.and.callReturn(100);
reporter.jasmineDone();
var duration = container.querySelector(".banner .duration");
expect(duration.innerHTML).toMatch(/finished in 0.1s/);
});
it("reports the suite and spec names with status", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() { return container; },
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
});
reporter.initialize();
reporter.jasmineStarted({});
reporter.suiteStarted({
id: 1,
description: "A Suite",
fullName: "A Suite"
});
var specResult = {
id: 123,
description: "with a spec",
fullName: "A Suite with a spec",
status: "passed"
};
reporter.specStarted(specResult);
reporter.specDone(specResult);
reporter.suiteStarted({
id: 2,
description: "inner suite",
fullName: "A Suite inner suite"
});
var specResult = {
id: 124,
description: "with another spec",
fullName: "A Suite inner suite with another spec",
status: "passed"
};
reporter.specStarted(specResult);
reporter.specDone(specResult);
reporter.suiteDone({id: 2});
specResult = {
id: 209,
description: "with a failing spec",
fullName: "A Suite inner with a failing spec",
status: "failed",
failedExpectations: []
};
reporter.specStarted(specResult);
reporter.specDone(specResult);
reporter.suiteDone({id: 1});
reporter.jasmineDone({});
var summary = container.querySelector(".summary");
expect(summary.childNodes.length).toEqual(1);
var outerSuite = summary.childNodes[0];
expect(outerSuite.childNodes.length).toEqual(4);
var classes = [];
for (var i = 0; i < outerSuite.childNodes.length; i++) {
var node = outerSuite.childNodes[i];
classes.push(node.getAttribute("class"));
}
expect(classes).toEqual(["suite-detail", "specs", "suite", "specs"]);
var suiteDetail = outerSuite.childNodes[0];
var suiteLink = suiteDetail.childNodes[0];
expect(suiteLink.innerHTML).toEqual("A Suite");
expect(suiteLink.getAttribute('href')).toEqual("?spec=A%20Suite");
var specs = outerSuite.childNodes[1];
var spec = specs.childNodes[0];
expect(spec.getAttribute("class")).toEqual("passed");
expect(spec.getAttribute("id")).toEqual("spec-123");
var specLink = spec.childNodes[0];
expect(specLink.innerHTML).toEqual("with a spec");
expect(specLink.getAttribute("href")).toEqual("?spec=A%20Suite%20with%20a%20spec");
// expect(specLink.getAttribute("title")).toEqual("A Suite with a spec");
});
describe("UI for raising/catching exceptions", function() {
it("should be unchecked if the env is catching", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() {
return container;
},
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
reporter.initialize();
reporter.jasmineDone({});
var raisingExceptionsUI = container.querySelector(".raise");
expect(raisingExceptionsUI.checked).toBe(false);
});
it("should be checked if the env is not catching", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() {
return container;
},
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
reporter.initialize();
env.catchExceptions(false);
reporter.jasmineDone({});
var raisingExceptionsUI = container.querySelector(".raise");
expect(raisingExceptionsUI.checked).toBe(true);
});
it("should affect the query param for catching exceptions", function() {
var env = new j$.Env(),
container = document.createElement("div"),
exceptionsClickHandler = jasmine.createSpy("raise exceptions checked"),
getContainer = function() {
return container;
},
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
onRaiseExceptionsClick: exceptionsClickHandler,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
reporter.initialize();
reporter.jasmineDone({});
var input = container.querySelector(".raise");
input.click();
expect(exceptionsClickHandler).toHaveBeenCalled();
});
});
describe("and all specs pass", function() {
var env, container, reporter;
beforeEach(function() {
env = new j$.Env();
container = document.createElement("div");
getContainer = function() { return container; },
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
});
reporter.initialize();
reporter.jasmineStarted({});
reporter.specDone({
id: 123,
description: "with a spec",
fullName: "A Suite with a spec",
status: "passed"
});
reporter.specDone({
id: 124,
description: "with another spec",
fullName: "A Suite inner suite with another spec",
status: "passed"
});
reporter.jasmineDone({});
});
it("reports the specs counts", function() {
var alertBars = container.querySelectorAll(".alert .bar");
expect(alertBars.length).toEqual(1);
expect(alertBars[0].getAttribute('class')).toMatch(/passed/);
expect(alertBars[0].innerHTML).toMatch(/2 specs, 0 failures/);
});
it("reports no failure details", function() {
var specFailure = container.querySelector(".failures");
expect(specFailure.childNodes.length).toEqual(0);
});
it("reports no pending specs", function() {
var alertBar = container.querySelector(".alert .bar");
expect(alertBar.innerHTML).not.toMatch(/pending spec[s]/);
});
});
describe("and there are pending specs", function() {
var env, container, reporter;
beforeEach(function() {
env = new j$.Env();
container = document.createElement("div");
getContainer = function() { return container; },
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
});
reporter.initialize();
reporter.jasmineStarted({});
reporter.specDone({
id: 123,
description: "with a spec",
fullName: "A Suite with a spec",
status: "pending"
});
reporter.jasmineDone({});
});
it("reports the pending specs count", function() {
var alertBar = container.querySelector(".alert .bar");
expect(alertBar.innerHTML).toMatch(/1 spec, 0 failures, 1 pending spec/);
});
it("reports no failure details", function() {
var specFailure = container.querySelector(".failures");
expect(specFailure.childNodes.length).toEqual(0);
});
});
describe("and some tests fail", function() {
var env, container, reporter;
beforeEach(function() {
env = new j$.Env();
container = document.createElement("div"),
getContainer = function() { return container; },
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
});
reporter.initialize();
reporter.jasmineStarted({});
var passingResult = {id: 123, status: "passed"};
reporter.specStarted(passingResult);
reporter.specDone(passingResult);
var failingResult = {
id: 124,
status: "failed",
description: "a failing spec",
fullName: "a suite with a failing spec",
failedExpectations: [
{
message: "a failure message",
stack: "a stack trace"
}
]
};
reporter.specStarted(failingResult);
reporter.specDone(failingResult);
reporter.jasmineDone({});
});
it("reports the specs counts", function() {
var alertBar = container.querySelector(".alert .bar");
expect(alertBar.getAttribute('class')).toMatch(/failed/);
expect(alertBar.innerHTML).toMatch(/2 specs, 1 failure/);
});
it("reports failure messages and stack traces", function() {
var specFailures = container.querySelector(".failures");
var failure = specFailures.childNodes[0];
expect(failure.getAttribute("class")).toMatch(/failed/);
expect(failure.getAttribute("class")).toMatch(/spec-detail/);
var specLink = failure.childNodes[0];
expect(specLink.getAttribute("class")).toEqual("description");
expect(specLink.getAttribute("title")).toEqual("a suite with a failing spec");
expect(specLink.getAttribute("href")).toEqual("?spec=a%20suite%20with%20a%20failing%20spec");
var message = failure.childNodes[1].childNodes[0];
expect(message.getAttribute("class")).toEqual("result-message");
expect(message.innerHTML).toEqual("a failure message");
var stackTrace = failure.childNodes[1].childNodes[1];
expect(stackTrace.getAttribute("class")).toEqual("stack-trace");
expect(stackTrace.innerHTML).toEqual("a stack trace");
});
it("allows switching between failure details and the spec summary", function() {
var menuBar = container.querySelectorAll(".bar")[1];
expect(menuBar.getAttribute("class")).not.toMatch(/hidden/);
var link = menuBar.querySelector('a');
expect(link.innerHTML).toEqual("Failures");
expect(link.getAttribute("href")).toEqual("#");
});
it("sets the reporter to 'Failures List' mode", function() {
var reporterNode = container.querySelector(".html-reporter");
expect(reporterNode.getAttribute("class")).toMatch("failure-list");
});
});
});
});

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