diff --git a/test/lib/backbone.js b/test/lib/backbone.js index cd777c4..b2e4932 100644 --- a/test/lib/backbone.js +++ b/test/lib/backbone.js @@ -1,4 +1,4 @@ -// Backbone.js 0.5.2 +// Backbone.js 0.5.3 // (c) 2010 Jeremy Ashkenas, DocumentCloud Inc. // Backbone may be freely distributed under the MIT license. // For all details and documentation: @@ -25,7 +25,7 @@ } // Current version of the library. Keep in sync with `package.json`. - Backbone.VERSION = '0.5.2'; + Backbone.VERSION = '0.5.3'; // Require Underscore, if we're on the server, and it's not already present. var _ = root._; @@ -41,7 +41,7 @@ return this; }; - // Turn on `emulateHTTP` to use support legacy HTTP servers. Setting this option will + // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option will // fake `"PUT"` and `"DELETE"` requests via the `_method` parameter and set a // `X-Http-Method-Override` header. Backbone.emulateHTTP = false; @@ -71,7 +71,7 @@ bind : function(ev, callback, context) { var calls = this._callbacks || (this._callbacks = {}); var list = calls[ev] || (calls[ev] = []); - list.push([callback, context || this]); + list.push([callback, context]); return this; }, @@ -114,7 +114,7 @@ list.splice(i, 1); i--; l--; } else { args = both ? Array.prototype.slice.call(arguments, 1) : arguments; - callback[0].apply(callback[1], args); + callback[0].apply(callback[1] || this, args); } } } @@ -641,7 +641,7 @@ var methods = ['forEach', 'each', 'map', 'reduce', 'reduceRight', 'find', 'detect', 'filter', 'select', 'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke', 'max', 'min', 'sortBy', 'sortedIndex', 'toArray', 'size', - 'first', 'rest', 'last', 'without', 'indexOf', 'lastIndexOf', 'isEmpty']; + 'first', 'rest', 'last', 'without', 'indexOf', 'lastIndexOf', 'isEmpty', 'groupBy']; // Mix in each Underscore method as a proxy to `Collection#models`. _.each(methods, function(method) { @@ -766,7 +766,7 @@ fragment = window.location.hash; } } - return fragment.replace(hashStrip, ''); + return decodeURIComponent(fragment.replace(hashStrip, '')); }, // Start the hash change handling, returning `true` if the current URL matches @@ -812,7 +812,10 @@ this.fragment = loc.hash.replace(hashStrip, ''); window.history.replaceState({}, document.title, loc.protocol + '//' + loc.host + this.options.root + this.fragment); } - return this.loadUrl(); + + if (!this.options.silent) { + return this.loadUrl(); + } }, // Add a route to be tested when the fragment changes. Routes added later may @@ -949,6 +952,7 @@ // not `change`, `submit`, and `reset` in Internet Explorer. delegateEvents : function(events) { if (!(events || (events = this.events))) return; + if (_.isFunction(events)) events = events.call(this); $(this.el).unbind('.delegateEvents' + this.cid); for (var key in events) { var method = this[events[key]]; @@ -1070,7 +1074,7 @@ } // Don't process data on a non-GET request. - if (params.type !== 'GET' && ! Backbone.emulateJSON) { + if (params.type !== 'GET' && !Backbone.emulateJSON) { params.processData = false; } diff --git a/test/lib/qunit.css b/test/lib/qunit.css index 1f8aa5e..c85f36a 100644 --- a/test/lib/qunit.css +++ b/test/lib/qunit.css @@ -1,11 +1,17 @@ -#qunit-tests li strong { - font-weight: normal; -} +/** + * QUnit - A JavaScript Unit Testing Framework + * + * http://docs.jquery.com/QUnit + * + * Copyright (c) 2011 John Resig, Jörn Zaefferer + * Dual licensed under the MIT (MIT-LICENSE.txt) + * or GPL (GPL-LICENSE.txt) licenses. + */ /** Font Family and Sizes */ #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { - font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; + font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; } #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } @@ -31,7 +37,7 @@ font-size: 1.5em; line-height: 1em; font-weight: normal; - + border-radius: 15px 15px 0 0; -moz-border-radius: 15px 15px 0 0; -webkit-border-top-right-radius: 15px; @@ -99,13 +105,13 @@ #qunit-tests ol { margin-top: 0.5em; padding: 0.5em; - + background-color: #fff; - + border-radius: 15px; -moz-border-radius: 15px; -webkit-border-radius: 15px; - + box-shadow: inset 0px 2px 13px #999; -moz-box-shadow: inset 0px 2px 13px #999; -webkit-box-shadow: inset 0px 2px 13px #999; @@ -168,7 +174,7 @@ #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } #qunit-tests .pass .test-name { color: #366097; } - + #qunit-tests .pass .test-actual, #qunit-tests .pass .test-expected { color: #999999; } @@ -180,6 +186,7 @@ color: #710909; background-color: #fff; border-left: 26px solid #EE5757; + white-space: pre; } #qunit-tests > li:last-child { diff --git a/test/lib/qunit.js b/test/lib/qunit.js index e00cca9..a711c82 100644 --- a/test/lib/qunit.js +++ b/test/lib/qunit.js @@ -15,10 +15,10 @@ var defined = { sessionStorage: (function() { try { return !!sessionStorage.getItem; - } catch(e){ + } catch(e) { return false; } - })() + })() }; var testId = 0; @@ -132,7 +132,7 @@ Test.prototype = { config.moduleStats.all += this.assertions.length; if ( tests ) { - var ol = document.createElement("ol"); + var ol = document.createElement("ol"); for ( var i = 0; i < this.assertions.length; i++ ) { var assertion = this.assertions[i]; @@ -275,7 +275,7 @@ var QUnit = { } // is 2nd argument a testEnvironment? if ( expected && typeof expected === 'object') { - testEnvironmentArg = expected; + testEnvironmentArg = expected; expected = null; } @@ -400,6 +400,9 @@ var QUnit = { // A slight delay, to avoid any current callbacks if ( defined.setTimeout ) { window.setTimeout(function() { + if (config.semaphore > 0) { + return; + } if ( config.timeout ) { clearTimeout(config.timeout); } @@ -439,12 +442,18 @@ var config = { // block until document ready blocking: true, + // when enabled, show only failing tests + // gets persisted through sessionStorage and can be changed in UI via checkbox + hidepassed: false, + // by default, run previously failed tests first // very useful in combination with "Hide passed tests" checked reorder: true, - noglobals: false, - notrycatch: false + // by default, modify document.title when suite is done + altertitle: true, + + urlConfig: ['noglobals', 'notrycatch'] }; // Load paramaters @@ -462,9 +471,6 @@ var config = { // allow just a key to turn on a flag, e.g., test.html?noglobals current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true; urlParams[ current[ 0 ] ] = current[ 1 ]; - if ( current[ 0 ] in config ) { - config[ current[ 0 ] ] = current[ 1 ]; - } } } @@ -649,6 +655,10 @@ extend(QUnit, { return window.location.pathname + querystring.slice( 0, -1 ); }, + extend: extend, + id: id, + addEvent: addEvent, + // Logging callbacks; all receive a single argument with the listed properties // run test/logs.html for any related changes begin: function() {}, @@ -670,7 +680,7 @@ if ( typeof document === "undefined" || document.readyState === "complete" ) { config.autorun = true; } -addEvent(window, "load", function() { +QUnit.load = function() { QUnit.begin({}); // Initialize the config, saving the execution queue @@ -680,15 +690,19 @@ addEvent(window, "load", function() { config.blocking = false; + var urlConfigHtml = '', len = config.urlConfig.length; + for ( var i = 0, val; i < len, val = config.urlConfig[i]; i++ ) { + config[val] = QUnit.urlParams[val]; + urlConfigHtml += ''; + } + var userAgent = id("qunit-userAgent"); if ( userAgent ) { userAgent.innerHTML = navigator.userAgent; } var banner = id("qunit-header"); if ( banner ) { - banner.innerHTML = ' ' + banner.innerHTML + ' ' + - '' + - ''; + banner.innerHTML = ' ' + banner.innerHTML + ' ' + urlConfigHtml; addEvent( banner, "change", function( event ) { var params = {}; params[ event.target.name ] = event.target.checked ? true : undefined; @@ -711,13 +725,13 @@ addEvent(window, "load", function() { } if ( defined.sessionStorage ) { if (filter.checked) { - sessionStorage.setItem("qunit-filter-passed-tests", "true"); + sessionStorage.setItem("qunit-filter-passed-tests", "true"); } else { sessionStorage.removeItem("qunit-filter-passed-tests"); } } }); - if ( defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) { + if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) { filter.checked = true; var ol = document.getElementById("qunit-tests"); ol.className = ol.className + " hidepass"; @@ -738,7 +752,9 @@ addEvent(window, "load", function() { if (config.autostart) { QUnit.start(); } -}); +}; + +addEvent(window, "load", QUnit.load); function done() { config.autorun = true; @@ -778,10 +794,13 @@ function done() { id( "qunit-testresult" ).innerHTML = html; } - if ( typeof document !== "undefined" && document.title ) { + if ( config.altertitle && typeof document !== "undefined" && document.title ) { // show ✖ for good, ✔ for bad suite result in title // use escape sequences in case file gets loaded with non-utf-8-charset - document.title = (config.stats.bad ? "\u2716" : "\u2714") + " " + document.title; + document.title = [ + (config.stats.bad ? "\u2716" : "\u2714"), + document.title.replace(/^[\u2714\u2716] /i, "") + ].join(" "); } QUnit.done( { @@ -828,6 +847,10 @@ function sourceFromStacktrace() { } else if (e.stack) { // Firefox, Chrome return e.stack.split("\n")[4]; + } else if (e.sourceURL) { + // Safari, PhantomJS + // TODO sourceURL points at the 'throw new Error' line above, useless + //return e.sourceURL + ":" + e.line; } } } @@ -868,9 +891,9 @@ function process() { break; } } - if (!config.blocking && !config.queue.length) { - done(); - } + if (!config.blocking && !config.queue.length) { + done(); + } } function saveGlobal() { @@ -957,170 +980,182 @@ function id(name) { // Author: Philippe Rathé QUnit.equiv = function () { - var innerEquiv; // the real equiv function - var callers = []; // stack to decide between skip/abort functions - var parents = []; // stack to avoiding loops from circular referencing - - // Call the o related callback with the given arguments. - function bindCallbacks(o, callbacks, args) { - var prop = QUnit.objectType(o); - if (prop) { - if (QUnit.objectType(callbacks[prop]) === "function") { - return callbacks[prop].apply(callbacks, args); - } else { - return callbacks[prop]; // or undefined - } - } - } - - var callbacks = function () { - - // for string, boolean, number and null - function useStrictEquality(b, a) { - if (b instanceof a.constructor || a instanceof b.constructor) { - // to catch short annotaion VS 'new' annotation of a declaration - // e.g. var i = 1; - // var j = new Number(1); - return a == b; - } else { - return a === b; - } - } - - return { - "string": useStrictEquality, - "boolean": useStrictEquality, - "number": useStrictEquality, - "null": useStrictEquality, - "undefined": useStrictEquality, - - "nan": function (b) { - return isNaN(b); - }, - - "date": function (b, a) { - return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf(); - }, - - "regexp": function (b, a) { - return QUnit.objectType(b) === "regexp" && - a.source === b.source && // the regex itself - a.global === b.global && // and its modifers (gmi) ... - a.ignoreCase === b.ignoreCase && - a.multiline === b.multiline; - }, - - // - skip when the property is a method of an instance (OOP) - // - abort otherwise, - // initial === would have catch identical references anyway - "function": function () { - var caller = callers[callers.length - 1]; - return caller !== Object && - typeof caller !== "undefined"; - }, - - "array": function (b, a) { - var i, j, loop; - var len; - - // b could be an object literal here - if ( ! (QUnit.objectType(b) === "array")) { - return false; - } + var innerEquiv; // the real equiv function + var callers = []; // stack to decide between skip/abort functions + var parents = []; // stack to avoiding loops from circular referencing - len = a.length; - if (len !== b.length) { // safe and faster - return false; - } + // Call the o related callback with the given arguments. + function bindCallbacks(o, callbacks, args) { + var prop = QUnit.objectType(o); + if (prop) { + if (QUnit.objectType(callbacks[prop]) === "function") { + return callbacks[prop].apply(callbacks, args); + } else { + return callbacks[prop]; // or undefined + } + } + } - //track reference to avoid circular references - parents.push(a); - for (i = 0; i < len; i++) { - loop = false; - for(j=0;jbrown fox jumped jumps over" */ QUnit.diff = (function() { - function diff(o, n){ - var ns = new Object(); - var os = new Object(); + function diff(o, n) { + var ns = {}; + var os = {}; for (var i = 0; i < n.length; i++) { if (ns[n[i]] == null) ns[n[i]] = { - rows: new Array(), + rows: [], o: null }; ns[n[i]].rows.push(i); @@ -1339,7 +1401,7 @@ QUnit.diff = (function() { for (var i = 0; i < o.length; i++) { if (os[o[i]] == null) os[o[i]] = { - rows: new Array(), + rows: [], n: null }; os[o[i]].rows.push(i); @@ -1392,7 +1454,7 @@ QUnit.diff = (function() { }; } - return function(o, n){ + return function(o, n) { o = o.replace(/\s+$/, ''); n = n.replace(/\s+$/, ''); var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/));