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
.jshintrc Normal file
View File

@@ -0,0 +1,9 @@
{
"bitwise": true,
"curly": true,
"freeze": true,
"immed": true,
"newcap": true,
"trailing": true,
"loopfunc": true
}

View File

@@ -7,6 +7,9 @@ env:
- USE_SAUCE=true
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="firefox"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- secure: WSPWhlnC4mWSnSPquX+m1/BCu5ch5NygkaHuM2Nea7lD8oS3XLX8QncZZAsQ4lnNfqoDDuBOizG0AESiqNvE4y6x5qvLLTS6q+ce255ZEMZ71TBdZgDEEvGMEjOPPsVXiXyTQOP1lwOPlrbZvaPgWV7e11KIBab6DfFcQpnvDgo=
- secure: SW7CJhZnwaNT749Gdnhvqb5rbXlAOsygUAzh9qhtyvbqXKkmJdBIEsO01YF6pbju1X2twE9JvWCOxeZju43NgQChJlPsGbjY2j3k/TdQeTAJesQe2K7ytwghunI30gjEovtRH0T3w1EmcKPH8yj5eBIcB2OYoJHx8KEC7e68q1g=
matrix:
@@ -14,11 +17,7 @@ matrix:
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh"
- env:
- JASMINE_BROWSER="firefox"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- env:
- env:
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.8"
- SAUCE_BROWSER_VERSION=6
@@ -26,22 +25,26 @@ matrix:
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.6"
- SAUCE_BROWSER_VERSION=5
- env:
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 8"
- SAUCE_BROWSER_VERSION=10
- env:
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 7"
- SAUCE_BROWSER_VERSION=9
- env:
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 7"
- SAUCE_BROWSER_VERSION=8
- env:
- env:
- JASMINE_BROWSER="chrome"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- env:
- env:
- JASMINE_BROWSER="phantomjs"
- USE_SAUCE=false
- env:
- USE_SAUCE=false
- JASMINE_BROWSER="phantomjs"
- TEST_COMMAND="bash travis-docs-script.sh"

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

View File

@@ -10,3 +10,5 @@ end
gemspec
gem "jasmine_selenium_runner", :git => 'https://github.com/jasmine/jasmine_selenium_runner.git'
gem "anchorman"

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**
@@ -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
* [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
Copyright (c) 2008-2013 Pivotal Labs. This software is licensed under the MIT License.

View File

@@ -9,7 +9,7 @@ load "jasmine/tasks/jasmine.rake"
namespace :jasmine do
task :set_env do
ENV['JASMINE_CONFIG_PATH'] = 'spec/support/jasmine.yml'
ENV['JASMINE_CONFIG_PATH'] ||= 'spec/support/jasmine.yml'
end
end

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

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

View File

@@ -1,7 +1,8 @@
var standaloneLibDir = "lib/jasmine-" + jasmineVersion;
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); }
module.exports = {
@@ -26,13 +27,21 @@ module.exports = {
],
dest: standaloneLibDir,
expand: true,
cwd: lib("")
cwd: libJasmineCore("")
},
{
src: [
"console.js"
],
dest: standaloneLibDir,
expand: true,
cwd: libConsole()
},
{
src: [ "boot.js" ],
dest: standaloneLibDir,
expand: true,
cwd: lib("boot")
cwd: libJasmineCore("boot")
},
{
src: [ "SpecRunner.html" ],
@@ -44,13 +53,13 @@ module.exports = {
src: [ "*.js" ],
dest: "src",
expand: true,
cwd: lib("example/src/")
cwd: libJasmineCore("example/src/")
},
{
src: [ "*.js" ],
dest: "spec",
expand: true,
cwd: lib("example/spec/")
cwd: libJasmineCore("example/spec/")
}
]
}

View File

@@ -44,7 +44,7 @@ module.exports = {
'src/console/requireConsole.js',
'src/console/ConsoleReporter.js'
],
dest: 'src/console/console.js'
dest: 'lib/console/console.js'
},
options: {
banner: license(),
@@ -54,4 +54,4 @@ module.exports = {
}
}
}
};
};

View File

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

View File

