Compare commits

..

61 Commits

Author SHA1 Message Date
Sheel Choksi 04c7db9259 Update built distribution to include latest 2.0.0-rc5 fixes 2013-10-29 17:40:15 -07:00
Sheel Choksi 8585ef69a5 Update clock not installed message to reflect current boot installation process 2013-10-29 17:33:51 -07:00
Sheel Choksi cb5aea1fcf Fix builds by working around browser timing functions not being successfully overridden 2013-10-29 17:32:04 -07:00
Sheel Choksi 966f76b481 Add in missing clock uninstall 2013-10-29 17:28:41 -07:00
Sheel Choksi 40e3020fdc Build distribution for 2.0.0-rc5 and associated standalone distribution 2013-10-29 14:03:02 -07:00
Sheel Choksi 69549a6ff3 Add in 2.0.0-rc5 release notes 2013-10-29 14:03:01 -07:00
Sheel Choksi a03fad8911 Move built console.js into lib and include in standalone distribution
[finishes #59679110]
2013-10-29 14:03:01 -07:00
Sheel Choksi 61993cf1fc Expose Jasmine's topSuite [finishes #59774024] 2013-10-29 11:27:12 -07:00
Kyriacos Souroullas and Sheel Choksi cd9d5284cd Matchers can have a negativeCompare
- Passing in a 'negativeCompare' will cause that function to be used when it is a 'not' assertion
- Otherwise, the reversal of the compare's result will be used instead

[finishes #59703824]
2013-10-28 17:13:18 -07:00
Kyriacos Souroullas and Sheel Choksi e346e7dcc1 Revert removal of compare nesting
Since we want the user to be able to pass a negative comparison function, the extra layer of wrapping is now needed
2013-10-28 17:13:09 -07:00
Davis W. Frank dd8a455f91 Adding Code Climate badge to README 2013-10-25 12:25:27 -07:00
Davis W. Frank 9e149d1e0f Move node dev deps forward, add .jshintrc to support latest grunt-contrib-jshint and Code Climate score 2013-10-25 12:23:57 -07:00
Sheel Choksi and Tim Jarratt 797984f173 Add newlines to end of files 2013-10-25 10:57:43 -07:00
Sheel Choksi and Tim Jarratt 29c5c127e5 Refactor Suite.addSpec and .addSuite to .addChild 2013-10-25 10:52:31 -07:00
Sheel Choksi and Tim Jarratt 26581b4c91 Rename Suite.children_ to .children
Also removed some unit tests that were brittle, and already tested by
better, more round-trip tests.
2013-10-25 10:25:50 -07:00
Davis W. Frank 243ff80196 Fixing global leak for 'timer' 2013-10-24 17:17:05 -07:00
Davis W. Frank 284bb0b608 Giving Sheel his due 2013-10-24 16:55:51 -07:00
Sheel Choksi 6453ed656b Suites just have children instead of separating into specs/suites 2013-10-24 16:35:00 -07:00
Sheel Choksi a1a948b8df Remove completeCallback from suite as its unused 2013-10-24 16:34:34 -07:00
Sheel Choksi 7a4876ecfa Also move function to determine whether specs should catch exceptions into closure 2013-10-24 16:24:55 -07:00
Sheel Choksi d9ece1f14f Remove version/versionString and currentRunner
- Instead of version/versionString, jasmine.version should be sufficient
- currentRunner was exposing Jasmine's internal top level suite
2013-10-24 15:42:46 -07:00
Sheel Choksi f1613ce77c Move additional methods from Env prototype to env closure
- Users can no longer spelunk the spec tree from topSuite
- Users no longer have access to currentSuite/currentSpec
- Other miscellaneous (arguably less useful) methods have also been tucked
away into the closure, like suiteFactory
2013-10-24 15:28:01 -07:00
Sheel Choksi a3424ea265 Remove addCustomEqualityTester and addMatchers from global
These functions are available on the jasmine namespace
2013-10-24 14:00:05 -07:00
Sheel Choksi ab0b2b783c Move next spec/next suite ids into closure
No longer exposing these from the environment
2013-10-24 13:43:04 -07:00
Sheel Choksi d0aff9ed02 Use toThrowError instead of toThrow in places where we are expecting an error 2013-10-24 12:15:17 -07:00
Sheel Choksi a309117758 Remove TODO: should be easier to load polyfill for timeout functions as Jasmine does not get references to these functions until boot.js is loaded 2013-10-24 11:58:21 -07:00
Sheel Choksi 0c6e590a93 A spec without expectations is considered passing
- Specs are passing by default unless told otherwise
- Getting the result.status of a spec before the spec has run is now
  undefined instead of pending

[finishes #59422744]
2013-10-24 11:34:42 -07:00
Sheel Choksi d06da150de Stop passing in queryString to HTMLReporter, it is unused 2013-10-23 11:06:42 -07:00
Sheel Choksi 39d7ebf28e Remove an extra layer of wrapping for matchers/custom matchers
Helps reduce how nested custom matchers have to be for users as well as
Jasmine internal matchers

[#59161378]
2013-10-20 22:21:56 -07:00
Sheel Choksi 5f429fcb37 Re-enable CustomMatchersSpec and update for current version of custom matchers 2013-10-20 21:58:16 -07:00
Sheel Choksi b6eb9a4d5e Remove now unused updateInterval that was being set in specs 2013-10-20 17:12:40 -07:00
Sheel Choksi fdb7df812c Improve error message when a spec doesn't call the async callback within the default time interval 2013-10-19 21:18:06 -07:00
Davis W. Frank 81299860aa Merge pull request #450 from slackersoft/manualClockUninstall
Env no longer automatically uninstalls the clock after each spec
2013-10-18 15:51:10 -07:00
slackersoft ca6fa6f711 Env no longer automatically uninstalls the clock after each spec
- Behaves more like how we want plugins to behave

[#58281436]
2013-10-16 18:39:03 -07:00
Davis W. Frank 5aaafed4d8 Move clock from global to jasmine; provide a function to access the clock. 2013-10-10 16:24:58 -07:00
Davis W. Frank c28c124f58 removed addMatchers from the global. This should have been in previous commit 2013-10-10 14:11:44 -07:00
Davis W. Frank f0a1adb61c Continuing boot change with docs 2013-10-10 12:00:46 -07:00
Davis W. Frank 5ff2aecab8 Moving a documented-up boot.js from the website back into core 2013-10-10 11:59:59 -07:00
Davis W. Frank 8ca8197b4c Make exposure of addMatchers and addCustomEqualityTesters be on jasmine instead of inconsistent. 2013-10-10 11:32:21 -07:00
Davis W. Frank 55716723b5 Adding Compass as a dev dependency in order to build HTMLreporter CSS 2013-10-10 11:27:40 -07:00
Davis W. Frank 3973cc5a71 Merge pull request #443 from kryger/patch-1
Fixed broken link to contributing guide
2013-10-08 07:48:53 -07:00
Lukasz Kryger 95af58ade6 Fixed broken link to contributing guide 2013-10-08 11:33:55 +01:00
slackersoft 6641d64305 Make addCustomEqualityTester available on jasmine global
- User shouldn't have to `jasmine.getEnv()` to add one

[#54582648]
2013-10-06 11:32:38 -07:00
slackersoft 7c1fcd7bb5 Regenerate jasmine.js for QueueRunner fix 2013-10-06 11:32:19 -07:00
slackersoft e91d0341a4 Revert "Make addCustomEqualityTester available on jasmine global"
Oops, this made it on global object, not `jasmnie`

This reverts commit 144ff174f6.
2013-10-06 11:11:46 -07:00
slackersoft 144ff174f6 Make addCustomEqualityTester available on jasmine global
- User shouldn't have to `jasmine.getEnv()` to add one
2013-10-06 11:05:35 -07:00
Gregg Van Hove and Tim Jarratt af4bfa8bc4 Env should use the "public" QueueRunner interface 2013-10-04 17:04:22 -07:00
Gregg Van Hove and Tim Jarratt 620e3f5992 Run docs tests under phantomjs 2013-10-04 13:32:56 -07:00
Gregg Van Hove and Tim Jarratt ea76a30d85 Update standalone distributions
[#30296755]
2013-10-04 12:28:27 -07:00
Gregg Van Hove and Tim Jarratt adde1b4a5b Doc js files from jasmine.github.io should be part of CI build
[Finish #50572569]
2013-10-04 12:10:38 -07:00
Gregg Van Hove and Tim Jarratt 07e7ad2314 Update jasmine_favicon.png
Using the new image from google drive. It's 32x32px but browsers should
be able to downsize that to 16x16 if they need to

[Finish #57170588]
2013-10-04 10:55:01 -07:00
Davis W. Frank 706180ad01 2.0 rc3 release notes 2013-10-03 16:36:08 -07:00
Davis W. Frank 547c9cfde9 Adding Anchorman back in as a dependency 2013-10-03 16:35:56 -07:00
Gregg Van Hove and Tim Jarratt d3ec12e62a buildStandaloneDist should also build jasmine.js 2013-10-03 15:28:42 -07:00
Gregg Van Hove and Tim Jarratt 749c15fe07 Bump version to rc3 in jasmine.js 2013-10-03 15:28:26 -07:00
Gregg Van Hove and Tim Jarratt 7e071547f5 Custom matchers fail to behave as expected
If they return false, that should be respected.

Submitted via @tjgrathwell

[Finish #58184156]
close #434
2013-10-03 15:13:27 -07:00
Gregg Van Hove 6354ee17e5 Merge pull request #439 from tjarratt/pull_request_travis
Don't try to use SauceLabs on pull request builds
2013-10-03 12:32:32 -07:00
Gregg Van Hove and Tim Jarratt 255a50baee Update contribution guidelines for pull requests
[Finish #45961121]
2013-10-03 12:30:07 -07:00
Tim Jarratt 520a8c85a2 Don't bother trying to still use firefox 2013-10-03 12:07:57 -07:00
Gregg Van Hove and Tim Jarratt 6de355544f Make firefox with Sauce explicitly the default test
Apparently Travis-ci will create a default test separate from your
matrix includes and this resulted in some testrun duplication.
2013-10-03 11:44:48 -07:00
Gregg Van Hove and Tim Jarratt 95572fb314 Don't try to use SauceLabs on pull request builds 2013-10-03 11:24:57 -07:00
65 changed files with 1419 additions and 913 deletions
+9
View File
@@ -0,0 +1,9 @@
{
"bitwise": true,
"curly": true,
"freeze": true,
"immed": true,
"newcap": true,
"trailing": true,
"loopfunc": true
}
+13 -10
View File
@@ -7,6 +7,9 @@ env:
- USE_SAUCE=true - USE_SAUCE=true
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
- TEST_COMMAND="bash travis-core-script.sh" - TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="firefox"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- secure: WSPWhlnC4mWSnSPquX+m1/BCu5ch5NygkaHuM2Nea7lD8oS3XLX8QncZZAsQ4lnNfqoDDuBOizG0AESiqNvE4y6x5qvLLTS6q+ce255ZEMZ71TBdZgDEEvGMEjOPPsVXiXyTQOP1lwOPlrbZvaPgWV7e11KIBab6DfFcQpnvDgo= - secure: WSPWhlnC4mWSnSPquX+m1/BCu5ch5NygkaHuM2Nea7lD8oS3XLX8QncZZAsQ4lnNfqoDDuBOizG0AESiqNvE4y6x5qvLLTS6q+ce255ZEMZ71TBdZgDEEvGMEjOPPsVXiXyTQOP1lwOPlrbZvaPgWV7e11KIBab6DfFcQpnvDgo=
- secure: SW7CJhZnwaNT749Gdnhvqb5rbXlAOsygUAzh9qhtyvbqXKkmJdBIEsO01YF6pbju1X2twE9JvWCOxeZju43NgQChJlPsGbjY2j3k/TdQeTAJesQe2K7ytwghunI30gjEovtRH0T3w1EmcKPH8yj5eBIcB2OYoJHx8KEC7e68q1g= - secure: SW7CJhZnwaNT749Gdnhvqb5rbXlAOsygUAzh9qhtyvbqXKkmJdBIEsO01YF6pbju1X2twE9JvWCOxeZju43NgQChJlPsGbjY2j3k/TdQeTAJesQe2K7ytwghunI30gjEovtRH0T3w1EmcKPH8yj5eBIcB2OYoJHx8KEC7e68q1g=
matrix: matrix:
@@ -14,11 +17,7 @@ matrix:
- env: - env:
- USE_SAUCE=false - USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh" - TEST_COMMAND="bash travis-node-script.sh"
- env: - env:
- JASMINE_BROWSER="firefox"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- env:
- JASMINE_BROWSER="safari" - JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.8" - SAUCE_OS="OS X 10.8"
- SAUCE_BROWSER_VERSION=6 - SAUCE_BROWSER_VERSION=6
@@ -26,22 +25,26 @@ matrix:
- JASMINE_BROWSER="safari" - JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.6" - SAUCE_OS="OS X 10.6"
- SAUCE_BROWSER_VERSION=5 - SAUCE_BROWSER_VERSION=5
- env: - env:
- JASMINE_BROWSER="internet explorer" - JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 8" - SAUCE_OS="Windows 8"
- SAUCE_BROWSER_VERSION=10 - SAUCE_BROWSER_VERSION=10
- env: - env:
- JASMINE_BROWSER="internet explorer" - JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 7" - SAUCE_OS="Windows 7"
- SAUCE_BROWSER_VERSION=9 - SAUCE_BROWSER_VERSION=9
- env: - env:
- JASMINE_BROWSER="internet explorer" - JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 7" - SAUCE_OS="Windows 7"
- SAUCE_BROWSER_VERSION=8 - SAUCE_BROWSER_VERSION=8
- env: - env:
- JASMINE_BROWSER="chrome" - JASMINE_BROWSER="chrome"
- SAUCE_OS="Linux" - SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION='' - SAUCE_BROWSER_VERSION=''
- env: - env:
- JASMINE_BROWSER="phantomjs" - JASMINE_BROWSER="phantomjs"
- USE_SAUCE=false - USE_SAUCE=false
- env:
- USE_SAUCE=false
- JASMINE_BROWSER="phantomjs"
- TEST_COMMAND="bash travis-docs-script.sh"
+5
View File
@@ -107,5 +107,10 @@ Jasmine uses Node.js with a custom runner to test outside of a browser.
1. Ensure JSHint is green with `grunt jsHint` 1. Ensure JSHint is green with `grunt jsHint`
1. Build `jasmine.js` with `grunt buildDistribution` and run all specs again - this ensures that your changes self-test well 1. Build `jasmine.js` with `grunt buildDistribution` and run all specs again - this ensures that your changes self-test well
## Submitting a Pull Request
1. Revert your changes to `jasmine.js` and `jasmine-html.js`
* We do this because `jasmine.js` and `jasmine-html.js` are auto-generated (as you've seen in the previous steps) and accepting multiple pull requests when this auto-generated file changes causes lots of headaches.
1. When we accept your pull request, we will generate these files as a separate commit and merge the entire branch into master.
Note that we use Travis for Continuous Integration. We only accept green pull requests. Note that we use Travis for Continuous Integration. We only accept green pull requests.
+2
View File
@@ -10,3 +10,5 @@ end
gemspec gemspec
gem "jasmine_selenium_runner", :git => 'https://github.com/jasmine/jasmine_selenium_runner.git' gem "jasmine_selenium_runner", :git => 'https://github.com/jasmine/jasmine_selenium_runner.git'
gem "anchorman"
+5 -1
View File
@@ -1,4 +1,4 @@
<a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a> [![Build Status](https://travis-ci.org/pivotal/jasmine.png?branch=master)](https://travis-ci.org/pivotal/jasmine) <a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a> [![Build Status](https://travis-ci.org/pivotal/jasmine.png?branch=master)](https://travis-ci.org/pivotal/jasmine) [![Code Climate](https://codeclimate.com/repos/5269970a13d6374b6c01d632/badges/8bc25526da64e02065f4/gpa.png)](https://codeclimate.com/repos/5269970a13d6374b6c01d632/feed)
======= =======
**A JavaScript Testing Framework** **A JavaScript Testing Framework**
@@ -22,6 +22,10 @@ Please read the [contributors' guide](https://github.com/pivotal/jasmine/blob/ma
* [Davis W. Frank](mailto:dwfrank@pivotallabs.com), Pivotal Labs * [Davis W. Frank](mailto:dwfrank@pivotallabs.com), Pivotal Labs
* [Rajan Agaskar](mailto:rajan@pivotallabs.com), Pivotal Labs * [Rajan Agaskar](mailto:rajan@pivotallabs.com), Pivotal Labs
* [Sheel Choksi](mailto:schoksi@pivotallabs.com), Pivotal Labs
### Maintainers Emeritus
* [Christian Williams](mailto:antixian666@gmail.com), Square * [Christian Williams](mailto:antixian666@gmail.com), Square
Copyright (c) 2008-2013 Pivotal Labs. This software is licensed under the MIT License. Copyright (c) 2008-2013 Pivotal Labs. This software is licensed under the MIT License.
+1 -1
View File
@@ -9,7 +9,7 @@ load "jasmine/tasks/jasmine.rake"
namespace :jasmine do namespace :jasmine do
task :set_env do task :set_env do
ENV['JASMINE_CONFIG_PATH'] = 'spec/support/jasmine.yml' ENV['JASMINE_CONFIG_PATH'] ||= 'spec/support/jasmine.yml'
end end
end end
Binary file not shown.
Binary file not shown.
Binary file not shown.
+14 -5
View File
@@ -1,7 +1,8 @@
var standaloneLibDir = "lib/jasmine-" + jasmineVersion; var standaloneLibDir = "lib/jasmine-" + jasmineVersion;
function root(path) { return "./" + path; } function root(path) { return "./" + path; }
function lib(path) { return root("lib/jasmine-core/" + path); } function libJasmineCore(path) { return root("lib/jasmine-core/" + path); }
function libConsole() { return "lib/console/" }
function dist(path) { return root("dist/" + path); } function dist(path) { return root("dist/" + path); }
module.exports = { module.exports = {
@@ -26,13 +27,21 @@ module.exports = {
], ],
dest: standaloneLibDir, dest: standaloneLibDir,
expand: true, expand: true,
cwd: lib("") cwd: libJasmineCore("")
},
{
src: [
"console.js"
],
dest: standaloneLibDir,
expand: true,
cwd: libConsole()
}, },
{ {
src: [ "boot.js" ], src: [ "boot.js" ],
dest: standaloneLibDir, dest: standaloneLibDir,
expand: true, expand: true,
cwd: lib("boot") cwd: libJasmineCore("boot")
}, },
{ {
src: [ "SpecRunner.html" ], src: [ "SpecRunner.html" ],
@@ -44,13 +53,13 @@ module.exports = {
src: [ "*.js" ], src: [ "*.js" ],
dest: "src", dest: "src",
expand: true, expand: true,
cwd: lib("example/src/") cwd: libJasmineCore("example/src/")
}, },
{ {
src: [ "*.js" ], src: [ "*.js" ],
dest: "spec", dest: "spec",
expand: true, expand: true,
cwd: lib("example/spec/") cwd: libJasmineCore("example/spec/")
} }
] ]
} }
+2 -2
View File
@@ -44,7 +44,7 @@ module.exports = {
'src/console/requireConsole.js', 'src/console/requireConsole.js',
'src/console/ConsoleReporter.js' 'src/console/ConsoleReporter.js'
], ],
dest: 'src/console/console.js' dest: 'lib/console/console.js'
}, },
options: { options: {
banner: license(), banner: license(),
@@ -54,4 +54,4 @@ module.exports = {
} }
} }
} }
}; };
+2 -8
View File
@@ -5,13 +5,7 @@ module.exports = {
'lib/jasmine-core/jasmine.js' 'lib/jasmine-core/jasmine.js'
], ],
options: { options: {
/* While it's possible that we could be considering unwanted prototype methods, mostly jshintrc: '.jshintrc'
* we're doing this because the objects are being used as maps.
*/
forin: false,
/* We're fine with functions defined inside loops (setTimeout functions, etc) */
loopfunc: true
}, },
all: ['src/**/*.js'] all: ['src/**/*.js']
}; };
+2 -1
View File
@@ -1,7 +1,7 @@
var grunt = require("grunt"); var grunt = require("grunt");
function standaloneTmpDir(path) { return "dist/tmp/" + path; } function standaloneTmpDir(path) { return "dist/tmp/" + path; }
grunt.registerTask("build:compileSpecRunner", grunt.registerTask("build:compileSpecRunner",
"Processes the spec runner template and writes to a tmp file", "Processes the spec runner template and writes to a tmp file",
function() { function() {
@@ -23,6 +23,7 @@ grunt.registerTask("build:cleanSpecRunner",
grunt.registerTask("buildStandaloneDist", grunt.registerTask("buildStandaloneDist",
"Builds a standalone distribution", "Builds a standalone distribution",
[ [
"buildDistribution",
"build:compileSpecRunner", "build:compileSpecRunner",
"compress:standalone", "compress:standalone",
"build:cleanSpecRunner" "build:cleanSpecRunner"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 905 B

After

Width:  |  Height:  |  Size: 2.0 KiB

+1
View File
@@ -19,4 +19,5 @@ Gem::Specification.new do |s|
s.add_development_dependency "rake" s.add_development_dependency "rake"
s.add_development_dependency "sauce-connect" s.add_development_dependency "sauce-connect"
s.add_development_dependency "jasmine_selenium_runner" s.add_development_dependency "jasmine_selenium_runner"
s.add_development_dependency "compass"
end end
+84 -8
View File
@@ -20,13 +20,40 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
// Jasmine boot.js for browser runners - exposes external/global interface, builds the Jasmine environment and executes it. /**
Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
The location of `boot.js` can be specified and/or overridden in `jasmine.yml`.
[jasmine-gem]: http://github.com/pivotal/jasmine-gem
*/
(function() { (function() {
/**
* ## Require &amp; Instantiate
*
* Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
*/
window.jasmine = jasmineRequire.core(jasmineRequire); window.jasmine = jasmineRequire.core(jasmineRequire);
/**
* Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
*/
jasmineRequire.html(jasmine); jasmineRequire.html(jasmine);
/**
* Create the Jasmine environment. This is used to run all specs in a project.
*/
var env = jasmine.getEnv(); var env = jasmine.getEnv();
/**
* ## The Global Interface
*
* Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
*/
var jasmineInterface = { var jasmineInterface = {
describe: function(description, specDefinitions) { describe: function(description, specDefinitions) {
return env.describe(description, specDefinitions); return env.describe(description, specDefinitions);
@@ -60,37 +87,64 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
return env.pending(); return env.pending();
}, },
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) { spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName); return env.spyOn(obj, methodName);
}, },
clock: env.clock,
jsApiReporter: new jasmine.JsApiReporter({ jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer() timer: new jasmine.Timer()
}) })
}; };
/**
* Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
*/
if (typeof window == "undefined" && typeof exports == "object") { if (typeof window == "undefined" && typeof exports == "object") {
extend(exports, jasmineInterface); extend(exports, jasmineInterface);
} else { } else {
extend(window, jasmineInterface); extend(window, jasmineInterface);
} }
/**
* Expose the interface for adding custom equality testers.
*/
jasmine.addCustomEqualityTester = function(tester) {
env.addCustomEqualityTester(tester);
};
/**
* Expose the interface for adding custom expectation matchers
*/
jasmine.addMatchers = function(matchers) {
return env.addMatchers(matchers);
};
/**
* Expose the mock interface for the JavaScript timeout functions
*/
jasmine.clock = function() {
return env.clock;
};
/**
* ## Runner Parameters
*
* More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
*/
var queryString = new jasmine.QueryString({ var queryString = new jasmine.QueryString({
getWindowLocation: function() { return window.location; } getWindowLocation: function() { return window.location; }
}); });
// TODO: move all of catching to raise so we don't break our brains
var catchingExceptions = queryString.getParam("catch"); var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions); env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
/**
* ## Reporters
* The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
*/
var htmlReporter = new jasmine.HtmlReporter({ var htmlReporter = new jasmine.HtmlReporter({
env: env, env: env,
queryString: queryString,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); }, onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
getContainer: function() { return document.body; }, getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); }, createElement: function() { return document.createElement.apply(document, arguments); },
@@ -98,9 +152,15 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
timer: new jasmine.Timer() timer: new jasmine.Timer()
}); });
/**
* The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript.
*/
env.addReporter(jasmineInterface.jsApiReporter); env.addReporter(jasmineInterface.jsApiReporter);
env.addReporter(htmlReporter); env.addReporter(htmlReporter);
/**
* Filter which specs will be run by matching the start of the full name against the `spec` query param.
*/
var specFilter = new jasmine.HtmlSpecFilter({ var specFilter = new jasmine.HtmlSpecFilter({
filterString: function() { return queryString.getParam("spec"); } filterString: function() { return queryString.getParam("spec"); }
}); });
@@ -109,6 +169,19 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
return specFilter.matches(spec.getFullName()); return specFilter.matches(spec.getFullName());
}; };
/**
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
*/
window.setTimeout = window.setTimeout;
window.setInterval = window.setInterval;
window.clearTimeout = window.clearTimeout;
window.clearInterval = window.clearInterval;
/**
* ## Execution
*
* Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
*/
var currentWindowOnload = window.onload; var currentWindowOnload = window.onload;
window.onload = function() { window.onload = function() {
@@ -119,6 +192,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
env.execute(); env.execute();
}; };
/**
* Helper function for readability above.
*/
function extend(destination, source) { function extend(destination, source) {
for (var property in source) destination[property] = source[property]; for (var property in source) destination[property] = source[property];
return destination; return destination;
+84 -8
View File
@@ -1,10 +1,37 @@
// Jasmine boot.js for browser runners - exposes external/global interface, builds the Jasmine environment and executes it. /**
Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
The location of `boot.js` can be specified and/or overridden in `jasmine.yml`.
[jasmine-gem]: http://github.com/pivotal/jasmine-gem
*/
(function() { (function() {
/**
* ## Require &amp; Instantiate
*
* Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
*/
window.jasmine = jasmineRequire.core(jasmineRequire); window.jasmine = jasmineRequire.core(jasmineRequire);
/**
* Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
*/
jasmineRequire.html(jasmine); jasmineRequire.html(jasmine);
/**
* Create the Jasmine environment. This is used to run all specs in a project.
*/
var env = jasmine.getEnv(); var env = jasmine.getEnv();
/**
* ## The Global Interface
*
* Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
*/
var jasmineInterface = { var jasmineInterface = {
describe: function(description, specDefinitions) { describe: function(description, specDefinitions) {
return env.describe(description, specDefinitions); return env.describe(description, specDefinitions);
@@ -38,37 +65,64 @@
return env.pending(); return env.pending();
}, },
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) { spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName); return env.spyOn(obj, methodName);
}, },
clock: env.clock,
jsApiReporter: new jasmine.JsApiReporter({ jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer() timer: new jasmine.Timer()
}) })
}; };
/**
* Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
*/
if (typeof window == "undefined" && typeof exports == "object") { if (typeof window == "undefined" && typeof exports == "object") {
extend(exports, jasmineInterface); extend(exports, jasmineInterface);
} else { } else {
extend(window, jasmineInterface); extend(window, jasmineInterface);
} }
/**
* Expose the interface for adding custom equality testers.
*/
jasmine.addCustomEqualityTester = function(tester) {
env.addCustomEqualityTester(tester);
};
/**
* Expose the interface for adding custom expectation matchers
*/
jasmine.addMatchers = function(matchers) {
return env.addMatchers(matchers);
};
/**
* Expose the mock interface for the JavaScript timeout functions
*/
jasmine.clock = function() {
return env.clock;
};
/**
* ## Runner Parameters
*
* More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
*/
var queryString = new jasmine.QueryString({ var queryString = new jasmine.QueryString({
getWindowLocation: function() { return window.location; } getWindowLocation: function() { return window.location; }
}); });
// TODO: move all of catching to raise so we don't break our brains
var catchingExceptions = queryString.getParam("catch"); var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions); env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
/**
* ## Reporters
* The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
*/
var htmlReporter = new jasmine.HtmlReporter({ var htmlReporter = new jasmine.HtmlReporter({
env: env, env: env,
queryString: queryString,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); }, onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
getContainer: function() { return document.body; }, getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); }, createElement: function() { return document.createElement.apply(document, arguments); },
@@ -76,9 +130,15 @@
timer: new jasmine.Timer() timer: new jasmine.Timer()
}); });
/**
* The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript.
*/
env.addReporter(jasmineInterface.jsApiReporter); env.addReporter(jasmineInterface.jsApiReporter);
env.addReporter(htmlReporter); env.addReporter(htmlReporter);
/**
* Filter which specs will be run by matching the start of the full name against the `spec` query param.
*/
var specFilter = new jasmine.HtmlSpecFilter({ var specFilter = new jasmine.HtmlSpecFilter({
filterString: function() { return queryString.getParam("spec"); } filterString: function() { return queryString.getParam("spec"); }
}); });
@@ -87,6 +147,19 @@
return specFilter.matches(spec.getFullName()); return specFilter.matches(spec.getFullName());
}; };
/**
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
*/
window.setTimeout = window.setTimeout;
window.setInterval = window.setInterval;
window.clearTimeout = window.clearTimeout;
window.clearInterval = window.clearInterval;
/**
* ## Execution
*
* Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
*/
var currentWindowOnload = window.onload; var currentWindowOnload = window.onload;
window.onload = function() { window.onload = function() {
@@ -97,6 +170,9 @@
env.execute(); env.execute();
}; };
/**
* Helper function for readability above.
*/
function extend(destination, source) { function extend(destination, source) {
for (var property in source) destination[property] = source[property]; for (var property in source) destination[property] = source[property];
return destination; return destination;
+6 -3
View File
@@ -26,11 +26,12 @@ jasmineRequire.html = function(j$) {
j$.QueryString = jasmineRequire.QueryString(); j$.QueryString = jasmineRequire.QueryString();
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
}; };
jasmineRequire.HtmlReporter = function(j$) { jasmineRequire.HtmlReporter = function(j$) {
var noopTimer = { var noopTimer = {
start: function(){}, start: function() {},
elapsed: function(){ return 0; } elapsed: function() { return 0; }
}; };
function HtmlReporter(options) { function HtmlReporter(options) {
@@ -101,7 +102,8 @@ jasmineRequire.HtmlReporter = function(j$) {
symbols.appendChild(createDom("li", { symbols.appendChild(createDom("li", {
className: result.status, className: result.status,
id: "spec_" + result.id, id: "spec_" + result.id,
title: result.fullName} title: result.fullName
}
)); ));
if (result.status == "failed") { if (result.status == "failed") {
@@ -307,6 +309,7 @@ jasmineRequire.ResultsNode = function() {
return ResultsNode; return ResultsNode;
}; };
jasmineRequire.QueryString = function() { jasmineRequire.QueryString = function() {
function QueryString(options) { function QueryString(options) {
+255 -279
View File
@@ -142,18 +142,18 @@ getJasmineRequireObj().base = function(j$) {
j$.createSpy = function(name, originalFn) { j$.createSpy = function(name, originalFn) {
var spyStrategy = new j$.SpyStrategy({ var spyStrategy = new j$.SpyStrategy({
name: name, name: name,
fn: originalFn, fn: originalFn,
getSpy: function() { return spy; } getSpy: function() { return spy; }
}), }),
callTracker = new j$.CallTracker(), callTracker = new j$.CallTracker(),
spy = function() { spy = function() {
callTracker.track({ callTracker.track({
object: this, object: this,
args: Array.prototype.slice.apply(arguments) args: Array.prototype.slice.apply(arguments)
}); });
return spyStrategy.exec.apply(this, arguments); return spyStrategy.exec.apply(this, arguments);
}; };
for (var prop in originalFn) { for (var prop in originalFn) {
if (prop === 'and' || prop === 'calls') { if (prop === 'and' || prop === 'calls') {
@@ -174,7 +174,7 @@ getJasmineRequireObj().base = function(j$) {
return false; return false;
} }
return putativeSpy.and instanceof j$.SpyStrategy && return putativeSpy.and instanceof j$.SpyStrategy &&
putativeSpy.calls instanceof j$.CallTracker; putativeSpy.calls instanceof j$.CallTracker;
}; };
j$.createSpyObj = function(baseName, methodNames) { j$.createSpyObj = function(baseName, methodNames) {
@@ -194,14 +194,16 @@ getJasmineRequireObj().util = function() {
var util = {}; var util = {};
util.inherit = function(childClass, parentClass) { util.inherit = function(childClass, parentClass) {
var subclass = function() { var Subclass = function() {
}; };
subclass.prototype = parentClass.prototype; Subclass.prototype = parentClass.prototype;
childClass.prototype = new subclass(); childClass.prototype = new Subclass();
}; };
util.htmlEscape = function(str) { util.htmlEscape = function(str) {
if (!str) return str; if (!str) {
return str;
}
return str.replace(/&/g, '&amp;') return str.replace(/&/g, '&amp;')
.replace(/</g, '&lt;') .replace(/</g, '&lt;')
.replace(/>/g, '&gt;'); .replace(/>/g, '&gt;');
@@ -209,7 +211,9 @@ getJasmineRequireObj().util = function() {
util.argsToArray = function(args) { util.argsToArray = function(args) {
var arrayOfArgs = []; var arrayOfArgs = [];
for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); for (var i = 0; i < args.length; i++) {
arrayOfArgs.push(args[i]);
}
return arrayOfArgs; return arrayOfArgs;
}; };
@@ -222,7 +226,6 @@ getJasmineRequireObj().util = function() {
getJasmineRequireObj().Spec = function(j$) { getJasmineRequireObj().Spec = function(j$) {
function Spec(attrs) { function Spec(attrs) {
this.encounteredExpectations = false;
this.expectationFactory = attrs.expectationFactory; this.expectationFactory = attrs.expectationFactory;
this.resultCallback = attrs.resultCallback || function() {}; this.resultCallback = attrs.resultCallback || function() {};
this.id = attrs.id; this.id = attrs.id;
@@ -248,13 +251,11 @@ getJasmineRequireObj().Spec = function(j$) {
id: this.id, id: this.id,
description: this.description, description: this.description,
fullName: this.getFullName(), fullName: this.getFullName(),
status: this.status(),
failedExpectations: [] failedExpectations: []
}; };
} }
Spec.prototype.addExpectationResult = function(passed, data) { Spec.prototype.addExpectationResult = function(passed, data) {
this.encounteredExpectations = true;
if (passed) { if (passed) {
return; return;
} }
@@ -278,7 +279,7 @@ getJasmineRequireObj().Spec = function(j$) {
function timeoutable(fn) { function timeoutable(fn) {
return function(done) { return function(done) {
var timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() { var timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
onException(new Error('timeout')); onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
done(); done();
}, j$.DEFAULT_TIMEOUT_INTERVAL]]); }, j$.DEFAULT_TIMEOUT_INTERVAL]]);
@@ -292,8 +293,8 @@ getJasmineRequireObj().Spec = function(j$) {
} }
var befores = this.beforeFns() || [], var befores = this.beforeFns() || [],
afters = this.afterFns() || [], afters = this.afterFns() || [],
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn; thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
var allFns = befores.concat(thisOne).concat(afters); var allFns = befores.concat(thisOne).concat(afters);
this.queueRunner({ this.queueRunner({
@@ -303,18 +304,18 @@ getJasmineRequireObj().Spec = function(j$) {
}); });
function onException(e) { function onException(e) {
if (Spec.isPendingSpecException(e)) { if (Spec.isPendingSpecException(e)) {
self.pend(); self.pend();
return; return;
} }
self.addExpectationResult(false, { self.addExpectationResult(false, {
matcherName: "", matcherName: "",
passed: false, passed: false,
expected: "", expected: "",
actual: "", actual: "",
error: e error: e
}); });
} }
function complete() { function complete() {
@@ -340,7 +341,7 @@ getJasmineRequireObj().Spec = function(j$) {
return 'disabled'; return 'disabled';
} }
if (this.markedPending || !this.encounteredExpectations) { if (this.markedPending) {
return 'pending'; return 'pending';
} }
@@ -375,6 +376,8 @@ getJasmineRequireObj().Env = function(j$) {
var self = this; var self = this;
var global = options.global || j$.getGlobal(); var global = options.global || j$.getGlobal();
var totalSpecsDefined = 0;
var catchExceptions = true; var catchExceptions = true;
var realSetTimeout = j$.getGlobal().setTimeout; var realSetTimeout = j$.getGlobal().setTimeout;
@@ -385,9 +388,10 @@ getJasmineRequireObj().Env = function(j$) {
var spies = []; var spies = [];
this.currentSpec = null; var currentSpec = null;
var currentSuite = null;
this.reporter = new j$.ReportDispatcher([ var reporter = new j$.ReportDispatcher([
"jasmineStarted", "jasmineStarted",
"jasmineDone", "jasmineDone",
"suiteStarted", "suiteStarted",
@@ -396,14 +400,11 @@ getJasmineRequireObj().Env = function(j$) {
"specDone" "specDone"
]); ]);
this.lastUpdate = 0;
this.specFilter = function() { this.specFilter = function() {
return true; return true;
}; };
this.nextSpecId_ = 0; var equalityTesters = [];
this.nextSuiteId_ = 0;
this.equalityTesters_ = [];
var customEqualityTesters = []; var customEqualityTesters = [];
this.addCustomEqualityTester = function(tester) { this.addCustomEqualityTester = function(tester) {
@@ -412,6 +413,16 @@ getJasmineRequireObj().Env = function(j$) {
j$.Expectation.addCoreMatchers(j$.matchers); j$.Expectation.addCoreMatchers(j$.matchers);
var nextSpecId = 0;
var getNextSpecId = function() {
return 'spec' + nextSpecId++;
};
var nextSuiteId = 0;
var getNextSuiteId = function() {
return 'suite' + nextSuiteId++;
};
var expectationFactory = function(actual, spec) { var expectationFactory = function(actual, spec) {
return j$.Expectation.Factory({ return j$.Expectation.Factory({
util: j$.matchersUtil, util: j$.matchersUtil,
@@ -426,32 +437,34 @@ getJasmineRequireObj().Env = function(j$) {
}; };
var specStarted = function(spec) { var specStarted = function(spec) {
self.currentSpec = spec; currentSpec = spec;
self.reporter.specStarted(spec.result); reporter.specStarted(spec.result);
}; };
var beforeFns = function(currentSuite) { var beforeFns = function(suite) {
return function() { return function() {
var befores = []; var befores = [];
for (var suite = currentSuite; suite; suite = suite.parentSuite) { while(suite) {
befores = befores.concat(suite.beforeFns); befores = befores.concat(suite.beforeFns);
suite = suite.parentSuite;
} }
return befores.reverse(); return befores.reverse();
}; };
}; };
var afterFns = function(currentSuite) { var afterFns = function(suite) {
return function() { return function() {
var afters = []; var afters = [];
for (var suite = currentSuite; suite; suite = suite.parentSuite) { while(suite) {
afters = afters.concat(suite.afterFns); afters = afters.concat(suite.afterFns);
suite = suite.parentSuite;
} }
return afters; return afters;
}; };
}; };
var getSpecName = function(spec, currentSuite) { var getSpecName = function(spec, suite) {
return currentSuite.getFullName() + ' ' + spec.description; return suite.getFullName() + ' ' + spec.description;
}; };
// TODO: we may just be able to pass in the fn instead of wrapping here // TODO: we may just be able to pass in the fn instead of wrapping here
@@ -474,10 +487,6 @@ getJasmineRequireObj().Env = function(j$) {
return catchExceptions; return catchExceptions;
}; };
this.catchException = function(e) {
return j$.Spec.isPendingSpecException(e) || catchExceptions;
};
var maximumSpecCallbackDepth = 20; var maximumSpecCallbackDepth = 20;
var currentSpecCallbackDepth = 0; var currentSpecCallbackDepth = 0;
@@ -491,19 +500,136 @@ getJasmineRequireObj().Env = function(j$) {
} }
} }
var queueRunnerFactory = function(options) { var catchException = function(e) {
options.catchException = self.catchException; return j$.Spec.isPendingSpecException(e) || catchExceptions;
options.clearStack = options.clearStack || clearStack;
new j$.QueueRunner(options).run(options.fns, 0);
}; };
var totalSpecsDefined = 0; var queueRunnerFactory = function(options) {
this.specFactory = function(description, fn, suite) { options.catchException = catchException;
options.clearStack = options.clearStack || clearStack;
new j$.QueueRunner(options).execute();
};
var topSuite = new j$.Suite({
env: this,
id: getNextSuiteId(),
description: 'Jasmine__TopLevel__Suite',
queueRunner: queueRunnerFactory,
resultCallback: function() {} // TODO - hook this up
});
runnableLookupTable[topSuite.id] = topSuite;
currentSuite = topSuite;
this.topSuite = function() {
return topSuite;
};
this.execute = function(runnablesToRun) {
runnablesToRun = runnablesToRun || [topSuite.id];
var allFns = [];
for(var i = 0; i < runnablesToRun.length; i++) {
var runnable = runnableLookupTable[runnablesToRun[i]];
allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable));
}
reporter.jasmineStarted({
totalSpecsDefined: totalSpecsDefined
});
queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone});
};
this.addReporter = function(reporterToAdd) {
reporter.addReporter(reporterToAdd);
};
this.addMatchers = function(matchersToAdd) {
j$.Expectation.addMatchers(matchersToAdd);
};
this.spyOn = function(obj, methodName) {
if (j$.util.isUndefined(obj)) {
throw new Error("spyOn could not find an object to spy upon for " + methodName + "()");
}
if (j$.util.isUndefined(obj[methodName])) {
throw new Error(methodName + '() method does not exist');
}
if (obj[methodName] && j$.isSpy(obj[methodName])) {
//TODO?: should this return the current spy? Downside: may cause user confusion about spy state
throw new Error(methodName + ' has already been spied upon');
}
var spy = j$.createSpy(methodName, obj[methodName]);
spies.push({
spy: spy,
baseObj: obj,
methodName: methodName,
originalValue: obj[methodName]
});
obj[methodName] = spy;
return spy;
};
var suiteFactory = function(description) {
var suite = new j$.Suite({
env: self,
id: getNextSuiteId(),
description: description,
parentSuite: currentSuite,
queueRunner: queueRunnerFactory,
onStart: suiteStarted,
resultCallback: function(attrs) {
reporter.suiteDone(attrs);
}
});
runnableLookupTable[suite.id] = suite;
return suite;
};
this.describe = function(description, specDefinitions) {
var suite = suiteFactory(description);
var parentSuite = currentSuite;
parentSuite.addChild(suite);
currentSuite = suite;
var declarationError = null;
try {
specDefinitions.call(suite);
} catch (e) {
declarationError = e;
}
if (declarationError) {
this.it("encountered a declaration exception", function() {
throw declarationError;
});
}
currentSuite = parentSuite;
return suite;
};
this.xdescribe = function(description, specDefinitions) {
var suite = this.describe(description, specDefinitions);
suite.disable();
return suite;
};
var specFactory = function(description, fn, suite) {
totalSpecsDefined++; totalSpecsDefined++;
var spec = new j$.Spec({ var spec = new j$.Spec({
id: self.nextSpecId(), id: getNextSpecId(),
beforeFns: beforeFns(suite), beforeFns: beforeFns(suite),
afterFns: afterFns(suite), afterFns: afterFns(suite),
expectationFactory: expectationFactory, expectationFactory: expectationFactory,
@@ -539,193 +665,45 @@ getJasmineRequireObj().Env = function(j$) {
function specResultCallback(result) { function specResultCallback(result) {
removeAllSpies(); removeAllSpies();
j$.Expectation.resetMatchers(); j$.Expectation.resetMatchers();
customEqualityTesters.length = 0; customEqualityTesters = [];
self.clock.uninstall(); currentSpec = null;
self.currentSpec = null; reporter.specDone(result);
self.reporter.specDone(result);
} }
}; };
var suiteStarted = function(suite) { var suiteStarted = function(suite) {
self.reporter.suiteStarted(suite.result); reporter.suiteStarted(suite.result);
}; };
var suiteConstructor = j$.Suite; this.it = function(description, fn) {
var spec = specFactory(description, fn, currentSuite);
this.topSuite = new j$.Suite({ currentSuite.addChild(spec);
env: this, return spec;
id: this.nextSuiteId(),
description: 'Jasmine__TopLevel__Suite',
queueRunner: queueRunnerFactory,
completeCallback: function() {}, // TODO - hook this up
resultCallback: function() {} // TODO - hook this up
});
runnableLookupTable[this.topSuite.id] = this.topSuite;
this.currentSuite = this.topSuite;
this.suiteFactory = function(description) {
var suite = new suiteConstructor({
env: self,
id: self.nextSuiteId(),
description: description,
parentSuite: self.currentSuite,
queueRunner: queueRunnerFactory,
onStart: suiteStarted,
resultCallback: function(attrs) {
self.reporter.suiteDone(attrs);
}
});
runnableLookupTable[suite.id] = suite;
return suite;
}; };
this.execute = function(runnablesToRun) { this.xit = function(description, fn) {
runnablesToRun = runnablesToRun || [this.topSuite.id]; var spec = this.it(description, fn);
spec.pend();
var allFns = []; return spec;
for(var i = 0; i < runnablesToRun.length; i++) {
var runnable = runnableLookupTable[runnablesToRun[i]];
allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable));
}
this.reporter.jasmineStarted({
totalSpecsDefined: totalSpecsDefined
});
queueRunnerFactory({fns: allFns, onComplete: this.reporter.jasmineDone});
}; };
this.spyOn = function(obj, methodName) { this.expect = function(actual) {
if (j$.util.isUndefined(obj)) { return currentSpec.expect(actual);
throw new Error("spyOn could not find an object to spy upon for " + methodName + "()"); };
}
if (j$.util.isUndefined(obj[methodName])) { this.beforeEach = function(beforeEachFunction) {
throw new Error(methodName + '() method does not exist'); currentSuite.beforeEach(beforeEachFunction);
} };
if (obj[methodName] && j$.isSpy(obj[methodName])) { this.afterEach = function(afterEachFunction) {
//TODO?: should this return the current spy? Downside: may cause user confusion about spy state currentSuite.afterEach(afterEachFunction);
throw new Error(methodName + ' has already been spied upon'); };
}
var spy = j$.createSpy(methodName, obj[methodName]); this.pending = function() {
throw j$.Spec.pendingSpecExceptionMessage;
spies.push({
spy: spy,
baseObj: obj,
methodName: methodName,
originalValue: obj[methodName]
});
obj[methodName] = spy;
return spy;
}; };
} }
Env.prototype.addMatchers = function(matchersToAdd) {
j$.Expectation.addMatchers(matchersToAdd);
};
Env.prototype.version = function() {
return j$.version;
};
Env.prototype.expect = function(actual) {
return this.currentSpec.expect(actual);
};
// TODO: move this to closure
Env.prototype.versionString = function() {
console.log("DEPRECATED == use j$.version");
return j$.version;
};
// TODO: move this to closure
Env.prototype.nextSpecId = function() {
return 'spec' + this.nextSpecId_++;
};
// TODO: move this to closure
Env.prototype.nextSuiteId = function() {
return 'suite' + this.nextSuiteId_++;
};
// TODO: move this to closure
Env.prototype.addReporter = function(reporter) {
this.reporter.addReporter(reporter);
};
// TODO: move this to closure
Env.prototype.describe = function(description, specDefinitions) {
var suite = this.suiteFactory(description);
var parentSuite = this.currentSuite;
parentSuite.addSuite(suite);
this.currentSuite = suite;
var declarationError = null;
try {
specDefinitions.call(suite);
} catch (e) {
declarationError = e;
}
if (declarationError) {
this.it("encountered a declaration exception", function() {
throw declarationError;
});
}
this.currentSuite = parentSuite;
return suite;
};
// TODO: move this to closure
Env.prototype.xdescribe = function(description, specDefinitions) {
var suite = this.describe(description, specDefinitions);
suite.disable();
return suite;
};
// TODO: move this to closure
Env.prototype.it = function(description, fn) {
var spec = this.specFactory(description, fn, this.currentSuite);
this.currentSuite.addSpec(spec);
return spec;
};
// TODO: move this to closure
Env.prototype.xit = function(description, fn) {
var spec = this.it(description, fn);
spec.pend();
return spec;
};
// TODO: move this to closure
Env.prototype.beforeEach = function(beforeEachFunction) {
this.currentSuite.beforeEach(beforeEachFunction);
};
// TODO: move this to closure
Env.prototype.afterEach = function(afterEachFunction) {
this.currentSuite.afterEach(afterEachFunction);
};
// TODO: move this to closure
Env.prototype.pending = function() {
throw j$.Spec.pendingSpecExceptionMessage;
};
// TODO: Still needed?
Env.prototype.currentRunner = function() {
return this.topSuite;
};
return Env; return Env;
}; };
@@ -839,6 +817,7 @@ getJasmineRequireObj().Any = function() {
return Any; return Any;
}; };
getJasmineRequireObj().CallTracker = function() { getJasmineRequireObj().CallTracker = function() {
function CallTracker() { function CallTracker() {
@@ -905,7 +884,8 @@ getJasmineRequireObj().Clock = function() {
setInterval: setInterval, setInterval: setInterval,
clearInterval: clearInterval clearInterval: clearInterval
}, },
installed = false; installed = false,
timer;
self.install = function() { self.install = function() {
replace(global, fakeTimingFunctions); replace(global, fakeTimingFunctions);
@@ -952,7 +932,7 @@ getJasmineRequireObj().Clock = function() {
if (installed) { if (installed) {
delayedFunctionScheduler.tick(millis); delayedFunctionScheduler.tick(millis);
} else { } else {
throw new Error("Mock clock is not installed, use jasmine.getEnv().clock.install()"); throw new Error("Mock clock is not installed, use jasmine.clock().install()");
} }
}; };
@@ -960,8 +940,6 @@ getJasmineRequireObj().Clock = function() {
function legacyIE() { function legacyIE() {
//if these methods are polyfilled, apply will be present //if these methods are polyfilled, apply will be present
//TODO: it may be difficult to load the polyfill before jasmine loads
//(env should be new-ed inside of onload)
return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply; return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply;
} }
@@ -1163,12 +1141,21 @@ getJasmineRequireObj().Expectation = function() {
args.unshift(this.actual); args.unshift(this.actual);
var result = matcherFactory(this.util, this.customEqualityTesters).compare.apply(null, args); var matcher = matcherFactory(this.util, this.customEqualityTesters),
matcherCompare = matcher.compare;
function defaultNegativeCompare() {
var result = matcher.compare.apply(null, args);
result.pass = !result.pass;
return result;
}
if (this.isNot) { if (this.isNot) {
result.pass = !result.pass; matcherCompare = matcher.negativeCompare || defaultNegativeCompare;
} }
var result = matcherCompare.apply(null, args);
if (!result.pass) { if (!result.pass) {
if (!result.message) { if (!result.message) {
args.unshift(this.isNot); args.unshift(this.isNot);
@@ -1364,8 +1351,8 @@ getJasmineRequireObj().pp = function(j$) {
PrettyPrinter.prototype.iterateObject = function(obj, fn) { PrettyPrinter.prototype.iterateObject = function(obj, fn) {
for (var property in obj) { for (var property in obj) {
if (!obj.hasOwnProperty(property)) continue; if (!obj.hasOwnProperty(property)) { continue; }
if (property == '__Jasmine_been_here_before__') continue; if (property == '__Jasmine_been_here_before__') { continue; }
fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) &&
obj.__lookupGetter__(property) !== null) : false); obj.__lookupGetter__(property) !== null) : false);
} }
@@ -1522,11 +1509,11 @@ getJasmineRequireObj().ReportDispatcher = function() {
for (var i = 0; i < dispatchedMethods.length; i++) { for (var i = 0; i < dispatchedMethods.length; i++) {
var method = dispatchedMethods[i]; var method = dispatchedMethods[i];
this[method] = function(m) { this[method] = (function(m) {
return function() { return function() {
dispatch(m, arguments); dispatch(m, arguments);
}; };
}(method); }(method));
} }
var reporters = []; var reporters = [];
@@ -1610,7 +1597,6 @@ getJasmineRequireObj().Suite = function() {
this.parentSuite = attrs.parentSuite; this.parentSuite = attrs.parentSuite;
this.description = attrs.description; this.description = attrs.description;
this.onStart = attrs.onStart || function() {}; this.onStart = attrs.onStart || function() {};
this.completeCallback = attrs.completeCallback || function() {}; // TODO: this is unused
this.resultCallback = attrs.resultCallback || function() {}; this.resultCallback = attrs.resultCallback || function() {};
this.clearStack = attrs.clearStack || function(fn) {fn();}; this.clearStack = attrs.clearStack || function(fn) {fn();};
@@ -1619,9 +1605,7 @@ getJasmineRequireObj().Suite = function() {
this.queueRunner = attrs.queueRunner || function() {}; this.queueRunner = attrs.queueRunner || function() {};
this.disabled = false; this.disabled = false;
this.children_ = []; // TODO: rename this.children = [];
this.suites = []; // TODO: needed?
this.specs = []; // TODO: needed?
this.result = { this.result = {
id: this.id, id: this.id,
@@ -1653,19 +1637,8 @@ getJasmineRequireObj().Suite = function() {
this.afterFns.unshift(fn); this.afterFns.unshift(fn);
}; };
Suite.prototype.addSpec = function(spec) { Suite.prototype.addChild = function(child) {
this.children_.push(spec); this.children.push(child);
this.specs.push(spec); // TODO: needed?
};
Suite.prototype.addSuite = function(suite) {
suite.parentSuite = this;
this.children_.push(suite);
this.suites.push(suite); // TODO: needed?
};
Suite.prototype.children = function() {
return this.children_;
}; };
Suite.prototype.execute = function(onComplete) { Suite.prototype.execute = function(onComplete) {
@@ -1675,11 +1648,10 @@ getJasmineRequireObj().Suite = function() {
return; return;
} }
var allFns = [], var allFns = [];
children = this.children_;
for (var i = 0; i < children.length; i++) { for (var i = 0; i < this.children.length; i++) {
allFns.push(wrapChildAsAsync(children[i])); allFns.push(wrapChildAsAsync(this.children[i]));
} }
this.onStart(this); this.onStart(this);
@@ -1701,7 +1673,7 @@ getJasmineRequireObj().Suite = function() {
return function(done) { child.execute(done); }; return function(done) { child.execute(done); };
} }
}; };
return Suite; return Suite;
}; };
@@ -1727,6 +1699,7 @@ getJasmineRequireObj().Timer = function() {
return Timer; return Timer;
}; };
getJasmineRequireObj().matchersUtil = function(j$) { getJasmineRequireObj().matchersUtil = function(j$) {
// TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter? // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter?
@@ -1766,7 +1739,9 @@ getJasmineRequireObj().matchersUtil = function(j$) {
if (expected.length > 0) { if (expected.length > 0) {
for (var i = 0; i < expected.length; i++) { for (var i = 0; i < expected.length; i++) {
if (i > 0) message += ","; if (i > 0) {
message += ",";
}
message += " " + j$.pp(expected[i]); message += " " + j$.pp(expected[i]);
} }
} }
@@ -1781,9 +1756,9 @@ getJasmineRequireObj().matchersUtil = function(j$) {
var result = true; var result = true;
for (var i = 0; i < customTesters.length; i++) { for (var i = 0; i < customTesters.length; i++) {
result = customTesters[i](a, b); var customTesterResult = customTesters[i](a, b);
if (result) { if (!j$.util.isUndefined(customTesterResult)) {
return true; return customTesterResult;
} }
} }
@@ -1814,11 +1789,11 @@ getJasmineRequireObj().matchersUtil = function(j$) {
// Identical objects are equal. `0 === -0`, but they aren't identical. // Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) return a !== 0 || 1 / a == 1 / b; if (a === b) { return a !== 0 || 1 / a == 1 / b; }
// A strict comparison is necessary because `null == undefined`. // A strict comparison is necessary because `null == undefined`.
if (a === null || b === null) return a === b; if (a === null || b === null) { return a === b; }
var className = Object.prototype.toString.call(a); var className = Object.prototype.toString.call(a);
if (className != Object.prototype.toString.call(b)) return false; if (className != Object.prototype.toString.call(b)) { return false; }
switch (className) { switch (className) {
// Strings, numbers, dates, and booleans are compared by value. // Strings, numbers, dates, and booleans are compared by value.
case '[object String]': case '[object String]':
@@ -1842,14 +1817,14 @@ getJasmineRequireObj().matchersUtil = function(j$) {
a.multiline == b.multiline && a.multiline == b.multiline &&
a.ignoreCase == b.ignoreCase; a.ignoreCase == b.ignoreCase;
} }
if (typeof a != 'object' || typeof b != 'object') return false; if (typeof a != 'object' || typeof b != 'object') { return false; }
// Assume equality for cyclic structures. The algorithm for detecting cyclic // Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
var length = aStack.length; var length = aStack.length;
while (length--) { while (length--) {
// Linear search. Performance is inversely proportional to the number of // Linear search. Performance is inversely proportional to the number of
// unique nested structures. // unique nested structures.
if (aStack[length] == a) return bStack[length] == b; if (aStack[length] == a) { return bStack[length] == b; }
} }
// Add the first object to the stack of traversed objects. // Add the first object to the stack of traversed objects.
aStack.push(a); aStack.push(a);
@@ -1863,7 +1838,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
if (result) { if (result) {
// Deep compare the contents, ignoring non-numeric properties. // Deep compare the contents, ignoring non-numeric properties.
while (size--) { while (size--) {
if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) break; if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) { break; }
} }
} }
} else { } else {
@@ -1880,13 +1855,13 @@ getJasmineRequireObj().matchersUtil = function(j$) {
// Count the expected number of properties. // Count the expected number of properties.
size++; size++;
// Deep compare each member. // Deep compare each member.
if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) break; if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) { break; }
} }
} }
// Ensure that both objects contain the same number of properties. // Ensure that both objects contain the same number of properties.
if (result) { if (result) {
for (key in b) { for (key in b) {
if (has(b, key) && !(size--)) break; if (has(b, key) && !(size--)) { break; }
} }
result = !size; result = !size;
} }
@@ -1906,6 +1881,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
} }
} }
}; };
getJasmineRequireObj().toBe = function() { getJasmineRequireObj().toBe = function() {
function toBe() { function toBe() {
return { return {
@@ -2387,5 +2363,5 @@ getJasmineRequireObj().toThrowError = function(j$) {
}; };
getJasmineRequireObj().version = function() { getJasmineRequireObj().version = function() {
return "2.0.0-rc2"; return "2.0.0-rc5";
}; };
+1 -1
View File
@@ -4,6 +4,6 @@
# #
module Jasmine module Jasmine
module Core module Core
VERSION = "2.0.0.rc3" VERSION = "2.0.0.rc5"
end end
end end
+6 -6
View File
@@ -1,13 +1,13 @@
{ {
"name": "jasmine-core", "name": "jasmine-core",
"license": "MIT", "license": "MIT",
"version": "2.0.0-rc3", "version": "2.0.0-rc5",
"devDependencies": { "devDependencies": {
"grunt": "~0.4.1", "grunt": "~0.4.1",
"grunt-contrib-jshint": "~0.2.0", "grunt-contrib-jshint": "~0.7.0",
"grunt-contrib-concat": "~0.1.3", "grunt-contrib-concat": "~0.3.0",
"grunt-contrib-compass": "~0.1.3", "grunt-contrib-compass": "~0.6.0",
"grunt-contrib-compress": "~0.4.1", "grunt-contrib-compress": "~0.5.2",
"shelljs": "~0.1.2" "shelljs": "~0.1.4"
} }
} }
+1 -1
View File
@@ -135,4 +135,4 @@ _Release Notes generated with [Anchorman](http://github.com/infews/anchorman)_
[travis_jasmine]: http://travis-ci.org/jasmine [travis_jasmine]: http://travis-ci.org/jasmine
[sauce]: http://saucelabs.com [sauce]: http://saucelabs.com
[node_suite]: https://github.com/pivotal/jasmine/blob/master/spec/node_suite.js [node_suite]: https://github.com/pivotal/jasmine/blob/master/spec/node_suite.js
[intro]: http://pivotal.github.com/jasmine/ [intro]: http://pivotal.github.com/jasmine/
+151
View File
@@ -0,0 +1,151 @@
# Jasmine Core 2.0 Release Notes
## Summary
These notes are for RC3 of Jasmine Core 2.0.
## Breaking Changes
The [`introduction.js`][intro] page covers the current syntax, highlighting the changes. Here are known breaking interface changes that are not backwards compatible with 1.x.
* New syntax for asynchronous specs
* New syntax for spies
* New interface for reporters
* Better Equality testing
* Easier custom matchers
* Change to `toThrow` matcher
### New syntax for asynchronous specs
Similar to [Mocha][mocha], Jasmine befores, specs, and afters can take an optional "done" callback in order to force asynchronous tests. The next function, whether it's a before, spec or after, will wait until this function is called or if a timeout is reached.
### New syntax for spies
Spies have a slightly modified syntax. The ideas came from a desire to preserve any of the properties on a spied-upon function and some better testing patterns.
### New interface for reporters
The reporter interface has changed. The callbacks are different and more consistent. The objects passed in should only provide what is needed to report results. This enforces an interface to result data so custom reporters will be less coupled to Jasmine implementation. The full suite execution time is also reported.
### Better Equality testing
We have tossed the previous equality code and are now using new code for testing equality. We started with [Underscore.js][underscore]'s `isEqual`, refactored a bit and added some additional tests.
### Easier custom matchers
Custom matchers have always been possible, but this was barely documented and clunky to test. We've changed how matchers are added and tested. Jasmine adds its own matchers by the same mechanism that as custom matchers use. Dogfooding FTW.
### Change to `toThrow` matcher
We've changed the behavior of the `toThrow` matcher, moving some functionality to the `toThrowError` matcher. This should allow more of the requested use cases.
## Other Changes
* Massive refactoring and better testing
* Environment setup now in `boot.js`
* Development & Build moved to Grunt
* Change in how Jasmine is loaded
* Change in how Jasmine is tested
* Better node.js support
* Better Continuous Integration Environment at Travis
* Support matrix updated
* Removed JsDoc Pages
## Massive refactoring and better testing
This is the biggest set of changes. We've touched nearly every file and every object. We've slammed objects back together and pulled out new extractions. We've made the code more consistently styled. We've improved the tests nearly everywhere.
In general, Jasmine is made of smaller, more-loosely-coupled objects, unit-tested with explicit dependencies injected. This made tests easier to write, read, and maintain. We know this has made Jasmine development easier for the core team. We expect (and hope) this makes it easier for the community to extend Jasmine and provide pull requests that make more sense the first time out.
## Environment setup now in `boot.js`
Instantiation and setup of the Jasmine environment, including building reporters, exposing the "global" functions, and executing tests has moved into its own file: `boot.js`. This should make it easier to add custom reporters, configure some objects, or just in general change how you use Jasmine from the outside.
For example, during development, Jasmine uses it's own `devboot.js` to load itself twice - once from `jasmine.js` and once from the source directories.
## Development & Build moved to Grunt
We've moved away from Ruby and embraced Node.js and [Grunt.js][grunt] for the various command line tasks during development. Yes, it's a just a different set of dependencies. But it's less code for the team to maintain - it turns out that JavaScript tools are pretty good at building JavaScript projects. This will make it easier for the community to make sure contributions work in browser and in Node.js before submitting Pull Requests. There is more detail in the [Contributor's Guide][contrib].
## Change in how Jasmine is loaded
We did not want to add new run-time dependencies, yet we needed to be cleaner when loading Jasmine. So we wrote a custom "require" scheme that works in Node.js and in browsers. This only affects pull requests that add files - please be careful in these cases. Again, the [Contributor's Guide][contrib] should help.
## Change in how Jasmine is tested with Jasmine
Writing a custom require system helped enforce self-testing - the built `jasmine.js` testing Jasmine from the source directories. Overall this has improved the stability of the code. When you look at Jasmine's tests, you'll see both `jasmine` and `j$` used. The former, `jasmine`, will always be used to test the code from source, which is loaded into the reference `j$`. Please adhere to this pattern when writing tests for contributions.
## Better node.js support
Node.js is now officially a first-class citizen. For a long time we've made sure tests were green in Node before releasing. But it is now officially part of Jasmine's CI build at [Travis][travis]. For the curious, the [`node_suite.js`][node_suite], is essentially a `boot.js` for Node. An official npm is coming.
## Better Continuous Integration Environment at Travis
The [CI build at Travis][travis_jasmine] now runs the core specs in a build matrix across browsers. It's far from complete on the operating system matrix, but you will see that Jasmine runs against: Firefox, Chrome, Safari 5, Safari 6, Phantom.js, Node.js, and IE versions 8, 9, and 10. Big thanks to [SauceLabs][sauce] for their support of open source projects. We will happily take pull requests for additional OS/Browser combos within the matrix.
## Support Matrix Updated
We're dropping support for IE < 8. Jasmine 1.x remains for projects supporting earlier versions of browsers.
## Removed JsDoc Pages
Comments in code are lies waiting to happen. Jasmine's JsDoc comments were no exception. The comments were out of date, the generated pages were even more out of date, and frankly they were not helpful. So they're gone.
Last year saw the posting of the [`introduction.js`][intro] page to document the real, practical interface for projects to use. This page has received a lot of positive feedback so expect more pages like this one.
## Pull Requests & Issues
The following Pull Requests were merged:
* ObjectContaining wrong filed value error message #[394](https://github.com/pivotal/jasmine/issues/394) from albertandrejev
* Removed unnecessary parameter from `suiteFactory()` call #[397](https://github.com/pivotal/jasmine/issues/397) from valera-rozuvan
* `jasmine.Any` supports `Boolean` #[392](https://github.com/pivotal/jasmine/issues/392) from albertandrejev
* Reporters get execution time #[30](https://github.com/pivotal/jasmine/issues/30)
* `toThrow` matchers handle falsy exceptions #[317](https://github.com/pivotal/jasmine/issues/371)
* Removed deprecated `jasmine.Matchers.pp` #[363](https://github.com/pivotal/jasmine/issues/363) from robinboehm
* Fix for Clock ticking to default to 0 #[340](https://github.com/pivotal/jasmine/issues/340) from Caio Cunha
* Whitespace failures should be easier to understand #[332](https://github.com/pivotal/jasmine/issues/332) from bjornblomqvist
* Fix for more markdown-y image for Build status #[329](https://github.com/pivotal/jasmine/issues/329) from sunliwen
* UTF-8 encoding fixes #[333](https://github.com/pivotal/jasmine/issues/333) from bjornblomqvist
### Fixed in RC3
* Improved the performance of the HTML output with a CSS change #[428](https://github.com/pivotal/jasmine/issues/428) - Thanks @tjgrathwell
* Removed an accidental global pollution of `j$` as a reference to Jasmine. Thanks to Morten Maxild from the mailing list
There were several other pull requests that either had already been fixed, or were good starting points for the various changes above. Thank you for all of the hard work to keep Jasmine awesome.
## Other Bugs & Features
There were a few small changes and fixes that didn't fit into any of the above categories:
* HTML Reporter refactored for simplicity and performance
* Default character encoding on the HTML runner page is UTF-8
* [Escape special regex characters from the spec param](http://www.pivotaltracker.com/story/52731407)
* Favicon returns
* [Clock supports `eval`'d strings as functions](http://www.pivotaltracker.com/story/40853563)
* There should always be stack traces on failures
* Removed references to unused `jasmine.VERBOSE`
* Removed references to unused `jasmine.XmlHttpRequest`
### Fixed in RC3
* There is now a consistent `this` between `beforeEach`, `it` and `afterEach` for a spec
* A spy's strategy now has properties `returnValue` and `throwError` because they are better names
* Make it easy to copy the title of failing specs from the HTML output
* Don't add periods to the full name of a spec fix #[427](https://github.com/pivotal/jasmine/issues/427)
* Allow Env to take optional spec/suite ids when asked to `execute`
* [Mock clock now less intrusive, replacing global timer functions only when clock is installed](http://www.pivotaltracker.com/story/54168708)
* Restore custom failure messages for `toHaveBeenCalledWith`
[mocha]: http://visionmedia.github.io/mocha/
[underscore]: http://underscorejs.org/
[grunt]: http://gruntjs.com
[contrib]: https://github.com/pivotal/jasmine/blob/master/CONTRIBUTING.md
[travis]: http://travis-ci.org
[travis_jasmine]: http://travis-ci.org/jasmine
[sauce]: http://saucelabs.com
[node_suite]: https://github.com/pivotal/jasmine/blob/master/spec/node_suite.js
[intro]: http://jasmine.github.io/2.0/introduction.html
------
_Release Notes generated with [Anchorman](http://github.com/infews/anchorman)_
+175
View File
@@ -0,0 +1,175 @@
# Jasmine Core 2.0 Release Notes
## Summary
These notes are for RC5 of Jasmine Core 2.0.
## Breaking Changes
The [`introduction.js`][intro] page covers the current syntax, highlighting the changes. Here are known breaking interface changes that are not backwards compatible with 1.x.
* New syntax for asynchronous specs
* New syntax for spies
* New interface for reporters
* Better Equality testing
* Easier custom matchers
* Change to `toThrow` matcher
* Clock does not uninstall itself at the end of a spec
* More Jasmine internal variables/functions have been moved into closures
### New syntax for asynchronous specs
Similar to [Mocha][mocha], Jasmine befores, specs, and afters can take an optional "done" callback in order to force asynchronous tests. The next function, whether it's a before, spec or after, will wait until this function is called or if a timeout is reached.
### New syntax for spies
Spies have a slightly modified syntax. The ideas came from a desire to preserve any of the properties on a spied-upon function and some better testing patterns.
### New interface for reporters
The reporter interface has changed. The callbacks are different and more consistent. The objects passed in should only provide what is needed to report results. This enforces an interface to result data so custom reporters will be less coupled to Jasmine implementation. The full suite execution time is also reported.
### Better Equality testing
We have tossed the previous equality code and are now using new code for testing equality. We started with [Underscore.js][underscore]'s `isEqual`, refactored a bit and added some additional tests.
### Easier custom matchers
Custom matchers have always been possible, but this was barely documented and clunky to test. We've changed how matchers are added and tested. Jasmine adds its own matchers by the same mechanism that as custom matchers use. Dogfooding FTW.
### Change to `toThrow` matcher
We've changed the behavior of the `toThrow` matcher, moving some functionality to the `toThrowError` matcher. This should allow more of the requested use cases.
### Clock does not uninstall itself at the end of a spec
After installing the Jasmine Clock, it will stay installed until uninstall is called -- clearing up any ambiguity for when those timing functions will go back to being the actual ones.
## More Jasmine internal variables/functions have been moved into closures
Certain variables/functions like a function to get the next spec id have been moved into closures, making the Jasmine interface cleaner.
## Other Changes
* Massive refactoring and better testing
* Environment setup now in `boot.js`
* Development & Build moved to Grunt
* Change in how Jasmine is loaded
* Change in how Jasmine is tested
* Better node.js support
* Better Continuous Integration Environment at Travis
* Support matrix updated
* Removed JsDoc Pages
* Adding Code Climate for JavaScript
## Massive refactoring and better testing
This is the biggest set of changes. We've touched nearly every file and every object. We've slammed objects back together and pulled out new extractions. We've made the code more consistently styled. We've improved the tests nearly everywhere.
In general, Jasmine is made of smaller, more-loosely-coupled objects, unit-tested with explicit dependencies injected. This made tests easier to write, read, and maintain. We know this has made Jasmine development easier for the core team. We expect (and hope) this makes it easier for the community to extend Jasmine and provide pull requests that make more sense the first time out.
## Environment setup now in `boot.js`
Instantiation and setup of the Jasmine environment, including building reporters, exposing the "global" functions, and executing tests has moved into its own file: `boot.js`. This should make it easier to add custom reporters, configure some objects, or just in general change how you use Jasmine from the outside.
For example, during development, Jasmine uses it's own `devboot.js` to load itself twice - once from `jasmine.js` and once from the source directories.
## Development & Build moved to Grunt
We've moved away from Ruby and embraced Node.js and [Grunt.js][grunt] for the various command line tasks during development. Yes, it's a just a different set of dependencies. But it's less code for the team to maintain - it turns out that JavaScript tools are pretty good at building JavaScript projects. This will make it easier for the community to make sure contributions work in browser and in Node.js before submitting Pull Requests. There is more detail in the [Contributor's Guide][contrib].
## Change in how Jasmine is loaded
We did not want to add new run-time dependencies, yet we needed to be cleaner when loading Jasmine. So we wrote a custom "require" scheme that works in Node.js and in browsers. This only affects pull requests that add files - please be careful in these cases. Again, the [Contributor's Guide][contrib] should help.
## Change in how Jasmine is tested with Jasmine
Writing a custom require system helped enforce self-testing - the built `jasmine.js` testing Jasmine from the source directories. Overall this has improved the stability of the code. When you look at Jasmine's tests, you'll see both `jasmine` and `j$` used. The former, `jasmine`, will always be used to test the code from source, which is loaded into the reference `j$`. Please adhere to this pattern when writing tests for contributions.
## Better node.js support
Node.js is now officially a first-class citizen. For a long time we've made sure tests were green in Node before releasing. But it is now officially part of Jasmine's CI build at [Travis][travis]. For the curious, the [`node_suite.js`][node_suite], is essentially a `boot.js` for Node. An official npm is coming.
## Better Continuous Integration Environment at Travis
The [CI build at Travis][travis_jasmine] now runs the core specs in a build matrix across browsers. It's far from complete on the operating system matrix, but you will see that Jasmine runs against: Firefox, Chrome, Safari 5, Safari 6, Phantom.js, Node.js, and IE versions 8, 9, and 10. Big thanks to [SauceLabs][sauce] for their support of open source projects. We will happily take pull requests for additional OS/Browser combos within the matrix.
## Support Matrix Updated
We're dropping support for IE < 8. Jasmine 1.x remains for projects supporting earlier versions of browsers.
## Removed JsDoc Pages
Comments in code are lies waiting to happen. Jasmine's JsDoc comments were no exception. The comments were out of date, the generated pages were even more out of date, and frankly they were not helpful. So they're gone.
Last year saw the posting of the [`introduction.js`][intro] page to document the real, practical interface for projects to use. This page has received a lot of positive feedback so expect more pages like this one.
## Adding Code Climate for JavaScript
We are running Code Climate for Jasmine. We have some work to do here but it's helping us easily find code hotspots.
## Pull Requests & Issues
The following Pull Requests were merged:
* ObjectContaining wrong filed value error message #[394](https://github.com/pivotal/jasmine/issues/394) from albertandrejev
* Removed unnecessary parameter from `suiteFactory()` call #[397](https://github.com/pivotal/jasmine/issues/397) from valera-rozuvan
* `jasmine.Any` supports `Boolean` #[392](https://github.com/pivotal/jasmine/issues/392) from albertandrejev
* Reporters get execution time #[30](https://github.com/pivotal/jasmine/issues/30)
* `toThrow` matchers handle falsy exceptions #[317](https://github.com/pivotal/jasmine/issues/371)
* Removed deprecated `jasmine.Matchers.pp` #[363](https://github.com/pivotal/jasmine/issues/363) from robinboehm
* Fix for Clock ticking to default to 0 #[340](https://github.com/pivotal/jasmine/issues/340) from Caio Cunha
* Whitespace failures should be easier to understand #[332](https://github.com/pivotal/jasmine/issues/332) from bjornblomqvist
* Fix for more markdown-y image for Build status #[329](https://github.com/pivotal/jasmine/issues/329) from sunliwen
* UTF-8 encoding fixes #[333](https://github.com/pivotal/jasmine/issues/333) from bjornblomqvist
### Fixed in RC3
* Improved the performance of the HTML output with a CSS change #[428](https://github.com/pivotal/jasmine/issues/428) - Thanks @tjgrathwell
* Removed an accidental global pollution of `j$` as a reference to Jasmine. Thanks to Morten Maxild from the mailing list
### Fixed in RC5
* Jasmine global object has a addCustomEqualityTester and addMatchers (no longer directly on global)
* Fixed a global leak of `timer`
* Remove currentRunner from Env (users can use topSuite from Env instead)
* [Specs without expectations are now considered passing](http://www.pivotaltracker.com/story/59422744)
* Improve error message when a spec does not call the async callback within the default time interval
* Allow passing a negativeCompare in a custom matcher for more custom implementations when `.not` is called
* Update favicon to be higher resolution
There were several other pull requests that either had already been fixed, or were good starting points for the various changes above. Thank you for all of the hard work to keep Jasmine awesome.
## Other Bugs & Features
There were a few small changes and fixes that didn't fit into any of the above categories:
* HTML Reporter refactored for simplicity and performance
* Default character encoding on the HTML runner page is UTF-8
* [Escape special regex characters from the spec param](http://www.pivotaltracker.com/story/52731407)
* Favicon returns
* [Clock supports `eval`'d strings as functions](http://www.pivotaltracker.com/story/40853563)
* There should always be stack traces on failures
* Removed references to unused `jasmine.VERBOSE`
* Removed references to unused `jasmine.XmlHttpRequest`
### Fixed in RC3
* There is now a consistent `this` between `beforeEach`, `it` and `afterEach` for a spec
* A spy's strategy now has properties `returnValue` and `throwError` because they are better names
* Make it easy to copy the title of failing specs from the HTML output
* Don't add periods to the full name of a spec fix #[427](https://github.com/pivotal/jasmine/issues/427)
* Allow Env to take optional spec/suite ids when asked to `execute`
* [Mock clock now less intrusive, replacing global timer functions only when clock is installed](http://www.pivotaltracker.com/story/54168708)
* Restore custom failure messages for `toHaveBeenCalledWith`
[mocha]: http://visionmedia.github.io/mocha/
[underscore]: http://underscorejs.org/
[grunt]: http://gruntjs.com
[contrib]: https://github.com/pivotal/jasmine/blob/master/CONTRIBUTING.md
[travis]: http://travis-ci.org
[travis_jasmine]: http://travis-ci.org/jasmine
[sauce]: http://saucelabs.com
[node_suite]: https://github.com/pivotal/jasmine/blob/master/spec/node_suite.js
[intro]: http://jasmine.github.io/2.0/introduction.html
------
_Release Notes generated with [Anchorman](http://github.com/infews/anchorman)_
+1 -1
View File
@@ -42,4 +42,4 @@ describe("Any", function() {
expect(any.jasmineToString()).toMatch('<jasmine.any'); expect(any.jasmineToString()).toMatch('<jasmine.any');
}); });
}); });
-20
View File
@@ -341,24 +341,4 @@ describe("Clock (acceptance)", function() {
clock.tick(); clock.tick();
expect(delayedFn2).toHaveBeenCalled(); expect(delayedFn2).toHaveBeenCalled();
}); });
it("calls the global clearTimeout correctly when not installed", function() {
var delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['clearTimeout']),
global = jasmine.getGlobal(),
clock = new j$.Clock(global, delayedFunctionScheduler);
expect(function() {
clock.clearTimeout(123)
}).not.toThrow();
});
it("calls the global clearTimeout correctly when not installed", function() {
var delayedFunctionScheduler = jasmine.createSpyObj('delayedFunctionScheduler', ['clearTimeout']),
global = jasmine.getGlobal(),
clock = new j$.Clock(global, delayedFunctionScheduler);
expect(function() {
clock.clearInterval(123)
}).not.toThrow();
});
}); });
+149 -96
View File
@@ -1,96 +1,149 @@
////TODO: matchers should be add-able to the env, not to the spec. describe("Custom Matchers (Integration)", function() {
//describe("Custom Matchers", function() { var env;
// var env; var fakeTimer;
// var fakeTimer;
// beforeEach(function() {
// beforeEach(function() { env = new j$.Env();
// env = new jasmine.Env(); });
// env.updateInterval = 0;
// }); it("allows adding more matchers local to a spec", function(done) {
// env.it('spec defining a custom matcher', function() {
// it("should be easy to add more matchers local to a spec, suite, etc.", function() { env.addMatchers({
// var spec1, spec2, spec1Matcher, spec2Matcher; matcherForSpec: function() {
// var suite = env.describe('some suite', function() { return {
// env.beforeEach(function() { compare: function(actual, expected) {
// this.addMatchers({ return { pass: false, message: "matcherForSpec: actual: " + actual + "; expected: " + expected };
// matcherForSuite: function(expected) { }
// this.message = "matcherForSuite: actual: " + this.actual + "; expected: " + expected; }
// return true; }
// } });
// });
// }); env.expect("zzz").matcherForSpec("yyy");
// });
// spec1 = env.it('spec with an expectation').runs(function () {
// this.addMatchers({ env.it("spec without custom matcher defined", function() {
// matcherForSpec: function(expected) { expect(env.expect("zzz").matcherForSpec).toBeUndefined();
// this.message = "matcherForSpec: actual: " + this.actual + "; expected: " + expected; });
// return true;
// } var specDoneSpy = jasmine.createSpy("specDoneSpy");
// }); var expectations = function() {
// spec1Matcher = this.expect("xxx"); var firstSpecResult = specDoneSpy.calls.first().args[0];
// }); expect(firstSpecResult.status).toEqual("failed");
// expect(firstSpecResult.failedExpectations[0].message).toEqual("matcherForSpec: actual: zzz; expected: yyy");
// spec2 = env.it('spec with failing expectation').runs(function () { done();
// spec2Matcher = this.expect("yyy"); };
// }); env.addReporter({ specDone:specDoneSpy, jasmineDone: expectations});
// });
// env.execute();
// suite.execute(); });
//
// spec1Matcher.matcherForSuite("expected"); it("passes the spec if the custom matcher passes", function(done) {
// expect(spec1Matcher.message).toEqual("matcherForSuite: actual: xxx; expected: expected"); env.addMatchers({
// spec1Matcher.matcherForSpec("expected"); toBeReal: function() {
// expect(spec1Matcher.message).toEqual("matcherForSpec: actual: xxx; expected: expected"); return { compare: function() { return { pass: true }; } };
// }
// spec2Matcher.matcherForSuite("expected"); });
// expect(spec2Matcher.message).toEqual("matcherForSuite: actual: yyy; expected: expected");
// expect(spec2Matcher.matcherForSpec).toBe(jasmine.undefined); env.it("spec using custom matcher", function() {
// }); env.expect(true).toBeReal();
// });
// it("should generate messages with the same rules as for regular matchers when this.report() is not called", function() {
// var spec; var specExpectations = function(result) {
// var suite = env.describe('some suite', function() { expect(result.status).toEqual('passed');
// spec = env.it('spec with an expectation').runs(function () { };
// this.addMatchers({
// toBeTrue: function() { env.addReporter({ specDone: specExpectations, jasmineDone: done });
// return this.actual === true; env.execute();
// } });
// });
// this.expect(true).toBeTrue(); it("uses the negative compare function for a negative comparison, if provided", function(done) {
// this.expect(false).toBeTrue(); env.addMatchers({
// }); toBeReal: function() {
// }); return {
// compare: function() { return { pass: true }; },
// suite.execute(); negativeCompare: function() { return { pass: true }; }
// };
// var results = spec.results().getItems(); }
// expect(results[0].message).toEqual("Passed."); });
// expect(results[1].message).toEqual("Expected false to be true.");
// }); env.it("spec with custom negative comparison matcher", function() {
// env.expect(true).not.toBeReal();
// it("should pass args", function() { });
// var matcherCallArgs = [];
// var spec; var specExpectations = function(result) {
// var suite = env.describe('some suite', function() { expect(result.status).toEqual('passed');
// spec = env.it('spec with an expectation').runs(function () { }
// this.addMatchers({
// toBeTrue: function() { env.addReporter({ specDone: specExpectations, jasmineDone: done });
// matcherCallArgs.push(jasmine.util.argsToArray(arguments)); env.execute();
// return this.actual === true; });
// }
// }); it("generates messages with the same rules as built in matchers absent a custom message", function(done) {
// this.expect(true).toBeTrue(); env.addMatchers({
// this.expect(false).toBeTrue('arg'); toBeReal: function() {
// this.expect(true).toBeTrue('arg1', 'arg2'); return {
// }); compare: function() {
// }); return { pass: false };
// }
// suite.execute(); }
// var results = spec.results().getItems(); }
// expect(results[0].expected).toEqual(jasmine.undefined); });
// expect(results[1].expected).toEqual('arg');
// expect(results[2].expected).toEqual(['arg1', 'arg2']); env.it('spec with an expectation', function() {
// env.expect("a").toBeReal();
// expect(matcherCallArgs).toEqual([[], ['arg'], ['arg1', 'arg2']]); });
// });
//}); var specExpectations = function(result) {
expect(result.failedExpectations[0].message).toEqual("Expected 'a' to be real.");
};
env.addReporter({ specDone: specExpectations, jasmineDone: done });
env.execute();
});
it("passes the expected and actual arguments to the comparison function", function(done) {
var argumentSpy = jasmine.createSpy("argument spy").and.returnValue({ pass: true });
env.addMatchers({
toBeReal: function() {
return { compare: argumentSpy };
}
});
env.it('spec with an expectation', function () {
env.expect(true).toBeReal();
env.expect(true).toBeReal("arg");
env.expect(true).toBeReal("arg1", "arg2");
});
var specExpectations = function() {
expect(argumentSpy).toHaveBeenCalledWith(true);
expect(argumentSpy).toHaveBeenCalledWith(true, "arg");
expect(argumentSpy).toHaveBeenCalledWith(true, "arg1", "arg2");
};
env.addReporter({ specDone: specExpectations, jasmineDone: done });
env.execute();
});
it("passes the jasmine utility and current equality matchers to the expectation factory", function(done) {
var matcherFactory = function() { return { compare: function() { return {pass: true}; }}; },
argumentSpy = jasmine.createSpy("argument spy").and.returnValue(matcherFactory),
customEqualityFn = function() { return true; };
env.addCustomEqualityTester(customEqualityFn);
env.addMatchers({
toBeReal: argumentSpy
});
env.it("spec with expectation", function() {
env.expect(true).toBeReal();
});
var specExpectations = function() {
expect(argumentSpy).toHaveBeenCalledWith(j$.matchersUtil, [customEqualityFn]);
};
env.addReporter({ specDone: specExpectations, jasmineDone: done });
env.execute();
});
});
+7 -39
View File
@@ -3,29 +3,6 @@ describe("Env", function() {
var env; var env;
beforeEach(function() { beforeEach(function() {
env = new j$.Env(); env = new j$.Env();
env.updateInterval = 0;
});
describe('ids', function() {
it('nextSpecId should return consecutive integers, starting at 0', function() {
expect(env.nextSpecId()).toEqual('spec0');
expect(env.nextSpecId()).toEqual('spec1');
expect(env.nextSpecId()).toEqual('spec2');
});
});
describe("reporting", function() {
var fakeReporter;
beforeEach(function() {
fakeReporter = jasmine.createSpyObj("fakeReporter", ["jasmineStarted"]);
});
it("should allow reporters to be registered", function() {
env.addReporter(fakeReporter);
env.reporter.jasmineStarted();
expect(fakeReporter.jasmineStarted).toHaveBeenCalled();
});
}); });
it('removes all spies when env is executed', function(done) { it('removes all spies when env is executed', function(done) {
@@ -107,21 +84,6 @@ describe("Env", function() {
}); });
}); });
describe("#catchException", function() {
it("returns true if the exception is a pending spec exception", function() {
env.catchExceptions(false);
expect(env.catchException(new Error(j$.Spec.pendingSpecExceptionMessage))).toBe(true);
});
it("returns false if the exception is not a pending spec exception and not catching exceptions", function() {
env.catchExceptions(false);
expect(env.catchException(new Error("external error"))).toBe(false);
expect(env.catchException(new Error(j$.Spec.pendingSpecExceptionMessage))).toBe(true);
});
});
describe("#pending", function() { describe("#pending", function() {
it("throws the Pending Spec exception", function() { it("throws the Pending Spec exception", function() {
expect(function() { expect(function() {
@@ -130,6 +92,12 @@ describe("Env", function() {
}); });
}); });
describe("#topSuite", function() {
it("returns the Jasmine top suite for users to traverse the spec tree", function() {
var suite = env.topSuite();
expect(suite.description).toEqual('Jasmine__TopLevel__Suite');
});
});
}); });
// TODO: move these into a separate file // TODO: move these into a separate file
@@ -356,6 +324,7 @@ describe("Env integration", function() {
env.clock.install(); env.clock.install();
env.clock.setTimeout(delayedFunctionForMockClock, 100); env.clock.setTimeout(delayedFunctionForMockClock, 100);
env.clock.tick(100); env.clock.tick(100);
env.clock.uninstall();
}); });
env.it("test without mock clock", function() { env.it("test without mock clock", function() {
env.clock.setTimeout(delayedFunctionForGlobalClock, 100); env.clock.setTimeout(delayedFunctionForGlobalClock, 100);
@@ -444,7 +413,6 @@ describe("Env integration", function() {
}); });
var suiteResult = reporter.suiteStarted.calls.first().args[0]; var suiteResult = reporter.suiteStarted.calls.first().args[0];
expect(suiteResult.description).toEqual("A Suite"); expect(suiteResult.description).toEqual("A Suite");
expect(reporter.jasmineDone).toHaveBeenCalled();
done(); done();
}); });
+13 -19
View File
@@ -3,22 +3,20 @@ describe('Exceptions:', function() {
beforeEach(function() { beforeEach(function() {
env = new j$.Env(); env = new j$.Env();
env.updateInterval = 0;
}); });
describe('with break on exception', function() { describe('with break on exception', function() {
it('should not catch the exception', function() { it('should not catch the exception', function() {
env.catchExceptions(false); env.catchExceptions(false);
var suite = env.describe('suite for break on exceptions', function() { env.describe('suite for break on exceptions', function() {
env.it('should break when an exception is thrown', function() { env.it('should break when an exception is thrown', function() {
throw new Error('I should hit a breakpoint!'); throw new Error('I should hit a breakpoint!');
}); });
}); });
var runner = env.currentRunner();
var dont_change = 'I will never change!'; var dont_change = 'I will never change!';
try { try {
suite.execute(); env.execute();
dont_change = 'oops I changed'; dont_change = 'oops I changed';
} }
catch (e) {} catch (e) {}
@@ -29,36 +27,32 @@ describe('Exceptions:', function() {
describe("with catch on exception", function() { describe("with catch on exception", function() {
it('should handle exceptions thrown, but continue', function() { it('should handle exceptions thrown, but continue', function() {
var ranSecondTest = false, var secondTest = jasmine.createSpy('second test');
suite = env.describe('Suite for handles exceptions', function () { env.describe('Suite for handles exceptions', function () {
env.it('should be a test that fails because it throws an exception', function() { env.it('should be a test that fails because it throws an exception', function() {
throw new Error(); throw new Error();
}); });
env.it('should be a passing test that runs after exceptions are thrown from a async test', function() { env.it('should be a passing test that runs after exceptions are thrown from a async test', secondTest);
ranSecondTest = true;
});
}); });
suite.execute(); env.execute();
expect(ranSecondTest).toBe(true); expect(secondTest).toHaveBeenCalled();
}); });
it("should handle exceptions thrown directly in top-level describe blocks and continue", function () { it("should handle exceptions thrown directly in top-level describe blocks and continue", function () {
var ranSecondDescribe = false, suite, suite2, runner = env.currentRunner(); var secondDescribe = jasmine.createSpy("second describe");
suite = env.describe("a suite that throws an exception", function () { env.describe("a suite that throws an exception", function () {
env.it("is a test that should pass", function () { env.it("is a test that should pass", function () {
this.expect(true).toEqual(true); this.expect(true).toEqual(true);
}); });
throw new Error("top level error"); throw new Error("top level error");
}); });
suite2 = env.describe("a suite that doesn't throw an exception", function () { env.describe("a suite that doesn't throw an exception", secondDescribe);
ranSecondDescribe = true;
});
runner.execute(); env.execute();
expect(ranSecondDescribe).toBe(true); expect(secondDescribe).toHaveBeenCalled();
}); });
}); });
}); });
+74 -1
View File
@@ -317,4 +317,77 @@ describe("Expectation", function() {
message: "I am a custom message" message: "I am a custom message"
}); });
}); });
});
it("reports a passing result to the spec when the 'not' comparison passes, given a negativeCompare", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: true }; },
negativeCompare: function() { return { pass: true }; }
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
actual = "an actual",
expectation;
j$.Expectation.addMatchers(matchers);
expectation = new j$.Expectation({
matchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(true, {
matcherName: "toFoo",
passed: true,
expected: "hello",
actual: actual,
message: ""
});
});
it("reports a failing result and a custom fail message to the spec when the 'not' comparison fails, given a negativeCompare", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: true }; },
negativeCompare: function() {
return {
pass: false,
message: "I'm a custom message"
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
actual = "an actual",
expectation;
j$.Expectation.addMatchers(matchers);
expectation = new j$.Expectation({
matchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
passed: false,
expected: "hello",
actual: actual,
message: "I'm a custom message"
});
});
});
-1
View File
@@ -6,7 +6,6 @@ xdescribe('JsApiReporter (integration specs)', function() {
beforeEach(function() { beforeEach(function() {
env = new j$.Env(); env = new j$.Env();
env.updateInterval = 0;
suite = env.describe("top-level suite", function() { suite = env.describe("top-level suite", function() {
spec1 = env.it("spec 1", function() { spec1 = env.it("spec 1", function() {
+1 -1
View File
@@ -61,4 +61,4 @@ describe("ObjectContaining", function() {
expect(containing.jasmineToString()).toMatch("<jasmine.objectContaining"); expect(containing.jasmineToString()).toMatch("<jasmine.objectContaining");
}); });
}); });
+28 -20
View File
@@ -36,11 +36,20 @@ describe("QueueRunner", function() {
expect(asyncContext).toBe(context); expect(asyncContext).toBe(context);
}); });
it("supports asynchronous functions, only advancing to next function after a done() callback", function() { describe("with an asynchronous function", function() {
//TODO: it would be nice if spy arity could match the fake, so we could do something like: beforeEach(function() {
//createSpy('asyncfn').and.callFake(function(done) {}); jasmine.clock().install();
});
var onComplete = jasmine.createSpy('onComplete'), afterEach(function() {
jasmine.clock().uninstall();
});
it("supports asynchronous functions, only advancing to next function after a done() callback", function() {
//TODO: it would be nice if spy arity could match the fake, so we could do something like:
//createSpy('asyncfn').and.callFake(function(done) {});
var onComplete = jasmine.createSpy('onComplete'),
beforeCallback = jasmine.createSpy('beforeCallback'), beforeCallback = jasmine.createSpy('beforeCallback'),
fnCallback = jasmine.createSpy('fnCallback'), fnCallback = jasmine.createSpy('fnCallback'),
afterCallback = jasmine.createSpy('afterCallback'), afterCallback = jasmine.createSpy('afterCallback'),
@@ -67,29 +76,28 @@ describe("QueueRunner", function() {
onComplete: onComplete onComplete: onComplete
}); });
clock.install(); queueRunner.execute();
queueRunner.execute(); expect(beforeCallback).toHaveBeenCalled();
expect(fnCallback).not.toHaveBeenCalled();
expect(afterCallback).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
expect(beforeCallback).toHaveBeenCalled(); jasmine.clock().tick(100);
expect(fnCallback).not.toHaveBeenCalled();
expect(afterCallback).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
clock.tick(100); expect(fnCallback).toHaveBeenCalled();
expect(afterCallback).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
expect(fnCallback).toHaveBeenCalled(); jasmine.clock().tick(100);
expect(afterCallback).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
clock.tick(100); expect(afterCallback).toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
expect(afterCallback).toHaveBeenCalled(); jasmine.clock().tick(100);
expect(onComplete).not.toHaveBeenCalled();
clock.tick(100); expect(onComplete).toHaveBeenCalled();
});
expect(onComplete).toHaveBeenCalled();
}); });
it("calls an exception handler when an exception is thrown in a fn", function() { it("calls an exception handler when an exception is thrown in a fn", function() {
+1 -1
View File
@@ -37,4 +37,4 @@ describe("ReportDispatcher", function() {
dispatcher.foo(123, 456); dispatcher.foo(123, 456);
}).not.toThrow(); }).not.toThrow();
}); });
}); });
-1
View File
@@ -5,7 +5,6 @@ describe("jasmine spec running", function () {
beforeEach(function() { beforeEach(function() {
env = new j$.Env(); env = new j$.Env();
env.updateInterval = 0;
}); });
it('should assign spec ids sequentially', function() { it('should assign spec ids sequentially', function() {
+2 -11
View File
@@ -189,18 +189,9 @@ describe("Spec", function() {
expect(done).toHaveBeenCalled(); expect(done).toHaveBeenCalled();
}); });
it("#status returns pending by default", function() { it("#status returns passing by default", function() {
var spec = new j$.Spec({fn: jasmine.createSpy("spec body")}); var spec = new j$.Spec({fn: jasmine.createSpy("spec body")});
expect(spec.status()).toEqual('pending'); expect(spec.status()).toEqual('passed');
});
it("#status returns pending if no expectations were encountered", function() {
var specBody = jasmine.createSpy("spec body"),
spec = new j$.Spec({fn: specBody});
spec.execute();
expect(spec.status()).toEqual('pending');
}); });
it("#status returns passed if all expectations in the spec have passed", function() { it("#status returns passed if all expectations in the spec have passed", function() {
+2 -50
View File
@@ -67,54 +67,6 @@ describe("Suite", function() {
expect(suite.afterFns).toEqual([innerAfter, outerAfter]); expect(suite.afterFns).toEqual([innerAfter, outerAfter]);
}); });
it("adds specs", function() {
var env = new j$.Env(),
fakeQueue = {
add: jasmine.createSpy()
},
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueFactory: function() {
return fakeQueue
}
}),
fakeSpec = {};
expect(suite.specs.length).toEqual(0);
suite.addSpec(fakeSpec);
expect(suite.specs.length).toEqual(1);
});
it("adds suites", function() {
var env = new j$.Env(),
fakeQueue = {
add: jasmine.createSpy()
},
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueFactory: function() {
return fakeQueue
}
}),
anotherSuite = new j$.Suite({
env: env,
description: "I am another suite",
queueFactory: function() {
return fakeQueue
}
});
expect(suite.suites.length).toEqual(0);
suite.addSuite(anotherSuite);
expect(suite.suites.length).toEqual(1);
});
it("can be disabled", function() { it("can be disabled", function() {
var env = new j$.Env(), var env = new j$.Env(),
fakeQueueRunner = jasmine.createSpy('fake queue runner'), fakeQueueRunner = jasmine.createSpy('fake queue runner'),
@@ -154,8 +106,8 @@ describe("Suite", function() {
spyOn(suite, "execute"); spyOn(suite, "execute");
parentSuite.addSpec(fakeSpec1); parentSuite.addChild(fakeSpec1);
parentSuite.addSuite(suite); parentSuite.addChild(suite);
parentSuite.execute(parentSuiteDone); parentSuite.execute(parentSuiteDone);
+13 -1
View File
@@ -153,10 +153,22 @@ describe("matchersUtil", function() {
expect(j$.matchersUtil.equals(1, 2, [tester])).toBe(true); expect(j$.matchersUtil.equals(1, 2, [tester])).toBe(true);
}); });
it("passes for two empty Objects", function () {
expect(j$.matchersUtil.equals({}, {})).toBe(true);
});
describe("when a custom equality matcher is installed that returns 'undefined'", function () {
var tester = function(a, b) { return jasmine.undefined; };
it("passes for two empty Objects", function () {
expect(j$.matchersUtil.equals({}, {}, [tester])).toBe(true);
});
});
it("fails for equivalents when a custom equality matcher returns false", function() { it("fails for equivalents when a custom equality matcher returns false", function() {
var tester = function(a, b) { return false; }; var tester = function(a, b) { return false; };
expect(j$.matchersUtil.equals(1, 2, [tester])).toBe(false); expect(j$.matchersUtil.equals(1, 1, [tester])).toBe(false);
}); });
}); });
+4 -4
View File
@@ -4,7 +4,7 @@ describe("toThrowError", function() {
expect(function() { expect(function() {
matcher.compare({}); matcher.compare({});
}).toThrow(new Error("Actual is not a Function")); // TODO: this needs to change for self-test }).toThrowError("Actual is not a Function");
}); });
it("throws an error when the expected is not an Error, string, or RegExp", function() { it("throws an error when the expected is not an Error, string, or RegExp", function() {
@@ -15,7 +15,7 @@ describe("toThrowError", function() {
expect(function() { expect(function() {
matcher.compare(fn, 1); matcher.compare(fn, 1);
}).toThrow(new Error("Expected is not an Error, string, or RegExp.")); // TODO: this needs to change for self-test }).toThrowError("Expected is not an Error, string, or RegExp.");
}); });
it("throws an error when the expected error type is not an Error", function() { it("throws an error when the expected error type is not an Error", function() {
@@ -26,7 +26,7 @@ describe("toThrowError", function() {
expect(function() { expect(function() {
matcher.compare(fn, void 0, "foo"); matcher.compare(fn, void 0, "foo");
}).toThrow(new Error("Expected error type is not an Error.")); // TODO: this needs to change for self-test }).toThrowError("Expected error type is not an Error.");
}); });
it("throws an error when the expected error message is not a string or RegExp", function() { it("throws an error when the expected error message is not a string or RegExp", function() {
@@ -37,7 +37,7 @@ describe("toThrowError", function() {
expect(function() { expect(function() {
matcher.compare(fn, Error, 1); matcher.compare(fn, Error, 1);
}).toThrow(new Error("Expected error message is not a string or RegExp.")); // TODO: this needs to change for self-test }).toThrowError("Expected error message is not a string or RegExp.");
}); });
it("fails if actual does not throw at all", function() { it("fails if actual does not throw at all", function() {
+3 -2
View File
@@ -4,7 +4,8 @@ describe("toThrow", function() {
expect(function() { expect(function() {
matcher.compare({}); matcher.compare({});
}).toThrow(new Error("Actual is not a Function")); // TODO: this needs to change for self-test matcherComparator({});
}).toThrowError("Actual is not a Function");
}); });
it("fails if actual does not throw", function() { it("fails if actual does not throw", function() {
@@ -95,4 +96,4 @@ describe("toThrow", function() {
expect(result.pass).toBe(false); expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw undefined, but it threw 5."); expect(result.message).toEqual("Expected function to throw undefined, but it threw 5.");
}); });
}); });
+1 -1
View File
@@ -15,4 +15,4 @@ describe("j$.HtmlSpecFilter", function() {
expect(specFilter.matches("foo")).toBe(true); expect(specFilter.matches("foo")).toBe(true);
expect(specFilter.matches("bar")).toBe(false); expect(specFilter.matches("bar")).toBe(false);
}); });
}); });
-1
View File
@@ -3,7 +3,6 @@ describe("MatchersSpec - HTML Dependent", function () {
beforeEach(function() { beforeEach(function() {
env = new j$.Env(); env = new j$.Env();
env.updateInterval = 0;
var suite = env.describe("suite", function() { var suite = env.describe("suite", function() {
spec = env.it("spec", function() { spec = env.it("spec", function() {
+1 -1
View File
@@ -40,4 +40,4 @@ describe("QueryString", function() {
expect(queryString.getParam("baz")).toBeFalsy(); expect(queryString.getParam("baz")).toBeFalsy();
}); });
}); });
}); });
+1 -1
View File
@@ -59,4 +59,4 @@ describe("ResultsNode", function() {
expect(node.last()).toBe(node.children[node.children.length - 1]); expect(node.last()).toBe(node.children[node.children.length - 1]);
}); });
}); });
+13 -11
View File
@@ -6,7 +6,7 @@ var path = require('path');
var jasmineRequire = require('../lib/jasmine-core/jasmine.js'); var jasmineRequire = require('../lib/jasmine-core/jasmine.js');
var jasmine = jasmineRequire.core(jasmineRequire); var jasmine = jasmineRequire.core(jasmineRequire);
var consoleFns = require('../src/console/console.js'); var consoleFns = require('../lib/console/console.js');
extend(jasmineRequire, consoleFns); extend(jasmineRequire, consoleFns);
jasmineRequire.console(jasmineRequire, jasmine); jasmineRequire.console(jasmineRequire, jasmine);
@@ -41,20 +41,10 @@ var jasmineInterface = {
return env.expect(actual); return env.expect(actual);
}, },
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) { spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName); return env.spyOn(obj, methodName);
}, },
clock: env.clock,
setTimeout: env.clock.setTimeout,
clearTimeout: env.clock.clearTimeout,
setInterval: env.clock.setInterval,
clearInterval: env.clock.clearInterval,
jsApiReporter: new jasmine.JsApiReporter({ jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer() timer: new jasmine.Timer()
}) })
@@ -67,6 +57,18 @@ function extend(destination, source) {
return destination; return destination;
} }
jasmine.addCustomEqualityTester = function(tester) {
env.addCustomEqualityTester(tester);
};
jasmine.addMatchers = function(matchers) {
return env.addMatchers(matchers);
};
jasmine.clock = function() {
return env.clock;
};
// Jasmine "runner" // Jasmine "runner"
function executeSpecs(specs, done, isVerbose, showColors) { function executeSpecs(specs, done, isVerbose, showColors) {
global.jasmine = jasmine; global.jasmine = jasmine;
+17 -6
View File
@@ -39,15 +39,10 @@
return env.pending(); return env.pending();
}, },
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) { spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName); return env.spyOn(obj, methodName);
}, },
clock: env.clock,
jsApiReporter: new jasmine.JsApiReporter({ jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer() timer: new jasmine.Timer()
}) })
@@ -59,6 +54,18 @@
extend(window, jasmineInterface); extend(window, jasmineInterface);
} }
jasmine.addCustomEqualityTester = function(tester) {
env.addCustomEqualityTester(tester);
};
jasmine.addMatchers = function(matchers) {
return env.addMatchers(matchers);
};
jasmine.clock = function() {
return env.clock;
};
var queryString = new jasmine.QueryString({ var queryString = new jasmine.QueryString({
getWindowLocation: function() { return window.location; } getWindowLocation: function() { return window.location; }
}); });
@@ -69,7 +76,6 @@
var htmlReporter = new jasmine.HtmlReporter({ var htmlReporter = new jasmine.HtmlReporter({
env: env, env: env,
queryString: queryString,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); }, onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
getContainer: function() { return document.body; }, getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); }, createElement: function() { return document.createElement.apply(document, arguments); },
@@ -88,6 +94,11 @@
return specFilter.matches(spec.getFullName()); return specFilter.matches(spec.getFullName());
}; };
window.setTimeout = window.setTimeout;
window.setInterval = window.setInterval;
window.clearTimeout = window.clearTimeout;
window.clearInterval = window.clearInterval;
var currentWindowOnload = window.onload; var currentWindowOnload = window.onload;
window.onload = function() { window.onload = function() {
+1 -1
View File
@@ -33,4 +33,4 @@ getJasmineRequireObj().Any = function() {
}; };
return Any; return Any;
}; };
+3 -4
View File
@@ -13,7 +13,8 @@ getJasmineRequireObj().Clock = function() {
setInterval: setInterval, setInterval: setInterval,
clearInterval: clearInterval clearInterval: clearInterval
}, },
installed = false; installed = false,
timer;
self.install = function() { self.install = function() {
replace(global, fakeTimingFunctions); replace(global, fakeTimingFunctions);
@@ -60,7 +61,7 @@ getJasmineRequireObj().Clock = function() {
if (installed) { if (installed) {
delayedFunctionScheduler.tick(millis); delayedFunctionScheduler.tick(millis);
} else { } else {
throw new Error("Mock clock is not installed, use jasmine.getEnv().clock.install()"); throw new Error("Mock clock is not installed, use jasmine.clock().install()");
} }
}; };
@@ -68,8 +69,6 @@ getJasmineRequireObj().Clock = function() {
function legacyIE() { function legacyIE() {
//if these methods are polyfilled, apply will be present //if these methods are polyfilled, apply will be present
//TODO: it may be difficult to load the polyfill before jasmine loads
//(env should be new-ed inside of onload)
return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply; return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply;
} }
+174 -197
View File
@@ -5,6 +5,8 @@ getJasmineRequireObj().Env = function(j$) {
var self = this; var self = this;
var global = options.global || j$.getGlobal(); var global = options.global || j$.getGlobal();
var totalSpecsDefined = 0;
var catchExceptions = true; var catchExceptions = true;
var realSetTimeout = j$.getGlobal().setTimeout; var realSetTimeout = j$.getGlobal().setTimeout;
@@ -15,9 +17,10 @@ getJasmineRequireObj().Env = function(j$) {
var spies = []; var spies = [];
this.currentSpec = null; var currentSpec = null;
var currentSuite = null;
this.reporter = new j$.ReportDispatcher([ var reporter = new j$.ReportDispatcher([
"jasmineStarted", "jasmineStarted",
"jasmineDone", "jasmineDone",
"suiteStarted", "suiteStarted",
@@ -26,14 +29,11 @@ getJasmineRequireObj().Env = function(j$) {
"specDone" "specDone"
]); ]);
this.lastUpdate = 0;
this.specFilter = function() { this.specFilter = function() {
return true; return true;
}; };
this.nextSpecId_ = 0; var equalityTesters = [];
this.nextSuiteId_ = 0;
this.equalityTesters_ = [];
var customEqualityTesters = []; var customEqualityTesters = [];
this.addCustomEqualityTester = function(tester) { this.addCustomEqualityTester = function(tester) {
@@ -42,6 +42,16 @@ getJasmineRequireObj().Env = function(j$) {
j$.Expectation.addCoreMatchers(j$.matchers); j$.Expectation.addCoreMatchers(j$.matchers);
var nextSpecId = 0;
var getNextSpecId = function() {
return 'spec' + nextSpecId++;
};
var nextSuiteId = 0;
var getNextSuiteId = function() {
return 'suite' + nextSuiteId++;
};
var expectationFactory = function(actual, spec) { var expectationFactory = function(actual, spec) {
return j$.Expectation.Factory({ return j$.Expectation.Factory({
util: j$.matchersUtil, util: j$.matchersUtil,
@@ -56,32 +66,34 @@ getJasmineRequireObj().Env = function(j$) {
}; };
var specStarted = function(spec) { var specStarted = function(spec) {
self.currentSpec = spec; currentSpec = spec;
self.reporter.specStarted(spec.result); reporter.specStarted(spec.result);
}; };
var beforeFns = function(currentSuite) { var beforeFns = function(suite) {
return function() { return function() {
var befores = []; var befores = [];
for (var suite = currentSuite; suite; suite = suite.parentSuite) { while(suite) {
befores = befores.concat(suite.beforeFns); befores = befores.concat(suite.beforeFns);
suite = suite.parentSuite;
} }
return befores.reverse(); return befores.reverse();
}; };
}; };
var afterFns = function(currentSuite) { var afterFns = function(suite) {
return function() { return function() {
var afters = []; var afters = [];
for (var suite = currentSuite; suite; suite = suite.parentSuite) { while(suite) {
afters = afters.concat(suite.afterFns); afters = afters.concat(suite.afterFns);
suite = suite.parentSuite;
} }
return afters; return afters;
}; };
}; };
var getSpecName = function(spec, currentSuite) { var getSpecName = function(spec, suite) {
return currentSuite.getFullName() + ' ' + spec.description; return suite.getFullName() + ' ' + spec.description;
}; };
// TODO: we may just be able to pass in the fn instead of wrapping here // TODO: we may just be able to pass in the fn instead of wrapping here
@@ -104,10 +116,6 @@ getJasmineRequireObj().Env = function(j$) {
return catchExceptions; return catchExceptions;
}; };
this.catchException = function(e) {
return j$.Spec.isPendingSpecException(e) || catchExceptions;
};
var maximumSpecCallbackDepth = 20; var maximumSpecCallbackDepth = 20;
var currentSpecCallbackDepth = 0; var currentSpecCallbackDepth = 0;
@@ -121,19 +129,136 @@ getJasmineRequireObj().Env = function(j$) {
} }
} }
var queueRunnerFactory = function(options) { var catchException = function(e) {
options.catchException = self.catchException; return j$.Spec.isPendingSpecException(e) || catchExceptions;
options.clearStack = options.clearStack || clearStack;
new j$.QueueRunner(options).run(options.fns, 0);
}; };
var totalSpecsDefined = 0; var queueRunnerFactory = function(options) {
this.specFactory = function(description, fn, suite) { options.catchException = catchException;
options.clearStack = options.clearStack || clearStack;
new j$.QueueRunner(options).execute();
};
var topSuite = new j$.Suite({
env: this,
id: getNextSuiteId(),
description: 'Jasmine__TopLevel__Suite',
queueRunner: queueRunnerFactory,
resultCallback: function() {} // TODO - hook this up
});
runnableLookupTable[topSuite.id] = topSuite;
currentSuite = topSuite;
this.topSuite = function() {
return topSuite;
};
this.execute = function(runnablesToRun) {
runnablesToRun = runnablesToRun || [topSuite.id];
var allFns = [];
for(var i = 0; i < runnablesToRun.length; i++) {
var runnable = runnableLookupTable[runnablesToRun[i]];
allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable));
}
reporter.jasmineStarted({
totalSpecsDefined: totalSpecsDefined
});
queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone});
};
this.addReporter = function(reporterToAdd) {
reporter.addReporter(reporterToAdd);
};
this.addMatchers = function(matchersToAdd) {
j$.Expectation.addMatchers(matchersToAdd);
};
this.spyOn = function(obj, methodName) {
if (j$.util.isUndefined(obj)) {
throw new Error("spyOn could not find an object to spy upon for " + methodName + "()");
}
if (j$.util.isUndefined(obj[methodName])) {
throw new Error(methodName + '() method does not exist');
}
if (obj[methodName] && j$.isSpy(obj[methodName])) {
//TODO?: should this return the current spy? Downside: may cause user confusion about spy state
throw new Error(methodName + ' has already been spied upon');
}
var spy = j$.createSpy(methodName, obj[methodName]);
spies.push({
spy: spy,
baseObj: obj,
methodName: methodName,
originalValue: obj[methodName]
});
obj[methodName] = spy;
return spy;
};
var suiteFactory = function(description) {
var suite = new j$.Suite({
env: self,
id: getNextSuiteId(),
description: description,
parentSuite: currentSuite,
queueRunner: queueRunnerFactory,
onStart: suiteStarted,
resultCallback: function(attrs) {
reporter.suiteDone(attrs);
}
});
runnableLookupTable[suite.id] = suite;
return suite;
};
this.describe = function(description, specDefinitions) {
var suite = suiteFactory(description);
var parentSuite = currentSuite;
parentSuite.addChild(suite);
currentSuite = suite;
var declarationError = null;
try {
specDefinitions.call(suite);
} catch (e) {
declarationError = e;
}
if (declarationError) {
this.it("encountered a declaration exception", function() {
throw declarationError;
});
}
currentSuite = parentSuite;
return suite;
};
this.xdescribe = function(description, specDefinitions) {
var suite = this.describe(description, specDefinitions);
suite.disable();
return suite;
};
var specFactory = function(description, fn, suite) {
totalSpecsDefined++; totalSpecsDefined++;
var spec = new j$.Spec({ var spec = new j$.Spec({
id: self.nextSpecId(), id: getNextSpecId(),
beforeFns: beforeFns(suite), beforeFns: beforeFns(suite),
afterFns: afterFns(suite), afterFns: afterFns(suite),
expectationFactory: expectationFactory, expectationFactory: expectationFactory,
@@ -169,192 +294,44 @@ getJasmineRequireObj().Env = function(j$) {
function specResultCallback(result) { function specResultCallback(result) {
removeAllSpies(); removeAllSpies();
j$.Expectation.resetMatchers(); j$.Expectation.resetMatchers();
customEqualityTesters.length = 0; customEqualityTesters = [];
self.clock.uninstall(); currentSpec = null;
self.currentSpec = null; reporter.specDone(result);
self.reporter.specDone(result);
} }
}; };
var suiteStarted = function(suite) { var suiteStarted = function(suite) {
self.reporter.suiteStarted(suite.result); reporter.suiteStarted(suite.result);
}; };
var suiteConstructor = j$.Suite; this.it = function(description, fn) {
var spec = specFactory(description, fn, currentSuite);
this.topSuite = new j$.Suite({ currentSuite.addChild(spec);
env: this, return spec;
id: this.nextSuiteId(),
description: 'Jasmine__TopLevel__Suite',
queueRunner: queueRunnerFactory,
completeCallback: function() {}, // TODO - hook this up
resultCallback: function() {} // TODO - hook this up
});
runnableLookupTable[this.topSuite.id] = this.topSuite;
this.currentSuite = this.topSuite;
this.suiteFactory = function(description) {
var suite = new suiteConstructor({
env: self,
id: self.nextSuiteId(),
description: description,
parentSuite: self.currentSuite,
queueRunner: queueRunnerFactory,
onStart: suiteStarted,
resultCallback: function(attrs) {
self.reporter.suiteDone(attrs);
}
});
runnableLookupTable[suite.id] = suite;
return suite;
}; };
this.execute = function(runnablesToRun) { this.xit = function(description, fn) {
runnablesToRun = runnablesToRun || [this.topSuite.id]; var spec = this.it(description, fn);
spec.pend();
var allFns = []; return spec;
for(var i = 0; i < runnablesToRun.length; i++) {
var runnable = runnableLookupTable[runnablesToRun[i]];
allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable));
}
this.reporter.jasmineStarted({
totalSpecsDefined: totalSpecsDefined
});
queueRunnerFactory({fns: allFns, onComplete: this.reporter.jasmineDone});
}; };
this.spyOn = function(obj, methodName) { this.expect = function(actual) {
if (j$.util.isUndefined(obj)) { return currentSpec.expect(actual);
throw new Error("spyOn could not find an object to spy upon for " + methodName + "()"); };
}
if (j$.util.isUndefined(obj[methodName])) { this.beforeEach = function(beforeEachFunction) {
throw new Error(methodName + '() method does not exist'); currentSuite.beforeEach(beforeEachFunction);
} };
if (obj[methodName] && j$.isSpy(obj[methodName])) { this.afterEach = function(afterEachFunction) {
//TODO?: should this return the current spy? Downside: may cause user confusion about spy state currentSuite.afterEach(afterEachFunction);
throw new Error(methodName + ' has already been spied upon'); };
}
var spy = j$.createSpy(methodName, obj[methodName]); this.pending = function() {
throw j$.Spec.pendingSpecExceptionMessage;
spies.push({
spy: spy,
baseObj: obj,
methodName: methodName,
originalValue: obj[methodName]
});
obj[methodName] = spy;
return spy;
}; };
} }
Env.prototype.addMatchers = function(matchersToAdd) {
j$.Expectation.addMatchers(matchersToAdd);
};
Env.prototype.version = function() {
return j$.version;
};
Env.prototype.expect = function(actual) {
return this.currentSpec.expect(actual);
};
// TODO: move this to closure
Env.prototype.versionString = function() {
console.log("DEPRECATED == use j$.version");
return j$.version;
};
// TODO: move this to closure
Env.prototype.nextSpecId = function() {
return 'spec' + this.nextSpecId_++;
};
// TODO: move this to closure
Env.prototype.nextSuiteId = function() {
return 'suite' + this.nextSuiteId_++;
};
// TODO: move this to closure
Env.prototype.addReporter = function(reporter) {
this.reporter.addReporter(reporter);
};
// TODO: move this to closure
Env.prototype.describe = function(description, specDefinitions) {
var suite = this.suiteFactory(description);
var parentSuite = this.currentSuite;
parentSuite.addSuite(suite);
this.currentSuite = suite;
var declarationError = null;
try {
specDefinitions.call(suite);
} catch (e) {
declarationError = e;
}
if (declarationError) {
this.it("encountered a declaration exception", function() {
throw declarationError;
});
}
this.currentSuite = parentSuite;
return suite;
};
// TODO: move this to closure
Env.prototype.xdescribe = function(description, specDefinitions) {
var suite = this.describe(description, specDefinitions);
suite.disable();
return suite;
};
// TODO: move this to closure
Env.prototype.it = function(description, fn) {
var spec = this.specFactory(description, fn, this.currentSuite);
this.currentSuite.addSpec(spec);
return spec;
};
// TODO: move this to closure
Env.prototype.xit = function(description, fn) {
var spec = this.it(description, fn);
spec.pend();
return spec;
};
// TODO: move this to closure
Env.prototype.beforeEach = function(beforeEachFunction) {
this.currentSuite.beforeEach(beforeEachFunction);
};
// TODO: move this to closure
Env.prototype.afterEach = function(afterEachFunction) {
this.currentSuite.afterEach(afterEachFunction);
};
// TODO: move this to closure
Env.prototype.pending = function() {
throw j$.Spec.pendingSpecExceptionMessage;
};
// TODO: Still needed?
Env.prototype.currentRunner = function() {
return this.topSuite;
};
return Env; return Env;
}; };
+11 -2
View File
@@ -22,12 +22,21 @@ getJasmineRequireObj().Expectation = function() {
args.unshift(this.actual); args.unshift(this.actual);
var result = matcherFactory(this.util, this.customEqualityTesters).compare.apply(null, args); var matcher = matcherFactory(this.util, this.customEqualityTesters),
matcherCompare = matcher.compare;
function defaultNegativeCompare() {
var result = matcher.compare.apply(null, args);
result.pass = !result.pass;
return result;
}
if (this.isNot) { if (this.isNot) {
result.pass = !result.pass; matcherCompare = matcher.negativeCompare || defaultNegativeCompare;
} }
var result = matcherCompare.apply(null, args);
if (!result.pass) { if (!result.pass) {
if (!result.message) { if (!result.message) {
args.unshift(this.isNot); args.unshift(this.isNot);
+2 -2
View File
@@ -47,8 +47,8 @@ getJasmineRequireObj().pp = function(j$) {
PrettyPrinter.prototype.iterateObject = function(obj, fn) { PrettyPrinter.prototype.iterateObject = function(obj, fn) {
for (var property in obj) { for (var property in obj) {
if (!obj.hasOwnProperty(property)) continue; if (!obj.hasOwnProperty(property)) { continue; }
if (property == '__Jasmine_been_here_before__') continue; if (property == '__Jasmine_been_here_before__') { continue; }
fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) &&
obj.__lookupGetter__(property) !== null) : false); obj.__lookupGetter__(property) !== null) : false);
} }
+2 -2
View File
@@ -5,11 +5,11 @@ getJasmineRequireObj().ReportDispatcher = function() {
for (var i = 0; i < dispatchedMethods.length; i++) { for (var i = 0; i < dispatchedMethods.length; i++) {
var method = dispatchedMethods[i]; var method = dispatchedMethods[i];
this[method] = function(m) { this[method] = (function(m) {
return function() { return function() {
dispatch(m, arguments); dispatch(m, arguments);
}; };
}(method); }(method));
} }
var reporters = []; var reporters = [];
+15 -18
View File
@@ -1,6 +1,5 @@
getJasmineRequireObj().Spec = function(j$) { getJasmineRequireObj().Spec = function(j$) {
function Spec(attrs) { function Spec(attrs) {
this.encounteredExpectations = false;
this.expectationFactory = attrs.expectationFactory; this.expectationFactory = attrs.expectationFactory;
this.resultCallback = attrs.resultCallback || function() {}; this.resultCallback = attrs.resultCallback || function() {};
this.id = attrs.id; this.id = attrs.id;
@@ -26,13 +25,11 @@ getJasmineRequireObj().Spec = function(j$) {
id: this.id, id: this.id,
description: this.description, description: this.description,
fullName: this.getFullName(), fullName: this.getFullName(),
status: this.status(),
failedExpectations: [] failedExpectations: []
}; };
} }
Spec.prototype.addExpectationResult = function(passed, data) { Spec.prototype.addExpectationResult = function(passed, data) {
this.encounteredExpectations = true;
if (passed) { if (passed) {
return; return;
} }
@@ -56,7 +53,7 @@ getJasmineRequireObj().Spec = function(j$) {
function timeoutable(fn) { function timeoutable(fn) {
return function(done) { return function(done) {
var timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() { var timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
onException(new Error('timeout')); onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
done(); done();
}, j$.DEFAULT_TIMEOUT_INTERVAL]]); }, j$.DEFAULT_TIMEOUT_INTERVAL]]);
@@ -70,8 +67,8 @@ getJasmineRequireObj().Spec = function(j$) {
} }
var befores = this.beforeFns() || [], var befores = this.beforeFns() || [],
afters = this.afterFns() || [], afters = this.afterFns() || [],
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn; thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
var allFns = befores.concat(thisOne).concat(afters); var allFns = befores.concat(thisOne).concat(afters);
this.queueRunner({ this.queueRunner({
@@ -81,18 +78,18 @@ getJasmineRequireObj().Spec = function(j$) {
}); });
function onException(e) { function onException(e) {
if (Spec.isPendingSpecException(e)) { if (Spec.isPendingSpecException(e)) {
self.pend(); self.pend();
return; return;
} }
self.addExpectationResult(false, { self.addExpectationResult(false, {
matcherName: "", matcherName: "",
passed: false, passed: false,
expected: "", expected: "",
actual: "", actual: "",
error: e error: e
}); });
} }
function complete() { function complete() {
@@ -118,7 +115,7 @@ getJasmineRequireObj().Spec = function(j$) {
return 'disabled'; return 'disabled';
} }
if (this.markedPending || !this.encounteredExpectations) { if (this.markedPending) {
return 'pending'; return 'pending';
} }
+7 -22
View File
@@ -5,7 +5,6 @@ getJasmineRequireObj().Suite = function() {
this.parentSuite = attrs.parentSuite; this.parentSuite = attrs.parentSuite;
this.description = attrs.description; this.description = attrs.description;
this.onStart = attrs.onStart || function() {}; this.onStart = attrs.onStart || function() {};
this.completeCallback = attrs.completeCallback || function() {}; // TODO: this is unused
this.resultCallback = attrs.resultCallback || function() {}; this.resultCallback = attrs.resultCallback || function() {};
this.clearStack = attrs.clearStack || function(fn) {fn();}; this.clearStack = attrs.clearStack || function(fn) {fn();};
@@ -14,9 +13,7 @@ getJasmineRequireObj().Suite = function() {
this.queueRunner = attrs.queueRunner || function() {}; this.queueRunner = attrs.queueRunner || function() {};
this.disabled = false; this.disabled = false;
this.children_ = []; // TODO: rename this.children = [];
this.suites = []; // TODO: needed?
this.specs = []; // TODO: needed?
this.result = { this.result = {
id: this.id, id: this.id,
@@ -48,19 +45,8 @@ getJasmineRequireObj().Suite = function() {
this.afterFns.unshift(fn); this.afterFns.unshift(fn);
}; };
Suite.prototype.addSpec = function(spec) { Suite.prototype.addChild = function(child) {
this.children_.push(spec); this.children.push(child);
this.specs.push(spec); // TODO: needed?
};
Suite.prototype.addSuite = function(suite) {
suite.parentSuite = this;
this.children_.push(suite);
this.suites.push(suite); // TODO: needed?
};
Suite.prototype.children = function() {
return this.children_;
}; };
Suite.prototype.execute = function(onComplete) { Suite.prototype.execute = function(onComplete) {
@@ -70,11 +56,10 @@ getJasmineRequireObj().Suite = function() {
return; return;
} }
var allFns = [], var allFns = [];
children = this.children_;
for (var i = 0; i < children.length; i++) { for (var i = 0; i < this.children.length; i++) {
allFns.push(wrapChildAsAsync(children[i])); allFns.push(wrapChildAsAsync(this.children[i]));
} }
this.onStart(this); this.onStart(this);
@@ -96,7 +81,7 @@ getJasmineRequireObj().Suite = function() {
return function(done) { child.execute(done); }; return function(done) { child.execute(done); };
} }
}; };
return Suite; return Suite;
}; };
+1 -1
View File
@@ -15,4 +15,4 @@ getJasmineRequireObj().Timer = function() {
} }
return Timer; return Timer;
}; };
+13 -13
View File
@@ -51,18 +51,18 @@ getJasmineRequireObj().base = function(j$) {
j$.createSpy = function(name, originalFn) { j$.createSpy = function(name, originalFn) {
var spyStrategy = new j$.SpyStrategy({ var spyStrategy = new j$.SpyStrategy({
name: name, name: name,
fn: originalFn, fn: originalFn,
getSpy: function() { return spy; } getSpy: function() { return spy; }
}), }),
callTracker = new j$.CallTracker(), callTracker = new j$.CallTracker(),
spy = function() { spy = function() {
callTracker.track({ callTracker.track({
object: this, object: this,
args: Array.prototype.slice.apply(arguments) args: Array.prototype.slice.apply(arguments)
}); });
return spyStrategy.exec.apply(this, arguments); return spyStrategy.exec.apply(this, arguments);
}; };
for (var prop in originalFn) { for (var prop in originalFn) {
if (prop === 'and' || prop === 'calls') { if (prop === 'and' || prop === 'calls') {
@@ -83,7 +83,7 @@ getJasmineRequireObj().base = function(j$) {
return false; return false;
} }
return putativeSpy.and instanceof j$.SpyStrategy && return putativeSpy.and instanceof j$.SpyStrategy &&
putativeSpy.calls instanceof j$.CallTracker; putativeSpy.calls instanceof j$.CallTracker;
}; };
j$.createSpyObj = function(baseName, methodNames) { j$.createSpyObj = function(baseName, methodNames) {
+15 -13
View File
@@ -37,7 +37,9 @@ getJasmineRequireObj().matchersUtil = function(j$) {
if (expected.length > 0) { if (expected.length > 0) {
for (var i = 0; i < expected.length; i++) { for (var i = 0; i < expected.length; i++) {
if (i > 0) message += ","; if (i > 0) {
message += ",";
}
message += " " + j$.pp(expected[i]); message += " " + j$.pp(expected[i]);
} }
} }
@@ -52,9 +54,9 @@ getJasmineRequireObj().matchersUtil = function(j$) {
var result = true; var result = true;
for (var i = 0; i < customTesters.length; i++) { for (var i = 0; i < customTesters.length; i++) {
result = customTesters[i](a, b); var customTesterResult = customTesters[i](a, b);
if (result) { if (!j$.util.isUndefined(customTesterResult)) {
return true; return customTesterResult;
} }
} }
@@ -85,11 +87,11 @@ getJasmineRequireObj().matchersUtil = function(j$) {
// Identical objects are equal. `0 === -0`, but they aren't identical. // Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) return a !== 0 || 1 / a == 1 / b; if (a === b) { return a !== 0 || 1 / a == 1 / b; }
// A strict comparison is necessary because `null == undefined`. // A strict comparison is necessary because `null == undefined`.
if (a === null || b === null) return a === b; if (a === null || b === null) { return a === b; }
var className = Object.prototype.toString.call(a); var className = Object.prototype.toString.call(a);
if (className != Object.prototype.toString.call(b)) return false; if (className != Object.prototype.toString.call(b)) { return false; }
switch (className) { switch (className) {
// Strings, numbers, dates, and booleans are compared by value. // Strings, numbers, dates, and booleans are compared by value.
case '[object String]': case '[object String]':
@@ -113,14 +115,14 @@ getJasmineRequireObj().matchersUtil = function(j$) {
a.multiline == b.multiline && a.multiline == b.multiline &&
a.ignoreCase == b.ignoreCase; a.ignoreCase == b.ignoreCase;
} }
if (typeof a != 'object' || typeof b != 'object') return false; if (typeof a != 'object' || typeof b != 'object') { return false; }
// Assume equality for cyclic structures. The algorithm for detecting cyclic // Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
var length = aStack.length; var length = aStack.length;
while (length--) { while (length--) {
// Linear search. Performance is inversely proportional to the number of // Linear search. Performance is inversely proportional to the number of
// unique nested structures. // unique nested structures.
if (aStack[length] == a) return bStack[length] == b; if (aStack[length] == a) { return bStack[length] == b; }
} }
// Add the first object to the stack of traversed objects. // Add the first object to the stack of traversed objects.
aStack.push(a); aStack.push(a);
@@ -134,7 +136,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
if (result) { if (result) {
// Deep compare the contents, ignoring non-numeric properties. // Deep compare the contents, ignoring non-numeric properties.
while (size--) { while (size--) {
if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) break; if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) { break; }
} }
} }
} else { } else {
@@ -151,13 +153,13 @@ getJasmineRequireObj().matchersUtil = function(j$) {
// Count the expected number of properties. // Count the expected number of properties.
size++; size++;
// Deep compare each member. // Deep compare each member.
if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) break; if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) { break; }
} }
} }
// Ensure that both objects contain the same number of properties. // Ensure that both objects contain the same number of properties.
if (result) { if (result) {
for (key in b) { for (key in b) {
if (has(b, key) && !(size--)) break; if (has(b, key) && !(size--)) { break; }
} }
result = !size; result = !size;
} }
@@ -176,4 +178,4 @@ getJasmineRequireObj().matchersUtil = function(j$) {
return typeof obj === 'function'; return typeof obj === 'function';
} }
} }
}; };
+9 -5
View File
@@ -3,14 +3,16 @@ getJasmineRequireObj().util = function() {
var util = {}; var util = {};
util.inherit = function(childClass, parentClass) { util.inherit = function(childClass, parentClass) {
var subclass = function() { var Subclass = function() {
}; };
subclass.prototype = parentClass.prototype; Subclass.prototype = parentClass.prototype;
childClass.prototype = new subclass(); childClass.prototype = new Subclass();
}; };
util.htmlEscape = function(str) { util.htmlEscape = function(str) {
if (!str) return str; if (!str) {
return str;
}
return str.replace(/&/g, '&amp;') return str.replace(/&/g, '&amp;')
.replace(/</g, '&lt;') .replace(/</g, '&lt;')
.replace(/>/g, '&gt;'); .replace(/>/g, '&gt;');
@@ -18,7 +20,9 @@ getJasmineRequireObj().util = function() {
util.argsToArray = function(args) { util.argsToArray = function(args) {
var arrayOfArgs = []; var arrayOfArgs = [];
for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); for (var i = 0; i < args.length; i++) {
arrayOfArgs.push(args[i]);
}
return arrayOfArgs; return arrayOfArgs;
}; };
+4 -3
View File
@@ -1,8 +1,8 @@
jasmineRequire.HtmlReporter = function(j$) { jasmineRequire.HtmlReporter = function(j$) {
var noopTimer = { var noopTimer = {
start: function(){}, start: function() {},
elapsed: function(){ return 0; } elapsed: function() { return 0; }
}; };
function HtmlReporter(options) { function HtmlReporter(options) {
@@ -73,7 +73,8 @@ jasmineRequire.HtmlReporter = function(j$) {
symbols.appendChild(createDom("li", { symbols.appendChild(createDom("li", {
className: result.status, className: result.status,
id: "spec_" + result.id, id: "spec_" + result.id,
title: result.fullName} title: result.fullName
}
)); ));
if (result.status == "failed") { if (result.status == "failed") {
+1 -1
View File
@@ -16,4 +16,4 @@ jasmineRequire.ResultsNode = function() {
} }
return ResultsNode; return ResultsNode;
}; };
+1 -1
View File
@@ -3,4 +3,4 @@ jasmineRequire.html = function(j$) {
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
j$.QueryString = jasmineRequire.QueryString(); j$.QueryString = jasmineRequire.QueryString();
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
}; };
+1 -1
View File
@@ -1,3 +1,3 @@
getJasmineRequireObj().version = function() { getJasmineRequireObj().version = function() {
return "<%= version %>"; return "<%= version %>";
}; };
+6 -4
View File
@@ -1,12 +1,14 @@
#!/bin/bash -e #!/bin/bash -e
export DISPLAY=:99.0
/etc/init.d/xvfb start
if [ $USE_SAUCE == true ] if [ $USE_SAUCE == true ]
then then
if [ $TRAVIS_SECURE_ENV_VARS == true ]
then
curl https://gist.github.com/santiycr/5139565/raw/sauce_connect_setup.sh | bash curl https://gist.github.com/santiycr/5139565/raw/sauce_connect_setup.sh | bash
else
echo "skipping tests since we can't use sauce"
exit 0
fi
fi fi
bundle exec rake jasmine:ci bundle exec rake jasmine:ci
+3
View File
@@ -0,0 +1,3 @@
git clone https://github.com/jasmine/jasmine.github.io.git
bundle exec rake jasmine:ci JASMINE_CONFIG_PATH=jasmine.github.io/2.0/spec/support/jasmine.yml