Compare commits

...

40 Commits

Author SHA1 Message Date
Davis W. Frank & Rajan Agaskar
867de62699 Releasing 1.3
- Allow users to set the pretty-printer's recursion depth
- When pretty-printing objects, don't include inherited properties.
- Change toBeCloseTo matcher to be more consistent
- Added toBeNaN matcher
- Add checkbox to test runner which toggles catching of exceptions duri
- Add config option which stops jasmine from capturing exceptions in a
2012-11-27 13:47:02 -08:00
Rajan Agaskar
74cdc5a04f Merge pull request #290 from maxbrunsfeld/smaller-pretty-print2
smaller, more configurable pretty-printing of objects
2012-10-29 09:32:40 -07:00
Max Brunsfeld
ddbee65aa8 Allow users to set the pretty-printer's recursion depth
Currently, jasmine's pretty printer traverses objects
to 40 levels of nesting. If an object is more deeply
nested than that, an exception is thrown. I find that
after a few levels of nesting, the output becomes
difficult to read. The process of serializing such
deep objects also sometimes crashes the browser or
causes a 'slow script' warning.

This commit exposes a 'MAX_PRETTY_PRINT_DEPTH' option.
It also causes the pretty printer to skip over
parts of an object that are nested to deeply by simply
printing out 'Object' or 'Array', rather than throwing
an exception.
2012-10-28 12:27:26 -07:00
Max Brunsfeld
beeb872a82 When pretty-printing objects, don't include inherited properties.
When making assertions about complex objects, Jasmine's
failure message are sometimes gigantic and difficult
to read because the string representation of an object
contains all of the methods and properties in its
prototype chain. This commit causes the pretty printer
to only display on object's own properties.
2012-10-28 12:27:26 -07:00
Rajan Agaskar
dbcb0b7983 Merge pull request #234 from yopefonic/master
comparison for regExp that compares pattern and modifiers
2012-10-26 19:51:47 -07:00
Joost Elfering
c8436d1d44 adding a check for the sticky regExp option supported by Firefox and accepted by the ES6. Note that the tests for this case are checking for the support of the sticky parameter. the logic is still tested by the other expect statements in browsers that do not support sticky but will never enter that block as creating a regExp with that flag is not allowed. Coverage is still good. See pivotal/jasmine#234 2012-10-27 01:51:19 +01:00
Joost Elfering
639f757f6f added some specs to strengthen the coverage pivotal/jasmine#234 2012-10-27 01:50:34 +01:00
Joost Elfering
d65bdc7e59 resolving issue that was identified via pivotal/jasmine#199 where RegExp objects were not properly compared resulting in non-matching RegExp objects to always return true. a patch to jasmine.Env.equals_ adds an extra step for RexExp objects to be compared. 2012-10-27 01:50:34 +01:00
Rajan Agaskar
a1ed56741b Merge pull request #193 from slackersoft/spy_called_with_messages
less confusing messages for toHaveBeenCalledWith
2012-10-05 17:53:11 -07:00
Rajan Agaskar
7473b455dc Merge pull request #225 from gunnarahlberg/master
spec that to spy on an undefined method throws exception
2012-10-05 17:44:00 -07:00
Rajan Agaskar
b6fb23b069 Merge pull request #254 from jcracknell/nan-matcher
Added toBeNaN matcher
2012-10-05 17:31:36 -07:00
Rajan Agaskar
386e83b53f Merge pull request #280 from ronaldploeger/master
JSDoc @return-tag to 'spyOn' and 'expect' functions
2012-10-05 17:10:51 -07:00
PLOE09
f2b25f1780 Add JSDoc @return-tag to 'spyOn' and 'expect' functions support
code completion in Spket IDE
2012-09-14 16:36:32 +02:00
Davis W. Frank
5ca2888301 Merge pull request #242 from ChrisTM/master
Fix swapped template values in build_standalone_runner.rb.
2012-09-02 22:58:08 -07:00
Davis W. Frank
147cb36760 Merge pull request #269 from kconnor/master
create downloads dir if needed during build_standalone_distribution
2012-09-02 17:42:11 -07:00
Davis W. Frank
107463ad57 Merge pull request #251 from doochik/patch-1
update jsdoc for jasmine.Matchers.prototype.toThrow
2012-09-02 17:40:51 -07:00
Davis W. Frank
39a55d8f10 Merge pull request #257 from kevinoid/no-window-or-exports
Don't assume exports is defined when window is undefined
2012-09-02 17:40:16 -07:00
Rajan Agaskar
4b48dc1069 Merge pull request #260 from rgould/master
Guarantee that afterEach and after blocks are always run
2012-09-01 13:05:41 -07:00
Rajan Agaskar
921f52862f Merge pull request #270 from Wolfy87/patch-1
Wrapped the reserved word, "for", in quotes.
2012-08-15 14:17:29 -07:00
Oliver Caldwell
ea2ffb7b01 Wrapped the reserved word, "for", in quotes.
This stops it throwing errors in IE and other browsers. I think the newer Firefox and Chrome versions are the only browsers to not die when running it.
2012-08-15 21:44:28 +02:00
Kevin Connor
54fbc48eb2 create downloads dir if needed during build_standalone_distribution 2012-08-15 12:41:09 -07:00
Davis W. Frank
06c900ab20 Merge pull request #264 from dburt/master
Change toBeCloseTo matcher to be more consistent
2012-08-12 09:23:15 -07:00
Davis W. Frank
3e070e9db6 Move to an earlier RedCarpet to fix an incompatibility with Rocco. Regen of gh-pages. 2012-08-11 16:53:08 -07:00
Dave Burt
7e04571ec0 Change toBeCloseTo matcher to be more consistent.
It now calculates and compares a difference, rather than rounding
two separate quantities and testing for their equality.
2012-07-31 15:03:55 +10:00
rgould
ddd48f2c88 Regenerate jasmine.js after adding ensured support. 2012-07-24 18:54:36 -04:00
rgould
1c2e50d244 Add 'ensured' blocks to the queue.
This blocks will be run even when a preceeding block sets the abort
flag. This is so that we can support afterEach calls running when the
spec fails due to a timeout.
2012-07-24 18:45:30 -04:00
rgould
d2d60a798d Merge remote-tracking branch 'bigfix/after_waitsFor'
* bigfix/after_waitsFor:
  Test that show that afterEach and after are not being called when a waitsFor times out.
  Test that afterEach is called after a failing spec.
  Consolidate all waitsFor specs in the same describe block.
2012-07-24 16:36:28 -04:00
Kevin Locke
442f3bf872 Don't assume exports is defined when window is undefined
The current code makes the assumption that if window is undefined it is
being run in an environment which supports the CommonJS Modules spec.
This is not the case when Jasmine is being run in rhino or SpiderMonkey
(smjs) without EnvJS.

