diff --git a/Rakefile b/Rakefile index 3f600de..96924e1 100644 --- a/Rakefile +++ b/Rakefile @@ -44,7 +44,7 @@ namespace :jasmine do passed = false end - if line.scan(/window/).length > 0 + if line.scan(/window/).length > 0 && !line.include?("typeof") puts "Dangerous window at #{src}:#{i}:\n > #{line}" passed = false end @@ -55,6 +55,8 @@ namespace :jasmine do puts "Lint failed!" exit 1 end + + system("node jshint/run.js") || exit(1) end desc 'Builds lib/jasmine from source' diff --git a/example/spec/SpecHelper.js b/example/spec/SpecHelper.js index 4919c87..e9b8284 100644 --- a/example/spec/SpecHelper.js +++ b/example/spec/SpecHelper.js @@ -2,8 +2,8 @@ beforeEach(function() { this.addMatchers({ toBePlaying: function(expectedSong) { var player = this.actual; - return player.currentlyPlayingSong === expectedSong - && player.isPlaying; + return player.currentlyPlayingSong === expectedSong && + player.isPlaying; } - }) + }); }); diff --git a/jshint/jshint.js b/jshint/jshint.js index 4611989..013950c 100755 --- a/jshint/jshint.js +++ b/jshint/jshint.js @@ -221,7 +221,7 @@ lightseagreen, lightskyblue, lightslategray, lightsteelblue, lightyellow, lime, limegreen, line, "line-height", linen, link, "list-style", "list-style-image", "list-style-position", - "list-style-type", load, loadClass, localStorage, location, log, m, magenta, + "list-style-type", load, loadClass, localStorage, location, log, loopfunc, m, magenta, map, margin, "margin-bottom", "margin-left", "margin-right", "margin-top", mark, "marker-offset", maroon, match, "max-height", "max-width", maxerr, maxlen, md5, mediumaquamarine, mediumblue, mediumorchid, mediumpurple, @@ -314,9 +314,9 @@ var JSHINT = (function () { }, -// These are the JSHint options. +// These are the JSHint boolean options. - options = { + boolOptions = { adsafe : true, // if ADsafe should be enforced asi : true, // if automatic semicolon insertion should be tolerated bitwise : true, // if bitwise operators should not be allowed @@ -336,6 +336,7 @@ var JSHINT = (function () { immed : true, // if immediate invocations must be wrapped in parens jquery : true, // if jQuery globals should be predefined laxbreak : true, // if line breaks should not be checked + loopfunc : true, // if functions should be allowed to be defined within loops newcap : true, // if constructor names must be capitalized noarg : true, // if arguments.caller and arguments.callee should be disallowed node : true, // if the Node.js environment globals should be predefined @@ -356,7 +357,7 @@ var JSHINT = (function () { white : true, // if strict whitespace rules apply widget : true // if the Yahoo Widgets globals should be predefined }, - + // browser contains a set of global names which are commonly provided by a // web browser environment. @@ -2017,7 +2018,7 @@ klass: do { warning("ADsafe restriction."); } obj = option; - filter = options; + filter = boolOptions; break; case '/*global': if (option.safe) { @@ -4896,7 +4897,7 @@ loop: for (;;) { t = nexttoken; adjacent(token, nexttoken); f = doFunction(i); - if (funct['(loopage)']) { + if (!option.loopfunc && funct['(loopage)']) { warning("Don't make functions within a loop.", t); } p = f['(params)']; @@ -5032,7 +5033,7 @@ loop: for (;;) { nonadjacent(token, nexttoken); } doFunction(i); - if (funct['(loopage)']) { + if (!option.loopfunc && funct['(loopage)']) { warning("Don't make functions within a loop."); } return this; @@ -5529,11 +5530,10 @@ loop: for (;;) { // The actual JSHINT function itself. - var itself = function (s, o, g) { + var itself = function (s, o) { var a, i, k; JSHINT.errors = []; predefined = Object.create(standard); - combine(predefined, g || {}); if (o) { a = o.predef; if (a) { @@ -5552,22 +5552,23 @@ loop: for (;;) { o.safe = true; } if (o.safe) { - o.browser = - o.css = - o.debug = - o.devel = - o.evil = - o.forin = - o.on = - o.rhino = - o.windows = - o.sub = - o.widget = false; + o.browser = + o.css = + o.debug = + o.devel = + o.evil = + o.forin = + o.loopfunc = + o.on = + o.rhino = + o.windows = + o.sub = + o.widget = false; - o.eqeqeq = - o.nomen = - o.safe = - o.undef = true; + o.eqeqeq = + o.nomen = + o.safe = + o.undef = true; predefined.Date = predefined['eval'] = diff --git a/jshint/run.js b/jshint/run.js index 69e4762..00a9e79 100644 --- a/jshint/run.js +++ b/jshint/run.js @@ -1,42 +1,70 @@ -var fs = require("fs") -var sys = require("sys") -var path = require("path") +var fs = require("fs"); +var sys = require("sys"); +var path = require("path"); var JSHINT = require("./jshint").JSHINT; -function isVendorFile(fullPath) { - var fileName = path.basename(fullPath) - var vendorFiles = ["json2.js", "jshint.js", "publish.js"] - for (var i=0; i=1) { + console.log("JSHINT failure: ", file); + console.log(errors); + process.exit(1); } } \ No newline at end of file diff --git a/lib/jasmine-html.js b/lib/jasmine-html.js index 81402b9..327c12f 100644 --- a/lib/jasmine-html.js +++ b/lib/jasmine-html.js @@ -110,7 +110,7 @@ jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { var results = suite.results(); var status = results.passed() ? 'passed' : 'failed'; - if (results.totalCount == 0) { // todo: change this to check results.skipped + if (results.totalCount === 0) { // todo: change this to check results.skipped status = 'skipped'; } this.suiteDivs[suite.id].className += " " + status; @@ -183,6 +183,6 @@ jasmine.TrivialReporter.prototype.specFilter = function(spec) { paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); } - if (!paramMap["spec"]) return true; - return spec.getFullName().indexOf(paramMap["spec"]) == 0; + if (!paramMap.spec) return true; + return spec.getFullName().indexOf(paramMap.spec) === 0; }; diff --git a/lib/jasmine.js b/lib/jasmine.js index 964f99e..585a992 100644 --- a/lib/jasmine.js +++ b/lib/jasmine.js @@ -1,10 +1,12 @@ +var isCommonJS = typeof window == "undefined"; + /** * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. * * @namespace */ var jasmine = {}; - +if (isCommonJS) exports.jasmine = jasmine; /** * @private */ @@ -106,7 +108,8 @@ jasmine.ExpectationResult.prototype.passed = function () { * Getter for the Jasmine environment. Ensures one gets created */ jasmine.getEnv = function() { - return jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); + var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); + return env; }; /** @@ -169,7 +172,7 @@ jasmine.pp = function(value) { * @returns {Boolean} */ jasmine.isDomNode = function(obj) { - return obj['nodeType'] > 0; + return obj.nodeType > 0; }; /** @@ -405,7 +408,7 @@ jasmine.isSpy = function(putativeSpy) { * @param {Array} methodNames array of names of methods to make spies */ jasmine.createSpyObj = function(baseName, methodNames) { - if (!jasmine.isArray_(methodNames) || methodNames.length == 0) { + if (!jasmine.isArray_(methodNames) || methodNames.length === 0) { throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); } var obj = {}; @@ -443,6 +446,7 @@ jasmine.log = function() { var spyOn = function(obj, methodName) { return jasmine.getEnv().currentSpec.spyOn(obj, methodName); }; +if (isCommonJS) exports.spyOn = spyOn; /** * Creates a Jasmine spec that will be added to the current suite. @@ -460,6 +464,7 @@ var spyOn = function(obj, methodName) { var it = function(desc, func) { return jasmine.getEnv().it(desc, func); }; +if (isCommonJS) exports.it = it; /** * Creates a disabled Jasmine spec. @@ -472,6 +477,7 @@ var it = function(desc, func) { var xit = function(desc, func) { return jasmine.getEnv().xit(desc, func); }; +if (isCommonJS) exports.xit = xit; /** * Starts a chain for a Jasmine expectation. @@ -484,6 +490,7 @@ var xit = function(desc, func) { var expect = function(actual) { return jasmine.getEnv().currentSpec.expect(actual); }; +if (isCommonJS) exports.expect = expect; /** * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. @@ -493,6 +500,7 @@ var expect = function(actual) { var runs = function(func) { jasmine.getEnv().currentSpec.runs(func); }; +if (isCommonJS) exports.runs = runs; /** * Waits a fixed time period before moving to the next block. @@ -503,6 +511,7 @@ var runs = function(func) { var waits = function(timeout) { jasmine.getEnv().currentSpec.waits(timeout); }; +if (isCommonJS) exports.waits = waits; /** * Waits for the latchFunction to return true before proceeding to the next block. @@ -514,6 +523,7 @@ var waits = function(timeout) { var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); }; +if (isCommonJS) exports.waitsFor = waitsFor; /** * A function that is called before each spec in a suite. @@ -525,6 +535,7 @@ var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout var beforeEach = function(beforeEachFunction) { jasmine.getEnv().beforeEach(beforeEachFunction); }; +if (isCommonJS) exports.beforeEach = beforeEach; /** * A function that is called after each spec in a suite. @@ -536,6 +547,7 @@ var beforeEach = function(beforeEachFunction) { var afterEach = function(afterEachFunction) { jasmine.getEnv().afterEach(afterEachFunction); }; +if (isCommonJS) exports.afterEach = afterEach; /** * Defines a suite of specifications. @@ -555,6 +567,7 @@ var afterEach = function(afterEachFunction) { var describe = function(description, specDefinitions) { return jasmine.getEnv().describe(description, specDefinitions); }; +if (isCommonJS) exports.describe = describe; /** * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. @@ -565,27 +578,27 @@ var describe = function(description, specDefinitions) { var xdescribe = function(description, specDefinitions) { return jasmine.getEnv().xdescribe(description, specDefinitions); }; +if (isCommonJS) exports.xdescribe = xdescribe; // Provide the XMLHttpRequest class for IE 5.x-6.x: jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { - try { - return new ActiveXObject("Msxml2.XMLHTTP.6.0"); - } catch(e) { + function tryIt(f) { + try { + return f(); + } catch(e) { + } + return null; } - try { - return new ActiveXObject("Msxml2.XMLHTTP.3.0"); - } catch(e) { - } - try { - return new ActiveXObject("Msxml2.XMLHTTP"); - } catch(e) { - } - try { - return new ActiveXObject("Microsoft.XMLHTTP"); - } catch(e) { - } - throw new Error("This browser does not support XMLHttpRequest."); + + var xhr = tryIt(function(){return new ActiveXObject("Msxml2.XMLHTTP.6.0");}) || + tryIt(function(){return new ActiveXObject("Msxml2.XMLHTTP.3.0");}) || + tryIt(function(){return new ActiveXObject("Msxml2.XMLHTTP");}) || + tryIt(function(){return new ActiveXObject("Microsoft.XMLHTTP");}); + + if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); + + return xhr; } : XMLHttpRequest; /** * @namespace @@ -606,7 +619,7 @@ jasmine.util.inherit = function(childClass, parentClass) { var subclass = function() { }; subclass.prototype = parentClass.prototype; - childClass.prototype = new subclass; + childClass.prototype = new subclass(); }; jasmine.util.formatException = function(e) { @@ -828,7 +841,7 @@ jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchVal b.__Jasmine_been_here_before__ = a; var hasKey = function(obj, keyName) { - return obj != null && obj[keyName] !== jasmine.undefined; + return obj !== null && obj[keyName] !== jasmine.undefined; }; for (var property in b) { @@ -854,7 +867,7 @@ jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchVal delete a.__Jasmine_been_here_before__; delete b.__Jasmine_been_here_before__; - return (mismatchKeys.length == 0 && mismatchValues.length == 0); + return (mismatchKeys.length === 0 && mismatchValues.length === 0); }; jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { @@ -1302,7 +1315,7 @@ jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); } this.message = function() { - if (this.actual.callCount == 0) { + if (this.actual.callCount === 0) { // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw] return [ "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.", @@ -1333,7 +1346,7 @@ jasmine.Matchers.prototype.wasNotCalledWith = function() { return [ "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" - ] + ]; }; return !this.env.contains_(this.actual.argsForCall, expectedArgs); @@ -1390,7 +1403,7 @@ jasmine.Matchers.prototype.toThrow = function(expected) { this.message = function() { if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { - return ["Expected function " + not + "to throw", expected ? expected.message || expected : " an exception", ", but it threw", exception.message || exception].join(' '); + return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' '); } else { return "Expected function to throw an exception."; } @@ -1602,7 +1615,8 @@ jasmine.PrettyPrinter.prototype.format = function(value) { jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { for (var property in obj) { if (property == '__Jasmine_been_here_before__') continue; - fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) != null) : false); + fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && + obj.__lookupGetter__(property) !== null) : false); } }; @@ -2417,5 +2431,5 @@ jasmine.version_= { "major": 1, "minor": 0, "build": 1, - "revision": 1286311016 + "revision": 1298761339 }; diff --git a/spec/node_suite.js b/spec/node_suite.js index 4ddc9eb..97be47e 100644 --- a/spec/node_suite.js +++ b/spec/node_suite.js @@ -3,10 +3,10 @@ var sys = require('sys'); var path = require('path'); // yes, really keep this here to keep us honest, but only for jasmine's own runner! [xw] -undefined = "diz be undefined yo"; +// undefined = "diz be undefined yo"; var jasmineGlobals = require("../src/base"); -for(var k in jasmineGlobals) {global[k] = jasmineGlobals[k]}; +for(var k in jasmineGlobals) {global[k] = jasmineGlobals[k];} //load jasmine src files based on the order in runner.html var srcFilesInProperRequireOrder = []; @@ -15,7 +15,7 @@ var srcFileLines = []; for (var i=0; i 0; + return obj.nodeType > 0; }; /** @@ -407,7 +408,7 @@ jasmine.isSpy = function(putativeSpy) { * @param {Array} methodNames array of names of methods to make spies */ jasmine.createSpyObj = function(baseName, methodNames) { - if (!jasmine.isArray_(methodNames) || methodNames.length == 0) { + if (!jasmine.isArray_(methodNames) || methodNames.length === 0) { throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); } var obj = {}; @@ -582,21 +583,20 @@ if (isCommonJS) exports.xdescribe = xdescribe; // Provide the XMLHttpRequest class for IE 5.x-6.x: jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { - try { - return new ActiveXObject("Msxml2.XMLHTTP.6.0"); - } catch(e) { + function tryIt(f) { + try { + return f(); + } catch(e) { + } + return null; } - try { - return new ActiveXObject("Msxml2.XMLHTTP.3.0"); - } catch(e) { - } - try { - return new ActiveXObject("Msxml2.XMLHTTP"); - } catch(e) { - } - try { - return new ActiveXObject("Microsoft.XMLHTTP"); - } catch(e) { - } - throw new Error("This browser does not support XMLHttpRequest."); + + var xhr = tryIt(function(){return new ActiveXObject("Msxml2.XMLHTTP.6.0");}) || + tryIt(function(){return new ActiveXObject("Msxml2.XMLHTTP.3.0");}) || + tryIt(function(){return new ActiveXObject("Msxml2.XMLHTTP");}) || + tryIt(function(){return new ActiveXObject("Microsoft.XMLHTTP");}); + + if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); + + return xhr; } : XMLHttpRequest; \ No newline at end of file diff --git a/src/html/TrivialReporter.js b/src/html/TrivialReporter.js index 81402b9..327c12f 100644 --- a/src/html/TrivialReporter.js +++ b/src/html/TrivialReporter.js @@ -110,7 +110,7 @@ jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { var results = suite.results(); var status = results.passed() ? 'passed' : 'failed'; - if (results.totalCount == 0) { // todo: change this to check results.skipped + if (results.totalCount === 0) { // todo: change this to check results.skipped status = 'skipped'; } this.suiteDivs[suite.id].className += " " + status; @@ -183,6 +183,6 @@ jasmine.TrivialReporter.prototype.specFilter = function(spec) { paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); } - if (!paramMap["spec"]) return true; - return spec.getFullName().indexOf(paramMap["spec"]) == 0; + if (!paramMap.spec) return true; + return spec.getFullName().indexOf(paramMap.spec) === 0; }; diff --git a/src/util.js b/src/util.js index f5d453a..067be2b 100644 --- a/src/util.js +++ b/src/util.js @@ -17,7 +17,7 @@ jasmine.util.inherit = function(childClass, parentClass) { var subclass = function() { }; subclass.prototype = parentClass.prototype; - childClass.prototype = new subclass; + childClass.prototype = new subclass(); }; jasmine.util.formatException = function(e) {