Compare commits

..

68 Commits

Author SHA1 Message Date
Greg Cobb and Gregg Van Hove
e173cd1c9d bump version to 2.2.1 for bower fix 2015-02-02 12:24:14 -08:00
Gregg Van Hove
234dc1a047 Merge pull request #763 from gabrielhpugliese/gabrielhpugliese-patch-bower-json
Fix missing comma on bower.json
2015-02-02 12:16:47 -08:00
Gabriel H Pugliese
d22a030b87 Fix missing comma on bower.json 2015-02-02 18:03:32 -02:00
Greg Cobb and Gregg Van Hove
4acb7448d8 Update release notes and bump version for 2.2.0 2015-02-02 11:27:14 -08:00
slackersoft
a26e85ff3a update 2.2.0 release notes now that I've pulled 2015-01-30 13:03:08 -08:00
slackersoft
39e175c05f Initial cut of release notes for 2.2.0 2015-01-30 13:02:01 -08:00
Christopher Amavisca
d129a6c0ee Restructure node examples folder structure to look more realistic.
- Updates PlayerSpec's require statement to match folder structure change
2015-01-27 14:39:59 -08:00
slackersoft
837101c025 Add a basic bower config
- Also ignore sauce_connect.log

Fix #719
2015-01-26 17:53:41 -08:00
slackersoft
8e3066db42 Allow pending to take a reason and show it in the HtmlReporter
[#78954014] Fix #671
2015-01-26 15:55:31 -08:00
slackersoft
a857f4c042 Merge branch 'ptomato-gjs-global-object' 2015-01-26 12:22:05 -08:00
slackersoft
dca543accb Merge branch 'gjs-global-object' of https://github.com/ptomato/jasmine into ptomato-gjs-global-object 2015-01-26 12:21:56 -08:00
slackersoft
5dbcf27f72 Merge branch 'ptomato-spidermonkey-compat' 2015-01-26 11:47:35 -08:00
slackersoft
b54de4a180 Merge branch 'spidermonkey-compat' of https://github.com/ptomato/jasmine into ptomato-spidermonkey-compat 2015-01-26 11:47:09 -08:00
slackersoft
46509f05a9 Add jshint to node run on travis
- To ensure that pull requests pass

[Finish #59588854]
2015-01-26 10:59:44 -08:00
Philip Chimento
ebaa2e7f24 Set jasmineGlobal correctly in GJS
In GJS, jasmineGlobal was not getting set to the global object; when
importing jasmine.js in GJS, "this" resolves to the jasmine.js module
object, not the global object. Solve this specifically for GJS by
assuming that `window.toString === '[object GjsGlobal]'` only in GJS; if
this is the case, assign "window" to "jasmineGlobal".

Adding a "var" to the declaration of "getJasmineRequireObj" is also
necessary, or else "getJasmineRequireObj" won't be exported in the
Jasmine module.

See #751
2015-01-24 23:50:40 -08:00
Philip Chimento
5eaf7152bf Fix some SpiderMonkey lint
SpiderMonkey complains about functions not always returning a value. In
most cases that is a conscious code style choice, so it is not fixed
here.

In one case (MockDate) the interpreter thought you could have fallen off
the end of a "switch" statement, although the number of arguments
prevented that. This was fixed by changing the last case to "default".

In another case (QueueRunner) the function really did return a value
sometimes and nothing other times, although as far as I could see, it
could only ever return "undefined". The function now explicitly only
returns no value.

See #751
2015-01-24 23:43:38 -08:00
Greg Cobb
ebbaab4cf9 Prevents *Alls from running when runnables are explicitly set
- This requires passing if runnables are set to the Suite. Hopefully in
  the future we will change how focused runnables and *Alls interact so
  this is no longer necessary.

[#732]
2015-01-23 17:27:13 -08:00
Greg Cobb
1936a36c79 Fix jslint issues 2015-01-23 17:23:07 -08:00
slackersoft
1dd4af3835 anything and stringMatching have custom pretty-print now. 2015-01-21 12:59:01 -08:00
slackersoft
6ae054c3e2 Update contribution guide to mention possible ffi dependencies for Ubuntu
Fixes #755
2015-01-21 12:55:07 -08:00
Gregg Van Hove
e5feba994f Merge pull request #746 from swirlycheetah/patch-1
Fix spelling mistake
2015-01-14 17:00:19 -08:00
Chris Wheatley
20faa883fb fix spelling mistake 2015-01-14 22:15:49 +00:00
Gregg Van Hove
3bba1eabd4 Merge pull request #745 from rohit/fix-repo-url
Use new jasmine github repo url
2015-01-14 10:26:39 -08:00
Rohit Arondekar
9ad3eac469 Use new jasmine github repo url 2015-01-14 20:47:09 +05:30
Gregg Van Hove
3140d5fb95 Allow createSpyObj to be called with just an array of method names
[Finish #50757607] #321
2015-01-12 15:16:50 -08:00
Gregg Van Hove
69a61547e7 Don't forget to buildDistribution
- Also fix jshint errors

[#59947350] #440
2015-01-12 14:10:50 -08:00
Gregg Van Hove
a999490de9 Merge branch 'arrayContaining' of https://github.com/slackersoft/jasmine into slackersoft-arrayContaining
Merge #440 [Finish #59947350]
2015-01-12 14:01:02 -08:00
Gregg Van Hove
c1479acd17 Fix fail specs for all browsers #734 2015-01-12 13:37:10 -08:00
Gregg Van Hove
3a93f845d6 Use the stack trace from the Error object if supplied
Fixes #734
2015-01-12 11:51:45 -08:00
Gregg Van Hove
6c58024321 Update readme with link to upgrading doc and mention browser support.
Fix #739
2015-01-12 11:06:59 -08:00
Gregg Van Hove
aeae141fd4 Merge branch 'moonmaster9000-patch-2' 2015-01-12 10:08:15 -08:00
Matt Parker
a951bbbb47 Link to the Jasmine NPM module
Also, put the jasmine-<language> links above the confusing "install jasmine on your local box" stuff (why would I want to do that?)
2015-01-12 10:08:04 -08:00
slackersoft
895c17e5c1 Merge branch 'rohit-equals-null-protoObjects' 2014-12-20 16:48:26 -08:00
Rohit Arondekar
a84eaf2cbe Allow null prototype obj to be compared for equals
Fixes #729
2014-12-20 08:35:27 +05:30
slackersoft
9f240c5b9e Build distribution to properly expose stringMatching
[#58120558]
2014-12-19 12:45:58 -08:00
slackersoft
dfa8a77dc3 Add asymmetric equality tester to match a string against a regexp
- Also move the asymmetric testers into their own dir for easier
  locating.

[#58120558] Fix #243
2014-12-19 12:39:24 -08:00
Gregg Van Hove
2472982fe9 Merge pull request #730 from rohit/patch-1
Fix URL's of Jasmine repositories on Github
2014-12-19 09:21:02 -08:00
Rohit Arondekar
c85500a924 Fix URL's of Jasmine repositories on Github 2014-12-19 07:36:03 +05:30
slackersoft
482f4d62fc Add anything matcher to match any value that is neither null or undefined
[finish #58117878] Fix #186
2014-12-17 12:58:47 -08:00
slackersoft
bfcd8b046d Allow asymmetric equality testers to preempt their symmetric brethren
- Also allow them to be compared to each other properly.

Fixes #540
2014-12-16 17:45:58 -08:00
slackersoft
2ab22951a1 Just check if either side implements asymmetricMatch
- Don't explicitly look for `Any` or `ObjectContaining`

[#82295210]
2014-12-16 17:29:18 -08:00
slackersoft
6c131beda7 Don't double escape focus spec links.
- QueryString already escapes parameter values, no need to escape when
  passing them in from HtmlReporter.

[finish #29578495]
2014-12-16 17:21:22 -08:00
slackersoft
ea88023553 Check for ObjectContaining on either side of equality.
- Also clean up `undefined` check.

Fixes #682
2014-12-16 17:07:35 -08:00
slackersoft
6bd98cb2ab Rename jasmineMatches to asymmetricMatch
- This should be more clear what it is for

[finish #82295210]
2014-12-16 16:47:31 -08:00
slackersoft
b4b3ac25a1 spyOn explicitly checks to see that a method name to spy on was passed.
[finish #27689237]
2014-12-16 13:21:48 -08:00
slackersoft
7570bc422b Display the name of the constructor when pretty printing objects
Fixes #598 [finishes #81228592]
2014-12-16 12:56:04 -08:00
slackersoft
eca8d8f009 Also test in IE 11 on travis 2014-12-16 11:57:48 -08:00
slackersoft
305252f5a8 toMatch requires the expected to be a String or RegExp
- Otherwise it was using the `toString` as the RegExp, which is almost
  definitely _not_ what you want.

Fixes #723
2014-12-16 11:50:45 -08:00
slackersoft
0fdb28c6ff Merge branch 'toEqualDomNodes' of https://github.com/alexeibs/jasmine into alexeibs-toEqualDomNodes 2014-12-16 11:25:14 -08:00
slackersoft
a84202a6f9 Also check custom properties on Arrays when computing equality
[Finishes #50616649]
2014-12-16 10:22:23 -08:00
slackersoft
503f4b7f49 Keep extra query params when focusing on a spec or suite
[finish #29578495]
2014-12-15 18:30:32 -08:00
slackersoft
fbe38018c9 Hide more things from the npm package
Fixes #726
2014-12-11 12:48:50 -08:00
slackersoft
8bb2f67fb3 Properly record finishing an xdescribe so further cleanup works
Fix #724
2014-12-09 12:40:00 -08:00
slackersoft
ba9c863de9 Add spec to verify custom query params are left alone
[#29578495]
2014-12-05 08:12:42 -08:00
slackersoft
02161b7d48 ObjectContaining no longer tries to track exact mismatches
- equals wasn't looking at it anyways, so just bail as soon as something
  is different.
2014-12-05 08:06:20 -08:00
slackersoft
4d5f27d359 Reschedule all functions for a tick before executing any
- This allows any function run during a tick to cancel any other in the
  same tick.

Fixes #708
2014-12-05 08:01:34 -08:00
slackersoft
a4faa80be4 pass through all args from external interface for befores, afters, its
Fix #483
2014-12-02 13:29:43 -08:00
slackersoft
b68ba90ad7 Just return the result directly from any and objectContaining
- They return false when they fail which means not equal.
2014-12-02 07:56:40 -08:00
slackersoft
dc7be9c55e change 2.1.3 release notes filename to match others 2014-12-01 12:49:40 -08:00
slackersoft
b56c2a69ac add standalone dist for 2.1.3 2014-12-01 12:46:52 -08:00
slackersoft
4b6789ccd9 version bump for 2.1.3 2014-12-01 12:43:52 -08:00
slackersoft
9f94e8e226 Top level suite no longer reports suiteStart and suiteDone
- jasmineStart and jasmineDone are reported separately

Fixes #716
2014-11-28 21:25:45 -08:00
slackersoft
55f32e2dc6 Don't keep the expected and actual for a passed expectation
- It causes memory problems in phantom and you probably don't need it
  anyways.

Fixes #640 Fixes #690
2014-11-22 15:03:27 -08:00
Gregg Van Hove
b30a85c8f1 Merge pull request #712 from joshk/patch-1
Use the new build env on Travis
2014-11-22 14:58:34 -08:00
Josh Kalderimis
20ce62d5f5 Use the new build env on Travis
better faster stronger

more ram, cpu, faster boot times, better network

docs coming soon
2014-11-22 14:21:03 -05:00
Christopher Amavisca
c3de57aaac Update travis badge 2014-11-22 11:16:07 -08:00
Alexei Bykov
ac8ef2988d add better support of DOM nodes into equality matcher 2014-08-24 17:07:18 +04:00
slackersoft
b5b77b318a Argument matcher for an array containing at least the specified entries 2013-10-03 18:21:47 -07:00
70 changed files with 1463 additions and 510 deletions

View File

@@ -1,6 +1,7 @@
dist/
grunt/
node_modules
pkg/
release_notes/
spec/
src/
@@ -8,14 +9,20 @@ Gemfile
Gemfile.lock
Rakefile
jasmine-core.gemspec
.rspec
.travis.yml
.jshintrc
.bundle/
.gitignore
.gitmodules
.idea
.jshintrc
.rspec
.sass-cache/
.travis.yml
*.sh
*.py
Gruntfile.js
lib/jasmine-core.rb
lib/jasmine-core/boot/
lib/jasmine-core/spec
lib/jasmine-core/version.rb
lib/jasmine-core/*.py
sauce_connect.log

View File

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

View File

@@ -9,8 +9,8 @@ Please submit pull requests via feature branches using the semi-standard workflo
1. Fork it
1. Clone your fork: (`git clone git@github.com:yourUserName/jasmine.git`)
1. Change directory: (`cd jasmine`)
1. Asign original repository to a remote named 'upstream': (`git remote add
upstream https://github.com/pivotal/jasmine.git`)
1. Assign original repository to a remote named 'upstream': (`git remote add
upstream https://github.com/jasmine/jasmine.git`)
1. Pull in changes not present in your local repository: (`git fetch upstream`)
1. Create your feature branch (`git checkout -b my-new-feature`)
1. Commit your changes (`git commit -am 'Add some feature'`)
@@ -67,7 +67,11 @@ To install the Ruby dependencies, you will need Ruby, Rubygems, and Bundler avai
$ bundle
...will install all of the Ruby dependencies.
...will install all of the Ruby dependencies. If the ffi gem fails to build its native extensions, you may need to manually install some system dependencies. On Ubuntu:
$ apt-get install gcc ruby ruby-dev libxml2 libxml2-dev libxslt1-dev
...should get you to the point that `bundle` can install everything.
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.
@@ -94,13 +98,13 @@ Follow these tips and your pull request, patch, or suggestion is much more likel
### Running Specs
Jasmine uses the [Jasmine Ruby gem](http://github.com/pivotal/jasmine-gem) to test itself in browser.
Jasmine uses the [Jasmine Ruby gem](http://github.com/jasmine/jasmine-gem) to test itself in browser.
$ rake jasmine
...and then visit `http://localhost:8888` to run specs.
Jasmine uses the [Jasmine NPM package](http://github.com/pivotal/jasmine-npm) to test itself in a Node.js/npm environment.
Jasmine uses the [Jasmine NPM package](http://github.com/jasmine/jasmine-npm) to test itself in a Node.js/npm environment.
$ grunt execSpecsInNode

View File

@@ -1,5 +1,5 @@
source 'https://rubygems.org'
gem "jasmine", :git => 'https://github.com/pivotal/jasmine-gem.git'
gem "jasmine", :git => 'https://github.com/jasmine/jasmine-gem.git'
# gem "jasmine", path: "../jasmine-gem"
gemspec

View File

@@ -1,6 +1,6 @@
<a name="README">[<img src="https://rawgithub.com/pivotal/jasmine/master/images/jasmine-horizontal.svg" width="400px" />](http://jasmine.github.io)</a>
<a name="README">[<img src="https://rawgithub.com/jasmine/jasmine/master/images/jasmine-horizontal.svg" width="400px" />](http://jasmine.github.io)</a>
[![Build Status](https://travis-ci.org/pivotal/jasmine.png?branch=master)](https://travis-ci.org/pivotal/jasmine) [![Code Climate](https://codeclimate.com/github/pivotal/jasmine.png)](https://codeclimate.com/github/pivotal/jasmine)
[![Build Status](https://travis-ci.org/jasmine/jasmine.png?branch=master)](https://travis-ci.org/jasmine/jasmine) [![Code Climate](https://codeclimate.com/github/pivotal/jasmine.png)](https://codeclimate.com/github/pivotal/jasmine)
=======
@@ -11,17 +11,26 @@ Jasmine is a Behavior Driven Development testing framework for JavaScript. It do
Documentation & guides live here: [http://jasmine.github.io](http://jasmine.github.io/)
For a quick start guide of Jasmine 2.0, see the beginning of [http://jasmine.github.io/2.0/introduction.html](http://jasmine.github.io/2.0/introduction.html)
Upgrading from Jasmine 1.x? Check out the [2.0 release notes](https://github.com/pivotal/jasmine/blob/v2.0.0/release_notes/20.md) for a list of what's new (including breaking interface changes).
Upgrading from Jasmine 1.x? Check out the [2.0 release notes](https://github.com/jasmine/jasmine/blob/v2.0.0/release_notes/20.md) for a list of what's new (including breaking interface changes). You can also read the [upgrade guide](http://jasmine.github.io/2.0/upgrading.html).
## Contributing
Please read the [contributors' guide](https://github.com/pivotal/jasmine/blob/master/CONTRIBUTING.md)
Please read the [contributors' guide](https://github.com/jasmine/jasmine/blob/master/CONTRIBUTING.md)
## Installation
For the Jasmine NPM module:<br>
[https://github.com/jasmine/jasmine-npm](https://github.com/jasmine/jasmine-npm)
For the Jasmine Ruby Gem:<br>
[https://github.com/jasmine/jasmine-gem](https://github.com/jasmine/jasmine-gem)
For the Jasmine Python Egg:<br>
[https://github.com/jasmine/jasmine-py](https://github.com/jasmine/jasmine-py)
To install Jasmine on your local box:
* Clone Jasmine - `git clone https://github.com/pivotal/jasmine.git`
* Clone Jasmine - `git clone https://github.com/jasmine/jasmine.git`
* Create a Jasmine directory in your project - `mkdir my-project/jasmine`
* Move latest dist to your project directory - `mv jasmine/dist/jasmine-standalone-2.0.0.zip my-project/jasmine`
* Change directory - `cd my-project/jasmine`
@@ -36,12 +45,9 @@ Add the following to your HTML file:
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.0/jasmine-html.js"></script>
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.0/boot.js"></script>
For the Jasmine Ruby Gem:<br>
[https://github.com/pivotal/jasmine-gem](https://github.com/pivotal/jasmine-gem)
For the Jasmine Python Egg:<br>
[https://github.com/pivotal/jasmine-py](https://github.com/pivotal/jasmine-py)
## Supported environments
Jasmine tests itself across many browsers (Safari, Chrome, Firefox, PhantomJS, and new Internet Explorer) as well as node. To see the exact version tests are run against look at our [.travis.yml](https://github.com/jasmine/jasmine/blob/master/.travis.yml)
## Support
@@ -55,7 +61,7 @@ For the Jasmine Python Egg:<br>
* [Davis W. Frank](mailto:dwfrank@pivotal.io), Pivotal Labs
* [Rajan Agaskar](mailto:rajan@pivotal.io), Pivotal Labs
* [Gregg Van Hove](mailto:ghove@pivotal.io), Pivotal Labs
* [Gregg Van Hove](mailto:gvanhove@pivotal.io), Pivotal Labs
### Maintainers Emeritus

View File

@@ -15,11 +15,16 @@ Please attempt to keep commits to `master` small, but cohesive. If a feature is
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.
The current version lives in the file `/package.json`. This version will be the version number that is currently released. When releasing a new version, update `package.json` and `bower.json` with the new version and `grunt build:copyVersionToGem` to update the gem version number.
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.
Note that Jasmine should only use the "patch" version number in the following cases:
* Changes related to packaging for a specific platform (npm, gem, or pip).
* Fixes for regressions.
When jasmine-core revs its major or minor version, the binding libraries should also rev to that version.
## Release
@@ -61,7 +66,7 @@ Probably only need to do this when releasing a minor version, and not a patch ve
### Finally
1. Visit the [Releases page for Jasmine](https://github.com/pivotal/jasmine/releases), find the tag just pushed.
1. Visit the [Releases page for Jasmine](https://github.com/jasmine/jasmine/releases), find the tag just pushed.
1. Paste in a link to the correct release notes for this release. The link should reference the blob and tag correctly, and the markdown file for the notes.
1. If it is a pre-release, mark it as such.
1. Attach the standalone zipfile

38
bower.json Normal file
View File

@@ -0,0 +1,38 @@
{
"name": "jasmine-core",
"version": "2.2.1",
"homepage": "http://jasmine.github.io",
"authors": [
"slackersoft <gregg@slackersoft.net>"
],
"description": "Official packaging of Jasmine's core files",
"keywords": [
"jasmine",
"bdd"
],
"license": "MIT",
"moduleType": "globals",
"ignore": [
"**/.*",
"dist",
"grunt",
"node_modules",
"pkg",
"release_notes",
"spec",
"src",
"Gemfile",
"Gemfile.lock",
"Rakefile",
"jasmine-core.gemspec",
"*.sh",
"*.py",
"Gruntfile.js",
"lib/jasmine-core.rb",
"lib/jasmine-core/boot/",
"lib/jasmine-core/spec",
"lib/jasmine-core/version.rb",
"lib/jasmine-core/*.py",
"sauce_connect.log"
]
}

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

Binary file not shown.

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

Binary file not shown.

View File

@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
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.homepage = "http://jasmine.github.io"
s.rubyforge_project = "jasmine-core"
s.license = "MIT"

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2014 Pivotal Labs
Copyright (c) 2008-2015 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,5 +1,5 @@
/*
Copyright (c) 2008-2014 Pivotal Labs
Copyright (c) 2008-2015 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -84,7 +84,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var htmlReporter = new jasmine.HtmlReporter({
env: env,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); },
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); },

View File

@@ -62,7 +62,8 @@
*/
var htmlReporter = new jasmine.HtmlReporter({
env: env,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); },
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); },

View File

@@ -1,6 +1,6 @@
describe("Player", function() {
var Player = require('../src/Player.js');
var Song = require('../src/Song.js');
var Player = require('../../lib/jasmine_examples/Player');
var Song = require('../../lib/jasmine_examples/Song');
var player;
var song;

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2014 Pivotal Labs
Copyright (c) 2008-2015 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -40,6 +40,7 @@ jasmineRequire.HtmlReporter = function(j$) {
createElement = options.createElement,
createTextNode = options.createTextNode,
onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
addToExistingQueryString = options.addToExistingQueryString || defaultQueryString,
timer = options.timer || noopTimer,
results = [],
specsExecuted = 0,
@@ -220,6 +221,9 @@ jasmineRequire.HtmlReporter = function(j$) {
if(noExpectations(resultNode.result)) {
specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
}
if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
}
specListNode.appendChild(
createDom('li', {
className: resultNode.result.status,
@@ -267,7 +271,7 @@ jasmineRequire.HtmlReporter = function(j$) {
function clearPrior() {
// return the reporter
var oldReporter = find('');
if(oldReporter) {
getContainer().removeChild(oldReporter);
}
@@ -306,7 +310,11 @@ jasmineRequire.HtmlReporter = function(j$) {
}
function specHref(result) {
return '?spec=' + encodeURIComponent(result.fullName);
return addToExistingQueryString('spec', result.fullName);
}
function defaultQueryString(key, value) {
return '?' + key + '=' + value;
}
function setMenuModeTo(mode) {
@@ -358,10 +366,14 @@ jasmineRequire.ResultsNode = function() {
jasmineRequire.QueryString = function() {
function QueryString(options) {
this.setParam = function(key, value) {
this.navigateWithNewParam = function(key, value) {
options.getWindowLocation().search = this.fullStringWithNewParam(key, value);
};
this.fullStringWithNewParam = function(key, value) {
var paramMap = queryStringToParamMap();
paramMap[key] = value;
options.getWindowLocation().search = toQueryString(paramMap);
return toQueryString(paramMap);
};
this.getParam = function(key) {

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2014 Pivotal Labs
Copyright (c) 2008-2015 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -20,13 +20,16 @@ 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.
*/
getJasmineRequireObj = (function (jasmineGlobal) {
var getJasmineRequireObj = (function (jasmineGlobal) {
var jasmineRequire;
if (typeof module !== 'undefined' && module.exports) {
jasmineGlobal = global;
jasmineRequire = exports;
} else {
if (typeof window !== 'undefined' && typeof window.toString === 'function' && window.toString() === '[object GjsGlobal]') {
jasmineGlobal = window;
}
jasmineRequire = jasmineGlobal.jasmineRequire = jasmineGlobal.jasmineRequire || {};
}
@@ -40,6 +43,7 @@ getJasmineRequireObj = (function (jasmineGlobal) {
jRequire.base(j$, jasmineGlobal);
j$.util = jRequire.util();
j$.Any = jRequire.Any();
j$.Anything = jRequire.Anything(j$);
j$.CallTracker = jRequire.CallTracker();
j$.MockDate = jRequire.MockDate();
j$.Clock = jRequire.Clock();
@@ -51,12 +55,14 @@ getJasmineRequireObj = (function (jasmineGlobal) {
j$.JsApiReporter = jRequire.JsApiReporter();
j$.matchersUtil = jRequire.matchersUtil(j$);
j$.ObjectContaining = jRequire.ObjectContaining(j$);
j$.ArrayContaining = jRequire.ArrayContaining(j$);
j$.pp = jRequire.pp(j$);
j$.QueueRunner = jRequire.QueueRunner(j$);
j$.ReportDispatcher = jRequire.ReportDispatcher();
j$.Spec = jRequire.Spec(j$);
j$.SpyRegistry = jRequire.SpyRegistry(j$);
j$.SpyStrategy = jRequire.SpyStrategy();
j$.StringMatching = jRequire.StringMatching(j$);
j$.Suite = jRequire.Suite();
j$.Timer = jRequire.Timer();
j$.version = jRequire.version();
@@ -138,14 +144,30 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
return obj.nodeType > 0;
};
j$.fnNameFor = function(func) {
return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1];
};
j$.any = function(clazz) {
return new j$.Any(clazz);
};
j$.anything = function() {
return new j$.Anything();
};
j$.objectContaining = function(sample) {
return new j$.ObjectContaining(sample);
};
j$.stringMatching = function(expected) {
return new j$.StringMatching(expected);
};
j$.arrayContaining = function(sample) {
return new j$.ArrayContaining(sample);
};
j$.createSpy = function(name, originalFn) {
var spyStrategy = new j$.SpyStrategy({
@@ -190,6 +212,11 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
};
j$.createSpyObj = function(baseName, methodNames) {
if (j$.isArray_(baseName) && j$.util.isUndefined(methodNames)) {
methodNames = baseName;
baseName = 'unknown';
}
if (!j$.isArray_(methodNames) || methodNames.length === 0) {
throw 'createSpyObj requires a non-empty array of method names to create spies for';
}
@@ -285,7 +312,8 @@ getJasmineRequireObj().Spec = function(j$) {
description: this.description,
fullName: this.getFullName(),
failedExpectations: [],
passedExpectations: []
passedExpectations: [],
pendingReason: ''
};
}
@@ -334,7 +362,7 @@ getJasmineRequireObj().Spec = function(j$) {
Spec.prototype.onException = function onException(e) {
if (Spec.isPendingSpecException(e)) {
this.pend();
this.pend(extractCustomPendingMessage(e));
return;
}
@@ -351,8 +379,11 @@ getJasmineRequireObj().Spec = function(j$) {
this.disabled = true;
};
Spec.prototype.pend = function() {
Spec.prototype.pend = function(message) {
this.markedPending = true;
if (message) {
this.result.pendingReason = message;
}
};
Spec.prototype.status = function() {
@@ -379,6 +410,14 @@ getJasmineRequireObj().Spec = function(j$) {
return this.getSpecName(this);
};
var extractCustomPendingMessage = function(e) {
var fullMessage = e.toString(),
boilerplateStart = fullMessage.indexOf(Spec.pendingSpecExceptionMessage),
boilerplateEnd = boilerplateStart + Spec.pendingSpecExceptionMessage.length;
return fullMessage.substr(boilerplateEnd);
};
Spec.pendingSpecExceptionMessage = '=> marked Pending';
Spec.isPendingSpecException = function(e) {
@@ -573,13 +612,7 @@ getJasmineRequireObj().Env = function(j$) {
env: this,
id: getNextSuiteId(),
description: 'Jasmine__TopLevel__Suite',
queueRunner: queueRunnerFactory,
onStart: function(suite) {
reporter.suiteStarted(suite.result);
},
resultCallback: function(attrs) {
reporter.suiteDone(attrs);
}
queueRunner: queueRunnerFactory
});
runnableLookupTable[topSuite.id] = topSuite;
defaultResourcesForRunnable(topSuite.id);
@@ -637,11 +670,12 @@ getJasmineRequireObj().Env = function(j$) {
onStart: suiteStarted,
expectationFactory: expectationFactory,
expectationResultFactory: expectationResultFactory,
runnablesExplictlySetGetter: runnablesExplictlySetGetter,
resultCallback: function(attrs) {
if (!suite.disabled) {
clearResourcesForRunnable(suite.id);
currentlyExecutingSuites.pop();
}
currentlyExecutingSuites.pop();
reporter.suiteDone(attrs);
}
});
@@ -829,8 +863,12 @@ getJasmineRequireObj().Env = function(j$) {
});
};
this.pending = function() {
throw j$.Spec.pendingSpecExceptionMessage;
this.pending = function(message) {
var fullMessage = j$.Spec.pendingSpecExceptionMessage;
if(message) {
fullMessage += message;
}
throw fullMessage;
};
this.fail = function(error) {
@@ -845,7 +883,8 @@ getJasmineRequireObj().Env = function(j$) {
passed: false,
expected: '',
actual: '',
message: message
message: message,
error: error && error.message ? error : null
});
};
}
@@ -932,43 +971,6 @@ getJasmineRequireObj().JsApiReporter = function() {
return JsApiReporter;
};
getJasmineRequireObj().Any = function() {
function Any(expectedObject) {
this.expectedObject = expectedObject;
}
Any.prototype.jasmineMatches = function(other) {
if (this.expectedObject == String) {
return typeof other == 'string' || other instanceof String;
}
if (this.expectedObject == Number) {
return typeof other == 'number' || other instanceof Number;
}
if (this.expectedObject == Function) {
return typeof other == 'function' || other instanceof Function;
}
if (this.expectedObject == Object) {
return typeof other == 'object';
}
if (this.expectedObject == Boolean) {
return typeof other == 'boolean';
}
return other instanceof this.expectedObject;
};
Any.prototype.jasmineToString = function() {
return '<jasmine.any(' + this.expectedObject + ')>';
};
return Any;
};
getJasmineRequireObj().CallTracker = function() {
function CallTracker() {
@@ -1250,6 +1252,12 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
scheduledFn.runAtMillis + scheduledFn.millis);
}
function forEachFunction(funcsToRun, callback) {
for (var i = 0; i < funcsToRun.length; ++i) {
callback(funcsToRun[i]);
}
}
function runScheduledFunctions(endTime) {
if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) {
return;
@@ -1261,15 +1269,15 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
var funcsToRun = scheduledFunctions[currentTime];
delete scheduledFunctions[currentTime];
for (var i = 0; i < funcsToRun.length; ++i) {
var funcToRun = funcsToRun[i];
forEachFunction(funcsToRun, function(funcToRun) {
if (funcToRun.recurring) {
reschedule(funcToRun);
}
});
forEachFunction(funcsToRun, function(funcToRun) {
funcToRun.funcToCall.apply(null, funcToRun.params || []);
}
});
} while (scheduledLookup.length > 0 &&
// checking first if we're out of time prevents setTimeout(0)
// scheduled in a funcToRun from forcing an extra iteration
@@ -1411,15 +1419,20 @@ getJasmineRequireObj().buildExpectationResult = function() {
var messageFormatter = options.messageFormatter || function() {},
stackFormatter = options.stackFormatter || function() {};
return {
var result = {
matcherName: options.matcherName,
expected: options.expected,
actual: options.actual,
message: message(),
stack: stack(),
passed: options.passed
};
if(!result.passed) {
result.expected = options.expected;
result.actual = options.actual;
}
return result;
function message() {
if (options.passed) {
return 'Passed.';
@@ -1507,7 +1520,7 @@ getJasmineRequireObj().MockDate = function() {
case 6:
return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3],
arguments[4], arguments[5]);
case 7:
default:
return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3],
arguments[4], arguments[5], arguments[6]);
}
@@ -1534,41 +1547,6 @@ getJasmineRequireObj().MockDate = function() {
return MockDate;
};
getJasmineRequireObj().ObjectContaining = function(j$) {
function ObjectContaining(sample) {
this.sample = sample;
}
ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); }
mismatchKeys = mismatchKeys || [];
mismatchValues = mismatchValues || [];
var hasKey = function(obj, keyName) {
return obj !== null && !j$.util.isUndefined(obj[keyName]);
};
for (var property in this.sample) {
if (!hasKey(other, property) && hasKey(this.sample, property)) {
mismatchKeys.push('expected has key \'' + property + '\', but missing from actual.');
}
else if (!j$.matchersUtil.equals(other[property], this.sample[property])) {
mismatchValues.push('\'' + property + '\' was \'' + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + '\' in actual, but was \'' + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + '\' in expected.');
}
}
return (mismatchKeys.length === 0 && mismatchValues.length === 0);
};
ObjectContaining.prototype.jasmineToString = function() {
return '<jasmine.objectContaining(' + j$.pp(this.sample) + ')>';
};
return ObjectContaining;
};
getJasmineRequireObj().pp = function(j$) {
function PrettyPrinter() {
@@ -1668,13 +1646,15 @@ getJasmineRequireObj().pp = function(j$) {
};
StringPrettyPrinter.prototype.emitObject = function(obj) {
var constructorName = obj.constructor ? j$.fnNameFor(obj.constructor) : 'null';
this.append(constructorName);
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
this.append('Object');
return;
}
var self = this;
this.append('{ ');
this.append('({ ');
var first = true;
this.iterateObject(obj, function(property, isGetter) {
@@ -1693,7 +1673,7 @@ getJasmineRequireObj().pp = function(j$) {
}
});
this.append(' }');
this.append(' })');
};
StringPrettyPrinter.prototype.append = function(value) {
@@ -1743,7 +1723,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
var queueableFn = queueableFns[iterativeIndex];
if (queueableFn.fn.length > 0) {
return attemptAsync(queueableFn);
attemptAsync(queueableFn);
return;
} else {
attemptSync(queueableFn);
}
@@ -1858,6 +1839,10 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()');
}
if (j$.util.isUndefined(methodName)) {
throw new Error('No method name supplied');
}
if (j$.util.isUndefined(obj[methodName])) {
throw new Error(methodName + '() method does not exist');
}
@@ -1964,6 +1949,7 @@ getJasmineRequireObj().Suite = function() {
this.clearStack = attrs.clearStack || function(fn) {fn();};
this.expectationFactory = attrs.expectationFactory;
this.expectationResultFactory = attrs.expectationResultFactory;
this.runnablesExplictlySetGetter = attrs.runnablesExplictlySetGetter || function() {};
this.beforeFns = [];
this.afterFns = [];
@@ -2075,14 +2061,8 @@ getJasmineRequireObj().Suite = function() {
};
Suite.prototype.isExecutable = function() {
var foundActive = false;
for(var i = 0; i < this.children.length; i++) {
if(this.children[i].isExecutable()) {
foundActive = true;
break;
}
}
return foundActive;
var runnablesExplicitlySet = this.runnablesExplictlySetGetter();
return !runnablesExplicitlySet && hasExecutableChild(this.children);
};
Suite.prototype.sharedUserContext = function() {
@@ -2135,6 +2115,17 @@ getJasmineRequireObj().Suite = function() {
return !args[0];
}
function hasExecutableChild(children) {
var foundActive = false;
for (var i = 0; i < children.length; i++) {
if (children[i].isExecutable()) {
foundActive = true;
break;
}
}
return foundActive;
}
function clone(obj) {
var clonedObj = {};
for (var prop in obj) {
@@ -2176,6 +2167,131 @@ getJasmineRequireObj().Timer = function() {
return Timer;
};
getJasmineRequireObj().Any = function() {
function Any(expectedObject) {
this.expectedObject = expectedObject;
}
Any.prototype.asymmetricMatch = function(other) {
if (this.expectedObject == String) {
return typeof other == 'string' || other instanceof String;
}
if (this.expectedObject == Number) {
return typeof other == 'number' || other instanceof Number;
}
if (this.expectedObject == Function) {
return typeof other == 'function' || other instanceof Function;
}
if (this.expectedObject == Object) {
return typeof other == 'object';
}
if (this.expectedObject == Boolean) {
return typeof other == 'boolean';
}
return other instanceof this.expectedObject;
};
Any.prototype.jasmineToString = function() {
return '<jasmine.any(' + this.expectedObject + ')>';
};
return Any;
};
getJasmineRequireObj().Anything = function(j$) {
function Anything() {}
Anything.prototype.asymmetricMatch = function(other) {
return !j$.util.isUndefined(other) && other !== null;
};
Anything.prototype.jasmineToString = function() {
return '<jasmine.anything>';
};
return Anything;
};
getJasmineRequireObj().ArrayContaining = function(j$) {
function ArrayContaining(sample) {
this.sample = sample;
}
ArrayContaining.prototype.asymmetricMatch = function(other) {
var className = Object.prototype.toString.call(this.sample);
if (className !== '[object Array]') { throw new Error('You must provide an array to arrayContaining, not \'' + this.sample + '\'.'); }
for (var i = 0; i < this.sample.length; i++) {
var item = this.sample[i];
if (!j$.matchersUtil.contains(other, item)) {
return false;
}
}
return true;
};
ArrayContaining.prototype.jasmineToString = function () {
return '<jasmine.arrayContaining(' + jasmine.pp(this.sample) +')>';
};
return ArrayContaining;
};
getJasmineRequireObj().ObjectContaining = function(j$) {
function ObjectContaining(sample) {
this.sample = sample;
}
ObjectContaining.prototype.asymmetricMatch = function(other) {
if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); }
for (var property in this.sample) {
if (!Object.prototype.hasOwnProperty.call(other, property) ||
!j$.matchersUtil.equals(this.sample[property], other[property])) {
return false;
}
}
return true;
};
ObjectContaining.prototype.jasmineToString = function() {
return '<jasmine.objectContaining(' + j$.pp(this.sample) + ')>';
};
return ObjectContaining;
};
getJasmineRequireObj().StringMatching = function(j$) {
function StringMatching(expected) {
if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) {
throw new Error('Expected is not a String or a RegExp');
}
this.regexp = new RegExp(expected);
}
StringMatching.prototype.asymmetricMatch = function(other) {
return this.regexp.test(other);
};
StringMatching.prototype.jasmineToString = function() {
return '<jasmine.stringMatching(' + this.regexp + ')>';
};
return StringMatching;
};
getJasmineRequireObj().matchersUtil = function(j$) {
// TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter?
@@ -2229,11 +2345,37 @@ getJasmineRequireObj().matchersUtil = function(j$) {
}
};
function isAsymmetric(obj) {
return obj && j$.isA_('Function', obj.asymmetricMatch);
}
function asymmetricMatch(a, b) {
var asymmetricA = isAsymmetric(a),
asymmetricB = isAsymmetric(b);
if (asymmetricA && asymmetricB) {
return undefined;
}
if (asymmetricA) {
return a.asymmetricMatch(b);
}
if (asymmetricB) {
return b.asymmetricMatch(a);
}
}
// Equality function lovingly adapted from isEqual in
// [Underscore](http://underscorejs.org)
function eq(a, b, aStack, bStack, customTesters) {
var result = true;
var asymmetricResult = asymmetricMatch(a, b);
if (!j$.util.isUndefined(asymmetricResult)) {
return asymmetricResult;
}
for (var i = 0; i < customTesters.length; i++) {
var customTesterResult = customTesters[i](a, b);
if (!j$.util.isUndefined(customTesterResult)) {
@@ -2241,27 +2383,6 @@ getJasmineRequireObj().matchersUtil = function(j$) {
}
}
if (a instanceof j$.Any) {
result = a.jasmineMatches(b);
if (result) {
return true;
}
}
if (b instanceof j$.Any) {
result = b.jasmineMatches(a);
if (result) {
return true;
}
}
if (b instanceof j$.ObjectContaining) {
result = b.jasmineMatches(a);
if (result) {
return true;
}
}
if (a instanceof Error && b instanceof Error) {
return a.message == b.message;
}
@@ -2297,6 +2418,29 @@ getJasmineRequireObj().matchersUtil = function(j$) {
a.ignoreCase == b.ignoreCase;
}
if (typeof a != 'object' || typeof b != 'object') { return false; }
var aIsDomNode = j$.isDomNode(a);
var bIsDomNode = j$.isDomNode(b);
if (aIsDomNode && bIsDomNode) {
// At first try to use DOM3 method isEqualNode
if (a.isEqualNode) {
return a.isEqualNode(b);
}
// IE8 doesn't support isEqualNode, try to use outerHTML && innerText
var aIsElement = a instanceof Element;
var bIsElement = b instanceof Element;
if (aIsElement && bIsElement) {
return a.outerHTML == b.outerHTML;
}
if (aIsElement || bIsElement) {
return false;
}
return a.innerText == b.innerText && a.textContent == b.textContent;
}
if (aIsDomNode || bIsDomNode) {
return false;
}
// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
var length = aStack.length;
@@ -2310,17 +2454,12 @@ getJasmineRequireObj().matchersUtil = function(j$) {
bStack.push(b);
var size = 0;
// Recursively compare objects and arrays.
if (className == '[object Array]') {
// Compare array lengths to determine if a deep comparison is necessary.
size = a.length;
result = size == b.length;
if (result) {
// Deep compare the contents, ignoring non-numeric properties.
while (size--) {
if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) { break; }
}
}
} else {
// Compare array lengths to determine if a deep comparison is necessary.
if (className == '[object Array]' && a.length !== b.length) {
result = false;
}
if (result) {
// Objects with different constructors are not equivalent, but `Object`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
@@ -2352,7 +2491,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
return result;
function has(obj, key) {
return obj.hasOwnProperty(key);
return Object.prototype.hasOwnProperty.call(obj, key);
}
function isFunction(obj) {
@@ -2621,11 +2760,15 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
return toHaveBeenCalledWith;
};
getJasmineRequireObj().toMatch = function() {
getJasmineRequireObj().toMatch = function(j$) {
function toMatch() {
return {
compare: function(actual, expected) {
if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) {
throw new Error('Expected is not a String or a RegExp');
}
var regexp = new RegExp(expected);
return {
@@ -2718,7 +2861,7 @@ getJasmineRequireObj().toThrowError = function(j$) {
}
if (errorMatcher.hasNoSpecifics()) {
pass.message = 'Expected function not to throw an Error, but it threw ' + fnNameFor(thrown) + '.';
pass.message = 'Expected function not to throw an Error, but it threw ' + j$.fnNameFor(thrown) + '.';
return pass;
}
@@ -2772,9 +2915,9 @@ getJasmineRequireObj().toThrowError = function(j$) {
}
return {
errorTypeDescription: errorType ? fnNameFor(errorType) : 'an exception',
errorTypeDescription: errorType ? j$.fnNameFor(errorType) : 'an exception',
thrownDescription: function(thrown) {
var thrownName = errorType ? fnNameFor(thrown.constructor) : 'an exception',
var thrownName = errorType ? j$.fnNameFor(thrown.constructor) : 'an exception',
thrownMessage = '';
if (expected) {
@@ -2802,10 +2945,6 @@ getJasmineRequireObj().toThrowError = function(j$) {
};
}
function fnNameFor(func) {
return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1];
}
function isStringOrRegExp(potential) {
return potential instanceof RegExp || (typeof potential == 'string');
}
@@ -2838,32 +2977,32 @@ getJasmineRequireObj().interface = function(jasmine, env) {
return env.fdescribe(description, specDefinitions);
},
it: function(desc, func) {
return env.it(desc, func);
it: function() {
return env.it.apply(env, arguments);
},
xit: function(desc, func) {
return env.xit(desc, func);
xit: function() {
return env.xit.apply(env, arguments);
},
fit: function(desc, func) {
return env.fit(desc, func);
fit: function() {
return env.fit.apply(env, arguments);
},
beforeEach: function(beforeEachFunction) {
return env.beforeEach(beforeEachFunction);
beforeEach: function() {
return env.beforeEach.apply(env, arguments);
},
afterEach: function(afterEachFunction) {
return env.afterEach(afterEachFunction);
afterEach: function() {
return env.afterEach.apply(env, arguments);
},
beforeAll: function(beforeAllFunction) {
return env.beforeAll(beforeAllFunction);
beforeAll: function() {
return env.beforeAll.apply(env, arguments);
},
afterAll: function(afterAllFunction) {
return env.afterAll(afterAllFunction);
afterAll: function() {
return env.afterAll.apply(env, arguments);
},
expect: function(actual) {
@@ -2871,7 +3010,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
},
pending: function() {
return env.pending();
return env.pending.apply(env, arguments);
},
fail: function() {
@@ -2905,5 +3044,5 @@ getJasmineRequireObj().interface = function(jasmine, env) {
};
getJasmineRequireObj().version = function() {
return '2.1.2';
return '2.2.0';
};

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2014 Pivotal Labs
Copyright (c) 2008-2015 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

@@ -4,6 +4,6 @@
#
module Jasmine
module Core
VERSION = "2.1.2"
VERSION = "2.2.1"
end
end

View File

@@ -1,10 +1,10 @@
{
"name": "jasmine-core",
"license": "MIT",
"version": "2.1.2",
"version": "2.2.1",
"repository": {
"type": "git",
"url": "https://github.com/pivotal/jasmine.git"
"url": "https://github.com/jasmine/jasmine.git"
},
"description": "Official packaging of Jasmine's core files for use by Node.js projects.",
"homepage": "http://jasmine.github.io",
@@ -17,7 +17,7 @@
"grunt-contrib-compress": "~0.5.2",
"shelljs": "~0.1.4",
"glob": "~3.2.9",
"jasmine": "https://github.com/pivotal/jasmine-npm/archive/master.tar.gz",
"jasmine": "https://github.com/jasmine/jasmine-npm/archive/master.tar.gz",
"load-grunt-tasks": "^0.4.0"
}
}

21
release_notes/2.1.3.md Normal file
View File

@@ -0,0 +1,21 @@
# Jasmine Core 2.1.3 Release Notes
## Summary
This release is primarily a bug-fix release to clean up some recent regressions.
## Pull Requests & Issues
* Top level suite no longer reports suiteStart and suiteDone
- Fixes [#716](https://github.com/jasmine/jasmine/issues/716)
* Don't keep the expected and actual for a passed expectation
- Fixes [#640](https://github.com/jasmine/jasmine/issues/640)
- Fixes [#690](https://github.com/jasmine/jasmine/issues/690)
* Use the new build env on Travis
- Merges [#712](https://github.com/jasmine/jasmine/issues/712) from @joshk
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

98
release_notes/2.2.0.md Normal file
View File

@@ -0,0 +1,98 @@
# Jasmine Core 2.2.0 Release Notes
## Changes
* `ObjectContaining` no longer tries to track exact mismatches
* HTML reporter keeps extra query params when focusing on a spec or suite
* Check custom properties on Arrays when computing equality
* Better error message if `spyOn` is called without a method name
* Rename `jasmineMatches` to `asymmetricMatch`
* Don't double escape focus spec links
* Jasmine equality checks if either side implements `asymmetricMatch`
* Add asymmetric equality tester to match a string with a RegExp
* Add jshint to node build on Travis for pull request builds
* Restructure node examples directory to look more realistic
## Pull Requests & Issues
* Add a basic bower config
- Fixes [#719](https://github.com/jasmine/jasmine/issues/719)
* Allow `pending` to take a reason and show it in the HtmlReporter
- Fixes [#671](https://github.com/jasmine/jasmine/issues/671)
* Set jasmineGlobal correctly in GJS
- Merges [#757](https://github.com/jasmine/jasmine/issues/757) from @ptomato
- Fixes [#751](https://github.com/jasmine/jasmine/issues/751)
* Fix some SpiderMonkey lint warnings
- Merges [#752](https://github.com/jasmine/jasmine/issues/752) from @ptomato
- Fixes [#751](https://github.com/jasmine/jasmine/issues/751)
* Prevents *Alls from running when runnables are explicitly set
- Fixes [#732](https://github.com/jasmine/jasmine/issues/732)
* Update contribution guide to mention possible ffi dependencies for Ubuntu
- Fixes [#755](https://github.com/jasmine/jasmine/issues/755)
* Fix spelling mistake in contributors guide
- Merges [#746](https://github.com/jasmine/jasmine/issues/746) from @swirlycheetah
* Use new jasmine github repo url
- Merges [#745](https://github.com/jasmine/jasmine/issues/745) rohit
* Allow `createSpyObj` to be called with just an array of method names
- Fixes [#321](https://github.com/jasmine/jasmine/issues/321)
* Add `arrayContaining` matcher
- Merges [#440](https://github.com/jasmine/jasmine/issues/440) from @slackersoft
* Use the stack trace from the Error object if supplied
- Fixes [#734](https://github.com/jasmine/jasmine/issues/734)
* Update readme with link to upgrading doc and mention browser support.
- Fixes [#739](https://github.com/jasmine/jasmine/issues/739)
* Link to the Jasmine NPM module
- Merges [#736](https://github.com/jasmine/jasmine/issues/736) from @moonmaster9000
* Allow null prototype objects to be compared for equality
- Merges [#731](https://github.com/jasmine/jasmine/issues/731) from @rohit
- Fixes [#729](https://github.com/jasmine/jasmine/issues/729)
* Fix URL's of Jasmine repositories on Github
- Merges [#730](https://github.com/jasmine/jasmine/issues/730) from @rohit
* Add `anything` matcher to match any value that is neither null or undefined
- Fixes [#186](https://github.com/jasmine/jasmine/issues/186)
* Allow asymmetric equality testers to preempt their symmetric brethren
- Fixes [#540](https://github.com/jasmine/jasmine/issues/540)
* Check for `ObjectContaining` on either side of equality
- Fixes [#682](https://github.com/jasmine/jasmine/issues/682)
* Display the name of the constructor when pretty printing objects
- Fixes [#598](https://github.com/jasmine/jasmine/issues/598)
* `toMatch` requires the `expected` to be a String or RegExp
- Fixes [#723](https://github.com/jasmine/jasmine/issues/723)
* Better equality comparison of Dom nodes
- Merges [#657](https://github.com/jasmine/jasmine/issues/657) from @alexeibs
* Hide unnecessary files from the npm package
- Fixes [#726](https://github.com/jasmine/jasmine/issues/726)
* Properly record finishing an `xdescribe` so further cleanup works
- Fixes [#724](https://github.com/jasmine/jasmine/issues/724)
* Reschedule all functions for a tick before executing any. This allows any function run during a tick to cancel any other in the same tick.
- Fixes [#708](https://github.com/jasmine/jasmine/issues/708)
* Pass through all args from external interface for befores, afters, its
- Fixes [#483](https://github.com/jasmine/jasmine/issues/483)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

15
release_notes/2.2.1.md Normal file
View File

@@ -0,0 +1,15 @@
# Jasmine Core 2.2.1 Release Notes
## Summary
This is a hotfix release to fix the packaging for bower
## Changes
* Fix missing comma on bower.json
- Merges [#763](https://github.com/jasmine/jasmine/issues/763) from @gabrielhpugliese
- Merges [#764](https://github.com/jasmine/jasmine/issues/764) from @joshuacc
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

View File

@@ -7,7 +7,7 @@ with open('package.json') as packageFile:
setup(
name="jasmine-core",
version=version,
url="http://pivotal.github.io/jasmine/",
url="http://jasmine.github.io",
author="Pivotal Labs",
author_email="jasmine-js@googlegroups.com",
description=('Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on '+

View File

@@ -255,5 +255,42 @@ describe("DelayedFunctionScheduler", function() {
scheduler.tick(10);
});
it("removes functions during a tick that runs the function", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn'),
fnDelay = 10,
timeoutKey;
timeoutKey = scheduler.scheduleFunction(fn, fnDelay, [], true);
scheduler.scheduleFunction(function () {
scheduler.removeFunctionWithId(timeoutKey);
}, 2 * fnDelay);
expect(fn).not.toHaveBeenCalled();
scheduler.tick(3 * fnDelay);
expect(fn).toHaveBeenCalled();
expect(fn.calls.count()).toBe(2);
});
it("removes functions during the first tick that runs the function", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn'),
fnDelay = 10,
timeoutKey;
timeoutKey = scheduler.scheduleFunction(fn, fnDelay, [], true);
scheduler.scheduleFunction(function () {
scheduler.removeFunctionWithId(timeoutKey);
}, fnDelay);
expect(fn).not.toHaveBeenCalled();
scheduler.tick(3 * fnDelay);
expect(fn).toHaveBeenCalled();
expect(fn.calls.count()).toBe(1);
});
});

View File

@@ -11,6 +11,12 @@ describe("Env", function() {
env.pending();
}).toThrow(j$.Spec.pendingSpecExceptionMessage);
});
it("throws the Pending Spec exception with a custom message", function() {
expect(function() {
env.pending('custom message');
}).toThrow(j$.Spec.pendingSpecExceptionMessage + 'custom message');
});
});
describe("#topSuite", function() {

View File

@@ -1,70 +0,0 @@
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");
});
it("matches recursively", function() {
var containing = new j$.ObjectContaining({one: new j$.ObjectContaining({two: {}})});
expect(containing.jasmineMatches({one: {two: {}}})).toBe(true);
});
});

View File

@@ -16,7 +16,7 @@ describe("j$.pp", function () {
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 ]");
expect(j$.pp([1, 'foo', {}, jasmine.undefined, null])).toEqual("[ 1, 'foo', Object({ }), undefined, null ]");
});
it("should indicate circular array references", function() {
@@ -32,18 +32,18 @@ describe("j$.pp", function () {
});
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: 'bar'})).toEqual("Object({ foo: 'bar' })");
expect(j$.pp({foo:'bar', baz:3, nullValue: null, undefinedValue: jasmine.undefined})).toEqual("Object({ foo: 'bar', baz: 3, nullValue: null, undefinedValue: undefined })");
expect(j$.pp({foo: function () {
}, bar: [1, 2, 3]})).toEqual("{ foo: Function, bar: [ 1, 2, 3 ] }");
}, bar: [1, 2, 3]})).toEqual("Object({ foo: Function, bar: [ 1, 2, 3 ] })");
});
it("should not include inherited properties when stringifying an object", function() {
var SomeClass = function() {};
var SomeClass = function SomeClass() {};
SomeClass.prototype.foo = "inherited foo";
var instance = new SomeClass();
instance.bar = "my own bar";
expect(j$.pp(instance)).toEqual("{ bar: 'my own bar' }");
expect(j$.pp(instance)).toEqual("SomeClass({ bar: 'my own bar' })");
});
it("should not recurse objects and arrays more deeply than j$.MAX_PRETTY_PRINT_DEPTH", function() {
@@ -53,15 +53,15 @@ describe("j$.pp", function () {
try {
j$.MAX_PRETTY_PRINT_DEPTH = 2;
expect(j$.pp(nestedObject)).toEqual("{ level1: { level2: Object } }");
expect(j$.pp(nestedObject)).toEqual("Object({ level1: Object({ 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(nestedObject)).toEqual("Object({ level1: Object({ level2: Object({ 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(nestedObject)).toEqual("Object({ level1: Object({ level2: Object({ level3: Object({ level4: 'leaf' }) }) }) })");
expect(j$.pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, [ 4, 'leaf' ] ] ] ]");
} finally {
j$.MAX_PRETTY_PRINT_DEPTH = originalMaxDepth;
@@ -73,7 +73,7 @@ describe("j$.pp", function () {
var frozenObject = {foo: {bar: 'baz'}};
frozenObject.circular = frozenObject;
frozenObject = Object.freeze(frozenObject);
expect(j$.pp(frozenObject)).toEqual("{ foo: { bar: 'baz' }, circular: <circular reference: Object> }");
expect(j$.pp(frozenObject)).toEqual("Object({ foo: Object({ bar: 'baz' }), circular: <circular reference: Object> })");
}
});
@@ -96,7 +96,7 @@ describe("j$.pp", function () {
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> }");
expect(j$.pp(sampleValue)).toEqual("Object({ foo: 'hello', nested: <circular reference: Object> })");
});
it("should indicate getters on objects as such", function() {
@@ -108,10 +108,10 @@ describe("j$.pp", function () {
});
}
if (sampleValue.__defineGetter__) {
expect(j$.pp(sampleValue)).toEqual("{ id: 1, calculatedValue: <getter> }");
expect(j$.pp(sampleValue)).toEqual("Object({ id: 1, calculatedValue: <getter> })");
}
else {
expect(j$.pp(sampleValue)).toEqual("{ id: 1 }");
expect(j$.pp(sampleValue)).toEqual("Object({ id: 1 })");
}
});
@@ -157,6 +157,6 @@ describe("j$.pp", function () {
var obj = Object.create(null);
obj.foo = 'bar';
expect(j$.pp(obj)).toEqual("{ foo: 'bar' }");
expect(j$.pp(obj)).toEqual("null({ foo: 'bar' })");
});
});

View File

@@ -14,6 +14,10 @@ describe("Spec", function() {
expect(j$.Spec.isPendingSpecException(fakeError)).toBe(true);
});
it("#isPendingSpecException returns true for a pending spec exception with a custom message", function() {
expect(j$.Spec.isPendingSpecException(j$.Spec.pendingSpecExceptionMessage + 'foo')).toBe(true);
});
it("#isPendingSpecException returns false for not a pending spec exception", function() {
var e = new Error("foo");
@@ -174,7 +178,8 @@ describe("Spec", function() {
description: 'with a spec',
fullName: 'a suite with a spec',
failedExpectations: [],
passedExpectations: []
passedExpectations: [],
pendingReason: ''
});
});
@@ -254,6 +259,24 @@ describe("Spec", function() {
spec.execute();
expect(spec.status()).toEqual("pending");
expect(spec.result.pendingReason).toEqual('');
});
it("should set the pendingReason", function() {
var fakeQueueRunner = function(opts) {
opts.onException(new Error(j$.Spec.pendingSpecExceptionMessage + 'custom message'));
},
spec = new j$.Spec({
description: 'my test',
id: 'some-id',
queueableFn: { fn: function() { } },
queueRunnerFactory: fakeQueueRunner
});
spec.execute();
expect(spec.status()).toEqual("pending");
expect(spec.result.pendingReason).toEqual('custom message');
});
});
});

View File

@@ -7,6 +7,15 @@ describe("SpyRegistry", function() {
}).toThrowError(/could not find an object/);
});
it("checks that a method name was passed", function() {
var spyRegistry = new j$.SpyRegistry(),
subject = {};
expect(function() {
spyRegistry.spyOn(subject);
}).toThrowError(/No method name supplied/);
});
it("checks for the existence of the method", function() {
var spyRegistry = new j$.SpyRegistry(),
subject = {};

View File

@@ -7,7 +7,7 @@ describe('Spies', 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);
@@ -68,6 +68,14 @@ describe('Spies', function () {
expect(spyObj.method2.and.identity()).toEqual('BaseName.method2');
});
it("should allow you to omit the baseName", function() {
var spyObj = j$.createSpyObj(['method1', 'method2']);
expect(spyObj).toEqual({ method1: jasmine.any(Function), method2: jasmine.any(Function)});
expect(spyObj.method1.and.identity()).toEqual('unknown.method1');
expect(spyObj.method2.and.identity()).toEqual('unknown.method2');
});
it("should throw if you do not pass an array argument", function() {
expect(function() {
j$.createSpyObj('BaseName');

View File

@@ -117,6 +117,32 @@ describe("Suite", function() {
expect(lastAfter).toHaveBeenCalled();
});
it("does not run *All functions if runnables are explicitly set", function(){
var env = new j$.Env(),
fakeQueueRunner = jasmine.createSpy('fake queue runner'),
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueRunner: fakeQueueRunner,
runnablesExplictlySetGetter: function(){return true;}
}),
beforeAll = jasmine.createSpy('beforeAll'),
afterAll = jasmine.createSpy('afterAll'),
fakeIt = {execute: jasmine.createSpy('it'), isExecutable: function() { return true; } };
suite.beforeAll(beforeAll);
suite.afterAll(afterAll);
suite.addChild(fakeIt);
suite.execute();
var suiteFns = fakeQueueRunner.calls.mostRecent().args[0].queueableFns;
expect(suite.isExecutable()).toBeFalsy();
expect(suiteFns.length).toEqual(1);
expect(beforeAll).not.toHaveBeenCalled();
expect(afterAll).not.toHaveBeenCalled();
});
it("can be disabled, but still calls callbacks", function() {
var env = new j$.Env(),
fakeQueueRunner = jasmine.createSpy('fake queue runner'),

View File

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

View File

@@ -0,0 +1,44 @@
describe("Anything", function() {
it("matches a string", function() {
var anything = new j$.Anything();
expect(anything.asymmetricMatch('foo')).toBe(true);
});
it("matches a number", function() {
var anything = new j$.Anything();
expect(anything.asymmetricMatch(42)).toBe(true);
});
it("matches an object", function() {
var anything = new j$.Anything();
expect(anything.asymmetricMatch({ foo: 'bar' })).toBe(true);
});
it("matches an array", function() {
var anything = new j$.Anything();
expect(anything.asymmetricMatch([1,2,3])).toBe(true);
});
it("doesn't match undefined", function() {
var anything = new j$.Anything();
expect(anything.asymmetricMatch()).toBe(false);
expect(anything.asymmetricMatch(undefined)).toBe(false);
});
it("doesn't match null", function() {
var anything = new j$.Anything();
expect(anything.asymmetricMatch(null)).toBe(false);
});
it("jasmineToString's itself", function() {
var anything = new j$.Anything();
expect(anything.jasmineToString()).toEqual("<jasmine.anything>");
});
});

View File

@@ -0,0 +1,39 @@
describe("ArrayContaining", function() {
it("matches any actual to an empty array", function() {
var containing = new j$.ArrayContaining([]);
expect(containing.asymmetricMatch("foo")).toBe(true);
});
it("does not work when not passed an array", function() {
var containing = new j$.ArrayContaining("foo");
expect(function() {
containing.asymmetricMatch([]);
}).toThrowError(/not 'foo'/);
});
it("matches when the item is in the actual", function() {
var containing = new j$.ArrayContaining(["foo"]);
expect(containing.asymmetricMatch(["foo"])).toBe(true);
});
it("matches when additional items are in the actual", function() {
var containing = new j$.ArrayContaining(["foo"]);
expect(containing.asymmetricMatch(["foo", "bar"])).toBe(true);
});
it("does not match when the item is not in the actual", function() {
var containing = new j$.ArrayContaining(["foo"]);
expect(containing.asymmetricMatch(["bar"])).toBe(false);
});
it("jasmineToStrings itself", function() {
var containing = new j$.ArrayContaining([]);
expect(containing.jasmineToString()).toMatch("<jasmine.arrayContaining");
});
});

View File

@@ -0,0 +1,58 @@
describe("ObjectContaining", function() {
it("matches any actual to an empty object", function() {
var containing = new j$.ObjectContaining({});
expect(containing.asymmetricMatch("foo")).toBe(true);
});
it("does not match an empty object actual", function() {
var containing = new j$.ObjectContaining("foo");
expect(function() {
containing.asymmetricMatch({})
}).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.asymmetricMatch({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.asymmetricMatch({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.asymmetricMatch({foo: "fooVal", bar: "barVal"})).toBe(false);
});
it("jasmineToString's itself", function() {
var containing = new j$.ObjectContaining({});
expect(containing.jasmineToString()).toMatch("<jasmine.objectContaining");
});
it("matches recursively", function() {
var containing = new j$.ObjectContaining({one: new j$.ObjectContaining({two: {}})});
expect(containing.asymmetricMatch({one: {two: {}}})).toBe(true);
});
it("matches when key is present with undefined value", function() {
var containing = new j$.ObjectContaining({ one: undefined });
expect(containing.asymmetricMatch({ one: undefined })).toBe(true);
});
it("does not match when key with undefined value is not present", function() {
var containing = new j$.ObjectContaining({ one: undefined });
expect(containing.asymmetricMatch({})).toBe(false);
});
});

View File

@@ -0,0 +1,27 @@
describe("StringMatching", function() {
it("matches a string against a provided regexp", function() {
var matcher = new j$.StringMatching(/foo/);
expect(matcher.asymmetricMatch('barfoobaz')).toBe(true);
expect(matcher.asymmetricMatch('barbaz')).toBe(false);
});
it("matches a string against provided string", function() {
var matcher = new j$.StringMatching('foo');
expect(matcher.asymmetricMatch('barfoobaz')).toBe(true);
expect(matcher.asymmetricMatch('barbaz')).toBe(false);
});
it("raises an Error when the expected is not a String or RegExp", function() {
expect(function() {
new j$.StringMatching({});
}).toThrowError(/not a String or a RegExp/);
});
it("jasmineToString's itself", function() {
var matching = new j$.StringMatching(/^foo/);
expect(matching.jasmineToString()).toEqual("<jasmine.stringMatching(/^foo/)>");
});
});

View File

@@ -100,21 +100,6 @@ describe("Env integration", function() {
env.execute();
});
it('Tells the reporter when the top-level suite has started and finished', function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('reporter', ['suiteStarted', 'suiteDone', 'jasmineDone']);
reporter.jasmineDone.and.callFake(function() {
expect(reporter.suiteStarted).toHaveBeenCalled();
expect(reporter.suiteDone).toHaveBeenCalled();
done();
});
env.addReporter(reporter);
env.execute();
});
it("Multiple top-level Suites execute as expected", function(done) {
var env = new j$.Env(),
calls = [];
@@ -176,9 +161,24 @@ describe("Env integration", function() {
})]
}));
expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({
description: 'has a message from an Error',
description: 'has a message and stack trace from an Error',
failedExpectations: [jasmine.objectContaining({
message: 'Failed: error message'
message: 'Failed: error message',
stack: {
asymmetricMatch: function(other) {
if (!other) {
// IE doesn't give us a stacktrace so just ignore it.
return true;
}
var split = other.split('\n'),
firstLine = split[0];
if (firstLine.indexOf('error message') >= 0) {
// Chrome inserts the message and a newline before the first stacktrace line.
firstLine = split[1];
}
return firstLine.indexOf('EnvSpec') >= 0;
}
}
})]
}));
done();
@@ -194,7 +194,7 @@ describe("Env integration", function() {
env.fail('messy message');
});
env.it('has a message from an Error', function() {
env.it('has a message and stack trace from an Error', function() {
env.fail(new Error('error message'));
});
});
@@ -1105,7 +1105,7 @@ describe("Env integration", function() {
});
expect(reporter.specDone.calls.count()).toBe(5);
var suiteResult = reporter.suiteStarted.calls.argsFor(1)[0];
var suiteResult = reporter.suiteStarted.calls.argsFor(0)[0];
expect(suiteResult.description).toEqual("A Suite");
done();
@@ -1137,6 +1137,67 @@ describe("Env integration", function() {
env.execute();
});
it('should report pending spec messages', function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [
'specDone',
'jasmineDone'
]);
reporter.jasmineDone.and.callFake(function() {
var specStatus = reporter.specDone.calls.argsFor(0)[0];
expect(specStatus.pendingReason).toBe('with a message');
done();
});
env.addReporter(reporter);
env.it('will be pending', function() {
env.pending('with a message');
});
env.execute();
});
it('should report xdescribes 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: 1
});
expect(reporter.specDone).not.toHaveBeenCalled();
expect(reporter.suiteDone.calls.count()).toBe(3);
done();
});
env.addReporter(reporter);
env.describe("A Suite", function() {
env.describe("nested", function() {
env.xdescribe("xd out", function() {
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;

View File

@@ -228,7 +228,7 @@ describe("jasmine spec running", function () {
env.execute();
});
it('should run beforeAlls before beforeEachs and afterAlls after afterEachs', function() {
it('should run beforeAlls before beforeEachs and afterAlls after afterEachs', function(done) {
var actions = [];
env.beforeAll(function() {
@@ -289,7 +289,7 @@ describe("jasmine spec running", function () {
env.execute();
});
it('should run beforeAlls and afterAlls as beforeEachs and afterEachs in the order declared when runnablesToRun is provided', function() {
it('should run beforeAlls and afterAlls as beforeEachs and afterEachs in the order declared when runnablesToRun is provided', function(done) {
var actions = [],
spec,
spec2;
@@ -366,6 +366,30 @@ describe("jasmine spec running", function () {
env.execute([spec.id, spec2.id]);
});
it('only runs *Alls once in a focused suite', function(done){
var actions = [];
env.fdescribe('Suite', function() {
env.beforeAll(function(){
actions.push('beforeAll');
});
env.it('should run beforeAll once', function() {
actions.push('spec');
});
env.afterAll(function(){
actions.push('afterAll');
});
});
var assertions = function() {
expect(actions).toEqual(['beforeAll', 'spec', 'afterAll']);
done();
};
env.addReporter({jasmineDone: assertions});
env.execute();
});
describe('focused runnables', function() {
it('runs the relevant alls and eachs for each runnable', function(done) {
var actions = [];

View File

@@ -58,6 +58,16 @@ describe("matchersUtil", function() {
expect(j$.matchersUtil.equals([1, 2], [1, 2, 3])).toBe(false);
});
it("fails for Arrays whose contents are equivalent, but have differing properties", function() {
var one = [1,2,3],
two = [1,2,3];
one.foo = 'bar';
two.foo = 'baz';
expect(j$.matchersUtil.equals(one, two)).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);
});
@@ -122,6 +132,45 @@ describe("matchersUtil", function() {
expect(j$.matchersUtil.equals(a,b)).toBe(true);
});
it("passes for equivalent DOM nodes", function() {
if (typeof document === 'undefined') {
return;
}
var a = document.createElement("div");
a.setAttribute("test-attr", "attr-value")
a.appendChild(document.createTextNode('test'));
var b = document.createElement("div");
b.setAttribute("test-attr", "attr-value")
b.appendChild(document.createTextNode('test'));
expect(j$.matchersUtil.equals(a,b)).toBe(true);
});
it("fails for DOM nodes with different attributes or child nodes", function() {
if (typeof document === 'undefined') {
return;
}
var a = document.createElement("div");
a.setAttribute("test-attr", "attr-value")
a.appendChild(document.createTextNode('test'));
var b = document.createElement("div");
b.setAttribute("test-attr", "attr-value2")
b.appendChild(document.createTextNode('test'));
expect(j$.matchersUtil.equals(a,b)).toBe(false);
b.setAttribute("test-attr", "attr-value");
expect(j$.matchersUtil.equals(a,b)).toBe(true);
b.appendChild(document.createTextNode('2'));
expect(j$.matchersUtil.equals(a,b)).toBe(false);
a.appendChild(document.createTextNode('2'));
expect(j$.matchersUtil.equals(a,b)).toBe(true);
});
it("passes when Any is used", function() {
var number = 3,
anyNumber = new j$.Any(Number);
@@ -142,9 +191,31 @@ describe("matchersUtil", function() {
var obj = {
foo: 3,
bar: 7
};
},
containing = new j$.ObjectContaining({foo: 3});
expect(j$.matchersUtil.equals(obj, new j$.ObjectContaining({foo: 3}))).toBe(true);
expect(j$.matchersUtil.equals(obj, containing)).toBe(true);
expect(j$.matchersUtil.equals(containing, obj)).toBe(true);
});
it("passes when an asymmetric equality tester returns true", function() {
var tester = { asymmetricMatch: function(other) { return true; } };
expect(j$.matchersUtil.equals(false, tester)).toBe(true);
expect(j$.matchersUtil.equals(tester, false)).toBe(true);
});
it("fails when an asymmetric equality tester returns false", function() {
var tester = { asymmetricMatch: function(other) { return false; } };
expect(j$.matchersUtil.equals(true, tester)).toBe(false);
expect(j$.matchersUtil.equals(tester, true)).toBe(false);
});
it("passes when ArrayContaining is used", function() {
var arr = ["foo", "bar"];
expect(j$.matchersUtil.equals(arr, new j$.ArrayContaining(["bar"]))).toBe(true);
});
it("passes when a custom equality matcher returns true", function() {
@@ -170,6 +241,45 @@ describe("matchersUtil", function() {
expect(j$.matchersUtil.equals(1, 1, [tester])).toBe(false);
});
it("passes for an asymmetric equality tester that returns true when a custom equality tester return false", function() {
var asymmetricTester = { asymmetricMatch: function(other) { return true; } },
symmetricTester = function(a, b) { return false; };
expect(j$.matchersUtil.equals(asymmetricTester, true, [symmetricTester])).toBe(true);
expect(j$.matchersUtil.equals(true, asymmetricTester, [symmetricTester])).toBe(true);
});
it("passes when an Any is compared to an Any that checks for the same type", function() {
var any1 = new j$.Any(Function),
any2 = new j$.Any(Function);
expect(j$.matchersUtil.equals(any1, any2)).toBe(true);
});
it("passes for null prototype objects with same properties", function () {
if (jasmine.getEnv().ieVersion < 9) { return; }
var objA = Object.create(null),
objB = Object.create(null);
objA.name = 'test';
objB.name = 'test';
expect(j$.matchersUtil.equals(objA, objB)).toBe(true);
});
it("fails for null prototype objects with different properties", function () {
if (jasmine.getEnv().ieVersion < 9) { return; }
var objA = Object.create(null),
objB = Object.create(null);
objA.name = 'test';
objB.test = 'name';
expect(j$.matchersUtil.equals(objA, objB)).toBe(false);
});
});
describe("contains", function() {

View File

@@ -30,5 +30,13 @@ describe("toMatch", function() {
result = matcher.compare('bar', 'foo');
expect(result.pass).toBe(false);
});
it("throws an Error when the expected is not a String or RegExp", function() {
var matcher = j$.matchers.toMatch();
expect(function() {
matcher.compare('foo', { bar: 'baz' });
}).toThrowError('Expected is not a String or a RegExp');
});
});

View File

@@ -278,7 +278,8 @@ describe("New HtmlReporter", function() {
env: env,
getContainer: getContainer,
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
addToExistingQueryString: function(key, value) { return "?foo=bar&" + key + "=" + value; }
});
reporter.initialize();
@@ -350,7 +351,7 @@ describe("New HtmlReporter", function() {
var suiteDetail = outerSuite.childNodes[0];
var suiteLink = suiteDetail.childNodes[0];
expect(suiteLink.innerHTML).toEqual("A Suite");
expect(suiteLink.getAttribute('href')).toEqual("?spec=A%20Suite");
expect(suiteLink.getAttribute('href')).toEqual("?foo=bar&spec=A Suite");
var specs = outerSuite.childNodes[1];
var spec = specs.childNodes[0];
@@ -359,7 +360,7 @@ describe("New HtmlReporter", function() {
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("href")).toEqual("?foo=bar&spec=A Suite with a spec");
// expect(specLink.getAttribute("title")).toEqual("A Suite with a spec");
});
@@ -532,14 +533,17 @@ describe("New HtmlReporter", function() {
reporter.initialize();
reporter.jasmineStarted({ totalSpecsDefined: 1 });
reporter.specDone({
var specStatus = {
id: 123,
description: "with a spec",
fullName: "A Suite with a spec",
status: "pending",
passedExpectations: [],
failedExpectations: []
});
failedExpectations: [],
pendingReason: "my custom pending reason"
};
reporter.specStarted(specStatus);
reporter.specDone(specStatus);
reporter.jasmineDone({});
});
@@ -554,6 +558,12 @@ describe("New HtmlReporter", function() {
expect(specFailure.childNodes.length).toEqual(0);
});
it("displays the custom pending reason", function() {
var pendingDetails = container.querySelector(".summary .pending");
expect(pendingDetails.innerHTML).toContain("my custom pending reason");
});
});
describe("and some tests fail", function() {
@@ -567,7 +577,8 @@ describe("New HtmlReporter", function() {
env: env,
getContainer: getContainer,
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); }
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
addToExistingQueryString: function(key, value) { return "?foo=bar&" + key + "=" + value; }
});
reporter.initialize();
@@ -614,7 +625,7 @@ describe("New HtmlReporter", function() {
var specLink = specDiv.childNodes[0];
expect(specLink.getAttribute("title")).toEqual("a suite with a failing spec");
expect(specLink.getAttribute("href")).toEqual("?spec=a%20suite%20with%20a%20failing%20spec");
expect(specLink.getAttribute("href")).toEqual("?foo=bar&spec=a suite with a failing spec");
var message = failure.childNodes[1].childNodes[0];
expect(message.getAttribute("class")).toEqual("result-message");

View File

@@ -3,7 +3,7 @@ describe("j$.pp (HTML Dependent)", function () {
var sampleNode = document.createElement('div');
sampleNode.innerHTML = 'foo<b>bar</b>';
expect(j$.pp(sampleNode)).toEqual("HTMLNode");
expect(j$.pp({foo: sampleNode})).toEqual("{ foo: HTMLNode }");
expect(j$.pp({foo: sampleNode})).toEqual("Object({ foo: HTMLNode })");
});
it("should print Firefox's wrapped native objects correctly", function() {

View File

@@ -1,7 +1,6 @@
describe("QueryString", function() {
describe("#setParam", function() {
describe("#navigateWithNewParam", function() {
it("sets the query string to include the given key/value pair", function() {
var windowLocation = {
search: ""
@@ -10,10 +9,40 @@ describe("QueryString", function() {
getWindowLocation: function() { return windowLocation }
});
queryString.setParam("foo", "bar baz");
queryString.navigateWithNewParam("foo", "bar baz");
expect(windowLocation.search).toMatch(/foo=bar%20baz/);
});
it("leaves existing params alone", function() {
var windowLocation = {
search: "?foo=bar"
},
queryString = new j$.QueryString({
getWindowLocation: function() { return windowLocation }
});
queryString.navigateWithNewParam("baz", "quux");
expect(windowLocation.search).toMatch(/foo=bar/);
expect(windowLocation.search).toMatch(/baz=quux/);
});
});
describe('#fullStringWithNewParam', function() {
it("gets the query string including the given key/value pair", function() {
var windowLocation = {
search: "?foo=bar"
},
queryString = new j$.QueryString({
getWindowLocation: function() { return windowLocation }
});
var result = queryString.fullStringWithNewParam("baz", "quux");
expect(result).toMatch(/foo=bar/);
expect(result).toMatch(/baz=quux/);
});
});
describe("#getParam", function() {

View File

@@ -114,6 +114,12 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
scheduledFn.runAtMillis + scheduledFn.millis);
}
function forEachFunction(funcsToRun, callback) {
for (var i = 0; i < funcsToRun.length; ++i) {
callback(funcsToRun[i]);
}
}
function runScheduledFunctions(endTime) {
if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) {
return;
@@ -125,15 +131,15 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
var funcsToRun = scheduledFunctions[currentTime];
delete scheduledFunctions[currentTime];
for (var i = 0; i < funcsToRun.length; ++i) {
var funcToRun = funcsToRun[i];
forEachFunction(funcsToRun, function(funcToRun) {
if (funcToRun.recurring) {
reschedule(funcToRun);
}
});
forEachFunction(funcsToRun, function(funcToRun) {
funcToRun.funcToCall.apply(null, funcToRun.params || []);
}
});
} while (scheduledLookup.length > 0 &&
// checking first if we're out of time prevents setTimeout(0)
// scheduled in a funcToRun from forcing an extra iteration

View File

@@ -179,13 +179,7 @@ getJasmineRequireObj().Env = function(j$) {
env: this,
id: getNextSuiteId(),
description: 'Jasmine__TopLevel__Suite',
queueRunner: queueRunnerFactory,
onStart: function(suite) {
reporter.suiteStarted(suite.result);
},
resultCallback: function(attrs) {
reporter.suiteDone(attrs);
}
queueRunner: queueRunnerFactory
});
runnableLookupTable[topSuite.id] = topSuite;
defaultResourcesForRunnable(topSuite.id);
@@ -243,11 +237,12 @@ getJasmineRequireObj().Env = function(j$) {
onStart: suiteStarted,
expectationFactory: expectationFactory,
expectationResultFactory: expectationResultFactory,
runnablesExplictlySetGetter: runnablesExplictlySetGetter,
resultCallback: function(attrs) {
if (!suite.disabled) {
clearResourcesForRunnable(suite.id);
currentlyExecutingSuites.pop();
}
currentlyExecutingSuites.pop();
reporter.suiteDone(attrs);
}
});
@@ -435,8 +430,12 @@ getJasmineRequireObj().Env = function(j$) {
});
};
this.pending = function() {
throw j$.Spec.pendingSpecExceptionMessage;
this.pending = function(message) {
var fullMessage = j$.Spec.pendingSpecExceptionMessage;
if(message) {
fullMessage += message;
}
throw fullMessage;
};
this.fail = function(error) {
@@ -451,7 +450,8 @@ getJasmineRequireObj().Env = function(j$) {
passed: false,
expected: '',
actual: '',
message: message
message: message,
error: error && error.message ? error : null
});
};
}

View File

@@ -4,15 +4,20 @@ getJasmineRequireObj().buildExpectationResult = function() {
var messageFormatter = options.messageFormatter || function() {},
stackFormatter = options.stackFormatter || function() {};
return {
var result = {
matcherName: options.matcherName,
expected: options.expected,
actual: options.actual,
message: message(),
stack: stack(),
passed: options.passed
};
if(!result.passed) {
result.expected = options.expected;
result.actual = options.actual;
}
return result;
function message() {
if (options.passed) {
return 'Passed.';

View File

@@ -54,7 +54,7 @@ getJasmineRequireObj().MockDate = function() {
case 6:
return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3],
arguments[4], arguments[5]);
case 7:
default:
return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3],
arguments[4], arguments[5], arguments[6]);
}

View File

@@ -1,34 +0,0 @@
getJasmineRequireObj().ObjectContaining = function(j$) {
function ObjectContaining(sample) {
this.sample = sample;
}
ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); }
mismatchKeys = mismatchKeys || [];
mismatchValues = mismatchValues || [];
var hasKey = function(obj, keyName) {
return obj !== null && !j$.util.isUndefined(obj[keyName]);
};
for (var property in this.sample) {
if (!hasKey(other, property) && hasKey(this.sample, property)) {
mismatchKeys.push('expected has key \'' + property + '\', but missing from actual.');
}
else if (!j$.matchersUtil.equals(other[property], this.sample[property])) {
mismatchValues.push('\'' + property + '\' was \'' + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + '\' in actual, but was \'' + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + '\' in expected.');
}
}
return (mismatchKeys.length === 0 && mismatchValues.length === 0);
};
ObjectContaining.prototype.jasmineToString = function() {
return '<jasmine.objectContaining(' + j$.pp(this.sample) + ')>';
};
return ObjectContaining;
};

View File

@@ -97,13 +97,15 @@ getJasmineRequireObj().pp = function(j$) {
};
StringPrettyPrinter.prototype.emitObject = function(obj) {
var constructorName = obj.constructor ? j$.fnNameFor(obj.constructor) : 'null';
this.append(constructorName);
if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
this.append('Object');
return;
}
var self = this;
this.append('{ ');
this.append('({ ');
var first = true;
this.iterateObject(obj, function(property, isGetter) {
@@ -122,7 +124,7 @@ getJasmineRequireObj().pp = function(j$) {
}
});
this.append(' }');
this.append(' })');
};
StringPrettyPrinter.prototype.append = function(value) {

View File

@@ -34,7 +34,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
var queueableFn = queueableFns[iterativeIndex];
if (queueableFn.fn.length > 0) {
return attemptAsync(queueableFn);
attemptAsync(queueableFn);
return;
} else {
attemptSync(queueableFn);
}

View File

@@ -22,7 +22,8 @@ getJasmineRequireObj().Spec = function(j$) {
description: this.description,
fullName: this.getFullName(),
failedExpectations: [],
passedExpectations: []
passedExpectations: [],
pendingReason: ''
};
}
@@ -71,7 +72,7 @@ getJasmineRequireObj().Spec = function(j$) {
Spec.prototype.onException = function onException(e) {
if (Spec.isPendingSpecException(e)) {
this.pend();
this.pend(extractCustomPendingMessage(e));
return;
}
@@ -88,8 +89,11 @@ getJasmineRequireObj().Spec = function(j$) {
this.disabled = true;
};
Spec.prototype.pend = function() {
Spec.prototype.pend = function(message) {
this.markedPending = true;
if (message) {
this.result.pendingReason = message;
}
};
Spec.prototype.status = function() {
@@ -116,6 +120,14 @@ getJasmineRequireObj().Spec = function(j$) {
return this.getSpecName(this);
};
var extractCustomPendingMessage = function(e) {
var fullMessage = e.toString(),
boilerplateStart = fullMessage.indexOf(Spec.pendingSpecExceptionMessage),
boilerplateEnd = boilerplateStart + Spec.pendingSpecExceptionMessage.length;
return fullMessage.substr(boilerplateEnd);
};
Spec.pendingSpecExceptionMessage = '=> marked Pending';
Spec.isPendingSpecException = function(e) {

View File

@@ -9,6 +9,10 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()');
}
if (j$.util.isUndefined(methodName)) {
throw new Error('No method name supplied');
}
if (j$.util.isUndefined(obj[methodName])) {
throw new Error(methodName + '() method does not exist');
}

View File

@@ -9,6 +9,7 @@ getJasmineRequireObj().Suite = function() {
this.clearStack = attrs.clearStack || function(fn) {fn();};
this.expectationFactory = attrs.expectationFactory;
this.expectationResultFactory = attrs.expectationResultFactory;
this.runnablesExplictlySetGetter = attrs.runnablesExplictlySetGetter || function() {};
this.beforeFns = [];
this.afterFns = [];
@@ -120,14 +121,8 @@ getJasmineRequireObj().Suite = function() {
};
Suite.prototype.isExecutable = function() {
var foundActive = false;
for(var i = 0; i < this.children.length; i++) {
if(this.children[i].isExecutable()) {
foundActive = true;
break;
}
}
return foundActive;
var runnablesExplicitlySet = this.runnablesExplictlySetGetter();
return !runnablesExplicitlySet && hasExecutableChild(this.children);
};
Suite.prototype.sharedUserContext = function() {
@@ -180,6 +175,17 @@ getJasmineRequireObj().Suite = function() {
return !args[0];
}
function hasExecutableChild(children) {
var foundActive = false;
for (var i = 0; i < children.length; i++) {
if (children[i].isExecutable()) {
foundActive = true;
break;
}
}
return foundActive;
}
function clone(obj) {
var clonedObj = {};
for (var prop in obj) {

View File

@@ -4,7 +4,7 @@ getJasmineRequireObj().Any = function() {
this.expectedObject = expectedObject;
}
Any.prototype.jasmineMatches = function(other) {
Any.prototype.asymmetricMatch = function(other) {
if (this.expectedObject == String) {
return typeof other == 'string' || other instanceof String;
}
@@ -20,7 +20,7 @@ getJasmineRequireObj().Any = function() {
if (this.expectedObject == Object) {
return typeof other == 'object';
}
if (this.expectedObject == Boolean) {
return typeof other == 'boolean';
}

View File

@@ -0,0 +1,14 @@
getJasmineRequireObj().Anything = function(j$) {
function Anything() {}
Anything.prototype.asymmetricMatch = function(other) {
return !j$.util.isUndefined(other) && other !== null;
};
Anything.prototype.jasmineToString = function() {
return '<jasmine.anything>';
};
return Anything;
};

View File

@@ -0,0 +1,25 @@
getJasmineRequireObj().ArrayContaining = function(j$) {
function ArrayContaining(sample) {
this.sample = sample;
}
ArrayContaining.prototype.asymmetricMatch = function(other) {
var className = Object.prototype.toString.call(this.sample);
if (className !== '[object Array]') { throw new Error('You must provide an array to arrayContaining, not \'' + this.sample + '\'.'); }
for (var i = 0; i < this.sample.length; i++) {
var item = this.sample[i];
if (!j$.matchersUtil.contains(other, item)) {
return false;
}
}
return true;
};
ArrayContaining.prototype.jasmineToString = function () {
return '<jasmine.arrayContaining(' + jasmine.pp(this.sample) +')>';
};
return ArrayContaining;
};

View File

@@ -0,0 +1,25 @@
getJasmineRequireObj().ObjectContaining = function(j$) {
function ObjectContaining(sample) {
this.sample = sample;
}
ObjectContaining.prototype.asymmetricMatch = function(other) {
if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); }
for (var property in this.sample) {
if (!Object.prototype.hasOwnProperty.call(other, property) ||
!j$.matchersUtil.equals(this.sample[property], other[property])) {
return false;
}
}
return true;
};
ObjectContaining.prototype.jasmineToString = function() {
return '<jasmine.objectContaining(' + j$.pp(this.sample) + ')>';
};
return ObjectContaining;
};

View File

@@ -0,0 +1,20 @@
getJasmineRequireObj().StringMatching = function(j$) {
function StringMatching(expected) {
if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) {
throw new Error('Expected is not a String or a RegExp');
}
this.regexp = new RegExp(expected);
}
StringMatching.prototype.asymmetricMatch = function(other) {
return this.regexp.test(other);
};
StringMatching.prototype.jasmineToString = function() {
return '<jasmine.stringMatching(' + this.regexp + ')>';
};
return StringMatching;
};

View File

@@ -37,14 +37,30 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
return obj.nodeType > 0;
};
j$.fnNameFor = function(func) {
return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1];
};
j$.any = function(clazz) {
return new j$.Any(clazz);
};
j$.anything = function() {
return new j$.Anything();
};
j$.objectContaining = function(sample) {
return new j$.ObjectContaining(sample);
};
j$.stringMatching = function(expected) {
return new j$.StringMatching(expected);
};
j$.arrayContaining = function(sample) {
return new j$.ArrayContaining(sample);
};
j$.createSpy = function(name, originalFn) {
var spyStrategy = new j$.SpyStrategy({
@@ -89,6 +105,11 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
};
j$.createSpyObj = function(baseName, methodNames) {
if (j$.isArray_(baseName) && j$.util.isUndefined(methodNames)) {
methodNames = baseName;
baseName = 'unknown';
}
if (!j$.isArray_(methodNames) || methodNames.length === 0) {
throw 'createSpyObj requires a non-empty array of method names to create spies for';
}

View File

@@ -51,11 +51,37 @@ getJasmineRequireObj().matchersUtil = function(j$) {
}
};
function isAsymmetric(obj) {
return obj && j$.isA_('Function', obj.asymmetricMatch);
}
function asymmetricMatch(a, b) {
var asymmetricA = isAsymmetric(a),
asymmetricB = isAsymmetric(b);
if (asymmetricA && asymmetricB) {
return undefined;
}
if (asymmetricA) {
return a.asymmetricMatch(b);
}
if (asymmetricB) {
return b.asymmetricMatch(a);
}
}
// Equality function lovingly adapted from isEqual in
// [Underscore](http://underscorejs.org)
function eq(a, b, aStack, bStack, customTesters) {
var result = true;
var asymmetricResult = asymmetricMatch(a, b);
if (!j$.util.isUndefined(asymmetricResult)) {
return asymmetricResult;
}
for (var i = 0; i < customTesters.length; i++) {
var customTesterResult = customTesters[i](a, b);
if (!j$.util.isUndefined(customTesterResult)) {
@@ -63,27 +89,6 @@ getJasmineRequireObj().matchersUtil = function(j$) {
}
}
if (a instanceof j$.Any) {
result = a.jasmineMatches(b);
if (result) {
return true;
}
}
if (b instanceof j$.Any) {
result = b.jasmineMatches(a);
if (result) {
return true;
}
}
if (b instanceof j$.ObjectContaining) {
result = b.jasmineMatches(a);
if (result) {
return true;
}
}
if (a instanceof Error && b instanceof Error) {
return a.message == b.message;
}
@@ -119,6 +124,29 @@ getJasmineRequireObj().matchersUtil = function(j$) {
a.ignoreCase == b.ignoreCase;
}
if (typeof a != 'object' || typeof b != 'object') { return false; }
var aIsDomNode = j$.isDomNode(a);
var bIsDomNode = j$.isDomNode(b);
if (aIsDomNode && bIsDomNode) {
// At first try to use DOM3 method isEqualNode
if (a.isEqualNode) {
return a.isEqualNode(b);
}
// IE8 doesn't support isEqualNode, try to use outerHTML && innerText
var aIsElement = a instanceof Element;
var bIsElement = b instanceof Element;
if (aIsElement && bIsElement) {
return a.outerHTML == b.outerHTML;
}
if (aIsElement || bIsElement) {
return false;
}
return a.innerText == b.innerText && a.textContent == b.textContent;
}
if (aIsDomNode || bIsDomNode) {
return false;
}
// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
var length = aStack.length;
@@ -132,17 +160,12 @@ getJasmineRequireObj().matchersUtil = function(j$) {
bStack.push(b);
var size = 0;
// Recursively compare objects and arrays.
if (className == '[object Array]') {
// Compare array lengths to determine if a deep comparison is necessary.
size = a.length;
result = size == b.length;
if (result) {
// Deep compare the contents, ignoring non-numeric properties.
while (size--) {
if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) { break; }
}
}
} else {
// Compare array lengths to determine if a deep comparison is necessary.
if (className == '[object Array]' && a.length !== b.length) {
result = false;
}
if (result) {
// Objects with different constructors are not equivalent, but `Object`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
@@ -174,7 +197,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
return result;
function has(obj, key) {
return obj.hasOwnProperty(key);
return Object.prototype.hasOwnProperty.call(obj, key);
}
function isFunction(obj) {

View File

@@ -1,8 +1,12 @@
getJasmineRequireObj().toMatch = function() {
getJasmineRequireObj().toMatch = function(j$) {
function toMatch() {
return {
compare: function(actual, expected) {
if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) {
throw new Error('Expected is not a String or a RegExp');
}
var regexp = new RegExp(expected);
return {

View File

@@ -31,7 +31,7 @@ getJasmineRequireObj().toThrowError = function(j$) {
}
if (errorMatcher.hasNoSpecifics()) {
pass.message = 'Expected function not to throw an Error, but it threw ' + fnNameFor(thrown) + '.';
pass.message = 'Expected function not to throw an Error, but it threw ' + j$.fnNameFor(thrown) + '.';
return pass;
}
@@ -85,9 +85,9 @@ getJasmineRequireObj().toThrowError = function(j$) {
}
return {
errorTypeDescription: errorType ? fnNameFor(errorType) : 'an exception',
errorTypeDescription: errorType ? j$.fnNameFor(errorType) : 'an exception',
thrownDescription: function(thrown) {
var thrownName = errorType ? fnNameFor(thrown.constructor) : 'an exception',
var thrownName = errorType ? j$.fnNameFor(thrown.constructor) : 'an exception',
thrownMessage = '';
if (expected) {
@@ -115,10 +115,6 @@ getJasmineRequireObj().toThrowError = function(j$) {
};
}
function fnNameFor(func) {
return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1];
}
function isStringOrRegExp(potential) {
return potential instanceof RegExp || (typeof potential == 'string');
}

View File

@@ -1,10 +1,13 @@
getJasmineRequireObj = (function (jasmineGlobal) {
var getJasmineRequireObj = (function (jasmineGlobal) {
var jasmineRequire;
if (typeof module !== 'undefined' && module.exports) {
jasmineGlobal = global;
jasmineRequire = exports;
} else {
if (typeof window !== 'undefined' && typeof window.toString === 'function' && window.toString() === '[object GjsGlobal]') {
jasmineGlobal = window;
}
jasmineRequire = jasmineGlobal.jasmineRequire = jasmineGlobal.jasmineRequire || {};
}
@@ -18,6 +21,7 @@ getJasmineRequireObj = (function (jasmineGlobal) {
jRequire.base(j$, jasmineGlobal);
j$.util = jRequire.util();
j$.Any = jRequire.Any();
j$.Anything = jRequire.Anything(j$);
j$.CallTracker = jRequire.CallTracker();
j$.MockDate = jRequire.MockDate();
j$.Clock = jRequire.Clock();
@@ -29,12 +33,14 @@ getJasmineRequireObj = (function (jasmineGlobal) {
j$.JsApiReporter = jRequire.JsApiReporter();
j$.matchersUtil = jRequire.matchersUtil(j$);
j$.ObjectContaining = jRequire.ObjectContaining(j$);
j$.ArrayContaining = jRequire.ArrayContaining(j$);
j$.pp = jRequire.pp(j$);
j$.QueueRunner = jRequire.QueueRunner(j$);
j$.ReportDispatcher = jRequire.ReportDispatcher();
j$.Spec = jRequire.Spec(j$);
j$.SpyRegistry = jRequire.SpyRegistry(j$);
j$.SpyStrategy = jRequire.SpyStrategy();
j$.StringMatching = jRequire.StringMatching(j$);
j$.Suite = jRequire.Suite();
j$.Timer = jRequire.Timer();
j$.version = jRequire.version();

View File

@@ -12,32 +12,32 @@ getJasmineRequireObj().interface = function(jasmine, env) {
return env.fdescribe(description, specDefinitions);
},
it: function(desc, func) {
return env.it(desc, func);
it: function() {
return env.it.apply(env, arguments);
},
xit: function(desc, func) {
return env.xit(desc, func);
xit: function() {
return env.xit.apply(env, arguments);
},
fit: function(desc, func) {
return env.fit(desc, func);
fit: function() {
return env.fit.apply(env, arguments);
},
beforeEach: function(beforeEachFunction) {
return env.beforeEach(beforeEachFunction);
beforeEach: function() {
return env.beforeEach.apply(env, arguments);
},
afterEach: function(afterEachFunction) {
return env.afterEach(afterEachFunction);
afterEach: function() {
return env.afterEach.apply(env, arguments);
},
beforeAll: function(beforeAllFunction) {
return env.beforeAll(beforeAllFunction);
beforeAll: function() {
return env.beforeAll.apply(env, arguments);
},
afterAll: function(afterAllFunction) {
return env.afterAll(afterAllFunction);
afterAll: function() {
return env.afterAll.apply(env, arguments);
},
expect: function(actual) {
@@ -45,7 +45,7 @@ getJasmineRequireObj().interface = function(jasmine, env) {
},
pending: function() {
return env.pending();
return env.pending.apply(env, arguments);
},
fail: function() {

View File

@@ -11,6 +11,7 @@ jasmineRequire.HtmlReporter = function(j$) {
createElement = options.createElement,
createTextNode = options.createTextNode,
onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
addToExistingQueryString = options.addToExistingQueryString || defaultQueryString,
timer = options.timer || noopTimer,
results = [],
specsExecuted = 0,
@@ -191,6 +192,9 @@ jasmineRequire.HtmlReporter = function(j$) {
if(noExpectations(resultNode.result)) {
specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
}
if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
}
specListNode.appendChild(
createDom('li', {
className: resultNode.result.status,
@@ -238,7 +242,7 @@ jasmineRequire.HtmlReporter = function(j$) {
function clearPrior() {
// return the reporter
var oldReporter = find('');
if(oldReporter) {
getContainer().removeChild(oldReporter);
}
@@ -277,7 +281,11 @@ jasmineRequire.HtmlReporter = function(j$) {
}
function specHref(result) {
return '?spec=' + encodeURIComponent(result.fullName);
return addToExistingQueryString('spec', result.fullName);
}
function defaultQueryString(key, value) {
return '?' + key + '=' + value;
}
function setMenuModeTo(mode) {

View File

@@ -1,10 +1,14 @@
jasmineRequire.QueryString = function() {
function QueryString(options) {
this.setParam = function(key, value) {
this.navigateWithNewParam = function(key, value) {
options.getWindowLocation().search = this.fullStringWithNewParam(key, value);
};
this.fullStringWithNewParam = function(key, value) {
var paramMap = queryStringToParamMap();
paramMap[key] = value;
options.getWindowLocation().search = toQueryString(paramMap);
return toQueryString(paramMap);
};
this.getParam = function(key) {

View File

@@ -3,4 +3,4 @@
npm install -g grunt-cli
npm install
grunt execSpecsInNode
grunt jshint execSpecsInNode