@@ -1,7 +1,7 @@
var grunt = require("grunt");
function standaloneTmpDir(path) { return "dist/tmp/" + path; }
grunt.registerTask("build:compileSpecRunner",
"Processes the spec runner template and writes to a tmp file",
function() {
@@ -23,6 +23,7 @@ grunt.registerTask("build:cleanSpecRunner",
grunt.registerTask("buildStandaloneDist",
"Builds a standalone distribution",
[
"buildDistribution",
"build:compileSpecRunner",
"compress:standalone",
"build:cleanSpecRunner"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 905 B

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -19,4 +19,5 @@ Gem::Specification.new do |s|
s.add_development_dependency "rake"
s.add_development_dependency "sauce-connect"
s.add_development_dependency "jasmine_selenium_runner"
s.add_development_dependency "compass"
end

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
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() {
/**
* ## 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);
/**
* 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);
/**
* Create the Jasmine environment. This is used to run all specs in a project.
*/
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 = {
describe: function(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();
},
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName);
},
clock: env.clock,
jsApiReporter: new jasmine.JsApiReporter({
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") {
extend(exports, jasmineInterface);
} else {
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({
getWindowLocation: function() { return window.location; }
});
// TODO: move all of catching to raise so we don't break our brains
var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
/**
* ## 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({
env: env,
queryString: queryString,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
getContainer: function() { return document.body; },
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()
});
/**
* 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(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({
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());
};
/**
* 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;
window.onload = function() {
@@ -119,6 +192,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
env.execute();
};
/**
* Helper function for readability above.
*/
function extend(destination, source) {
for (var property in source) destination[property] = source[property];
return destination;

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() {
/**
* ## 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);
/**
* 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);
/**
* Create the Jasmine environment. This is used to run all specs in a project.
*/
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 = {
describe: function(description, specDefinitions) {
return env.describe(description, specDefinitions);
@@ -38,37 +65,64 @@
return env.pending();
},
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName);
},
clock: env.clock,
jsApiReporter: new jasmine.JsApiReporter({
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") {
extend(exports, jasmineInterface);
} else {
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({
getWindowLocation: function() { return window.location; }
});
// TODO: move all of catching to raise so we don't break our brains
var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
/**
* ## 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({
env: env,
queryString: queryString,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
@@ -76,9 +130,15 @@
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(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({
filterString: function() { return queryString.getParam("spec"); }
});
@@ -87,6 +147,19 @@
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;
window.onload = function() {
@@ -97,6 +170,9 @@
env.execute();
};
/**
* Helper function for readability above.
*/
function extend(destination, source) {
for (var property in source) destination[property] = source[property];
return destination;

View File

@@ -26,11 +26,12 @@ jasmineRequire.html = function(j$) {
j$.QueryString = jasmineRequire.QueryString();
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
};
jasmineRequire.HtmlReporter = function(j$) {
var noopTimer = {
start: function(){},
elapsed: function(){ return 0; }
start: function() {},
elapsed: function() { return 0; }
};
function HtmlReporter(options) {
@@ -101,7 +102,8 @@ jasmineRequire.HtmlReporter = function(j$) {
symbols.appendChild(createDom("li", {
className: result.status,
id: "spec_" + result.id,
title: result.fullName}
title: result.fullName
}
));
if (result.status == "failed") {
@@ -307,6 +309,7 @@ jasmineRequire.ResultsNode = function() {
return ResultsNode;
};
jasmineRequire.QueryString = function() {
function QueryString(options) {

View File

@@ -142,18 +142,18 @@ getJasmineRequireObj().base = function(j$) {
j$.createSpy = function(name, originalFn) {
var spyStrategy = new j$.SpyStrategy({
name: name,
fn: originalFn,
getSpy: function() { return spy; }
}),
callTracker = new j$.CallTracker(),
spy = function() {
callTracker.track({
object: this,
args: Array.prototype.slice.apply(arguments)
});
return spyStrategy.exec.apply(this, arguments);
};
name: name,
fn: originalFn,
getSpy: function() { return spy; }
}),
callTracker = new j$.CallTracker(),
spy = function() {
callTracker.track({
object: this,
args: Array.prototype.slice.apply(arguments)
});
return spyStrategy.exec.apply(this, arguments);
};
for (var prop in originalFn) {
if (prop === 'and' || prop === 'calls') {
@@ -174,7 +174,7 @@ getJasmineRequireObj().base = function(j$) {
return false;
}
return putativeSpy.and instanceof j$.SpyStrategy &&
putativeSpy.calls instanceof j$.CallTracker;
putativeSpy.calls instanceof j$.CallTracker;
};
j$.createSpyObj = function(baseName, methodNames) {
@@ -194,14 +194,16 @@ getJasmineRequireObj().util = function() {
var util = {};
util.inherit = function(childClass, parentClass) {
var subclass = function() {
var Subclass = function() {
};
subclass.prototype = parentClass.prototype;
childClass.prototype = new subclass();
Subclass.prototype = parentClass.prototype;
childClass.prototype = new Subclass();
};
util.htmlEscape = function(str) {
if (!str) return str;
if (!str) {
return str;
}
return str.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
@@ -209,7 +211,9 @@ getJasmineRequireObj().util = function() {
util.argsToArray = function(args) {
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;
};
@@ -222,7 +226,6 @@ getJasmineRequireObj().util = function() {
getJasmineRequireObj().Spec = function(j$) {
function Spec(attrs) {
this.encounteredExpectations = false;
this.expectationFactory = attrs.expectationFactory;
this.resultCallback = attrs.resultCallback || function() {};
this.id = attrs.id;
@@ -248,13 +251,11 @@ getJasmineRequireObj().Spec = function(j$) {
id: this.id,
description: this.description,
fullName: this.getFullName(),
status: this.status(),
failedExpectations: []
};
}
Spec.prototype.addExpectationResult = function(passed, data) {
this.encounteredExpectations = true;
if (passed) {
return;
}
@@ -278,7 +279,7 @@ getJasmineRequireObj().Spec = function(j$) {
function timeoutable(fn) {
return function(done) {
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();
}, j$.DEFAULT_TIMEOUT_INTERVAL]]);
@@ -292,8 +293,8 @@ getJasmineRequireObj().Spec = function(j$) {
}
var befores = this.beforeFns() || [],
afters = this.afterFns() || [],
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
afters = this.afterFns() || [],
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
var allFns = befores.concat(thisOne).concat(afters);
this.queueRunner({
@@ -303,18 +304,18 @@ getJasmineRequireObj().Spec = function(j$) {
});
function onException(e) {
if (Spec.isPendingSpecException(e)) {
self.pend();
return;
}
if (Spec.isPendingSpecException(e)) {
self.pend();
return;
}
self.addExpectationResult(false, {
matcherName: "",
passed: false,
expected: "",
actual: "",
error: e
});
self.addExpectationResult(false, {
matcherName: "",
passed: false,
expected: "",
actual: "",
error: e
});
}
function complete() {
@@ -340,7 +341,7 @@ getJasmineRequireObj().Spec = function(j$) {
return 'disabled';
}
if (this.markedPending || !this.encounteredExpectations) {
if (this.markedPending) {
return 'pending';
}
@@ -375,6 +376,8 @@ getJasmineRequireObj().Env = function(j$) {
var self = this;
var global = options.global || j$.getGlobal();
var totalSpecsDefined = 0;
var catchExceptions = true;
var realSetTimeout = j$.getGlobal().setTimeout;
@@ -385,9 +388,10 @@ getJasmineRequireObj().Env = function(j$) {
var spies = [];
this.currentSpec = null;
var currentSpec = null;
var currentSuite = null;
this.reporter = new j$.ReportDispatcher([
var reporter = new j$.ReportDispatcher([
"jasmineStarted",
"jasmineDone",
"suiteStarted",
@@ -396,14 +400,11 @@ getJasmineRequireObj().Env = function(j$) {
"specDone"
]);
this.lastUpdate = 0;
this.specFilter = function() {
return true;
};
this.nextSpecId_ = 0;
this.nextSuiteId_ = 0;
this.equalityTesters_ = [];
var equalityTesters = [];
var customEqualityTesters = [];
this.addCustomEqualityTester = function(tester) {
@@ -412,6 +413,16 @@ getJasmineRequireObj().Env = function(j$) {
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) {
return j$.Expectation.Factory({
util: j$.matchersUtil,
@@ -426,32 +437,34 @@ getJasmineRequireObj().Env = function(j$) {
};
var specStarted = function(spec) {
self.currentSpec = spec;
self.reporter.specStarted(spec.result);
currentSpec = spec;
reporter.specStarted(spec.result);
};
var beforeFns = function(currentSuite) {
var beforeFns = function(suite) {
return function() {
var befores = [];
for (var suite = currentSuite; suite; suite = suite.parentSuite) {
while(suite) {
befores = befores.concat(suite.beforeFns);
suite = suite.parentSuite;
}
return befores.reverse();
};
};
var afterFns = function(currentSuite) {
var afterFns = function(suite) {
return function() {
var afters = [];
for (var suite = currentSuite; suite; suite = suite.parentSuite) {
while(suite) {
afters = afters.concat(suite.afterFns);
suite = suite.parentSuite;
}
return afters;
};
};
var getSpecName = function(spec, currentSuite) {
return currentSuite.getFullName() + ' ' + spec.description;
var getSpecName = function(spec, suite) {
return suite.getFullName() + ' ' + spec.description;
};
// 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;
};
this.catchException = function(e) {
return j$.Spec.isPendingSpecException(e) || catchExceptions;
};
var maximumSpecCallbackDepth = 20;
var currentSpecCallbackDepth = 0;
@@ -491,19 +500,136 @@ getJasmineRequireObj().Env = function(j$) {
}
}
var queueRunnerFactory = function(options) {
options.catchException = self.catchException;
options.clearStack = options.clearStack || clearStack;
new j$.QueueRunner(options).run(options.fns, 0);
var catchException = function(e) {
return j$.Spec.isPendingSpecException(e) || catchExceptions;
};
var totalSpecsDefined = 0;
this.specFactory = function(description, fn, suite) {
var queueRunnerFactory = function(options) {
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++;
var spec = new j$.Spec({
id: self.nextSpecId(),
id: getNextSpecId(),
beforeFns: beforeFns(suite),
afterFns: afterFns(suite),
expectationFactory: expectationFactory,
@@ -539,193 +665,45 @@ getJasmineRequireObj().Env = function(j$) {
function specResultCallback(result) {
removeAllSpies();
j$.Expectation.resetMatchers();
customEqualityTesters.length = 0;
self.clock.uninstall();
self.currentSpec = null;
self.reporter.specDone(result);
customEqualityTesters = [];
currentSpec = null;
reporter.specDone(result);
}
};
var suiteStarted = function(suite) {
self.reporter.suiteStarted(suite.result);
reporter.suiteStarted(suite.result);
};
var suiteConstructor = j$.Suite;
this.topSuite = new j$.Suite({
env: this,
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.it = function(description, fn) {
var spec = specFactory(description, fn, currentSuite);
currentSuite.addChild(spec);
return spec;
};
this.execute = function(runnablesToRun) {
runnablesToRun = runnablesToRun || [this.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));
}
this.reporter.jasmineStarted({
totalSpecsDefined: totalSpecsDefined
});
queueRunnerFactory({fns: allFns, onComplete: this.reporter.jasmineDone});
this.xit = function(description, fn) {
var spec = this.it(description, fn);
spec.pend();
return spec;
};
this.spyOn = function(obj, methodName) {
if (j$.util.isUndefined(obj)) {
throw new Error("spyOn could not find an object to spy upon for " + methodName + "()");
}
this.expect = function(actual) {
return currentSpec.expect(actual);
};
if (j$.util.isUndefined(obj[methodName])) {
throw new Error(methodName + '() method does not exist');
}
this.beforeEach = function(beforeEachFunction) {
currentSuite.beforeEach(beforeEachFunction);
};
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');
}
this.afterEach = function(afterEachFunction) {
currentSuite.afterEach(afterEachFunction);
};
var spy = j$.createSpy(methodName, obj[methodName]);
spies.push({
spy: spy,
baseObj: obj,
methodName: methodName,
originalValue: obj[methodName]
});
obj[methodName] = spy;
return spy;
this.pending = function() {
throw j$.Spec.pendingSpecExceptionMessage;
};
}
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;
};
@@ -839,6 +817,7 @@ getJasmineRequireObj().Any = function() {
return Any;
};
getJasmineRequireObj().CallTracker = function() {
function CallTracker() {
@@ -905,7 +884,8 @@ getJasmineRequireObj().Clock = function() {
setInterval: setInterval,
clearInterval: clearInterval
},
installed = false;
installed = false,
timer;
self.install = function() {
replace(global, fakeTimingFunctions);
@@ -952,7 +932,7 @@ getJasmineRequireObj().Clock = function() {
if (installed) {
delayedFunctionScheduler.tick(millis);
} 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() {
//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;
}
@@ -1163,12 +1141,21 @@ getJasmineRequireObj().Expectation = function() {
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) {
result.pass = !result.pass;
matcherCompare = matcher.negativeCompare || defaultNegativeCompare;
}
var result = matcherCompare.apply(null, args);
if (!result.pass) {
if (!result.message) {
args.unshift(this.isNot);
@@ -1364,8 +1351,8 @@ getJasmineRequireObj().pp = function(j$) {
PrettyPrinter.prototype.iterateObject = function(obj, fn) {
for (var property in obj) {
if (!obj.hasOwnProperty(property)) continue;
if (property == '__Jasmine_been_here_before__') continue;
if (!obj.hasOwnProperty(property)) { continue; }
if (property == '__Jasmine_been_here_before__') { continue; }
fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) &&
obj.__lookupGetter__(property) !== null) : false);
}
@@ -1522,11 +1509,11 @@ getJasmineRequireObj().ReportDispatcher = function() {
for (var i = 0; i < dispatchedMethods.length; i++) {
var method = dispatchedMethods[i];
this[method] = function(m) {
this[method] = (function(m) {
return function() {
dispatch(m, arguments);
};
}(method);
}(method));
}
var reporters = [];
@@ -1610,7 +1597,6 @@ getJasmineRequireObj().Suite = function() {
this.parentSuite = attrs.parentSuite;
this.description = attrs.description;
this.onStart = attrs.onStart || function() {};
this.completeCallback = attrs.completeCallback || function() {}; // TODO: this is unused
this.resultCallback = attrs.resultCallback || function() {};
this.clearStack = attrs.clearStack || function(fn) {fn();};
@@ -1619,9 +1605,7 @@ getJasmineRequireObj().Suite = function() {
this.queueRunner = attrs.queueRunner || function() {};
this.disabled = false;
this.children_ = []; // TODO: rename
this.suites = []; // TODO: needed?
this.specs = []; // TODO: needed?
this.children = [];
this.result = {
id: this.id,
@@ -1653,19 +1637,8 @@ getJasmineRequireObj().Suite = function() {
this.afterFns.unshift(fn);
};
Suite.prototype.addSpec = function(spec) {
this.children_.push(spec);
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.addChild = function(child) {
this.children.push(child);
};
Suite.prototype.execute = function(onComplete) {
@@ -1675,11 +1648,10 @@ getJasmineRequireObj().Suite = function() {
return;
}
var allFns = [],
children = this.children_;
var allFns = [];
for (var i = 0; i < children.length; i++) {
allFns.push(wrapChildAsAsync(children[i]));
for (var i = 0; i < this.children.length; i++) {
allFns.push(wrapChildAsAsync(this.children[i]));
}
this.onStart(this);
@@ -1701,7 +1673,7 @@ getJasmineRequireObj().Suite = function() {
return function(done) { child.execute(done); };
}
};
return Suite;
};
@@ -1727,6 +1699,7 @@ getJasmineRequireObj().Timer = function() {
return Timer;
};
getJasmineRequireObj().matchersUtil = function(j$) {
// 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) {
for (var i = 0; i < expected.length; i++) {
if (i > 0) message += ",";
if (i > 0) {
message += ",";
}
message += " " + j$.pp(expected[i]);
}
}
@@ -1781,9 +1756,9 @@ getJasmineRequireObj().matchersUtil = function(j$) {
var result = true;
for (var i = 0; i < customTesters.length; i++) {
result = customTesters[i](a, b);
if (result) {
return true;
var customTesterResult = customTesters[i](a, b);
if (!j$.util.isUndefined(customTesterResult)) {
return customTesterResult;
}
}
@@ -1814,11 +1789,11 @@ getJasmineRequireObj().matchersUtil = function(j$) {
// 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).
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`.
if (a === null || b === null) return a === b;
if (a === null || b === null) { return a === b; }
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) {
// Strings, numbers, dates, and booleans are compared by value.
case '[object String]':
@@ -1842,14 +1817,14 @@ getJasmineRequireObj().matchersUtil = function(j$) {
a.multiline == b.multiline &&
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
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
var length = aStack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// 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.
aStack.push(a);
@@ -1863,7 +1838,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
if (result) {
// Deep compare the contents, ignoring non-numeric properties.
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 {
@@ -1880,13 +1855,13 @@ getJasmineRequireObj().matchersUtil = function(j$) {
// Count the expected number of properties.
size++;
// 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.
if (result) {
for (key in b) {
if (has(b, key) && !(size--)) break;
if (has(b, key) && !(size--)) { break; }
}
result = !size;
}
@@ -1906,6 +1881,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
}
}
};
getJasmineRequireObj().toBe = function() {
function toBe() {
return {
@@ -2387,5 +2363,5 @@ getJasmineRequireObj().toThrowError = function(j$) {
};
getJasmineRequireObj().version = function() {
return "2.0.0-rc2";
};
return "2.0.0-rc5";
};

View File

@@ -4,6 +4,6 @@
#
module Jasmine
module Core
VERSION = "2.0.0.rc3"
VERSION = "2.0.0.rc5"
end
end

View File

@@ -1,13 +1,13 @@
{
"name": "jasmine-core",
"license": "MIT",
"version": "2.0.0-rc3",
"version": "2.0.0-rc5",
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-jshint": "~0.2.0",
"grunt-contrib-concat": "~0.1.3",
"grunt-contrib-compass": "~0.1.3",
"grunt-contrib-compress": "~0.4.1",
"shelljs": "~0.1.2"
"grunt-contrib-jshint": "~0.7.0",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-compass": "~0.6.0",
"grunt-contrib-compress": "~0.5.2",
"shelljs": "~0.1.4"
}
}

View File

@@ -135,4 +135,4 @@ _Release Notes generated with [Anchorman](http://github.com/infews/anchorman)_
[travis_jasmine]: http://travis-ci.org/jasmine
[sauce]: http://saucelabs.com
[node_suite]: https://github.com/pivotal/jasmine/blob/master/spec/node_suite.js
[intro]: http://pivotal.github.com/jasmine/
[intro]: http://pivotal.github.com/jasmine/

151
release_notes/20rc3.md Normal file
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
release_notes/20rc5.md Normal file
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)_

View File

@@ -42,4 +42,4 @@ describe("Any", function() {
expect(any.jasmineToString()).toMatch('<jasmine.any');
});
});
});

View File

@@ -341,24 +341,4 @@ describe("Clock (acceptance)", function() {
clock.tick();
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();
});
});

View File

@@ -1,96 +1,149 @@
////TODO: matchers should be add-able to the env, not to the spec.
//describe("Custom Matchers", function() {
// var env;
// var fakeTimer;
//
// beforeEach(function() {
// env = new jasmine.Env();
// env.updateInterval = 0;
// });
//
// it("should be easy to add more matchers local to a spec, suite, etc.", function() {
// var spec1, spec2, spec1Matcher, spec2Matcher;
// var suite = env.describe('some suite', function() {
// env.beforeEach(function() {
// this.addMatchers({
// matcherForSuite: function(expected) {
// this.message = "matcherForSuite: actual: " + this.actual + "; expected: " + expected;
// return true;
// }
// });
// });
//
// spec1 = env.it('spec with an expectation').runs(function () {
// this.addMatchers({
// matcherForSpec: function(expected) {
// this.message = "matcherForSpec: actual: " + this.actual + "; expected: " + expected;
// return true;
// }
// });
// spec1Matcher = this.expect("xxx");
// });
//
// spec2 = env.it('spec with failing expectation').runs(function () {
// spec2Matcher = this.expect("yyy");
// });
// });
//
// suite.execute();
//
// spec1Matcher.matcherForSuite("expected");
// expect(spec1Matcher.message).toEqual("matcherForSuite: actual: xxx; expected: expected");
// spec1Matcher.matcherForSpec("expected");
// expect(spec1Matcher.message).toEqual("matcherForSpec: actual: xxx; expected: expected");
//
// spec2Matcher.matcherForSuite("expected");
// expect(spec2Matcher.message).toEqual("matcherForSuite: actual: yyy; expected: expected");
// expect(spec2Matcher.matcherForSpec).toBe(jasmine.undefined);
// });
//
// it("should generate messages with the same rules as for regular matchers when this.report() is not called", function() {
// var spec;
// var suite = env.describe('some suite', function() {
// spec = env.it('spec with an expectation').runs(function () {
// this.addMatchers({
// toBeTrue: function() {
// return this.actual === true;
// }
// });
// this.expect(true).toBeTrue();
// this.expect(false).toBeTrue();
// });
// });
//
// suite.execute();
//
// var results = spec.results().getItems();
// expect(results[0].message).toEqual("Passed.");
// expect(results[1].message).toEqual("Expected false to be true.");
// });
//
// it("should pass args", function() {
// var matcherCallArgs = [];
// var spec;
// var suite = env.describe('some suite', function() {
// spec = env.it('spec with an expectation').runs(function () {
// this.addMatchers({
// toBeTrue: function() {
// matcherCallArgs.push(jasmine.util.argsToArray(arguments));
// return this.actual === true;
// }
// });
// this.expect(true).toBeTrue();
// this.expect(false).toBeTrue('arg');
// this.expect(true).toBeTrue('arg1', 'arg2');
// });
// });
//
// suite.execute();
// var results = spec.results().getItems();
// expect(results[0].expected).toEqual(jasmine.undefined);
// expect(results[1].expected).toEqual('arg');
// expect(results[2].expected).toEqual(['arg1', 'arg2']);
//
// expect(matcherCallArgs).toEqual([[], ['arg'], ['arg1', 'arg2']]);
// });
//});
describe("Custom Matchers (Integration)", function() {
var env;
var fakeTimer;
beforeEach(function() {
env = new j$.Env();
});
it("allows adding more matchers local to a spec", function(done) {
env.it('spec defining a custom matcher', function() {
env.addMatchers({
matcherForSpec: function() {
return {
compare: function(actual, expected) {
return { pass: false, message: "matcherForSpec: actual: " + actual + "; expected: " + expected };
}
}
}
});
env.expect("zzz").matcherForSpec("yyy");
});
env.it("spec without custom matcher defined", function() {
expect(env.expect("zzz").matcherForSpec).toBeUndefined();
});
var specDoneSpy = jasmine.createSpy("specDoneSpy");
var expectations = function() {
var firstSpecResult = specDoneSpy.calls.first().args[0];
expect(firstSpecResult.status).toEqual("failed");
expect(firstSpecResult.failedExpectations[0].message).toEqual("matcherForSpec: actual: zzz; expected: yyy");
done();
};
env.addReporter({ specDone:specDoneSpy, jasmineDone: expectations});
env.execute();
});
it("passes the spec if the custom matcher passes", function(done) {
env.addMatchers({
toBeReal: function() {
return { compare: function() { return { pass: true }; } };
}
});
env.it("spec using custom matcher", function() {
env.expect(true).toBeReal();
});
var specExpectations = function(result) {
expect(result.status).toEqual('passed');
};
env.addReporter({ specDone: specExpectations, jasmineDone: done });
env.execute();
});
it("uses the negative compare function for a negative comparison, if provided", function(done) {
env.addMatchers({
toBeReal: function() {
return {
compare: function() { return { pass: true }; },
negativeCompare: function() { return { pass: true }; }
};
}
});
env.it("spec with custom negative comparison matcher", function() {
env.expect(true).not.toBeReal();
});
var specExpectations = function(result) {
expect(result.status).toEqual('passed');
}
env.addReporter({ specDone: specExpectations, jasmineDone: done });
env.execute();
});
it("generates messages with the same rules as built in matchers absent a custom message", function(done) {
env.addMatchers({
toBeReal: function() {
return {
compare: function() {
return { pass: false };
}
}
}
});
env.it('spec with an expectation', function() {
env.expect("a").toBeReal();
});
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();
});
});

View File

@@ -3,29 +3,6 @@ describe("Env", function() {
var env;
beforeEach(function() {
env = new j$.Env();
env.updateInterval = 0;
});
describe('ids', function() {
it('nextSpecId should return consecutive integers, starting at 0', function() {
expect(env.nextSpecId()).toEqual('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) {
@@ -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() {
it("throws the Pending Spec exception", 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
@@ -356,6 +324,7 @@ describe("Env integration", function() {
env.clock.install();
env.clock.setTimeout(delayedFunctionForMockClock, 100);
env.clock.tick(100);
env.clock.uninstall();
});
env.it("test without mock clock", function() {
env.clock.setTimeout(delayedFunctionForGlobalClock, 100);
@@ -444,7 +413,6 @@ describe("Env integration", function() {
});
var suiteResult = reporter.suiteStarted.calls.first().args[0];
expect(suiteResult.description).toEqual("A Suite");
expect(reporter.jasmineDone).toHaveBeenCalled();
done();
});

View File

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

View File

@@ -317,4 +317,77 @@ describe("Expectation", function() {
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"
});
});
});

View File

@@ -6,7 +6,6 @@ xdescribe('JsApiReporter (integration specs)', function() {
beforeEach(function() {
env = new j$.Env();
env.updateInterval = 0;
suite = env.describe("top-level suite", function() {
spec1 = env.it("spec 1", function() {

View File

@@ -61,4 +61,4 @@ describe("ObjectContaining", function() {
expect(containing.jasmineToString()).toMatch("<jasmine.objectContaining");
});
});
});

View File

@@ -36,11 +36,20 @@ describe("QueueRunner", function() {
expect(asyncContext).toBe(context);
});
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) {});
describe("with an asynchronous function", function() {
beforeEach(function() {
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'),
fnCallback = jasmine.createSpy('fnCallback'),
afterCallback = jasmine.createSpy('afterCallback'),
@@ -67,29 +76,28 @@ describe("QueueRunner", function() {
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();
expect(fnCallback).not.toHaveBeenCalled();
expect(afterCallback).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
jasmine.clock().tick(100);
clock.tick(100);
expect(fnCallback).toHaveBeenCalled();
expect(afterCallback).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
expect(fnCallback).toHaveBeenCalled();
expect(afterCallback).not.toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
jasmine.clock().tick(100);
clock.tick(100);
expect(afterCallback).toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
expect(afterCallback).toHaveBeenCalled();
expect(onComplete).not.toHaveBeenCalled();
jasmine.clock().tick(100);
clock.tick(100);
expect(onComplete).toHaveBeenCalled();
expect(onComplete).toHaveBeenCalled();
});
});
it("calls an exception handler when an exception is thrown in a fn", function() {

View File

@@ -37,4 +37,4 @@ describe("ReportDispatcher", function() {
dispatcher.foo(123, 456);
}).not.toThrow();
});
});
});

View File

@@ -5,7 +5,6 @@ describe("jasmine spec running", function () {
beforeEach(function() {
env = new j$.Env();
env.updateInterval = 0;
});
it('should assign spec ids sequentially', function() {

View File

@@ -189,18 +189,9 @@ describe("Spec", function() {
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")});
expect(spec.status()).toEqual('pending');
});
it("#status returns pending if no expectations were encountered", function() {
var specBody = jasmine.createSpy("spec body"),
spec = new j$.Spec({fn: specBody});
spec.execute();
expect(spec.status()).toEqual('pending');
expect(spec.status()).toEqual('passed');
});
it("#status returns passed if all expectations in the spec have passed", function() {

View File

@@ -67,54 +67,6 @@ describe("Suite", function() {
expect(suite.afterFns).toEqual([innerAfter, outerAfter]);
});
it("adds specs", function() {
var env = new j$.Env(),
fakeQueue = {
add: jasmine.createSpy()
},
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueFactory: function() {
return fakeQueue
}
}),
fakeSpec = {};
expect(suite.specs.length).toEqual(0);
suite.addSpec(fakeSpec);
expect(suite.specs.length).toEqual(1);
});
it("adds suites", function() {
var env = new j$.Env(),
fakeQueue = {
add: jasmine.createSpy()
},
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueFactory: function() {
return fakeQueue
}
}),
anotherSuite = new j$.Suite({
env: env,
description: "I am another suite",
queueFactory: function() {
return fakeQueue
}
});
expect(suite.suites.length).toEqual(0);
suite.addSuite(anotherSuite);
expect(suite.suites.length).toEqual(1);
});
it("can be disabled", function() {
var env = new j$.Env(),
fakeQueueRunner = jasmine.createSpy('fake queue runner'),
@@ -154,8 +106,8 @@ describe("Suite", function() {
spyOn(suite, "execute");
parentSuite.addSpec(fakeSpec1);
parentSuite.addSuite(suite);
parentSuite.addChild(fakeSpec1);
parentSuite.addChild(suite);
parentSuite.execute(parentSuiteDone);

View File

@@ -153,10 +153,22 @@ describe("matchersUtil", function() {
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() {
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);
});
});

View File

@@ -4,7 +4,7 @@ describe("toThrowError", function() {
expect(function() {
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() {
@@ -15,7 +15,7 @@ describe("toThrowError", function() {
expect(function() {
matcher.compare(fn, 1);
}).toThrow(new Error("Expected is not an Error, string, or RegExp.")); // TODO: this needs to change for self-test
}).toThrowError("Expected is not an Error, string, or RegExp.");
});
it("throws an error when the expected error type is not an Error", function() {
@@ -26,7 +26,7 @@ describe("toThrowError", function() {
expect(function() {
matcher.compare(fn, void 0, "foo");
}).toThrow(new Error("Expected error type is not an Error.")); // TODO: this needs to change for self-test
}).toThrowError("Expected error type is not an Error.");
});
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() {
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() {

View File

@@ -4,7 +4,8 @@ describe("toThrow", function() {
expect(function() {
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() {
@@ -95,4 +96,4 @@ describe("toThrow", function() {
expect(result.pass).toBe(false);
expect(result.message).toEqual("Expected function to throw undefined, but it threw 5.");
});
});
});

View File

@@ -15,4 +15,4 @@ describe("j$.HtmlSpecFilter", function() {
expect(specFilter.matches("foo")).toBe(true);
expect(specFilter.matches("bar")).toBe(false);
});
});
});

View File

@@ -3,7 +3,6 @@ describe("MatchersSpec - HTML Dependent", function () {
beforeEach(function() {
env = new j$.Env();
env.updateInterval = 0;
var suite = env.describe("suite", function() {
spec = env.it("spec", function() {

View File

@@ -40,4 +40,4 @@ describe("QueryString", function() {
expect(queryString.getParam("baz")).toBeFalsy();
});
});
});
});

View File

@@ -59,4 +59,4 @@ describe("ResultsNode", function() {
expect(node.last()).toBe(node.children[node.children.length - 1]);
});
});
});

View File

@@ -6,7 +6,7 @@ var path = require('path');
var jasmineRequire = require('../lib/jasmine-core/jasmine.js');
var jasmine = jasmineRequire.core(jasmineRequire);
var consoleFns = require('../src/console/console.js');
var consoleFns = require('../lib/console/console.js');
extend(jasmineRequire, consoleFns);
jasmineRequire.console(jasmineRequire, jasmine);
@@ -41,20 +41,10 @@ var jasmineInterface = {
return env.expect(actual);
},
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName);
},
clock: env.clock,
setTimeout: env.clock.setTimeout,
clearTimeout: env.clock.clearTimeout,
setInterval: env.clock.setInterval,
clearInterval: env.clock.clearInterval,
jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer()
})
@@ -67,6 +57,18 @@ function extend(destination, source) {
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"
function executeSpecs(specs, done, isVerbose, showColors) {
global.jasmine = jasmine;

View File

@@ -39,15 +39,10 @@
return env.pending();
},
addMatchers: function(matchers) {
return env.addMatchers(matchers);
},
spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName);
},
clock: env.clock,
jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer()
})
@@ -59,6 +54,18 @@
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({
getWindowLocation: function() { return window.location; }
});
@@ -69,7 +76,6 @@
var htmlReporter = new jasmine.HtmlReporter({
env: env,
queryString: queryString,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
@@ -88,6 +94,11 @@
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;
window.onload = function() {

View File

@@ -33,4 +33,4 @@ getJasmineRequireObj().Any = function() {
};
return Any;
};
};

View File

@@ -13,7 +13,8 @@ getJasmineRequireObj().Clock = function() {
setInterval: setInterval,
clearInterval: clearInterval
},
installed = false;
installed = false,
timer;
self.install = function() {
replace(global, fakeTimingFunctions);
@@ -60,7 +61,7 @@ getJasmineRequireObj().Clock = function() {
if (installed) {
delayedFunctionScheduler.tick(millis);
} 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() {
//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;
}

View File

@@ -5,6 +5,8 @@ getJasmineRequireObj().Env = function(j$) {
var self = this;
var global = options.global || j$.getGlobal();
var totalSpecsDefined = 0;
var catchExceptions = true;
var realSetTimeout = j$.getGlobal().setTimeout;
@@ -15,9 +17,10 @@ getJasmineRequireObj().Env = function(j$) {
var spies = [];
this.currentSpec = null;
var currentSpec = null;
var currentSuite = null;
this.reporter = new j$.ReportDispatcher([
var reporter = new j$.ReportDispatcher([
"jasmineStarted",
"jasmineDone",
"suiteStarted",
@@ -26,14 +29,11 @@ getJasmineRequireObj().Env = function(j$) {
"specDone"
]);
this.lastUpdate = 0;
this.specFilter = function() {
return true;
};
this.nextSpecId_ = 0;
this.nextSuiteId_ = 0;
this.equalityTesters_ = [];
var equalityTesters = [];
var customEqualityTesters = [];
this.addCustomEqualityTester = function(tester) {
@@ -42,6 +42,16 @@ getJasmineRequireObj().Env = function(j$) {
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) {
return j$.Expectation.Factory({
util: j$.matchersUtil,
@@ -56,32 +66,34 @@ getJasmineRequireObj().Env = function(j$) {
};
var specStarted = function(spec) {
self.currentSpec = spec;
self.reporter.specStarted(spec.result);
currentSpec = spec;
reporter.specStarted(spec.result);
};
var beforeFns = function(currentSuite) {
var beforeFns = function(suite) {
return function() {
var befores = [];
for (var suite = currentSuite; suite; suite = suite.parentSuite) {
while(suite) {
befores = befores.concat(suite.beforeFns);
suite = suite.parentSuite;
}
return befores.reverse();
};
};
var afterFns = function(currentSuite) {
var afterFns = function(suite) {
return function() {
var afters = [];
for (var suite = currentSuite; suite; suite = suite.parentSuite) {
while(suite) {
afters = afters.concat(suite.afterFns);
suite = suite.parentSuite;
}
return afters;
};
};
var getSpecName = function(spec, currentSuite) {
return currentSuite.getFullName() + ' ' + spec.description;
var getSpecName = function(spec, suite) {
return suite.getFullName() + ' ' + spec.description;
};
// 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;
};
this.catchException = function(e) {
return j$.Spec.isPendingSpecException(e) || catchExceptions;
};
var maximumSpecCallbackDepth = 20;
var currentSpecCallbackDepth = 0;
@@ -121,19 +129,136 @@ getJasmineRequireObj().Env = function(j$) {
}
}
var queueRunnerFactory = function(options) {
options.catchException = self.catchException;
options.clearStack = options.clearStack || clearStack;
new j$.QueueRunner(options).run(options.fns, 0);
var catchException = function(e) {
return j$.Spec.isPendingSpecException(e) || catchExceptions;
};
var totalSpecsDefined = 0;
this.specFactory = function(description, fn, suite) {
var queueRunnerFactory = function(options) {
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++;
var spec = new j$.Spec({
id: self.nextSpecId(),
id: getNextSpecId(),
beforeFns: beforeFns(suite),
afterFns: afterFns(suite),
expectationFactory: expectationFactory,
@@ -169,192 +294,44 @@ getJasmineRequireObj().Env = function(j$) {
function specResultCallback(result) {
removeAllSpies();
j$.Expectation.resetMatchers();
customEqualityTesters.length = 0;
self.clock.uninstall();
self.currentSpec = null;
self.reporter.specDone(result);
customEqualityTesters = [];
currentSpec = null;
reporter.specDone(result);
}
};
var suiteStarted = function(suite) {
self.reporter.suiteStarted(suite.result);
reporter.suiteStarted(suite.result);
};
var suiteConstructor = j$.Suite;
this.topSuite = new j$.Suite({
env: this,
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.it = function(description, fn) {
var spec = specFactory(description, fn, currentSuite);
currentSuite.addChild(spec);
return spec;
};
this.execute = function(runnablesToRun) {
runnablesToRun = runnablesToRun || [this.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));
}
this.reporter.jasmineStarted({
totalSpecsDefined: totalSpecsDefined
});
queueRunnerFactory({fns: allFns, onComplete: this.reporter.jasmineDone});
this.xit = function(description, fn) {
var spec = this.it(description, fn);
spec.pend();
return spec;
};
this.spyOn = function(obj, methodName) {
if (j$.util.isUndefined(obj)) {
throw new Error("spyOn could not find an object to spy upon for " + methodName + "()");
}
this.expect = function(actual) {
return currentSpec.expect(actual);
};
if (j$.util.isUndefined(obj[methodName])) {
throw new Error(methodName + '() method does not exist');
}
this.beforeEach = function(beforeEachFunction) {
currentSuite.beforeEach(beforeEachFunction);
};
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');
}
this.afterEach = function(afterEachFunction) {
currentSuite.afterEach(afterEachFunction);
};
var spy = j$.createSpy(methodName, obj[methodName]);
spies.push({
spy: spy,
baseObj: obj,
methodName: methodName,
originalValue: obj[methodName]
});
obj[methodName] = spy;
return spy;
this.pending = function() {
throw j$.Spec.pendingSpecExceptionMessage;
};
}
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;
};

View File

@@ -22,12 +22,21 @@ getJasmineRequireObj().Expectation = function() {
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) {
result.pass = !result.pass;
matcherCompare = matcher.negativeCompare || defaultNegativeCompare;
}
var result = matcherCompare.apply(null, args);
if (!result.pass) {
if (!result.message) {
args.unshift(this.isNot);

View File

@@ -47,8 +47,8 @@ getJasmineRequireObj().pp = function(j$) {
PrettyPrinter.prototype.iterateObject = function(obj, fn) {
for (var property in obj) {
if (!obj.hasOwnProperty(property)) continue;
if (property == '__Jasmine_been_here_before__') continue;
if (!obj.hasOwnProperty(property)) { continue; }
if (property == '__Jasmine_been_here_before__') { continue; }
fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) &&
obj.__lookupGetter__(property) !== null) : false);
}

View File

@@ -5,11 +5,11 @@ getJasmineRequireObj().ReportDispatcher = function() {
for (var i = 0; i < dispatchedMethods.length; i++) {
var method = dispatchedMethods[i];
this[method] = function(m) {
this[method] = (function(m) {
return function() {
dispatch(m, arguments);
};
}(method);
}(method));
}
var reporters = [];

View File

@@ -1,6 +1,5 @@
getJasmineRequireObj().Spec = function(j$) {
function Spec(attrs) {
this.encounteredExpectations = false;
this.expectationFactory = attrs.expectationFactory;
this.resultCallback = attrs.resultCallback || function() {};
this.id = attrs.id;
@@ -26,13 +25,11 @@ getJasmineRequireObj().Spec = function(j$) {
id: this.id,
description: this.description,
fullName: this.getFullName(),
status: this.status(),
failedExpectations: []
};
}
Spec.prototype.addExpectationResult = function(passed, data) {
this.encounteredExpectations = true;
if (passed) {
return;
}
@@ -56,7 +53,7 @@ getJasmineRequireObj().Spec = function(j$) {
function timeoutable(fn) {
return function(done) {
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();
}, j$.DEFAULT_TIMEOUT_INTERVAL]]);
@@ -70,8 +67,8 @@ getJasmineRequireObj().Spec = function(j$) {
}
var befores = this.beforeFns() || [],
afters = this.afterFns() || [],
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
afters = this.afterFns() || [],
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
var allFns = befores.concat(thisOne).concat(afters);
this.queueRunner({
@@ -81,18 +78,18 @@ getJasmineRequireObj().Spec = function(j$) {
});
function onException(e) {
if (Spec.isPendingSpecException(e)) {
self.pend();
return;
}
if (Spec.isPendingSpecException(e)) {
self.pend();
return;
}
self.addExpectationResult(false, {
matcherName: "",
passed: false,
expected: "",
actual: "",
error: e
});
self.addExpectationResult(false, {
matcherName: "",
passed: false,
expected: "",
actual: "",
error: e
});
}
function complete() {
@@ -118,7 +115,7 @@ getJasmineRequireObj().Spec = function(j$) {
return 'disabled';
}
if (this.markedPending || !this.encounteredExpectations) {
if (this.markedPending) {
return 'pending';
}

View File

@@ -5,7 +5,6 @@ getJasmineRequireObj().Suite = function() {
this.parentSuite = attrs.parentSuite;
this.description = attrs.description;
this.onStart = attrs.onStart || function() {};
this.completeCallback = attrs.completeCallback || function() {}; // TODO: this is unused
this.resultCallback = attrs.resultCallback || function() {};
this.clearStack = attrs.clearStack || function(fn) {fn();};
@@ -14,9 +13,7 @@ getJasmineRequireObj().Suite = function() {
this.queueRunner = attrs.queueRunner || function() {};
this.disabled = false;
this.children_ = []; // TODO: rename
this.suites = []; // TODO: needed?
this.specs = []; // TODO: needed?
this.children = [];
this.result = {
id: this.id,
@@ -48,19 +45,8 @@ getJasmineRequireObj().Suite = function() {
this.afterFns.unshift(fn);
};
Suite.prototype.addSpec = function(spec) {
this.children_.push(spec);
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.addChild = function(child) {
this.children.push(child);
};
Suite.prototype.execute = function(onComplete) {
@@ -70,11 +56,10 @@ getJasmineRequireObj().Suite = function() {
return;
}
var allFns = [],
children = this.children_;
var allFns = [];
for (var i = 0; i < children.length; i++) {
allFns.push(wrapChildAsAsync(children[i]));
for (var i = 0; i < this.children.length; i++) {
allFns.push(wrapChildAsAsync(this.children[i]));
}
this.onStart(this);
@@ -96,7 +81,7 @@ getJasmineRequireObj().Suite = function() {
return function(done) { child.execute(done); };
}
};
return Suite;
};

View File

@@ -15,4 +15,4 @@ getJasmineRequireObj().Timer = function() {
}
return Timer;
};
};

View File

@@ -51,18 +51,18 @@ getJasmineRequireObj().base = function(j$) {
j$.createSpy = function(name, originalFn) {
var spyStrategy = new j$.SpyStrategy({
name: name,
fn: originalFn,
getSpy: function() { return spy; }
}),
callTracker = new j$.CallTracker(),
spy = function() {
callTracker.track({
object: this,
args: Array.prototype.slice.apply(arguments)
});
return spyStrategy.exec.apply(this, arguments);
};
name: name,
fn: originalFn,
getSpy: function() { return spy; }
}),
callTracker = new j$.CallTracker(),
spy = function() {
callTracker.track({
object: this,
args: Array.prototype.slice.apply(arguments)
});
return spyStrategy.exec.apply(this, arguments);
};
for (var prop in originalFn) {
if (prop === 'and' || prop === 'calls') {
@@ -83,7 +83,7 @@ getJasmineRequireObj().base = function(j$) {
return false;
}
return putativeSpy.and instanceof j$.SpyStrategy &&
putativeSpy.calls instanceof j$.CallTracker;
putativeSpy.calls instanceof j$.CallTracker;
};
j$.createSpyObj = function(baseName, methodNames) {

View File

@@ -37,7 +37,9 @@ getJasmineRequireObj().matchersUtil = function(j$) {
if (expected.length > 0) {
for (var i = 0; i < expected.length; i++) {
if (i > 0) message += ",";
if (i > 0) {
message += ",";
}
message += " " + j$.pp(expected[i]);
}
}
@@ -52,9 +54,9 @@ getJasmineRequireObj().matchersUtil = function(j$) {
var result = true;
for (var i = 0; i < customTesters.length; i++) {
result = customTesters[i](a, b);
if (result) {
return true;
var customTesterResult = customTesters[i](a, b);
if (!j$.util.isUndefined(customTesterResult)) {
return customTesterResult;
}
}
@@ -85,11 +87,11 @@ getJasmineRequireObj().matchersUtil = function(j$) {
// 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).
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`.
if (a === null || b === null) return a === b;
if (a === null || b === null) { return a === b; }
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) {
// Strings, numbers, dates, and booleans are compared by value.
case '[object String]':
@@ -113,14 +115,14 @@ getJasmineRequireObj().matchersUtil = function(j$) {
a.multiline == b.multiline &&
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
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
var length = aStack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// 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.
aStack.push(a);
@@ -134,7 +136,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
if (result) {
// Deep compare the contents, ignoring non-numeric properties.
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 {
@@ -151,13 +153,13 @@ getJasmineRequireObj().matchersUtil = function(j$) {
// Count the expected number of properties.
size++;
// 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.
if (result) {
for (key in b) {
if (has(b, key) && !(size--)) break;
if (has(b, key) && !(size--)) { break; }
}
result = !size;
}
@@ -176,4 +178,4 @@ getJasmineRequireObj().matchersUtil = function(j$) {
return typeof obj === 'function';
}
}
};
};

View File

@@ -3,14 +3,16 @@ getJasmineRequireObj().util = function() {
var util = {};
util.inherit = function(childClass, parentClass) {
var subclass = function() {
var Subclass = function() {
};
subclass.prototype = parentClass.prototype;
childClass.prototype = new subclass();
Subclass.prototype = parentClass.prototype;
childClass.prototype = new Subclass();
};
util.htmlEscape = function(str) {
if (!str) return str;
if (!str) {
return str;
}
return str.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
@@ -18,7 +20,9 @@ getJasmineRequireObj().util = function() {
util.argsToArray = function(args) {
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;
};

View File

@@ -1,8 +1,8 @@
jasmineRequire.HtmlReporter = function(j$) {
var noopTimer = {
start: function(){},
elapsed: function(){ return 0; }
start: function() {},
elapsed: function() { return 0; }
};
function HtmlReporter(options) {
@@ -73,7 +73,8 @@ jasmineRequire.HtmlReporter = function(j$) {
symbols.appendChild(createDom("li", {
className: result.status,
id: "spec_" + result.id,
title: result.fullName}
title: result.fullName
}
));
if (result.status == "failed") {

View File

@@ -16,4 +16,4 @@ jasmineRequire.ResultsNode = function() {
}
return ResultsNode;
};
};

View File

@@ -3,4 +3,4 @@ jasmineRequire.html = function(j$) {
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
j$.QueryString = jasmineRequire.QueryString();
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
};
};

View File

@@ -1,3 +1,3 @@
getJasmineRequireObj().version = function() {
return "<%= version %>";
};
};

View File

@@ -1,12 +1,14 @@
#!/bin/bash -e
export DISPLAY=:99.0
/etc/init.d/xvfb start
if [ $USE_SAUCE == true ]
then
if [ $TRAVIS_SECURE_ENV_VARS == true ]
then
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
bundle exec rake jasmine:ci

3
travis-docs-script.sh Normal file
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