Compare commits

...

409 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
ragaskar
6b5956724b Version bump to rc4 2011-09-01 07:26:07 -04:00
Rajan Agaskar
ec24992250 Merge pull request #123 from Osukaru/master
fixed html comments in SpecRunner.html example
2011-09-01 04:23:41 -07:00
Osukaru
83f232237d fixed html comments 2011-08-26 01:22:11 +03:00
Rajan Agaskar
98d32bb4a4 Merge pull request #111 from qfox/patch-1
Add missing semi.
2011-07-21 04:07:52 -07:00
qfox
c4f27ae377 ASI trolling 2011-07-21 00:58:53 -07:00
ragaskar
a075c75bce Version bump to 1.1.0.rc3 2011-07-13 07:23:29 -04:00
ragaskar
a617b59e6a Bump to rc2 2011-06-24 21:34:29 -04:00
ragaskar
917b37481e Update rake 2011-06-24 21:25:06 -04:00
ragaskar
67bbc98faa Bump version 2011-06-24 21:22:19 -04:00
Davis W. Frank
620f7b6e4c Updates to Pages; Updates to docs; 2011-06-23 19:02:17 -07:00
ragaskar
b722f416c7 Write out version.rb on dist build 2011-06-23 07:55:04 -04:00
ragaskar
634a7dc402 Rollback pages submodule bump 2011-06-23 07:32:05 -04:00
Davis W. Frank
a4522e4dce Updated Release readme 2011-06-21 20:19:28 -07:00
Davis W. Frank
e113c338d0 Merge branch 'master' of github.com:pivotal/jasmine 2011-06-21 20:11:10 -07:00
ragaskar
b81f690a25 Require JSON in time for the gemspec 2011-06-21 08:05:41 -04:00
ragaskar
c06e189699 Ignore tags 2011-06-21 08:05:20 -04:00
Davis W. Frank
67b6cfb828 Improve the rake standalone task 2011-06-20 18:27:57 -07:00
Davis W. Frank
57e622fb2a Fix to version structure for "release_candidate" 2011-06-20 18:17:24 -07:00
Davis W. Frank
c0664dd6aa merge 2011-06-20 08:46:37 -07:00
Davis W. Frank
b640ce6fc0 wip on readme for release 2011-06-20 07:32:40 -07:00
ragaskar
e9af7834f5 Better argument handling in Jasmine::Core#spec_files 2011-06-18 09:43:14 -04:00
ragaskar
0d43ae9c38 Give Jasmine::Core access to jasmine specs
[#13128217]
2011-06-18 09:39:23 -04:00
ragaskar
30431a3958 Gem-ize jasmine
[Finishes #13128217]
2011-06-17 21:01:42 -04:00
Davis W. Frank
3775919c92 remove old, commented-out tasks 2011-06-17 08:23:17 -07:00
Davis W. Frank
a692ff8c95 Need HAML in the Gemfile; continued fixes to the Rake tasks 2011-06-17 08:20:22 -07:00
Davis W. Frank
e4e9b51544 rename TrivialConsoleReporter to ConsoleReporter 2011-06-16 22:35:57 -07:00
Davis W. Frank
0b97951766 Better coloring of output of Rake tasks; Turn off colored output in Rake tasks if not on a TTY (not sure if it works in Hudson); Add support to TCR for turning off colors since there is code to calc options but it wasn't used; NOTE: coloring in TCR should be MUCH better tested. 2011-06-16 22:34:11 -07:00
Davis W. Frank
75dd391d57 should fix red build 2011-06-16 08:33:59 -07:00
Davis W. Frank
ae24e00c0f Support for release candidates in the version.json file; propagates up through the version string everywhere: filenames, ZIP, source code 2011-06-15 18:37:12 -07:00
Davis W. Frank
6b2e45eab5 Refactor of standalone build tasks; Better templating of the core runner.html and the example SpecRunner.html 2011-06-15 09:15:40 -07:00
Davis W. Frank
e59171935f breaking up distribution tasks; moving version to a template to have a simpler concat function 2011-06-14 08:30:14 -07:00
Davis W. Frank
2ba0aa371c Refactor how the distribution is built 2011-06-13 08:23:10 -07:00
Davis W. Frank
c2ed71717f Remove link to github page from Runner 2011-06-11 16:51:16 -07:00
Davis W. Frank
09e8822107 WIP on new Contribution docs 2011-06-11 16:47:12 -07:00
Davis W. Frank
15763c2eb0 Output number of expected specs for browser, node before running specs. NOTE: We distribution tasks still broken. 2011-06-11 15:59:34 -07:00
Davis W. Frank
3f264cde34 fix so that all specs are pulled into runner.html 2011-06-11 14:48:41 -07:00
Davis W. Frank
f83cb7f766 Runner.html is now generated (ensures all source & specs get tested); beginnings of refactoring of Rake tasks. 2011-06-09 19:24:51 -07:00
Davis W. Frank
9d5470ff55 removing expectation count from TCR to match browser reporter 2011-06-08 18:36:58 -07:00
Davis W. Frank
86b095e5a4 Src & Spec dirs now have same structure; console/, core/, and html/ 2011-06-08 18:30:35 -07:00
Davis W. Frank
4c6dafa3f5 OCD 2011-06-08 08:36:03 -07:00
Davis W. Frank
3f4adf7715 Removed dead code 2011-06-08 08:29:39 -07:00
Davis W. Frank
af7f1818b0 Revert back to the old jasmine.css 2011-06-05 21:55:51 -07:00
Davis W. Frank
12f56787b0 Move building single-file JS to use a JSON file with initial priority files 2011-06-05 21:55:32 -07:00
Davis W. Frank
e88d88e427 Move all core files into src/core.
Move Browser & Node specs to test against lib/jasmine.js instead of the separate source. Yes, this makes development a little harder but it's better to test that jasmine.js was built correctly.
2011-06-05 21:28:26 -07:00
Davis W. Frank
ba10d178b2 Better stack trace on exception. Better results if exception is due to true exception 2011-06-01 21:14:59 -07:00
Davis W. Frank
da297d0f56 And what I meant was *this* commit was pulling in the fixes to TrivialConsoleReporter 2011-05-25 08:28:16 -07:00
Davis W. Frank
7ead5388c2 merge in fixes to TrivialConsoleReporter: correct # of specs, no longer limited by column length 2011-05-25 08:14:18 -07:00
Davis W. Frank
a445a62e7c TrivialConsoleReporter now reports the correct number of specs that were executed. TCR is still very heavily mocked instead of using testing an actual Jasmine environment. But now at least the numbers are correct. 2011-05-16 18:28:46 -07:00
Davis W. Frank
1d65d56a92 TrivialConsoleReporter refactor & fixes. No longer limitied to 50 columns of dots. 2011-05-16 08:08:12 -07:00
ragaskar
d875d1d997 Don't run TrivialConsoleReporter specs if TrivialConsoleReporter is not loaded 2011-05-06 23:18:57 -04:00
ragaskar
1fae8f0a31 Rebuild main jasmine lib 2011-05-06 23:08:49 -04:00
ragaskar
c1f8151bcb Add png suitable for favicon 2011-05-06 22:40:53 -04:00
ragaskar
bd8a3baed1 Remove unused image files 2011-05-06 22:30:48 -04:00
ragaskar
118324b451 Don't show 'Jasmine waiting for...' console messages unless jasmine.VERBOSE is set to true 2011-05-06 19:07:00 -04:00
ragaskar
c30f7d1aa7 Fail with an error if node is not installed when running rake spec 2011-05-06 18:34:42 -04:00
ragaskar
de7be4b316 ignore rvmrc 2011-05-06 18:32:58 -04:00
Davis W. Frank
b02aa9840a fixed bad merge of gvanhove's describe exception fix 2011-04-17 21:44:41 -07:00
Davis W. Frank
61de2268fe toBeCloseTo matcher merged in 2011-04-17 21:18:41 -07:00
gvanhove
dd32048383 Failure messages for toHaveBeenCalledWith print out the name of the spy 2011-04-17 20:55:32 -07:00
gvanhove
32e736aa47 commit updated version into jasmine.js 2011-04-17 20:55:32 -07:00
Steve Conover
38e9af8f68 integrating TrivialConsoleReporter into node_suite.js, deleting some code pulled over from jasmine-node 2011-04-17 20:50:57 -07:00
Carl Jackson & Davis W. Frank
e826fbb170 More README edits for the Contributor guide 2011-03-09 13:31:03 -08:00
Carl Jackson & Davis W. Frank
0c77662c5b One more README tweak 2011-03-09 13:15:33 -08:00
Davis W. Frank
75fb19bc49 README changes 2011-03-09 08:16:47 -08:00
Davis W. Frank
6ec825f62d Updating docs. Version goes to 1.1.0 2011-03-08 18:39:13 -08:00
Davis W. Frank
fc994108db Update Rakefile a bit. Added more rake tasks to run specs. 2011-03-08 18:38:46 -08:00
Davis W. Frank
70aed2d900 move all "assertion" to "expectation" 2011-03-08 18:37:44 -08:00
Davis W. Frank
ccfa17499f Merge remote branch 'sconover/trivial_console_reporter' into work 2011-03-07 22:35:25 -08:00
Davis W. Frank
ab087ef5f8 Pendantic terminology 2011-03-07 22:34:58 -08:00
Davis W. Frank
0ef6582f73 Merging in sconover/jshint 2011-03-07 22:30:43 -08:00
Steve Conover
a1ba43c864 call back when done 2011-02-28 23:58:06 -08:00
Steve Conover
88ee377662 integrated trivial console into a real-world situation and dicovered a couple mistakes/misses 2011-02-28 23:18:53 -08:00
Steve Conover
f5afe18a6b semicolon fixes subsequent to jshint run 2011-02-28 22:56:04 -08:00
Steve Conover
2731716ccb making this consistent 2011-02-28 22:39:16 -08:00
Steve Conover
4e5083d570 style rf 2011-02-28 22:36:31 -08:00
Steve Conover
b9cbd3c5a0 integration test - failure scenario 2011-02-28 22:30:03 -08:00
Steve Conover
e42026ee84 rename *node to *console 2011-02-28 21:15:57 -08:00
Steve Conover
a1f58f8be4 rf 2011-02-28 21:15:57 -08:00
Steve Conover
ac00d765d2 integration tests - passing scenarios 2011-02-28 21:15:57 -08:00
Steve Conover
b1dceeacd4 stack traces 2011-02-28 21:15:57 -08:00
Steve Conover
5018f0d1c2 spec failure - description 2011-02-28 21:15:57 -08:00
Steve Conover
9704550b33 rf 2011-02-28 21:15:56 -08:00
Steve Conover
882c287191 specs/assertions/failures 2011-02-28 21:15:56 -08:00
Steve Conover
7d2b900b48 remember suite results as suites finish 2011-02-28 21:15:56 -08:00
Steve Conover
f701fdc132 needful 2011-02-28 21:15:56 -08:00
Steve Conover
eb49fab652 print elapsed time in summary 2011-02-28 21:15:56 -08:00
Steve Conover
e8c8a0bdfd run result - passed green, failed red 2011-02-28 21:15:56 -08:00
Steve Conover
e6a080039f print started when the test run starts 2011-02-28 21:15:56 -08:00
Steve Conover
c485c33a3c skipped specs mean yellow star 2011-02-28 21:15:56 -08:00
Steve Conover
8fbf3ba859 newline at 50 characters 2011-02-28 21:15:56 -08:00
Steve Conover
dccafe33b0 style reform 2011-02-28 21:15:56 -08:00
Steve Conover
c1d2718bea red F, duh 2011-02-28 21:15:55 -08:00
Steve Conover
945a9ba638 failing spec makes a red dot 2011-02-28 21:15:55 -08:00
Steve Conover
528b5abeda beginning of trivial node reporter, based on jasmine-node. jshint rules exclude bad escapements WRT ansi colors, beacuse that's ok. 2011-02-28 21:15:55 -08:00
Davis W. Frank
d7cced2e7c How to for release 2011-02-27 14:22:53 -08:00
Davis W. Frank
3be0610572 adding latest pages 2011-02-27 14:00:45 -08:00
Davis W. Frank
5e90115eaf removing incorrectlt added submodule 2011-02-27 12:33:47 -08:00
Davis W. Frank
148317eb90 1.0.2, finishing to Frank for static pages 2011-02-27 12:26:38 -08:00
Davis W. Frank
45b4e1316c updating for new pages 2011-02-27 10:36:13 -08:00
Davis W. Frank
aee4c5926c .gitmodules 2011-02-27 09:48:17 -08:00
Steve Conover
f41af6c2d0 jshint passes - run 'node jshint/run.js'. running jshint with a couple jshint options and workarounds to allow certain jasmine-specific styles. many actual style problems are fixed. the jshint run is integrated into rake jasmine:lint. 2011-02-26 15:07:59 -08:00
Steve Conover
9f90c4eca5 initial jshint commit. including the library, made a runner for jasmine. 2011-02-26 11:23:25 -08:00
Steve Conover
545752ae20 semicolons 2011-02-26 11:01:33 -08:00
Steve Conover
c04f1b1fa8 node spec/node_suite.js runs all dom-independent jasmine specs. basic commonjs support for jasmine along the way. node_suite.js and runner.html are both green. 2011-02-26 10:53:55 -08:00
Davis W. Frank
fa9741dbda removed old ghpages dir 2011-02-25 08:14:48 -08:00
Davis W. Frank
560cb2edcb wip 2011-02-25 08:10:34 -08:00
Davis W. Frank
9a12b32a3a swapping ignore from Jekyll to staticmatic 2011-01-25 13:23:01 -08:00
Christian Williams
bd15ed6a45 Really? "File.exist?", not "File.exists?"? Whatever. 2010-11-09 13:10:40 -05:00
Christian Williams
fa74051071 Don't commit Gemfile.lock. 2010-11-09 09:48:30 -05:00
Christian Williams
127fe049d9 Build for 1.0.1. 2010-10-05 13:51:29 -07:00
Christian Williams
550e378dc0 Fix download page regen after redesign. 2010-10-05 13:50:55 -07:00
Christian Williams
377703745f Making the checkboxes work fine on IE. onchange doesnt work very well with checkboxes there. The target is not set too.
Original author: Fabio M. Costa <fabiomcosta@gmail.com>
2010-10-05 13:27:50 -07:00
Fabio M. Costa
8ecfd26325 Making the checkboxes work fine on IE. onchange doesnt work very well with checkboxes there. The target is not set too. 2010-10-05 13:25:24 -07:00
Christian Williams
2d10cc1404 IE doesn't have console.log.apply(); fall back to console.log() in that case. 2010-10-05 13:11:27 -07:00
Christian Williams & Ryan Richard
63df354e78 Drop in jsdoc template (from jsdoc-toolkit 2.1.0). 2010-10-05 13:11:04 -07: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
Christian Williams
c8d9fc562f Un-hide release notes for 1.0.
Shade prerelease standalone versions in download list.
2010-09-14 13:42:38 -07:00
208 changed files with 13052 additions and 9789 deletions

14
.gitignore vendored
View File

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

2
.gitmodules vendored
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

111
Contribute.markdown Normal file
View File

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

61
GOALS_2.0.md Normal file
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

15
Gemfile
View File

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

48
Gruntfile.js Normal file
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,4 @@
Copyright (c) 2008-2010 Pivotal Labs
Copyright (c) 2008-2011 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@@ -1,28 +1,27 @@
<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**
Want to use Jasmine in a project? Go HERE: [http://pivotal.github.com/jasmine/](http://pivotal.github.com/jasmine/)
Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on browsers, DOM, or any JavaScript framework. Thus it's suited for websites, [Node.js](http://nodejs.org) projects, or anywhere that JavaScript can run.
Want to contribute to Jasmine? Read on...
Documentation & guides live here: [http://pivotal.github.com/jasmine/](http://pivotal.github.com/jasmine/)
<i>(More developer docs to come...)</i>
## Contributing
Please read the [contributors' guide](https://github.com/pivotal/jasmine/blob/master/Contribute.markdown)
## Support
We now have a Google Group for support & discussion.
* Discussion: [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js)
* Group email: [jasmine-js@googlegroups.com](jasmine-js@googlegroups.com)
* Current build status of Jasmine is visible at [ci.pivotallabs.com](http://ci.pivotallabs.com)
* Pivotal Tracker project: [http://www.pivotaltracker.com/projects/10606](http://www.pivotaltracker.com/projects/10606)
* Twitter: [@JasmineBDD](http://twitter.com/JasmineBDD)
* Search past discussions: [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js)
* Send an email to the list: [jasmine-js@googlegroups.com](jasmine-js@googlegroups.com)
* View the project backlog at Pivotal Tracker: [http://www.pivotaltracker.com/projects/10606](http://www.pivotaltracker.com/projects/10606)
* Follow us on Twitter: [@JasmineBDD](http://twitter.com/JasmineBDD)
## Maintainers
* [Davis W. Frank](mailto:dwfrank@pivotallabs.com), Pivotal Labs
* [Rajan Agaskar](mailto:rajan@pivotallabs.com), Pivotal Labs
* [Christian Williams](mailto:xian@pivotallabs.com), Pivotal Labs
* [Christian Williams](mailto:antixian666@gmail.com), Square
## Developers
We welcome your contributions! Jasmine is currently maintained by Davis Frank ([infews](http://github.com/infews)), Rajan Agaskar ([ragaskar](http://github.com/ragaskar)), and Christian Williams ([Xian](http://github.com/Xian)). You can help us by removing all other recipients from your pull request.
Copyright (c) 2008-2010 Pivotal Labs. This software is licensed under the MIT License.
Copyright (c) 2008-2013 Pivotal Labs. This software is licensed under the MIT License.

194
Rakefile
View File

@@ -1,179 +1,39 @@
def jasmine_sources
sources = ["src/base.js", "src/util.js", "src/Env.js", "src/Reporter.js", "src/Block.js"]
sources += Dir.glob('src/*.js').reject { |f| f == 'src/base.js' || sources.include?(f) }.sort
sources
require "bundler"
Bundler::GemHelper.install_tasks
require "json"
require "jasmine"
Dir["#{File.dirname(__FILE__)}/tasks/**/*.rb"].each do |file|
require file
end
def jasmine_html_sources
["src/html/TrivialReporter.js"]
end
def jasmine_version
"#{version_hash['major']}.#{version_hash['minor']}.#{version_hash['build']}"
end
def version_hash
require 'json'
@version ||= JSON.parse(File.new("src/version.json").read);
end
task :default => 'jasmine:dist'
def substitute_jasmine_version(filename)
contents = File.read(filename)
contents = contents.gsub(/##JASMINE_VERSION##/, (jasmine_version))
contents = contents.gsub(/[^\n]*REMOVE_THIS_LINE_FROM_BUILD[^\n]*/, '')
File.open(filename, 'w') { |f| f.write(contents) }
# TODO: Is there better way to invoke this using Jasmine gem???
task :core_spec do
exec "ruby spec/jasmine_self_test_spec.rb"
end
namespace :jasmine do
task :server do
port = ENV['JASMINE_PORT'] || 8888
jasmine_yml = ENV['JASMINE_YML'] || 'jasmine.yml'
Jasmine.load_configuration_from_yaml(File.join(Dir.pwd, 'spec', jasmine_yml))
config = Jasmine.config
server = Jasmine::Server.new(port, Jasmine::Application.app(config))
server.start
desc 'Prepares for distribution'
task :dist => ['jasmine:build', 'jasmine:doc', 'jasmine:build_example_project', 'jasmine:fill_index_downloads']
desc 'Check jasmine sources for coding problems'
task :lint do
passed = true
jasmine_sources.each do |src|
lines = File.read(src).split(/\n/)
lines.each_index do |i|
line = lines[i]
undefineds = line.scan(/.?undefined/)
if undefineds.include?(" undefined") || undefineds.include?("\tundefined")
puts "Dangerous undefined at #{src}:#{i}:\n > #{line}"
passed = false
end
if line.scan(/window/).length > 0
puts "Dangerous window at #{src}:#{i}:\n > #{line}"
passed = false
end
end
end
unless passed
puts "Lint failed!"
exit 1
end
puts "your tests are here:"
puts " http://localhost:#{port}/"
end
desc 'Builds lib/jasmine from source'
task :build => :lint do
puts 'Building Jasmine from source'
desc "Copy examples from Jasmine JS to the gem"
task :copy_examples_to_gem do
require "fileutils"
sources = jasmine_sources
version = version_hash
old_jasmine_files = Dir.glob('lib/jasmine*.js')
old_jasmine_files.each { |file| File.delete(file) }
File.open("lib/jasmine.js", 'w') do |jasmine|
sources.each do |source_filename|
jasmine.puts(File.read(source_filename))
end
jasmine.puts %{
jasmine.version_= {
"major": #{version['major'].to_json},
"minor": #{version['minor'].to_json},
"build": #{version['build'].to_json},
"revision": #{Time.now.to_i}
};
}
end
File.open("lib/jasmine-html.js", 'w') do |jasmine_html|
jasmine_html_sources.each do |source_filename|
jasmine_html.puts(File.read(source_filename))
end
end
FileUtils.cp("src/html/jasmine.css", "lib/jasmine.css")
end
task :need_pages_submodule do
unless File.exists?('pages/index.html')
raise "Jasmine pages submodule isn't present. Run git submodule update --init"
end
end
desc "Build jasmine documentation"
task :doc => :need_pages_submodule do
puts 'Creating Jasmine Documentation'
require 'rubygems'
require 'jsdoc_helper'
FileUtils.rm_r "pages/jsdoc", :force => true
JsdocHelper::Rake::Task.new(:lambda_jsdoc) do |t|
t[:files] = jasmine_sources << jasmine_html_sources
t[:options] = "-a"
t[:out] = "pages/jsdoc"
end
Rake::Task[:lambda_jsdoc].invoke
end
desc "Build example project"
task :build_example_project => :need_pages_submodule do
require 'tmpdir'
temp_dir = File.join(Dir.tmpdir, 'jasmine-standalone-project')
puts "Building Example Project in #{temp_dir}"
FileUtils.rm_r temp_dir if File.exists?(temp_dir)
Dir.mkdir(temp_dir)
root = File.expand_path(File.dirname(__FILE__))
FileUtils.cp_r File.join(root, 'example/.'), File.join(temp_dir)
substitute_jasmine_version(File.join(temp_dir, "SpecRunner.html"))
lib_dir = File.join(temp_dir, "lib/jasmine-#{jasmine_version}")
FileUtils.mkdir_p(lib_dir)
{
"lib/jasmine.js" => "jasmine.js",
"lib/jasmine-html.js" => "jasmine-html.js",
"src/html/jasmine.css" => "jasmine.css",
"MIT.LICENSE" => "MIT.LICENSE"
}.each_pair do |src, dest|
FileUtils.cp(File.join(root, src), File.join(lib_dir, dest))
end
dist_dir = File.join(root, 'pages/downloads')
zip_file_name = File.join(dist_dir, "jasmine-standalone-#{jasmine_version}.zip")
puts "Zipping Example Project and moving to #{zip_file_name}"
FileUtils.mkdir(dist_dir) unless File.exist?(dist_dir)
if File.exist?(zip_file_name)
puts "WARNING!!! #{zip_file_name} already exists!"
FileUtils.rm(zip_file_name)
end
exec "cd #{temp_dir} && zip -r #{zip_file_name} . -x .[a-zA-Z0-9]*"
end
task :fill_index_downloads do
require 'digest/sha1'
download_html = "<!-- START_DOWNLOADS -->\n"
download_html += "<table>\n<tr><th></th><th>Version</th><th>Size</th><th>Date</th><th>SHA1</th></tr>\n"
Dir.glob('pages/downloads/*.zip').sort.reverse.each do |f|
sha1 = Digest::SHA1.hexdigest File.read(f)
fn = f.sub(/^pages\//, '')
version = /jasmine-standalone-(.*).zip/.match(f)[1]
download_html += "<tr>\n"
download_html += "<td class=\"link\"><a href='#{fn}'>#{fn.sub(/downloads\//, '')}</a></td>\n"
download_html += "<td class=\"version\">#{version}</td>\n"
download_html += "<td class=\"size\">#{File.size(f) / 1024}k</td>\n"
download_html += "<td class=\"date\">#{File.mtime(f).strftime("%Y/%m/%d %H:%M:%S %Z")}</td>\n"
download_html += "<td class=\"sha\">#{sha1}</td>\n"
download_html += "</tr>\n"
end
download_html += "</table>\n<!-- END_DOWNLOADS -->"
index_page = File.read('pages/index.html')
matcher = /<!-- START_DOWNLOADS -->.*<!-- END_DOWNLOADS -->/m
index_page = index_page.sub(matcher, download_html)
File.open('pages/index.html', 'w') {|f| f.write(index_page)}
puts "rewrote that file"
# copy jasmine's example tree into our generator templates dir
FileUtils.rm_r('generators/jasmine/templates/jasmine-example', :force => true)
FileUtils.cp_r(File.join(Jasmine::Core.path, 'example'), 'generators/jasmine/templates/jasmine-example', :preserve => true)
end
end
task :jasmine => ['jasmine:dist']
desc "Run specs via server"
task :jasmine => ['jasmine:server']

47
Release.markdown Normal file
View File

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

View File

@@ -1,21 +0,0 @@
# Project-specific configuration for CruiseControl.rb
Project.configure do |project|
# Send email notifications about broken and fixed builds to email1@your.site, email2@your.site (default: send to nobody)
# project.email_notifier.emails = ['email1@your.site', 'email2@your.site']
# Set email 'from' field to john@doe.com:
# project.email_notifier.from = 'john@doe.com'
# Build the project by invoking rake task 'custom'
project.rake_task = 'jasmine:test:ci:saucelabs'
# Build the project by invoking shell script "build_my_app.sh". Keep in mind that when the script is invoked,
# current working directory is <em>[cruise&nbsp;data]</em>/projects/your_project/work, so if you do not keep build_my_app.sh
# in version control, it should be '../build_my_app.sh' instead
#project.build_command = 'cp ../saucelabs.yml .'
# Ping Subversion for new revisions every 5 minutes (default: 30 seconds)
# project.scheduler.polling_interval = 5.minutes
end

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.

View File

@@ -1,27 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Jasmine Test Runner</title>
<link rel="stylesheet" type="text/css" href="lib/jasmine-##JASMINE_VERSION##/jasmine.css">
<script type="text/javascript" src="lib/jasmine-##JASMINE_VERSION##/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-##JASMINE_VERSION##/jasmine-html.js"></script>
<!-- include source files here... -->
<script type="text/javascript" src="src/Player.js"></script>
<script type="text/javascript" src="src/Song.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="spec/SpecHelper.js"></script>
<script type="text/javascript" src="spec/PlayerSpec.js"></script>
</head>
<body>
<div id="REMOVE_THIS_LINE_FROM_BUILD"><p>You must be trying to look at examples in the Jasmine source tree.</p><p>Please download a distribution version of Jasmine at <a href="http://pivotal.github.com/jasmine/">http://pivotal.github.com/jasmine/</a>.</p></div>
<script type="text/javascript">
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
jasmine.getEnv().execute();
</script>
</body>
</html>

View File

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

10
grunt/config/compass.js Normal file
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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 759 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

BIN
images/jasmine_favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 768 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

27
jasmine-core.gemspec Normal file
View File

@@ -0,0 +1,27 @@
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "jasmine-core/version"
Gem::Specification.new do |s|
s.name = "jasmine-core"
s.version = Jasmine::Core::VERSION
s.platform = Gem::Platform::RUBY
s.authors = ["Rajan Agaskar", "Davis W. Frank", "Christian Williams"]
s.summary = %q{JavaScript BDD framework}
s.description = %q{Test your JavaScript without any framework dependencies, in any environment, and with a nice descriptive syntax.}
s.email = %q{jasmine-js@googlegroups.com}
s.homepage = "http://pivotal.github.com/jasmine"
s.rubyforge_project = "jasmine-core"
s.license = "MIT"
s.files = Dir.glob("./lib/**/*") + Dir.glob("./lib/jasmine-core/spec/**/*.js")
s.require_paths = ["lib"]
s.add_development_dependency "json_pure", ">= 1.4.3"
s.add_development_dependency "sass"
s.add_development_dependency "compass"
s.add_development_dependency "rspec"
s.add_development_dependency "fuubar"
s.add_development_dependency "awesome_print"
s.add_development_dependency "nokogiri"
s.add_development_dependency "sauce-connect"
end

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

@@ -0,0 +1,49 @@
module Jasmine
module Core
class << self
def path
File.join(File.dirname(__FILE__), "jasmine-core")
end
def js_files
(["jasmine.js"] + Dir.glob(File.join(path, "*.js"))).map { |f| File.basename(f) }.uniq - boot_files
end
SPEC_TYPES = ["core", "html", "node"]
def core_spec_files
spec_files("core")
end
def html_spec_files
spec_files("html")
end
def node_spec_files
spec_files("node")
end
def boot_files
["boot.js"]
end
def boot_dir
File.join(path, 'boot')
end
def spec_files(type)
raise ArgumentError.new("Unrecognized spec type") unless SPEC_TYPES.include?(type)
(Dir.glob(File.join(path, "spec", type, "*.js"))).map { |f| File.join("spec", type, File.basename(f)) }.uniq
end
def css_files
Dir.glob(File.join(path, "*.css")).map { |f| File.basename(f) }
end
def images_dir
File.join(File.dirname(__FILE__), '../images')
end
end
end
end

131
lib/jasmine-core/boot.js Normal file
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

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

View File

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

View File

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

View File

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

2361
lib/jasmine-core/jasmine.js Normal file

File diff suppressed because it is too large Load Diff

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

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

View File

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

View File

@@ -1,182 +0,0 @@
jasmine.TrivialReporter = function(doc) {
this.document = doc || document;
this.suiteDivs = {};
this.logRunningSpecs = false;
};
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
var el = document.createElement(type);
for (var i = 2; i < arguments.length; i++) {
var child = arguments[i];
if (typeof child === 'string') {
el.appendChild(document.createTextNode(child));
} else {
if (child) { el.appendChild(child); }
}
}
for (var attr in attrs) {
if (attr == "className") {
el[attr] = attrs[attr];
} else {
el.setAttribute(attr, attrs[attr]);
}
}
return el;
};
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
var showPassed, showSkipped;
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
this.createDom('div', { className: 'banner' },
this.createDom('div', { className: 'logo' },
this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "Jasmine"),
this.createDom('span', { className: 'version' }, runner.env.versionString())),
this.createDom('div', { className: 'options' },
"Show ",
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
)
),
this.runnerDiv = this.createDom('div', { className: 'runner running' },
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
);
this.document.body.appendChild(this.outerDiv);
var suites = runner.suites();
for (var i = 0; i < suites.length; i++) {
var suite = suites[i];
var suiteDiv = this.createDom('div', { className: 'suite' },
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
this.suiteDivs[suite.id] = suiteDiv;
var parentDiv = this.outerDiv;
if (suite.parentSuite) {
parentDiv = this.suiteDivs[suite.parentSuite.id];
}
parentDiv.appendChild(suiteDiv);
}
this.startedAt = new Date();
var self = this;
showPassed.onchange = function(evt) {
if (evt.target.checked) {
self.outerDiv.className += ' show-passed';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
}
};
showSkipped.onchange = function(evt) {
if (evt.target.checked) {
self.outerDiv.className += ' show-skipped';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
}
};
};
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
var results = runner.results();
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
this.runnerDiv.setAttribute("class", className);
//do it twice for IE
this.runnerDiv.setAttribute("className", className);
var specs = runner.specs();
var specCount = 0;
for (var i = 0; i < specs.length; i++) {
if (this.specFilter(specs[i])) {
specCount++;
}
}
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
};
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
var results = suite.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.totalCount == 0) { // todo: change this to check results.skipped
status = 'skipped';
}
this.suiteDivs[suite.id].className += " " + status;
};
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
if (this.logRunningSpecs) {
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
}
};
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
var results = spec.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.skipped) {
status = 'skipped';
}
var specDiv = this.createDom('div', { className: 'spec ' + status },
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
this.createDom('a', {
className: 'description',
href: '?spec=' + encodeURIComponent(spec.getFullName()),
title: spec.getFullName()
}, spec.description));
var resultItems = results.getItems();
var messagesDiv = this.createDom('div', { className: 'messages' });
for (var i = 0; i < resultItems.length; i++) {
var result = resultItems[i];
if (result.type == 'log') {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
} else if (result.type == 'expect' && result.passed && !result.passed()) {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
if (result.trace.stack) {
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
}
}
}
if (messagesDiv.childNodes.length > 0) {
specDiv.appendChild(messagesDiv);
}
this.suiteDivs[spec.suite.id].appendChild(specDiv);
};
jasmine.TrivialReporter.prototype.log = function() {
var console = jasmine.getGlobal().console;
if (console && console.log) console.log.apply(console, arguments);
};
jasmine.TrivialReporter.prototype.getLocation = function() {
return this.document.location;
};
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
var paramMap = {};
var params = this.getLocation().search.substring(1).split('&');
for (var i = 0; i < params.length; i++) {
var p = params[i].split('=');
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
}
if (!paramMap["spec"]) return true;
return spec.getFullName().indexOf(paramMap["spec"]) == 0;
};

View File

@@ -1,166 +0,0 @@
body {
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
}
.jasmine_reporter a:visited, .jasmine_reporter a {
color: #303;
}
.jasmine_reporter a:hover, .jasmine_reporter a:active {
color: blue;
}
.run_spec {
float:right;
padding-right: 5px;
font-size: .8em;
text-decoration: none;
}
.jasmine_reporter {
margin: 0 5px;
}
.banner {
color: #303;
background-color: #fef;
padding: 5px;
}
.logo {
float: left;
font-size: 1.1em;
padding-left: 5px;
}
.logo .version {
font-size: .6em;
padding-left: 1em;
}
.runner.running {
background-color: yellow;
}
.options {
text-align: right;
font-size: .8em;
}
.suite {
border: 1px outset gray;
margin: 5px 0;
padding-left: 1em;
}
.suite .suite {
margin: 5px;
}
.suite.passed {
background-color: #dfd;
}
.suite.failed {
background-color: #fdd;
}
.spec {
margin: 5px;
padding-left: 1em;
clear: both;
}
.spec.failed, .spec.passed, .spec.skipped {
padding-bottom: 5px;
border: 1px solid gray;
}
.spec.failed {
background-color: #fbb;
border-color: red;
}
.spec.passed {
background-color: #bfb;
border-color: green;
}
.spec.skipped {
background-color: #bbb;
}
.messages {
border-left: 1px dashed gray;
padding-left: 1em;
padding-right: 1em;
}
.passed {
background-color: #cfc;
display: none;
}
.failed {
background-color: #fbb;
}
.skipped {
color: #777;
background-color: #eee;
display: none;
}
/*.resultMessage {*/
/*white-space: pre;*/
/*}*/
.resultMessage span.result {
display: block;
line-height: 2em;
color: black;
}
.resultMessage .mismatch {
color: black;
}
.stackTrace {
white-space: pre;
font-size: .8em;
margin-left: 10px;
max-height: 5em;
overflow: auto;
border: 1px inset red;
padding: 1em;
background: #eef;
}
.finished-at {
padding-left: 1em;
font-size: .6em;
}
.show-passed .passed,
.show-skipped .skipped {
display: block;
}
#jasmine_content {
position:fixed;
right: 100%;
}
.runner {
border: 1px solid gray;
display: block;
margin: 5px 0;
padding: 2px 0 2px 10px;
}

File diff suppressed because it is too large Load Diff

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 60e240ad40

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

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

45
spec/core/AnySpec.js Normal file
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

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

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

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

511
spec/core/EnvSpec.js Normal file
View File

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

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

@@ -0,0 +1,64 @@
xdescribe('Exceptions:', function() {
var env;
beforeEach(function() {
env = new j$.Env();
env.updateInterval = 0;
});
describe('with break on exception', function() {
it('should not catch the exception', function() {
env.catchExceptions(false);
var suite = env.describe('suite for break on exceptions', function() {
env.it('should break when an exception is thrown', function() {
throw new Error('I should hit a breakpoint!');
});
});
var runner = env.currentRunner();
var dont_change = 'I will never change!';
try {
suite.execute();
dont_change = 'oops I changed';
}
catch (e) {}
expect(dont_change).toEqual('I will never change!');
});
});
describe("with catch on exception", function() {
it('should handle exceptions thrown, but continue', function() {
var ranSecondTest = false,
suite = env.describe('Suite for handles exceptions', function () {
env.it('should be a test that fails because it throws an exception', function() {
throw new Error();
});
env.it('should be a passing test that runs after exceptions are thrown from a async test', function() {
ranSecondTest = true;
});
});
suite.execute();
expect(ranSecondTest).toBe(true);
});
it("should handle exceptions thrown directly in top-level describe blocks and continue", function () {
var ranSecondDescribe = false, suite, suite2, runner = env.currentRunner();
suite = env.describe("a suite that throws an exception", function () {
env.it("is a test that should pass", function () {
this.expect(true).toEqual(true);
});
throw new Error("top level error");
});
suite2 = env.describe("a suite that doesn't throw an exception", function () {
ranSecondDescribe = true;
});
runner.execute();
expect(ranSecondDescribe).toBe(true);
});
});
});

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

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

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

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

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

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

@@ -0,0 +1,308 @@
// TODO: This should really be part of the Env Integration Spec
describe("jasmine spec running", function () {
var env;
var fakeTimer;
beforeEach(function() {
env = new j$.Env();
env.updateInterval = 0;
});
it('should assign spec ids sequentially', function() {
var it0, it1, it2, it3, it4;
env.describe('test suite', function() {
it0 = env.it('spec 0', function() {
});
it1 = env.it('spec 1', function() {
});
it2 = env.xit('spec 2', function() {
});
it3 = env.it('spec 3', function() {
});
});
env.describe('test suite 2', function() {
it4 = env.it('spec 4', function() {
});
});
expect(it0.id).toEqual(0);
expect(it1.id).toEqual(1);
expect(it2.id).toEqual(2);
expect(it3.id).toEqual(3);
expect(it4.id).toEqual(4);
});
it('nested suites', function (done) {
var foo = 0;
var bar = 0;
var baz = 0;
var quux = 0;
var nested = env.describe('suite', function () {
env.describe('nested', function () {
env.it('should run nested suites', function () {
foo++;
});
env.it('should run nested suites', function () {
bar++;
});
});
env.describe('nested 2', function () {
env.it('should run suites following nested suites', function () {
baz++;
});
});
env.it('should run tests following nested suites', function () {
quux++;
});
});
expect(foo).toEqual(0);
expect(bar).toEqual(0);
expect(baz).toEqual(0);
expect(quux).toEqual(0);
nested.execute(function() {
expect(foo).toEqual(1);
expect(bar).toEqual(1);
expect(baz).toEqual(1);
expect(quux).toEqual(1);
done();
});
});
it("should permit nested describes", function(done) {
var actions = [];
env.beforeEach(function () {
actions.push('topSuite beforeEach');
});
env.afterEach(function () {
actions.push('topSuite afterEach');
});
env.describe('Something', function() {
env.beforeEach(function() {
actions.push('outer beforeEach');
});
env.afterEach(function() {
actions.push('outer afterEach');
});
env.it('does it 1', function() {
actions.push('outer it 1');
});
env.describe('Inner 1', function() {
env.beforeEach(function() {
actions.push('inner 1 beforeEach');
});
env.afterEach(function() {
actions.push('inner 1 afterEach');
});
env.it('does it 2', function() {
actions.push('inner 1 it');
});
});
env.it('does it 3', function() {
actions.push('outer it 2');
});
env.describe('Inner 2', function() {
env.beforeEach(function() {
actions.push('inner 2 beforeEach');
});
env.afterEach(function() {
actions.push('inner 2 afterEach');
});
env.it('does it 2', function() {
actions.push('inner 2 it');
});
});
});
var assertions = function() {
var expected = [
"topSuite beforeEach",
"outer beforeEach",
"outer it 1",
"outer afterEach",
"topSuite afterEach",
"topSuite beforeEach",
"outer beforeEach",
"inner 1 beforeEach",
"inner 1 it",
"inner 1 afterEach",
"outer afterEach",
"topSuite afterEach",
"topSuite beforeEach",
"outer beforeEach",
"outer it 2",
"outer afterEach",
"topSuite afterEach",
"topSuite beforeEach",
"outer beforeEach",
"inner 2 beforeEach",
"inner 2 it",
"inner 2 afterEach",
"outer afterEach",
"topSuite afterEach"
];
expect(actions).toEqual(expected);
done();
}
env.addReporter({jasmineDone: assertions});
env.execute();
});
it("should run multiple befores and afters in the order they are declared", function(done) {
var actions = [];
env.beforeEach(function () {
actions.push('runner beforeEach1');
});
env.afterEach(function () {
actions.push('runner afterEach1');
});
env.beforeEach(function () {
actions.push('runner beforeEach2');
});
env.afterEach(function () {
actions.push('runner afterEach2');
});
env.describe('Something', function() {
env.beforeEach(function() {
actions.push('beforeEach1');
});
env.afterEach(function() {
actions.push('afterEach1');
});
env.beforeEach(function() {
actions.push('beforeEach2');
});
env.afterEach(function() {
actions.push('afterEach2');
});
env.it('does it 1', function() {
actions.push('outer it 1');
});
});
var assertions = function() {
var expected = [
"runner beforeEach1",
"runner beforeEach2",
"beforeEach1",
"beforeEach2",
"outer it 1",
"afterEach2",
"afterEach1",
"runner afterEach2",
"runner afterEach1"
];
expect(actions).toEqual(expected);
done();
};
env.addReporter({jasmineDone: assertions});
env.execute();
});
it("shouldn't run disabled suites", function(done) {
var specInADisabledSuite = jasmine.createSpy("specInADisabledSuite"),
suite = env.describe('A Suite', function() {
env.xdescribe('with a disabled suite', function(){
env.it('spec inside a disabled suite', specInADisabledSuite);
});
});
suite.execute(function() {
expect(specInADisabledSuite).not.toHaveBeenCalled();
done();
});
});
it("should set all pending specs to pending when a suite is run", function(done) {
var pendingSpec,
suite = env.describe('default current suite', function() {
pendingSpec = env.it("I am a pending spec");
});
suite.execute(function() {
expect(pendingSpec.status()).toBe("pending");
done();
});
});
// TODO: is this useful? It doesn't catch syntax errors
xit("should recover gracefully when there are errors in describe functions", function() {
var specs = [];
var superSimpleReporter = new j$.Reporter();
superSimpleReporter.reportSpecResults = function(result) {
specs.push("Spec: " + result.fullName);
};
try {
env.describe("outer1", function() {
env.describe("inner1", function() {
env.it("should thingy", function() {
this.expect(true).toEqual(true);
});
throw new Error("fake error");
});
env.describe("inner2", function() {
env.it("should other thingy", function() {
this.expect(true).toEqual(true);
});
});
throw new Error("fake error");
});
} catch(e) {
}
env.describe("outer2", function() {
env.it("should xxx", function() {
this.expect(true).toEqual(true);
});
});
env.addReporter(superSimpleReporter);
env.execute();
expect(specs.join('')).toMatch(new RegExp(
'Spec: outer1 inner1 should thingy.' +
'Spec: outer1 inner1 encountered a declaration exception.' +
'Spec: outer1 inner2 should other thingy.' +
'Spec: outer1 encountered a declaration exception.' +
'Spec: outer2 should xxx.'
));
});
});

244
spec/core/SpecSpec.js Normal file
View File

@@ -0,0 +1,244 @@
describe("Spec", function() {
it("#isPendingSpecException returns true for a pending spec exception", function() {
var e = new Error(j$.Spec.pendingSpecExceptionMessage);
expect(j$.Spec.isPendingSpecException(e)).toBe(true);
});
it("#isPendingSpecException returns true for a pending spec exception (even when FF bug is present)", function() {
var fakeError = {
toString: function() { return "Error: " + j$.Spec.pendingSpecExceptionMessage; }
};
expect(j$.Spec.isPendingSpecException(fakeError)).toBe(true);
});
it("#isPendingSpecException returns true for a pending spec exception", function() {
var e = new Error("foo");
expect(j$.Spec.isPendingSpecException(e)).toBe(false);
});
it("delegates execution to a QueueRunner", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
spec = new j$.Spec({
description: 'my test',
id: 'some-id',
fn: function() {},
queueRunner: fakeQueueRunner
});
spec.execute();
expect(fakeQueueRunner).toHaveBeenCalled();
});
it("should call the start callback on execution", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
beforesWereCalled = false,
startCallback = jasmine.createSpy('startCallback'),
spec = new j$.Spec({
id: 123,
description: 'foo bar',
fn: function() {},
onStart: startCallback,
queueRunner: fakeQueueRunner
});
spec.execute();
expect(startCallback).toHaveBeenCalledWith(spec);
});
it("should call the start callback on execution but before any befores are called", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
beforesWereCalled = false,
startCallback = jasmine.createSpy('start-callback').and.callFake(function() {
expect(beforesWereCalled).toBe(false);
}),
spec = new j$.Spec({
fn: function() {},
beforeFns: function() {
return [function() {
beforesWereCalled = true
}]
},
onStart: startCallback,
queueRunner: fakeQueueRunner
});
spec.execute();
expect(startCallback).toHaveBeenCalled();
});
it("provides all before fns and after fns to be run", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
before = jasmine.createSpy('before'),
after = jasmine.createSpy('after'),
fn = jasmine.createSpy('test body').and.callFake(function() {
expect(before).toHaveBeenCalled();
expect(after).not.toHaveBeenCalled();
}),
spec = new j$.Spec({
fn: fn,
beforeFns: function() {
return [before]
},
afterFns: function() {
return [after]
},
queueRunner: fakeQueueRunner
});
spec.execute();
var allSpecFns = fakeQueueRunner.calls.mostRecent().args[0].fns;
expect(allSpecFns).toEqual([before, fn, after]);
});
it("is marked pending if created without a function body", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
startCallback = jasmine.createSpy('startCallback'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({
onStart: startCallback,
fn: null,
resultCallback: resultCallback,
queueRunner: fakeQueueRunner
});
expect(spec.status()).toBe('pending');
});
it("can be disabled, but still calls callbacks", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
startCallback = jasmine.createSpy('startCallback'),
specBody = jasmine.createSpy('specBody'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({
onStart:startCallback,
fn: specBody,
resultCallback: resultCallback,
queueRunner: fakeQueueRunner
});
spec.disable();
expect(spec.status()).toBe('disabled');
spec.execute();
expect(fakeQueueRunner).not.toHaveBeenCalled();
expect(specBody).not.toHaveBeenCalled();
expect(startCallback).toHaveBeenCalled();
expect(resultCallback).toHaveBeenCalled();
});
it("can be marked pending, but still calls callbacks when executed", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
startCallback = jasmine.createSpy('startCallback'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({
onStart: startCallback,
resultCallback: resultCallback,
description: "with a spec",
getSpecName: function() {
return "a suite with a spec"
},
queueRunner: fakeQueueRunner
});
spec.pend();
expect(spec.status()).toBe('pending');
spec.execute();
expect(fakeQueueRunner).not.toHaveBeenCalled();
expect(startCallback).toHaveBeenCalled();
expect(resultCallback).toHaveBeenCalledWith({
id: spec.id,
status: 'pending',
description: 'with a spec',
fullName: 'a suite with a spec',
failedExpectations: []
});
});
it("should call the done callback on execution complete", function() {
var done = jasmine.createSpy('done callback'),
spec = new j$.Spec({
fn: function() {},
catchExceptions: function() { return false; },
resultCallback: function() {},
queueRunner: function(attrs) { attrs.onComplete(); }
});
spec.execute(done);
expect(done).toHaveBeenCalled();
});
it("#status returns pending by default", function() {
var spec = new j$.Spec({fn: jasmine.createSpy("spec body")});
expect(spec.status()).toEqual('pending');
});
it("#status returns pending if no expectations were encountered", function() {
var specBody = jasmine.createSpy("spec body"),
spec = new j$.Spec({fn: specBody});
spec.execute();
expect(spec.status()).toEqual('pending');
});
it("#status returns passed if all expectations in the spec have passed", function() {
var spec = new j$.Spec({fn: jasmine.createSpy("spec body")});
spec.addExpectationResult(true);
expect(spec.status()).toBe('passed');
});
it("#status returns failed if any expectations in the spec have failed", function() {
var spec = new j$.Spec({ fn: jasmine.createSpy("spec body") });
spec.addExpectationResult(true);
spec.addExpectationResult(false);
expect(spec.status()).toBe('failed');
});
it("can return its full name", function() {
var spec;
spec = new j$.Spec({
getSpecName: function(passedVal) {
// expect(passedVal).toBe(spec); TODO: a exec time, spec is undefined WTF?
return 'expected val';
}
});
expect(spec.getFullName()).toBe('expected val');
});
describe("when a spec is marked pending during execution", function() {
it("should mark the spec as pending", function() {
var fakeQueueRunner = function(opts) {
opts.onException(new Error(j$.Spec.pendingSpecExceptionMessage));
},
spec = new j$.Spec({
description: 'my test',
id: 'some-id',
fn: function() { },
queueRunner: fakeQueueRunner
});
spec.execute();
expect(spec.status()).toEqual("pending");
});
});
});

