Compare commits
96 Commits
v2.0.0.rc3
...
v2.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
812b14d000 | ||
|
|
a2a8b5dde2 | ||
|
|
78bed99ba3 | ||
|
|
f9191d7b0d | ||
|
|
83a692d5a8 | ||
|
|
14a8c2ca09 | ||
|
|
b2e8de7bcd | ||
|
|
1d98a23b14 | ||
|
|
16ffd3b3fb | ||
|
|
6bc87ad223 | ||
|
|
555d328cf2 | ||
|
|
c78fba4b13 | ||
|
|
8a6d7828c6 | ||
|
|
c888b0c1b8 | ||
|
|
72e9851217 | ||
|
|
7ee5073921 | ||
|
|
614a18453e | ||
|
|
916f889c01 | ||
|
|
4a7b79ad0d | ||
|
|
775e2ff0a9 | ||
|
|
1b6725ec25 | ||
|
|
952eb59707 | ||
|
|
de6a305b44 | ||
|
|
8513201fa3 | ||
|
|
6e07dccb68 | ||
|
|
fcc50cc6f4 | ||
|
|
9e8466ba2b | ||
|
|
4350045d61 | ||
|
|
666e9c341e | ||
|
|
5830d9f86b | ||
|
|
ea888e4c03 | ||
|
|
c7e3ca6c8a | ||
|
|
06db4a8583 | ||
|
|
a2debf60b6 | ||
|
|
04c7db9259 | ||
|
|
8585ef69a5 | ||
|
|
cb5aea1fcf | ||
|
|
966f76b481 | ||
|
|
40e3020fdc | ||
|
|
69549a6ff3 | ||
|
|
a03fad8911 | ||
|
|
61993cf1fc | ||
|
|
cd9d5284cd | ||
|
|
e346e7dcc1 | ||
|
|
dd8a455f91 | ||
|
|
9e149d1e0f | ||
|
|
797984f173 | ||
|
|
29c5c127e5 | ||
|
|
26581b4c91 | ||
|
|
243ff80196 | ||
|
|
284bb0b608 | ||
|
|
6453ed656b | ||
|
|
a1a948b8df | ||
|
|
7a4876ecfa | ||
|
|
d9ece1f14f | ||
|
|
f1613ce77c | ||
|
|
a3424ea265 | ||
|
|
ab0b2b783c | ||
|
|
d0aff9ed02 | ||
|
|
a309117758 | ||
|
|
0c6e590a93 | ||
|
|
d06da150de | ||
|
|
39d7ebf28e | ||
|
|
5f429fcb37 | ||
|
|
b6eb9a4d5e | ||
|
|
fdb7df812c | ||
|
|
81299860aa | ||
|
|
ca6fa6f711 | ||
|
|
5aaafed4d8 | ||
|
|
c28c124f58 | ||
|
|
f0a1adb61c | ||
|
|
5ff2aecab8 | ||
|
|
8ca8197b4c | ||
|
|
55716723b5 | ||
|
|
3973cc5a71 | ||
|
|
95af58ade6 | ||
|
|
6641d64305 | ||
|
|
7c1fcd7bb5 | ||
|
|
e91d0341a4 | ||
|
|
144ff174f6 | ||
|
|
af4bfa8bc4 | ||
|
|
620e3f5992 | ||
|
|
ea76a30d85 | ||
|
|
adde1b4a5b | ||
|
|
07e7ad2314 | ||
|
|
706180ad01 | ||
|
|
547c9cfde9 | ||
|
|
d3ec12e62a | ||
|
|
749c15fe07 | ||
|
|
7e071547f5 | ||
|
|
6354ee17e5 | ||
|
|
255a50baee | ||
|
|
520a8c85a2 | ||
|
|
6de355544f | ||
|
|
95572fb314 | ||
|
|
ffa6138d75 |
9
.jshintrc
Normal file
9
.jshintrc
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"bitwise": true,
|
||||
"curly": true,
|
||||
"freeze": true,
|
||||
"immed": true,
|
||||
"newcap": true,
|
||||
"trailing": true,
|
||||
"loopfunc": true
|
||||
}
|
||||
23
.travis.yml
23
.travis.yml
@@ -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"
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
2
Gemfile
2
Gemfile
@@ -10,3 +10,5 @@ end
|
||||
gemspec
|
||||
|
||||
gem "jasmine_selenium_runner", :git => 'https://github.com/jasmine/jasmine_selenium_runner.git'
|
||||
|
||||
gem "anchorman"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a> [](https://travis-ci.org/pivotal/jasmine)
|
||||
<a name="README">[Jasmine](http://pivotal.github.com/jasmine/)</a> [](https://travis-ci.org/pivotal/jasmine) [](https://codeclimate.com/repos/5269970a13d6374b6c01d632/feed)
|
||||
|
||||
=======
|
||||
**A JavaScript Testing Framework**
|
||||
|
||||
Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on browsers, DOM, or any JavaScript framework. Thus it's suited for websites, [Node.js](http://nodejs.org) projects, or anywhere that JavaScript can run.
|
||||
|
||||
Documentation & guides live here: [http://pivotal.github.com/jasmine/](http://pivotal.github.com/jasmine/)
|
||||
Documentation & guides live here: [http://jasmine.github.io](http://jasmine.github.io/)
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -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.
|
||||
2
Rakefile
2
Rakefile
@@ -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
BIN
dist/jasmine-standalone-1.3.1.zip
vendored
Normal file
Binary file not shown.
BIN
dist/jasmine-standalone-2.0.0-alpha.zip
vendored
BIN
dist/jasmine-standalone-2.0.0-alpha.zip
vendored
Binary file not shown.
BIN
dist/jasmine-standalone-2.0.0-rc5.zip
vendored
Normal file
BIN
dist/jasmine-standalone-2.0.0-rc5.zip
vendored
Normal file
Binary file not shown.
BIN
dist/jasmine-standalone-2.0.0.zip
vendored
Normal file
BIN
dist/jasmine-standalone-2.0.0.zip
vendored
Normal file
Binary file not shown.
@@ -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/")
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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 = {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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']
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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 |
@@ -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
|
||||
|
||||
@@ -50,10 +50,10 @@ getJasmineRequireObj().ConsoleReporter = function() {
|
||||
failedSpecs = [],
|
||||
pendingCount,
|
||||
ansi = {
|
||||
green: '\033[32m',
|
||||
red: '\033[31m',
|
||||
yellow: '\033[33m',
|
||||
none: '\033[0m'
|
||||
green: '\x1B[32m',
|
||||
red: '\x1B[31m',
|
||||
yellow: '\x1B[33m',
|
||||
none: '\x1B[0m'
|
||||
};
|
||||
|
||||
this.jasmineStarted = function() {
|
||||
@@ -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 & 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;
|
||||
|
||||
@@ -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 & 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;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
beforeEach(function () {
|
||||
jasmine.Expectation.addMatchers({
|
||||
toBePlaying: function () {
|
||||
return {
|
||||
compare: function (actual, expected) {
|
||||
var player = actual;
|
||||
jasmine.addMatchers({
|
||||
toBePlaying: function () {
|
||||
return {
|
||||
compare: function (actual, expected) {
|
||||
var player = actual;
|
||||
|
||||
return {
|
||||
pass: player.currentlyPlayingSong === expected && player.isPlaying
|
||||
}
|
||||
}
|
||||
};
|
||||
return {
|
||||
pass: player.currentlyPlayingSong === expected && player.isPlaying
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,6 @@
|
||||
#
|
||||
module Jasmine
|
||||
module Core
|
||||
VERSION = "2.0.0.rc3"
|
||||
VERSION = "2.0.0"
|
||||
end
|
||||
end
|
||||
|
||||
16
package.json
16
package.json
@@ -1,13 +1,17 @@
|
||||
{
|
||||
"name": "jasmine-core",
|
||||
"license": "MIT",
|
||||
"version": "2.0.0-rc3",
|
||||
"version": "2.0.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pivotal/jasmine.git"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
179
release_notes/20.md
Normal file
179
release_notes/20.md
Normal file
@@ -0,0 +1,179 @@
|
||||
# Jasmine Core 2.0 Release Notes
|
||||
|
||||
## Summary
|
||||
|
||||
These notes are for Jasmine Core 2.0.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
The [`introduction.js`][intro] page covers the current syntax, highlighting the changes. Here are the known 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
|
||||
* Replaced custom matchers for ease of use
|
||||
* Change to `toThrow` matcher
|
||||
* Clock now remains installed when a spec finishes
|
||||
* More Jasmine internal variables/functions have been moved into closures
|
||||
|
||||
### New syntax for asynchronous specs
|
||||
|
||||
Similar to [Mocha][mocha], Jasmine `before`s, `spec`s, and `after`s 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 until a timeout is reached.
|
||||
|
||||
### New syntax for spies
|
||||
|
||||
Spies have a slightly modified syntax. The idea 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 been **replaced**. 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 the Jasmine implementation. The Jasmine reporter API now includes a slot for a `timer` object.
|
||||
|
||||
### Better Equality testing
|
||||
|
||||
We removed 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.
|
||||
|
||||
### Replaced custom matchers for ease of use
|
||||
|
||||
The interface for adding custom matchers has been **replaced**. It has always been possible to add custom matchers, but the API was barely documented and difficult to test. We've changed how matchers are added and tested. Jasmine adds its own matchers by the same mechanism that 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 now remains installed when a spec finishes
|
||||
|
||||
After installing the Jasmine Clock, it will stay installed until `uninstall` is called -- clearing up any ambiguity for when those timing functions will revert to using the global clock object.
|
||||
|
||||
## 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 and Build moved to Grunt
|
||||
* Changes to how Jasmine is loaded
|
||||
* Changes to 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 merged objects together and factored out code. We styled the code more consistently. We've improved nearly every test.
|
||||
|
||||
In general, Jasmine is made of smaller, more-loosely-coupled objects, unit-tested with explicit dependencies injected. This made tests easier to read, write, 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 its own `devboot.js` to load itself twice - once from `jasmine.js` and once from the source directories.
|
||||
|
||||
## Development and Build moved to Grunt
|
||||
|
||||
We've moved away from Ruby and embraced [Node.js][node] 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 browsers and in Node.js before submitting Pull Requests. There is more detail in the [Contributor's Guide][contrib].
|
||||
|
||||
## Changes to 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 which add files - please be careful in these cases. Again, the [Contributor's Guide][contrib] should help.
|
||||
|
||||
## Changes to 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][phantom], [Node.js][node], 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][jasmine_downloads] remains for projects that need to support older 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 and 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
|
||||
* Replaced deprecated octal literal with hexadecimal from kris7t
|
||||
* Make getGlobal() work in strict mode from metaweta
|
||||
* Clears timeout timer even when async spec throws an exception from tidoust
|
||||
* Timeouts scheduled within a delayed function are correctly scheduled and executed from maciej-filip-sz
|
||||
|
||||
### Bug Fixes
|
||||
* 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 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`
|
||||
* 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
|
||||
* Make all async functions be subject to the timeout
|
||||
|
||||
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 and 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`
|
||||
|
||||
[mocha]: http://visionmedia.github.io/mocha/
|
||||
[underscore]: http://underscorejs.org/
|
||||
[grunt]: http://gruntjs.com
|
||||
[node]: http://nodejs.org
|
||||
[phantom]: http://phantomjs.org
|
||||
[jasmine_downloads]: https://github.com/pivotal/jasmine/downloads
|
||||
[contrib]: https://github.com/pivotal/jasmine/blob/master/CONTRIBUTING.md
|
||||
[travis]: http://travis-ci.org
|
||||
[travis_jasmine]: http://travis-ci.org/jasmine
|
||||
[sauce]: http://saucelabs.com
|
||||
[node_suite]: https://github.com/pivotal/jasmine/blob/master/spec/node_suite.js
|
||||
[intro]: http://jasmine.github.io/2.0/introduction.html
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with [Anchorman](http://github.com/infews/anchorman)_
|
||||
@@ -1,138 +0,0 @@
|
||||
# Jasmine Core 2.0 Release Notes
|
||||
|
||||
## Summary
|
||||
|
||||
These notes are for RC1 of Jasmine Core 2.0.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
These changes have breaking interface changes and are not backwards compatible with 1.x.
|
||||
|
||||
* New syntax for asynchronous specs
|
||||
* New syntax for spies
|
||||
* New interface for reporters
|
||||
* Better Equality testing
|
||||
* Easier custom matchers
|
||||
* Change to `toThrow` matcher
|
||||
|
||||
### New syntax for asynchronous specs
|
||||
|
||||
Similar to [Mocha][mocha], Jasmine befores, specs, and afters can take an optional "done" callback in order to force asynchronous tests. The next function, whether it's a before, spec or after, will wait until this function is called or if a timeout is reached.
|
||||
|
||||
### New syntax for spies
|
||||
|
||||
Spies have a slightly modified syntax. The ideas came from a desire to preserve any of the properties on a spied-upon function and some better testing patterns.
|
||||
|
||||
### New interface for reporters
|
||||
|
||||
The reporter interface has changed. The callbacks are different and more consistent. The objects passed in should only provide what is needed to report results. This enforces an interface to result data so custom reporters will be less coupled to Jasmine implementation. The full suite execution time is also reported.
|
||||
|
||||
### Better Equality testing
|
||||
|
||||
We have tossed the previous equality code and are now using new code for testing equality. We started with [Underscore.js][underscore]'s `isEqual`, refactored a bit and added some additional tests.
|
||||
|
||||
### Easier custom matchers
|
||||
|
||||
Custom matchers have always been possible, but this was barely documented and clunky to test. We've changed how matchers are added and tested. Jasmine adds its own matchers by the same mechanism that as custom matchers use. Dogfooding FTW.
|
||||
|
||||
### Change to `toThrow` matcher
|
||||
|
||||
We've changed the behavior of the `toThrow` matcher, moving some functionality to the `toThrowError` matcher. This should allow more of the requested use cases.
|
||||
|
||||
## Other Changes
|
||||
|
||||
* Massive refactoring and better testing
|
||||
* Environment setup now in `boot.js`
|
||||
* Development & Build moved to Grunt
|
||||
* Change in how Jasmine is loaded
|
||||
* Change in how Jasmine is tested
|
||||
* Better node.js support
|
||||
* Better Continuous Integration Environment at Travis
|
||||
* Support matrix updated
|
||||
* Removed JsDoc Pages
|
||||
|
||||
## Massive refactoring and better testing
|
||||
|
||||
This is the biggest set of changes. We've touched nearly every file and every object. We've slammed objects back together and pulled out new extractions. We've made the code more consistently styled. We've improved the tests nearly everywhere.
|
||||
|
||||
In general, Jasmine is made of smaller, more-loosely-coupled objects, unit-tested with explicit dependencies injected. This made tests easier to write, read, and maintain. We know this has made Jasmine development easier for the core team. We expect (and hope) this makes it easier for the community to extend Jasmine and provide pull requests that make more sense the first time out.
|
||||
|
||||
## Environment setup now in `boot.js`
|
||||
|
||||
Instantiation and setup of the Jasmine environment, including building reporters, exposing the "global" functions, and executing tests has moved into its own file: `boot.js`. This should make it easier to add custom reporters, configure some objects, or just in general change how you use Jasmine from the outside.
|
||||
|
||||
For example, during development, Jasmine uses it's own `devboot.js` to load itself twice - once from `jasmine.js` and once from the source directories.
|
||||
|
||||
## Development & Build moved to Grunt
|
||||
|
||||
We've moved away from Ruby and embraced Node.js and [Grunt.js][grunt] for the various command line tasks during development. Yes, it's a just a different set of dependencies. But it's less code for the team to maintain - it turns out that JavaScript tools are pretty good at building JavaScript projects. This will make it easier for the community to make sure contributions work in browser and in Node.js before submitting Pull Requests. There is more detail in the [Contributor's Guide][contrib].
|
||||
|
||||
## Change in how Jasmine is loaded
|
||||
|
||||
We did not want to add new run-time dependencies, yet we needed to be cleaner when loading Jasmine. So we wrote a custom "require" scheme that works in Node.js and in browsers. This only affects pull requests that add files - please be careful in these cases. Again, the [Contributor's Guide][contrib] should help.
|
||||
|
||||
## Change in how Jasmine is tested with Jasmine
|
||||
|
||||
Writing a custom require system helped enforce self-testing - the built `jasmine.js` testing Jasmine from the source directories. Overall this has improved the stability of the code. When you look at Jasmine's tests, you'll see both `jasmine` and `j$` used. The former, `jasmine`, will always be used to test the code from source, which is loaded into the reference `j$`. Please adhere to this pattern when writing tests for contributions.
|
||||
|
||||
## Better node.js support
|
||||
|
||||
Node.js is now officially a first-class citizen. For a long time we've made sure tests were green in Node before releasing. But it is now officially part of Jasmine's CI build at [Travis][travis]. For the curious, the [`node_suite.js`][node_suite], is essentially a `boot.js` for Node. An official npm is coming.
|
||||
|
||||
## Better Continuous Integration Environment at Travis
|
||||
|
||||
The [CI build at Travis][travis_jasmine] now runs the core specs in a build matrix across browsers. It's far from complete on the operating system matrix, but you will see that Jasmine runs against: Firefox, Chrome, Safari 5, Safari 6, Phantom.js, Node.js, and IE versions 8, 9, and 10. Big thanks to [SauceLabs][sauce] for their support of open source projects. We will happily take pull requests for additional OS/Browser combos within the matrix.
|
||||
|
||||
## Support Matrix Updated
|
||||
|
||||
We're dropping support for IE < 8. Jasmine 1.x remains for projects supporting earlier versions of browsers.
|
||||
|
||||
## Removed JsDoc Pages
|
||||
|
||||
Comments in code are lies waiting to happen. Jasmine's JsDoc comments were no exception. The comments were out of date, the generated pages were even more out of date, and frankly they were not helpful. So they're gone.
|
||||
|
||||
Last year saw the posting of the [`introduction.js`][intro] page to document the real, practical interface for projects to use. This page has received a lot of positive feedback so expect more pages like this one.
|
||||
|
||||
## Pull Requests & Issues
|
||||
|
||||
The following Pull Requests were merged:
|
||||
|
||||
* ObjectContaining wrong filed value error message #[394](https://github.com/pivotal/jasmine/issues/394) from albertandrejev
|
||||
* Removed unnecessary parameter from `suiteFactory()` call #[397](https://github.com/pivotal/jasmine/issues/397) from valera-rozuvan
|
||||
* `jasmine.Any` supports `Boolean` #[392](https://github.com/pivotal/jasmine/issues/392) from albertandrejev
|
||||
* Reporters get execution time #[30](https://github.com/pivotal/jasmine/issues/30)
|
||||
* `toThrow` matchers handle falsy exceptions #[317](https://github.com/pivotal/jasmine/issues/371)
|
||||
* Removed deprecated `jasmine.Matchers.pp` #[363](https://github.com/pivotal/jasmine/issues/363) from robinboehm
|
||||
* Fix for Clock ticking to default to 0 #[340](https://github.com/pivotal/jasmine/issues/340) from Caio Cunha
|
||||
* Whitespace failures should be easier to understand #[332](https://github.com/pivotal/jasmine/issues/332) from bjornblomqvist
|
||||
* Fix for more markdown-y image for Build status #[329](https://github.com/pivotal/jasmine/issues/329) from sunliwen
|
||||
* UTF-8 encoding fixes #[333](https://github.com/pivotal/jasmine/issues/333) from bjornblomqvist
|
||||
|
||||
There were several other pull requests that either had already been fixed, or were good starting points for the various changes above. Thank you for all of the hard work to keep Jasmine awesome.
|
||||
|
||||
## Other Bugs & Features
|
||||
|
||||
There were a few small changes and fixes that didn't fit into any of the above categories:
|
||||
|
||||
* HTML Reporter refactored for simplicity and performance
|
||||
* Default character encoding on the HTML runner page is UTF-8
|
||||
* [Escape special regex characters from the spec param](http://www.pivotaltracker.com/story/52731407)
|
||||
* Favicon returns
|
||||
* [Clock supports `eval`'d strings as functions](http://www.pivotaltracker.com/story/40853563)
|
||||
* There should always be stack traces on failures
|
||||
* Removed references to unused `jasmine.VERBOSE`
|
||||
* Removed references to unused `jasmine.XmlHttpRequest`
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with [Anchorman](http://github.com/infews/anchorman)_
|
||||
|
||||
[mocha]: http://visionmedia.github.io/mocha/
|
||||
[underscore]: http://underscorejs.org/
|
||||
[grunt]: http://gruntjs.com
|
||||
[contrib]: https://github.com/pivotal/jasmine/blob/master/Contribute.markdown
|
||||
[travis]: http://travis-ci.org
|
||||
[travis_jasmine]: http://travis-ci.org/jasmine
|
||||
[sauce]: http://saucelabs.com
|
||||
[node_suite]: https://github.com/pivotal/jasmine/blob/master/spec/node_suite.js
|
||||
[intro]: http://pivotal.github.com/jasmine/
|
||||
@@ -80,7 +80,7 @@ describe("ConsoleReporter", function() {
|
||||
expect(out.getOutput()).toEqual("*");
|
||||
});
|
||||
|
||||
it("reports a summary when done (singluar spec and time)", function() {
|
||||
it("reports a summary when done (singular spec and time)", function() {
|
||||
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
|
||||
reporter = new j$.ConsoleReporter({
|
||||
print: out.print,
|
||||
@@ -198,7 +198,7 @@ describe("ConsoleReporter", function() {
|
||||
|
||||
reporter.specDone({status: "passed"});
|
||||
|
||||
expect(out.getOutput()).toEqual("\033[32m.\033[0m");
|
||||
expect(out.getOutput()).toEqual("\x1B[32m.\x1B[0m");
|
||||
});
|
||||
|
||||
it("does not report a disabled spec", function() {
|
||||
@@ -220,7 +220,7 @@ describe("ConsoleReporter", function() {
|
||||
|
||||
reporter.specDone({status: 'failed'});
|
||||
|
||||
expect(out.getOutput()).toEqual("\033[31mF\033[0m");
|
||||
expect(out.getOutput()).toEqual("\x1B[31mF\x1B[0m");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -42,4 +42,4 @@ describe("Any", function() {
|
||||
expect(any.jasmineToString()).toMatch('<jasmine.any');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -342,23 +342,18 @@ describe("Clock (acceptance)", function() {
|
||||
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);
|
||||
it("correctly calls functions scheduled while the Clock is advancing", function() {
|
||||
var delayedFn1 = jasmine.createSpy('delayedFn1'),
|
||||
delayedFn2 = jasmine.createSpy('delayedFn2'),
|
||||
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
|
||||
clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler);
|
||||
|
||||
expect(function() {
|
||||
clock.clearTimeout(123)
|
||||
}).not.toThrow();
|
||||
});
|
||||
delayedFn1.and.callFake(function() { clock.setTimeout(delayedFn2, 1); });
|
||||
clock.install();
|
||||
clock.setTimeout(delayedFn1, 5);
|
||||
|
||||
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();
|
||||
clock.tick(6);
|
||||
expect(delayedFn1).toHaveBeenCalled();
|
||||
expect(delayedFn2).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
////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']]);
|
||||
// });
|
||||
//});
|
||||
@@ -175,5 +175,72 @@ describe("DelayedFunctionScheduler", function() {
|
||||
expect(fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("schedules a function for later execution during a tick", function () {
|
||||
var scheduler = new j$.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn'),
|
||||
fnDelay = 10;
|
||||
|
||||
scheduler.scheduleFunction(function () {
|
||||
scheduler.scheduleFunction(fn, fnDelay);
|
||||
}, 0);
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
scheduler.tick(fnDelay);
|
||||
|
||||
expect(fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("#removeFunctionWithId removes a previously scheduled function with a given id during a tick", function () {
|
||||
var scheduler = new j$.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn'),
|
||||
fnDelay = 10,
|
||||
timeoutKey;
|
||||
|
||||
scheduler.scheduleFunction(function () {
|
||||
scheduler.removeFunctionWithId(timeoutKey);
|
||||
}, 0);
|
||||
timeoutKey = scheduler.scheduleFunction(fn, fnDelay);
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
scheduler.tick(fnDelay);
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("executes recurring functions interleaved with regular functions and functions scheduled during a tick in the correct order", function () {
|
||||
var scheduler = new j$.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn'),
|
||||
recurringCallCount = 0,
|
||||
recurring = jasmine.createSpy('recurring').and.callFake(function() {
|
||||
recurringCallCount++;
|
||||
if (recurringCallCount < 5) {
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
}
|
||||
}),
|
||||
innerFn = jasmine.createSpy('innerFn').and.callFake(function() {
|
||||
expect(recurring.calls.count()).toBe(4);
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
}),
|
||||
scheduling = jasmine.createSpy('scheduling').and.callFake(function() {
|
||||
expect(recurring.calls.count()).toBe(3);
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
scheduler.scheduleFunction(innerFn, 10); // 41ms absolute
|
||||
});
|
||||
|
||||
scheduler.scheduleFunction(recurring, 10, [], true);
|
||||
scheduler.scheduleFunction(fn, 50);
|
||||
scheduler.scheduleFunction(scheduling, 31);
|
||||
|
||||
scheduler.tick(60);
|
||||
|
||||
expect(recurring).toHaveBeenCalled();
|
||||
expect(recurring.calls.count()).toBe(6);
|
||||
expect(fn).toHaveBeenCalled();
|
||||
expect(scheduling).toHaveBeenCalled();
|
||||
expect(innerFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -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) {
|
||||
@@ -56,13 +33,13 @@ describe("Env", function() {
|
||||
});
|
||||
|
||||
describe("#spyOn", function() {
|
||||
it("checks for the existance of the object", function() {
|
||||
it("checks for the existence of the object", function() {
|
||||
expect(function() {
|
||||
env.spyOn(void 0, 'pants');
|
||||
}).toThrowError(/could not find an object/);
|
||||
});
|
||||
|
||||
it("checks for the existance of the method", function() {
|
||||
it("checks for the existence of the method", function() {
|
||||
var subject = {};
|
||||
|
||||
expect(function() {
|
||||
@@ -84,41 +61,9 @@ describe("Env", function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var subject = { spiedFunc: function() { originalFunctionWasCalled = true; } };
|
||||
|
||||
originalFunc = subject.spiedFunc;
|
||||
|
||||
var spy = env.spyOn(subject, 'spiedFunc');
|
||||
|
||||
expect(subject.spiedFunc).toEqual(spy);
|
||||
|
||||
expect(subject.spiedFunc.calls.any()).toEqual(false);
|
||||
expect(subject.spiedFunc.calls.count()).toEqual(0);
|
||||
|
||||
subject.spiedFunc('foo');
|
||||
|
||||
expect(subject.spiedFunc.calls.any()).toEqual(true);
|
||||
expect(subject.spiedFunc.calls.count()).toEqual(1);
|
||||
expect(subject.spiedFunc.calls.mostRecent().args).toEqual(['foo']);
|
||||
expect(subject.spiedFunc.calls.mostRecent().object).toEqual(subject);
|
||||
expect(originalFunctionWasCalled).toEqual(false);
|
||||
|
||||
subject.spiedFunc('bar');
|
||||
expect(subject.spiedFunc.calls.count()).toEqual(2);
|
||||
expect(subject.spiedFunc.calls.mostRecent().args).toEqual(['bar']);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#catchException", function() {
|
||||
it("returns true if the exception is a pending spec exception", function() {
|
||||
env.catchExceptions(false);
|
||||
|
||||
expect(env.catchException(new Error(j$.Spec.pendingSpecExceptionMessage))).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false if the exception is not a pending spec exception and not catching exceptions", function() {
|
||||
env.catchExceptions(false);
|
||||
|
||||
expect(env.catchException(new Error("external error"))).toBe(false);
|
||||
expect(env.catchException(new Error(j$.Spec.pendingSpecExceptionMessage))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -130,467 +75,11 @@ 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
|
||||
describe("Env integration", function() {
|
||||
|
||||
it("Suites execute as expected (no nesting)", function(done) {
|
||||
var env = new j$.Env(),
|
||||
calls = [];
|
||||
|
||||
var assertions = function() {
|
||||
expect(calls).toEqual([
|
||||
"with a spec",
|
||||
"and another spec"
|
||||
]);
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions});
|
||||
|
||||
env.describe("A Suite", function() {
|
||||
env.it("with a spec", function() {
|
||||
calls.push("with a spec");
|
||||
});
|
||||
env.it("and another spec", function() {
|
||||
calls.push("and another spec");
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Nested Suites execute as expected", function(done) {
|
||||
var env = new j$.Env(),
|
||||
calls = [];
|
||||
|
||||
var assertions = function() {
|
||||
expect(calls).toEqual([
|
||||
'an outer spec',
|
||||
'an inner spec',
|
||||
'another inner spec'
|
||||
]);
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions });
|
||||
|
||||
env.describe("Outer suite", function() {
|
||||
env.it("an outer spec", function() {
|
||||
calls.push('an outer spec')
|
||||
});
|
||||
env.describe("Inner suite", function() {
|
||||
env.it("an inner spec", function() {
|
||||
calls.push('an inner spec');
|
||||
});
|
||||
env.it("another inner spec", function() {
|
||||
calls.push('another inner spec');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Multiple top-level Suites execute as expected", function(done) {
|
||||
var env = new j$.Env(),
|
||||
calls = [];
|
||||
|
||||
var assertions = function() {
|
||||
expect(calls).toEqual([
|
||||
'an outer spec',
|
||||
'an inner spec',
|
||||
'another inner spec',
|
||||
'a 2nd outer spec'
|
||||
]);
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions });
|
||||
|
||||
|
||||
env.describe("Outer suite", function() {
|
||||
env.it("an outer spec", function() {
|
||||
calls.push('an outer spec')
|
||||
});
|
||||
env.describe("Inner suite", function() {
|
||||
env.it("an inner spec", function() {
|
||||
calls.push('an inner spec');
|
||||
});
|
||||
env.it("another inner spec", function() {
|
||||
calls.push('another inner spec');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.describe("Another outer suite", function() {
|
||||
env.it("a 2nd outer spec", function() {
|
||||
calls.push('a 2nd outer spec')
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("calls associated befores/specs/afters with the same 'this'", function(done) {
|
||||
var env = new j$.Env();
|
||||
|
||||
env.addReporter({jasmineDone: done});
|
||||
|
||||
env.describe("tests", function() {
|
||||
var firstTimeThrough = true, firstSpecContext, secondSpecContext;
|
||||
|
||||
env.beforeEach(function() {
|
||||
if (firstTimeThrough) {
|
||||
firstSpecContext = this;
|
||||
} else {
|
||||
secondSpecContext = this;
|
||||
}
|
||||
expect(this).toEqual({});
|
||||
});
|
||||
|
||||
env.it("sync spec", function() {
|
||||
expect(this).toBe(firstSpecContext);
|
||||
});
|
||||
|
||||
env.it("another sync spec", function() {
|
||||
expect(this).toBe(secondSpecContext);
|
||||
});
|
||||
|
||||
env.afterEach(function() {
|
||||
if (firstTimeThrough) {
|
||||
expect(this).toBe(firstSpecContext);
|
||||
firstTimeThrough = false;
|
||||
} else {
|
||||
expect(this).toBe(secondSpecContext);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("calls associated befores/its/afters with the same 'this' for an async spec", function(done) {
|
||||
var env = new j$.Env();
|
||||
|
||||
env.addReporter({jasmineDone: done});
|
||||
|
||||
env.describe("with an async spec", function() {
|
||||
var specContext;
|
||||
|
||||
env.beforeEach(function() {
|
||||
specContext = this;
|
||||
expect(this).toEqual({});
|
||||
});
|
||||
|
||||
env.it("sync spec", function(underTestCallback) {
|
||||
expect(this).toBe(specContext);
|
||||
underTestCallback();
|
||||
});
|
||||
|
||||
env.afterEach(function() {
|
||||
expect(this).toBe(specContext);
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Allows specifying which specs and suites to run", function(done) {
|
||||
var env = new j$.Env(),
|
||||
calls = [],
|
||||
suiteCallback = jasmine.createSpy('suite callback'),
|
||||
firstSpec,
|
||||
secondSuite;
|
||||
|
||||
var assertions = function() {
|
||||
expect(calls).toEqual([
|
||||
'third spec',
|
||||
'first spec'
|
||||
]);
|
||||
expect(suiteCallback).toHaveBeenCalled();
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({jasmineDone: assertions, suiteDone: suiteCallback});
|
||||
|
||||
env.describe("first suite", function() {
|
||||
firstSpec = env.it("first spec", function() {
|
||||
calls.push('first spec');
|
||||
});
|
||||
env.it("second spec", function() {
|
||||
calls.push('second spec');
|
||||
});
|
||||
});
|
||||
|
||||
secondSuite = env.describe("second suite", function() {
|
||||
env.it("third spec", function() {
|
||||
calls.push('third spec');
|
||||
});
|
||||
});
|
||||
|
||||
env.execute([secondSuite.id, firstSpec.id]);
|
||||
});
|
||||
|
||||
it("Mock clock can be installed and used in tests", function(done) {
|
||||
var globalSetTimeout = jasmine.createSpy('globalSetTimeout'),
|
||||
delayedFunctionForGlobalClock = jasmine.createSpy('delayedFunctionForGlobalClock'),
|
||||
delayedFunctionForMockClock = jasmine.createSpy('delayedFunctionForMockClock'),
|
||||
env = new j$.Env({global: { setTimeout: globalSetTimeout }});
|
||||
|
||||
var assertions = function() {
|
||||
expect(delayedFunctionForMockClock).toHaveBeenCalled();
|
||||
expect(globalSetTimeout).toHaveBeenCalledWith(delayedFunctionForGlobalClock, 100);
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions });
|
||||
|
||||
env.describe("tests", function() {
|
||||
env.it("test with mock clock", function() {
|
||||
env.clock.install();
|
||||
env.clock.setTimeout(delayedFunctionForMockClock, 100);
|
||||
env.clock.tick(100);
|
||||
});
|
||||
env.it("test without mock clock", function() {
|
||||
env.clock.setTimeout(delayedFunctionForGlobalClock, 100);
|
||||
});
|
||||
});
|
||||
|
||||
expect(globalSetTimeout).not.toHaveBeenCalled();
|
||||
expect(delayedFunctionForMockClock).not.toHaveBeenCalled();
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("should run async specs in order, waiting for them to complete", function(done) {
|
||||
var env = new j$.Env(), mutatedVar;
|
||||
|
||||
env.describe("tests", function() {
|
||||
env.beforeEach(function() {
|
||||
mutatedVar = 2;
|
||||
});
|
||||
|
||||
env.it("async spec", function(underTestCallback) {
|
||||
setTimeout(function() {
|
||||
expect(mutatedVar).toEqual(2);
|
||||
underTestCallback();
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
env.it("after async spec", function() {
|
||||
mutatedVar = 3;
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
describe("with a mock clock", function() {
|
||||
var originalTimeout;
|
||||
|
||||
beforeEach(function() {
|
||||
originalTimeout = j$.DEFAULT_TIMEOUT_INTERVAL;
|
||||
jasmine.getEnv().clock.install();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
jasmine.getEnv().clock.uninstall();
|
||||
j$.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
|
||||
});
|
||||
|
||||
it("should wait a specified interval before failing specs haven't called done yet", function(done) {
|
||||
var env = new j$.Env(),
|
||||
reporter = jasmine.createSpyObj('fakeReporter', [ "specDone" ]);
|
||||
|
||||
reporter.specDone.and.callFake(function() {
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({status: 'failed'}));
|
||||
done();
|
||||
});
|
||||
|
||||
env.addReporter(reporter);
|
||||
j$.DEFAULT_TIMEOUT_INTERVAL = 8414;
|
||||
|
||||
env.it("async spec that doesn't call done", function(underTestCallback) {
|
||||
env.expect(true).toBeTruthy();
|
||||
jasmine.getEnv().clock.tick(8414);
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: something is wrong with this spec
|
||||
it("should report as expected", function(done) {
|
||||
var env = new j$.Env(),
|
||||
reporter = jasmine.createSpyObj('fakeReporter', [
|
||||
"jasmineStarted",
|
||||
"jasmineDone",
|
||||
"suiteStarted",
|
||||
"suiteDone",
|
||||
"specStarted",
|
||||
"specDone"
|
||||
]);
|
||||
|
||||
reporter.jasmineDone.and.callFake(function() {
|
||||
expect(reporter.jasmineStarted).toHaveBeenCalledWith({
|
||||
totalSpecsDefined: 3
|
||||
});
|
||||
var suiteResult = reporter.suiteStarted.calls.first().args[0];
|
||||
expect(suiteResult.description).toEqual("A Suite");
|
||||
expect(reporter.jasmineDone).toHaveBeenCalled();
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.describe("A Suite", function() {
|
||||
env.it("with a top level spec", function() {
|
||||
env.expect(true).toBe(true);
|
||||
});
|
||||
env.describe("with a nested suite", function() {
|
||||
env.xit("with a pending spec", function() {
|
||||
env.expect(true).toBe(true);
|
||||
});
|
||||
env.it("with a spec", function() {
|
||||
env.expect(true).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("should be possible to get full name from a spec", function() {
|
||||
var env = new j$.Env({global: { setTimeout: setTimeout }}),
|
||||
topLevelSpec, nestedSpec, doublyNestedSpec;
|
||||
|
||||
env.describe("my tests", function() {
|
||||
topLevelSpec = env.it("are sometimes top level", function() {
|
||||
});
|
||||
env.describe("are sometimes", function() {
|
||||
nestedSpec = env.it("singly nested", function() {
|
||||
});
|
||||
env.describe("even", function() {
|
||||
doublyNestedSpec = env.it("doubly nested", function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
expect(topLevelSpec.getFullName()).toBe("my tests are sometimes top level");
|
||||
expect(nestedSpec.getFullName()).toBe("my tests are sometimes singly nested");
|
||||
expect(doublyNestedSpec.getFullName()).toBe("my tests are sometimes even doubly nested");
|
||||
});
|
||||
|
||||
it("Custom equality testers should be per spec", function(done) {
|
||||
var env = new j$.Env({global: { setTimeout: setTimeout }}),
|
||||
reporter = jasmine.createSpyObj('fakeReproter', [
|
||||
"jasmineStarted",
|
||||
"jasmineDone",
|
||||
"suiteStarted",
|
||||
"suiteDone",
|
||||
"specStarted",
|
||||
"specDone"
|
||||
]);
|
||||
|
||||
reporter.jasmineDone.and.callFake(function() {
|
||||
var firstSpecResult = reporter.specDone.calls.first().args[0],
|
||||
secondSpecResult = reporter.specDone.calls.mostRecent().args[0];
|
||||
|
||||
expect(firstSpecResult.status).toEqual("passed");
|
||||
expect(secondSpecResult.status).toEqual("failed");
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.describe("testing custom equality testers", function() {
|
||||
env.it("with a custom tester", function() {
|
||||
env.addCustomEqualityTester(function(a, b) { return true; });
|
||||
env.expect("a").toEqual("b");
|
||||
});
|
||||
|
||||
env.it("without a custom tester", function() {
|
||||
env.expect("a").toEqual("b");
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Custom matchers should be per spec", function() {
|
||||
var env = new j$.Env({global: { setTimeout: setTimeout }}),
|
||||
matchers = {
|
||||
toFoo: function() {}
|
||||
},
|
||||
reporter = jasmine.createSpyObj('fakeReproter', [
|
||||
"jasmineStarted",
|
||||
"jasmineDone",
|
||||
"suiteStarted",
|
||||
"suiteDone",
|
||||
"specStarted",
|
||||
"specDone"
|
||||
]);
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.describe("testing custom matchers", function() {
|
||||
env.it("with a custom matcher", function() {
|
||||
env.addMatchers(matchers);
|
||||
expect(env.expect().toFoo).toBeDefined();
|
||||
});
|
||||
|
||||
env.it("without a custom matcher", function() {
|
||||
expect(env.expect().toFoo).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Custom equality testers for toContain should be per spec", function(done) {
|
||||
var env = new j$.Env({global: { setTimeout: setTimeout }}),
|
||||
reporter = jasmine.createSpyObj('fakeReproter', [
|
||||
"jasmineStarted",
|
||||
"jasmineDone",
|
||||
"suiteStarted",
|
||||
"suiteDone",
|
||||
"specStarted",
|
||||
"specDone"
|
||||
]);
|
||||
|
||||
reporter.jasmineDone.and.callFake(function() {
|
||||
var firstSpecResult = reporter.specDone.calls.first().args[0],
|
||||
secondSpecResult = reporter.specDone.calls.mostRecent().args[0];
|
||||
|
||||
expect(firstSpecResult.status).toEqual("passed");
|
||||
expect(secondSpecResult.status).toEqual("failed");
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.describe("testing custom equality testers", function() {
|
||||
env.it("with a custom tester", function() {
|
||||
env.addCustomEqualityTester(function(a, b) { return true; });
|
||||
env.expect(["a"]).toContain("b");
|
||||
});
|
||||
|
||||
env.it("without a custom tester", function() {
|
||||
env.expect("a").toContain("b");
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,62 +3,66 @@ 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!';
|
||||
var spy = jasmine.createSpy('spy');
|
||||
|
||||
try {
|
||||
suite.execute();
|
||||
dont_change = 'oops I changed';
|
||||
env.execute();
|
||||
spy();
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
expect(dont_change).toEqual('I will never change!');
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
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 () {
|
||||
it('should handle exceptions thrown, but continue', function(done) {
|
||||
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);
|
||||
expectations = function() {
|
||||
expect(secondTest).toHaveBeenCalled();
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: expectations });
|
||||
env.execute();
|
||||
});
|
||||
|
||||
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 () {
|
||||
it("should handle exceptions thrown directly in top-level describe blocks and continue", function(done) {
|
||||
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);
|
||||
expectations = function() {
|
||||
expect(secondDescribe).toHaveBeenCalled();
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: expectations });
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ describe("buildExpectationResult", function() {
|
||||
expect(result.message).toBe('Passed.');
|
||||
});
|
||||
|
||||
it("message returns the message for failing expecations", function() {
|
||||
it("message returns the message for failing expectations", function() {
|
||||
var result = j$.buildExpectationResult({passed: false, message: 'some-value'});
|
||||
expect(result.message).toBe('some-value');
|
||||
});
|
||||
|
||||
@@ -46,7 +46,7 @@ describe("Expectation", function() {
|
||||
expect(expectation.toFoo).toBeUndefined();
|
||||
});
|
||||
|
||||
it("Factory builds an expectaion/negative expectation", function() {
|
||||
it("Factory builds an expectation/negative expectation", function() {
|
||||
var builtExpectation = j$.Expectation.Factory();
|
||||
|
||||
expect(builtExpectation instanceof j$.Expectation).toBe(true);
|
||||
@@ -254,7 +254,7 @@ describe("Expectation", function() {
|
||||
}
|
||||
},
|
||||
util = {
|
||||
buildFailureMessage: function() { return "default messge"; }
|
||||
buildFailureMessage: function() { return "default message"; }
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy("addExpectationResult"),
|
||||
actual = "an actual",
|
||||
@@ -277,7 +277,7 @@ describe("Expectation", function() {
|
||||
passed: false,
|
||||
expected: "hello",
|
||||
actual: actual,
|
||||
message: "default messge"
|
||||
message: "default message"
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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"
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -61,4 +61,4 @@ describe("ObjectContaining", function() {
|
||||
|
||||
expect(containing.jasmineToString()).toMatch("<jasmine.objectContaining");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -37,4 +37,4 @@ describe("ReportDispatcher", function() {
|
||||
dispatcher.foo(123, 456);
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@ describe("Spec", function() {
|
||||
description: 'my test',
|
||||
id: 'some-id',
|
||||
fn: function() {},
|
||||
queueRunner: fakeQueueRunner
|
||||
queueRunnerFactory: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
@@ -42,7 +42,7 @@ describe("Spec", function() {
|
||||
description: 'foo bar',
|
||||
fn: function() {},
|
||||
onStart: startCallback,
|
||||
queueRunner: fakeQueueRunner
|
||||
queueRunnerFactory: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
@@ -69,7 +69,7 @@ describe("Spec", function() {
|
||||
}]
|
||||
},
|
||||
onStart: startCallback,
|
||||
queueRunner: fakeQueueRunner
|
||||
queueRunnerFactory: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
@@ -93,7 +93,7 @@ describe("Spec", function() {
|
||||
afterFns: function() {
|
||||
return [after]
|
||||
},
|
||||
queueRunner: fakeQueueRunner
|
||||
queueRunnerFactory: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
@@ -111,7 +111,7 @@ describe("Spec", function() {
|
||||
onStart: startCallback,
|
||||
fn: null,
|
||||
resultCallback: resultCallback,
|
||||
queueRunner: fakeQueueRunner
|
||||
queueRunnerFactory: fakeQueueRunner
|
||||
});
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ describe("Spec", function() {
|
||||
onStart:startCallback,
|
||||
fn: specBody,
|
||||
resultCallback: resultCallback,
|
||||
queueRunner: fakeQueueRunner
|
||||
queueRunnerFactory: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.disable();
|
||||
@@ -154,7 +154,7 @@ describe("Spec", function() {
|
||||
getSpecName: function() {
|
||||
return "a suite with a spec"
|
||||
},
|
||||
queueRunner: fakeQueueRunner
|
||||
queueRunnerFactory: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.pend();
|
||||
@@ -181,7 +181,7 @@ describe("Spec", function() {
|
||||
fn: function() {},
|
||||
catchExceptions: function() { return false; },
|
||||
resultCallback: function() {},
|
||||
queueRunner: function(attrs) { attrs.onComplete(); }
|
||||
queueRunnerFactory: function(attrs) { attrs.onComplete(); }
|
||||
});
|
||||
|
||||
spec.execute(done);
|
||||
@@ -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() {
|
||||
@@ -217,17 +208,99 @@ describe("Spec", function() {
|
||||
});
|
||||
|
||||
it("can return its full name", function() {
|
||||
var spec;
|
||||
spec = new j$.Spec({
|
||||
getSpecName: function(passedVal) {
|
||||
// expect(passedVal).toBe(spec); TODO: a exec time, spec is undefined WTF?
|
||||
return 'expected val';
|
||||
}
|
||||
var specNameSpy = jasmine.createSpy('specNameSpy').and.returnValue('expected val');
|
||||
|
||||
var spec = new j$.Spec({
|
||||
getSpecName: specNameSpy
|
||||
});
|
||||
|
||||
expect(spec.getFullName()).toBe('expected val');
|
||||
expect(specNameSpy.calls.mostRecent().args[0].id).toEqual(spec.id);
|
||||
});
|
||||
|
||||
it("sets a timeout for async functions to keep them from running forever", function() {
|
||||
var queueRunnerSpy = jasmine.createSpy('queue runner'),
|
||||
setTimeoutSpy = jasmine.createSpy('setTimeout'),
|
||||
spec = new j$.Spec({
|
||||
beforeFns: function() { return [function(done) { }]; },
|
||||
fn: function(done) { },
|
||||
afterFns: function() { return [function(done) { }]; },
|
||||
timer: {
|
||||
setTimeout: setTimeoutSpy,
|
||||
clearTimeout: function() {}
|
||||
},
|
||||
queueRunnerFactory: queueRunnerSpy
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
var fns = queueRunnerSpy.calls.mostRecent().args[0].fns;
|
||||
|
||||
for (var i = 0; i < fns.length; i++) {
|
||||
fns[i]();
|
||||
}
|
||||
|
||||
expect(setTimeoutSpy.calls.count()).toEqual(3);
|
||||
expect(setTimeoutSpy).toHaveBeenCalledWith(jasmine.any(Function), j$.DEFAULT_TIMEOUT_INTERVAL);
|
||||
});
|
||||
|
||||
it("resets the timeout timer when an async before throws an exception", function() {
|
||||
var queueRunnerSpy = jasmine.createSpy('queueRunner'),
|
||||
clearTimeoutSpy = jasmine.createSpy('clear timeout'),
|
||||
spec = new j$.Spec({
|
||||
beforeFns: function() { return [function(done) {}]; },
|
||||
fn: function() { },
|
||||
timer: {
|
||||
setTimeout: function () { return 920; },
|
||||
clearTimeout: clearTimeoutSpy
|
||||
},
|
||||
queueRunnerFactory: queueRunnerSpy
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
queueRunnerSpy.calls.mostRecent().args[0].fns[0]();
|
||||
queueRunnerSpy.calls.mostRecent().args[0].onException(new Error());
|
||||
|
||||
expect(clearTimeoutSpy).toHaveBeenCalledWith(920);
|
||||
});
|
||||
|
||||
it("resets the timeout timer when an async spec throws an exception", function() {
|
||||
var queueRunnerSpy = jasmine.createSpy('queueRunner'),
|
||||
clearTimeoutSpy = jasmine.createSpy('clear timeout'),
|
||||
spec = new j$.Spec({
|
||||
fn: function(done) { },
|
||||
timer: {
|
||||
setTimeout: function () { return 920; },
|
||||
clearTimeout: clearTimeoutSpy
|
||||
},
|
||||
queueRunnerFactory: queueRunnerSpy
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
queueRunnerSpy.calls.mostRecent().args[0].fns[0]();
|
||||
queueRunnerSpy.calls.mostRecent().args[0].onException(new Error());
|
||||
|
||||
expect(clearTimeoutSpy).toHaveBeenCalledWith(920);
|
||||
});
|
||||
|
||||
it("resets the timeout timer when an async after spec throws an exception", function() {
|
||||
var queueRunnerSpy = jasmine.createSpy('queueRunner'),
|
||||
clearTimeoutSpy = jasmine.createSpy('clear timeout'),
|
||||
spec = new j$.Spec({
|
||||
fn: function() { },
|
||||
afterFns: function() { return [function(done) {}]; },
|
||||
timer: {
|
||||
setTimeout: function () { return 920; },
|
||||
clearTimeout: clearTimeoutSpy
|
||||
},
|
||||
queueRunnerFactory: queueRunnerSpy
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
queueRunnerSpy.calls.mostRecent().args[0].fns[1]();
|
||||
queueRunnerSpy.calls.mostRecent().args[0].onException(new Error());
|
||||
|
||||
expect(clearTimeoutSpy).toHaveBeenCalledWith(920);
|
||||
});
|
||||
describe("when a spec is marked pending during execution", function() {
|
||||
it("should mark the spec as pending", function() {
|
||||
var fakeQueueRunner = function(opts) {
|
||||
@@ -237,7 +310,7 @@ describe("Spec", function() {
|
||||
description: 'my test',
|
||||
id: 'some-id',
|
||||
fn: function() { },
|
||||
queueRunner: fakeQueueRunner
|
||||
queueRunnerFactory: fakeQueueRunner
|
||||
});
|
||||
|
||||
spec.execute();
|
||||
|
||||
@@ -14,7 +14,7 @@ describe('Spies', function () {
|
||||
expect(spy.bob).toEqual("test");
|
||||
});
|
||||
|
||||
it("warns the user that we indend to overwrite an existing property", function() {
|
||||
it("warns the user that we intend to overwrite an existing property", function() {
|
||||
TestClass.prototype.someFunction.and = "turkey";
|
||||
|
||||
expect(function() {
|
||||
@@ -28,6 +28,25 @@ describe('Spies', function () {
|
||||
expect(spy.and).toEqual(jasmine.any(j$.SpyStrategy));
|
||||
expect(spy.calls).toEqual(jasmine.any(j$.CallTracker));
|
||||
});
|
||||
|
||||
it("tracks the argument of calls", function () {
|
||||
var spy = j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
var trackSpy = spyOn(spy.calls, "track");
|
||||
|
||||
spy("arg");
|
||||
|
||||
expect(trackSpy.calls.mostRecent().args[0].args).toEqual(["arg"]);
|
||||
});
|
||||
|
||||
it("tracks the context of calls", function () {
|
||||
var spy = j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
var trackSpy = spyOn(spy.calls, "track");
|
||||
|
||||
var contextObject = { spyMethod: spy };
|
||||
contextObject.spyMethod();
|
||||
|
||||
expect(trackSpy.calls.mostRecent().args[0].object).toEqual(contextObject);
|
||||
});
|
||||
});
|
||||
|
||||
describe("createSpyObj", function() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
149
spec/core/integration/CustomMatchersSpec.js
Normal file
149
spec/core/integration/CustomMatchersSpec.js
Normal file
@@ -0,0 +1,149 @@
|
||||
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();
|
||||
});
|
||||
});
|
||||
488
spec/core/integration/EnvSpec.js
Normal file
488
spec/core/integration/EnvSpec.js
Normal file
@@ -0,0 +1,488 @@
|
||||
describe("Env integration", function() {
|
||||
|
||||
it("Suites execute as expected (no nesting)", function(done) {
|
||||
var env = new j$.Env(),
|
||||
calls = [];
|
||||
|
||||
var assertions = function() {
|
||||
expect(calls).toEqual([
|
||||
"with a spec",
|
||||
"and another spec"
|
||||
]);
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions});
|
||||
|
||||
env.describe("A Suite", function() {
|
||||
env.it("with a spec", function() {
|
||||
calls.push("with a spec");
|
||||
});
|
||||
env.it("and another spec", function() {
|
||||
calls.push("and another spec");
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Nested Suites execute as expected", function(done) {
|
||||
var env = new j$.Env(),
|
||||
calls = [];
|
||||
|
||||
var assertions = function() {
|
||||
expect(calls).toEqual([
|
||||
'an outer spec',
|
||||
'an inner spec',
|
||||
'another inner spec'
|
||||
]);
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions });
|
||||
|
||||
env.describe("Outer suite", function() {
|
||||
env.it("an outer spec", function() {
|
||||
calls.push('an outer spec')
|
||||
});
|
||||
env.describe("Inner suite", function() {
|
||||
env.it("an inner spec", function() {
|
||||
calls.push('an inner spec');
|
||||
});
|
||||
env.it("another inner spec", function() {
|
||||
calls.push('another inner spec');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Multiple top-level Suites execute as expected", function(done) {
|
||||
var env = new j$.Env(),
|
||||
calls = [];
|
||||
|
||||
var assertions = function() {
|
||||
expect(calls).toEqual([
|
||||
'an outer spec',
|
||||
'an inner spec',
|
||||
'another inner spec',
|
||||
'a 2nd outer spec'
|
||||
]);
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions });
|
||||
|
||||
|
||||
env.describe("Outer suite", function() {
|
||||
env.it("an outer spec", function() {
|
||||
calls.push('an outer spec')
|
||||
});
|
||||
env.describe("Inner suite", function() {
|
||||
env.it("an inner spec", function() {
|
||||
calls.push('an inner spec');
|
||||
});
|
||||
env.it("another inner spec", function() {
|
||||
calls.push('another inner spec');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.describe("Another outer suite", function() {
|
||||
env.it("a 2nd outer spec", function() {
|
||||
calls.push('a 2nd outer spec')
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("calls associated befores/specs/afters with the same 'this'", function(done) {
|
||||
var env = new j$.Env();
|
||||
|
||||
env.addReporter({jasmineDone: done});
|
||||
|
||||
env.describe("tests", function() {
|
||||
var firstTimeThrough = true, firstSpecContext, secondSpecContext;
|
||||
|
||||
env.beforeEach(function() {
|
||||
if (firstTimeThrough) {
|
||||
firstSpecContext = this;
|
||||
} else {
|
||||
secondSpecContext = this;
|
||||
}
|
||||
expect(this).toEqual({});
|
||||
});
|
||||
|
||||
env.it("sync spec", function() {
|
||||
expect(this).toBe(firstSpecContext);
|
||||
});
|
||||
|
||||
env.it("another sync spec", function() {
|
||||
expect(this).toBe(secondSpecContext);
|
||||
});
|
||||
|
||||
env.afterEach(function() {
|
||||
if (firstTimeThrough) {
|
||||
expect(this).toBe(firstSpecContext);
|
||||
firstTimeThrough = false;
|
||||
} else {
|
||||
expect(this).toBe(secondSpecContext);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("calls associated befores/its/afters with the same 'this' for an async spec", function(done) {
|
||||
var env = new j$.Env();
|
||||
|
||||
env.addReporter({jasmineDone: done});
|
||||
|
||||
env.describe("with an async spec", function() {
|
||||
var specContext;
|
||||
|
||||
env.beforeEach(function() {
|
||||
specContext = this;
|
||||
expect(this).toEqual({});
|
||||
});
|
||||
|
||||
env.it("sync spec", function(underTestCallback) {
|
||||
expect(this).toBe(specContext);
|
||||
underTestCallback();
|
||||
});
|
||||
|
||||
env.afterEach(function() {
|
||||
expect(this).toBe(specContext);
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Allows specifying which specs and suites to run", function(done) {
|
||||
var env = new j$.Env(),
|
||||
calls = [],
|
||||
suiteCallback = jasmine.createSpy('suite callback'),
|
||||
firstSpec,
|
||||
secondSuite;
|
||||
|
||||
var assertions = function() {
|
||||
expect(calls).toEqual([
|
||||
'third spec',
|
||||
'first spec'
|
||||
]);
|
||||
expect(suiteCallback).toHaveBeenCalled();
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({jasmineDone: assertions, suiteDone: suiteCallback});
|
||||
|
||||
env.describe("first suite", function() {
|
||||
firstSpec = env.it("first spec", function() {
|
||||
calls.push('first spec');
|
||||
});
|
||||
env.it("second spec", function() {
|
||||
calls.push('second spec');
|
||||
});
|
||||
});
|
||||
|
||||
secondSuite = env.describe("second suite", function() {
|
||||
env.it("third spec", function() {
|
||||
calls.push('third spec');
|
||||
});
|
||||
});
|
||||
|
||||
env.execute([secondSuite.id, firstSpec.id]);
|
||||
});
|
||||
|
||||
it("Functions can be spied on and have their calls tracked", function () {
|
||||
var env = new j$.Env();
|
||||
|
||||
var originalFunctionWasCalled = false;
|
||||
var subject = { spiedFunc: function() { originalFunctionWasCalled = true; } };
|
||||
|
||||
var spy = env.spyOn(subject, 'spiedFunc');
|
||||
|
||||
expect(subject.spiedFunc).toEqual(spy);
|
||||
|
||||
expect(subject.spiedFunc.calls.any()).toEqual(false);
|
||||
expect(subject.spiedFunc.calls.count()).toEqual(0);
|
||||
|
||||
subject.spiedFunc('foo');
|
||||
|
||||
expect(subject.spiedFunc.calls.any()).toEqual(true);
|
||||
expect(subject.spiedFunc.calls.count()).toEqual(1);
|
||||
expect(subject.spiedFunc.calls.mostRecent().args).toEqual(['foo']);
|
||||
expect(subject.spiedFunc.calls.mostRecent().object).toEqual(subject);
|
||||
expect(originalFunctionWasCalled).toEqual(false);
|
||||
|
||||
subject.spiedFunc('bar');
|
||||
expect(subject.spiedFunc.calls.count()).toEqual(2);
|
||||
expect(subject.spiedFunc.calls.mostRecent().args).toEqual(['bar']);
|
||||
});
|
||||
|
||||
it("Mock clock can be installed and used in tests", function(done) {
|
||||
var globalSetTimeout = jasmine.createSpy('globalSetTimeout'),
|
||||
delayedFunctionForGlobalClock = jasmine.createSpy('delayedFunctionForGlobalClock'),
|
||||
delayedFunctionForMockClock = jasmine.createSpy('delayedFunctionForMockClock'),
|
||||
env = new j$.Env({global: { setTimeout: globalSetTimeout }});
|
||||
|
||||
var assertions = function() {
|
||||
expect(delayedFunctionForMockClock).toHaveBeenCalled();
|
||||
expect(globalSetTimeout).toHaveBeenCalledWith(delayedFunctionForGlobalClock, 100);
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions });
|
||||
|
||||
env.describe("tests", function() {
|
||||
env.it("test with mock clock", function() {
|
||||
env.clock.install();
|
||||
env.clock.setTimeout(delayedFunctionForMockClock, 100);
|
||||
env.clock.tick(100);
|
||||
env.clock.uninstall();
|
||||
});
|
||||
env.it("test without mock clock", function() {
|
||||
env.clock.setTimeout(delayedFunctionForGlobalClock, 100);
|
||||
});
|
||||
});
|
||||
|
||||
expect(globalSetTimeout).not.toHaveBeenCalled();
|
||||
expect(delayedFunctionForMockClock).not.toHaveBeenCalled();
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("should run async specs in order, waiting for them to complete", function(done) {
|
||||
var env = new j$.Env(), mutatedVar;
|
||||
|
||||
env.describe("tests", function() {
|
||||
env.beforeEach(function() {
|
||||
mutatedVar = 2;
|
||||
});
|
||||
|
||||
env.it("async spec", function(underTestCallback) {
|
||||
setTimeout(function() {
|
||||
expect(mutatedVar).toEqual(2);
|
||||
underTestCallback();
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
env.it("after async spec", function() {
|
||||
mutatedVar = 3;
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
describe("with a mock clock", function() {
|
||||
var originalTimeout;
|
||||
|
||||
beforeEach(function() {
|
||||
originalTimeout = j$.DEFAULT_TIMEOUT_INTERVAL;
|
||||
jasmine.getEnv().clock.install();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
jasmine.getEnv().clock.uninstall();
|
||||
j$.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
|
||||
});
|
||||
|
||||
it("should wait a specified interval before failing specs haven't called done yet", function(done) {
|
||||
var env = new j$.Env(),
|
||||
reporter = jasmine.createSpyObj('fakeReporter', [ "specDone" ]);
|
||||
|
||||
reporter.specDone.and.callFake(function() {
|
||||
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({status: 'failed'}));
|
||||
done();
|
||||
});
|
||||
|
||||
env.addReporter(reporter);
|
||||
j$.DEFAULT_TIMEOUT_INTERVAL = 8414;
|
||||
|
||||
env.it("async spec that doesn't call done", function(underTestCallback) {
|
||||
env.expect(true).toBeTruthy();
|
||||
jasmine.getEnv().clock.tick(8415);
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: something is wrong with this spec
|
||||
it("should report as expected", function(done) {
|
||||
var env = new j$.Env(),
|
||||
reporter = jasmine.createSpyObj('fakeReporter', [
|
||||
"jasmineStarted",
|
||||
"jasmineDone",
|
||||
"suiteStarted",
|
||||
"suiteDone",
|
||||
"specStarted",
|
||||
"specDone"
|
||||
]);
|
||||
|
||||
reporter.jasmineDone.and.callFake(function() {
|
||||
expect(reporter.jasmineStarted).toHaveBeenCalledWith({
|
||||
totalSpecsDefined: 3
|
||||
});
|
||||
var suiteResult = reporter.suiteStarted.calls.first().args[0];
|
||||
expect(suiteResult.description).toEqual("A Suite");
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.describe("A Suite", function() {
|
||||
env.it("with a top level spec", function() {
|
||||
env.expect(true).toBe(true);
|
||||
});
|
||||
env.describe("with a nested suite", function() {
|
||||
env.xit("with a pending spec", function() {
|
||||
env.expect(true).toBe(true);
|
||||
});
|
||||
env.it("with a spec", function() {
|
||||
env.expect(true).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("should be possible to get full name from a spec", function() {
|
||||
var env = new j$.Env({global: { setTimeout: setTimeout }}),
|
||||
topLevelSpec, nestedSpec, doublyNestedSpec;
|
||||
|
||||
env.describe("my tests", function() {
|
||||
topLevelSpec = env.it("are sometimes top level", function() {
|
||||
});
|
||||
env.describe("are sometimes", function() {
|
||||
nestedSpec = env.it("singly nested", function() {
|
||||
});
|
||||
env.describe("even", function() {
|
||||
doublyNestedSpec = env.it("doubly nested", function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
expect(topLevelSpec.getFullName()).toBe("my tests are sometimes top level");
|
||||
expect(nestedSpec.getFullName()).toBe("my tests are sometimes singly nested");
|
||||
expect(doublyNestedSpec.getFullName()).toBe("my tests are sometimes even doubly nested");
|
||||
});
|
||||
|
||||
it("Custom equality testers should be per spec", function(done) {
|
||||
var env = new j$.Env({global: { setTimeout: setTimeout }}),
|
||||
reporter = jasmine.createSpyObj('fakeReporter', [
|
||||
"jasmineStarted",
|
||||
"jasmineDone",
|
||||
"suiteStarted",
|
||||
"suiteDone",
|
||||
"specStarted",
|
||||
"specDone"
|
||||
]);
|
||||
|
||||
reporter.jasmineDone.and.callFake(function() {
|
||||
var firstSpecResult = reporter.specDone.calls.first().args[0],
|
||||
secondSpecResult = reporter.specDone.calls.mostRecent().args[0];
|
||||
|
||||
expect(firstSpecResult.status).toEqual("passed");
|
||||
expect(secondSpecResult.status).toEqual("failed");
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.describe("testing custom equality testers", function() {
|
||||
env.it("with a custom tester", function() {
|
||||
env.addCustomEqualityTester(function(a, b) { return true; });
|
||||
env.expect("a").toEqual("b");
|
||||
});
|
||||
|
||||
env.it("without a custom tester", function() {
|
||||
env.expect("a").toEqual("b");
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Custom matchers should be per spec", function() {
|
||||
var env = new j$.Env({global: { setTimeout: setTimeout }}),
|
||||
matchers = {
|
||||
toFoo: function() {}
|
||||
},
|
||||
reporter = jasmine.createSpyObj('fakeReporter', [
|
||||
"jasmineStarted",
|
||||
"jasmineDone",
|
||||
"suiteStarted",
|
||||
"suiteDone",
|
||||
"specStarted",
|
||||
"specDone"
|
||||
]);
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.describe("testing custom matchers", function() {
|
||||
env.it("with a custom matcher", function() {
|
||||
env.addMatchers(matchers);
|
||||
expect(env.expect().toFoo).toBeDefined();
|
||||
});
|
||||
|
||||
env.it("without a custom matcher", function() {
|
||||
expect(env.expect().toFoo).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it("Custom equality testers for toContain should be per spec", function(done) {
|
||||
var env = new j$.Env({global: { setTimeout: setTimeout }}),
|
||||
reporter = jasmine.createSpyObj('fakeReporter', [
|
||||
"jasmineStarted",
|
||||
"jasmineDone",
|
||||
"suiteStarted",
|
||||
"suiteDone",
|
||||
"specStarted",
|
||||
"specDone"
|
||||
]);
|
||||
|
||||
reporter.jasmineDone.and.callFake(function() {
|
||||
var firstSpecResult = reporter.specDone.calls.first().args[0],
|
||||
secondSpecResult = reporter.specDone.calls.mostRecent().args[0];
|
||||
|
||||
expect(firstSpecResult.status).toEqual("passed");
|
||||
expect(secondSpecResult.status).toEqual("failed");
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
env.addReporter(reporter);
|
||||
|
||||
env.describe("testing custom equality testers", function() {
|
||||
env.it("with a custom tester", function() {
|
||||
env.addCustomEqualityTester(function(a, b) { return true; });
|
||||
env.expect(["a"]).toContain("b");
|
||||
});
|
||||
|
||||
env.it("without a custom tester", function() {
|
||||
env.expect("a").toContain("b");
|
||||
});
|
||||
});
|
||||
|
||||
env.execute();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
// TODO: This should really be part of the Env Integration Spec
|
||||
describe("jasmine spec running", function () {
|
||||
var env;
|
||||
var fakeTimer;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new j$.Env();
|
||||
env.updateInterval = 0;
|
||||
});
|
||||
|
||||
it('should assign spec ids sequentially', function() {
|
||||
@@ -1,6 +1,6 @@
|
||||
describe("matchersUtil", function() {
|
||||
describe("equals", function() {
|
||||
it("passes for literals that are threequal", function() {
|
||||
it("passes for literals that are triple-equal", function() {
|
||||
expect(j$.matchersUtil.equals(null, null)).toBe(true);
|
||||
expect(j$.matchersUtil.equals(void 0, void 0)).toBe(true);
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -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() {
|
||||
@@ -246,7 +246,7 @@ describe("toThrowError", function() {
|
||||
expect(result.message).toEqual("Expected function to throw TypeError with message \"bar\", but it threw TypeError with message \"foo\".");
|
||||
});
|
||||
|
||||
it("passes if thrown is a type of Error and has the same type as the expected Error and the message matches the exepcted message", function() {
|
||||
it("passes if thrown is a type of Error and has the same type as the expected Error and the message matches the expected message", function() {
|
||||
var util = {
|
||||
equals: jasmine.createSpy('delegated-equal').and.returnValue(true)
|
||||
},
|
||||
|
||||
@@ -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.");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,4 +15,4 @@ describe("j$.HtmlSpecFilter", function() {
|
||||
expect(specFilter.matches("foo")).toBe(true);
|
||||
expect(specFilter.matches("bar")).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -40,4 +40,4 @@ describe("QueryString", function() {
|
||||
expect(queryString.getParam("baz")).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -59,4 +59,4 @@ describe("ResultsNode", function() {
|
||||
|
||||
expect(node.last()).toBe(node.children[node.children.length - 1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -15,10 +15,10 @@ getJasmineRequireObj().ConsoleReporter = function() {
|
||||
failedSpecs = [],
|
||||
pendingCount,
|
||||
ansi = {
|
||||
green: '\033[32m',
|
||||
red: '\033[31m',
|
||||
yellow: '\033[33m',
|
||||
none: '\033[0m'
|
||||
green: '\x1B[32m',
|
||||
red: '\x1B[31m',
|
||||
yellow: '\x1B[33m',
|
||||
none: '\x1B[0m'
|
||||
};
|
||||
|
||||
this.jasmineStarted = function() {
|
||||
|
||||
@@ -33,4 +33,4 @@ getJasmineRequireObj().Any = function() {
|
||||
};
|
||||
|
||||
return Any;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
getJasmineRequireObj().DelayedFunctionScheduler = function() {
|
||||
function DelayedFunctionScheduler() {
|
||||
var self = this;
|
||||
var scheduledLookup = [];
|
||||
var scheduledFunctions = {};
|
||||
var currentTime = 0;
|
||||
var delayedFnCount = 0;
|
||||
|
||||
self.tick = function(millis) {
|
||||
millis = millis || 0;
|
||||
currentTime = currentTime + millis;
|
||||
runFunctionsWithinRange(currentTime - millis, currentTime);
|
||||
var endTime = currentTime + millis;
|
||||
|
||||
runScheduledFunctions(endTime);
|
||||
currentTime = endTime;
|
||||
};
|
||||
|
||||
self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) {
|
||||
@@ -24,7 +27,8 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
|
||||
millis = millis || 0;
|
||||
timeoutKey = timeoutKey || ++delayedFnCount;
|
||||
runAtMillis = runAtMillis || (currentTime + millis);
|
||||
scheduledFunctions[timeoutKey] = {
|
||||
|
||||
var funcToSchedule = {
|
||||
runAtMillis: runAtMillis,
|
||||
funcToCall: f,
|
||||
recurring: recurring,
|
||||
@@ -32,58 +36,73 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
|
||||
timeoutKey: timeoutKey,
|
||||
millis: millis
|
||||
};
|
||||
|
||||
if (runAtMillis in scheduledFunctions) {
|
||||
scheduledFunctions[runAtMillis].push(funcToSchedule);
|
||||
} else {
|
||||
scheduledFunctions[runAtMillis] = [funcToSchedule];
|
||||
scheduledLookup.push(runAtMillis);
|
||||
scheduledLookup.sort(function (a, b) {
|
||||
return a - b;
|
||||
});
|
||||
}
|
||||
|
||||
return timeoutKey;
|
||||
};
|
||||
|
||||
self.removeFunctionWithId = function(timeoutKey) {
|
||||
delete scheduledFunctions[timeoutKey];
|
||||
for (var runAtMillis in scheduledFunctions) {
|
||||
var funcs = scheduledFunctions[runAtMillis];
|
||||
var i = indexOfFirstToPass(funcs, function (func) {
|
||||
return func.timeoutKey === timeoutKey;
|
||||
});
|
||||
|
||||
if (i > -1) {
|
||||
if (funcs.length === 1) {
|
||||
delete scheduledFunctions[runAtMillis];
|
||||
deleteFromLookup(runAtMillis);
|
||||
} else {
|
||||
funcs.splice(i, 1);
|
||||
}
|
||||
|
||||
// intervals get rescheduled when executed, so there's never more
|
||||
// than a single scheduled function with a given timeoutKey
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.reset = function() {
|
||||
currentTime = 0;
|
||||
scheduledLookup = [];
|
||||
scheduledFunctions = {};
|
||||
delayedFnCount = 0;
|
||||
};
|
||||
|
||||
return self;
|
||||
|
||||
// finds/dupes functions within range and removes them.
|
||||
function functionsWithinRange(startMillis, endMillis) {
|
||||
var fnsToRun = [];
|
||||
for (var timeoutKey in scheduledFunctions) {
|
||||
var scheduledFunc = scheduledFunctions[timeoutKey];
|
||||
if (scheduledFunc &&
|
||||
scheduledFunc.runAtMillis >= startMillis &&
|
||||
scheduledFunc.runAtMillis <= endMillis) {
|
||||
function indexOfFirstToPass(array, testFn) {
|
||||
var index = -1;
|
||||
|
||||
// remove fn -- we'll reschedule later if it is recurring.
|
||||
self.removeFunctionWithId(timeoutKey);
|
||||
if (!scheduledFunc.recurring) {
|
||||
fnsToRun.push(scheduledFunc); // schedules each function only once
|
||||
} else {
|
||||
fnsToRun.push(buildNthInstanceOf(scheduledFunc, 0));
|
||||
var additionalTimesFnRunsInRange =
|
||||
Math.floor((endMillis - scheduledFunc.runAtMillis) / scheduledFunc.millis);
|
||||
for (var i = 0; i < additionalTimesFnRunsInRange; i++) {
|
||||
fnsToRun.push(buildNthInstanceOf(scheduledFunc, i + 1));
|
||||
}
|
||||
reschedule(buildNthInstanceOf(scheduledFunc, additionalTimesFnRunsInRange));
|
||||
}
|
||||
for (var i = 0; i < array.length; ++i) {
|
||||
if (testFn(array[i])) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fnsToRun;
|
||||
return index;
|
||||
}
|
||||
|
||||
function buildNthInstanceOf(scheduledFunc, n) {
|
||||
return {
|
||||
runAtMillis: scheduledFunc.runAtMillis + (scheduledFunc.millis * n),
|
||||
funcToCall: scheduledFunc.funcToCall,
|
||||
params: scheduledFunc.params,
|
||||
millis: scheduledFunc.millis,
|
||||
recurring: scheduledFunc.recurring,
|
||||
timeoutKey: scheduledFunc.timeoutKey
|
||||
};
|
||||
function deleteFromLookup(key) {
|
||||
var value = Number(key);
|
||||
var i = indexOfFirstToPass(scheduledLookup, function (millis) {
|
||||
return millis === value;
|
||||
});
|
||||
|
||||
if (i > -1) {
|
||||
scheduledLookup.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
function reschedule(scheduledFn) {
|
||||
@@ -95,21 +114,30 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
|
||||
scheduledFn.runAtMillis + scheduledFn.millis);
|
||||
}
|
||||
|
||||
|
||||
function runFunctionsWithinRange(startMillis, endMillis) {
|
||||
var funcsToRun = functionsWithinRange(startMillis, endMillis);
|
||||
if (funcsToRun.length === 0) {
|
||||
function runScheduledFunctions(endTime) {
|
||||
if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) {
|
||||
return;
|
||||
}
|
||||
|
||||
funcsToRun.sort(function(a, b) {
|
||||
return a.runAtMillis - b.runAtMillis;
|
||||
});
|
||||
do {
|
||||
currentTime = scheduledLookup.shift();
|
||||
|
||||
for (var i = 0; i < funcsToRun.length; ++i) {
|
||||
var funcToRun = funcsToRun[i];
|
||||
funcToRun.funcToCall.apply(null, funcToRun.params || []);
|
||||
}
|
||||
var funcsToRun = scheduledFunctions[currentTime];
|
||||
delete scheduledFunctions[currentTime];
|
||||
|
||||
for (var i = 0; i < funcsToRun.length; ++i) {
|
||||
var funcToRun = funcsToRun[i];
|
||||
funcToRun.funcToCall.apply(null, funcToRun.params || []);
|
||||
|
||||
if (funcToRun.recurring) {
|
||||
reschedule(funcToRun);
|
||||
}
|
||||
}
|
||||
} while (scheduledLookup.length > 0 &&
|
||||
// checking first if we're out of time prevents setTimeout(0)
|
||||
// scheduled in a funcToRun from forcing an extra iteration
|
||||
currentTime !== endTime &&
|
||||
scheduledLookup[0] <= endTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
353
src/core/Env.js
353
src/core/Env.js
@@ -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,97 +129,33 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
}
|
||||
}
|
||||
|
||||
var catchException = function(e) {
|
||||
return j$.Spec.isPendingSpecException(e) || catchExceptions;
|
||||
};
|
||||
|
||||
var queueRunnerFactory = function(options) {
|
||||
options.catchException = self.catchException;
|
||||
options.catchException = catchException;
|
||||
options.clearStack = options.clearStack || clearStack;
|
||||
|
||||
new j$.QueueRunner(options).run(options.fns, 0);
|
||||
new j$.QueueRunner(options).execute();
|
||||
};
|
||||
|
||||
var totalSpecsDefined = 0;
|
||||
this.specFactory = function(description, fn, suite) {
|
||||
totalSpecsDefined++;
|
||||
|
||||
var spec = new j$.Spec({
|
||||
id: self.nextSpecId(),
|
||||
beforeFns: beforeFns(suite),
|
||||
afterFns: afterFns(suite),
|
||||
expectationFactory: expectationFactory,
|
||||
exceptionFormatter: exceptionFormatter,
|
||||
resultCallback: specResultCallback,
|
||||
getSpecName: function(spec) {
|
||||
return getSpecName(spec, suite);
|
||||
},
|
||||
onStart: specStarted,
|
||||
description: description,
|
||||
expectationResultFactory: expectationResultFactory,
|
||||
queueRunner: queueRunnerFactory,
|
||||
fn: fn,
|
||||
timer: {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}
|
||||
});
|
||||
|
||||
runnableLookupTable[spec.id] = spec;
|
||||
|
||||
if (!self.specFilter(spec)) {
|
||||
spec.disable();
|
||||
}
|
||||
|
||||
return spec;
|
||||
|
||||
function removeAllSpies() {
|
||||
for (var i = 0; i < spies.length; i++) {
|
||||
var spyEntry = spies[i];
|
||||
spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
|
||||
}
|
||||
spies = [];
|
||||
}
|
||||
|
||||
function specResultCallback(result) {
|
||||
removeAllSpies();
|
||||
j$.Expectation.resetMatchers();
|
||||
customEqualityTesters.length = 0;
|
||||
self.clock.uninstall();
|
||||
self.currentSpec = null;
|
||||
self.reporter.specDone(result);
|
||||
}
|
||||
};
|
||||
|
||||
var suiteStarted = function(suite) {
|
||||
self.reporter.suiteStarted(suite.result);
|
||||
};
|
||||
|
||||
var suiteConstructor = j$.Suite;
|
||||
|
||||
this.topSuite = new j$.Suite({
|
||||
var topSuite = new j$.Suite({
|
||||
env: this,
|
||||
id: this.nextSuiteId(),
|
||||
id: getNextSuiteId(),
|
||||
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;
|
||||
runnableLookupTable[topSuite.id] = topSuite;
|
||||
currentSuite = 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.topSuite = function() {
|
||||
return topSuite;
|
||||
};
|
||||
|
||||
this.execute = function(runnablesToRun) {
|
||||
runnablesToRun = runnablesToRun || [this.topSuite.id];
|
||||
runnablesToRun = runnablesToRun || [topSuite.id];
|
||||
|
||||
var allFns = [];
|
||||
for(var i = 0; i < runnablesToRun.length; i++) {
|
||||
@@ -219,11 +163,19 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable));
|
||||
}
|
||||
|
||||
this.reporter.jasmineStarted({
|
||||
reporter.jasmineStarted({
|
||||
totalSpecsDefined: totalSpecsDefined
|
||||
});
|
||||
|
||||
queueRunnerFactory({fns: allFns, onComplete: this.reporter.jasmineDone});
|
||||
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) {
|
||||
@@ -253,108 +205,133 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
|
||||
return spy;
|
||||
};
|
||||
}
|
||||
|
||||
Env.prototype.addMatchers = function(matchersToAdd) {
|
||||
j$.Expectation.addMatchers(matchersToAdd);
|
||||
};
|
||||
|
||||
Env.prototype.version = function() {
|
||||
return j$.version;
|
||||
};
|
||||
|
||||
Env.prototype.expect = function(actual) {
|
||||
return this.currentSpec.expect(actual);
|
||||
};
|
||||
|
||||
|
||||
// TODO: move this to closure
|
||||
Env.prototype.versionString = function() {
|
||||
console.log("DEPRECATED == use j$.version");
|
||||
return j$.version;
|
||||
};
|
||||
|
||||
// TODO: move this to closure
|
||||
Env.prototype.nextSpecId = function() {
|
||||
return 'spec' + this.nextSpecId_++;
|
||||
};
|
||||
|
||||
// TODO: move this to closure
|
||||
Env.prototype.nextSuiteId = function() {
|
||||
return 'suite' + this.nextSuiteId_++;
|
||||
};
|
||||
|
||||
// TODO: move this to closure
|
||||
Env.prototype.addReporter = function(reporter) {
|
||||
this.reporter.addReporter(reporter);
|
||||
};
|
||||
|
||||
// TODO: move this to closure
|
||||
Env.prototype.describe = function(description, specDefinitions) {
|
||||
var suite = this.suiteFactory(description);
|
||||
|
||||
var parentSuite = this.currentSuite;
|
||||
parentSuite.addSuite(suite);
|
||||
this.currentSuite = suite;
|
||||
|
||||
var declarationError = null;
|
||||
try {
|
||||
specDefinitions.call(suite);
|
||||
} catch (e) {
|
||||
declarationError = e;
|
||||
}
|
||||
|
||||
if (declarationError) {
|
||||
this.it("encountered a declaration exception", function() {
|
||||
throw declarationError;
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.currentSuite = parentSuite;
|
||||
runnableLookupTable[suite.id] = suite;
|
||||
return suite;
|
||||
};
|
||||
|
||||
return suite;
|
||||
};
|
||||
this.describe = function(description, specDefinitions) {
|
||||
var suite = suiteFactory(description);
|
||||
|
||||
// TODO: move this to closure
|
||||
Env.prototype.xdescribe = function(description, specDefinitions) {
|
||||
var suite = this.describe(description, specDefinitions);
|
||||
suite.disable();
|
||||
return suite;
|
||||
};
|
||||
var parentSuite = currentSuite;
|
||||
parentSuite.addChild(suite);
|
||||
currentSuite = 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;
|
||||
};
|
||||
var declarationError = null;
|
||||
try {
|
||||
specDefinitions.call(suite);
|
||||
} catch (e) {
|
||||
declarationError = e;
|
||||
}
|
||||
|
||||
// TODO: move this to closure
|
||||
Env.prototype.xit = function(description, fn) {
|
||||
var spec = this.it(description, fn);
|
||||
spec.pend();
|
||||
return spec;
|
||||
};
|
||||
if (declarationError) {
|
||||
this.it("encountered a declaration exception", function() {
|
||||
throw declarationError;
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: move this to closure
|
||||
Env.prototype.beforeEach = function(beforeEachFunction) {
|
||||
this.currentSuite.beforeEach(beforeEachFunction);
|
||||
};
|
||||
currentSuite = parentSuite;
|
||||
|
||||
// TODO: move this to closure
|
||||
Env.prototype.afterEach = function(afterEachFunction) {
|
||||
this.currentSuite.afterEach(afterEachFunction);
|
||||
};
|
||||
return suite;
|
||||
};
|
||||
|
||||
// TODO: move this to closure
|
||||
Env.prototype.pending = function() {
|
||||
throw j$.Spec.pendingSpecExceptionMessage;
|
||||
};
|
||||
this.xdescribe = function(description, specDefinitions) {
|
||||
var suite = this.describe(description, specDefinitions);
|
||||
suite.disable();
|
||||
return suite;
|
||||
};
|
||||
|
||||
// TODO: Still needed?
|
||||
Env.prototype.currentRunner = function() {
|
||||
return this.topSuite;
|
||||
};
|
||||
var specFactory = function(description, fn, suite) {
|
||||
totalSpecsDefined++;
|
||||
|
||||
var spec = new j$.Spec({
|
||||
id: getNextSpecId(),
|
||||
beforeFns: beforeFns(suite),
|
||||
afterFns: afterFns(suite),
|
||||
expectationFactory: expectationFactory,
|
||||
exceptionFormatter: exceptionFormatter,
|
||||
resultCallback: specResultCallback,
|
||||
getSpecName: function(spec) {
|
||||
return getSpecName(spec, suite);
|
||||
},
|
||||
onStart: specStarted,
|
||||
description: description,
|
||||
expectationResultFactory: expectationResultFactory,
|
||||
queueRunnerFactory: queueRunnerFactory,
|
||||
fn: fn,
|
||||
timer: {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}
|
||||
});
|
||||
|
||||
runnableLookupTable[spec.id] = spec;
|
||||
|
||||
if (!self.specFilter(spec)) {
|
||||
spec.disable();
|
||||
}
|
||||
|
||||
return spec;
|
||||
|
||||
function removeAllSpies() {
|
||||
for (var i = 0; i < spies.length; i++) {
|
||||
var spyEntry = spies[i];
|
||||
spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
|
||||
}
|
||||
spies = [];
|
||||
}
|
||||
|
||||
function specResultCallback(result) {
|
||||
removeAllSpies();
|
||||
j$.Expectation.resetMatchers();
|
||||
customEqualityTesters = [];
|
||||
currentSpec = null;
|
||||
reporter.specDone(result);
|
||||
}
|
||||
};
|
||||
|
||||
var suiteStarted = function(suite) {
|
||||
reporter.suiteStarted(suite.result);
|
||||
};
|
||||
|
||||
this.it = function(description, fn) {
|
||||
var spec = specFactory(description, fn, currentSuite);
|
||||
currentSuite.addChild(spec);
|
||||
return spec;
|
||||
};
|
||||
|
||||
this.xit = function(description, fn) {
|
||||
var spec = this.it(description, fn);
|
||||
spec.pend();
|
||||
return spec;
|
||||
};
|
||||
|
||||
this.expect = function(actual) {
|
||||
return currentSpec.expect(actual);
|
||||
};
|
||||
|
||||
this.beforeEach = function(beforeEachFunction) {
|
||||
currentSuite.beforeEach(beforeEachFunction);
|
||||
};
|
||||
|
||||
this.afterEach = function(afterEachFunction) {
|
||||
currentSuite.afterEach(afterEachFunction);
|
||||
};
|
||||
|
||||
this.pending = function() {
|
||||
throw j$.Spec.pendingSpecExceptionMessage;
|
||||
};
|
||||
}
|
||||
|
||||
return Env;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 = [];
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
getJasmineRequireObj().Spec = function(j$) {
|
||||
function Spec(attrs) {
|
||||
this.encounteredExpectations = false;
|
||||
this.expectationFactory = attrs.expectationFactory;
|
||||
this.resultCallback = attrs.resultCallback || function() {};
|
||||
this.id = attrs.id;
|
||||
this.description = attrs.description || '';
|
||||
this.fn = attrs.fn;
|
||||
this.beforeFns = attrs.beforeFns || function() {};
|
||||
this.afterFns = attrs.afterFns || function() {};
|
||||
this.catchingExceptions = attrs.catchingExceptions;
|
||||
this.beforeFns = attrs.beforeFns || function() { return []; };
|
||||
this.afterFns = attrs.afterFns || function() { return []; };
|
||||
this.onStart = attrs.onStart || function() {};
|
||||
this.exceptionFormatter = attrs.exceptionFormatter || function() {};
|
||||
this.getSpecName = attrs.getSpecName || function() { return ''; };
|
||||
this.expectationResultFactory = attrs.expectationResultFactory || function() { };
|
||||
this.queueRunner = attrs.queueRunner || function() {};
|
||||
this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
|
||||
this.catchingExceptions = attrs.catchingExceptions || function() { return true; };
|
||||
|
||||
this.timer = attrs.timer || {setTimeout: setTimeout, clearTimeout: clearTimeout};
|
||||
@@ -26,13 +24,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;
|
||||
}
|
||||
@@ -44,7 +40,8 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
};
|
||||
|
||||
Spec.prototype.execute = function(onComplete) {
|
||||
var self = this;
|
||||
var self = this,
|
||||
timeout;
|
||||
|
||||
this.onStart(this);
|
||||
|
||||
@@ -55,13 +52,13 @@ 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'));
|
||||
timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
|
||||
onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
|
||||
done();
|
||||
}, j$.DEFAULT_TIMEOUT_INTERVAL]]);
|
||||
|
||||
var callDone = function() {
|
||||
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
|
||||
clearTimeoutable();
|
||||
done();
|
||||
};
|
||||
|
||||
@@ -69,30 +66,38 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
};
|
||||
}
|
||||
|
||||
var befores = this.beforeFns() || [],
|
||||
afters = this.afterFns() || [],
|
||||
thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
|
||||
var allFns = befores.concat(thisOne).concat(afters);
|
||||
function clearTimeoutable() {
|
||||
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
|
||||
timeout = void 0;
|
||||
}
|
||||
|
||||
this.queueRunner({
|
||||
fns: allFns,
|
||||
var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()),
|
||||
allTimeoutableFns = [];
|
||||
for (var i = 0; i < allFns.length; i++) {
|
||||
var fn = allFns[i];
|
||||
allTimeoutableFns.push(fn.length > 0 ? timeoutable(fn) : fn);
|
||||
}
|
||||
|
||||
this.queueRunnerFactory({
|
||||
fns: allTimeoutableFns,
|
||||
onException: onException,
|
||||
onComplete: complete
|
||||
});
|
||||
|
||||
function onException(e) {
|
||||
if (Spec.isPendingSpecException(e)) {
|
||||
self.pend();
|
||||
return;
|
||||
}
|
||||
clearTimeoutable();
|
||||
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 +123,7 @@ getJasmineRequireObj().Spec = function(j$) {
|
||||
return 'disabled';
|
||||
}
|
||||
|
||||
if (this.markedPending || !this.encounteredExpectations) {
|
||||
if (this.markedPending) {
|
||||
return 'pending';
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -15,4 +15,4 @@ getJasmineRequireObj().Timer = function() {
|
||||
}
|
||||
|
||||
return Timer;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -6,13 +6,12 @@ getJasmineRequireObj().base = function(j$) {
|
||||
j$.MAX_PRETTY_PRINT_DEPTH = 40;
|
||||
j$.DEFAULT_TIMEOUT_INTERVAL = 5000;
|
||||
|
||||
j$.getGlobal = function() {
|
||||
function getGlobal() {
|
||||
return this;
|
||||
}
|
||||
|
||||
return getGlobal();
|
||||
};
|
||||
j$.getGlobal = (function() {
|
||||
var jasmineGlobal = eval.call(null, "this");
|
||||
return function() {
|
||||
return jasmineGlobal;
|
||||
};
|
||||
})();
|
||||
|
||||
j$.getEnv = function(options) {
|
||||
var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options);
|
||||
@@ -51,18 +50,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 +82,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) {
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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") {
|
||||
|
||||
@@ -16,4 +16,4 @@ jasmineRequire.ResultsNode = function() {
|
||||
}
|
||||
|
||||
return ResultsNode;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -3,4 +3,4 @@ jasmineRequire.html = function(j$) {
|
||||
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
|
||||
j$.QueryString = jasmineRequire.QueryString();
|
||||
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
getJasmineRequireObj().version = function() {
|
||||
return "<%= version %>";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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
3
travis-docs-script.sh
Normal 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
|
||||
Reference in New Issue
Block a user