The fix is simply to check that exports is an object.

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2012-07-19 14:10:39 -06:00
James Cracknell
f910df00bb Added toBeNaN matcher 2012-07-12 20:04:14 -06:00
Alexey Androsov
500b856cfa update jsdoc for jasmine.Matchers.prototype.toThrow
expected argument is optional
2012-07-10 15:12:32 +04:00
Rajan Agaskar
dad4865fbf Merge pull request #221 from rupurt/no_try_catch_multi_commit
No try catch multi commit
2012-06-28 09:56:39 -07:00
Alex Kwiatkowski
1771ec3c63 Add checkbox to test runner which toggles catching of exceptions during tests 2012-06-24 00:02:52 -04:00
Alex Kwiatkowski
2385acedd8 Add config option which stops jasmine from capturing exceptions in a test 2012-06-23 23:12:31 -04:00
Christopher Mitchell
4c28bef387 Fix swapped template values in build_standalone_runner.rb.
`example_source_tags` and `example_spec_tags` each returned what the other
should have returned. I noticed this bug because it made the comments in
SpecRunner.html about where to include spec and source files incongruous with
the example tags that followed.
2012-06-16 17:49:43 -07:00
Davis W. Frank
7bbcf51d45 Removed Frank for GHPages generation. Now using Rocco and a Thor task to build it 2012-05-27 13:16:20 -07:00
Gunnar Ahlberg
4f218f7d6a cover spy on on undefined method 2012-05-02 14:11:22 +02:00
gvanhove
a3ccd8b0d3 less confusing messages for toHaveBeenCalledWith 2012-03-02 19:28:15 -08:00
John Firebaugh
dbcabd397e Test that show that afterEach and after are not being called when a waitsFor times out. 2010-09-29 08:25:58 -07:00
John Firebaugh
a8b0a0ee4f Test that afterEach is called after a failing spec. 2010-09-29 08:19:43 -07:00
John Firebaugh
60a5d60f42 Consolidate all waitsFor specs in the same describe block. 2010-09-28 20:43:50 -07:00
31 changed files with 798 additions and 363 deletions

View File

@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
s.files = Dir.glob("./lib/**/*") + Dir.glob("./lib/jasmine-core/spec/**/*.js")
s.require_paths = ["lib"]
s.add_development_dependency "json_pure", ">= 1.4.3"
s.add_development_dependency "frank"
s.add_development_dependency "tilt"
s.add_development_dependency "sass"
s.add_development_dependency "compass"
s.add_development_dependency "ragaskar-jsdoc_helper"
@@ -26,4 +26,7 @@ Gem::Specification.new do |s|
s.add_development_dependency "awesome_print"
s.add_development_dependency "thor"
s.add_development_dependency "nokogiri"
s.add_development_dependency "redcarpet", "1.7"
s.add_development_dependency "rocco"
s.add_development_dependency "rdiscount"
end

View File

@@ -78,6 +78,7 @@ jasmine.HtmlReporter = function(_doc) {
createReporterDom(runner.env.versionString());
doc.body.appendChild(dom.reporter);
setExceptionHandling();
reporterView = new jasmine.HtmlReporter.ReporterView(dom);
reporterView.addSpecs(specs, self.specFilter);
@@ -131,7 +132,7 @@ jasmine.HtmlReporter = function(_doc) {
}
var paramMap = [];
var params = doc.location.search.substring(1).split('&');
var params = jasmine.HtmlReporter.parameters(doc);
for (var i = 0; i < params.length; i++) {
var p = params[i].split('=');
@@ -151,14 +152,78 @@ jasmine.HtmlReporter = function(_doc) {
self.createDom('span', { className: 'version' }, version)),
dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
dom.alert = self.createDom('div', {className: 'alert'}),
dom.alert = self.createDom('div', {className: 'alert'},
self.createDom('span', { className: 'exceptions' },
self.createDom('label', { className: 'label', for: 'no_try_catch' }, 'No try/catch'),
self.createDom('input', { id: 'no_try_catch', type: 'checkbox' }))),
dom.results = self.createDom('div', {className: 'results'},
dom.summary = self.createDom('div', { className: 'summary' }),
dom.details = self.createDom('div', { id: 'details' }))
);
}
function noTryCatch() {
return window.location.search.match(/catch=false/);
}
function searchWithCatch() {
var params = jasmine.HtmlReporter.parameters(window.document);
var removed = false;
var i = 0;
while (!removed && i < params.length) {
if (params[i].match(/catch=/)) {
params.splice(i, 1);
removed = true;
}
i++;
}
if (jasmine.CATCH_EXCEPTIONS) {
params.push("catch=false");
}
return params.join("&");
}
function setExceptionHandling() {
var chxCatch = document.getElementById('no_try_catch');
if (noTryCatch()) {
chxCatch.setAttribute('checked', true);
jasmine.CATCH_EXCEPTIONS = false;
}
chxCatch.onclick = function() {
window.location.search = searchWithCatch();
};
}
};
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporter.ReporterView = function(dom) {
jasmine.HtmlReporter.parameters = function(doc) {
var paramStr = doc.location.search.substring(1);
var params = [];
if (paramStr.length > 0) {
params = paramStr.split('&');
}
return params;
}
jasmine.HtmlReporter.sectionLink = function(sectionName) {
var link = '?';
var params = [];
if (sectionName) {
params.push('spec=' + encodeURIComponent(sectionName));
}
if (!jasmine.CATCH_EXCEPTIONS) {
params.push("catch=false");
}
if (params.length > 0) {
link += params.join("&");
}
return link;
};
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);
jasmine.HtmlReporter.ReporterView = function(dom) {
this.startedAt = new Date();
this.runningSpecCount = 0;
this.completeSpecCount = 0;
@@ -241,14 +306,14 @@ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporte
// currently running UI
if (isUndefined(this.runningAlert)) {
this.runningAlert = this.createDom('a', {href: "?", className: "runningAlert bar"});
this.runningAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "runningAlert bar" });
dom.alert.appendChild(this.runningAlert);
}
this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);
// skipped specs UI
if (isUndefined(this.skippedAlert)) {
this.skippedAlert = this.createDom('a', {href: "?", className: "skippedAlert bar"});
this.skippedAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "skippedAlert bar" });
}
this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
@@ -259,7 +324,7 @@ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporte
// passing specs UI
if (isUndefined(this.passedAlert)) {
this.passedAlert = this.createDom('span', {href: "?", className: "passingAlert bar"});
this.passedAlert = this.createDom('span', { href: jasmine.HtmlReporter.sectionLink(), className: "passingAlert bar" });
}
this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);
@@ -331,11 +396,11 @@ jasmine.HtmlReporter.SpecView = function(spec, dom, views) {
this.dom.symbolSummary.appendChild(this.symbol);
this.summary = this.createDom('div', { className: 'specSummary' },
this.createDom('a', {
className: 'description',
href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
title: this.spec.getFullName()
}, this.spec.description)
this.createDom('a', {
className: 'description',
href: jasmine.HtmlReporter.sectionLink(this.spec.getFullName()),
title: this.spec.getFullName()
}, this.spec.description)
);
this.detail = this.createDom('div', { className: 'specDetail' },
@@ -406,7 +471,7 @@ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.Ht
this.views = views;
this.element = this.createDom('div', { className: 'suite' },
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(this.suite.getFullName()) }, this.suite.description)
this.createDom('a', { className: 'description', href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()) }, this.suite.description)
);
this.appendToSummary(this.suite, this.element);

View File

@@ -19,6 +19,7 @@ body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
#HTMLReporter .symbolSummary li.pending { line-height: 11px; }
#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
#HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
#HTMLReporter .runningAlert { background-color: #666666; }
#HTMLReporter .skippedAlert { background-color: #aaaaaa; }

View File