48
spec/core/SpySpec.js Normal file
View File

@@ -0,0 +1,48 @@
describe('Spies', function () {
describe("createSpy", function() {
var TestClass;
beforeEach(function() {
TestClass = function() {};
TestClass.prototype.someFunction = function() {};
TestClass.prototype.someFunction.bob = "test";
});
it("preserves the properties of the spied function", function() {
var spy = j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
expect(spy.bob).toEqual("test");
});
it("warns the user that we indend to overwrite an existing property", function() {
TestClass.prototype.someFunction.and = "turkey";
expect(function() {
j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
}).toThrowError("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
});
it("adds a spyStrategy and callTracker to the spy", function() {
var spy = j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
expect(spy.and).toEqual(jasmine.any(j$.SpyStrategy));
expect(spy.calls).toEqual(jasmine.any(j$.CallTracker));
});
});
describe("createSpyObj", function() {
it("should create an object with a bunch of spy methods when you call jasmine.createSpyObj()", function() {
var spyObj = j$.createSpyObj('BaseName', ['method1', 'method2']);
expect(spyObj).toEqual({ method1: jasmine.any(Function), method2: jasmine.any(Function)});
expect(spyObj.method1.and.identity()).toEqual('BaseName.method1');
expect(spyObj.method2.and.identity()).toEqual('BaseName.method2');
});
it("should throw if you do not pass an array argument", function() {
expect(function() {
j$.createSpyObj('BaseName');
}).toThrow("createSpyObj requires a non-empty array of method names to create spies for");
});
});
});

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

230
spec/core/SuiteSpec.js Normal file
View File

@@ -0,0 +1,230 @@
describe("Suite", function() {
it("keeps its id", function() {
var env = new j$.Env(),
suite = new j$.Suite({
env: env,
id: 456,
description: "I am a suite"
});
expect(suite.id).toEqual(456);
});
it("returns its full name", function() {
var env = new j$.Env(),
suite = new j$.Suite({
env: env,
description: "I am a suite"
});
expect(suite.getFullName()).toEqual("I am a suite");
});
it("returns its full name when it has parent suites", function() {
var env = new j$.Env(),
parentSuite = new j$.Suite({
env: env,
description: "I am a parent suite",
parentSuite: jasmine.createSpy('pretend top level suite')
}),
suite = new j$.Suite({
env: env,
description: "I am a suite",
parentSuite: parentSuite
});
expect(suite.getFullName()).toEqual("I am a parent suite I am a suite");
});
it("adds before functions in order of needed execution", function() {
var env = new j$.Env(),
suite = new j$.Suite({
env: env,
description: "I am a suite"
}),
outerBefore = jasmine.createSpy('outerBeforeEach'),
innerBefore = jasmine.createSpy('insideBeforeEach');
suite.beforeEach(outerBefore);
suite.beforeEach(innerBefore);
expect(suite.beforeFns).toEqual([innerBefore, outerBefore]);
});
it("adds after functions in order of needed execution", function() {
var env = new j$.Env(),
suite = new j$.Suite({
env: env,
description: "I am a suite"
}),
outerAfter = jasmine.createSpy('outerAfterEach'),
innerAfter = jasmine.createSpy('insideAfterEach');
suite.afterEach(outerAfter);
suite.afterEach(innerAfter);
expect(suite.afterFns).toEqual([innerAfter, outerAfter]);
});
it("adds specs", function() {
var env = new j$.Env(),
fakeQueue = {
add: jasmine.createSpy()
},
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueFactory: function() {
return fakeQueue
}
}),
fakeSpec = {};
expect(suite.specs.length).toEqual(0);
suite.addSpec(fakeSpec);
expect(suite.specs.length).toEqual(1);
});
it("adds suites", function() {
var env = new j$.Env(),
fakeQueue = {
add: jasmine.createSpy()
},
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueFactory: function() {
return fakeQueue
}
}),
anotherSuite = new j$.Suite({
env: env,
description: "I am another suite",
queueFactory: function() {
return fakeQueue
}
});
expect(suite.suites.length).toEqual(0);
suite.addSuite(anotherSuite);
expect(suite.suites.length).toEqual(1);
});
it("can be disabled", function() {
var env = new j$.Env(),
fakeQueueRunner = jasmine.createSpy('fake queue runner'),
suite = new j$.Suite({
env: env,
description: "with a child suite",
queueRunner: fakeQueueRunner
});
suite.disable();
expect(suite.disabled).toBe(true);
suite.execute();
expect(fakeQueueRunner).not.toHaveBeenCalled();
});
it("delegates execution of its specs and suites", function() {
var env = new j$.Env(),
parentSuiteDone = jasmine.createSpy('parent suite done'),
fakeQueueRunnerForParent = jasmine.createSpy('fake parent queue runner'),
parentSuite = new j$.Suite({
env: env,
description: "I am a parent suite",
queueRunner: fakeQueueRunnerForParent
}),
fakeQueueRunner = jasmine.createSpy('fake queue runner'),
suite = new j$.Suite({
env: env,
description: "with a child suite",
queueRunner: fakeQueueRunner
}),
fakeSpec1 = {
execute: jasmine.createSpy('fakeSpec1')
};
spyOn(suite, "execute");
parentSuite.addSpec(fakeSpec1);
parentSuite.addSuite(suite);
parentSuite.execute(parentSuiteDone);
var parentSuiteFns = fakeQueueRunnerForParent.calls.mostRecent().args[0].fns;
parentSuiteFns[0]();
expect(fakeSpec1.execute).toHaveBeenCalled();
parentSuiteFns[1]();
expect(suite.execute).toHaveBeenCalled();
});
it("calls a provided onStart callback when starting", function() {
var env = new j$.Env(),
suiteStarted = jasmine.createSpy('suiteStarted'),
fakeQueueRunner = function(attrs) { attrs.onComplete(); },
suite = new j$.Suite({
env: env,
description: "with a child suite",
onStart: suiteStarted,
queueRunner: fakeQueueRunner
}),
fakeSpec1 = {
execute: jasmine.createSpy('fakeSpec1')
};
suite.execute();
expect(suiteStarted).toHaveBeenCalledWith(suite);
});
it("calls a provided onComplete callback when done", function() {
var env = new j$.Env(),
suiteCompleted = jasmine.createSpy('parent suite done'),
fakeQueueRunner = function(attrs) { attrs.onComplete(); },
suite = new j$.Suite({
env: env,
description: "with a child suite",
queueRunner: fakeQueueRunner
}),
fakeSpec1 = {
execute: jasmine.createSpy('fakeSpec1')
};
suite.execute(suiteCompleted);
expect(suiteCompleted).toHaveBeenCalled();
});
it("calls a provided result callback when done", function() {
var env = new j$.Env(),
suiteResultsCallback = jasmine.createSpy('suite result callback'),
fakeQueueRunner = function(attrs) { attrs.onComplete(); },
suite = new j$.Suite({
env: env,
description: "with a child suite",
queueRunner: fakeQueueRunner,
resultCallback: suiteResultsCallback
}),
fakeSpec1 = {
execute: jasmine.createSpy('fakeSpec1')
};
suite.execute();
expect(suiteResultsCallback).toHaveBeenCalledWith({
id: suite.id,
status: '',
description: "with a child suite",
fullName: "with a child suite"
});
});
});

13
spec/core/TimerSpec.js Normal file
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);
});
});

28
spec/core/UtilSpec.js Normal file
View File

@@ -0,0 +1,28 @@
describe("j$.util", function() {
describe("isArray_", function() {
it("should return true if the argument is an array", function() {
expect(j$.isArray_([])).toBe(true);
expect(j$.isArray_(['a'])).toBe(true);
});
it("should return false if the argument is not an array", function() {
expect(j$.isArray_(undefined)).toBe(false);
expect(j$.isArray_({})).toBe(false);
expect(j$.isArray_(function() {})).toBe(false);
expect(j$.isArray_('foo')).toBe(false);
expect(j$.isArray_(5)).toBe(false);
expect(j$.isArray_(null)).toBe(false);
});
});
describe("isUndefined", function() {
it("reports if a variable is defined", function() {
var a;
expect(j$.util.isUndefined(a)).toBe(true);
expect(j$.util.isUndefined(undefined)).toBe(true);
var undefined = "diz be undefined yo";
expect(j$.util.isUndefined(undefined)).toBe(false);
});
});
});

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