@@ -1,4 +1,4 @@
var isCommonJS = typeof window == "undefined";
var isCommonJS = typeof window == "undefined" && typeof exports == "object";
/**
* Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
@@ -34,11 +34,23 @@ jasmine.VERBOSE = false;
*/
jasmine.DEFAULT_UPDATE_INTERVAL = 250;
/**
* Maximum levels of nesting that will be included when an object is pretty-printed
*/
jasmine.MAX_PRETTY_PRINT_DEPTH = 40;
/**
* Default timeout interval in milliseconds for waitsFor() blocks.
*/
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
/**
* By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite.
* Set to false to let the exception bubble up in the browser.
*
*/
jasmine.CATCH_EXCEPTIONS = true;
jasmine.getGlobal = function() {
function getGlobal() {
return this;
@@ -463,7 +475,7 @@ jasmine.log = function() {
* @see jasmine.createSpy
* @param obj
* @param methodName
* @returns a Jasmine spy that can be chained with all spy methods
* @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods
*/
var spyOn = function(obj, methodName) {
return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
@@ -508,6 +520,7 @@ if (isCommonJS) exports.xit = xit;
* jasmine.Matchers functions.
*
* @param {Object} actual Actual value to test against and expected value
* @return {jasmine.Matchers}
*/
var expect = function(actual) {
return jasmine.getEnv().currentSpec.expect(actual);
@@ -867,6 +880,25 @@ jasmine.Env.prototype.xit = function(desc, func) {
};
};
jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) {
if (a.source != b.source)
mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/");
if (a.ignoreCase != b.ignoreCase)
mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier");
if (a.global != b.global)
mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier");
if (a.multiline != b.multiline)
mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier");
if (a.sticky != b.sticky)
mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier");
return (mismatchValues.length === 0);
};
jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
return true;
@@ -953,6 +985,10 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
return (a == b);
}
if (a instanceof RegExp && b instanceof RegExp) {
return this.compareRegExps_(a, b, mismatchKeys, mismatchValues);
}
if (typeof a === "object" && typeof b === "object") {
return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
}
@@ -1019,11 +1055,16 @@ jasmine.Block = function(env, func, spec) {
this.spec = spec;
};
jasmine.Block.prototype.execute = function(onComplete) {
try {
jasmine.Block.prototype.execute = function(onComplete) {
if (!jasmine.CATCH_EXCEPTIONS) {
this.func.apply(this.spec);
} catch (e) {
this.spec.fail(e);
}
else {
try {
this.func.apply(this.spec);
} catch (e) {
this.spec.fail(e);
}
}
onComplete();
};
@@ -1281,6 +1322,17 @@ jasmine.Matchers.prototype.toBeNull = function() {
return (this.actual === null);
};
/**
* Matcher that compares the actual to NaN.
*/
jasmine.Matchers.prototype.toBeNaN = function() {
this.message = function() {
return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ];
};
return (this.actual !== this.actual);
};
/**
* Matcher that boolean not-nots the actual.
*/
@@ -1358,18 +1410,14 @@ jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function() {
var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was.";
var positiveMessage = "";
if (this.actual.callCount === 0) {
// todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
return [
"Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
"Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
];
positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.";
} else {
return [
"Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
"Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
];
positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but actual calls were " + jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g, '')
}
return [positiveMessage, invertedMessage];
};
return this.env.contains_(this.actual.argsForCall, expectedArgs);
@@ -1427,22 +1475,19 @@ jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
* up to a given level of decimal precision (default 2).
*
* @param {Number} expected
* @param {Number} precision
* @param {Number} precision, as number of decimal places
*/
jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
if (!(precision === 0)) {
precision = precision || 2;
}
var multiplier = Math.pow(10, precision);
var actual = Math.round(this.actual * multiplier);
expected = Math.round(expected * multiplier);
return expected == actual;
return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2);
};
/**
* Matcher that checks that the expected exception was thrown by the actual.
*
* @param {String} expected
* @param {String} [expected]
*/
jasmine.Matchers.prototype.toThrow = function(expected) {
var result = false;
@@ -1840,10 +1885,6 @@ jasmine.PrettyPrinter = function() {
* @param value
*/
jasmine.PrettyPrinter.prototype.format = function(value) {
if (this.ppNestLevel_ > 40) {
throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
}
this.ppNestLevel_++;
try {
if (value === jasmine.undefined) {
@@ -1886,6 +1927,7 @@ jasmine.PrettyPrinter.prototype.format = function(value) {
jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
for (var property in obj) {
if (!obj.hasOwnProperty(property)) continue;
if (property == '__Jasmine_been_here_before__') continue;
fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
obj.__lookupGetter__(property) !== null) : false);
@@ -1913,6 +1955,11 @@ jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
};
jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
this.append("Array");
return;
}
this.append('[ ');
for (var i = 0; i < array.length; i++) {
if (i > 0) {
@@ -1924,6 +1971,11 @@ jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
};
jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
this.append("Object");
return;
}
var self = this;
this.append('{ ');
var first = true;
@@ -1952,6 +2004,10 @@ jasmine.StringPrettyPrinter.prototype.append = function(value) {
};
jasmine.Queue = function(env) {
this.env = env;
// parallel to blocks. each true value in this array means the block will
// get executed even if we abort
this.ensured = [];
this.blocks = [];
this.running = false;
this.index = 0;
@@ -1959,15 +2015,30 @@ jasmine.Queue = function(env) {
this.abort = false;
};
jasmine.Queue.prototype.addBefore = function(block) {
jasmine.Queue.prototype.addBefore = function(block, ensure) {
if (ensure === jasmine.undefined) {
ensure = false;
}
this.blocks.unshift(block);
this.ensured.unshift(ensure);
};
jasmine.Queue.prototype.add = function(block) {
jasmine.Queue.prototype.add = function(block, ensure) {
if (ensure === jasmine.undefined) {
ensure = false;
}
this.blocks.push(block);
this.ensured.push(ensure);
};
jasmine.Queue.prototype.insertNext = function(block) {
jasmine.Queue.prototype.insertNext = function(block, ensure) {
if (ensure === jasmine.undefined) {
ensure = false;
}
this.ensured.splice((this.index + this.offset + 1), 0, ensure);
this.blocks.splice((this.index + this.offset + 1), 0, block);
this.offset++;
};
@@ -1991,7 +2062,7 @@ jasmine.Queue.prototype.next_ = function() {
while (goAgain) {
goAgain = false;
if (self.index < self.blocks.length && !this.abort) {
if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) {
var calledSynchronously = true;
var completedSynchronously = false;
@@ -2282,7 +2353,7 @@ jasmine.Spec.prototype.finish = function(onComplete) {
jasmine.Spec.prototype.after = function(doAfter) {
if (this.queue.isRunning()) {
this.queue.add(new jasmine.Block(this.env, doAfter, this));
this.queue.add(new jasmine.Block(this.env, doAfter, this), true);
} else {
this.afterCallbacks.unshift(doAfter);
}
@@ -2320,15 +2391,15 @@ jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
}
for (i = 0; i < this.afterCallbacks.length; i++) {
this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true);
}
for (suite = this.suite; suite; suite = suite.parentSuite) {
for (i = 0; i < suite.after_.length; i++) {
this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true);
}
}
for (i = 0; i < runner.after_.length; i++) {
this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true);
}
};
@@ -2523,7 +2594,7 @@ jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
jasmine.version_= {
"major": 1,
"minor": 2,
"minor": 3,
"build": 0,
"revision": 1337005947
"revision": 1354052693
};

View File

@@ -1,6 +1,6 @@
module Jasmine
module Core
VERSION = "1.2.0"
VERSION = "1.3.0"
end
end

2
pages

Submodule pages updated: b928db73fc...00ba05c213

View File

@@ -32,118 +32,144 @@ describe('Exceptions:', function() {
expect(jasmine.util.formatException(sampleWebkitException)).toEqual(expected);
});
it('should handle exceptions thrown, but continue', function() {
var fakeTimer = new jasmine.FakeTimer();
env.setTimeout = fakeTimer.setTimeout;
env.clearTimeout = fakeTimer.clearTimeout;
env.setInterval = fakeTimer.setInterval;
env.clearInterval = fakeTimer.clearInterval;
//we run two exception tests to make sure we continue after throwing an exception
var suite = env.describe('Suite for handles exceptions', function () {
env.it('should be a test that fails because it throws an exception', function() {
throw new Error('fake error 1');
});
env.it('should be another test that fails because it throws an exception', function() {
this.runs(function () {
throw new Error('fake error 2');
describe('with break on exception', function() {
it('should not catch the exception', function() {
var suite = env.describe('suite for break on exceptions', function() {
env.it('should break when an exception is thrown', function() {
throw new Error('I should hit a breakpoint!');
});
this.runs(function () {
});
var runner = env.currentRunner();
var dont_change = 'I will never change!';
var oldCatch = jasmine.CATCH_EXCEPTIONS;
jasmine.CATCH_EXCEPTIONS = false;
try {
suite.execute();
dont_change = 'oops I changed';
}
catch (e) {}
finally {
jasmine.CATCH_EXCEPTIONS = oldCatch;
}
expect(dont_change).toEqual('I will never change!');
});
});
describe("with catch on exception", function() {
it('should handle exceptions thrown, but continue', function() {
var fakeTimer = new jasmine.FakeTimer();
env.setTimeout = fakeTimer.setTimeout;
env.clearTimeout = fakeTimer.clearTimeout;
env.setInterval = fakeTimer.setInterval;
env.clearInterval = fakeTimer.clearInterval;
//we run two exception tests to make sure we continue after throwing an exception
var suite = env.describe('Suite for handles exceptions', function () {
env.it('should be a test that fails because it throws an exception', function() {
throw new Error('fake error 1');
});
env.it('should be another test that fails because it throws an exception', function() {
this.runs(function () {
throw new Error('fake error 2');
});
this.runs(function () {
this.expect(true).toEqual(true);
});
});
env.it('should be a passing test that runs after exceptions are thrown', function() {
this.expect(true).toEqual(true);
});
env.it('should be another test that fails because it throws an exception after a wait', function() {
this.runs(function () {
var foo = 'foo';
});
this.waits(250);
this.runs(function () {
throw new Error('fake error 3');
});
});
env.it('should be a passing test that runs after exceptions are thrown from a async test', function() {
this.expect(true).toEqual(true);
});
});
env.it('should be a passing test that runs after exceptions are thrown', function() {
this.expect(true).toEqual(true);
});
var runner = env.currentRunner();
suite.execute();
fakeTimer.tick(2500);
env.it('should be another test that fails because it throws an exception after a wait', function() {
this.runs(function () {
var foo = 'foo';
});
this.waits(250);
this.runs(function () {
throw new Error('fake error 3');
});
});
var suiteResults = suite.results();
var specResults = suiteResults.getItems();
env.it('should be a passing test that runs after exceptions are thrown from a async test', function() {
this.expect(true).toEqual(true);
});
expect(suiteResults.passed()).toEqual(false);
//
expect(specResults.length).toEqual(5);
expect(specResults[0].passed()).toMatch(false);
var blockResults = specResults[0].getItems();
expect(blockResults[0].passed()).toEqual(false);
expect(blockResults[0].message).toMatch(/fake error 1/);
expect(specResults[1].passed()).toEqual(false);
blockResults = specResults[1].getItems();
expect(blockResults[0].passed()).toEqual(false);
expect(blockResults[0].message).toMatch(/fake error 2/);
expect(blockResults[1].passed()).toEqual(true);
expect(specResults[2].passed()).toEqual(true);
expect(specResults[3].passed()).toEqual(false);
blockResults = specResults[3].getItems();
expect(blockResults[0].message).toMatch(/fake error 3/);
expect(specResults[4].passed()).toEqual(true);
});
var runner = env.currentRunner();
suite.execute();
fakeTimer.tick(2500);
var suiteResults = suite.results();
var specResults = suiteResults.getItems();
expect(suiteResults.passed()).toEqual(false);
//
expect(specResults.length).toEqual(5);
expect(specResults[0].passed()).toMatch(false);
var blockResults = specResults[0].getItems();
expect(blockResults[0].passed()).toEqual(false);
expect(blockResults[0].message).toMatch(/fake error 1/);
expect(specResults[1].passed()).toEqual(false);
blockResults = specResults[1].getItems();
expect(blockResults[0].passed()).toEqual(false);
expect(blockResults[0].message).toMatch(/fake error 2/);
expect(blockResults[1].passed()).toEqual(true);
expect(specResults[2].passed()).toEqual(true);
expect(specResults[3].passed()).toEqual(false);
blockResults = specResults[3].getItems();
expect(blockResults[0].message).toMatch(/fake error 3/);
expect(specResults[4].passed()).toEqual(true);
});
it("should handle exceptions thrown directly in top-level describe blocks and continue", function () {
var suite = env.describe("a top level describe block that throws an exception", function () {
env.it("is a test that should pass", function () {
it("should handle exceptions thrown directly in top-level describe blocks and continue", function () {
var suite = env.describe("a top level describe block 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");
});
throw new Error("top level error");
});
suite.execute();
var suiteResults = suite.results();
var specResults = suiteResults.getItems();
suite.execute();
var suiteResults = suite.results();
var specResults = suiteResults.getItems();
expect(suiteResults.passed()).toEqual(false);
expect(specResults.length).toEqual(2);
expect(suiteResults.passed()).toEqual(false);
expect(specResults.length).toEqual(2);
expect(specResults[1].description).toMatch(/encountered a declaration exception/);
});
expect(specResults[1].description).toMatch(/encountered a declaration exception/);
});
it("should handle exceptions thrown directly in nested describe blocks and continue", function () {
var suite = env.describe("a top level describe", function () {
env.describe("a mid-level describe that throws an exception", function () {
env.it("is a test that should pass", function () {
this.expect(true).toEqual(true);
});
it("should handle exceptions thrown directly in nested describe blocks and continue", function () {
var suite = env.describe("a top level describe", function () {
env.describe("a mid-level describe that throws an exception", function () {
env.it("is a test that should pass", function () {
this.expect(true).toEqual(true);
});
throw new Error("a mid-level error");
});
});
throw new Error("a mid-level error");
});
});
suite.execute();
var suiteResults = suite.results();
var specResults = suiteResults.getItems();
suite.execute();
var suiteResults = suite.results();
var specResults = suiteResults.getItems();
expect(suiteResults.passed()).toEqual(false);
expect(specResults.length).toEqual(1);
expect(suiteResults.passed()).toEqual(false);
expect(specResults.length).toEqual(1);
var nestedSpecResults = specResults[0].getItems();
var nestedSpecResults = specResults[0].getItems();
expect(nestedSpecResults.length).toEqual(2);
expect(nestedSpecResults[1].description).toMatch(/encountered a declaration exception/);
});
});
expect(nestedSpecResults.length).toEqual(2);
expect(nestedSpecResults[1].description).toMatch(/encountered a declaration exception/);
});
});
});

View File

@@ -75,6 +75,18 @@ describe("jasmine.Matchers", function() {
expect((match(parseInt('5', 10)).toEqual(5))).toPass();
expect((match(5).toNotEqual(5))).toFail();
expect((match(parseInt('5', 10)).toNotEqual(5))).toFail();
expect((match(/1/i).toEqual(/1/i))).toPass();
expect((match(/1/i).toNotEqual(/1/i))).toFail();
expect((match(/[abc]/gm).toEqual(/1/i))).toFail();
expect((match(/[abc]/gm).toNotEqual(/1/i))).toPass();
// only test if the browser supports the sticky option on a regExp see pull #234
if (RegExp.prototype.sticky !== undefined) {
var sticky_regexp = new RegExp("[abc]", "y");
expect((match(sticky_regexp).toEqual(/1/i))).toFail();
expect((match(sticky_regexp).toNotEqual(/1/i))).toPass();
}
});
it("toEqual to build an Expectation Result", function() {
@@ -281,6 +293,29 @@ describe("jasmine.Matchers", function() {
expect(result.actual).toEqual(actual);
});
it("toBeNaN", function() {
expect(match(Number.NaN).toBeNaN()).toPass();
expect(match(0).toBeNaN()).toFail();
expect(match(1).toBeNaN()).toFail();
expect(match(null).toBeNaN()).toFail();
expect(match(Number.POSITIVE_INFINITY).toBeNaN()).toFail();
expect(match(Number.NEGATIVE_INFINITY).toBeNaN()).toFail();
expect(match('NaN').toBeNaN()).toFail();
});
it("toBeNaN to build an ExpectationResult", function() {
var actual = 'a';
var matcher = match(actual);
matcher.toBeNaN();
var result = lastResult();
expect(result.matcherName).toEqual("toBeNaN");
expect(result.passed()).toFail();
expect(result.message).toMatch("Expected 'a' to be NaN.");
expect(result.actual).toMatch(actual);
});
it("toBeFalsy", function() {
expect(match(false).toBeFalsy()).toPass();
expect(match(true).toBeFalsy()).toFail();
@@ -510,6 +545,11 @@ describe("jasmine.Matchers", function() {
expect(-1.23).not.toBeCloseTo(-1.24);
});
it("expects close numbers to 'be close' and further numbers not to", function() {
expect(1.225).not.toBeCloseTo(1.234); // difference is 0.009
expect(1.225).toBeCloseTo(1.224); // difference is 0.001
});
it("accepts an optional precision argument", function() {
expect(1).toBeCloseTo(1.1, 0);
expect(1.2).toBeCloseTo(1.23, 1);
@@ -771,7 +811,13 @@ describe("jasmine.Matchers", function() {
TestClass.spyFunction('d', 'e', 'f');
var expected = match(TestClass.spyFunction);
expect(expected.toHaveBeenCalledWith('a', 'b')).toFail();
expect(lastResult().message).toEqual("Expected spy My spy to have been called with [ 'a', 'b' ] but was called with [ [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] ]");
expect(lastResult().message).toEqual("Expected spy My spy to have been called with [ 'a', 'b' ] but actual calls were [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ]");
});
it("should return a decent message when it hasn't been called", function() {
var expected = match(TestClass.spyFunction);
expect(expected.toHaveBeenCalledWith('a', 'b')).toFail();
expect(lastResult().message).toEqual("Expected spy My spy to have been called with [ 'a', 'b' ] but it was never called.");
});
it("should return a decent message when inverted", function() {
@@ -779,7 +825,7 @@ describe("jasmine.Matchers", function() {
TestClass.spyFunction('d', 'e', 'f');
var expected = match(TestClass.spyFunction);
expect(expected.not.toHaveBeenCalledWith('a', 'b', 'c')).toFail();
expect(lastResult().message).toEqual("Expected spy My spy not to have been called with [ 'a', 'b', 'c' ] but was called with [ [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] ]");
expect(lastResult().message).toEqual("Expected spy My spy not to have been called with [ 'a', 'b', 'c' ] but it was.");
});
it('should throw an exception when invoked on a non-spy', shouldThrowAnExceptionWhenInvokedOnANonSpy('toHaveBeenCalledWith'));

View File

@@ -32,6 +32,36 @@ describe("jasmine.pp", function () {
}, bar: [1, 2, 3]})).toEqual("{ foo : Function, bar : [ 1, 2, 3 ] }");
});
it("should not include inherited properties when stringifying an object", function() {
var SomeClass = function() {};
SomeClass.prototype.foo = "inherited foo";
var instance = new SomeClass();
instance.bar = "my own bar";
expect(jasmine.pp(instance)).toEqual("{ bar : 'my own bar' }");
});
it("should not recurse objects and arrays more deeply than jasmine.MAX_PRETTY_PRINT_DEPTH", function() {
var originalMaxDepth = jasmine.MAX_PRETTY_PRINT_DEPTH;
var nestedObject = { level1: { level2: { level3: { level4: "leaf" } } } };
var nestedArray = [1, [2, [3, [4, "leaf"]]]];
try {
jasmine.MAX_PRETTY_PRINT_DEPTH = 2;
expect(jasmine.pp(nestedObject)).toEqual("{ level1 : { level2 : Object } }");
expect(jasmine.pp(nestedArray)).toEqual("[ 1, [ 2, Array ] ]");
jasmine.MAX_PRETTY_PRINT_DEPTH = 3;
expect(jasmine.pp(nestedObject)).toEqual("{ level1 : { level2 : { level3 : Object } } }");
expect(jasmine.pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, Array ] ] ]");
jasmine.MAX_PRETTY_PRINT_DEPTH = 4;
expect(jasmine.pp(nestedObject)).toEqual("{ level1 : { level2 : { level3 : { level4 : 'leaf' } } } }");
expect(jasmine.pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, [ 4, 'leaf' ] ] ] ]");
} finally {
jasmine.MAX_PRETTY_PRINT_DEPTH = originalMaxDepth;
}
});
it("should stringify RegExp objects properly", function() {
expect(jasmine.pp(/x|y|z/)).toEqual("/x|y|z/");
});

View File

@@ -105,6 +105,19 @@ describe('RunnerTest', function() {
expect(runnerResults.totalCount).toEqual(3);
expect(runnerResults.passedCount).toEqual(3);
});
it('should run after a failing spec', function () {
var afterEach = jasmine.createSpy();
env.afterEach(afterEach);
env.describe('suite', function () {
env.it('fails', function () {
this.explodes();
});
}).execute();
expect(afterEach).toHaveBeenCalled();
});
});

View File

@@ -398,6 +398,123 @@ describe("jasmine spec running", function () {
expect(timeoutSpec.results().getItems()[0].message).toEqual('timeout: timed out after 500 msec waiting for something to happen');
expect(subsequentSpecRan).toEqual(true);
});
it("runs afterEach after timing out", function() {
var afterEach = jasmine.createSpy('afterEach');
env.describe('foo', function () {
env.afterEach(afterEach);
env.it('waitsFor', function () {
this.waitsFor(100, function() {
return false;
});
});
}).execute();
fakeTimer.tick(500);
expect(afterEach).toHaveBeenCalled();
});
it("runs single-spec after functions after timing out", function() {
var after = jasmine.createSpy('after');
env.describe('foo', function () {
env.it('waitsFor', function () {
this.after(after);
this.waitsFor(100, function() {
return false;
});
});
}).execute();
fakeTimer.tick(500);
expect(after).toHaveBeenCalled();
});
describe('with consecutive calls', function () {
var foo;
beforeEach(function () {
foo = 0;
});
it('exits immediately (does not stack) if the latchFunction times out', function () {
var reachedFirstWaitsFor = false;
var reachedSecondWaitsFor = false;
env.describe('suite that waits', function () {
env.it('should stack timeouts', function() {
this.waitsFor(500, function () {
reachedFirstWaitsFor = true;
return false;
});
this.waitsFor(500, function () {
reachedSecondWaitsFor = true;
});
this.runs(function () {
foo++;
});
});
});
expect(reachedFirstWaitsFor).toEqual(false);
env.execute();
expect(reachedFirstWaitsFor).toEqual(true);
expect(foo).toEqual(0);
expect(reachedSecondWaitsFor).toEqual(false);
fakeTimer.tick(500);
expect(reachedSecondWaitsFor).toEqual(false);
expect(foo).toEqual(0);
fakeTimer.tick(500);
expect(reachedSecondWaitsFor).toEqual(false);
expect(foo).toEqual(0);
});
it('stacks latchFunctions', function () {
var firstWaitsResult = false;
var secondWaitsResult = false;
var waitsSuite = env.describe('suite that waits', function () {
env.it('spec with waitsFors', function() {
this.waitsFor(600, function () {
fakeTimer.setTimeout(function () {
firstWaitsResult = true;
}, 300);
return firstWaitsResult;
});
this.waitsFor(600, function () {
fakeTimer.setTimeout(function () {
secondWaitsResult = true;
}, 300);
return secondWaitsResult;
});
this.runs(function () {
foo++;
});
});
});
expect(firstWaitsResult).toEqual(false);
expect(secondWaitsResult).toEqual(false);
waitsSuite.execute();
expect(firstWaitsResult).toEqual(false);
expect(secondWaitsResult).toEqual(false);
expect(foo).toEqual(0);
fakeTimer.tick(300);
expect(firstWaitsResult).toEqual(true);
expect(secondWaitsResult).toEqual(false);
expect(foo).toEqual(0);
fakeTimer.tick(300);
expect(firstWaitsResult).toEqual(true);
expect(secondWaitsResult).toEqual(true);
expect(foo).toEqual(1);
});
});
});
it("testSpecAfter", function() {
@@ -579,90 +696,6 @@ describe("jasmine spec running", function () {
expect(quux).toEqual(1);
});
describe('#waitsFor should allow consecutive calls', function () {
var foo;
beforeEach(function () {
foo = 0;
});
it('exits immediately (does not stack) if the latchFunction times out', function () {
var reachedFirstWaitsFor = false;
var reachedSecondWaitsFor = false;
env.describe('suite that waits', function () {
env.it('should stack timeouts', function() {
this.waitsFor(500, function () {
reachedFirstWaitsFor = true;
return false;
});
this.waitsFor(500, function () {
reachedSecondWaitsFor = true;
});
this.runs(function () {
foo++;
});
});
});
expect(reachedFirstWaitsFor).toEqual(false);
env.execute();
expect(reachedFirstWaitsFor).toEqual(true);
expect(foo).toEqual(0);
expect(reachedSecondWaitsFor).toEqual(false);
fakeTimer.tick(500);
expect(reachedSecondWaitsFor).toEqual(false);
expect(foo).toEqual(0);
fakeTimer.tick(500);
expect(reachedSecondWaitsFor).toEqual(false);
expect(foo).toEqual(0);
});
it('stacks latchFunctions', function () {
var firstWaitsResult = false;
var secondWaitsResult = false;
var waitsSuite = env.describe('suite that waits', function () {
env.it('spec with waitsFors', function() {
this.waitsFor(600, function () {
fakeTimer.setTimeout(function () {
firstWaitsResult = true;
}, 300);
return firstWaitsResult;
});
this.waitsFor(600, function () {
fakeTimer.setTimeout(function () {
secondWaitsResult = true;
}, 300);
return secondWaitsResult;
});
this.runs(function () {
foo++;
});
});
});
expect(firstWaitsResult).toEqual(false);
expect(secondWaitsResult).toEqual(false);
waitsSuite.execute();
expect(firstWaitsResult).toEqual(false);
expect(secondWaitsResult).toEqual(false);
expect(foo).toEqual(0);
fakeTimer.tick(300);
expect(firstWaitsResult).toEqual(true);
expect(secondWaitsResult).toEqual(false);
expect(foo).toEqual(0);
fakeTimer.tick(300);
expect(firstWaitsResult).toEqual(true);
expect(secondWaitsResult).toEqual(true);
expect(foo).toEqual(1);
});
});
it("#beforeEach should be able to eval runs and waits blocks", function () {
var foo = 0;
var bar = 0;

View File

@@ -165,6 +165,21 @@ describe('Spies', function () {
expect(exception).toBeDefined();
});
it('to spy on an undefined method throws exception', function() {
var TestClass = {
someFunction : function() {
}
};
function efunc() {
this.spyOn(TestClass, 'someOtherFunction');
};
expect(function() {
efunc();
}).toThrow('someOtherFunction() method does not exist');
});
it('should be able to reset a spy', function() {
var TestClass = { someFunction: function() {} };
this.spyOn(TestClass, 'someFunction');

View File

@@ -36,34 +36,25 @@ describe "Build Github Pages task" do
@output.should match(/Building Github Pages/)
end
it "should tell the user the pages are built" do
@output.should match(/Congratulations, project dumped to/)
end
it "should copy the latest jasmine files to the pages dir" do
['jasmine.js', 'jasmine.css', 'jasmine-html.js'].each do |lib_file|
source = File.read(File.join(project_root, 'lib', 'jasmine-core', lib_file))
dest = File.read(File.join(pages_dir, 'lib', lib_file))
it "should build the pages output to the requested diretory" do
Dir.chdir File.join(pages_dir, 'pages_output') do
pages = Dir.glob(File.join('**', '*'))
pages.should include('download.html')
pages.should include('index.html')
pages.should include(File.join('images', 'jasmine_logo.png'))
pages.should include(File.join('images', 'pivotal_logo.gif'))
pages.should include(File.join('css', 'pygments.css'))
pages.should include(File.join('css', 'screen.css'))
source.should == dest
end
end
it "should copy the generated page files to the destination directory" do
Dir.chdir pages_dir do
pages = Dir.glob(File.join('**', '*'))
it "should build a new page" do
@output.should match(/rocco/)
File.exist?(File.join(pages_dir, 'introduction.html')).should be_true
end
pages.should include('download.html')
pages.should include('index.html')
pages.should include(File.join('images', 'jasmine_logo.png'))
pages.should include(File.join('images', 'pivotal_logo.gif'))
pages.should include(File.join('css', 'pygments.css'))
pages.should include(File.join('css', 'screen.css'))
end
it "should copy the rocco output to index.html" do
introduction = File.read(File.join(pages_dir, 'introduction.html'))
index = File.read(File.join(pages_dir, 'index.html'))
index.should == introduction
end
end
end

View File

@@ -12,11 +12,16 @@ jasmine.Block = function(env, func, spec) {
this.spec = spec;
};
jasmine.Block.prototype.execute = function(onComplete) {
try {
jasmine.Block.prototype.execute = function(onComplete) {
if (!jasmine.CATCH_EXCEPTIONS) {
this.func.apply(this.spec);
} catch (e) {
this.spec.fail(e);
}
else {
try {
this.func.apply(this.spec);
} catch (e) {
this.spec.fail(e);
}
}
onComplete();
};

View File

@@ -168,6 +168,25 @@ jasmine.Env.prototype.xit = function(desc, func) {
};
};
jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) {
if (a.source != b.source)
mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/");
if (a.ignoreCase != b.ignoreCase)
mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier");
if (a.global != b.global)
mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier");
if (a.multiline != b.multiline)
mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier");
if (a.sticky != b.sticky)
mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier");
return (mismatchValues.length === 0);
};
jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
return true;
@@ -254,6 +273,10 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
return (a == b);
}
if (a instanceof RegExp && b instanceof RegExp) {
return this.compareRegExps_(a, b, mismatchKeys, mismatchValues);
}
if (typeof a === "object" && typeof b === "object") {
return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
}

View File

@@ -150,6 +150,17 @@ jasmine.Matchers.prototype.toBeNull = function() {
return (this.actual === null);
};
/**
* Matcher that compares the actual to NaN.
*/
jasmine.Matchers.prototype.toBeNaN = function() {
this.message = function() {
return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ];
};
return (this.actual !== this.actual);
};
/**
* Matcher that boolean not-nots the actual.
*/
@@ -227,18 +238,14 @@ jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function() {
var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was.";
var positiveMessage = "";
if (this.actual.callCount === 0) {
// todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
return [
"Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
"Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
];
positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.";
} else {
return [
"Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
"Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
];
positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but actual calls were " + jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g, '')
}
return [positiveMessage, invertedMessage];
};
return this.env.contains_(this.actual.argsForCall, expectedArgs);
@@ -296,22 +303,19 @@ jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
* up to a given level of decimal precision (default 2).
*
* @param {Number} expected
* @param {Number} precision
* @param {Number} precision, as number of decimal places
*/
jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
if (!(precision === 0)) {
precision = precision || 2;
}
var multiplier = Math.pow(10, precision);
var actual = Math.round(this.actual * multiplier);
expected = Math.round(expected * multiplier);
return expected == actual;
return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2);
};
/**
* Matcher that checks that the expected exception was thrown by the actual.
*
* @param {String} expected
* @param {String} [expected]
*/
jasmine.Matchers.prototype.toThrow = function(expected) {
var result = false;

View File

@@ -11,10 +11,6 @@ jasmine.PrettyPrinter = function() {
* @param value
*/
jasmine.PrettyPrinter.prototype.format = function(value) {
if (this.ppNestLevel_ > 40) {
throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
}
this.ppNestLevel_++;
try {
if (value === jasmine.undefined) {
@@ -57,6 +53,7 @@ jasmine.PrettyPrinter.prototype.format = function(value) {
jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
for (var property in obj) {
if (!obj.hasOwnProperty(property)) continue;
if (property == '__Jasmine_been_here_before__') continue;
fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
obj.__lookupGetter__(property) !== null) : false);
@@ -84,6 +81,11 @@ jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
};
jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
this.append("Array");
return;
}
this.append('[ ');
for (var i = 0; i < array.length; i++) {
if (i > 0) {
@@ -95,6 +97,11 @@ jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
};
jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
this.append("Object");
return;
}
var self = this;
this.append('{ ');
var first = true;

View File

@@ -1,5 +1,9 @@
jasmine.Queue = function(env) {
this.env = env;
// parallel to blocks. each true value in this array means the block will
// get executed even if we abort
this.ensured = [];
this.blocks = [];
this.running = false;
this.index = 0;
@@ -7,15 +11,30 @@ jasmine.Queue = function(env) {
this.abort = false;
};
jasmine.Queue.prototype.addBefore = function(block) {
jasmine.Queue.prototype.addBefore = function(block, ensure) {
if (ensure === jasmine.undefined) {
ensure = false;
}
this.blocks.unshift(block);
this.ensured.unshift(ensure);
};
jasmine.Queue.prototype.add = function(block) {
jasmine.Queue.prototype.add = function(block, ensure) {
if (ensure === jasmine.undefined) {
ensure = false;
}
this.blocks.push(block);
this.ensured.push(ensure);
};
jasmine.Queue.prototype.insertNext = function(block) {
jasmine.Queue.prototype.insertNext = function(block, ensure) {
if (ensure === jasmine.undefined) {
ensure = false;
}
this.ensured.splice((this.index + this.offset + 1), 0, ensure);
this.blocks.splice((this.index + this.offset + 1), 0, block);
this.offset++;
};
@@ -39,7 +58,7 @@ jasmine.Queue.prototype.next_ = function() {
while (goAgain) {
goAgain = false;
if (self.index < self.blocks.length && !this.abort) {
if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) {
var calledSynchronously = true;
var completedSynchronously = false;

View File

@@ -154,7 +154,7 @@ jasmine.Spec.prototype.finish = function(onComplete) {
jasmine.Spec.prototype.after = function(doAfter) {
if (this.queue.isRunning()) {
this.queue.add(new jasmine.Block(this.env, doAfter, this));
this.queue.add(new jasmine.Block(this.env, doAfter, this), true);
} else {
this.afterCallbacks.unshift(doAfter);
}
@@ -192,15 +192,15 @@ jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
}
for (i = 0; i < this.afterCallbacks.length; i++) {
this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true);
}
for (suite = this.suite; suite; suite = suite.parentSuite) {
for (i = 0; i < suite.after_.length; i++) {
this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true);
}
}
for (i = 0; i < runner.after_.length; i++) {
this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true);
}
};

View File

@@ -1,4 +1,4 @@
var isCommonJS = typeof window == "undefined";
var isCommonJS = typeof window == "undefined" && typeof exports == "object";
/**
* Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
@@ -34,11 +34,23 @@ jasmine.VERBOSE = false;
*/
jasmine.DEFAULT_UPDATE_INTERVAL = 250;
/**
* Maximum levels of nesting that will be included when an object is pretty-printed
*/
jasmine.MAX_PRETTY_PRINT_DEPTH = 40;
/**
* Default timeout interval in milliseconds for waitsFor() blocks.
*/
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
/**
* By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite.
* Set to false to let the exception bubble up in the browser.
*
*/
jasmine.CATCH_EXCEPTIONS = true;
jasmine.getGlobal = function() {
function getGlobal() {
return this;
@@ -463,7 +475,7 @@ jasmine.log = function() {
* @see jasmine.createSpy
* @param obj
* @param methodName
* @returns a Jasmine spy that can be chained with all spy methods
* @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods
*/
var spyOn = function(obj, methodName) {
return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
@@ -508,6 +520,7 @@ if (isCommonJS) exports.xit = xit;
* jasmine.Matchers functions.
*
* @param {Object} actual Actual value to test against and expected value
* @return {jasmine.Matchers}
*/
var expect = function(actual) {
return jasmine.getEnv().currentSpec.expect(actual);

View File

@@ -18,6 +18,7 @@ jasmine.HtmlReporter = function(_doc) {
createReporterDom(runner.env.versionString());
doc.body.appendChild(dom.reporter);
setExceptionHandling();
reporterView = new jasmine.HtmlReporter.ReporterView(dom);
reporterView.addSpecs(specs, self.specFilter);
@@ -71,7 +72,7 @@ jasmine.HtmlReporter = function(_doc) {
}
var paramMap = [];
var params = doc.location.search.substring(1).split('&');
var params = jasmine.HtmlReporter.parameters(doc);
for (var i = 0; i < params.length; i++) {
var p = params[i].split('=');
@@ -91,11 +92,74 @@ jasmine.HtmlReporter = function(_doc) {
self.createDom('span', { className: 'version' }, version)),
dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
dom.alert = self.createDom('div', {className: 'alert'}),
dom.alert = self.createDom('div', {className: 'alert'},
self.createDom('span', { className: 'exceptions' },
self.createDom('label', { className: 'label', for: 'no_try_catch' }, 'No try/catch'),
self.createDom('input', { id: 'no_try_catch', type: 'checkbox' }))),
dom.results = self.createDom('div', {className: 'results'},
dom.summary = self.createDom('div', { className: 'summary' }),
dom.details = self.createDom('div', { id: 'details' }))
);
}
function noTryCatch() {
return window.location.search.match(/catch=false/);
}
function searchWithCatch() {
var params = jasmine.HtmlReporter.parameters(window.document);
var removed = false;
var i = 0;
while (!removed && i < params.length) {
if (params[i].match(/catch=/)) {
params.splice(i, 1);
removed = true;
}
i++;
}
if (jasmine.CATCH_EXCEPTIONS) {
params.push("catch=false");
}
return params.join("&");
}
function setExceptionHandling() {
var chxCatch = document.getElementById('no_try_catch');
if (noTryCatch()) {
chxCatch.setAttribute('checked', true);
jasmine.CATCH_EXCEPTIONS = false;
}
chxCatch.onclick = function() {
window.location.search = searchWithCatch();
};
}
};
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);
jasmine.HtmlReporter.parameters = function(doc) {
var paramStr = doc.location.search.substring(1);
var params = [];
if (paramStr.length > 0) {
params = paramStr.split('&');
}
return params;
}
jasmine.HtmlReporter.sectionLink = function(sectionName) {
var link = '?';
var params = [];
if (sectionName) {
params.push('spec=' + encodeURIComponent(sectionName));
}
if (!jasmine.CATCH_EXCEPTIONS) {
params.push("catch=false");
}
if (params.length > 0) {
link += params.join("&");
}
return link;
};
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);

View File

@@ -81,14 +81,14 @@ jasmine.HtmlReporter.ReporterView = function(dom) {
// currently running UI
if (isUndefined(this.runningAlert)) {
this.runningAlert = this.createDom('a', {href: "?", className: "runningAlert bar"});
this.runningAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "runningAlert bar" });
dom.alert.appendChild(this.runningAlert);
}
this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);
// skipped specs UI
if (isUndefined(this.skippedAlert)) {
this.skippedAlert = this.createDom('a', {href: "?", className: "skippedAlert bar"});
this.skippedAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "skippedAlert bar" });
}
this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
@@ -99,7 +99,7 @@ jasmine.HtmlReporter.ReporterView = function(dom) {
// passing specs UI
if (isUndefined(this.passedAlert)) {
this.passedAlert = this.createDom('span', {href: "?", className: "passingAlert bar"});
this.passedAlert = this.createDom('span', { href: jasmine.HtmlReporter.sectionLink(), className: "passingAlert bar" });
}
this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);

View File

@@ -7,11 +7,11 @@ jasmine.HtmlReporter.SpecView = function(spec, dom, views) {
this.dom.symbolSummary.appendChild(this.symbol);
this.summary = this.createDom('div', { className: 'specSummary' },
this.createDom('a', {
className: 'description',
href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
title: this.spec.getFullName()
}, this.spec.description)
this.createDom('a', {
className: 'description',
href: jasmine.HtmlReporter.sectionLink(this.spec.getFullName()),
title: this.spec.getFullName()
}, this.spec.description)
);
this.detail = this.createDom('div', { className: 'specDetail' },

View File

@@ -4,7 +4,7 @@ jasmine.HtmlReporter.SuiteView = function(suite, dom, views) {
this.views = views;
this.element = this.createDom('div', { className: 'suite' },
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(this.suite.getFullName()) }, this.suite.description)
this.createDom('a', { className: 'description', href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()) }, this.suite.description)
);
this.appendToSummary(this.suite, this.element);

View File

@@ -136,167 +136,174 @@ body {
}
}
}
.exceptions {
color: #fff;
float: right;
margin-top: 5px;
margin-right: 5px;
}
//--- Alert ---//
.bar {
line-height: $line-height * 2;
font-size: $large-font-size;
display: block;
color: #eee;
}
.runningAlert {
background-color: $light-text-color;
}
.skippedAlert {
background-color: $feint-text-color;
&:first-child {
background-color: $text-color;
}
&:hover {
text-decoration: none;
color: white;
text-decoration: underline;
}
}
.passingAlert {
background-color: $light-passing-color;
&:first-child {
background-color: $passing-color;
}
}
.failingAlert {
background-color: $light-failing-color;
&:first-child {
background-color: $failing-color
}
}
//--- Results ---//
.results {
margin-top: $line-height;
}
//--- Results menu ---//
#details {
display: none;
}
.resultsMenu,
.resultsMenu a {
background-color: #fff;
color: $text-color;
}
&.showDetails {
.summaryMenuItem {
font-weight: normal;
text-decoration: inherit;
&:hover {
text-decoration: underline;
}
}
.detailsMenuItem {
font-weight: bold;
text-decoration: underline;
text-decoration: underline;
}
.summary {
display: none;
}
#details {
display: block;
}
}
.summaryMenuItem {
.summaryMenuItem {
font-weight: bold;
text-decoration: underline;
}
//--- Results summary ---//
.summary {
margin-top: $margin-unit;
.suite .suite, .specSummary {
margin-left: $margin-unit;
}
.specSummary {
&.passed a {
color: $passing-color;
color: $passing-color;
}
&.failed a {
color: $failing-color;
}
}
}
.description+.suite {
margin-top: 0;
}
.suite {
margin-top: $margin-unit;
a {
color: $text-color;
}
}
//--- Results details ---//
#details {
.specDetail {
margin-bottom: $line-height * 2;
.description {
//line-height: $line-height * 2;
display: block;
color: white;
background-color: $failing-color;
//font-size: $large-font-size;
}
}
}
.resultMessage {
padding-top: $line-height;
color: $text-color;
}
.resultMessage span.result {
display: block;
}
.stackTrace {
margin: 5px 0 0 0;
max-height: $line-height * 16;
overflow: auto;
line-height: 18px;
color: $light-text-color;
border: 1px solid #ddd;
background: white;
white-space: pre;
}
}
}

View File

@@ -19,6 +19,7 @@ body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
#HTMLReporter .symbolSummary li.pending { line-height: 11px; }
#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
#HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
#HTMLReporter .runningAlert { background-color: #666666; }
#HTMLReporter .skippedAlert { background-color: #aaaaaa; }

View File

@@ -1,7 +1,7 @@
jasmine.version_= {
"major": 1,
"minor": 2,
"minor": 3,
"build": 0,
"revision": 1337006083
"revision": 1354052693
};

View File

@@ -1,5 +1,5 @@
{
"major": 1,
"minor": 2,
"minor": 3,
"build": 0
}

View File

@@ -8,24 +8,21 @@ class JasmineDev < Thor
return unless pages_submodule_installed?
pages_output = File.join(pages_dir, 'pages_output')
FileUtils.rm_r(pages_output) if File.exist?(pages_output)
project_lib_dir = File.join(JasmineDev.project_root, 'lib', 'jasmine-core')
inside File.join('pages', 'pages_source') do
run_with_output "frank export #{pages_output}", :capture => true
pages_lib_dir = File.join(pages_dir, 'lib')
FileUtils.rm_r(pages_lib_dir) if File.exist?(pages_lib_dir)
['jasmine.js', 'jasmine-html.js', 'jasmine.css'].each do |file|
copy_file File.join(project_lib_dir, file), File.join(pages_lib_dir, file)
end
pages_files = Dir.chdir(pages_output) { Dir.glob('*') }
inside File.join(JasmineDev.project_root, 'pages', 'src') do
run_with_output "bundle exec rocco -l js introduction.js -t layout.mustache -o #{pages_dir}"
end
pages_files.each do |file|
source_path = File.join(pages_output, file)
destination_path = File.join(pages_dir, file)
if File.directory?(source_path)
directory source_path, destination_path
else
copy_file source_path, destination_path
end
inside pages_dir do
copy_file File.join(pages_dir,'introduction.html'), File.join(pages_dir,'index.html')
end
end
end

View File

@@ -28,7 +28,8 @@ class JasmineDev < Thor
run_with_output "zip -rq ../jasmine-standalone-#{version_string}.zip ."
say "Copying Zip file to downloads directory", :yellow
run "cp ../jasmine-standalone-#{version_string}.zip #{download_dir}"
run "mkdir -p #{download_dir}"
run "cp ../jasmine-standalone-#{version_string}.zip #{download_dir}/"
end
end
@@ -46,4 +47,4 @@ class JasmineDev < Thor
File.join('lib', "jasmine-#{version_string}")
end
end
end
end

View File

@@ -49,11 +49,11 @@ class JasmineDev < Thor
end
def example_source_tags
script_tags_for ['spec/SpecHelper.js', 'spec/PlayerSpec.js']
script_tags_for ['src/Player.js', 'src/Song.js']
end
def example_spec_tags
script_tags_for ['src/Player.js', 'src/Song.js']
script_tags_for ['spec/SpecHelper.js', 'spec/PlayerSpec.js']
end
end
end
end