From e6103c2efcb542f13ea3ac1869c7c622d66b9c4a Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Fri, 13 Jun 2014 11:47:06 +1000 Subject: [PATCH 01/16] Upgraded to Jasmine 2.0 --- app/assets/javascripts/jasminerice.js.coffee | 3 +- vendor/assets/javascripts/boot.js | 203 + vendor/assets/javascripts/jasmine-html.js | 920 ++-- vendor/assets/javascripts/jasmine.js | 4315 +++++++++--------- vendor/assets/stylesheets/jasmine.css | 137 +- 5 files changed, 2684 insertions(+), 2894 deletions(-) create mode 100644 vendor/assets/javascripts/boot.js diff --git a/app/assets/javascripts/jasminerice.js.coffee b/app/assets/javascripts/jasminerice.js.coffee index 1ace304..79457ed 100644 --- a/app/assets/javascripts/jasminerice.js.coffee +++ b/app/assets/javascripts/jasminerice.js.coffee @@ -1,6 +1,7 @@ #=require jasmine #=require jasmine-html -#=require jasmine-jquery-1.5.8 +#=require boot +#=require jasmine-jquery-1.11.0.js (-> execJasmine = -> diff --git a/vendor/assets/javascripts/boot.js b/vendor/assets/javascripts/boot.js new file mode 100644 index 0000000..8ca4c4e --- /dev/null +++ b/vendor/assets/javascripts/boot.js @@ -0,0 +1,203 @@ +/* +Copyright (c) 2008-2014 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +/** + Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project. + + If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms. + + The location of `boot.js` can be specified and/or overridden in `jasmine.yml`. + + [jasmine-gem]: http://github.com/pivotal/jasmine-gem + */ + +(function() { + + /** + * ## Require & Instantiate + * + * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference. + */ + window.jasmine = jasmineRequire.core(jasmineRequire); + + /** + * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference. + */ + jasmineRequire.html(jasmine); + + /** + * Create the Jasmine environment. This is used to run all specs in a project. + */ + var env = jasmine.getEnv(); + + /** + * ## The Global Interface + * + * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged. + */ + var jasmineInterface = { + describe: function(description, specDefinitions) { + return env.describe(description, specDefinitions); + }, + + xdescribe: function(description, specDefinitions) { + return env.xdescribe(description, specDefinitions); + }, + + it: function(desc, func) { + return env.it(desc, func); + }, + + xit: function(desc, func) { + return env.xit(desc, func); + }, + + beforeEach: function(beforeEachFunction) { + return env.beforeEach(beforeEachFunction); + }, + + afterEach: function(afterEachFunction) { + return env.afterEach(afterEachFunction); + }, + + expect: function(actual) { + return env.expect(actual); + }, + + pending: function() { + return env.pending(); + }, + + spyOn: function(obj, methodName) { + return env.spyOn(obj, methodName); + }, + + jsApiReporter: new jasmine.JsApiReporter({ + timer: new jasmine.Timer() + }) + }; + + /** + * Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`. + */ + if (typeof window == "undefined" && typeof exports == "object") { + extend(exports, jasmineInterface); + } else { + extend(window, jasmineInterface); + } + + /** + * Expose the interface for adding custom equality testers. + */ + jasmine.addCustomEqualityTester = function(tester) { + env.addCustomEqualityTester(tester); + }; + + /** + * Expose the interface for adding custom expectation matchers + */ + jasmine.addMatchers = function(matchers) { + return env.addMatchers(matchers); + }; + + /** + * Expose the mock interface for the JavaScript timeout functions + */ + jasmine.clock = function() { + return env.clock; + }; + + /** + * ## Runner Parameters + * + * More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface. + */ + + var queryString = new jasmine.QueryString({ + getWindowLocation: function() { return window.location; } + }); + + var catchingExceptions = queryString.getParam("catch"); + env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions); + + /** + * ## Reporters + * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any). + */ + var htmlReporter = new jasmine.HtmlReporter({ + env: env, + onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); }, + getContainer: function() { return document.body; }, + createElement: function() { return document.createElement.apply(document, arguments); }, + createTextNode: function() { return document.createTextNode.apply(document, arguments); }, + timer: new jasmine.Timer() + }); + + /** + * The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript. + */ + env.addReporter(jasmineInterface.jsApiReporter); + env.addReporter(htmlReporter); + + /** + * Filter which specs will be run by matching the start of the full name against the `spec` query param. + */ + var specFilter = new jasmine.HtmlSpecFilter({ + filterString: function() { return queryString.getParam("spec"); } + }); + + env.specFilter = function(spec) { + return specFilter.matches(spec.getFullName()); + }; + + /** + * Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack. + */ + window.setTimeout = window.setTimeout; + window.setInterval = window.setInterval; + window.clearTimeout = window.clearTimeout; + window.clearInterval = window.clearInterval; + + /** + * ## Execution + * + * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded. + */ + var currentWindowOnload = window.onload; + + window.onload = function() { + if (currentWindowOnload) { + currentWindowOnload(); + } + htmlReporter.initialize(); + env.execute(); + }; + + /** + * Helper function for readability above. + */ + function extend(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; + } + +}()); \ No newline at end of file diff --git a/vendor/assets/javascripts/jasmine-html.js b/vendor/assets/javascripts/jasmine-html.js index 543d569..4bc6e5f 100644 --- a/vendor/assets/javascripts/jasmine-html.js +++ b/vendor/assets/javascripts/jasmine-html.js @@ -1,681 +1,375 @@ -jasmine.HtmlReporterHelpers = {}; - -jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) { - var el = document.createElement(type); - - for (var i = 2; i < arguments.length; i++) { - var child = arguments[i]; - - if (typeof child === 'string') { - el.appendChild(document.createTextNode(child)); - } else { - if (child) { - el.appendChild(child); - } - } - } - - for (var attr in attrs) { - if (attr == "className") { - el[attr] = attrs[attr]; - } else { - el.setAttribute(attr, attrs[attr]); - } - } - - return el; +/* +Copyright (c) 2008-2014 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +jasmineRequire.html = function(j$) { + j$.ResultsNode = jasmineRequire.ResultsNode(); + j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); + j$.QueryString = jasmineRequire.QueryString(); + j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); }; -jasmine.HtmlReporterHelpers.getSpecStatus = function(child) { - var results = child.results(); - var status = results.passed() ? 'passed' : 'failed'; - if (results.skipped) { - status = 'skipped'; - } - - return status; -}; - -jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) { - var parentDiv = this.dom.summary; - var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite'; - var parent = child[parentSuite]; - - if (parent) { - if (typeof this.views.suites[parent.id] == 'undefined') { - this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views); - } - parentDiv = this.views.suites[parent.id].element; - } - - parentDiv.appendChild(childElement); -}; - - -jasmine.HtmlReporterHelpers.addHelpers = function(ctor) { - for(var fn in jasmine.HtmlReporterHelpers) { - ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn]; - } -}; - -jasmine.HtmlReporter = function(_doc) { - var self = this; - var doc = _doc || window.document; - - var reporterView; +jasmineRequire.HtmlReporter = function(j$) { - var dom = {}; - - // Jasmine Reporter Public Interface - self.logRunningSpecs = false; - - self.reportRunnerStarting = function(runner) { - var specs = runner.specs() || []; - - if (specs.length == 0) { - return; - } - - createReporterDom(runner.env.versionString()); - doc.body.appendChild(dom.reporter); - setExceptionHandling(); - - reporterView = new jasmine.HtmlReporter.ReporterView(dom); - reporterView.addSpecs(specs, self.specFilter); - }; - - self.reportRunnerResults = function(runner) { - reporterView && reporterView.complete(); - }; - - self.reportSuiteResults = function(suite) { - reporterView.suiteComplete(suite); - }; - - self.reportSpecStarting = function(spec) { - if (self.logRunningSpecs) { - self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); - } + var noopTimer = { + start: function() {}, + elapsed: function() { return 0; } }; - self.reportSpecResults = function(spec) { - reporterView.specComplete(spec); - }; + function HtmlReporter(options) { + var env = options.env || {}, + getContainer = options.getContainer, + createElement = options.createElement, + createTextNode = options.createTextNode, + onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {}, + timer = options.timer || noopTimer, + results = [], + specsExecuted = 0, + failureCount = 0, + pendingSpecCount = 0, + htmlReporterMain, + symbols; + + this.initialize = function() { + htmlReporterMain = createDom('div', {className: 'html-reporter'}, + createDom('div', {className: 'banner'}, + createDom('a', {className: 'title', href: 'http://jasmine.github.io/', target: '_blank'}), + createDom('span', {className: 'version'}, j$.version) + ), + createDom('ul', {className: 'symbol-summary'}), + createDom('div', {className: 'alert'}), + createDom('div', {className: 'results'}, + createDom('div', {className: 'failures'}) + ) + ); + getContainer().appendChild(htmlReporterMain); - self.log = function() { - var console = jasmine.getGlobal().console; - if (console && console.log) { - if (console.log.apply) { - console.log.apply(console, arguments); - } else { - console.log(arguments); // ie fix: console.log.apply doesn't exist on ie - } - } - }; + symbols = find('.symbol-summary'); + }; - self.specFilter = function(spec) { - if (!focusedSpecName()) { - return true; - } + var totalSpecsDefined; + this.jasmineStarted = function(options) { + totalSpecsDefined = options.totalSpecsDefined || 0; + timer.start(); + }; - return spec.getFullName().indexOf(focusedSpecName()) === 0; - }; + var summary = createDom('div', {className: 'summary'}); - return self; + var topResults = new j$.ResultsNode({}, '', null), + currentParent = topResults; - function focusedSpecName() { - var specName; + this.suiteStarted = function(result) { + currentParent.addChild(result, 'suite'); + currentParent = currentParent.last(); + }; - (function memoizeFocusedSpec() { - if (specName) { + this.suiteDone = function(result) { + if (currentParent == topResults) { return; } - var paramMap = []; - var params = jasmine.HtmlReporter.parameters(doc); - - for (var i = 0; i < params.length; i++) { - var p = params[i].split('='); - paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); - } - - specName = paramMap.spec; - })(); - - return specName; - } - - function createReporterDom(version) { - dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' }, - dom.banner = self.createDom('div', { className: 'banner' }, - self.createDom('span', { className: 'title' }, "Jasmine "), - self.createDom('span', { className: 'version' }, version)), - - dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}), - 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(); + currentParent = currentParent.parent; }; - } -}; -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; - this.passedCount = 0; - this.failedCount = 0; - this.skippedCount = 0; - - this.createResultsMenu = function() { - this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'}, - this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'), - ' | ', - this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing')); - - this.summaryMenuItem.onclick = function() { - dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, ''); - }; - - this.detailsMenuItem.onclick = function() { - showDetails(); - }; - }; - - this.addSpecs = function(specs, specFilter) { - this.totalSpecCount = specs.length; - - this.views = { - specs: {}, - suites: {} + this.specStarted = function(result) { + currentParent.addChild(result, 'spec'); }; - for (var i = 0; i < specs.length; i++) { - var spec = specs[i]; - this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views); - if (specFilter(spec)) { - this.runningSpecCount++; + var failures = []; + this.specDone = function(result) { + if(result.status == 'empty' && console && console.error) { + console.error('Spec \'' + result.fullName + '\' has no expectations.'); } - } - }; - - this.specComplete = function(spec) { - this.completeSpecCount++; - - if (isUndefined(this.views.specs[spec.id])) { - this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom); - } - - var specView = this.views.specs[spec.id]; - switch (specView.status()) { - case 'passed': - this.passedCount++; - break; + if (result.status != 'disabled') { + specsExecuted++; + } - case 'failed': - this.failedCount++; - break; + symbols.appendChild(createDom('li', { + className: result.status, + id: 'spec_' + result.id, + title: result.fullName + } + )); + + if (result.status == 'failed') { + failureCount++; + + var failure = + createDom('div', {className: 'spec-detail failed'}, + createDom('div', {className: 'description'}, + createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) + ), + createDom('div', {className: 'messages'}) + ); + var messages = failure.childNodes[1]; + + for (var i = 0; i < result.failedExpectations.length; i++) { + var expectation = result.failedExpectations[i]; + messages.appendChild(createDom('div', {className: 'result-message'}, expectation.message)); + messages.appendChild(createDom('div', {className: 'stack-trace'}, expectation.stack)); + } + + failures.push(failure); + } - case 'skipped': - this.skippedCount++; - break; - } + if (result.status == 'pending') { + pendingSpecCount++; + } + }; - specView.refresh(); - this.refresh(); - }; + this.jasmineDone = function() { + var banner = find('.banner'); + banner.appendChild(createDom('span', {className: 'duration'}, 'finished in ' + timer.elapsed() / 1000 + 's')); + + var alert = find('.alert'); + + alert.appendChild(createDom('span', { className: 'exceptions' }, + createDom('label', { className: 'label', 'for': 'raise-exceptions' }, 'raise exceptions'), + createDom('input', { + className: 'raise', + id: 'raise-exceptions', + type: 'checkbox' + }) + )); + var checkbox = find('#raise-exceptions'); + + checkbox.checked = !env.catchingExceptions(); + checkbox.onclick = onRaiseExceptionsClick; + + if (specsExecuted < totalSpecsDefined) { + var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all'; + alert.appendChild( + createDom('span', {className: 'bar skipped'}, + createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage) + ) + ); + } + var statusBarMessage = ''; + var statusBarClassName = 'bar '; - this.suiteComplete = function(suite) { - var suiteView = this.views.suites[suite.id]; - if (isUndefined(suiteView)) { - return; - } - suiteView.refresh(); - }; + if (totalSpecsDefined > 0) { + statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount); + if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); } + statusBarClassName += (failureCount > 0) ? 'failed' : 'passed'; + } else { + statusBarClassName += 'skipped'; + statusBarMessage += 'No specs found'; + } - this.refresh = function() { + alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage)); + + var results = find('.results'); + results.appendChild(summary); + + summaryList(topResults, summary); + + function summaryList(resultsTree, domParent) { + var specListNode; + for (var i = 0; i < resultsTree.children.length; i++) { + var resultNode = resultsTree.children[i]; + if (resultNode.type == 'suite') { + var suiteListNode = createDom('ul', {className: 'suite', id: 'suite-' + resultNode.result.id}, + createDom('li', {className: 'suite-detail'}, + createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) + ) + ); + + summaryList(resultNode, suiteListNode); + domParent.appendChild(suiteListNode); + } + if (resultNode.type == 'spec') { + if (domParent.getAttribute('class') != 'specs') { + specListNode = createDom('ul', {className: 'specs'}); + domParent.appendChild(specListNode); + } + var specDescription = resultNode.result.description; + if(resultNode.result.status == 'empty') { + specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; + } + specListNode.appendChild( + createDom('li', { + className: resultNode.result.status, + id: 'spec-' + resultNode.result.id + }, + createDom('a', {href: specHref(resultNode.result)}, specDescription) + ) + ); + } + } + } - if (isUndefined(this.resultsMenu)) { - this.createResultsMenu(); - } + if (failures.length) { + alert.appendChild( + createDom('span', {className: 'menu bar spec-list'}, + createDom('span', {}, 'Spec List | '), + createDom('a', {className: 'failures-menu', href: '#'}, 'Failures'))); + alert.appendChild( + createDom('span', {className: 'menu bar failure-list'}, + createDom('a', {className: 'spec-list-menu', href: '#'}, 'Spec List'), + createDom('span', {}, ' | Failures '))); + + find('.failures-menu').onclick = function() { + setMenuModeTo('failure-list'); + }; + find('.spec-list-menu').onclick = function() { + setMenuModeTo('spec-list'); + }; + + setMenuModeTo('failure-list'); + + var failureNode = find('.failures'); + for (var i = 0; i < failures.length; i++) { + failureNode.appendChild(failures[i]); + } + } + }; - // currently running UI - if (isUndefined(this.runningAlert)) { - 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); + return this; - // skipped specs UI - if (isUndefined(this.skippedAlert)) { - this.skippedAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "skippedAlert bar" }); + function find(selector) { + return getContainer().querySelector('.html-reporter ' + selector); } - this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; + function createDom(type, attrs, childrenVarArgs) { + var el = createElement(type); - if (this.skippedCount === 1 && isDefined(dom.alert)) { - dom.alert.appendChild(this.skippedAlert); - } + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; - // passing specs UI - if (isUndefined(this.passedAlert)) { - this.passedAlert = this.createDom('span', { href: jasmine.HtmlReporter.sectionLink(), className: "passingAlert bar" }); - } - this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount); + if (typeof child === 'string') { + el.appendChild(createTextNode(child)); + } else { + if (child) { + el.appendChild(child); + } + } + } - // failing specs UI - if (isUndefined(this.failedAlert)) { - this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"}); - } - this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount); + for (var attr in attrs) { + if (attr == 'className') { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } - if (this.failedCount === 1 && isDefined(dom.alert)) { - dom.alert.appendChild(this.failedAlert); - dom.alert.appendChild(this.resultsMenu); + return el; } - // summary info - this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount); - this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing"; - }; - - this.complete = function() { - dom.alert.removeChild(this.runningAlert); + function pluralize(singular, count) { + var word = (count == 1 ? singular : singular + 's'); - this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; - - if (this.failedCount === 0) { - dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount))); - } else { - showDetails(); + return '' + count + ' ' + word; } - dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s")); - }; - - return this; - - function showDetails() { - if (dom.reporter.className.search(/showDetails/) === -1) { - dom.reporter.className += " showDetails"; + function specHref(result) { + return '?spec=' + encodeURIComponent(result.fullName); } - } - - function isUndefined(obj) { - return typeof obj === 'undefined'; - } - - function isDefined(obj) { - return !isUndefined(obj); - } - function specPluralizedFor(count) { - var str = count + " spec"; - if (count > 1) { - str += "s" + function setMenuModeTo(mode) { + htmlReporterMain.setAttribute('class', 'html-reporter ' + mode); } - return str; } + return HtmlReporter; }; -jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView); - - -jasmine.HtmlReporter.SpecView = function(spec, dom, views) { - this.spec = spec; - this.dom = dom; - this.views = views; - - this.symbol = this.createDom('li', { className: 'pending' }); - this.dom.symbolSummary.appendChild(this.symbol); +jasmineRequire.HtmlSpecFilter = function() { + function HtmlSpecFilter(options) { + var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); + var filterPattern = new RegExp(filterString); - this.summary = this.createDom('div', { className: 'specSummary' }, - 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' }, - this.createDom('a', { - className: 'description', - href: '?spec=' + encodeURIComponent(this.spec.getFullName()), - title: this.spec.getFullName() - }, this.spec.getFullName()) - ); -}; - -jasmine.HtmlReporter.SpecView.prototype.status = function() { - return this.getSpecStatus(this.spec); -}; - -jasmine.HtmlReporter.SpecView.prototype.refresh = function() { - this.symbol.className = this.status(); - - switch (this.status()) { - case 'skipped': - break; - - case 'passed': - this.appendSummaryToSuiteDiv(); - break; - - case 'failed': - this.appendSummaryToSuiteDiv(); - this.appendFailureDetail(); - break; - } -}; - -jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() { - this.summary.className += ' ' + this.status(); - this.appendToSummary(this.spec, this.summary); -}; - -jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() { - this.detail.className += ' ' + this.status(); - - var resultItems = this.spec.results().getItems(); - var messagesDiv = this.createDom('div', { className: 'messages' }); - - for (var i = 0; i < resultItems.length; i++) { - var result = resultItems[i]; - - if (result.type == 'log') { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); - } else if (result.type == 'expect' && result.passed && !result.passed()) { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); - - if (result.trace.stack) { - messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); - } - } - } - - if (messagesDiv.childNodes.length > 0) { - this.detail.appendChild(messagesDiv); - this.dom.details.appendChild(this.detail); + this.matches = function(specName) { + return filterPattern.test(specName); + }; } -}; - -jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) { - this.suite = suite; - this.dom = dom; - this.views = views; - this.element = this.createDom('div', { className: 'suite' }, - this.createDom('a', { className: 'description', href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()) }, this.suite.description) - ); - - this.appendToSummary(this.suite, this.element); -}; - -jasmine.HtmlReporter.SuiteView.prototype.status = function() { - return this.getSpecStatus(this.suite); + return HtmlSpecFilter; }; -jasmine.HtmlReporter.SuiteView.prototype.refresh = function() { - this.element.className += " " + this.status(); -}; - -jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView); - -/* @deprecated Use jasmine.HtmlReporter instead - */ -jasmine.TrivialReporter = function(doc) { - this.document = doc || document; - this.suiteDivs = {}; - this.logRunningSpecs = false; -}; +jasmineRequire.ResultsNode = function() { + function ResultsNode(result, type, parent) { + this.result = result; + this.type = type; + this.parent = parent; -jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { - var el = document.createElement(type); + this.children = []; - for (var i = 2; i < arguments.length; i++) { - var child = arguments[i]; - - if (typeof child === 'string') { - el.appendChild(document.createTextNode(child)); - } else { - if (child) { el.appendChild(child); } - } - } + this.addChild = function(result, type) { + this.children.push(new ResultsNode(result, type, this)); + }; - for (var attr in attrs) { - if (attr == "className") { - el[attr] = attrs[attr]; - } else { - el.setAttribute(attr, attrs[attr]); - } + this.last = function() { + return this.children[this.children.length - 1]; + }; } - return el; + return ResultsNode; }; -jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { - var showPassed, showSkipped; - - this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' }, - this.createDom('div', { className: 'banner' }, - this.createDom('div', { className: 'logo' }, - this.createDom('span', { className: 'title' }, "Jasmine"), - this.createDom('span', { className: 'version' }, runner.env.versionString())), - this.createDom('div', { className: 'options' }, - "Show ", - showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), - this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), - showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), - this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") - ) - ), - - this.runnerDiv = this.createDom('div', { className: 'runner running' }, - this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), - this.runnerMessageSpan = this.createDom('span', {}, "Running..."), - this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) - ); - - this.document.body.appendChild(this.outerDiv); - - var suites = runner.suites(); - for (var i = 0; i < suites.length; i++) { - var suite = suites[i]; - var suiteDiv = this.createDom('div', { className: 'suite' }, - this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), - this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); - this.suiteDivs[suite.id] = suiteDiv; - var parentDiv = this.outerDiv; - if (suite.parentSuite) { - parentDiv = this.suiteDivs[suite.parentSuite.id]; - } - parentDiv.appendChild(suiteDiv); - } - - this.startedAt = new Date(); - - var self = this; - showPassed.onclick = function(evt) { - if (showPassed.checked) { - self.outerDiv.className += ' show-passed'; - } else { - self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); - } - }; - - showSkipped.onclick = function(evt) { - if (showSkipped.checked) { - self.outerDiv.className += ' show-skipped'; - } else { - self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); - } - }; -}; +jasmineRequire.QueryString = function() { + function QueryString(options) { -jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { - var results = runner.results(); - var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; - this.runnerDiv.setAttribute("class", className); - //do it twice for IE - this.runnerDiv.setAttribute("className", className); - var specs = runner.specs(); - var specCount = 0; - for (var i = 0; i < specs.length; i++) { - if (this.specFilter(specs[i])) { - specCount++; - } - } - var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); - message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; - this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); - - this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); -}; + this.setParam = function(key, value) { + var paramMap = queryStringToParamMap(); + paramMap[key] = value; + options.getWindowLocation().search = toQueryString(paramMap); + }; -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 - status = 'skipped'; - } - this.suiteDivs[suite.id].className += " " + status; -}; + this.getParam = function(key) { + return queryStringToParamMap()[key]; + }; -jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { - if (this.logRunningSpecs) { - this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); - } -}; + return this; -jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { - var results = spec.results(); - var status = results.passed() ? 'passed' : 'failed'; - if (results.skipped) { - status = 'skipped'; - } - var specDiv = this.createDom('div', { className: 'spec ' + status }, - this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), - this.createDom('a', { - className: 'description', - href: '?spec=' + encodeURIComponent(spec.getFullName()), - title: spec.getFullName() - }, spec.description)); - - - var resultItems = results.getItems(); - var messagesDiv = this.createDom('div', { className: 'messages' }); - for (var i = 0; i < resultItems.length; i++) { - var result = resultItems[i]; - - if (result.type == 'log') { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); - } else if (result.type == 'expect' && result.passed && !result.passed()) { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); - - if (result.trace.stack) { - messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + function toQueryString(paramMap) { + var qStrPairs = []; + for (var prop in paramMap) { + qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])); + } + return '?' + qStrPairs.join('&'); + } + + function queryStringToParamMap() { + var paramStr = options.getWindowLocation().search.substring(1), + params = [], + paramMap = {}; + + if (paramStr.length > 0) { + params = paramStr.split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + var value = decodeURIComponent(p[1]); + if (value === 'true' || value === 'false') { + value = JSON.parse(value); + } + paramMap[decodeURIComponent(p[0])] = value; + } } - } - } - - if (messagesDiv.childNodes.length > 0) { - specDiv.appendChild(messagesDiv); - } - - this.suiteDivs[spec.suite.id].appendChild(specDiv); -}; -jasmine.TrivialReporter.prototype.log = function() { - var console = jasmine.getGlobal().console; - if (console && console.log) { - if (console.log.apply) { - console.log.apply(console, arguments); - } else { - console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + return paramMap; } - } -}; - -jasmine.TrivialReporter.prototype.getLocation = function() { - return this.document.location; -}; -jasmine.TrivialReporter.prototype.specFilter = function(spec) { - var paramMap = {}; - var params = this.getLocation().search.substring(1).split('&'); - for (var i = 0; i < params.length; i++) { - var p = params[i].split('='); - paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); } - if (!paramMap.spec) { - return true; - } - return spec.getFullName().indexOf(paramMap.spec) === 0; -}; + return QueryString; +}; \ No newline at end of file diff --git a/vendor/assets/javascripts/jasmine.js b/vendor/assets/javascripts/jasmine.js index 6b3459b..1bfe4e8 100644 --- a/vendor/assets/javascripts/jasmine.js +++ b/vendor/assets/javascripts/jasmine.js @@ -1,2600 +1,2515 @@ -var isCommonJS = typeof window == "undefined" && typeof exports == "object"; - -/** - * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. - * - * @namespace - */ -var jasmine = {}; -if (isCommonJS) exports.jasmine = jasmine; -/** - * @private - */ -jasmine.unimplementedMethod_ = function() { - throw new Error("unimplemented method"); -}; +/* +Copyright (c) 2008-2014 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +function getJasmineRequireObj() { + if (typeof module !== 'undefined' && module.exports) { + return exports; + } else { + window.jasmineRequire = window.jasmineRequire || {}; + return window.jasmineRequire; + } +} + +getJasmineRequireObj().core = function(jRequire) { + var j$ = {}; + + jRequire.base(j$); + j$.util = jRequire.util(); + j$.Any = jRequire.Any(); + j$.CallTracker = jRequire.CallTracker(); + j$.MockDate = jRequire.MockDate(); + j$.Clock = jRequire.Clock(); + j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(); + j$.Env = jRequire.Env(j$); + j$.ExceptionFormatter = jRequire.ExceptionFormatter(); + j$.Expectation = jRequire.Expectation(); + j$.buildExpectationResult = jRequire.buildExpectationResult(); + j$.JsApiReporter = jRequire.JsApiReporter(); + j$.matchersUtil = jRequire.matchersUtil(j$); + j$.ObjectContaining = jRequire.ObjectContaining(j$); + j$.pp = jRequire.pp(j$); + j$.QueueRunner = jRequire.QueueRunner(j$); + j$.ReportDispatcher = jRequire.ReportDispatcher(); + j$.Spec = jRequire.Spec(j$); + j$.SpyStrategy = jRequire.SpyStrategy(); + j$.Suite = jRequire.Suite(); + j$.Timer = jRequire.Timer(); + j$.version = jRequire.version(); + + j$.matchers = jRequire.requireMatchers(jRequire, j$); + + return j$; +}; + +getJasmineRequireObj().requireMatchers = function(jRequire, j$) { + var availableMatchers = [ + 'toBe', + 'toBeCloseTo', + 'toBeDefined', + 'toBeFalsy', + 'toBeGreaterThan', + 'toBeLessThan', + 'toBeNaN', + 'toBeNull', + 'toBeTruthy', + 'toBeUndefined', + 'toContain', + 'toEqual', + 'toHaveBeenCalled', + 'toHaveBeenCalledWith', + 'toMatch', + 'toThrow', + 'toThrowError' + ], + matchers = {}; + + for (var i = 0; i < availableMatchers.length; i++) { + var name = availableMatchers[i]; + matchers[name] = jRequire[name](j$); + } + + return matchers; +}; + +getJasmineRequireObj().base = (function (jasmineGlobal) { + if (typeof module !== 'undefined' && module.exports) { + jasmineGlobal = global; + } + + return function(j$) { + j$.unimplementedMethod_ = function() { + throw new Error('unimplemented method'); + }; -/** - * Use jasmine.undefined instead of undefined, since undefined is just - * a plain old variable and may be redefined by somebody else. - * - * @private - */ -jasmine.undefined = jasmine.___undefined___; - -/** - * Show diagnostic messages in the console if set to true - * - */ -jasmine.VERBOSE = false; - -/** - * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. - * - */ -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; - } + j$.MAX_PRETTY_PRINT_DEPTH = 40; + j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100; + j$.DEFAULT_TIMEOUT_INTERVAL = 5000; - return getGlobal(); -}; + j$.getGlobal = function() { + return jasmineGlobal; + }; -/** - * Allows for bound functions to be compared. Internal use only. - * - * @ignore - * @private - * @param base {Object} bound 'this' for the function - * @param name {Function} function to find - */ -jasmine.bindOriginal_ = function(base, name) { - var original = base[name]; - if (original.apply) { - return function() { - return original.apply(base, arguments); + j$.getEnv = function(options) { + var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options); + //jasmine. singletons in here (setTimeout blah blah). + return env; }; - } else { - // IE support - return jasmine.getGlobal()[name]; - } -}; -jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); -jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); -jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); -jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); + j$.isArray_ = function(value) { + return j$.isA_('Array', value); + }; -jasmine.MessageResult = function(values) { - this.type = 'log'; - this.values = values; - this.trace = new Error(); // todo: test better -}; + j$.isString_ = function(value) { + return j$.isA_('String', value); + }; -jasmine.MessageResult.prototype.toString = function() { - var text = ""; - for (var i = 0; i < this.values.length; i++) { - if (i > 0) text += " "; - if (jasmine.isString_(this.values[i])) { - text += this.values[i]; - } else { - text += jasmine.pp(this.values[i]); - } - } - return text; -}; + j$.isNumber_ = function(value) { + return j$.isA_('Number', value); + }; -jasmine.ExpectationResult = function(params) { - this.type = 'expect'; - this.matcherName = params.matcherName; - this.passed_ = params.passed; - this.expected = params.expected; - this.actual = params.actual; - this.message = this.passed_ ? 'Passed.' : params.message; + j$.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; + }; - var trace = (params.trace || new Error(this.message)); - this.trace = this.passed_ ? '' : trace; -}; + j$.isDomNode = function(obj) { + return obj.nodeType > 0; + }; -jasmine.ExpectationResult.prototype.toString = function () { - return this.message; -}; + j$.any = function(clazz) { + return new j$.Any(clazz); + }; -jasmine.ExpectationResult.prototype.passed = function () { - return this.passed_; -}; + j$.objectContaining = function(sample) { + return new j$.ObjectContaining(sample); + }; -/** - * Getter for the Jasmine environment. Ensures one gets created - */ -jasmine.getEnv = function() { - var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); - return env; -}; + j$.createSpy = function(name, originalFn) { + + var spyStrategy = new j$.SpyStrategy({ + name: name, + fn: originalFn, + getSpy: function() { return spy; } + }), + callTracker = new j$.CallTracker(), + spy = function() { + callTracker.track({ + object: this, + args: Array.prototype.slice.apply(arguments) + }); + return spyStrategy.exec.apply(this, arguments); + }; + + for (var prop in originalFn) { + if (prop === 'and' || prop === 'calls') { + throw new Error('Jasmine spies would overwrite the \'and\' and \'calls\' properties on the object being spied upon'); + } -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isArray_ = function(value) { - return jasmine.isA_("Array", value); -}; + spy[prop] = originalFn[prop]; + } -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isString_ = function(value) { - return jasmine.isA_("String", value); -}; + spy.and = spyStrategy; + spy.calls = callTracker; -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isNumber_ = function(value) { - return jasmine.isA_("Number", value); -}; + return spy; + }; -/** - * @ignore - * @private - * @param {String} typeName - * @param value - * @returns {Boolean} - */ -jasmine.isA_ = function(typeName, value) { - return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; -}; + j$.isSpy = function(putativeSpy) { + if (!putativeSpy) { + return false; + } + return putativeSpy.and instanceof j$.SpyStrategy && + putativeSpy.calls instanceof j$.CallTracker; + }; -/** - * Pretty printer for expecations. Takes any object and turns it into a human-readable string. - * - * @param value {Object} an object to be outputted - * @returns {String} - */ -jasmine.pp = function(value) { - var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); - stringPrettyPrinter.format(value); - return stringPrettyPrinter.string; -}; + j$.createSpyObj = function(baseName, methodNames) { + if (!j$.isArray_(methodNames) || methodNames.length === 0) { + throw 'createSpyObj requires a non-empty array of method names to create spies for'; + } + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]); + } + return obj; + }; + }; +})(this); -/** - * Returns true if the object is a DOM Node. - * - * @param {Object} obj object to check - * @returns {Boolean} - */ -jasmine.isDomNode = function(obj) { - return obj.nodeType > 0; -}; +getJasmineRequireObj().util = function() { -/** - * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. - * - * @example - * // don't care about which function is passed in, as long as it's a function - * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); - * - * @param {Class} clazz - * @returns matchable object of the type clazz - */ -jasmine.any = function(clazz) { - return new jasmine.Matchers.Any(clazz); -}; + var util = {}; -/** - * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the - * attributes on the object. - * - * @example - * // don't care about any other attributes than foo. - * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"}); - * - * @param sample {Object} sample - * @returns matchable object for the sample - */ -jasmine.objectContaining = function (sample) { - return new jasmine.Matchers.ObjectContaining(sample); -}; + util.inherit = function(childClass, parentClass) { + var Subclass = function() { + }; + Subclass.prototype = parentClass.prototype; + childClass.prototype = new Subclass(); + }; -/** - * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. - * - * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine - * expectation syntax. Spies can be checked if they were called or not and what the calling params were. - * - * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). - * - * Spies are torn down at the end of every spec. - * - * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. - * - * @example - * // a stub - * var myStub = jasmine.createSpy('myStub'); // can be used anywhere - * - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // actual foo.not will not be called, execution stops - * spyOn(foo, 'not'); - - // foo.not spied upon, execution will continue to implementation - * spyOn(foo, 'not').andCallThrough(); - * - * // fake example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // foo.not(val) will return val - * spyOn(foo, 'not').andCallFake(function(value) {return value;}); - * - * // mock example - * foo.not(7 == 7); - * expect(foo.not).toHaveBeenCalled(); - * expect(foo.not).toHaveBeenCalledWith(true); - * - * @constructor - * @see spyOn, jasmine.createSpy, jasmine.createSpyObj - * @param {String} name - */ -jasmine.Spy = function(name) { - /** - * The name of the spy, if provided. - */ - this.identity = name || 'unknown'; - /** - * Is this Object a spy? - */ - this.isSpy = true; - /** - * The actual function this spy stubs. - */ - this.plan = function() { + util.htmlEscape = function(str) { + if (!str) { + return str; + } + return str.replace(/&/g, '&') + .replace(//g, '>'); }; - /** - * Tracking of the most recent call to the spy. - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy.mostRecentCall.args = [1, 2]; - */ - this.mostRecentCall = {}; - - /** - * Holds arguments for each call to the spy, indexed by call count - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy(7, 8); - * mySpy.mostRecentCall.args = [7, 8]; - * mySpy.argsForCall[0] = [1, 2]; - * mySpy.argsForCall[1] = [7, 8]; - */ - this.argsForCall = []; - this.calls = []; -}; -/** - * Tells a spy to call through to the actual implemenatation. - * - * @example - * var foo = { - * bar: function() { // do some stuff } - * } - * - * // defining a spy on an existing property: foo.bar - * spyOn(foo, 'bar').andCallThrough(); - */ -jasmine.Spy.prototype.andCallThrough = function() { - this.plan = this.originalValue; - return this; -}; + util.argsToArray = function(args) { + var arrayOfArgs = []; + for (var i = 0; i < args.length; i++) { + arrayOfArgs.push(args[i]); + } + return arrayOfArgs; + }; -/** - * For setting the return value of a spy. - * - * @example - * // defining a spy from scratch: foo() returns 'baz' - * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); - * - * // defining a spy on an existing property: foo.bar() returns 'baz' - * spyOn(foo, 'bar').andReturn('baz'); - * - * @param {Object} value - */ -jasmine.Spy.prototype.andReturn = function(value) { - this.plan = function() { - return value; + util.isUndefined = function(obj) { + return obj === void 0; }; - return this; -}; -/** - * For throwing an exception when a spy is called. - * - * @example - * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' - * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); - * - * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' - * spyOn(foo, 'bar').andThrow('baz'); - * - * @param {String} exceptionMsg - */ -jasmine.Spy.prototype.andThrow = function(exceptionMsg) { - this.plan = function() { - throw exceptionMsg; + util.arrayContains = function(array, search) { + var i = array.length; + while (i--) { + if (array[i] == search) { + return true; + } + } + return false; }; - return this; -}; -/** - * Calls an alternate implementation when a spy is called. - * - * @example - * var baz = function() { - * // do some stuff, return something - * } - * // defining a spy from scratch: foo() calls the function baz - * var foo = jasmine.createSpy('spy on foo').andCall(baz); - * - * // defining a spy on an existing property: foo.bar() calls an anonymnous function - * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); - * - * @param {Function} fakeFunc - */ -jasmine.Spy.prototype.andCallFake = function(fakeFunc) { - this.plan = fakeFunc; - return this; -}; + return util; +}; + +getJasmineRequireObj().Spec = function(j$) { + function Spec(attrs) { + this.expectationFactory = attrs.expectationFactory; + this.resultCallback = attrs.resultCallback || function() {}; + this.id = attrs.id; + this.description = attrs.description || ''; + this.fn = attrs.fn; + this.beforeFns = attrs.beforeFns || function() { return []; }; + this.afterFns = attrs.afterFns || function() { return []; }; + this.onStart = attrs.onStart || function() {}; + this.exceptionFormatter = attrs.exceptionFormatter || function() {}; + this.getSpecName = attrs.getSpecName || function() { return ''; }; + this.expectationResultFactory = attrs.expectationResultFactory || function() { }; + this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; + this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; + this.expectCalled = false; + + if (!this.fn) { + this.pend(); + } -/** - * Resets all of a spy's the tracking variables so that it can be used again. - * - * @example - * spyOn(foo, 'bar'); - * - * foo.bar(); - * - * expect(foo.bar.callCount).toEqual(1); - * - * foo.bar.reset(); - * - * expect(foo.bar.callCount).toEqual(0); - */ -jasmine.Spy.prototype.reset = function() { - this.wasCalled = false; - this.callCount = 0; - this.argsForCall = []; - this.calls = []; - this.mostRecentCall = {}; -}; + this.result = { + id: this.id, + description: this.description, + fullName: this.getFullName(), + failedExpectations: [] + }; + } -jasmine.createSpy = function(name) { - - var spyObj = function() { - spyObj.wasCalled = true; - spyObj.callCount++; - var args = jasmine.util.argsToArray(arguments); - spyObj.mostRecentCall.object = this; - spyObj.mostRecentCall.args = args; - spyObj.argsForCall.push(args); - spyObj.calls.push({object: this, args: args}); - return spyObj.plan.apply(this, arguments); + Spec.prototype.addExpectationResult = function(passed, data) { + this.expectCalled = true; + if (passed) { + return; + } + this.result.failedExpectations.push(this.expectationResultFactory(data)); }; - var spy = new jasmine.Spy(name); + Spec.prototype.expect = function(actual) { + return this.expectationFactory(actual, this); + }; - for (var prop in spy) { - spyObj[prop] = spy[prop]; - } + Spec.prototype.execute = function(onComplete) { + var self = this; - spyObj.reset(); + this.onStart(this); - return spyObj; -}; + if (this.markedPending || this.disabled) { + complete(); + return; + } -/** - * Determines whether an object is a spy. - * - * @param {jasmine.Spy|Object} putativeSpy - * @returns {Boolean} - */ -jasmine.isSpy = function(putativeSpy) { - return putativeSpy && putativeSpy.isSpy; -}; + var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()); -/** - * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something - * large in one call. - * - * @param {String} baseName name of spy class - * @param {Array} methodNames array of names of methods to make spies - */ -jasmine.createSpyObj = function(baseName, methodNames) { - 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 = {}; - for (var i = 0; i < methodNames.length; i++) { - obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); - } - return obj; -}; + this.queueRunnerFactory({ + fns: allFns, + onException: onException, + onComplete: complete, + enforceTimeout: function() { return true; } + }); -/** - * All parameters are pretty-printed and concatenated together, then written to the current spec's output. - * - * Be careful not to leave calls to jasmine.log in production code. - */ -jasmine.log = function() { - var spec = jasmine.getEnv().currentSpec; - spec.log.apply(spec, arguments); -}; + function onException(e) { + if (Spec.isPendingSpecException(e)) { + self.pend(); + return; + } -/** - * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. - * - * @example - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops - * - * @see jasmine.createSpy - * @param obj - * @param methodName - * @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); -}; -if (isCommonJS) exports.spyOn = spyOn; - -/** - * Creates a Jasmine spec that will be added to the current suite. - * - * // TODO: pending tests - * - * @example - * it('should be true', function() { - * expect(true).toEqual(true); - * }); - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var it = function(desc, func) { - return jasmine.getEnv().it(desc, func); -}; -if (isCommonJS) exports.it = it; - -/** - * Creates a disabled Jasmine spec. - * - * A convenience method that allows existing specs to be disabled temporarily during development. - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var xit = function(desc, func) { - return jasmine.getEnv().xit(desc, func); -}; -if (isCommonJS) exports.xit = xit; - -/** - * Starts a chain for a Jasmine expectation. - * - * It is passed an Object that is the actual value and should chain to one of the many - * 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); -}; -if (isCommonJS) exports.expect = expect; - -/** - * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. - * - * @param {Function} func Function that defines part of a jasmine spec. - */ -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. - * - * @deprecated Use waitsFor() instead - * @param {Number} timeout milliseconds to wait - */ -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. - * - * @param {Function} latchFunction - * @param {String} optional_timeoutMessage - * @param {Number} optional_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. - * - * Used for spec setup, including validating assumptions. - * - * @param {Function} beforeEachFunction - */ -var beforeEach = function(beforeEachFunction) { - jasmine.getEnv().beforeEach(beforeEachFunction); -}; -if (isCommonJS) exports.beforeEach = beforeEach; - -/** - * A function that is called after each spec in a suite. - * - * Used for restoring any state that is hijacked during spec execution. - * - * @param {Function} afterEachFunction - */ -var afterEach = function(afterEachFunction) { - jasmine.getEnv().afterEach(afterEachFunction); -}; -if (isCommonJS) exports.afterEach = afterEach; - -/** - * Defines a suite of specifications. - * - * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared - * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization - * of setup in some tests. - * - * @example - * // TODO: a simple suite - * - * // TODO: a simple suite with a nested describe block - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -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. - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -var xdescribe = function(description, specDefinitions) { - return jasmine.getEnv().xdescribe(description, specDefinitions); -}; -if (isCommonJS) exports.xdescribe = xdescribe; + self.addExpectationResult(false, { + matcherName: '', + passed: false, + expected: '', + actual: '', + error: e + }); + } + function complete() { + self.result.status = self.status(); + self.resultCallback(self.result); -// Provide the XMLHttpRequest class for IE 5.x-6.x: -jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { - function tryIt(f) { - try { - return f(); - } catch(e) { + if (onComplete) { + onComplete(); + } } - return null; - } + }; - 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"); - }); + Spec.prototype.disable = function() { + this.disabled = true; + }; - if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); - - return xhr; -} : XMLHttpRequest; -/** - * @namespace - */ -jasmine.util = {}; - -/** - * Declare that a child class inherit it's prototype from the parent class. - * - * @private - * @param {Function} childClass - * @param {Function} parentClass - */ -jasmine.util.inherit = function(childClass, parentClass) { - /** - * @private - */ - var subclass = function() { + Spec.prototype.pend = function() { + this.markedPending = true; }; - subclass.prototype = parentClass.prototype; - childClass.prototype = new subclass(); -}; -jasmine.util.formatException = function(e) { - var lineNumber; - if (e.line) { - lineNumber = e.line; - } - else if (e.lineNumber) { - lineNumber = e.lineNumber; - } + Spec.prototype.status = function() { + if (this.disabled) { + return 'disabled'; + } - var file; + if (this.markedPending) { + return 'pending'; + } - if (e.sourceURL) { - file = e.sourceURL; - } - else if (e.fileName) { - file = e.fileName; - } + if(!this.expectCalled) { + return 'empty'; + } - var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); + if (this.result.failedExpectations.length > 0) { + return 'failed'; + } else { + return 'passed'; + } + }; - if (file && lineNumber) { - message += ' in ' + file + ' (line ' + lineNumber + ')'; - } + Spec.prototype.getFullName = function() { + return this.getSpecName(this); + }; - return message; -}; + Spec.pendingSpecExceptionMessage = '=> marked Pending'; -jasmine.util.htmlEscape = function(str) { - if (!str) return str; - return str.replace(/&/g, '&') - .replace(//g, '>'); -}; + Spec.isPendingSpecException = function(e) { + return !!(e && e.toString && e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1); + }; -jasmine.util.argsToArray = function(args) { - var arrayOfArgs = []; - for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); - return arrayOfArgs; + return Spec; }; -jasmine.util.extend = function(destination, source) { - for (var property in source) destination[property] = source[property]; - return destination; +if (typeof window == void 0 && typeof exports == 'object') { + exports.Spec = jasmineRequire.Spec; +} + +getJasmineRequireObj().Env = function(j$) { + function Env(options) { + options = options || {}; + + var self = this; + var global = options.global || j$.getGlobal(); + + var totalSpecsDefined = 0; + + var catchExceptions = true; + + var realSetTimeout = j$.getGlobal().setTimeout; + var realClearTimeout = j$.getGlobal().clearTimeout; + this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler(), new j$.MockDate(global)); + + var runnableLookupTable = {}; + + var spies = []; + + var currentSpec = null; + var currentSuite = null; + + var reporter = new j$.ReportDispatcher([ + 'jasmineStarted', + 'jasmineDone', + 'suiteStarted', + 'suiteDone', + 'specStarted', + 'specDone' + ]); + + this.specFilter = function() { + return true; + }; + + var equalityTesters = []; + + var customEqualityTesters = []; + this.addCustomEqualityTester = function(tester) { + customEqualityTesters.push(tester); + }; + + j$.Expectation.addCoreMatchers(j$.matchers); + + var nextSpecId = 0; + var getNextSpecId = function() { + return 'spec' + nextSpecId++; + }; + + var nextSuiteId = 0; + var getNextSuiteId = function() { + return 'suite' + nextSuiteId++; + }; + + var expectationFactory = function(actual, spec) { + return j$.Expectation.Factory({ + util: j$.matchersUtil, + customEqualityTesters: customEqualityTesters, + actual: actual, + addExpectationResult: addExpectationResult + }); + + function addExpectationResult(passed, result) { + return spec.addExpectationResult(passed, result); + } + }; + + var specStarted = function(spec) { + currentSpec = spec; + reporter.specStarted(spec.result); + }; + + var beforeFns = function(suite) { + return function() { + var befores = []; + while(suite) { + befores = befores.concat(suite.beforeFns); + suite = suite.parentSuite; + } + return befores.reverse(); + }; + }; + + var afterFns = function(suite) { + return function() { + var afters = []; + while(suite) { + afters = afters.concat(suite.afterFns); + suite = suite.parentSuite; + } + return afters; + }; + }; + + var getSpecName = function(spec, suite) { + return suite.getFullName() + ' ' + spec.description; + }; + + // TODO: we may just be able to pass in the fn instead of wrapping here + var buildExpectationResult = j$.buildExpectationResult, + exceptionFormatter = new j$.ExceptionFormatter(), + expectationResultFactory = function(attrs) { + attrs.messageFormatter = exceptionFormatter.message; + attrs.stackFormatter = exceptionFormatter.stack; + + return buildExpectationResult(attrs); + }; + + // TODO: fix this naming, and here's where the value comes in + this.catchExceptions = function(value) { + catchExceptions = !!value; + return catchExceptions; + }; + + this.catchingExceptions = function() { + return catchExceptions; + }; + + var maximumSpecCallbackDepth = 20; + var currentSpecCallbackDepth = 0; + + function clearStack(fn) { + currentSpecCallbackDepth++; + if (currentSpecCallbackDepth >= maximumSpecCallbackDepth) { + currentSpecCallbackDepth = 0; + realSetTimeout(fn, 0); + } else { + fn(); + } + } + + var catchException = function(e) { + return j$.Spec.isPendingSpecException(e) || catchExceptions; + }; + + var queueRunnerFactory = function(options) { + options.catchException = catchException; + options.clearStack = options.clearStack || clearStack; + options.timer = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}; + + new j$.QueueRunner(options).execute(); + }; + + var topSuite = new j$.Suite({ + env: this, + id: getNextSuiteId(), + description: 'Jasmine__TopLevel__Suite', + queueRunner: queueRunnerFactory, + resultCallback: function() {} // TODO - hook this up + }); + runnableLookupTable[topSuite.id] = topSuite; + currentSuite = topSuite; + + this.topSuite = function() { + return topSuite; + }; + + this.execute = function(runnablesToRun) { + runnablesToRun = runnablesToRun || [topSuite.id]; + + var allFns = []; + for(var i = 0; i < runnablesToRun.length; i++) { + var runnable = runnableLookupTable[runnablesToRun[i]]; + allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable)); + } + + reporter.jasmineStarted({ + totalSpecsDefined: totalSpecsDefined + }); + + queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone}); + }; + + this.addReporter = function(reporterToAdd) { + reporter.addReporter(reporterToAdd); + }; + + this.addMatchers = function(matchersToAdd) { + j$.Expectation.addMatchers(matchersToAdd); + }; + + this.spyOn = function(obj, methodName) { + if (j$.util.isUndefined(obj)) { + throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()'); + } + + if (j$.util.isUndefined(obj[methodName])) { + throw new Error(methodName + '() method does not exist'); + } + + if (obj[methodName] && j$.isSpy(obj[methodName])) { + //TODO?: should this return the current spy? Downside: may cause user confusion about spy state + throw new Error(methodName + ' has already been spied upon'); + } + + var spy = j$.createSpy(methodName, obj[methodName]); + + spies.push({ + spy: spy, + baseObj: obj, + methodName: methodName, + originalValue: obj[methodName] + }); + + obj[methodName] = spy; + + return spy; + }; + + var suiteFactory = function(description) { + var suite = new j$.Suite({ + env: self, + id: getNextSuiteId(), + description: description, + parentSuite: currentSuite, + queueRunner: queueRunnerFactory, + onStart: suiteStarted, + resultCallback: function(attrs) { + reporter.suiteDone(attrs); + } + }); + + runnableLookupTable[suite.id] = suite; + return suite; + }; + + this.describe = function(description, specDefinitions) { + var suite = suiteFactory(description); + + var parentSuite = currentSuite; + parentSuite.addChild(suite); + currentSuite = suite; + + var declarationError = null; + try { + specDefinitions.call(suite); + } catch (e) { + declarationError = e; + } + + if (declarationError) { + this.it('encountered a declaration exception', function() { + throw declarationError; + }); + } + + currentSuite = parentSuite; + + return suite; + }; + + this.xdescribe = function(description, specDefinitions) { + var suite = this.describe(description, specDefinitions); + suite.disable(); + return suite; + }; + + var specFactory = function(description, fn, suite) { + totalSpecsDefined++; + + var spec = new j$.Spec({ + id: getNextSpecId(), + beforeFns: beforeFns(suite), + afterFns: afterFns(suite), + expectationFactory: expectationFactory, + exceptionFormatter: exceptionFormatter, + resultCallback: specResultCallback, + getSpecName: function(spec) { + return getSpecName(spec, suite); + }, + onStart: specStarted, + description: description, + expectationResultFactory: expectationResultFactory, + queueRunnerFactory: queueRunnerFactory, + fn: fn + }); + + runnableLookupTable[spec.id] = spec; + + if (!self.specFilter(spec)) { + spec.disable(); + } + + return spec; + + function removeAllSpies() { + for (var i = 0; i < spies.length; i++) { + var spyEntry = spies[i]; + spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue; + } + spies = []; + } + + function specResultCallback(result) { + removeAllSpies(); + j$.Expectation.resetMatchers(); + customEqualityTesters = []; + currentSpec = null; + reporter.specDone(result); + } + }; + + var suiteStarted = function(suite) { + reporter.suiteStarted(suite.result); + }; + + this.it = function(description, fn) { + var spec = specFactory(description, fn, currentSuite); + currentSuite.addChild(spec); + return spec; + }; + + this.xit = function(description, fn) { + var spec = this.it(description, fn); + spec.pend(); + return spec; + }; + + this.expect = function(actual) { + return currentSpec.expect(actual); + }; + + this.beforeEach = function(beforeEachFunction) { + currentSuite.beforeEach(beforeEachFunction); + }; + + this.afterEach = function(afterEachFunction) { + currentSuite.afterEach(afterEachFunction); + }; + + this.pending = function() { + throw j$.Spec.pendingSpecExceptionMessage; + }; + } + + return Env; }; -/** - * Environment for Jasmine - * - * @constructor - */ -jasmine.Env = function() { - this.currentSpec = null; - this.currentSuite = null; - this.currentRunner_ = new jasmine.Runner(this); - - this.reporter = new jasmine.MultiReporter(); - - this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; - this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; - this.lastUpdate = 0; - this.specFilter = function() { - return true; +getJasmineRequireObj().JsApiReporter = function() { + + var noopTimer = { + start: function(){}, + elapsed: function(){ return 0; } }; - this.nextSpecId_ = 0; - this.nextSuiteId_ = 0; - this.equalityTesters_ = []; + function JsApiReporter(options) { + var timer = options.timer || noopTimer, + status = 'loaded'; - // wrap matchers - this.matchersClass = function() { - jasmine.Matchers.apply(this, arguments); - }; - jasmine.util.inherit(this.matchersClass, jasmine.Matchers); + this.started = false; + this.finished = false; - jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); -}; + this.jasmineStarted = function() { + this.started = true; + status = 'started'; + timer.start(); + }; + + var executionTime; + this.jasmineDone = function() { + this.finished = true; + executionTime = timer.elapsed(); + status = 'done'; + }; -jasmine.Env.prototype.setTimeout = jasmine.setTimeout; -jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; -jasmine.Env.prototype.setInterval = jasmine.setInterval; -jasmine.Env.prototype.clearInterval = jasmine.clearInterval; + this.status = function() { + return status; + }; + + var suites = {}; + + this.suiteStarted = function(result) { + storeSuite(result); + }; + + this.suiteDone = function(result) { + storeSuite(result); + }; + + function storeSuite(result) { + suites[result.id] = result; + } + + this.suites = function() { + return suites; + }; + + var specs = []; + this.specStarted = function(result) { }; + + this.specDone = function(result) { + specs.push(result); + }; + + this.specResults = function(index, length) { + return specs.slice(index, index + length); + }; + + this.specs = function() { + return specs; + }; + + this.executionTime = function() { + return executionTime; + }; -/** - * @returns an object containing jasmine version build info, if set. - */ -jasmine.Env.prototype.version = function () { - if (jasmine.version_) { - return jasmine.version_; - } else { - throw new Error('Version not set'); } + + return JsApiReporter; }; -/** - * @returns string containing jasmine version build info, if set. - */ -jasmine.Env.prototype.versionString = function() { - if (!jasmine.version_) { - return "version unknown"; - } +getJasmineRequireObj().Any = function() { - var version = this.version(); - var versionString = version.major + "." + version.minor + "." + version.build; - if (version.release_candidate) { - versionString += ".rc" + version.release_candidate; + function Any(expectedObject) { + this.expectedObject = expectedObject; } - versionString += " revision " + version.revision; - return versionString; -}; -/** - * @returns a sequential integer starting at 0 - */ -jasmine.Env.prototype.nextSpecId = function () { - return this.nextSpecId_++; -}; + Any.prototype.jasmineMatches = function(other) { + if (this.expectedObject == String) { + return typeof other == 'string' || other instanceof String; + } -/** - * @returns a sequential integer starting at 0 - */ -jasmine.Env.prototype.nextSuiteId = function () { - return this.nextSuiteId_++; -}; + if (this.expectedObject == Number) { + return typeof other == 'number' || other instanceof Number; + } -/** - * Register a reporter to receive status updates from Jasmine. - * @param {jasmine.Reporter} reporter An object which will receive status updates. - */ -jasmine.Env.prototype.addReporter = function(reporter) { - this.reporter.addReporter(reporter); -}; + if (this.expectedObject == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedObject == Object) { + return typeof other == 'object'; + } -jasmine.Env.prototype.execute = function() { - this.currentRunner_.execute(); + if (this.expectedObject == Boolean) { + return typeof other == 'boolean'; + } + + return other instanceof this.expectedObject; + }; + + Any.prototype.jasmineToString = function() { + return ''; + }; + + return Any; }; -jasmine.Env.prototype.describe = function(description, specDefinitions) { - var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); +getJasmineRequireObj().CallTracker = function() { - var parentSuite = this.currentSuite; - if (parentSuite) { - parentSuite.add(suite); - } else { - this.currentRunner_.add(suite); - } + function CallTracker() { + var calls = []; - this.currentSuite = suite; + this.track = function(context) { + calls.push(context); + }; - var declarationError = null; - try { - specDefinitions.call(suite); - } catch(e) { - declarationError = e; - } + this.any = function() { + return !!calls.length; + }; - if (declarationError) { - this.it("encountered a declaration exception", function() { - throw declarationError; - }); - } + this.count = function() { + return calls.length; + }; - this.currentSuite = parentSuite; + this.argsFor = function(index) { + var call = calls[index]; + return call ? call.args : []; + }; - return suite; -}; + this.all = function() { + return calls; + }; -jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { - if (this.currentSuite) { - this.currentSuite.beforeEach(beforeEachFunction); - } else { - this.currentRunner_.beforeEach(beforeEachFunction); - } -}; + this.allArgs = function() { + var callArgs = []; + for(var i = 0; i < calls.length; i++){ + callArgs.push(calls[i].args); + } -jasmine.Env.prototype.currentRunner = function () { - return this.currentRunner_; -}; + return callArgs; + }; -jasmine.Env.prototype.afterEach = function(afterEachFunction) { - if (this.currentSuite) { - this.currentSuite.afterEach(afterEachFunction); - } else { - this.currentRunner_.afterEach(afterEachFunction); + this.first = function() { + return calls[0]; + }; + + this.mostRecent = function() { + return calls[calls.length - 1]; + }; + + this.reset = function() { + calls = []; + }; } + return CallTracker; }; -jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { - return { - execute: function() { +getJasmineRequireObj().Clock = function() { + function Clock(global, delayedFunctionScheduler, mockDate) { + var self = this, + realTimingFunctions = { + setTimeout: global.setTimeout, + clearTimeout: global.clearTimeout, + setInterval: global.setInterval, + clearInterval: global.clearInterval + }, + fakeTimingFunctions = { + setTimeout: setTimeout, + clearTimeout: clearTimeout, + setInterval: setInterval, + clearInterval: clearInterval + }, + installed = false, + timer; + + + self.install = function() { + replace(global, fakeTimingFunctions); + timer = fakeTimingFunctions; + installed = true; + + return self; + }; + + self.uninstall = function() { + delayedFunctionScheduler.reset(); + mockDate.uninstall(); + replace(global, realTimingFunctions); + + timer = realTimingFunctions; + installed = false; + }; + + self.mockDate = function(initialDate) { + mockDate.install(initialDate); + }; + + self.setTimeout = function(fn, delay, params) { + if (legacyIE()) { + if (arguments.length > 2) { + throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill'); + } + return timer.setTimeout(fn, delay); + } + return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]); + }; + + self.setInterval = function(fn, delay, params) { + if (legacyIE()) { + if (arguments.length > 2) { + throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill'); + } + return timer.setInterval(fn, delay); + } + return Function.prototype.apply.apply(timer.setInterval, [global, arguments]); + }; + + self.clearTimeout = function(id) { + return Function.prototype.call.apply(timer.clearTimeout, [global, id]); + }; + + self.clearInterval = function(id) { + return Function.prototype.call.apply(timer.clearInterval, [global, id]); + }; + + self.tick = function(millis) { + if (installed) { + mockDate.tick(millis); + delayedFunctionScheduler.tick(millis); + } else { + throw new Error('Mock clock is not installed, use jasmine.clock().install()'); + } + }; + + return self; + + function legacyIE() { + //if these methods are polyfilled, apply will be present + return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply; + } + + function replace(dest, source) { + for (var prop in source) { + dest[prop] = source[prop]; + } + } + + function setTimeout(fn, delay) { + return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2)); + } + + function clearTimeout(id) { + return delayedFunctionScheduler.removeFunctionWithId(id); } - }; -}; -jasmine.Env.prototype.it = function(description, func) { - var spec = new jasmine.Spec(this, this.currentSuite, description); - this.currentSuite.add(spec); - this.currentSpec = spec; + function setInterval(fn, interval) { + return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true); + } + + function clearInterval(id) { + return delayedFunctionScheduler.removeFunctionWithId(id); + } - if (func) { - spec.runs(func); + function argSlice(argsObj, n) { + return Array.prototype.slice.call(argsObj, 2); + } } - return spec; + return Clock; }; -jasmine.Env.prototype.xit = function(desc, func) { - return { - id: this.nextSpecId(), - runs: function() { +getJasmineRequireObj().DelayedFunctionScheduler = function() { + function DelayedFunctionScheduler() { + var self = this; + var scheduledLookup = []; + var scheduledFunctions = {}; + var currentTime = 0; + var delayedFnCount = 0; + + self.tick = function(millis) { + millis = millis || 0; + var endTime = currentTime + millis; + + runScheduledFunctions(endTime); + currentTime = endTime; + }; + + self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) { + var f; + if (typeof(funcToCall) === 'string') { + /* jshint evil: true */ + f = function() { return eval(funcToCall); }; + /* jshint evil: false */ + } else { + f = funcToCall; + } + + millis = millis || 0; + timeoutKey = timeoutKey || ++delayedFnCount; + runAtMillis = runAtMillis || (currentTime + millis); + + var funcToSchedule = { + runAtMillis: runAtMillis, + funcToCall: f, + recurring: recurring, + params: params, + timeoutKey: timeoutKey, + millis: millis + }; + + if (runAtMillis in scheduledFunctions) { + scheduledFunctions[runAtMillis].push(funcToSchedule); + } else { + scheduledFunctions[runAtMillis] = [funcToSchedule]; + scheduledLookup.push(runAtMillis); + scheduledLookup.sort(function (a, b) { + return a - b; + }); + } + + return timeoutKey; + }; + + self.removeFunctionWithId = function(timeoutKey) { + for (var runAtMillis in scheduledFunctions) { + var funcs = scheduledFunctions[runAtMillis]; + var i = indexOfFirstToPass(funcs, function (func) { + return func.timeoutKey === timeoutKey; + }); + + if (i > -1) { + if (funcs.length === 1) { + delete scheduledFunctions[runAtMillis]; + deleteFromLookup(runAtMillis); + } else { + funcs.splice(i, 1); + } + + // intervals get rescheduled when executed, so there's never more + // than a single scheduled function with a given timeoutKey + break; + } + } + }; + + self.reset = function() { + currentTime = 0; + scheduledLookup = []; + scheduledFunctions = {}; + delayedFnCount = 0; + }; + + return self; + + function indexOfFirstToPass(array, testFn) { + var index = -1; + + for (var i = 0; i < array.length; ++i) { + if (testFn(array[i])) { + index = i; + break; + } + } + + return index; + } + + function deleteFromLookup(key) { + var value = Number(key); + var i = indexOfFirstToPass(scheduledLookup, function (millis) { + return millis === value; + }); + + if (i > -1) { + scheduledLookup.splice(i, 1); + } + } + + function reschedule(scheduledFn) { + self.scheduleFunction(scheduledFn.funcToCall, + scheduledFn.millis, + scheduledFn.params, + true, + scheduledFn.timeoutKey, + scheduledFn.runAtMillis + scheduledFn.millis); } - }; -}; -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 + "/"); + function runScheduledFunctions(endTime) { + if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) { + return; + } - if (a.ignoreCase != b.ignoreCase) - mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier"); + do { + currentTime = scheduledLookup.shift(); - if (a.global != b.global) - mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier"); + var funcsToRun = scheduledFunctions[currentTime]; + delete scheduledFunctions[currentTime]; - if (a.multiline != b.multiline) - mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier"); + for (var i = 0; i < funcsToRun.length; ++i) { + var funcToRun = funcsToRun[i]; + funcToRun.funcToCall.apply(null, funcToRun.params || []); - if (a.sticky != b.sticky) - mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier"); + if (funcToRun.recurring) { + reschedule(funcToRun); + } + } + } while (scheduledLookup.length > 0 && + // checking first if we're out of time prevents setTimeout(0) + // scheduled in a funcToRun from forcing an extra iteration + currentTime !== endTime && + scheduledLookup[0] <= endTime); + } + } - return (mismatchValues.length === 0); + return DelayedFunctionScheduler; }; -jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { - if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { - return true; - } +getJasmineRequireObj().ExceptionFormatter = function() { + function ExceptionFormatter() { + this.message = function(error) { + var message = ''; - a.__Jasmine_been_here_before__ = b; - b.__Jasmine_been_here_before__ = a; + if (error.name && error.message) { + message += error.name + ': ' + error.message; + } else { + message += error.toString() + ' thrown'; + } - var hasKey = function(obj, keyName) { - return obj !== null && obj[keyName] !== jasmine.undefined; - }; + if (error.fileName || error.sourceURL) { + message += ' in ' + (error.fileName || error.sourceURL); + } - for (var property in b) { - if (!hasKey(a, property) && hasKey(b, property)) { - mismatchKeys.push("expected has key '" + property + "', but missing from actual."); - } - } - for (property in a) { - if (!hasKey(b, property) && hasKey(a, property)) { - mismatchKeys.push("expected missing key '" + property + "', but present in actual."); - } - } - for (property in b) { - if (property == '__Jasmine_been_here_before__') continue; - if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { - mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); - } - } + if (error.line || error.lineNumber) { + message += ' (line ' + (error.line || error.lineNumber) + ')'; + } + + return message; + }; - if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { - mismatchValues.push("arrays were not the same length"); + this.stack = function(error) { + return error ? error.stack : null; + }; } - delete a.__Jasmine_been_here_before__; - delete b.__Jasmine_been_here_before__; - return (mismatchKeys.length === 0 && mismatchValues.length === 0); + return ExceptionFormatter; }; -jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { - mismatchKeys = mismatchKeys || []; - mismatchValues = mismatchValues || []; +getJasmineRequireObj().Expectation = function() { - for (var i = 0; i < this.equalityTesters_.length; i++) { - var equalityTester = this.equalityTesters_[i]; - var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); - if (result !== jasmine.undefined) return result; - } + var matchers = {}; - if (a === b) return true; + function Expectation(options) { + this.util = options.util || { buildFailureMessage: function() {} }; + this.customEqualityTesters = options.customEqualityTesters || []; + this.actual = options.actual; + this.addExpectationResult = options.addExpectationResult || function(){}; + this.isNot = options.isNot; - if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { - return (a == jasmine.undefined && b == jasmine.undefined); + for (var matcherName in matchers) { + this[matcherName] = matchers[matcherName]; + } } - if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { - return a === b; - } + Expectation.prototype.wrapCompare = function(name, matcherFactory) { + return function() { + var args = Array.prototype.slice.call(arguments, 0), + expected = args.slice(0), + message = ''; - if (a instanceof Date && b instanceof Date) { - return a.getTime() == b.getTime(); - } + args.unshift(this.actual); - if (a.jasmineMatches) { - return a.jasmineMatches(b); - } + var matcher = matcherFactory(this.util, this.customEqualityTesters), + matcherCompare = matcher.compare; - if (b.jasmineMatches) { - return b.jasmineMatches(a); - } + function defaultNegativeCompare() { + var result = matcher.compare.apply(null, args); + result.pass = !result.pass; + return result; + } - if (a instanceof jasmine.Matchers.ObjectContaining) { - return a.matches(b); - } + if (this.isNot) { + matcherCompare = matcher.negativeCompare || defaultNegativeCompare; + } - if (b instanceof jasmine.Matchers.ObjectContaining) { - return b.matches(a); - } + var result = matcherCompare.apply(null, args); - if (jasmine.isString_(a) && jasmine.isString_(b)) { - return (a == b); - } + if (!result.pass) { + if (!result.message) { + args.unshift(this.isNot); + args.unshift(name); + message = this.util.buildFailureMessage.apply(null, args); + } else { + if (Object.prototype.toString.apply(result.message) === '[object Function]') { + message = result.message(); + } else { + message = result.message; + } + } + } - if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { - return (a == b); - } + if (expected.length == 1) { + expected = expected[0]; + } - if (a instanceof RegExp && b instanceof RegExp) { - return this.compareRegExps_(a, b, mismatchKeys, mismatchValues); - } + // TODO: how many of these params are needed? + this.addExpectationResult( + result.pass, + { + matcherName: name, + passed: result.pass, + message: message, + actual: this.actual, + expected: expected // TODO: this may need to be arrayified/sliced + } + ); + }; + }; - if (typeof a === "object" && typeof b === "object") { - return this.compareObjects_(a, b, mismatchKeys, mismatchValues); - } + Expectation.addCoreMatchers = function(matchers) { + var prototype = Expectation.prototype; + for (var matcherName in matchers) { + var matcher = matchers[matcherName]; + prototype[matcherName] = prototype.wrapCompare(matcherName, matcher); + } + }; - //Straight check - return (a === b); -}; + Expectation.addMatchers = function(matchersToAdd) { + for (var name in matchersToAdd) { + var matcher = matchersToAdd[name]; + matchers[name] = Expectation.prototype.wrapCompare(name, matcher); + } + }; -jasmine.Env.prototype.contains_ = function(haystack, needle) { - if (jasmine.isArray_(haystack)) { - for (var i = 0; i < haystack.length; i++) { - if (this.equals_(haystack[i], needle)) return true; + Expectation.resetMatchers = function() { + for (var name in matchers) { + delete matchers[name]; } - return false; - } - return haystack.indexOf(needle) >= 0; -}; + }; -jasmine.Env.prototype.addEqualityTester = function(equalityTester) { - this.equalityTesters_.push(equalityTester); -}; -/** No-op base class for Jasmine reporters. - * - * @constructor - */ -jasmine.Reporter = function() { -}; + Expectation.Factory = function(options) { + options = options || {}; -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { -}; + var expect = new Expectation(options); -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportRunnerResults = function(runner) { -}; + // TODO: this would be nice as its own Object - NegativeExpectation + // TODO: copy instead of mutate options + options.isNot = true; + expect.not = new Expectation(options); -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSuiteResults = function(suite) { -}; + return expect; + }; -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSpecStarting = function(spec) { + return Expectation; }; -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSpecResults = function(spec) { -}; +//TODO: expectation result may make more sense as a presentation of an expectation. +getJasmineRequireObj().buildExpectationResult = function() { + function buildExpectationResult(options) { + var messageFormatter = options.messageFormatter || function() {}, + stackFormatter = options.stackFormatter || function() {}; -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.log = function(str) { -}; + return { + matcherName: options.matcherName, + expected: options.expected, + actual: options.actual, + message: message(), + stack: stack(), + passed: options.passed + }; -/** - * Blocks are functions with executable code that make up a spec. - * - * @constructor - * @param {jasmine.Env} env - * @param {Function} func - * @param {jasmine.Spec} spec - */ -jasmine.Block = function(env, func, spec) { - this.env = env; - this.func = func; - this.spec = spec; -}; + function message() { + if (options.passed) { + return 'Passed.'; + } else if (options.message) { + return options.message; + } else if (options.error) { + return messageFormatter(options.error); + } + return ''; + } -jasmine.Block.prototype.execute = function(onComplete) { - if (!jasmine.CATCH_EXCEPTIONS) { - this.func.apply(this.spec); - } - else { - try { - this.func.apply(this.spec); - } catch (e) { - this.spec.fail(e); + function stack() { + if (options.passed) { + return ''; + } + + var error = options.error; + if (!error) { + try { + throw new Error(message()); + } catch (e) { + error = e; + } + } + return stackFormatter(error); } } - onComplete(); -}; -/** JavaScript API reporter. - * - * @constructor - */ -jasmine.JsApiReporter = function() { - this.started = false; - this.finished = false; - this.suites_ = []; - this.results_ = {}; -}; -jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { - this.started = true; - var suites = runner.topLevelSuites(); - for (var i = 0; i < suites.length; i++) { - var suite = suites[i]; - this.suites_.push(this.summarize_(suite)); - } + return buildExpectationResult; }; -jasmine.JsApiReporter.prototype.suites = function() { - return this.suites_; -}; +getJasmineRequireObj().MockDate = function() { + function MockDate(global) { + var self = this; + var currentTime = 0; -jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { - var isSuite = suiteOrSpec instanceof jasmine.Suite; - var summary = { - id: suiteOrSpec.id, - name: suiteOrSpec.description, - type: isSuite ? 'suite' : 'spec', - children: [] - }; - - if (isSuite) { - var children = suiteOrSpec.children(); - for (var i = 0; i < children.length; i++) { - summary.children.push(this.summarize_(children[i])); + if (!global || !global.Date) { + self.install = function() {}; + self.tick = function() {}; + self.uninstall = function() {}; + return self; } - } - return summary; -}; -jasmine.JsApiReporter.prototype.results = function() { - return this.results_; -}; + var GlobalDate = global.Date; -jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { - return this.results_[specId]; -}; + self.install = function(mockDate) { + if (mockDate instanceof GlobalDate) { + currentTime = mockDate.getTime(); + } else { + currentTime = new GlobalDate().getTime(); + } -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { - this.finished = true; -}; + global.Date = FakeDate; + }; -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { -}; + self.tick = function(millis) { + millis = millis || 0; + currentTime = currentTime + millis; + }; -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { - this.results_[spec.id] = { - messages: spec.results().getItems(), - result: spec.results().failedCount > 0 ? "failed" : "passed" - }; -}; + self.uninstall = function() { + currentTime = 0; + global.Date = GlobalDate; + }; -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.log = function(str) { -}; + createDateProperties(); -jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ - var results = {}; - for (var i = 0; i < specIds.length; i++) { - var specId = specIds[i]; - results[specId] = this.summarizeResult_(this.results_[specId]); - } - return results; -}; + return self; -jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ - var summaryMessages = []; - var messagesLength = result.messages.length; - for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { - var resultMessage = result.messages[messageIndex]; - summaryMessages.push({ - text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, - passed: resultMessage.passed ? resultMessage.passed() : true, - type: resultMessage.type, - message: resultMessage.message, - trace: { - stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined + function FakeDate() { + if (arguments.length === 0) { + return new GlobalDate(currentTime); + } else { + return new GlobalDate(arguments[0], arguments[1], arguments[2], + arguments[3], arguments[4], arguments[5], arguments[6]); } - }); - } + } - return { - result : result.result, - messages : summaryMessages - }; -}; + function createDateProperties() { -/** - * @constructor - * @param {jasmine.Env} env - * @param actual - * @param {jasmine.Spec} spec - */ -jasmine.Matchers = function(env, actual, spec, opt_isNot) { - this.env = env; - this.actual = actual; - this.spec = spec; - this.isNot = opt_isNot || false; - this.reportWasCalled_ = false; -}; + FakeDate.now = function() { + if (GlobalDate.now) { + return currentTime; + } else { + throw new Error('Browser does not support Date.now()'); + } + }; -// todo: @deprecated as of Jasmine 0.11, remove soon [xw] -jasmine.Matchers.pp = function(str) { - throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); -}; + FakeDate.toSource = GlobalDate.toSource; + FakeDate.toString = GlobalDate.toString; + FakeDate.parse = GlobalDate.parse; + FakeDate.UTC = GlobalDate.UTC; + } + } -// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] -jasmine.Matchers.prototype.report = function(result, failing_message, details) { - throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); + return MockDate; }; -jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { - for (var methodName in prototype) { - if (methodName == 'report') continue; - var orig = prototype[methodName]; - matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); +getJasmineRequireObj().ObjectContaining = function(j$) { + + function ObjectContaining(sample) { + this.sample = sample; } -}; -jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { - return function() { - var matcherArgs = jasmine.util.argsToArray(arguments); - var result = matcherFunction.apply(this, arguments); + ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) { + if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); } - if (this.isNot) { - result = !result; - } + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; - if (this.reportWasCalled_) return result; + var hasKey = function(obj, keyName) { + return obj !== null && !j$.util.isUndefined(obj[keyName]); + }; - var message; - if (!result) { - if (this.message) { - message = this.message.apply(this, arguments); - if (jasmine.isArray_(message)) { - message = message[this.isNot ? 1 : 0]; - } - } else { - var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); - message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; - if (matcherArgs.length > 0) { - for (var i = 0; i < matcherArgs.length; i++) { - if (i > 0) message += ","; - message += " " + jasmine.pp(matcherArgs[i]); - } - } - message += "."; + for (var property in this.sample) { + if (!hasKey(other, property) && hasKey(this.sample, property)) { + mismatchKeys.push('expected has key \'' + property + '\', but missing from actual.'); + } + else if (!j$.matchersUtil.equals(other[property], this.sample[property])) { + mismatchValues.push('\'' + property + '\' was \'' + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + '\' in actual, but was \'' + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + '\' in expected.'); } } - var expectationResult = new jasmine.ExpectationResult({ - matcherName: matcherName, - passed: result, - expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], - actual: this.actual, - message: message - }); - this.spec.addMatcherResult(expectationResult); - return jasmine.undefined; - }; -}; - + return (mismatchKeys.length === 0 && mismatchValues.length === 0); + }; + ObjectContaining.prototype.jasmineToString = function() { + return ''; + }; -/** - * toBe: compares the actual to the expected using === - * @param expected - */ -jasmine.Matchers.prototype.toBe = function(expected) { - return this.actual === expected; + return ObjectContaining; }; -/** - * toNotBe: compares the actual to the expected using !== - * @param expected - * @deprecated as of 1.0. Use not.toBe() instead. - */ -jasmine.Matchers.prototype.toNotBe = function(expected) { - return this.actual !== expected; -}; +getJasmineRequireObj().pp = function(j$) { -/** - * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. - * - * @param expected - */ -jasmine.Matchers.prototype.toEqual = function(expected) { - return this.env.equals_(this.actual, expected); -}; + function PrettyPrinter() { + this.ppNestLevel_ = 0; + this.seen = []; + } -/** - * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual - * @param expected - * @deprecated as of 1.0. Use not.toEqual() instead. - */ -jasmine.Matchers.prototype.toNotEqual = function(expected) { - return !this.env.equals_(this.actual, expected); -}; + PrettyPrinter.prototype.format = function(value) { + this.ppNestLevel_++; + try { + if (j$.util.isUndefined(value)) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === 0 && 1/value === -Infinity) { + this.emitScalar('-0'); + } else if (value === j$.getGlobal()) { + this.emitScalar(''); + } else if (value.jasmineToString) { + this.emitScalar(value.jasmineToString()); + } else if (typeof value === 'string') { + this.emitString(value); + } else if (j$.isSpy(value)) { + this.emitScalar('spy on ' + value.and.identity()); + } else if (value instanceof RegExp) { + this.emitScalar(value.toString()); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (j$.util.arrayContains(this.seen, value)) { + this.emitScalar(''); + } else if (j$.isArray_(value) || j$.isA_('Object', value)) { + this.seen.push(value); + if (j$.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + this.seen.pop(); + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } + }; -/** - * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes - * a pattern or a String. - * - * @param expected - */ -jasmine.Matchers.prototype.toMatch = function(expected) { - return new RegExp(expected).test(this.actual); -}; + PrettyPrinter.prototype.iterateObject = function(obj, fn) { + for (var property in obj) { + if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; } + fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && + obj.__lookupGetter__(property) !== null) : false); + } + }; -/** - * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch - * @param expected - * @deprecated as of 1.0. Use not.toMatch() instead. - */ -jasmine.Matchers.prototype.toNotMatch = function(expected) { - return !(new RegExp(expected).test(this.actual)); -}; + PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitString = j$.unimplementedMethod_; -/** - * Matcher that compares the actual to jasmine.undefined. - */ -jasmine.Matchers.prototype.toBeDefined = function() { - return (this.actual !== jasmine.undefined); -}; + function StringPrettyPrinter() { + PrettyPrinter.call(this); -/** - * Matcher that compares the actual to jasmine.undefined. - */ -jasmine.Matchers.prototype.toBeUndefined = function() { - return (this.actual === jasmine.undefined); -}; + this.string = ''; + } -/** - * Matcher that compares the actual to null. - */ -jasmine.Matchers.prototype.toBeNull = function() { - return (this.actual === null); -}; + j$.util.inherit(StringPrettyPrinter, PrettyPrinter); -/** - * Matcher that compares the actual to NaN. - */ -jasmine.Matchers.prototype.toBeNaN = function() { - this.message = function() { - return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ]; - }; + StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); + }; - return (this.actual !== this.actual); -}; + StringPrettyPrinter.prototype.emitString = function(value) { + this.append('\'' + value + '\''); + }; -/** - * Matcher that boolean not-nots the actual. - */ -jasmine.Matchers.prototype.toBeTruthy = function() { - return !!this.actual; -}; + StringPrettyPrinter.prototype.emitArray = function(array) { + if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { + this.append('Array'); + return; + } + var length = Math.min(array.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); + this.append('[ '); + for (var i = 0; i < length; i++) { + if (i > 0) { + this.append(', '); + } + this.format(array[i]); + } + if(array.length > length){ + this.append(', ...'); + } + this.append(' ]'); + }; + StringPrettyPrinter.prototype.emitObject = function(obj) { + if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { + this.append('Object'); + return; + } -/** - * Matcher that boolean nots the actual. - */ -jasmine.Matchers.prototype.toBeFalsy = function() { - return !this.actual; -}; + var self = this; + this.append('{ '); + var first = true; + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } -/** - * Matcher that checks to see if the actual, a Jasmine spy, was called. - */ -jasmine.Matchers.prototype.toHaveBeenCalled = function() { - if (arguments.length > 0) { - throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); - } + self.append(property); + self.append(': '); + if (isGetter) { + self.append(''); + } else { + self.format(obj[property]); + } + }); - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } + this.append(' }'); + }; - this.message = function() { - return [ - "Expected spy " + this.actual.identity + " to have been called.", - "Expected spy " + this.actual.identity + " not to have been called." - ]; + StringPrettyPrinter.prototype.append = function(value) { + this.string += value; }; - return this.actual.wasCalled; + return function(value) { + var stringPrettyPrinter = new StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; + }; }; -/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ -jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was not called. - * - * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead - */ -jasmine.Matchers.prototype.wasNotCalled = function() { - if (arguments.length > 0) { - throw new Error('wasNotCalled does not take arguments'); +getJasmineRequireObj().QueueRunner = function(j$) { + + function once(fn) { + var called = false; + return function() { + if (!called) { + called = true; + fn(); + } + }; } - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + function QueueRunner(attrs) { + this.fns = attrs.fns || []; + this.onComplete = attrs.onComplete || function() {}; + this.clearStack = attrs.clearStack || function(fn) {fn();}; + this.onException = attrs.onException || function() {}; + this.catchException = attrs.catchException || function() { return true; }; + this.enforceTimeout = attrs.enforceTimeout || function() { return false; }; + this.userContext = {}; + this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; } - this.message = function() { - return [ - "Expected spy " + this.actual.identity + " to not have been called.", - "Expected spy " + this.actual.identity + " to have been called." - ]; + QueueRunner.prototype.execute = function() { + this.run(this.fns, 0); }; - return !this.actual.wasCalled; -}; + QueueRunner.prototype.run = function(fns, recursiveIndex) { + var length = fns.length, + self = this, + iterativeIndex; -/** - * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. - * - * @example - * - */ -jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { - var expectedArgs = jasmine.util.argsToArray(arguments); - if (!jasmine.isSpy(this.actual)) { - 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) { - positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called."; - } else { - 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, '') + for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) { + var fn = fns[iterativeIndex]; + if (fn.length > 0) { + return attemptAsync(fn); + } else { + attemptSync(fn); + } } - return [positiveMessage, invertedMessage]; - }; - return this.env.contains_(this.actual.argsForCall, expectedArgs); -}; + var runnerDone = iterativeIndex >= length; -/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ -jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; + if (runnerDone) { + this.clearStack(this.onComplete); + } -/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ -jasmine.Matchers.prototype.wasNotCalledWith = function() { - var expectedArgs = jasmine.util.argsToArray(arguments); - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } + function attemptSync(fn) { + try { + fn.call(self.userContext); + } catch (e) { + handleException(e); + } + } - this.message = 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" - ]; - }; + function attemptAsync(fn) { + var clearTimeout = function () { + Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeoutId]]); + }, + next = once(function () { + clearTimeout(timeoutId); + self.run(fns, iterativeIndex + 1); + }), + timeoutId; + + if (self.enforceTimeout()) { + timeoutId = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() { + self.onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.')); + next(); + }, j$.DEFAULT_TIMEOUT_INTERVAL]]); + } - return !this.env.contains_(this.actual.argsForCall, expectedArgs); -}; + try { + fn.call(self.userContext, next); + } catch (e) { + handleException(e); + next(); + } + } -/** - * Matcher that checks that the expected item is an element in the actual Array. - * - * @param {Object} expected - */ -jasmine.Matchers.prototype.toContain = function(expected) { - return this.env.contains_(this.actual, expected); -}; + function handleException(e) { + self.onException(e); + if (!self.catchException(e)) { + //TODO: set a var when we catch an exception and + //use a finally block to close the loop in a nice way.. + throw e; + } + } + }; -/** - * Matcher that checks that the expected item is NOT an element in the actual Array. - * - * @param {Object} expected - * @deprecated as of 1.0. Use not.toContain() instead. - */ -jasmine.Matchers.prototype.toNotContain = function(expected) { - return !this.env.contains_(this.actual, expected); + return QueueRunner; }; -jasmine.Matchers.prototype.toBeLessThan = function(expected) { - return this.actual < expected; -}; +getJasmineRequireObj().ReportDispatcher = function() { + function ReportDispatcher(methods) { -jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { - return this.actual > expected; -}; + var dispatchedMethods = methods || []; -/** - * Matcher that checks that the expected item is equal to the actual item - * up to a given level of decimal precision (default 2). - * - * @param {Number} expected - * @param {Number} precision, as number of decimal places - */ -jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { - if (!(precision === 0)) { - precision = precision || 2; - } - return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2); -}; + for (var i = 0; i < dispatchedMethods.length; i++) { + var method = dispatchedMethods[i]; + this[method] = (function(m) { + return function() { + dispatch(m, arguments); + }; + }(method)); + } -/** - * Matcher that checks that the expected exception was thrown by the actual. - * - * @param {String} [expected] - */ -jasmine.Matchers.prototype.toThrow = function(expected) { - var result = false; - var exception; - if (typeof this.actual != 'function') { - throw new Error('Actual is not a function'); - } - try { - this.actual(); - } catch (e) { - exception = e; - } - if (exception) { - result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); - } + var reporters = []; - var not = this.isNot ? "not " : ""; + this.addReporter = function(reporter) { + reporters.push(reporter); + }; - 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(' '); - } else { - return "Expected function to throw an exception."; - } - }; + return this; - return result; -}; + function dispatch(method, args) { + for (var i = 0; i < reporters.length; i++) { + var reporter = reporters[i]; + if (reporter[method]) { + reporter[method].apply(reporter, args); + } + } + } + } -jasmine.Matchers.Any = function(expectedClass) { - this.expectedClass = expectedClass; + return ReportDispatcher; }; -jasmine.Matchers.Any.prototype.jasmineMatches = function(other) { - if (this.expectedClass == String) { - return typeof other == 'string' || other instanceof String; - } - if (this.expectedClass == Number) { - return typeof other == 'number' || other instanceof Number; - } +getJasmineRequireObj().SpyStrategy = function() { - if (this.expectedClass == Function) { - return typeof other == 'function' || other instanceof Function; - } + function SpyStrategy(options) { + options = options || {}; - if (this.expectedClass == Object) { - return typeof other == 'object'; - } + var identity = options.name || 'unknown', + originalFn = options.fn || function() {}, + getSpy = options.getSpy || function() {}, + plan = function() {}; - return other instanceof this.expectedClass; -}; + this.identity = function() { + return identity; + }; -jasmine.Matchers.Any.prototype.jasmineToString = function() { - return ''; -}; + this.exec = function() { + return plan.apply(this, arguments); + }; -jasmine.Matchers.ObjectContaining = function (sample) { - this.sample = sample; -}; + this.callThrough = function() { + plan = originalFn; + return getSpy(); + }; -jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) { - mismatchKeys = mismatchKeys || []; - mismatchValues = mismatchValues || []; + this.returnValue = function(value) { + plan = function() { + return value; + }; + return getSpy(); + }; - var env = jasmine.getEnv(); + this.throwError = function(something) { + var error = (something instanceof Error) ? something : new Error(something); + plan = function() { + throw error; + }; + return getSpy(); + }; - var hasKey = function(obj, keyName) { - return obj != null && obj[keyName] !== jasmine.undefined; - }; + this.callFake = function(fn) { + plan = fn; + return getSpy(); + }; - for (var property in this.sample) { - if (!hasKey(other, property) && hasKey(this.sample, property)) { - mismatchKeys.push("expected has key '" + property + "', but missing from actual."); - } - else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) { - mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual."); - } + this.stub = function(fn) { + plan = function() {}; + return getSpy(); + }; } - return (mismatchKeys.length === 0 && mismatchValues.length === 0); + return SpyStrategy; }; -jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () { - return ""; -}; -// Mock setTimeout, clearTimeout -// Contributed by Pivotal Computer Systems, www.pivotalsf.com +getJasmineRequireObj().Suite = function() { + function Suite(attrs) { + this.env = attrs.env; + this.id = attrs.id; + this.parentSuite = attrs.parentSuite; + this.description = attrs.description; + this.onStart = attrs.onStart || function() {}; + this.resultCallback = attrs.resultCallback || function() {}; + this.clearStack = attrs.clearStack || function(fn) {fn();}; -jasmine.FakeTimer = function() { - this.reset(); + this.beforeFns = []; + this.afterFns = []; + this.queueRunner = attrs.queueRunner || function() {}; + this.disabled = false; - var self = this; - self.setTimeout = function(funcToCall, millis) { - self.timeoutsMade++; - self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); - return self.timeoutsMade; - }; + this.children = []; - self.setInterval = function(funcToCall, millis) { - self.timeoutsMade++; - self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); - return self.timeoutsMade; - }; + this.result = { + id: this.id, + status: this.disabled ? 'disabled' : '', + description: this.description, + fullName: this.getFullName() + }; + } - self.clearTimeout = function(timeoutKey) { - self.scheduledFunctions[timeoutKey] = jasmine.undefined; + Suite.prototype.getFullName = function() { + var fullName = this.description; + for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + if (parentSuite.parentSuite) { + fullName = parentSuite.description + ' ' + fullName; + } + } + return fullName; }; - self.clearInterval = function(timeoutKey) { - self.scheduledFunctions[timeoutKey] = jasmine.undefined; + Suite.prototype.disable = function() { + this.disabled = true; }; -}; - -jasmine.FakeTimer.prototype.reset = function() { - this.timeoutsMade = 0; - this.scheduledFunctions = {}; - this.nowMillis = 0; -}; - -jasmine.FakeTimer.prototype.tick = function(millis) { - var oldMillis = this.nowMillis; - var newMillis = oldMillis + millis; - this.runFunctionsWithinRange(oldMillis, newMillis); - this.nowMillis = newMillis; -}; - -jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { - var scheduledFunc; - var funcsToRun = []; - for (var timeoutKey in this.scheduledFunctions) { - scheduledFunc = this.scheduledFunctions[timeoutKey]; - if (scheduledFunc != jasmine.undefined && - scheduledFunc.runAtMillis >= oldMillis && - scheduledFunc.runAtMillis <= nowMillis) { - funcsToRun.push(scheduledFunc); - this.scheduledFunctions[timeoutKey] = jasmine.undefined; - } - } + Suite.prototype.beforeEach = function(fn) { + this.beforeFns.unshift(fn); + }; - if (funcsToRun.length > 0) { - funcsToRun.sort(function(a, b) { - return a.runAtMillis - b.runAtMillis; - }); - for (var i = 0; i < funcsToRun.length; ++i) { - try { - var funcToRun = funcsToRun[i]; - this.nowMillis = funcToRun.runAtMillis; - funcToRun.funcToCall(); - if (funcToRun.recurring) { - this.scheduleFunction(funcToRun.timeoutKey, - funcToRun.funcToCall, - funcToRun.millis, - true); - } - } catch(e) { - } - } - this.runFunctionsWithinRange(oldMillis, nowMillis); - } -}; + Suite.prototype.afterEach = function(fn) { + this.afterFns.unshift(fn); + }; -jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { - this.scheduledFunctions[timeoutKey] = { - runAtMillis: this.nowMillis + millis, - funcToCall: funcToCall, - recurring: recurring, - timeoutKey: timeoutKey, - millis: millis + Suite.prototype.addChild = function(child) { + this.children.push(child); }; -}; -/** - * @namespace - */ -jasmine.Clock = { - defaultFakeTimer: new jasmine.FakeTimer(), + Suite.prototype.execute = function(onComplete) { + var self = this; + if (this.disabled) { + complete(); + return; + } + + var allFns = []; - reset: function() { - jasmine.Clock.assertInstalled(); - jasmine.Clock.defaultFakeTimer.reset(); - }, + for (var i = 0; i < this.children.length; i++) { + allFns.push(wrapChildAsAsync(this.children[i])); + } - tick: function(millis) { - jasmine.Clock.assertInstalled(); - jasmine.Clock.defaultFakeTimer.tick(millis); - }, + this.onStart(this); - runFunctionsWithinRange: function(oldMillis, nowMillis) { - jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); - }, + this.queueRunner({ + fns: allFns, + onComplete: complete + }); - scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { - jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); - }, + function complete() { + self.resultCallback(self.result); - useMock: function() { - if (!jasmine.Clock.isInstalled()) { - var spec = jasmine.getEnv().currentSpec; - spec.after(jasmine.Clock.uninstallMock); + if (onComplete) { + onComplete(); + } + } - jasmine.Clock.installMock(); + function wrapChildAsAsync(child) { + return function(done) { child.execute(done); }; } - }, + }; - installMock: function() { - jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; - }, + return Suite; +}; - uninstallMock: function() { - jasmine.Clock.assertInstalled(); - jasmine.Clock.installed = jasmine.Clock.real; - }, +if (typeof window == void 0 && typeof exports == 'object') { + exports.Suite = jasmineRequire.Suite; +} - real: { - setTimeout: jasmine.getGlobal().setTimeout, - clearTimeout: jasmine.getGlobal().clearTimeout, - setInterval: jasmine.getGlobal().setInterval, - clearInterval: jasmine.getGlobal().clearInterval - }, +getJasmineRequireObj().Timer = function() { + var defaultNow = (function(Date) { + return function() { return new Date().getTime(); }; + })(Date); - assertInstalled: function() { - if (!jasmine.Clock.isInstalled()) { - throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); - } - }, + function Timer(options) { + options = options || {}; - isInstalled: function() { - return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; - }, + var now = options.now || defaultNow, + startTime; - installed: null -}; -jasmine.Clock.installed = jasmine.Clock.real; + this.start = function() { + startTime = now(); + }; -//else for IE support -jasmine.getGlobal().setTimeout = function(funcToCall, millis) { - if (jasmine.Clock.installed.setTimeout.apply) { - return jasmine.Clock.installed.setTimeout.apply(this, arguments); - } else { - return jasmine.Clock.installed.setTimeout(funcToCall, millis); + this.elapsed = function() { + return now() - startTime; + }; } -}; -jasmine.getGlobal().setInterval = function(funcToCall, millis) { - if (jasmine.Clock.installed.setInterval.apply) { - return jasmine.Clock.installed.setInterval.apply(this, arguments); - } else { - return jasmine.Clock.installed.setInterval(funcToCall, millis); - } + return Timer; }; -jasmine.getGlobal().clearTimeout = function(timeoutKey) { - if (jasmine.Clock.installed.clearTimeout.apply) { - return jasmine.Clock.installed.clearTimeout.apply(this, arguments); - } else { - return jasmine.Clock.installed.clearTimeout(timeoutKey); - } -}; +getJasmineRequireObj().matchersUtil = function(j$) { + // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter? -jasmine.getGlobal().clearInterval = function(timeoutKey) { - if (jasmine.Clock.installed.clearTimeout.apply) { - return jasmine.Clock.installed.clearInterval.apply(this, arguments); - } else { - return jasmine.Clock.installed.clearInterval(timeoutKey); - } -}; + return { + equals: function(a, b, customTesters) { + customTesters = customTesters || []; -/** - * @constructor - */ -jasmine.MultiReporter = function() { - this.subReporters_ = []; -}; -jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); + return eq(a, b, [], [], customTesters); + }, -jasmine.MultiReporter.prototype.addReporter = function(reporter) { - this.subReporters_.push(reporter); -}; + contains: function(haystack, needle, customTesters) { + customTesters = customTesters || []; -(function() { - var functionNames = [ - "reportRunnerStarting", - "reportRunnerResults", - "reportSuiteResults", - "reportSpecStarting", - "reportSpecResults", - "log" - ]; - for (var i = 0; i < functionNames.length; i++) { - var functionName = functionNames[i]; - jasmine.MultiReporter.prototype[functionName] = (function(functionName) { - return function() { - for (var j = 0; j < this.subReporters_.length; j++) { - var subReporter = this.subReporters_[j]; - if (subReporter[functionName]) { - subReporter[functionName].apply(subReporter, arguments); + if (Object.prototype.toString.apply(haystack) === '[object Array]') { + for (var i = 0; i < haystack.length; i++) { + if (eq(haystack[i], needle, [], [], customTesters)) { + return true; } } - }; - })(functionName); - } -})(); -/** - * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults - * - * @constructor - */ -jasmine.NestedResults = function() { - /** - * The total count of results - */ - this.totalCount = 0; - /** - * Number of passed results - */ - this.passedCount = 0; - /** - * Number of failed results - */ - this.failedCount = 0; - /** - * Was this suite/spec skipped? - */ - this.skipped = false; - /** - * @ignore - */ - this.items_ = []; -}; - -/** - * Roll up the result counts. - * - * @param result - */ -jasmine.NestedResults.prototype.rollupCounts = function(result) { - this.totalCount += result.totalCount; - this.passedCount += result.passedCount; - this.failedCount += result.failedCount; -}; + return false; + } + return haystack.indexOf(needle) >= 0; + }, + + buildFailureMessage: function() { + var args = Array.prototype.slice.call(arguments, 0), + matcherName = args[0], + isNot = args[1], + actual = args[2], + expected = args.slice(3), + englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); + + var message = 'Expected ' + + j$.pp(actual) + + (isNot ? ' not ' : ' ') + + englishyPredicate; + + if (expected.length > 0) { + for (var i = 0; i < expected.length; i++) { + if (i > 0) { + message += ','; + } + message += ' ' + j$.pp(expected[i]); + } + } -/** - * Adds a log message. - * @param values Array of message parts which will be concatenated later. - */ -jasmine.NestedResults.prototype.log = function(values) { - this.items_.push(new jasmine.MessageResult(values)); -}; + return message + '.'; + } + }; -/** - * Getter for the results: message & results. - */ -jasmine.NestedResults.prototype.getItems = function() { - return this.items_; -}; + // Equality function lovingly adapted from isEqual in + // [Underscore](http://underscorejs.org) + function eq(a, b, aStack, bStack, customTesters) { + var result = true; -/** - * Adds a result, tracking counts (total, passed, & failed) - * @param {jasmine.ExpectationResult|jasmine.NestedResults} result - */ -jasmine.NestedResults.prototype.addResult = function(result) { - if (result.type != 'log') { - if (result.items_) { - this.rollupCounts(result); - } else { - this.totalCount++; - if (result.passed()) { - this.passedCount++; - } else { - this.failedCount++; + for (var i = 0; i < customTesters.length; i++) { + var customTesterResult = customTesters[i](a, b); + if (!j$.util.isUndefined(customTesterResult)) { + return customTesterResult; } } - } - this.items_.push(result); -}; - -/** - * @returns {Boolean} True if everything below passed - */ -jasmine.NestedResults.prototype.passed = function() { - return this.passedCount === this.totalCount; -}; -/** - * Base class for pretty printing for expectation results. - */ -jasmine.PrettyPrinter = function() { - this.ppNestLevel_ = 0; -}; -/** - * Formats a value in a nice, human-readable string. - * - * @param value - */ -jasmine.PrettyPrinter.prototype.format = function(value) { - this.ppNestLevel_++; - try { - if (value === jasmine.undefined) { - this.emitScalar('undefined'); - } else if (value === null) { - this.emitScalar('null'); - } else if (value === jasmine.getGlobal()) { - this.emitScalar(''); - } else if (value.jasmineToString) { - this.emitScalar(value.jasmineToString()); - } else if (typeof value === 'string') { - this.emitString(value); - } else if (jasmine.isSpy(value)) { - this.emitScalar("spy on " + value.identity); - } else if (value instanceof RegExp) { - this.emitScalar(value.toString()); - } else if (typeof value === 'function') { - this.emitScalar('Function'); - } else if (typeof value.nodeType === 'number') { - this.emitScalar('HTMLNode'); - } else if (value instanceof Date) { - this.emitScalar('Date(' + value + ')'); - } else if (value.__Jasmine_been_here_before__) { - this.emitScalar(''); - } else if (jasmine.isArray_(value) || typeof value == 'object') { - value.__Jasmine_been_here_before__ = true; - if (jasmine.isArray_(value)) { - this.emitArray(value); - } else { - this.emitObject(value); + if (a instanceof j$.Any) { + result = a.jasmineMatches(b); + if (result) { + return true; } - delete value.__Jasmine_been_here_before__; - } else { - this.emitScalar(value.toString()); } - } finally { - this.ppNestLevel_--; - } -}; - -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); - } -}; -jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; + if (b instanceof j$.Any) { + result = b.jasmineMatches(a); + if (result) { + return true; + } + } -jasmine.StringPrettyPrinter = function() { - jasmine.PrettyPrinter.call(this); + if (b instanceof j$.ObjectContaining) { + result = b.jasmineMatches(a); + if (result) { + return true; + } + } - this.string = ''; -}; -jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); + if (a instanceof Error && b instanceof Error) { + return a.message == b.message; + } -jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { - this.append(value); -}; + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) { return a !== 0 || 1 / a == 1 / b; } + // A strict comparison is necessary because `null == undefined`. + if (a === null || b === null) { return a === b; } + var className = Object.prototype.toString.call(a); + if (className != Object.prototype.toString.call(b)) { return false; } + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a === 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') { return false; } + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) { return bStack[length] == b; } + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) { break; } + } + } + } else { + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(isFunction(aCtor) && (aCtor instanceof aCtor) && + isFunction(bCtor) && (bCtor instanceof bCtor))) { + return false; + } + // Deep compare objects. + for (var key in a) { + if (has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) { break; } + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (has(b, key) && !(size--)) { break; } + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); -jasmine.StringPrettyPrinter.prototype.emitString = function(value) { - this.append("'" + value + "'"); -}; + return result; -jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { - if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) { - this.append("Array"); - return; - } + function has(obj, key) { + return obj.hasOwnProperty(key); + } - this.append('[ '); - for (var i = 0; i < array.length; i++) { - if (i > 0) { - this.append(', '); + function isFunction(obj) { + return typeof obj === 'function'; } - this.format(array[i]); } - this.append(' ]'); }; -jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { - if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) { - this.append("Object"); - return; +getJasmineRequireObj().toBe = function() { + function toBe() { + return { + compare: function(actual, expected) { + return { + pass: actual === expected + }; + } + }; } - var self = this; - this.append('{ '); - var first = true; - - this.iterateObject(obj, function(property, isGetter) { - if (first) { - first = false; - } else { - self.append(', '); - } - - self.append(property); - self.append(' : '); - if (isGetter) { - self.append(''); - } else { - self.format(obj[property]); - } - }); - - this.append(' }'); + return toBe; }; -jasmine.StringPrettyPrinter.prototype.append = function(value) { - this.string += 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; - this.offset = 0; - this.abort = false; -}; +getJasmineRequireObj().toBeCloseTo = function() { + + function toBeCloseTo() { + return { + compare: function(actual, expected, precision) { + if (precision !== 0) { + precision = precision || 2; + } -jasmine.Queue.prototype.addBefore = function(block, ensure) { - if (ensure === jasmine.undefined) { - ensure = false; + return { + pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2) + }; + } + }; } - this.blocks.unshift(block); - this.ensured.unshift(ensure); + return toBeCloseTo; }; -jasmine.Queue.prototype.add = function(block, ensure) { - if (ensure === jasmine.undefined) { - ensure = false; +getJasmineRequireObj().toBeDefined = function() { + function toBeDefined() { + return { + compare: function(actual) { + return { + pass: (void 0 !== actual) + }; + } + }; } - this.blocks.push(block); - this.ensured.push(ensure); + return toBeDefined; }; -jasmine.Queue.prototype.insertNext = function(block, ensure) { - if (ensure === jasmine.undefined) { - ensure = false; +getJasmineRequireObj().toBeFalsy = function() { + function toBeFalsy() { + return { + compare: function(actual) { + return { + pass: !!!actual + }; + } + }; } - this.ensured.splice((this.index + this.offset + 1), 0, ensure); - this.blocks.splice((this.index + this.offset + 1), 0, block); - this.offset++; + return toBeFalsy; }; -jasmine.Queue.prototype.start = function(onComplete) { - this.running = true; - this.onComplete = onComplete; - this.next_(); -}; +getJasmineRequireObj().toBeGreaterThan = function() { -jasmine.Queue.prototype.isRunning = function() { - return this.running; -}; + function toBeGreaterThan() { + return { + compare: function(actual, expected) { + return { + pass: actual > expected + }; + } + }; + } -jasmine.Queue.LOOP_DONT_RECURSE = true; + return toBeGreaterThan; +}; -jasmine.Queue.prototype.next_ = function() { - var self = this; - var goAgain = true; - while (goAgain) { - goAgain = false; - - if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) { - var calledSynchronously = true; - var completedSynchronously = false; +getJasmineRequireObj().toBeLessThan = function() { + function toBeLessThan() { + return { - var onComplete = function () { - if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { - completedSynchronously = true; - return; - } + compare: function(actual, expected) { + return { + pass: actual < expected + }; + } + }; + } - if (self.blocks[self.index].abort) { - self.abort = true; - } + return toBeLessThan; +}; +getJasmineRequireObj().toBeNaN = function(j$) { - self.offset = 0; - self.index++; + function toBeNaN() { + return { + compare: function(actual) { + var result = { + pass: (actual !== actual) + }; - var now = new Date().getTime(); - if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { - self.env.lastUpdate = now; - self.env.setTimeout(function() { - self.next_(); - }, 0); + if (result.pass) { + result.message = 'Expected actual not to be NaN.'; } else { - if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { - goAgain = true; - } else { - self.next_(); - } + result.message = function() { return 'Expected ' + j$.pp(actual) + ' to be NaN.'; }; } - }; - self.blocks[self.index].execute(onComplete); - calledSynchronously = false; - if (completedSynchronously) { - onComplete(); - } - - } else { - self.running = false; - if (self.onComplete) { - self.onComplete(); + return result; } - } + }; } -}; -jasmine.Queue.prototype.results = function() { - var results = new jasmine.NestedResults(); - for (var i = 0; i < this.blocks.length; i++) { - if (this.blocks[i].results) { - results.addResult(this.blocks[i].results()); - } - } - return results; + return toBeNaN; }; +getJasmineRequireObj().toBeNull = function() { -/** - * Runner - * - * @constructor - * @param {jasmine.Env} env - */ -jasmine.Runner = function(env) { - var self = this; - self.env = env; - self.queue = new jasmine.Queue(env); - self.before_ = []; - self.after_ = []; - self.suites_ = []; -}; - -jasmine.Runner.prototype.execute = function() { - var self = this; - if (self.env.reporter.reportRunnerStarting) { - self.env.reporter.reportRunnerStarting(this); + function toBeNull() { + return { + compare: function(actual) { + return { + pass: actual === null + }; + } + }; } - self.queue.start(function () { - self.finishCallback(); - }); -}; -jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { - beforeEachFunction.typeName = 'beforeEach'; - this.before_.splice(0,0,beforeEachFunction); + return toBeNull; }; -jasmine.Runner.prototype.afterEach = function(afterEachFunction) { - afterEachFunction.typeName = 'afterEach'; - this.after_.splice(0,0,afterEachFunction); -}; +getJasmineRequireObj().toBeTruthy = function() { + function toBeTruthy() { + return { + compare: function(actual) { + return { + pass: !!actual + }; + } + }; + } -jasmine.Runner.prototype.finishCallback = function() { - this.env.reporter.reportRunnerResults(this); + return toBeTruthy; }; -jasmine.Runner.prototype.addSuite = function(suite) { - this.suites_.push(suite); -}; +getJasmineRequireObj().toBeUndefined = function() { -jasmine.Runner.prototype.add = function(block) { - if (block instanceof jasmine.Suite) { - this.addSuite(block); + function toBeUndefined() { + return { + compare: function(actual) { + return { + pass: void 0 === actual + }; + } + }; } - this.queue.add(block); -}; -jasmine.Runner.prototype.specs = function () { - var suites = this.suites(); - var specs = []; - for (var i = 0; i < suites.length; i++) { - specs = specs.concat(suites[i].specs()); - } - return specs; + return toBeUndefined; }; -jasmine.Runner.prototype.suites = function() { - return this.suites_; -}; +getJasmineRequireObj().toContain = function() { + function toContain(util, customEqualityTesters) { + customEqualityTesters = customEqualityTesters || []; -jasmine.Runner.prototype.topLevelSuites = function() { - var topLevelSuites = []; - for (var i = 0; i < this.suites_.length; i++) { - if (!this.suites_[i].parentSuite) { - topLevelSuites.push(this.suites_[i]); - } - } - return topLevelSuites; -}; + return { + compare: function(actual, expected) { -jasmine.Runner.prototype.results = function() { - return this.queue.results(); -}; -/** - * Internal representation of a Jasmine specification, or test. - * - * @constructor - * @param {jasmine.Env} env - * @param {jasmine.Suite} suite - * @param {String} description - */ -jasmine.Spec = function(env, suite, description) { - if (!env) { - throw new Error('jasmine.Env() required'); - } - if (!suite) { - throw new Error('jasmine.Suite() required'); + return { + pass: util.contains(actual, expected, customEqualityTesters) + }; + } + }; } - var spec = this; - spec.id = env.nextSpecId ? env.nextSpecId() : null; - spec.env = env; - spec.suite = suite; - spec.description = description; - spec.queue = new jasmine.Queue(env); - - spec.afterCallbacks = []; - spec.spies_ = []; - - spec.results_ = new jasmine.NestedResults(); - spec.results_.description = description; - spec.matchersClass = null; -}; -jasmine.Spec.prototype.getFullName = function() { - return this.suite.getFullName() + ' ' + this.description + '.'; + return toContain; }; +getJasmineRequireObj().toEqual = function() { -jasmine.Spec.prototype.results = function() { - return this.results_; -}; + function toEqual(util, customEqualityTesters) { + customEqualityTesters = customEqualityTesters || []; -/** - * All parameters are pretty-printed and concatenated together, then written to the spec's output. - * - * Be careful not to leave calls to jasmine.log in production code. - */ -jasmine.Spec.prototype.log = function() { - return this.results_.log(arguments); -}; + return { + compare: function(actual, expected) { + var result = { + pass: false + }; -jasmine.Spec.prototype.runs = function (func) { - var block = new jasmine.Block(this.env, func, this); - this.addToQueue(block); - return this; -}; + result.pass = util.equals(actual, expected, customEqualityTesters); -jasmine.Spec.prototype.addToQueue = function (block) { - if (this.queue.isRunning()) { - this.queue.insertNext(block); - } else { - this.queue.add(block); + return result; + } + }; } -}; -/** - * @param {jasmine.ExpectationResult} result - */ -jasmine.Spec.prototype.addMatcherResult = function(result) { - this.results_.addResult(result); + return toEqual; }; -jasmine.Spec.prototype.expect = function(actual) { - var positive = new (this.getMatchersClass_())(this.env, actual, this); - positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); - return positive; -}; +getJasmineRequireObj().toHaveBeenCalled = function(j$) { -/** - * Waits a fixed time period before moving to the next block. - * - * @deprecated Use waitsFor() instead - * @param {Number} timeout milliseconds to wait - */ -jasmine.Spec.prototype.waits = function(timeout) { - var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); - this.addToQueue(waitsFunc); - return this; -}; + function toHaveBeenCalled() { + return { + compare: function(actual) { + var result = {}; -/** - * Waits for the latchFunction to return true before proceeding to the next block. - * - * @param {Function} latchFunction - * @param {String} optional_timeoutMessage - * @param {Number} optional_timeout - */ -jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { - var latchFunction_ = null; - var optional_timeoutMessage_ = null; - var optional_timeout_ = null; - - for (var i = 0; i < arguments.length; i++) { - var arg = arguments[i]; - switch (typeof arg) { - case 'function': - latchFunction_ = arg; - break; - case 'string': - optional_timeoutMessage_ = arg; - break; - case 'number': - optional_timeout_ = arg; - break; - } - } + if (!j$.isSpy(actual)) { + throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); + } - var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); - this.addToQueue(waitsForFunc); - return this; -}; + if (arguments.length > 1) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } -jasmine.Spec.prototype.fail = function (e) { - var expectationResult = new jasmine.ExpectationResult({ - passed: false, - message: e ? jasmine.util.formatException(e) : 'Exception', - trace: { stack: e.stack } - }); - this.results_.addResult(expectationResult); -}; + result.pass = actual.calls.any(); -jasmine.Spec.prototype.getMatchersClass_ = function() { - return this.matchersClass || this.env.matchersClass; -}; + result.message = result.pass ? + 'Expected spy ' + actual.and.identity() + ' not to have been called.' : + 'Expected spy ' + actual.and.identity() + ' to have been called.'; -jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { - var parent = this.getMatchersClass_(); - var newMatchersClass = function() { - parent.apply(this, arguments); - }; - jasmine.util.inherit(newMatchersClass, parent); - jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); - this.matchersClass = newMatchersClass; -}; + return result; + } + }; + } -jasmine.Spec.prototype.finishCallback = function() { - this.env.reporter.reportSpecResults(this); + return toHaveBeenCalled; }; -jasmine.Spec.prototype.finish = function(onComplete) { - this.removeAllSpies(); - this.finishCallback(); - if (onComplete) { - onComplete(); - } -}; +getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { -jasmine.Spec.prototype.after = function(doAfter) { - if (this.queue.isRunning()) { - this.queue.add(new jasmine.Block(this.env, doAfter, this), true); - } else { - this.afterCallbacks.unshift(doAfter); - } -}; + function toHaveBeenCalledWith(util, customEqualityTesters) { + return { + compare: function() { + var args = Array.prototype.slice.call(arguments, 0), + actual = args[0], + expectedArgs = args.slice(1), + result = { pass: false }; -jasmine.Spec.prototype.execute = function(onComplete) { - var spec = this; - if (!spec.env.specFilter(spec)) { - spec.results_.skipped = true; - spec.finish(onComplete); - return; - } + if (!j$.isSpy(actual)) { + throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); + } - this.env.reporter.reportSpecStarting(this); + if (!actual.calls.any()) { + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but it was never called.'; }; + return result; + } - spec.env.currentSpec = spec; + if (util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) { + result.pass = true; + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' not to have been called with ' + j$.pp(expectedArgs) + ' but it was.'; }; + } else { + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but actual calls were ' + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + '.'; }; + } - spec.addBeforesAndAftersToQueue(); + return result; + } + }; + } - spec.queue.start(function () { - spec.finish(onComplete); - }); + return toHaveBeenCalledWith; }; -jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { - var runner = this.env.currentRunner(); - var i; +getJasmineRequireObj().toMatch = function() { - for (var suite = this.suite; suite; suite = suite.parentSuite) { - for (i = 0; i < suite.before_.length; i++) { - this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); - } - } - for (i = 0; i < runner.before_.length; i++) { - 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), 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), true); - } - } - for (i = 0; i < runner.after_.length; i++) { - this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true); + function toMatch() { + return { + compare: function(actual, expected) { + var regexp = new RegExp(expected); + + return { + pass: regexp.test(actual) + }; + } + }; } -}; -jasmine.Spec.prototype.explodes = function() { - throw 'explodes function should not have been called'; + return toMatch; }; -jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { - if (obj == jasmine.undefined) { - throw "spyOn could not find an object to spy upon for " + methodName + "()"; - } +getJasmineRequireObj().toThrow = function(j$) { - if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { - throw methodName + '() method does not exist'; - } + function toThrow(util) { + return { + compare: function(actual, expected) { + var result = { pass: false }, + threw = false, + thrown; - if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { - throw new Error(methodName + ' has already been spied upon'); - } + if (typeof actual != 'function') { + throw new Error('Actual is not a Function'); + } + + try { + actual(); + } catch (e) { + threw = true; + thrown = e; + } - var spyObj = jasmine.createSpy(methodName); + if (!threw) { + result.message = 'Expected function to throw an exception.'; + return result; + } - this.spies_.push(spyObj); - spyObj.baseObj = obj; - spyObj.methodName = methodName; - spyObj.originalValue = obj[methodName]; + if (arguments.length == 1) { + result.pass = true; + result.message = function() { return 'Expected function not to throw, but it threw ' + j$.pp(thrown) + '.'; }; - obj[methodName] = spyObj; + return result; + } - return spyObj; -}; + if (util.equals(thrown, expected)) { + result.pass = true; + result.message = function() { return 'Expected function not to throw ' + j$.pp(expected) + '.'; }; + } else { + result.message = function() { return 'Expected function to throw ' + j$.pp(expected) + ', but it threw ' + j$.pp(thrown) + '.'; }; + } -jasmine.Spec.prototype.removeAllSpies = function() { - for (var i = 0; i < this.spies_.length; i++) { - var spy = this.spies_[i]; - spy.baseObj[spy.methodName] = spy.originalValue; + return result; + } + }; } - this.spies_ = []; -}; -/** - * Internal representation of a Jasmine suite. - * - * @constructor - * @param {jasmine.Env} env - * @param {String} description - * @param {Function} specDefinitions - * @param {jasmine.Suite} parentSuite - */ -jasmine.Suite = function(env, description, specDefinitions, parentSuite) { - var self = this; - self.id = env.nextSuiteId ? env.nextSuiteId() : null; - self.description = description; - self.queue = new jasmine.Queue(env); - self.parentSuite = parentSuite; - self.env = env; - self.before_ = []; - self.after_ = []; - self.children_ = []; - self.suites_ = []; - self.specs_ = []; + return toThrow; }; -jasmine.Suite.prototype.getFullName = function() { - var fullName = this.description; - for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { - fullName = parentSuite.description + ' ' + fullName; - } - return fullName; -}; +getJasmineRequireObj().toThrowError = function(j$) { + function toThrowError (util) { + return { + compare: function(actual) { + var threw = false, + pass = {pass: true}, + fail = {pass: false}, + thrown, + errorType, + message, + regexp, + name, + constructorName; -jasmine.Suite.prototype.finish = function(onComplete) { - this.env.reporter.reportSuiteResults(this); - this.finished = true; - if (typeof(onComplete) == 'function') { - onComplete(); - } -}; + if (typeof actual != 'function') { + throw new Error('Actual is not a Function'); + } -jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { - beforeEachFunction.typeName = 'beforeEach'; - this.before_.unshift(beforeEachFunction); -}; + extractExpectedParams.apply(null, arguments); -jasmine.Suite.prototype.afterEach = function(afterEachFunction) { - afterEachFunction.typeName = 'afterEach'; - this.after_.unshift(afterEachFunction); -}; + try { + actual(); + } catch (e) { + threw = true; + thrown = e; + } -jasmine.Suite.prototype.results = function() { - return this.queue.results(); -}; + if (!threw) { + fail.message = 'Expected function to throw an Error.'; + return fail; + } -jasmine.Suite.prototype.add = function(suiteOrSpec) { - this.children_.push(suiteOrSpec); - if (suiteOrSpec instanceof jasmine.Suite) { - this.suites_.push(suiteOrSpec); - this.env.currentRunner().addSuite(suiteOrSpec); - } else { - this.specs_.push(suiteOrSpec); - } - this.queue.add(suiteOrSpec); -}; + if (!(thrown instanceof Error)) { + fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; }; + return fail; + } -jasmine.Suite.prototype.specs = function() { - return this.specs_; -}; + if (arguments.length == 1) { + pass.message = 'Expected function not to throw an Error, but it threw ' + fnNameFor(thrown) + '.'; + return pass; + } -jasmine.Suite.prototype.suites = function() { - return this.suites_; -}; + if (errorType) { + name = fnNameFor(errorType); + constructorName = fnNameFor(thrown.constructor); + } -jasmine.Suite.prototype.children = function() { - return this.children_; -}; + if (errorType && message) { + if (thrown.constructor == errorType && util.equals(thrown.message, message)) { + pass.message = function() { return 'Expected function not to throw ' + name + ' with message ' + j$.pp(message) + '.'; }; + return pass; + } else { + fail.message = function() { return 'Expected function to throw ' + name + ' with message ' + j$.pp(message) + + ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; }; + return fail; + } + } -jasmine.Suite.prototype.execute = function(onComplete) { - var self = this; - this.queue.start(function () { - self.finish(onComplete); - }); -}; -jasmine.WaitsBlock = function(env, timeout, spec) { - this.timeout = timeout; - jasmine.Block.call(this, env, null, spec); -}; + if (errorType && regexp) { + if (thrown.constructor == errorType && regexp.test(thrown.message)) { + pass.message = function() { return 'Expected function not to throw ' + name + ' with message matching ' + j$.pp(regexp) + '.'; }; + return pass; + } else { + fail.message = function() { return 'Expected function to throw ' + name + ' with message matching ' + j$.pp(regexp) + + ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; }; + return fail; + } + } -jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); + if (errorType) { + if (thrown.constructor == errorType) { + pass.message = 'Expected function not to throw ' + name + '.'; + return pass; + } else { + fail.message = 'Expected function to throw ' + name + ', but it threw ' + constructorName + '.'; + return fail; + } + } -jasmine.WaitsBlock.prototype.execute = function (onComplete) { - if (jasmine.VERBOSE) { - this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); - } - this.env.setTimeout(function () { - onComplete(); - }, this.timeout); -}; -/** - * A block which waits for some condition to become true, with timeout. - * - * @constructor - * @extends jasmine.Block - * @param {jasmine.Env} env The Jasmine environment. - * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. - * @param {Function} latchFunction A function which returns true when the desired condition has been met. - * @param {String} message The message to display if the desired condition hasn't been met within the given time period. - * @param {jasmine.Spec} spec The Jasmine spec. - */ -jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { - this.timeout = timeout || env.defaultTimeoutInterval; - this.latchFunction = latchFunction; - this.message = message; - this.totalTimeSpentWaitingForLatch = 0; - jasmine.Block.call(this, env, null, spec); -}; -jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); + if (message) { + if (thrown.message == message) { + pass.message = function() { return 'Expected function not to throw an exception with message ' + j$.pp(message) + '.'; }; + return pass; + } else { + fail.message = function() { return 'Expected function to throw an exception with message ' + j$.pp(message) + + ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; }; + return fail; + } + } -jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; + if (regexp) { + if (regexp.test(thrown.message)) { + pass.message = function() { return 'Expected function not to throw an exception with a message matching ' + j$.pp(regexp) + '.'; }; + return pass; + } else { + fail.message = function() { return 'Expected function to throw an exception with a message matching ' + j$.pp(regexp) + + ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; }; + return fail; + } + } -jasmine.WaitsForBlock.prototype.execute = function(onComplete) { - if (jasmine.VERBOSE) { - this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); - } - var latchFunctionResult; - try { - latchFunctionResult = this.latchFunction.apply(this.spec); - } catch (e) { - this.spec.fail(e); - onComplete(); - return; - } + function fnNameFor(func) { + return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1]; + } - if (latchFunctionResult) { - onComplete(); - } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { - var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); - this.spec.fail({ - name: 'timeout', - message: message - }); + function extractExpectedParams() { + if (arguments.length == 1) { + return; + } - this.abort = true; - onComplete(); - } else { - this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; - var self = this; - this.env.setTimeout(function() { - self.execute(onComplete); - }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); + if (arguments.length == 2) { + var expected = arguments[1]; + + if (expected instanceof RegExp) { + regexp = expected; + } else if (typeof expected == 'string') { + message = expected; + } else if (checkForAnErrorType(expected)) { + errorType = expected; + } + + if (!(errorType || message || regexp)) { + throw new Error('Expected is not an Error, string, or RegExp.'); + } + } else { + if (checkForAnErrorType(arguments[1])) { + errorType = arguments[1]; + } else { + throw new Error('Expected error type is not an Error.'); + } + + if (arguments[2] instanceof RegExp) { + regexp = arguments[2]; + } else if (typeof arguments[2] == 'string') { + message = arguments[2]; + } else { + throw new Error('Expected error message is not a string or RegExp.'); + } + } + } + + function checkForAnErrorType(type) { + if (typeof type !== 'function') { + return false; + } + + var Surrogate = function() {}; + Surrogate.prototype = type.prototype; + return (new Surrogate()) instanceof Error; + } + } + }; } -}; -jasmine.version_= { - "major": 1, - "minor": 3, - "build": 1, - "revision": 1354556913 + return toThrowError; }; + +getJasmineRequireObj().version = function() { + return '2.0.0'; +}; \ No newline at end of file diff --git a/vendor/assets/stylesheets/jasmine.css b/vendor/assets/stylesheets/jasmine.css index 8c008dc..68e4c9e 100644 --- a/vendor/assets/stylesheets/jasmine.css +++ b/vendor/assets/stylesheets/jasmine.css @@ -1,82 +1,59 @@ body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } -#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } -#HTMLReporter a { text-decoration: none; } -#HTMLReporter a:hover { text-decoration: underline; } -#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; } -#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; } -#HTMLReporter #jasmine_content { position: fixed; right: 100%; } -#HTMLReporter .version { color: #aaaaaa; } -#HTMLReporter .banner { margin-top: 14px; } -#HTMLReporter .duration { color: #aaaaaa; float: right; } -#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; } -#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; } -#HTMLReporter .symbolSummary li.passed { font-size: 14px; } -#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; } -#HTMLReporter .symbolSummary li.failed { line-height: 9px; } -#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; } -#HTMLReporter .symbolSummary li.skipped { font-size: 14px; } -#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; } -#HTMLReporter .skippedAlert:first-child { background-color: #333333; } -#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; } -#HTMLReporter .passingAlert { background-color: #a6b779; } -#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; } -#HTMLReporter .failingAlert { background-color: #cf867e; } -#HTMLReporter .failingAlert:first-child { background-color: #b03911; } -#HTMLReporter .results { margin-top: 14px; } -#HTMLReporter #details { display: none; } -#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; } -#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } -#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } -#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } -#HTMLReporter.showDetails .summary { display: none; } -#HTMLReporter.showDetails #details { display: block; } -#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } -#HTMLReporter .summary { margin-top: 14px; } -#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; } -#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; } -#HTMLReporter .summary .specSummary.failed a { color: #b03911; } -#HTMLReporter .description + .suite { margin-top: 0; } -#HTMLReporter .suite { margin-top: 14px; } -#HTMLReporter .suite a { color: #333333; } -#HTMLReporter #details .specDetail { margin-bottom: 28px; } -#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; } -#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; } -#HTMLReporter .resultMessage span.result { display: block; } -#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } - -#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ } -#TrivialReporter a:visited, #TrivialReporter a { color: #303; } -#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; } -#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; } -#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; } -#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; } -#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; } -#TrivialReporter .runner.running { background-color: yellow; } -#TrivialReporter .options { text-align: right; font-size: .8em; } -#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; } -#TrivialReporter .suite .suite { margin: 5px; } -#TrivialReporter .suite.passed { background-color: #dfd; } -#TrivialReporter .suite.failed { background-color: #fdd; } -#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; } -#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; } -#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; } -#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; } -#TrivialReporter .spec.skipped { background-color: #bbb; } -#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; } -#TrivialReporter .passed { background-color: #cfc; display: none; } -#TrivialReporter .failed { background-color: #fbb; } -#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; } -#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; } -#TrivialReporter .resultMessage .mismatch { color: black; } -#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; } -#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; } -#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; } -#TrivialReporter #jasmine_content { position: fixed; right: 100%; } -#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; } +.html-reporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } +.html-reporter a { text-decoration: none; } +.html-reporter a:hover { text-decoration: underline; } +.html-reporter p, .html-reporter h1, .html-reporter h2, .html-reporter h3, .html-reporter h4, .html-reporter h5, .html-reporter h6 { margin: 0; line-height: 14px; } +.html-reporter .banner, .html-reporter .symbol-summary, .html-reporter .summary, .html-reporter .result-message, .html-reporter .spec .description, .html-reporter .spec-detail .description, .html-reporter .alert .bar, .html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; } +.html-reporter .banner { position: relative; } +.html-reporter .banner .title { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAZCAYAAACxZDnAAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAB2AAAAdgB+lymcgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAk/SURBVGiB7Zp/cFTVFcc/577NskmAIII4CAW15YcitlSYaVVgN0SxtoJYwfqrTnVqGY3Dj93ww2zWzSKQZCmoUNGOVipiW0dRaqMCuwtYtfVnFS1i2wEtM4oC8iu/Ntl7+se+DUlARGdIh5bvzJu57+5595zzffeec+59K6rKSRx/mP+2Af8v8HwV4aqS6DdIm6JGY7dEUpGW42XU/yLkaKEjfmm8kObGGYpeBIwAerk/NQDvgL6OmMWhRPm/OsHWExpfSHRV8d3fd9SuUPim26UK/xBlH8J5gM/tr0MkFEqU398ZBp+oOCLRNYFYBRAhG8M3ispdttn7Rtmfyw4ARP1RT6HDOWrlJpBpgABrJS9/UvCFYF0n2n/C4LAYHQ9UXg4SBRpB5oZS5UtQFKDGH1uL4M03nrLg+jtfBWbE/fPWqOgjwCU0N1QDt3WqBycI2hG9xB/toWIeBBC4OZgsX1VTHAvmjXYem7Zp7scIo4EuYrUnQDxQWV03Vmd33eQZY9VuVphaHah8qixZkeioqDpQWSzIsrZ9Ru1FM1ORXcfRvy9FTSCWAOkVSpaffzz1tCvv0uJUA31RVgeT4VUAWLuy2WMXR6PRdrLVxbFfWOXtSCRiZybu/BAIAiLIw1F/1EcHiJo84FRgMDAI6JHOeOX4uPWVcDbo4OOtpN2MFnQikGl2nKmLxsVGZjIyoKEbtQUH+W3XTXKpdeVU8GIZXLahYkZ8XOx7qjowlKx4sMYfuwVhZD6ebwN/aTt2KFX+/EJ/dKQjZhuwP5QMn9729/il0dPImLNx8t8Jrg3W14yN9gFocbzNc9bP2Q2wYNyCU/NIn1HXk/cLPqNnfW/2dN9P15YmvM1Ons5dP3dnVUlVUV46fdaMTeG/5UJe1B/1FYo5v4vPbimtjexvpxNznRHjAESviBYUHKA7gHgLDwTXBusXFUeHop46dzIdhoX+6ECPcc5qbnY2z9k057MvIro1GS4qvnuAVbsdeC+UDA+rCcRWADcCdSDPirJcRaer0F+tvUPEXClwNdAf2FOvtk+BkYWozETl9lCqfFlHZQv90YEu0ftCyXAPyNbmJmMeBopdsbSo3KGiy7Mvn7cH9Bry3e273n8SuJzs5HgPOBeVyxCdDYwBmhRmCNzjyvw749ixTsaMBZYC+UCTCsGyRHgpQE0gthcoAppCybAvXhybpspiAIV7gfGSXX2grGtxPD/JvfS4PzpMxVkBOuIQm6z0dbG3tX2ZObSGA6uZC7Ky8qbb5QGagULQKSq2KpQMTyhLhEeIOBcLzHBJBmSHz0NfUfdZaaP8KIheES0wGbPBJflzhJXAXhXNlYp7EX1+++4tk4AJwAZRKUHahbwk8AngFbgP5UXgI6C/kzFrgeUo74K+DnQR5Z6aMfO+5T77JFB/iCfdCvpqtk0p0A3hWcAilHhscxRac9l60GEgj4swHSWFcn1jo/n9kXxtY7AMBlDRDwBCyfB1eWpPU9WbgDW0SWRWM08A6xWZS0YGhZLl589aF/nIqvnANXjQsRBdcNDcDpwJrK/vavuFEuEb6nvZ/ihPu85+GExUzBYro10mDnbJL3oxk867MKP2TE9T4cZQMlwp8DYgKroglAoHPI1dhyBsBs4GfhNKhUeFkhUjQR4HDI5e7Pp4M9C63GcmKp5DxX3J+ka+r8eZoUT4R6hMcOm6ECBtZBrQB5WyULL82mAivCSUCgcEngLGx4vnBY5CtG4la+0ggMXFd5+RNuZ6EblE01IG8oOqQOzc6ouquzkiQSP6SyO2SAyTF/mjQwCM2EEAinxwLEQjXAwgovdG1kTqASJ/iKStMfF2cg6rgEaUiU2Ne3c5ec1LHDEDpr88vaGdMyp/BJj+8vQGUXk965YmWz1U3sg2pNsx2PZSaW1pE0A9mQ3uCNkkb2WUe395PBB7PnepZle4oqM6DncodDj6mis0AqAFnSTKWwN7DblRvLoMdIpBVpq89AyQW63KY6bFWQaZZ6yYyVUlVUXqhgzFdaijMnG65NRl7cSbJcBk2sp5OiTp4PrwK0bMEKBSYQ/Z3LEhHohd21auRe3OXFvFunHS7DtkgNYBiNFjqHbkk1wrkooczHVCtrRy79pVYiLsEXhB0Z10QKvgrHWRj4BPgSHzx83vE0qU3xdKhl/atmtrGW6iEqNVOLoW2Amc0uJkVtaN5e+hZLhy1rpZ+3CXuHGJrimO/bomENOa4tijWUPscNfa3QCK/tWlZXquJIxOjnotdnpbI6vGxM6zVodKnl0WSoUHgj4AoMqPv5yw44JXAARqg8nw+Nxl0RqrsryhUA+L0+224DWByl+BTEVZHUqFJ7mVyD8BjyhLFfuQGDNW0K1W5U+AiOotwVTFQzWB2M+BB4BtPl+PoaW1pU1xf+waFR53h38JGAl4EV0USlQEq0qqikwm/S7QD9gtSK2i44He7jN7RfQB1Jyu6E+BNUbtLCtmHnCVKktE+ByYCpyO8KzB3K42M86KlLkVw0ZVE0S0r2DDIBeo8BYqdwk6AbgG8IE8YcSusMpdIKNA3lEl1uPAac/s6/7po6BTgAOgq3w+LWtsNO8CfUBWq+gGFL/AZODBUDJ8a0ei2019n09nAzsQrowHYtfOTNz5oapcDWysw4ZycjMTFc+pcg8wf0DvoY8sKr57ABAHVFR+lottwVT4dyJaBWSACwEvympfF60EmLVu1j4yEkB5DThV0RuAIhVKXVU9UBnvtncAw62YLcBEIJnJeOYDASBbkys/tLblFBVGtpZlMAa0n4ieA5KtrJTvZO+5CijI8qBTFBmcJRlAh2PssI+7fey4JAN0A5lYWhvZn1EbAF4DnSLK/QIlijxU38vmbG+Hww6VFhVXXmZVajnCWcfCkuhZpsUZXpYqfzonH/fPG+uedQwQZWkwFT5M0YLRC3obxw4WWraXpSI7jmRIVUn0G46aM+oydnNkQ6Su7YbFiGnxOo0O+7s3ZHwHh5NntwVfiHwKsHh8tGdLUzbWA9TDrp75FDQ2UJDr8+X3/Lwp0+TRdF1rEhRv4QGoK9T0oclW3439uQ2LO9bBSCpysMYfbd1ctWS8mbYbk+pLon3JePo12JY3j3ZGf/L0rpNw8jy6k3DyC0sn4ahEd8TJb4ZfH1+J6JP4+jj5d4NOwn8AQAAydN2xotAAAAAASUVORK5CYII=') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -webkit-background-size: 100%; -moz-background-size: 100%; -o-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; } +.html-reporter .banner .version { margin-left: 14px; position: relative; top: 6px; } +.html-reporter .banner .duration { position: absolute; right: 14px; top: 6px; } +.html-reporter #jasmine_content { position: fixed; right: 100%; } +.html-reporter .version { color: #aaaaaa; } +.html-reporter .banner { margin-top: 14px; } +.html-reporter .duration { color: #aaaaaa; float: right; } +.html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; } +.html-reporter .symbol-summary li { display: inline-block; height: 8px; width: 14px; font-size: 16px; } +.html-reporter .symbol-summary li.passed { font-size: 14px; } +.html-reporter .symbol-summary li.passed:before { color: #007069; content: "\02022"; } +.html-reporter .symbol-summary li.failed { line-height: 9px; } +.html-reporter .symbol-summary li.failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; } +.html-reporter .symbol-summary li.disabled { font-size: 14px; } +.html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; } +.html-reporter .symbol-summary li.pending { line-height: 17px; } +.html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; } +.html-reporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; } +.html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } +.html-reporter .bar.failed { background-color: #ca3a11; } +.html-reporter .bar.passed { background-color: #007069; } +.html-reporter .bar.skipped { background-color: #bababa; } +.html-reporter .bar.menu { background-color: #fff; color: #aaaaaa; } +.html-reporter .bar.menu a { color: #333333; } +.html-reporter .bar a { color: white; } +.html-reporter.spec-list .bar.menu.failure-list, .html-reporter.spec-list .results .failures { display: none; } +.html-reporter.failure-list .bar.menu.spec-list, .html-reporter.failure-list .summary { display: none; } +.html-reporter .running-alert { background-color: #666666; } +.html-reporter .results { margin-top: 14px; } +.html-reporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } +.html-reporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } +.html-reporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } +.html-reporter.showDetails .summary { display: none; } +.html-reporter.showDetails #details { display: block; } +.html-reporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } +.html-reporter .summary { margin-top: 14px; } +.html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; } +.html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; } +.html-reporter .summary li.passed a { color: #007069; } +.html-reporter .summary li.failed a { color: #ca3a11; } +.html-reporter .summary li.empty a { color: #ba9d37; } +.html-reporter .summary li.pending a { color: #ba9d37; } +.html-reporter .description + .suite { margin-top: 0; } +.html-reporter .suite { margin-top: 14px; } +.html-reporter .suite a { color: #333333; } +.html-reporter .failures .spec-detail { margin-bottom: 28px; } +.html-reporter .failures .spec-detail .description { background-color: #ca3a11; } +.html-reporter .failures .spec-detail .description a { color: white; } +.html-reporter .result-message { padding-top: 14px; color: #333333; white-space: pre; } +.html-reporter .result-message span.result { display: block; } +.html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } \ No newline at end of file From 946ad7a82bc864c0f20a8863ae33a1fcb8dddb61 Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Fri, 13 Jun 2014 11:49:33 +1000 Subject: [PATCH 02/16] Fixed bad reference to jasmine-jquery --- app/assets/javascripts/jasminerice.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/jasminerice.js.coffee b/app/assets/javascripts/jasminerice.js.coffee index 79457ed..00cc599 100644 --- a/app/assets/javascripts/jasminerice.js.coffee +++ b/app/assets/javascripts/jasminerice.js.coffee @@ -1,7 +1,7 @@ #=require jasmine #=require jasmine-html #=require boot -#=require jasmine-jquery-1.11.0.js +#=require jasmine-jquery-1.5.8.js (-> execJasmine = -> From c5db9f57ea897b6f12a99b1f9c6539809be08fe3 Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Fri, 13 Jun 2014 12:16:08 +1000 Subject: [PATCH 03/16] Upgraded to jasmine-jquery 2.0.5 --- app/assets/javascripts/jasminerice.js.coffee | 2 +- .../javascripts/jasmine-jquery-1.5.8.js | 673 --------------- vendor/assets/javascripts/jasmine-jquery.js | 813 ++++++++++++++++++ 3 files changed, 814 insertions(+), 674 deletions(-) delete mode 100644 vendor/assets/javascripts/jasmine-jquery-1.5.8.js create mode 100644 vendor/assets/javascripts/jasmine-jquery.js diff --git a/app/assets/javascripts/jasminerice.js.coffee b/app/assets/javascripts/jasminerice.js.coffee index 00cc599..6ebd3f7 100644 --- a/app/assets/javascripts/jasminerice.js.coffee +++ b/app/assets/javascripts/jasminerice.js.coffee @@ -1,7 +1,7 @@ #=require jasmine #=require jasmine-html #=require boot -#=require jasmine-jquery-1.5.8.js +#=require jasmine-jquery.js (-> execJasmine = -> diff --git a/vendor/assets/javascripts/jasmine-jquery-1.5.8.js b/vendor/assets/javascripts/jasmine-jquery-1.5.8.js deleted file mode 100644 index b9e5a37..0000000 --- a/vendor/assets/javascripts/jasmine-jquery-1.5.8.js +++ /dev/null @@ -1,673 +0,0 @@ -/*! - Jasmine-jQuery: a set of jQuery helpers for Jasmine tests. - - Version 1.5.8 - - https://github.com/velesin/jasmine-jquery - - Copyright (c) 2010-2013 Wojciech Zawistowski, Travis Jeffery - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -var readFixtures = function() { - return jasmine.getFixtures().proxyCallTo_('read', arguments) -} - -var preloadFixtures = function() { - jasmine.getFixtures().proxyCallTo_('preload', arguments) -} - -var loadFixtures = function() { - jasmine.getFixtures().proxyCallTo_('load', arguments) -} - -var appendLoadFixtures = function() { - jasmine.getFixtures().proxyCallTo_('appendLoad', arguments) -} - -var setFixtures = function(html) { - return jasmine.getFixtures().proxyCallTo_('set', arguments) -} - -var appendSetFixtures = function() { - jasmine.getFixtures().proxyCallTo_('appendSet', arguments) -} - -var sandbox = function(attributes) { - return jasmine.getFixtures().sandbox(attributes) -} - -var spyOnEvent = function(selector, eventName) { - return jasmine.JQuery.events.spyOn(selector, eventName) -} - -var preloadStyleFixtures = function() { - jasmine.getStyleFixtures().proxyCallTo_('preload', arguments) -} - -var loadStyleFixtures = function() { - jasmine.getStyleFixtures().proxyCallTo_('load', arguments) -} - -var appendLoadStyleFixtures = function() { - jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments) -} - -var setStyleFixtures = function(html) { - jasmine.getStyleFixtures().proxyCallTo_('set', arguments) -} - -var appendSetStyleFixtures = function(html) { - jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments) -} - -var loadJSONFixtures = function() { - return jasmine.getJSONFixtures().proxyCallTo_('load', arguments) -} - -var getJSONFixture = function(url) { - return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url] -} - -jasmine.spiedEventsKey = function (selector, eventName) { - return [$(selector).selector, eventName].toString() -} - -jasmine.getFixtures = function() { - return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures() -} - -jasmine.getStyleFixtures = function() { - return jasmine.currentStyleFixtures_ = jasmine.currentStyleFixtures_ || new jasmine.StyleFixtures() -} - -jasmine.Fixtures = function() { - this.containerId = 'jasmine-fixtures' - this.fixturesCache_ = {} - this.fixturesPath = 'spec/javascripts/fixtures' -} - -jasmine.Fixtures.prototype.set = function(html) { - this.cleanUp() - return this.createContainer_(html) -} - -jasmine.Fixtures.prototype.appendSet= function(html) { - this.addToContainer_(html) -} - -jasmine.Fixtures.prototype.preload = function() { - this.read.apply(this, arguments) -} - -jasmine.Fixtures.prototype.load = function() { - this.cleanUp() - this.createContainer_(this.read.apply(this, arguments)) -} - -jasmine.Fixtures.prototype.appendLoad = function() { - this.addToContainer_(this.read.apply(this, arguments)) -} - -jasmine.Fixtures.prototype.read = function() { - var htmlChunks = [] - - var fixtureUrls = arguments - for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { - htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex])) - } - - return htmlChunks.join('') -} - -jasmine.Fixtures.prototype.clearCache = function() { - this.fixturesCache_ = {} -} - -jasmine.Fixtures.prototype.cleanUp = function() { - $('#' + this.containerId).remove() -} - -jasmine.Fixtures.prototype.sandbox = function(attributes) { - var attributesToSet = attributes || {} - return $('
').attr(attributesToSet) -} - -jasmine.Fixtures.prototype.createContainer_ = function(html) { - var container = $('
') - .attr('id', this.containerId) - .html(html); - $(document.body).append(container) - return container -} - -jasmine.Fixtures.prototype.addToContainer_ = function(html){ - var container = $(document.body).find('#'+this.containerId).append(html) - if(!container.length){ - this.createContainer_(html) - } -} - -jasmine.Fixtures.prototype.getFixtureHtml_ = function(url) { - if (typeof this.fixturesCache_[url] === 'undefined') { - this.loadFixtureIntoCache_(url) - } - return this.fixturesCache_[url] -} - -jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) { - var url = this.makeFixtureUrl_(relativeUrl) - var request = $.ajax({ - type: "GET", - url: url + "?" + new Date().getTime(), - async: false - }) - this.fixturesCache_[relativeUrl] = request.responseText -} - -jasmine.Fixtures.prototype.makeFixtureUrl_ = function(relativeUrl){ - return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl -} - -jasmine.Fixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) { - return this[methodName].apply(this, passedArguments) -} - - -jasmine.StyleFixtures = function() { - this.fixturesCache_ = {} - this.fixturesNodes_ = [] - this.fixturesPath = 'spec/javascripts/fixtures' -} - -jasmine.StyleFixtures.prototype.set = function(css) { - this.cleanUp() - this.createStyle_(css) -} - -jasmine.StyleFixtures.prototype.appendSet = function(css) { - this.createStyle_(css) -} - -jasmine.StyleFixtures.prototype.preload = function() { - this.read_.apply(this, arguments) -} - -jasmine.StyleFixtures.prototype.load = function() { - this.cleanUp() - this.createStyle_(this.read_.apply(this, arguments)) -} - -jasmine.StyleFixtures.prototype.appendLoad = function() { - this.createStyle_(this.read_.apply(this, arguments)) -} - -jasmine.StyleFixtures.prototype.cleanUp = function() { - while(this.fixturesNodes_.length) { - this.fixturesNodes_.pop().remove() - } -} - -jasmine.StyleFixtures.prototype.createStyle_ = function(html) { - var styleText = $('
').html(html).text(), - style = $('') - - this.fixturesNodes_.push(style) - - $('head').append(style) -} - -jasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache - -jasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read - -jasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_ - -jasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_ - -jasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_ - -jasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_ - -jasmine.getJSONFixtures = function() { - return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures() -} - -jasmine.JSONFixtures = function() { - this.fixturesCache_ = {} - this.fixturesPath = 'spec/javascripts/fixtures/json' -} - -jasmine.JSONFixtures.prototype.load = function() { - this.read.apply(this, arguments) - return this.fixturesCache_ -} - -jasmine.JSONFixtures.prototype.read = function() { - var fixtureUrls = arguments - for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { - this.getFixtureData_(fixtureUrls[urlIndex]) - } - return this.fixturesCache_ -} - -jasmine.JSONFixtures.prototype.clearCache = function() { - this.fixturesCache_ = {} -} - -jasmine.JSONFixtures.prototype.getFixtureData_ = function(url) { - this.loadFixtureIntoCache_(url) - return this.fixturesCache_[url] -} - -jasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) { - var self = this - var url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl - $.ajax({ - async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded - cache: false, - dataType: 'json', - url: url, - success: function(data) { - self.fixturesCache_[relativeUrl] = data - }, - error: function(jqXHR, status, errorThrown) { - throw Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')') - } - }) -} - -jasmine.JSONFixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) { - return this[methodName].apply(this, passedArguments) -} - -jasmine.JQuery = function() {} - -jasmine.JQuery.browserTagCaseIndependentHtml = function(html) { - return $('
').append(html).html() -} - -jasmine.JQuery.elementToString = function(element) { - var domEl = $(element).get(0) - if (domEl == undefined || domEl.cloneNode) - return $('
').append($(element).clone()).html() - else - return element.toString() -} - -jasmine.JQuery.matchersClass = {} - -!function(namespace) { - var data = { - spiedEvents: {}, - handlers: [] - } - - namespace.events = { - spyOn: function(selector, eventName) { - var handler = function(e) { - data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = jasmine.util.argsToArray(arguments) - } - $(selector).on(eventName, handler) - data.handlers.push(handler) - return { - selector: selector, - eventName: eventName, - handler: handler, - reset: function(){ - delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] - } - } - }, - - args: function(selector, eventName) { - var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]; - - if (!actualArgs) { - throw "There is no spy for " + eventName + " on " + selector.toString() + ". Make sure to create a spy using spyOnEvent."; - } - - return actualArgs; - }, - - wasTriggered: function(selector, eventName) { - return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]) - }, - - wasTriggeredWith: function(selector, eventName, expectedArgs, env) { - var actualArgs = jasmine.JQuery.events.args(selector, eventName).slice(1); - if (Object.prototype.toString.call(expectedArgs) !== '[object Array]') { - actualArgs = actualArgs[0]; - } - return env.equals_(expectedArgs, actualArgs); - }, - - wasPrevented: function(selector, eventName) { - var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)], - e = args ? args[0] : undefined; - return e && e.isDefaultPrevented() - }, - - wasStopped: function(selector, eventName) { - var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)], - e = args ? args[0] : undefined; - return e && e.isPropagationStopped() - }, - - cleanUp: function() { - data.spiedEvents = {} - data.handlers = [] - } - } -}(jasmine.JQuery) - -!function(){ - var jQueryMatchers = { - toHaveClass: function(className) { - return this.actual.hasClass(className) - }, - - toHaveCss: function(css){ - for (var prop in css){ - if (this.actual.css(prop) !== css[prop]) return false - } - return true - }, - - toBeVisible: function() { - return this.actual.is(':visible') - }, - - toBeHidden: function() { - return this.actual.is(':hidden') - }, - - toBeSelected: function() { - return this.actual.is(':selected') - }, - - toBeChecked: function() { - return this.actual.is(':checked') - }, - - toBeEmpty: function() { - return this.actual.is(':empty') - }, - - toExist: function() { - return $(document).find(this.actual).length - }, - - toHaveLength: function(length) { - return this.actual.length === length - }, - - toHaveAttr: function(attributeName, expectedAttributeValue) { - return hasProperty(this.actual.attr(attributeName), expectedAttributeValue) - }, - - toHaveProp: function(propertyName, expectedPropertyValue) { - return hasProperty(this.actual.prop(propertyName), expectedPropertyValue) - }, - - toHaveId: function(id) { - return this.actual.attr('id') == id - }, - - toHaveHtml: function(html) { - return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html) - }, - - toContainHtml: function(html){ - var actualHtml = this.actual.html() - var expectedHtml = jasmine.JQuery.browserTagCaseIndependentHtml(html) - return (actualHtml.indexOf(expectedHtml) >= 0) - }, - - toHaveText: function(text) { - var trimmedText = $.trim(this.actual.text()) - if (text && $.isFunction(text.test)) { - return text.test(trimmedText) - } else { - return trimmedText == text - } - }, - - toContainText: function(text) { - var trimmedText = $.trim(this.actual.text()) - if (text && $.isFunction(text.test)) { - return text.test(trimmedText) - } else { - return trimmedText.indexOf(text) != -1; - } - }, - - toHaveValue: function(value) { - return this.actual.val() === value - }, - - toHaveData: function(key, expectedValue) { - return hasProperty(this.actual.data(key), expectedValue) - }, - - toBe: function(selector) { - return this.actual.is(selector) - }, - - toContain: function(selector) { - return this.actual.find(selector).length - }, - - toBeMatchedBy: function(selector) { - return this.actual.filter(selector).length - }, - - toBeDisabled: function(selector){ - return this.actual.is(':disabled') - }, - - toBeFocused: function(selector) { - return this.actual[0] === this.actual[0].ownerDocument.activeElement - }, - - toHandle: function(event) { - - var events = $._data(this.actual.get(0), "events") - - if(!events || !event || typeof event !== "string") { - return false - } - - var namespaces = event.split(".") - var eventType = namespaces.shift() - var sortedNamespaces = namespaces.slice(0).sort() - var namespaceRegExp = new RegExp("(^|\\.)" + sortedNamespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") - - if(events[eventType] && namespaces.length) { - for(var i = 0; i < events[eventType].length; i++) { - var namespace = events[eventType][i].namespace - if(namespaceRegExp.test(namespace)) { - return true - } - } - } else { - return events[eventType] && events[eventType].length > 0 - } - }, - - // tests the existence of a specific event binding + handler - toHandleWith: function(eventName, eventHandler) { - var normalizedEventName = eventName.split('.')[0]; - var stack = $._data(this.actual.get(0), "events")[normalizedEventName] - for (var i = 0; i < stack.length; i++) { - if (stack[i].handler == eventHandler) return true - } - return false - } - } - - var hasProperty = function(actualValue, expectedValue) { - if (expectedValue === undefined) return actualValue !== undefined - return actualValue == expectedValue - } - - var bindMatcher = function(methodName) { - var builtInMatcher = jasmine.Matchers.prototype[methodName] - - jasmine.JQuery.matchersClass[methodName] = function() { - if (this.actual - && (this.actual instanceof $ - || jasmine.isDomNode(this.actual))) { - this.actual = $(this.actual) - var result = jQueryMatchers[methodName].apply(this, arguments) - var element - if (this.actual.get && (element = this.actual.get()[0]) && !$.isWindow(element) && element.tagName !== "HTML") - this.actual = jasmine.JQuery.elementToString(this.actual) - return result - } - - if (builtInMatcher) { - return builtInMatcher.apply(this, arguments) - } - - return false - } - } - - for(var methodName in jQueryMatchers) { - bindMatcher(methodName) - } -}() - -beforeEach(function() { - this.addMatchers(jasmine.JQuery.matchersClass) - this.addMatchers({ - toHaveBeenTriggeredOn: function(selector) { - this.message = function() { - return [ - "Expected event " + this.actual + " to have been triggered on " + selector, - "Expected event " + this.actual + " not to have been triggered on " + selector - ] - } - return jasmine.JQuery.events.wasTriggered(selector, this.actual) - } - }) - this.addMatchers({ - toHaveBeenTriggered: function(){ - var eventName = this.actual.eventName, - selector = this.actual.selector - this.message = function() { - return [ - "Expected event " + eventName + " to have been triggered on " + selector, - "Expected event " + eventName + " not to have been triggered on " + selector - ] - } - return jasmine.JQuery.events.wasTriggered(selector, eventName) - } - }) - this.addMatchers({ - toHaveBeenTriggeredOnAndWith: function() { - var selector = arguments[0], - expectedArgs = arguments[1], - wasTriggered = jasmine.JQuery.events.wasTriggered(selector, this.actual); - this.message = function() { - if (wasTriggered) { - var actualArgs = jasmine.JQuery.events.args(selector, this.actual, expectedArgs)[1]; - return [ - "Expected event " + this.actual + " to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs), - "Expected event " + this.actual + " not to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) - ] - } else { - return [ - "Expected event " + this.actual + " to have been triggered on " + selector, - "Expected event " + this.actual + " not to have been triggered on " + selector - ] - } - } - return wasTriggered && jasmine.JQuery.events.wasTriggeredWith(selector, this.actual, expectedArgs, this.env); - } - }) - this.addMatchers({ - toHaveBeenPreventedOn: function(selector) { - this.message = function() { - return [ - "Expected event " + this.actual + " to have been prevented on " + selector, - "Expected event " + this.actual + " not to have been prevented on " + selector - ] - } - return jasmine.JQuery.events.wasPrevented(selector, this.actual) - } - }) - this.addMatchers({ - toHaveBeenPrevented: function() { - var eventName = this.actual.eventName, - selector = this.actual.selector - this.message = function() { - return [ - "Expected event " + eventName + " to have been prevented on " + selector, - "Expected event " + eventName + " not to have been prevented on " + selector - ] - } - return jasmine.JQuery.events.wasPrevented(selector, eventName) - } - }) - this.addMatchers({ - toHaveBeenStoppedOn: function(selector) { - this.message = function() { - return [ - "Expected event " + this.actual + " to have been stopped on " + selector, - "Expected event " + this.actual + " not to have been stopped on " + selector - ] - } - return jasmine.JQuery.events.wasStopped(selector, this.actual) - } - }) - this.addMatchers({ - toHaveBeenStopped: function() { - var eventName = this.actual.eventName, - selector = this.actual.selector - this.message = function() { - return [ - "Expected event " + eventName + " to have been stopped on " + selector, - "Expected event " + eventName + " not to have been stopped on " + selector - ] - } - return jasmine.JQuery.events.wasStopped(selector, eventName) - } - }) - jasmine.getEnv().addEqualityTester(function(a, b) { - if(a instanceof jQuery && b instanceof jQuery) { - if(a.size() != b.size()) { - return jasmine.undefined; - } - else if(a.is(b)) { - return true; - } - } - return jasmine.undefined; - - }) -}) - -afterEach(function() { - jasmine.getFixtures().cleanUp() - jasmine.getStyleFixtures().cleanUp() - jasmine.JQuery.events.cleanUp() -}) diff --git a/vendor/assets/javascripts/jasmine-jquery.js b/vendor/assets/javascripts/jasmine-jquery.js new file mode 100644 index 0000000..f4dcb2a --- /dev/null +++ b/vendor/assets/javascripts/jasmine-jquery.js @@ -0,0 +1,813 @@ +/*! +Jasmine-jQuery: a set of jQuery helpers for Jasmine tests. + +Version 2.0.5 + +https://github.com/velesin/jasmine-jquery + +Copyright (c) 2010-2014 Wojciech Zawistowski, Travis Jeffery + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + ++function (window, jasmine, $) { "use strict"; + + jasmine.spiedEventsKey = function (selector, eventName) { + return [$(selector).selector, eventName].toString() + } + + jasmine.getFixtures = function () { + return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures() + } + + jasmine.getStyleFixtures = function () { + return jasmine.currentStyleFixtures_ = jasmine.currentStyleFixtures_ || new jasmine.StyleFixtures() + } + + jasmine.Fixtures = function () { + this.containerId = 'jasmine-fixtures' + this.fixturesCache_ = {} + this.fixturesPath = 'spec/javascripts/fixtures' + } + + jasmine.Fixtures.prototype.set = function (html) { + this.cleanUp() + return this.createContainer_(html) + } + + jasmine.Fixtures.prototype.appendSet= function (html) { + this.addToContainer_(html) + } + + jasmine.Fixtures.prototype.preload = function () { + this.read.apply(this, arguments) + } + + jasmine.Fixtures.prototype.load = function () { + this.cleanUp() + this.createContainer_(this.read.apply(this, arguments)) + } + + jasmine.Fixtures.prototype.appendLoad = function () { + this.addToContainer_(this.read.apply(this, arguments)) + } + + jasmine.Fixtures.prototype.read = function () { + var htmlChunks = [] + , fixtureUrls = arguments + + for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { + htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex])) + } + + return htmlChunks.join('') + } + + jasmine.Fixtures.prototype.clearCache = function () { + this.fixturesCache_ = {} + } + + jasmine.Fixtures.prototype.cleanUp = function () { + $('#' + this.containerId).remove() + } + + jasmine.Fixtures.prototype.sandbox = function (attributes) { + var attributesToSet = attributes || {} + return $('
').attr(attributesToSet) + } + + jasmine.Fixtures.prototype.createContainer_ = function (html) { + var container = $('
') + .attr('id', this.containerId) + .html(html) + + $(document.body).append(container) + return container + } + + jasmine.Fixtures.prototype.addToContainer_ = function (html){ + var container = $(document.body).find('#'+this.containerId).append(html) + + if (!container.length) { + this.createContainer_(html) + } + } + + jasmine.Fixtures.prototype.getFixtureHtml_ = function (url) { + if (typeof this.fixturesCache_[url] === 'undefined') { + this.loadFixtureIntoCache_(url) + } + return this.fixturesCache_[url] + } + + jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) { + var self = this + , url = this.makeFixtureUrl_(relativeUrl) + , htmlText = '' + , request = $.ajax({ + async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded + cache: false, + url: url, + success: function (data, status, $xhr) { + htmlText = $xhr.responseText + } + }).fail(function ($xhr, status, err) { + throw new Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')') + }) + + var scripts = $($.parseHTML(htmlText, true)).find('script[src]') || []; + + scripts.each(function(){ + $.ajax({ + async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded + cache: false, + dataType: 'script', + url: $(this).attr('src'), + success: function (data, status, $xhr) { + htmlText += '' + }, + error: function ($xhr, status, err) { + throw new Error('Script could not be loaded: ' + scriptSrc + ' (status: ' + status + ', message: ' + err.message + ')') + } + }); + }) + + self.fixturesCache_[relativeUrl] = htmlText; + } + + jasmine.Fixtures.prototype.makeFixtureUrl_ = function (relativeUrl){ + return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl + } + + jasmine.Fixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) { + return this[methodName].apply(this, passedArguments) + } + + + jasmine.StyleFixtures = function () { + this.fixturesCache_ = {} + this.fixturesNodes_ = [] + this.fixturesPath = 'spec/javascripts/fixtures' + } + + jasmine.StyleFixtures.prototype.set = function (css) { + this.cleanUp() + this.createStyle_(css) + } + + jasmine.StyleFixtures.prototype.appendSet = function (css) { + this.createStyle_(css) + } + + jasmine.StyleFixtures.prototype.preload = function () { + this.read_.apply(this, arguments) + } + + jasmine.StyleFixtures.prototype.load = function () { + this.cleanUp() + this.createStyle_(this.read_.apply(this, arguments)) + } + + jasmine.StyleFixtures.prototype.appendLoad = function () { + this.createStyle_(this.read_.apply(this, arguments)) + } + + jasmine.StyleFixtures.prototype.cleanUp = function () { + while(this.fixturesNodes_.length) { + this.fixturesNodes_.pop().remove() + } + } + + jasmine.StyleFixtures.prototype.createStyle_ = function (html) { + var styleText = $('
').html(html).text() + , style = $('') + + this.fixturesNodes_.push(style) + $('head').append(style) + } + + jasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache + jasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read + jasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_ + jasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_ + jasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_ + jasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_ + + jasmine.getJSONFixtures = function () { + return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures() + } + + jasmine.JSONFixtures = function () { + this.fixturesCache_ = {} + this.fixturesPath = 'spec/javascripts/fixtures/json' + } + + jasmine.JSONFixtures.prototype.load = function () { + this.read.apply(this, arguments) + return this.fixturesCache_ + } + + jasmine.JSONFixtures.prototype.read = function () { + var fixtureUrls = arguments + + for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { + this.getFixtureData_(fixtureUrls[urlIndex]) + } + + return this.fixturesCache_ + } + + jasmine.JSONFixtures.prototype.clearCache = function () { + this.fixturesCache_ = {} + } + + jasmine.JSONFixtures.prototype.getFixtureData_ = function (url) { + if (!this.fixturesCache_[url]) this.loadFixtureIntoCache_(url) + return this.fixturesCache_[url] + } + + jasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) { + var self = this + , url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl + + $.ajax({ + async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded + cache: false, + dataType: 'json', + url: url, + success: function (data) { + self.fixturesCache_[relativeUrl] = data + }, + error: function ($xhr, status, err) { + throw new Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')') + } + }) + } + + jasmine.JSONFixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) { + return this[methodName].apply(this, passedArguments) + } + + jasmine.jQuery = function () {} + + jasmine.jQuery.browserTagCaseIndependentHtml = function (html) { + return $('
').append(html).html() + } + + jasmine.jQuery.elementToString = function (element) { + return $(element).map(function () { return this.outerHTML; }).toArray().join(', ') + } + + var data = { + spiedEvents: {} + , handlers: [] + } + + jasmine.jQuery.events = { + spyOn: function (selector, eventName) { + var handler = function (e) { + data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = jasmine.util.argsToArray(arguments) + } + + $(selector).on(eventName, handler) + data.handlers.push(handler) + + return { + selector: selector, + eventName: eventName, + handler: handler, + reset: function (){ + delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] + } + } + }, + + args: function (selector, eventName) { + var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] + + if (!actualArgs) { + throw "There is no spy for " + eventName + " on " + selector.toString() + ". Make sure to create a spy using spyOnEvent." + } + + return actualArgs + }, + + wasTriggered: function (selector, eventName) { + return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]) + }, + + wasTriggeredWith: function (selector, eventName, expectedArgs, util, customEqualityTesters) { + var actualArgs = jasmine.jQuery.events.args(selector, eventName).slice(1) + + if (Object.prototype.toString.call(expectedArgs) !== '[object Array]') + actualArgs = actualArgs[0] + + return util.equals(expectedArgs, actualArgs, customEqualityTesters) + }, + + wasPrevented: function (selector, eventName) { + var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] + , e = args ? args[0] : undefined + + return e && e.isDefaultPrevented() + }, + + wasStopped: function (selector, eventName) { + var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] + , e = args ? args[0] : undefined + return e && e.isPropagationStopped() + }, + + cleanUp: function () { + data.spiedEvents = {} + data.handlers = [] + } + } + + var hasProperty = function (actualValue, expectedValue) { + if (expectedValue === undefined) + return actualValue !== undefined + + return actualValue === expectedValue + } + + beforeEach(function () { + jasmine.addMatchers({ + toHaveClass: function () { + return { + compare: function (actual, className) { + return { pass: $(actual).hasClass(className) } + } + } + }, + + toHaveCss: function () { + return { + compare: function (actual, css) { + for (var prop in css){ + var value = css[prop] + // see issue #147 on gh + ;if (value === 'auto' && $(actual).get(0).style[prop] === 'auto') continue + if ($(actual).css(prop) !== value) return { pass: false } + } + return { pass: true } + } + } + }, + + toBeVisible: function () { + return { + compare: function (actual) { + return { pass: $(actual).is(':visible') } + } + } + }, + + toBeHidden: function () { + return { + compare: function (actual) { + return { pass: $(actual).is(':hidden') } + } + } + }, + + toBeSelected: function () { + return { + compare: function (actual) { + return { pass: $(actual).is(':selected') } + } + } + }, + + toBeChecked: function () { + return { + compare: function (actual) { + return { pass: $(actual).is(':checked') } + } + } + }, + + toBeEmpty: function () { + return { + compare: function (actual) { + return { pass: $(actual).is(':empty') } + } + } + }, + + toBeInDOM: function () { + return { + compare: function (actual) { + return { pass: $.contains(document.documentElement, $(actual)[0]) } + } + } + }, + + toExist: function () { + return { + compare: function (actual) { + return { pass: $(actual).length } + } + } + }, + + toHaveLength: function () { + return { + compare: function (actual, length) { + return { pass: $(actual).length === length } + } + } + }, + + toHaveAttr: function () { + return { + compare: function (actual, attributeName, expectedAttributeValue) { + return { pass: hasProperty($(actual).attr(attributeName), expectedAttributeValue) } + } + } + }, + + toHaveProp: function () { + return { + compare: function (actual, propertyName, expectedPropertyValue) { + return { pass: hasProperty($(actual).prop(propertyName), expectedPropertyValue) } + } + } + }, + + toHaveId: function () { + return { + compare: function (actual, id) { + return { pass: $(actual).attr('id') == id } + } + } + }, + + toHaveHtml: function () { + return { + compare: function (actual, html) { + return { pass: $(actual).html() == jasmine.jQuery.browserTagCaseIndependentHtml(html) } + } + } + }, + + toContainHtml: function () { + return { + compare: function (actual, html) { + var actualHtml = $(actual).html() + , expectedHtml = jasmine.jQuery.browserTagCaseIndependentHtml(html) + + return { pass: (actualHtml.indexOf(expectedHtml) >= 0) } + } + } + }, + + toHaveText: function () { + return { + compare: function (actual, text) { + var actualText = $(actual).text() + var trimmedText = $.trim(actualText) + + if (text && $.isFunction(text.test)) { + return { pass: text.test(actualText) || text.test(trimmedText) } + } else { + return { pass: (actualText == text || trimmedText == text) } + } + } + } + }, + + toContainText: function () { + return { + compare: function (actual, text) { + var trimmedText = $.trim($(actual).text()) + + if (text && $.isFunction(text.test)) { + return { pass: text.test(trimmedText) } + } else { + return { pass: trimmedText.indexOf(text) != -1 } + } + } + } + }, + + toHaveValue: function () { + return { + compare: function (actual, value) { + return { pass: $(actual).val() === value } + } + } + }, + + toHaveData: function () { + return { + compare: function (actual, key, expectedValue) { + return { pass: hasProperty($(actual).data(key), expectedValue) } + } + } + }, + + toContainElement: function () { + return { + compare: function (actual, selector) { + if (window.debug) debugger + return { pass: $(actual).find(selector).length } + } + } + }, + + toBeMatchedBy: function () { + return { + compare: function (actual, selector) { + return { pass: $(actual).filter(selector).length } + } + } + }, + + toBeDisabled: function () { + return { + compare: function (actual, selector) { + return { pass: $(actual).is(':disabled') } + } + } + }, + + toBeFocused: function (selector) { + return { + compare: function (actual, selector) { + return { pass: $(actual)[0] === $(actual)[0].ownerDocument.activeElement } + } + } + }, + + toHandle: function () { + return { + compare: function (actual, event) { + var events = $._data($(actual).get(0), "events") + + if (!events || !event || typeof event !== "string") { + return { pass: false } + } + + var namespaces = event.split(".") + , eventType = namespaces.shift() + , sortedNamespaces = namespaces.slice(0).sort() + , namespaceRegExp = new RegExp("(^|\\.)" + sortedNamespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") + + if (events[eventType] && namespaces.length) { + for (var i = 0; i < events[eventType].length; i++) { + var namespace = events[eventType][i].namespace + + if (namespaceRegExp.test(namespace)) + return { pass: true } + } + } else { + return { pass: (events[eventType] && events[eventType].length > 0) } + } + + return { pass: false } + } + } + }, + + toHandleWith: function () { + return { + compare: function (actual, eventName, eventHandler) { + var normalizedEventName = eventName.split('.')[0] + , stack = $._data($(actual).get(0), "events")[normalizedEventName] + + for (var i = 0; i < stack.length; i++) { + if (stack[i].handler == eventHandler) return { pass: true } + } + + return { pass: false } + } + } + }, + + toHaveBeenTriggeredOn: function () { + return { + compare: function (actual, selector) { + var result = { pass: jasmine.jQuery.events.wasTriggered(selector, actual) } + + result.message = result.pass ? + "Expected event " + $(actual) + " not to have been triggered on " + selector : + "Expected event " + $(actual) + " to have been triggered on " + selector + + return result; + } + } + }, + + toHaveBeenTriggered: function (){ + return { + compare: function (actual) { + var eventName = actual.eventName + , selector = actual.selector + , result = { pass: jasmine.jQuery.events.wasTriggered(selector, eventName) } + + result.message = result.pass ? + "Expected event " + eventName + " not to have been triggered on " + selector : + "Expected event " + eventName + " to have been triggered on " + selector + + return result + } + } + }, + + toHaveBeenTriggeredOnAndWith: function (j$, customEqualityTesters) { + return { + compare: function (actual, selector, expectedArgs) { + var wasTriggered = jasmine.jQuery.events.wasTriggered(selector, actual) + , result = { pass: wasTriggered && jasmine.jQuery.events.wasTriggeredWith(selector, actual, expectedArgs, j$, customEqualityTesters) } + + if (wasTriggered) { + var actualArgs = jasmine.jQuery.events.args(selector, actual, expectedArgs)[1] + result.message = result.pass ? + "Expected event " + actual + " not to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) : + "Expected event " + actual + " to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) + + } else { + // todo check on this + result.message = result.pass ? + "Expected event " + actual + " not to have been triggered on " + selector : + "Expected event " + actual + " to have been triggered on " + selector + } + + return result + } + } + }, + + toHaveBeenPreventedOn: function () { + return { + compare: function (actual, selector) { + var result = { pass: jasmine.jQuery.events.wasPrevented(selector, actual) } + + result.message = result.pass ? + "Expected event " + actual + " not to have been prevented on " + selector : + "Expected event " + actual + " to have been prevented on " + selector + + return result + } + } + }, + + toHaveBeenPrevented: function () { + return { + compare: function (actual) { + var eventName = actual.eventName + , selector = actual.selector + , result = { pass: jasmine.jQuery.events.wasPrevented(selector, eventName) } + + result.message = result.pass ? + "Expected event " + eventName + " not to have been prevented on " + selector : + "Expected event " + eventName + " to have been prevented on " + selector + + return result + } + } + }, + + toHaveBeenStoppedOn: function () { + return { + compare: function (actual, selector) { + var result = { pass: jasmine.jQuery.events.wasStopped(selector, actual) } + + result.message = result.pass ? + "Expected event " + actual + " not to have been stopped on " + selector : + "Expected event " + actual + " to have been stopped on " + selector + + return result; + } + } + }, + + toHaveBeenStopped: function () { + return { + compare: function (actual) { + var eventName = actual.eventName + , selector = actual.selector + , result = { pass: jasmine.jQuery.events.wasStopped(selector, eventName) } + + result.message = result.pass ? + "Expected event " + eventName + " not to have been stopped on " + selector : + "Expected event " + eventName + " to have been stopped on " + selector + + return result + } + } + } + }) + + jasmine.getEnv().addCustomEqualityTester(function(a, b) { + if (a && b) { + if (a instanceof $ || jasmine.isDomNode(a)) { + var $a = $(a) + + if (b instanceof $) + return $a.length == b.length && a.is(b) + + return $a.is(b); + } + + if (b instanceof $ || jasmine.isDomNode(b)) { + var $b = $(b) + + if (a instanceof $) + return a.length == $b.length && $b.is(a) + + return $(b).is(a); + } + } + }) + + jasmine.getEnv().addCustomEqualityTester(function (a, b) { + if (a instanceof $ && b instanceof $ && a.size() == b.size()) + return a.is(b) + }) + }) + + afterEach(function () { + jasmine.getFixtures().cleanUp() + jasmine.getStyleFixtures().cleanUp() + jasmine.jQuery.events.cleanUp() + }) + + window.readFixtures = function () { + return jasmine.getFixtures().proxyCallTo_('read', arguments) + } + + window.preloadFixtures = function () { + jasmine.getFixtures().proxyCallTo_('preload', arguments) + } + + window.loadFixtures = function () { + jasmine.getFixtures().proxyCallTo_('load', arguments) + } + + window.appendLoadFixtures = function () { + jasmine.getFixtures().proxyCallTo_('appendLoad', arguments) + } + + window.setFixtures = function (html) { + return jasmine.getFixtures().proxyCallTo_('set', arguments) + } + + window.appendSetFixtures = function () { + jasmine.getFixtures().proxyCallTo_('appendSet', arguments) + } + + window.sandbox = function (attributes) { + return jasmine.getFixtures().sandbox(attributes) + } + + window.spyOnEvent = function (selector, eventName) { + return jasmine.jQuery.events.spyOn(selector, eventName) + } + + window.preloadStyleFixtures = function () { + jasmine.getStyleFixtures().proxyCallTo_('preload', arguments) + } + + window.loadStyleFixtures = function () { + jasmine.getStyleFixtures().proxyCallTo_('load', arguments) + } + + window.appendLoadStyleFixtures = function () { + jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments) + } + + window.setStyleFixtures = function (html) { + jasmine.getStyleFixtures().proxyCallTo_('set', arguments) + } + + window.appendSetStyleFixtures = function (html) { + jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments) + } + + window.loadJSONFixtures = function () { + return jasmine.getJSONFixtures().proxyCallTo_('load', arguments) + } + + window.getJSONFixture = function (url) { + return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url] + } +}(window, window.jasmine, window.jQuery); \ No newline at end of file From 1fa657bc8c10076ebc33303543a8110c5d6c9cb6 Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Fri, 13 Jun 2014 12:16:51 +1000 Subject: [PATCH 04/16] Added missing bar and foo files to the install generator --- lib/generators/jasminerice/install_generator.rb | 2 ++ lib/generators/jasminerice/templates/bar.js.coffee | 3 +++ lib/generators/jasminerice/templates/foo.js.coffee | 3 +++ 3 files changed, 8 insertions(+) create mode 100644 lib/generators/jasminerice/templates/bar.js.coffee create mode 100644 lib/generators/jasminerice/templates/foo.js.coffee diff --git a/lib/generators/jasminerice/install_generator.rb b/lib/generators/jasminerice/install_generator.rb index 837108c..154f914 100644 --- a/lib/generators/jasminerice/install_generator.rb +++ b/lib/generators/jasminerice/install_generator.rb @@ -11,6 +11,8 @@ def copy_files copy_file 'example_spec.js.coffee', 'spec/javascripts/example_spec.js.coffee' copy_file 'spec.css', 'spec/javascripts/spec.css' copy_file 'example_fixture.html.haml', 'spec/javascripts/fixtures/example_fixture.html.haml' + copy_file 'bar.js.coffee', 'app/assets/javascripts' + copy_file 'foo.js.coffee', 'app/assets/javascripts' end end end diff --git a/lib/generators/jasminerice/templates/bar.js.coffee b/lib/generators/jasminerice/templates/bar.js.coffee new file mode 100644 index 0000000..456ea75 --- /dev/null +++ b/lib/generators/jasminerice/templates/bar.js.coffee @@ -0,0 +1,3 @@ +class @Bar + bar: -> true + foo: -> false diff --git a/lib/generators/jasminerice/templates/foo.js.coffee b/lib/generators/jasminerice/templates/foo.js.coffee new file mode 100644 index 0000000..762e8a2 --- /dev/null +++ b/lib/generators/jasminerice/templates/foo.js.coffee @@ -0,0 +1,3 @@ +class @Foo + foo: -> true + bar: -> false From 42e2e845e33c36854f8e031e06ee6e0043c69a3d Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Fri, 13 Jun 2014 12:21:27 +1000 Subject: [PATCH 05/16] Fixed bad file copy in install_generator.rb --- lib/generators/jasminerice/install_generator.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/generators/jasminerice/install_generator.rb b/lib/generators/jasminerice/install_generator.rb index 154f914..d90d23b 100644 --- a/lib/generators/jasminerice/install_generator.rb +++ b/lib/generators/jasminerice/install_generator.rb @@ -11,8 +11,8 @@ def copy_files copy_file 'example_spec.js.coffee', 'spec/javascripts/example_spec.js.coffee' copy_file 'spec.css', 'spec/javascripts/spec.css' copy_file 'example_fixture.html.haml', 'spec/javascripts/fixtures/example_fixture.html.haml' - copy_file 'bar.js.coffee', 'app/assets/javascripts' - copy_file 'foo.js.coffee', 'app/assets/javascripts' + copy_file 'bar.js.coffee', 'app/assets/javascripts/bar.js.coffee' + copy_file 'foo.js.coffee', 'app/assets/javascripts/foo.js.coffee' end end end From a3374800709824757171e34723aab918f5d0088b Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Mon, 16 Jun 2014 14:25:06 +1000 Subject: [PATCH 06/16] Updated Jasmine to the latest release 2.0.5 --- vendor/assets/javascripts/boot.js | 24 +- vendor/assets/javascripts/jasmine-html.js | 162 +++--- vendor/assets/javascripts/jasmine.js | 615 +++++++++------------- vendor/assets/stylesheets/jasmine.css | 22 +- 4 files changed, 334 insertions(+), 489 deletions(-) mode change 100644 => 100755 vendor/assets/javascripts/boot.js mode change 100644 => 100755 vendor/assets/javascripts/jasmine-html.js mode change 100644 => 100755 vendor/assets/javascripts/jasmine.js mode change 100644 => 100755 vendor/assets/stylesheets/jasmine.css diff --git a/vendor/assets/javascripts/boot.js b/vendor/assets/javascripts/boot.js old mode 100644 new mode 100755 index 8ca4c4e..ec8baa0 --- a/vendor/assets/javascripts/boot.js +++ b/vendor/assets/javascripts/boot.js @@ -1,25 +1,3 @@ -/* -Copyright (c) 2008-2014 Pivotal Labs - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ /** Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project. @@ -200,4 +178,4 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. return destination; } -}()); \ No newline at end of file +}()); diff --git a/vendor/assets/javascripts/jasmine-html.js b/vendor/assets/javascripts/jasmine-html.js old mode 100644 new mode 100755 index 4bc6e5f..985d0d1 --- a/vendor/assets/javascripts/jasmine-html.js +++ b/vendor/assets/javascripts/jasmine-html.js @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2014 Pivotal Labs +Copyright (c) 2008-2013 Pivotal Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -49,20 +49,20 @@ jasmineRequire.HtmlReporter = function(j$) { symbols; this.initialize = function() { - htmlReporterMain = createDom('div', {className: 'html-reporter'}, - createDom('div', {className: 'banner'}, - createDom('a', {className: 'title', href: 'http://jasmine.github.io/', target: '_blank'}), - createDom('span', {className: 'version'}, j$.version) + htmlReporterMain = createDom("div", {className: "html-reporter"}, + createDom("div", {className: "banner"}, + createDom("span", {className: "title"}, "Jasmine"), + createDom("span", {className: "version"}, j$.version) ), - createDom('ul', {className: 'symbol-summary'}), - createDom('div', {className: 'alert'}), - createDom('div', {className: 'results'}, - createDom('div', {className: 'failures'}) + createDom("ul", {className: "symbol-summary"}), + createDom("div", {className: "alert"}), + createDom("div", {className: "results"}, + createDom("div", {className: "failures"}) ) ); getContainer().appendChild(htmlReporterMain); - symbols = find('.symbol-summary'); + symbols = find(".symbol-summary"); }; var totalSpecsDefined; @@ -71,13 +71,13 @@ jasmineRequire.HtmlReporter = function(j$) { timer.start(); }; - var summary = createDom('div', {className: 'summary'}); + var summary = createDom("div", {className: "summary"}); - var topResults = new j$.ResultsNode({}, '', null), + var topResults = new j$.ResultsNode({}, "", null), currentParent = topResults; this.suiteStarted = function(result) { - currentParent.addChild(result, 'suite'); + currentParent.addChild(result, "suite"); currentParent = currentParent.last(); }; @@ -90,94 +90,82 @@ jasmineRequire.HtmlReporter = function(j$) { }; this.specStarted = function(result) { - currentParent.addChild(result, 'spec'); + currentParent.addChild(result, "spec"); }; var failures = []; this.specDone = function(result) { - if(result.status == 'empty' && console && console.error) { - console.error('Spec \'' + result.fullName + '\' has no expectations.'); - } - - if (result.status != 'disabled') { + if (result.status != "disabled") { specsExecuted++; } - symbols.appendChild(createDom('li', { + symbols.appendChild(createDom("li", { className: result.status, - id: 'spec_' + result.id, + id: "spec_" + result.id, title: result.fullName } )); - if (result.status == 'failed') { + if (result.status == "failed") { failureCount++; var failure = - createDom('div', {className: 'spec-detail failed'}, - createDom('div', {className: 'description'}, - createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) + createDom("div", {className: "spec-detail failed"}, + createDom("div", {className: "description"}, + createDom("a", {title: result.fullName, href: specHref(result)}, result.fullName) ), - createDom('div', {className: 'messages'}) + createDom("div", {className: "messages"}) ); var messages = failure.childNodes[1]; for (var i = 0; i < result.failedExpectations.length; i++) { var expectation = result.failedExpectations[i]; - messages.appendChild(createDom('div', {className: 'result-message'}, expectation.message)); - messages.appendChild(createDom('div', {className: 'stack-trace'}, expectation.stack)); + messages.appendChild(createDom("div", {className: "result-message"}, expectation.message)); + messages.appendChild(createDom("div", {className: "stack-trace"}, expectation.stack)); } failures.push(failure); } - if (result.status == 'pending') { + if (result.status == "pending") { pendingSpecCount++; } }; this.jasmineDone = function() { - var banner = find('.banner'); - banner.appendChild(createDom('span', {className: 'duration'}, 'finished in ' + timer.elapsed() / 1000 + 's')); + var banner = find(".banner"); + banner.appendChild(createDom("span", {className: "duration"}, "finished in " + timer.elapsed() / 1000 + "s")); - var alert = find('.alert'); + var alert = find(".alert"); - alert.appendChild(createDom('span', { className: 'exceptions' }, - createDom('label', { className: 'label', 'for': 'raise-exceptions' }, 'raise exceptions'), - createDom('input', { - className: 'raise', - id: 'raise-exceptions', - type: 'checkbox' + alert.appendChild(createDom("span", { className: "exceptions" }, + createDom("label", { className: "label", 'for': "raise-exceptions" }, "raise exceptions"), + createDom("input", { + className: "raise", + id: "raise-exceptions", + type: "checkbox" }) )); - var checkbox = find('#raise-exceptions'); + var checkbox = find("input"); checkbox.checked = !env.catchingExceptions(); checkbox.onclick = onRaiseExceptionsClick; if (specsExecuted < totalSpecsDefined) { - var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all'; + var skippedMessage = "Ran " + specsExecuted + " of " + totalSpecsDefined + " specs - run all"; alert.appendChild( - createDom('span', {className: 'bar skipped'}, - createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage) + createDom("span", {className: "bar skipped"}, + createDom("a", {href: "?", title: "Run all specs"}, skippedMessage) ) ); } - var statusBarMessage = ''; - var statusBarClassName = 'bar '; - - if (totalSpecsDefined > 0) { - statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount); - if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); } - statusBarClassName += (failureCount > 0) ? 'failed' : 'passed'; - } else { - statusBarClassName += 'skipped'; - statusBarMessage += 'No specs found'; - } + var statusBarMessage = "" + pluralize("spec", specsExecuted) + ", " + pluralize("failure", failureCount); + if (pendingSpecCount) { statusBarMessage += ", " + pluralize("pending spec", pendingSpecCount); } - alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage)); + var statusBarClassName = "bar " + ((failureCount > 0) ? "failed" : "passed"); + alert.appendChild(createDom("span", {className: statusBarClassName}, statusBarMessage)); - var results = find('.results'); + var results = find(".results"); results.appendChild(summary); summaryList(topResults, summary); @@ -186,31 +174,27 @@ jasmineRequire.HtmlReporter = function(j$) { var specListNode; for (var i = 0; i < resultsTree.children.length; i++) { var resultNode = resultsTree.children[i]; - if (resultNode.type == 'suite') { - var suiteListNode = createDom('ul', {className: 'suite', id: 'suite-' + resultNode.result.id}, - createDom('li', {className: 'suite-detail'}, - createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) + if (resultNode.type == "suite") { + var suiteListNode = createDom("ul", {className: "suite", id: "suite-" + resultNode.result.id}, + createDom("li", {className: "suite-detail"}, + createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description) ) ); summaryList(resultNode, suiteListNode); domParent.appendChild(suiteListNode); } - if (resultNode.type == 'spec') { - if (domParent.getAttribute('class') != 'specs') { - specListNode = createDom('ul', {className: 'specs'}); + if (resultNode.type == "spec") { + if (domParent.getAttribute("class") != "specs") { + specListNode = createDom("ul", {className: "specs"}); domParent.appendChild(specListNode); } - var specDescription = resultNode.result.description; - if(resultNode.result.status == 'empty') { - specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; - } specListNode.appendChild( - createDom('li', { + createDom("li", { className: resultNode.result.status, - id: 'spec-' + resultNode.result.id + id: "spec-" + resultNode.result.id }, - createDom('a', {href: specHref(resultNode.result)}, specDescription) + createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description) ) ); } @@ -219,24 +203,24 @@ jasmineRequire.HtmlReporter = function(j$) { if (failures.length) { alert.appendChild( - createDom('span', {className: 'menu bar spec-list'}, - createDom('span', {}, 'Spec List | '), - createDom('a', {className: 'failures-menu', href: '#'}, 'Failures'))); + createDom('span', {className: "menu bar spec-list"}, + createDom("span", {}, "Spec List | "), + createDom('a', {className: "failures-menu", href: "#"}, "Failures"))); alert.appendChild( - createDom('span', {className: 'menu bar failure-list'}, - createDom('a', {className: 'spec-list-menu', href: '#'}, 'Spec List'), - createDom('span', {}, ' | Failures '))); + createDom('span', {className: "menu bar failure-list"}, + createDom('a', {className: "spec-list-menu", href: "#"}, "Spec List"), + createDom("span", {}, " | Failures "))); - find('.failures-menu').onclick = function() { + find(".failures-menu").onclick = function() { setMenuModeTo('failure-list'); }; - find('.spec-list-menu').onclick = function() { + find(".spec-list-menu").onclick = function() { setMenuModeTo('spec-list'); }; setMenuModeTo('failure-list'); - var failureNode = find('.failures'); + var failureNode = find(".failures"); for (var i = 0; i < failures.length; i++) { failureNode.appendChild(failures[i]); } @@ -246,7 +230,7 @@ jasmineRequire.HtmlReporter = function(j$) { return this; function find(selector) { - return getContainer().querySelector('.html-reporter ' + selector); + return getContainer().querySelector(selector); } function createDom(type, attrs, childrenVarArgs) { @@ -265,7 +249,7 @@ jasmineRequire.HtmlReporter = function(j$) { } for (var attr in attrs) { - if (attr == 'className') { + if (attr == "className") { el[attr] = attrs[attr]; } else { el.setAttribute(attr, attrs[attr]); @@ -276,17 +260,17 @@ jasmineRequire.HtmlReporter = function(j$) { } function pluralize(singular, count) { - var word = (count == 1 ? singular : singular + 's'); + var word = (count == 1 ? singular : singular + "s"); - return '' + count + ' ' + word; + return "" + count + " " + word; } function specHref(result) { - return '?spec=' + encodeURIComponent(result.fullName); + return "?spec=" + encodeURIComponent(result.fullName); } function setMenuModeTo(mode) { - htmlReporterMain.setAttribute('class', 'html-reporter ' + mode); + htmlReporterMain.setAttribute("class", "html-reporter " + mode); } } @@ -295,7 +279,7 @@ jasmineRequire.HtmlReporter = function(j$) { jasmineRequire.HtmlSpecFilter = function() { function HtmlSpecFilter(options) { - var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); + var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); var filterPattern = new RegExp(filterString); this.matches = function(specName) { @@ -344,9 +328,9 @@ jasmineRequire.QueryString = function() { function toQueryString(paramMap) { var qStrPairs = []; for (var prop in paramMap) { - qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])); + qStrPairs.push(encodeURIComponent(prop) + "=" + encodeURIComponent(paramMap[prop])); } - return '?' + qStrPairs.join('&'); + return "?" + qStrPairs.join('&'); } function queryStringToParamMap() { @@ -359,7 +343,7 @@ jasmineRequire.QueryString = function() { for (var i = 0; i < params.length; i++) { var p = params[i].split('='); var value = decodeURIComponent(p[1]); - if (value === 'true' || value === 'false') { + if (value === "true" || value === "false") { value = JSON.parse(value); } paramMap[decodeURIComponent(p[0])] = value; @@ -372,4 +356,4 @@ jasmineRequire.QueryString = function() { } return QueryString; -}; \ No newline at end of file +}; diff --git a/vendor/assets/javascripts/jasmine.js b/vendor/assets/javascripts/jasmine.js old mode 100644 new mode 100755 index 1bfe4e8..24463ec --- a/vendor/assets/javascripts/jasmine.js +++ b/vendor/assets/javascripts/jasmine.js @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2014 Pivotal Labs +Copyright (c) 2008-2013 Pivotal Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ function getJasmineRequireObj() { - if (typeof module !== 'undefined' && module.exports) { + if (typeof module !== "undefined" && module.exports) { return exports; } else { window.jasmineRequire = window.jasmineRequire || {}; @@ -36,7 +36,6 @@ getJasmineRequireObj().core = function(jRequire) { j$.util = jRequire.util(); j$.Any = jRequire.Any(); j$.CallTracker = jRequire.CallTracker(); - j$.MockDate = jRequire.MockDate(); j$.Clock = jRequire.Clock(); j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(); j$.Env = jRequire.Env(j$); @@ -47,7 +46,7 @@ getJasmineRequireObj().core = function(jRequire) { j$.matchersUtil = jRequire.matchersUtil(j$); j$.ObjectContaining = jRequire.ObjectContaining(j$); j$.pp = jRequire.pp(j$); - j$.QueueRunner = jRequire.QueueRunner(j$); + j$.QueueRunner = jRequire.QueueRunner(); j$.ReportDispatcher = jRequire.ReportDispatcher(); j$.Spec = jRequire.Spec(j$); j$.SpyStrategy = jRequire.SpyStrategy(); @@ -62,23 +61,23 @@ getJasmineRequireObj().core = function(jRequire) { getJasmineRequireObj().requireMatchers = function(jRequire, j$) { var availableMatchers = [ - 'toBe', - 'toBeCloseTo', - 'toBeDefined', - 'toBeFalsy', - 'toBeGreaterThan', - 'toBeLessThan', - 'toBeNaN', - 'toBeNull', - 'toBeTruthy', - 'toBeUndefined', - 'toContain', - 'toEqual', - 'toHaveBeenCalled', - 'toHaveBeenCalledWith', - 'toMatch', - 'toThrow', - 'toThrowError' + "toBe", + "toBeCloseTo", + "toBeDefined", + "toBeFalsy", + "toBeGreaterThan", + "toBeLessThan", + "toBeNaN", + "toBeNull", + "toBeTruthy", + "toBeUndefined", + "toContain", + "toEqual", + "toHaveBeenCalled", + "toHaveBeenCalledWith", + "toMatch", + "toThrow", + "toThrowError" ], matchers = {}; @@ -90,108 +89,104 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) { return matchers; }; -getJasmineRequireObj().base = (function (jasmineGlobal) { - if (typeof module !== 'undefined' && module.exports) { - jasmineGlobal = global; - } - - return function(j$) { - j$.unimplementedMethod_ = function() { - throw new Error('unimplemented method'); - }; +getJasmineRequireObj().base = function(j$) { + j$.unimplementedMethod_ = function() { + throw new Error("unimplemented method"); + }; - j$.MAX_PRETTY_PRINT_DEPTH = 40; - j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100; - j$.DEFAULT_TIMEOUT_INTERVAL = 5000; + j$.MAX_PRETTY_PRINT_DEPTH = 40; + j$.DEFAULT_TIMEOUT_INTERVAL = 5000; - j$.getGlobal = function() { + j$.getGlobal = (function() { + var jasmineGlobal = eval.call(null, "this"); + return function() { return jasmineGlobal; }; + })(); - j$.getEnv = function(options) { - var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options); - //jasmine. singletons in here (setTimeout blah blah). - return env; - }; - - j$.isArray_ = function(value) { - return j$.isA_('Array', value); - }; - - j$.isString_ = function(value) { - return j$.isA_('String', value); - }; + j$.getEnv = function(options) { + var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options); + //jasmine. singletons in here (setTimeout blah blah). + return env; + }; - j$.isNumber_ = function(value) { - return j$.isA_('Number', value); - }; + j$.isArray_ = function(value) { + return j$.isA_("Array", value); + }; - j$.isA_ = function(typeName, value) { - return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; - }; + j$.isString_ = function(value) { + return j$.isA_("String", value); + }; - j$.isDomNode = function(obj) { - return obj.nodeType > 0; - }; + j$.isNumber_ = function(value) { + return j$.isA_("Number", value); + }; - j$.any = function(clazz) { - return new j$.Any(clazz); - }; + j$.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; + }; - j$.objectContaining = function(sample) { - return new j$.ObjectContaining(sample); - }; + j$.isDomNode = function(obj) { + return obj.nodeType > 0; + }; - j$.createSpy = function(name, originalFn) { + j$.any = function(clazz) { + return new j$.Any(clazz); + }; - var spyStrategy = new j$.SpyStrategy({ - name: name, - fn: originalFn, - getSpy: function() { return spy; } - }), - callTracker = new j$.CallTracker(), - spy = function() { - callTracker.track({ - object: this, - args: Array.prototype.slice.apply(arguments) - }); - return spyStrategy.exec.apply(this, arguments); - }; + j$.objectContaining = function(sample) { + return new j$.ObjectContaining(sample); + }; - for (var prop in originalFn) { - if (prop === 'and' || prop === 'calls') { - throw new Error('Jasmine spies would overwrite the \'and\' and \'calls\' properties on the object being spied upon'); - } + j$.createSpy = function(name, originalFn) { + + var spyStrategy = new j$.SpyStrategy({ + name: name, + fn: originalFn, + getSpy: function() { return spy; } + }), + callTracker = new j$.CallTracker(), + spy = function() { + callTracker.track({ + object: this, + args: Array.prototype.slice.apply(arguments) + }); + return spyStrategy.exec.apply(this, arguments); + }; - spy[prop] = originalFn[prop]; + for (var prop in originalFn) { + if (prop === 'and' || prop === 'calls') { + throw new Error("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon"); } - spy.and = spyStrategy; - spy.calls = callTracker; + spy[prop] = originalFn[prop]; + } - return spy; - }; + spy.and = spyStrategy; + spy.calls = callTracker; - j$.isSpy = function(putativeSpy) { - if (!putativeSpy) { - return false; - } - return putativeSpy.and instanceof j$.SpyStrategy && - putativeSpy.calls instanceof j$.CallTracker; - }; + return spy; + }; - j$.createSpyObj = function(baseName, methodNames) { - if (!j$.isArray_(methodNames) || methodNames.length === 0) { - throw 'createSpyObj requires a non-empty array of method names to create spies for'; - } - var obj = {}; - for (var i = 0; i < methodNames.length; i++) { - obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]); - } - return obj; - }; + j$.isSpy = function(putativeSpy) { + if (!putativeSpy) { + return false; + } + return putativeSpy.and instanceof j$.SpyStrategy && + putativeSpy.calls instanceof j$.CallTracker; + }; + + j$.createSpyObj = function(baseName, methodNames) { + if (!j$.isArray_(methodNames) || methodNames.length === 0) { + throw "createSpyObj requires a non-empty array of method names to create spies for"; + } + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]); + } + return obj; }; -})(this); +}; getJasmineRequireObj().util = function() { @@ -225,16 +220,6 @@ getJasmineRequireObj().util = function() { return obj === void 0; }; - util.arrayContains = function(array, search) { - var i = array.length; - while (i--) { - if (array[i] == search) { - return true; - } - } - return false; - }; - return util; }; @@ -253,7 +238,8 @@ getJasmineRequireObj().Spec = function(j$) { this.expectationResultFactory = attrs.expectationResultFactory || function() { }; this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; - this.expectCalled = false; + + this.timer = attrs.timer || {setTimeout: setTimeout, clearTimeout: clearTimeout}; if (!this.fn) { this.pend(); @@ -268,7 +254,6 @@ getJasmineRequireObj().Spec = function(j$) { } Spec.prototype.addExpectationResult = function(passed, data) { - this.expectCalled = true; if (passed) { return; } @@ -280,7 +265,8 @@ getJasmineRequireObj().Spec = function(j$) { }; Spec.prototype.execute = function(onComplete) { - var self = this; + var self = this, + timeout; this.onStart(this); @@ -289,26 +275,52 @@ getJasmineRequireObj().Spec = function(j$) { return; } - var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()); + function timeoutable(fn) { + return function(done) { + timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() { + onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.')); + done(); + }, j$.DEFAULT_TIMEOUT_INTERVAL]]); + + var callDone = function() { + clearTimeoutable(); + done(); + }; + + fn.call(this, callDone); //TODO: do we care about more than 1 arg? + }; + } + + function clearTimeoutable() { + Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]); + timeout = void 0; + } + + var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()), + allTimeoutableFns = []; + for (var i = 0; i < allFns.length; i++) { + var fn = allFns[i]; + allTimeoutableFns.push(fn.length > 0 ? timeoutable(fn) : fn); + } this.queueRunnerFactory({ - fns: allFns, + fns: allTimeoutableFns, onException: onException, - onComplete: complete, - enforceTimeout: function() { return true; } + onComplete: complete }); function onException(e) { + clearTimeoutable(); if (Spec.isPendingSpecException(e)) { self.pend(); return; } self.addExpectationResult(false, { - matcherName: '', + matcherName: "", passed: false, - expected: '', - actual: '', + expected: "", + actual: "", error: e }); } @@ -340,10 +352,6 @@ getJasmineRequireObj().Spec = function(j$) { return 'pending'; } - if(!this.expectCalled) { - return 'empty'; - } - if (this.result.failedExpectations.length > 0) { return 'failed'; } else { @@ -355,16 +363,16 @@ getJasmineRequireObj().Spec = function(j$) { return this.getSpecName(this); }; - Spec.pendingSpecExceptionMessage = '=> marked Pending'; + Spec.pendingSpecExceptionMessage = "=> marked Pending"; Spec.isPendingSpecException = function(e) { - return !!(e && e.toString && e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1); + return e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1; }; return Spec; }; -if (typeof window == void 0 && typeof exports == 'object') { +if (typeof window == void 0 && typeof exports == "object") { exports.Spec = jasmineRequire.Spec; } @@ -381,7 +389,7 @@ getJasmineRequireObj().Env = function(j$) { var realSetTimeout = j$.getGlobal().setTimeout; var realClearTimeout = j$.getGlobal().clearTimeout; - this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler(), new j$.MockDate(global)); + this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler()); var runnableLookupTable = {}; @@ -391,12 +399,12 @@ getJasmineRequireObj().Env = function(j$) { var currentSuite = null; var reporter = new j$.ReportDispatcher([ - 'jasmineStarted', - 'jasmineDone', - 'suiteStarted', - 'suiteDone', - 'specStarted', - 'specDone' + "jasmineStarted", + "jasmineDone", + "suiteStarted", + "suiteDone", + "specStarted", + "specDone" ]); this.specFilter = function() { @@ -506,7 +514,6 @@ getJasmineRequireObj().Env = function(j$) { var queueRunnerFactory = function(options) { options.catchException = catchException; options.clearStack = options.clearStack || clearStack; - options.timer = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}; new j$.QueueRunner(options).execute(); }; @@ -551,7 +558,7 @@ getJasmineRequireObj().Env = function(j$) { this.spyOn = function(obj, methodName) { if (j$.util.isUndefined(obj)) { - throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()'); + throw new Error("spyOn could not find an object to spy upon for " + methodName + "()"); } if (j$.util.isUndefined(obj[methodName])) { @@ -609,7 +616,7 @@ getJasmineRequireObj().Env = function(j$) { } if (declarationError) { - this.it('encountered a declaration exception', function() { + this.it("encountered a declaration exception", function() { throw declarationError; }); } @@ -642,7 +649,8 @@ getJasmineRequireObj().Env = function(j$) { description: description, expectationResultFactory: expectationResultFactory, queueRunnerFactory: queueRunnerFactory, - fn: fn + fn: fn, + timer: {setTimeout: realSetTimeout, clearTimeout: realClearTimeout} }); runnableLookupTable[spec.id] = spec; @@ -715,7 +723,7 @@ getJasmineRequireObj().JsApiReporter = function() { function JsApiReporter(options) { var timer = options.timer || noopTimer, - status = 'loaded'; + status = "loaded"; this.started = false; this.finished = false; @@ -802,7 +810,7 @@ getJasmineRequireObj().Any = function() { if (this.expectedObject == Object) { return typeof other == 'object'; } - + if (this.expectedObject == Boolean) { return typeof other == 'boolean'; } @@ -811,7 +819,7 @@ getJasmineRequireObj().Any = function() { }; Any.prototype.jasmineToString = function() { - return ''; + return ''; }; return Any; @@ -869,7 +877,7 @@ getJasmineRequireObj().CallTracker = function() { }; getJasmineRequireObj().Clock = function() { - function Clock(global, delayedFunctionScheduler, mockDate) { + function Clock(global, delayedFunctionScheduler) { var self = this, realTimingFunctions = { setTimeout: global.setTimeout, @@ -886,32 +894,23 @@ getJasmineRequireObj().Clock = function() { installed = false, timer; - self.install = function() { replace(global, fakeTimingFunctions); timer = fakeTimingFunctions; installed = true; - - return self; }; self.uninstall = function() { delayedFunctionScheduler.reset(); - mockDate.uninstall(); replace(global, realTimingFunctions); - timer = realTimingFunctions; installed = false; }; - self.mockDate = function(initialDate) { - mockDate.install(initialDate); - }; - self.setTimeout = function(fn, delay, params) { if (legacyIE()) { if (arguments.length > 2) { - throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill'); + throw new Error("IE < 9 cannot support extra params to setTimeout without a polyfill"); } return timer.setTimeout(fn, delay); } @@ -921,7 +920,7 @@ getJasmineRequireObj().Clock = function() { self.setInterval = function(fn, delay, params) { if (legacyIE()) { if (arguments.length > 2) { - throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill'); + throw new Error("IE < 9 cannot support extra params to setInterval without a polyfill"); } return timer.setInterval(fn, delay); } @@ -938,10 +937,9 @@ getJasmineRequireObj().Clock = function() { self.tick = function(millis) { if (installed) { - mockDate.tick(millis); delayedFunctionScheduler.tick(millis); } else { - throw new Error('Mock clock is not installed, use jasmine.clock().install()'); + throw new Error("Mock clock is not installed, use jasmine.clock().install()"); } }; @@ -1131,20 +1129,16 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() { getJasmineRequireObj().ExceptionFormatter = function() { function ExceptionFormatter() { this.message = function(error) { - var message = ''; - - if (error.name && error.message) { - message += error.name + ': ' + error.message; - } else { - message += error.toString() + ' thrown'; - } + var message = error.name + + ': ' + + error.message; if (error.fileName || error.sourceURL) { - message += ' in ' + (error.fileName || error.sourceURL); + message += " in " + (error.fileName || error.sourceURL); } if (error.line || error.lineNumber) { - message += ' (line ' + (error.line || error.lineNumber) + ')'; + message += " (line " + (error.line || error.lineNumber) + ")"; } return message; @@ -1178,7 +1172,7 @@ getJasmineRequireObj().Expectation = function() { return function() { var args = Array.prototype.slice.call(arguments, 0), expected = args.slice(0), - message = ''; + message = ""; args.unshift(this.actual); @@ -1203,11 +1197,7 @@ getJasmineRequireObj().Expectation = function() { args.unshift(name); message = this.util.buildFailureMessage.apply(null, args); } else { - if (Object.prototype.toString.apply(result.message) === '[object Function]') { - message = result.message(); - } else { - message = result.message; - } + message = result.message; } } @@ -1283,18 +1273,18 @@ getJasmineRequireObj().buildExpectationResult = function() { function message() { if (options.passed) { - return 'Passed.'; + return "Passed."; } else if (options.message) { return options.message; } else if (options.error) { return messageFormatter(options.error); } - return ''; + return ""; } function stack() { if (options.passed) { - return ''; + return ""; } var error = options.error; @@ -1312,73 +1302,6 @@ getJasmineRequireObj().buildExpectationResult = function() { return buildExpectationResult; }; -getJasmineRequireObj().MockDate = function() { - function MockDate(global) { - var self = this; - var currentTime = 0; - - if (!global || !global.Date) { - self.install = function() {}; - self.tick = function() {}; - self.uninstall = function() {}; - return self; - } - - var GlobalDate = global.Date; - - self.install = function(mockDate) { - if (mockDate instanceof GlobalDate) { - currentTime = mockDate.getTime(); - } else { - currentTime = new GlobalDate().getTime(); - } - - global.Date = FakeDate; - }; - - self.tick = function(millis) { - millis = millis || 0; - currentTime = currentTime + millis; - }; - - self.uninstall = function() { - currentTime = 0; - global.Date = GlobalDate; - }; - - createDateProperties(); - - return self; - - function FakeDate() { - if (arguments.length === 0) { - return new GlobalDate(currentTime); - } else { - return new GlobalDate(arguments[0], arguments[1], arguments[2], - arguments[3], arguments[4], arguments[5], arguments[6]); - } - } - - function createDateProperties() { - - FakeDate.now = function() { - if (GlobalDate.now) { - return currentTime; - } else { - throw new Error('Browser does not support Date.now()'); - } - }; - - FakeDate.toSource = GlobalDate.toSource; - FakeDate.toString = GlobalDate.toString; - FakeDate.parse = GlobalDate.parse; - FakeDate.UTC = GlobalDate.UTC; - } - } - - return MockDate; -}; - getJasmineRequireObj().ObjectContaining = function(j$) { function ObjectContaining(sample) { @@ -1386,7 +1309,7 @@ getJasmineRequireObj().ObjectContaining = function(j$) { } ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) { - if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); } + if (typeof(this.sample) !== "object") { throw new Error("You must provide an object to objectContaining, not '"+this.sample+"'."); } mismatchKeys = mismatchKeys || []; mismatchValues = mismatchValues || []; @@ -1397,10 +1320,10 @@ getJasmineRequireObj().ObjectContaining = function(j$) { for (var property in this.sample) { if (!hasKey(other, property) && hasKey(this.sample, property)) { - mismatchKeys.push('expected has key \'' + property + '\', but missing from actual.'); + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); } - else if (!j$.matchersUtil.equals(other[property], this.sample[property])) { - mismatchValues.push('\'' + property + '\' was \'' + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + '\' in actual, but was \'' + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + '\' in expected.'); + else if (!j$.matchersUtil.equals(this.sample[property], other[property])) { + mismatchValues.push("'" + property + "' was '" + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + "' in actual, but was '" + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in expected."); } } @@ -1408,7 +1331,7 @@ getJasmineRequireObj().ObjectContaining = function(j$) { }; ObjectContaining.prototype.jasmineToString = function() { - return ''; + return ""; }; return ObjectContaining; @@ -1418,7 +1341,6 @@ getJasmineRequireObj().pp = function(j$) { function PrettyPrinter() { this.ppNestLevel_ = 0; - this.seen = []; } PrettyPrinter.prototype.format = function(value) { @@ -1428,8 +1350,6 @@ getJasmineRequireObj().pp = function(j$) { this.emitScalar('undefined'); } else if (value === null) { this.emitScalar('null'); - } else if (value === 0 && 1/value === -Infinity) { - this.emitScalar('-0'); } else if (value === j$.getGlobal()) { this.emitScalar(''); } else if (value.jasmineToString) { @@ -1437,7 +1357,7 @@ getJasmineRequireObj().pp = function(j$) { } else if (typeof value === 'string') { this.emitString(value); } else if (j$.isSpy(value)) { - this.emitScalar('spy on ' + value.and.identity()); + this.emitScalar("spy on " + value.and.identity()); } else if (value instanceof RegExp) { this.emitScalar(value.toString()); } else if (typeof value === 'function') { @@ -1446,16 +1366,16 @@ getJasmineRequireObj().pp = function(j$) { this.emitScalar('HTMLNode'); } else if (value instanceof Date) { this.emitScalar('Date(' + value + ')'); - } else if (j$.util.arrayContains(this.seen, value)) { + } else if (value.__Jasmine_been_here_before__) { this.emitScalar(''); } else if (j$.isArray_(value) || j$.isA_('Object', value)) { - this.seen.push(value); + value.__Jasmine_been_here_before__ = true; if (j$.isArray_(value)) { this.emitArray(value); } else { this.emitObject(value); } - this.seen.pop(); + delete value.__Jasmine_been_here_before__; } else { this.emitScalar(value.toString()); } @@ -1466,7 +1386,8 @@ getJasmineRequireObj().pp = function(j$) { PrettyPrinter.prototype.iterateObject = function(obj, fn) { for (var property in obj) { - if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; } + if (!obj.hasOwnProperty(property)) { continue; } + if (property == '__Jasmine_been_here_before__') { continue; } fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && obj.__lookupGetter__(property) !== null) : false); } @@ -1490,31 +1411,28 @@ getJasmineRequireObj().pp = function(j$) { }; StringPrettyPrinter.prototype.emitString = function(value) { - this.append('\'' + value + '\''); + this.append("'" + value + "'"); }; StringPrettyPrinter.prototype.emitArray = function(array) { if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { - this.append('Array'); + this.append("Array"); return; } - var length = Math.min(array.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); + this.append('[ '); - for (var i = 0; i < length; i++) { + for (var i = 0; i < array.length; i++) { if (i > 0) { this.append(', '); } this.format(array[i]); } - if(array.length > length){ - this.append(', ...'); - } this.append(' ]'); }; StringPrettyPrinter.prototype.emitObject = function(obj) { if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { - this.append('Object'); + this.append("Object"); return; } @@ -1530,7 +1448,7 @@ getJasmineRequireObj().pp = function(j$) { } self.append(property); - self.append(': '); + self.append(' : '); if (isGetter) { self.append(''); } else { @@ -1552,17 +1470,7 @@ getJasmineRequireObj().pp = function(j$) { }; }; -getJasmineRequireObj().QueueRunner = function(j$) { - - function once(fn) { - var called = false; - return function() { - if (!called) { - called = true; - fn(); - } - }; - } +getJasmineRequireObj().QueueRunner = function() { function QueueRunner(attrs) { this.fns = attrs.fns || []; @@ -1570,9 +1478,7 @@ getJasmineRequireObj().QueueRunner = function(j$) { this.clearStack = attrs.clearStack || function(fn) {fn();}; this.onException = attrs.onException || function() {}; this.catchException = attrs.catchException || function() { return true; }; - this.enforceTimeout = attrs.enforceTimeout || function() { return false; }; this.userContext = {}; - this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; } QueueRunner.prototype.execute = function() { @@ -1608,21 +1514,7 @@ getJasmineRequireObj().QueueRunner = function(j$) { } function attemptAsync(fn) { - var clearTimeout = function () { - Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeoutId]]); - }, - next = once(function () { - clearTimeout(timeoutId); - self.run(fns, iterativeIndex + 1); - }), - timeoutId; - - if (self.enforceTimeout()) { - timeoutId = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() { - self.onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.')); - next(); - }, j$.DEFAULT_TIMEOUT_INTERVAL]]); - } + var next = function () { self.run(fns, iterativeIndex + 1); }; try { fn.call(self.userContext, next); @@ -1686,7 +1578,7 @@ getJasmineRequireObj().SpyStrategy = function() { function SpyStrategy(options) { options = options || {}; - var identity = options.name || 'unknown', + var identity = options.name || "unknown", originalFn = options.fn || function() {}, getSpy = options.getSpy || function() {}, plan = function() {}; @@ -1820,20 +1712,16 @@ getJasmineRequireObj().Suite = function() { return Suite; }; -if (typeof window == void 0 && typeof exports == 'object') { +if (typeof window == void 0 && typeof exports == "object") { exports.Suite = jasmineRequire.Suite; } getJasmineRequireObj().Timer = function() { - var defaultNow = (function(Date) { - return function() { return new Date().getTime(); }; - })(Date); - function Timer(options) { options = options || {}; - var now = options.now || defaultNow, - startTime; + var now = options.now || function() { return new Date().getTime(); }, + startTime; this.start = function() { startTime = now(); @@ -1860,7 +1748,7 @@ getJasmineRequireObj().matchersUtil = function(j$) { contains: function(haystack, needle, customTesters) { customTesters = customTesters || []; - if (Object.prototype.toString.apply(haystack) === '[object Array]') { + if (Object.prototype.toString.apply(haystack) === "[object Array]") { for (var i = 0; i < haystack.length; i++) { if (eq(haystack[i], needle, [], [], customTesters)) { return true; @@ -1879,21 +1767,21 @@ getJasmineRequireObj().matchersUtil = function(j$) { expected = args.slice(3), englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); - var message = 'Expected ' + + var message = "Expected " + j$.pp(actual) + - (isNot ? ' not ' : ' ') + + (isNot ? " not " : " ") + englishyPredicate; if (expected.length > 0) { for (var i = 0; i < expected.length; i++) { if (i > 0) { - message += ','; + message += ","; } - message += ' ' + j$.pp(expected[i]); + message += " " + j$.pp(expected[i]); } } - return message + '.'; + return message + "."; } }; @@ -2130,9 +2018,9 @@ getJasmineRequireObj().toBeNaN = function(j$) { }; if (result.pass) { - result.message = 'Expected actual not to be NaN.'; + result.message = "Expected actual not to be NaN."; } else { - result.message = function() { return 'Expected ' + j$.pp(actual) + ' to be NaN.'; }; + result.message = "Expected " + j$.pp(actual) + " to be NaN."; } return result; @@ -2244,8 +2132,8 @@ getJasmineRequireObj().toHaveBeenCalled = function(j$) { result.pass = actual.calls.any(); result.message = result.pass ? - 'Expected spy ' + actual.and.identity() + ' not to have been called.' : - 'Expected spy ' + actual.and.identity() + ' to have been called.'; + "Expected spy " + actual.and.identity() + " not to have been called." : + "Expected spy " + actual.and.identity() + " to have been called."; return result; } @@ -2257,7 +2145,7 @@ getJasmineRequireObj().toHaveBeenCalled = function(j$) { getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { - function toHaveBeenCalledWith(util, customEqualityTesters) { + function toHaveBeenCalledWith(util) { return { compare: function() { var args = Array.prototype.slice.call(arguments, 0), @@ -2270,15 +2158,15 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { } if (!actual.calls.any()) { - result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but it was never called.'; }; + result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but it was never called."; return result; } - if (util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) { + if (util.contains(actual.calls.allArgs(), expectedArgs)) { result.pass = true; - result.message = function() { return 'Expected spy ' + actual.and.identity() + ' not to have been called with ' + j$.pp(expectedArgs) + ' but it was.'; }; + result.message = "Expected spy " + actual.and.identity() + " not to have been called with " + j$.pp(expectedArgs) + " but it was."; } else { - result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but actual calls were ' + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + '.'; }; + result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but actual calls were " + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + "."; } return result; @@ -2315,8 +2203,8 @@ getJasmineRequireObj().toThrow = function(j$) { threw = false, thrown; - if (typeof actual != 'function') { - throw new Error('Actual is not a Function'); + if (typeof actual != "function") { + throw new Error("Actual is not a Function"); } try { @@ -2327,22 +2215,22 @@ getJasmineRequireObj().toThrow = function(j$) { } if (!threw) { - result.message = 'Expected function to throw an exception.'; + result.message = "Expected function to throw an exception."; return result; } if (arguments.length == 1) { result.pass = true; - result.message = function() { return 'Expected function not to throw, but it threw ' + j$.pp(thrown) + '.'; }; + result.message = "Expected function not to throw, but it threw " + j$.pp(thrown) + "."; return result; } if (util.equals(thrown, expected)) { result.pass = true; - result.message = function() { return 'Expected function not to throw ' + j$.pp(expected) + '.'; }; + result.message = "Expected function not to throw " + j$.pp(expected) + "."; } else { - result.message = function() { return 'Expected function to throw ' + j$.pp(expected) + ', but it threw ' + j$.pp(thrown) + '.'; }; + result.message = "Expected function to throw " + j$.pp(expected) + ", but it threw " + j$.pp(thrown) + "."; } return result; @@ -2358,8 +2246,6 @@ getJasmineRequireObj().toThrowError = function(j$) { return { compare: function(actual) { var threw = false, - pass = {pass: true}, - fail = {pass: false}, thrown, errorType, message, @@ -2367,8 +2253,8 @@ getJasmineRequireObj().toThrowError = function(j$) { name, constructorName; - if (typeof actual != 'function') { - throw new Error('Actual is not a Function'); + if (typeof actual != "function") { + throw new Error("Actual is not a Function"); } extractExpectedParams.apply(null, arguments); @@ -2381,18 +2267,15 @@ getJasmineRequireObj().toThrowError = function(j$) { } if (!threw) { - fail.message = 'Expected function to throw an Error.'; - return fail; + return fail("Expected function to throw an Error."); } if (!(thrown instanceof Error)) { - fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; }; - return fail; + return fail("Expected function to throw an Error, but it threw " + thrown + "."); } if (arguments.length == 1) { - pass.message = 'Expected function not to throw an Error, but it threw ' + fnNameFor(thrown) + '.'; - return pass; + return pass("Expected function not to throw an Error, but it threw " + fnNameFor(thrown) + "."); } if (errorType) { @@ -2402,55 +2285,45 @@ getJasmineRequireObj().toThrowError = function(j$) { if (errorType && message) { if (thrown.constructor == errorType && util.equals(thrown.message, message)) { - pass.message = function() { return 'Expected function not to throw ' + name + ' with message ' + j$.pp(message) + '.'; }; - return pass; + return pass("Expected function not to throw " + name + " with message \"" + message + "\"."); } else { - fail.message = function() { return 'Expected function to throw ' + name + ' with message ' + j$.pp(message) + - ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; }; - return fail; + return fail("Expected function to throw " + name + " with message \"" + message + + "\", but it threw " + constructorName + " with message \"" + thrown.message + "\"."); } } if (errorType && regexp) { if (thrown.constructor == errorType && regexp.test(thrown.message)) { - pass.message = function() { return 'Expected function not to throw ' + name + ' with message matching ' + j$.pp(regexp) + '.'; }; - return pass; + return pass("Expected function not to throw " + name + " with message matching " + regexp + "."); } else { - fail.message = function() { return 'Expected function to throw ' + name + ' with message matching ' + j$.pp(regexp) + - ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; }; - return fail; + return fail("Expected function to throw " + name + " with message matching " + regexp + + ", but it threw " + constructorName + " with message \"" + thrown.message + "\"."); } } if (errorType) { if (thrown.constructor == errorType) { - pass.message = 'Expected function not to throw ' + name + '.'; - return pass; + return pass("Expected function not to throw " + name + "."); } else { - fail.message = 'Expected function to throw ' + name + ', but it threw ' + constructorName + '.'; - return fail; + return fail("Expected function to throw " + name + ", but it threw " + constructorName + "."); } } if (message) { if (thrown.message == message) { - pass.message = function() { return 'Expected function not to throw an exception with message ' + j$.pp(message) + '.'; }; - return pass; + return pass("Expected function not to throw an exception with message " + j$.pp(message) + "."); } else { - fail.message = function() { return 'Expected function to throw an exception with message ' + j$.pp(message) + - ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; }; - return fail; + return fail("Expected function to throw an exception with message " + j$.pp(message) + + ", but it threw an exception with message " + j$.pp(thrown.message) + "."); } } if (regexp) { if (regexp.test(thrown.message)) { - pass.message = function() { return 'Expected function not to throw an exception with a message matching ' + j$.pp(regexp) + '.'; }; - return pass; + return pass("Expected function not to throw an exception with a message matching " + j$.pp(regexp) + "."); } else { - fail.message = function() { return 'Expected function to throw an exception with a message matching ' + j$.pp(regexp) + - ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; }; - return fail; + return fail("Expected function to throw an exception with a message matching " + j$.pp(regexp) + + ", but it threw an exception with message " + j$.pp(thrown.message) + "."); } } @@ -2458,6 +2331,20 @@ getJasmineRequireObj().toThrowError = function(j$) { return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1]; } + function pass(notMessage) { + return { + pass: true, + message: notMessage + }; + } + + function fail(message) { + return { + pass: false, + message: message + }; + } + function extractExpectedParams() { if (arguments.length == 1) { return; @@ -2468,34 +2355,34 @@ getJasmineRequireObj().toThrowError = function(j$) { if (expected instanceof RegExp) { regexp = expected; - } else if (typeof expected == 'string') { + } else if (typeof expected == "string") { message = expected; } else if (checkForAnErrorType(expected)) { errorType = expected; } if (!(errorType || message || regexp)) { - throw new Error('Expected is not an Error, string, or RegExp.'); + throw new Error("Expected is not an Error, string, or RegExp."); } } else { if (checkForAnErrorType(arguments[1])) { errorType = arguments[1]; } else { - throw new Error('Expected error type is not an Error.'); + throw new Error("Expected error type is not an Error."); } if (arguments[2] instanceof RegExp) { regexp = arguments[2]; - } else if (typeof arguments[2] == 'string') { + } else if (typeof arguments[2] == "string") { message = arguments[2]; } else { - throw new Error('Expected error message is not a string or RegExp.'); + throw new Error("Expected error message is not a string or RegExp."); } } } function checkForAnErrorType(type) { - if (typeof type !== 'function') { + if (typeof type !== "function") { return false; } @@ -2511,5 +2398,5 @@ getJasmineRequireObj().toThrowError = function(j$) { }; getJasmineRequireObj().version = function() { - return '2.0.0'; -}; \ No newline at end of file + return "2.0.0"; +}; diff --git a/vendor/assets/stylesheets/jasmine.css b/vendor/assets/stylesheets/jasmine.css old mode 100644 new mode 100755 index 68e4c9e..f4d35b6 --- a/vendor/assets/stylesheets/jasmine.css +++ b/vendor/assets/stylesheets/jasmine.css @@ -5,10 +5,7 @@ body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } .html-reporter a:hover { text-decoration: underline; } .html-reporter p, .html-reporter h1, .html-reporter h2, .html-reporter h3, .html-reporter h4, .html-reporter h5, .html-reporter h6 { margin: 0; line-height: 14px; } .html-reporter .banner, .html-reporter .symbol-summary, .html-reporter .summary, .html-reporter .result-message, .html-reporter .spec .description, .html-reporter .spec-detail .description, .html-reporter .alert .bar, .html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; } -.html-reporter .banner { position: relative; } -.html-reporter .banner .title { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAZCAYAAACxZDnAAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAB2AAAAdgB+lymcgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAk/SURBVGiB7Zp/cFTVFcc/577NskmAIII4CAW15YcitlSYaVVgN0SxtoJYwfqrTnVqGY3Dj93ww2zWzSKQZCmoUNGOVipiW0dRaqMCuwtYtfVnFS1i2wEtM4oC8iu/Ntl7+se+DUlARGdIh5bvzJu57+5595zzffeec+59K6rKSRx/mP+2Af8v8HwV4aqS6DdIm6JGY7dEUpGW42XU/yLkaKEjfmm8kObGGYpeBIwAerk/NQDvgL6OmMWhRPm/OsHWExpfSHRV8d3fd9SuUPim26UK/xBlH8J5gM/tr0MkFEqU398ZBp+oOCLRNYFYBRAhG8M3ispdttn7Rtmfyw4ARP1RT6HDOWrlJpBpgABrJS9/UvCFYF0n2n/C4LAYHQ9UXg4SBRpB5oZS5UtQFKDGH1uL4M03nrLg+jtfBWbE/fPWqOgjwCU0N1QDt3WqBycI2hG9xB/toWIeBBC4OZgsX1VTHAvmjXYem7Zp7scIo4EuYrUnQDxQWV03Vmd33eQZY9VuVphaHah8qixZkeioqDpQWSzIsrZ9Ru1FM1ORXcfRvy9FTSCWAOkVSpaffzz1tCvv0uJUA31RVgeT4VUAWLuy2WMXR6PRdrLVxbFfWOXtSCRiZybu/BAIAiLIw1F/1EcHiJo84FRgMDAI6JHOeOX4uPWVcDbo4OOtpN2MFnQikGl2nKmLxsVGZjIyoKEbtQUH+W3XTXKpdeVU8GIZXLahYkZ8XOx7qjowlKx4sMYfuwVhZD6ebwN/aTt2KFX+/EJ/dKQjZhuwP5QMn9729/il0dPImLNx8t8Jrg3W14yN9gFocbzNc9bP2Q2wYNyCU/NIn1HXk/cLPqNnfW/2dN9P15YmvM1Ons5dP3dnVUlVUV46fdaMTeG/5UJe1B/1FYo5v4vPbimtjexvpxNznRHjAESviBYUHKA7gHgLDwTXBusXFUeHop46dzIdhoX+6ECPcc5qbnY2z9k057MvIro1GS4qvnuAVbsdeC+UDA+rCcRWADcCdSDPirJcRaer0F+tvUPEXClwNdAf2FOvtk+BkYWozETl9lCqfFlHZQv90YEu0ftCyXAPyNbmJmMeBopdsbSo3KGiy7Mvn7cH9Bry3e273n8SuJzs5HgPOBeVyxCdDYwBmhRmCNzjyvw749ixTsaMBZYC+UCTCsGyRHgpQE0gthcoAppCybAvXhybpspiAIV7gfGSXX2grGtxPD/JvfS4PzpMxVkBOuIQm6z0dbG3tX2ZObSGA6uZC7Ky8qbb5QGagULQKSq2KpQMTyhLhEeIOBcLzHBJBmSHz0NfUfdZaaP8KIheES0wGbPBJflzhJXAXhXNlYp7EX1+++4tk4AJwAZRKUHahbwk8AngFbgP5UXgI6C/kzFrgeUo74K+DnQR5Z6aMfO+5T77JFB/iCfdCvpqtk0p0A3hWcAilHhscxRac9l60GEgj4swHSWFcn1jo/n9kXxtY7AMBlDRDwBCyfB1eWpPU9WbgDW0SWRWM08A6xWZS0YGhZLl589aF/nIqvnANXjQsRBdcNDcDpwJrK/vavuFEuEb6nvZ/ihPu85+GExUzBYro10mDnbJL3oxk867MKP2TE9T4cZQMlwp8DYgKroglAoHPI1dhyBsBs4GfhNKhUeFkhUjQR4HDI5e7Pp4M9C63GcmKp5DxX3J+ka+r8eZoUT4R6hMcOm6ECBtZBrQB5WyULL82mAivCSUCgcEngLGx4vnBY5CtG4la+0ggMXFd5+RNuZ6EblE01IG8oOqQOzc6ouquzkiQSP6SyO2SAyTF/mjQwCM2EEAinxwLEQjXAwgovdG1kTqASJ/iKStMfF2cg6rgEaUiU2Ne3c5ec1LHDEDpr88vaGdMyp/BJj+8vQGUXk965YmWz1U3sg2pNsx2PZSaW1pE0A9mQ3uCNkkb2WUe395PBB7PnepZle4oqM6DncodDj6mis0AqAFnSTKWwN7DblRvLoMdIpBVpq89AyQW63KY6bFWQaZZ6yYyVUlVUXqhgzFdaijMnG65NRl7cSbJcBk2sp5OiTp4PrwK0bMEKBSYQ/Z3LEhHohd21auRe3OXFvFunHS7DtkgNYBiNFjqHbkk1wrkooczHVCtrRy79pVYiLsEXhB0Z10QKvgrHWRj4BPgSHzx83vE0qU3xdKhl/atmtrGW6iEqNVOLoW2Amc0uJkVtaN5e+hZLhy1rpZ+3CXuHGJrimO/bomENOa4tijWUPscNfa3QCK/tWlZXquJIxOjnotdnpbI6vGxM6zVodKnl0WSoUHgj4AoMqPv5yw44JXAARqg8nw+Nxl0RqrsryhUA+L0+224DWByl+BTEVZHUqFJ7mVyD8BjyhLFfuQGDNW0K1W5U+AiOotwVTFQzWB2M+BB4BtPl+PoaW1pU1xf+waFR53h38JGAl4EV0USlQEq0qqikwm/S7QD9gtSK2i44He7jN7RfQB1Jyu6E+BNUbtLCtmHnCVKktE+ByYCpyO8KzB3K42M86KlLkVw0ZVE0S0r2DDIBeo8BYqdwk6AbgG8IE8YcSusMpdIKNA3lEl1uPAac/s6/7po6BTgAOgq3w+LWtsNO8CfUBWq+gGFL/AZODBUDJ8a0ei2019n09nAzsQrowHYtfOTNz5oapcDWysw4ZycjMTFc+pcg8wf0DvoY8sKr57ABAHVFR+lottwVT4dyJaBWSACwEvympfF60EmLVu1j4yEkB5DThV0RuAIhVKXVU9UBnvtncAw62YLcBEIJnJeOYDASBbkys/tLblFBVGtpZlMAa0n4ieA5KtrJTvZO+5CijI8qBTFBmcJRlAh2PssI+7fey4JAN0A5lYWhvZn1EbAF4DnSLK/QIlijxU38vmbG+Hww6VFhVXXmZVajnCWcfCkuhZpsUZXpYqfzonH/fPG+uedQwQZWkwFT5M0YLRC3obxw4WWraXpSI7jmRIVUn0G46aM+oydnNkQ6Su7YbFiGnxOo0O+7s3ZHwHh5NntwVfiHwKsHh8tGdLUzbWA9TDrp75FDQ2UJDr8+X3/Lwp0+TRdF1rEhRv4QGoK9T0oclW3439uQ2LO9bBSCpysMYfbd1ctWS8mbYbk+pLon3JePo12JY3j3ZGf/L0rpNw8jy6k3DyC0sn4ahEd8TJb4ZfH1+J6JP4+jj5d4NOwn8AQAAydN2xotAAAAAASUVORK5CYII=') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -webkit-background-size: 100%; -moz-background-size: 100%; -o-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; } -.html-reporter .banner .version { margin-left: 14px; position: relative; top: 6px; } -.html-reporter .banner .duration { position: absolute; right: 14px; top: 6px; } +.html-reporter .banner .version { margin-left: 14px; } .html-reporter #jasmine_content { position: fixed; right: 100%; } .html-reporter .version { color: #aaaaaa; } .html-reporter .banner { margin-top: 14px; } @@ -16,17 +13,17 @@ body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } .html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; } .html-reporter .symbol-summary li { display: inline-block; height: 8px; width: 14px; font-size: 16px; } .html-reporter .symbol-summary li.passed { font-size: 14px; } -.html-reporter .symbol-summary li.passed:before { color: #007069; content: "\02022"; } +.html-reporter .symbol-summary li.passed:before { color: #5e7d00; content: "\02022"; } .html-reporter .symbol-summary li.failed { line-height: 9px; } -.html-reporter .symbol-summary li.failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; } +.html-reporter .symbol-summary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; } .html-reporter .symbol-summary li.disabled { font-size: 14px; } .html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; } .html-reporter .symbol-summary li.pending { line-height: 17px; } .html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; } .html-reporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; } .html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } -.html-reporter .bar.failed { background-color: #ca3a11; } -.html-reporter .bar.passed { background-color: #007069; } +.html-reporter .bar.failed { background-color: #b03911; } +.html-reporter .bar.passed { background-color: #a6b779; } .html-reporter .bar.skipped { background-color: #bababa; } .html-reporter .bar.menu { background-color: #fff; color: #aaaaaa; } .html-reporter .bar.menu a { color: #333333; } @@ -44,16 +41,15 @@ body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } .html-reporter .summary { margin-top: 14px; } .html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; } .html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; } -.html-reporter .summary li.passed a { color: #007069; } -.html-reporter .summary li.failed a { color: #ca3a11; } -.html-reporter .summary li.empty a { color: #ba9d37; } +.html-reporter .summary li.passed a { color: #5e7d00; } +.html-reporter .summary li.failed a { color: #b03911; } .html-reporter .summary li.pending a { color: #ba9d37; } .html-reporter .description + .suite { margin-top: 0; } .html-reporter .suite { margin-top: 14px; } .html-reporter .suite a { color: #333333; } .html-reporter .failures .spec-detail { margin-bottom: 28px; } -.html-reporter .failures .spec-detail .description { background-color: #ca3a11; } +.html-reporter .failures .spec-detail .description { background-color: #b03911; } .html-reporter .failures .spec-detail .description a { color: white; } .html-reporter .result-message { padding-top: 14px; color: #333333; white-space: pre; } .html-reporter .result-message span.result { display: block; } -.html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } \ No newline at end of file +.html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } From 63c88e3a6f356512657357ae195b14d8389be21a Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Mon, 16 Jun 2014 14:28:51 +1000 Subject: [PATCH 07/16] Removed unneeded code now taken care of by the jasmine boot.js Added in explicit require for jquery to ensure it is loaded prior to jasmine-jquery --- app/assets/javascripts/jasminerice.js.coffee | 32 +++----------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/app/assets/javascripts/jasminerice.js.coffee b/app/assets/javascripts/jasminerice.js.coffee index 6ebd3f7..595da94 100644 --- a/app/assets/javascripts/jasminerice.js.coffee +++ b/app/assets/javascripts/jasminerice.js.coffee @@ -1,33 +1,11 @@ #=require jasmine #=require jasmine-html #=require boot +#=require jquery #=require jasmine-jquery.js -(-> - execJasmine = -> - jasmineEnv.execute() - jasmineEnv = jasmine.getEnv() - jasmineEnv.updateInterval = 1000 +# Override the fixture paths +jasmine.getFixtures().fixturesPath = 'jasmine/fixtures' +jasmine.getStyleFixtures().fixturesPath = 'jasmine/fixtures' +jasmine.getJSONFixtures().fixturesPath = 'jasmine/fixtures/json' - window.jsApiReporter = new jasmine.JsApiReporter() - htmlReporter = new jasmine.HtmlReporter() - - jasmineEnv.addReporter htmlReporter - jasmineEnv.addReporter jsApiReporter - - jasmineEnv.specFilter = (spec) -> - htmlReporter.specFilter spec - - jasmine.getFixtures().fixturesPath = 'jasmine/fixtures' - jasmine.getStyleFixtures().fixturesPath = 'jasmine/fixtures' - jasmine.getJSONFixtures().fixturesPath = 'jasmine/fixtures/json' - - jasmine.rice = {} - jasmine.rice.autoExecute = true - - currentWindowOnload = window.onload - window.onload = -> - currentWindowOnload() if currentWindowOnload - if jasmine.rice.autoExecute - execJasmine() -)() From 70b456618f285169d5414d1263bf04ac677cb2ec Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Mon, 16 Jun 2014 14:31:11 +1000 Subject: [PATCH 08/16] Changed version to denote the major change to jasmine 2.0 --- Gemfile.lock | 2 +- jasminerice.gemspec | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 89b71e4..1376012 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - jasminerice (0.1.0) + jasminerice (2.0.0) coffee-rails GEM diff --git a/jasminerice.gemspec b/jasminerice.gemspec index 8d9d895..5974c00 100644 --- a/jasminerice.gemspec +++ b/jasminerice.gemspec @@ -2,10 +2,10 @@ # project in your rails apps through git. Gem::Specification.new do |s| s.name = "jasminerice" - s.version = "0.1.0" + s.version = "2.0.0" s.authors = ["Brad Phelan"] - s.summary = "Pain free coffeescript unit testing for Rails 3.1 using jasmine" - s.description = "Full support for the Rails 3.1 asset pipeline when bdd'ing your coffeescript or javascript using jasmine" + s.summary = "Pain free coffeescript unit testing for Rails using jasmine" + s.description = "Full support for the Rails asset pipeline when bdd'ing your coffeescript or javascript using jasmine" s.platform = Gem::Platform::RUBY s.files = Dir["{app,config,lib,vendor}/**/*"] + ["MIT.LICENSE", "README.md"] From 70c51b27a23d831ee6e55a0598289122006468bc Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Mon, 11 Aug 2014 19:48:23 +1000 Subject: [PATCH 09/16] Refactored testing added checks for missing files foo.js.coffee and bar.js.coffee --- spec/features/install_generator_spec.rb | 32 +++++++++++++------------ 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/spec/features/install_generator_spec.rb b/spec/features/install_generator_spec.rb index 70bf80f..16dacc9 100644 --- a/spec/features/install_generator_spec.rb +++ b/spec/features/install_generator_spec.rb @@ -1,6 +1,17 @@ require "spec_helper" feature "Installing Jasminerice", :aruba => true do + let(:file_names) do + [ + 'config/initializers/jasminerice.rb', + 'spec/javascripts/spec.js.coffee', + 'spec/javascripts/example_spec.js.coffee', + 'spec/javascripts/spec.css', + 'spec/javascripts/fixtures/example_fixture.html.haml', + 'app/assets/javascripts/foo.js.coffee', + 'app/assets/javascripts/bar.js.coffee' + ] + end before do unset_bundler_env_vars @@ -8,22 +19,13 @@ cd("testapp") append_to_file("Gemfile", %{\ngem "jasminerice", :path => "#{File.expand_path('../../../', __FILE__)}"\n}) run_simple("bundle install --local") + run_simple('bundle exec rails generate jasminerice:install --trace') end - scenario "installs the expected files" do - run_simple("bundle exec rails generate jasminerice:install --trace") - expected = <<-OUTPUT - create config/initializers/jasminerice.rb - create spec/javascripts/spec.js.coffee - create spec/javascripts/example_spec.js.coffee - create spec/javascripts/spec.css - create spec/javascripts/fixtures/example_fixture.html.haml - OUTPUT - assert_partial_output(expected, all_output) - check_file_presence(["config/initializers/jasminerice.rb"], true) - check_file_presence(["spec/javascripts/spec.js.coffee"], true) - check_file_presence(["spec/javascripts/example_spec.js.coffee"], true) - check_file_presence(["spec/javascripts/spec.css"], true) - check_file_presence(["spec/javascripts/fixtures/example_fixture.html.haml"], true) + context "when installing" do + it('will install the files') do + file_names.each { |name| check_file_presence([name], true) } + file_names.each { |name| expect(all_output).to include "create #{name}" } + end end end From 761f0b22aa0aa7b2fb1fb983cd6174658f5661c0 Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Mon, 11 Aug 2014 21:12:27 +1000 Subject: [PATCH 10/16] Updated rails to 3.2.18 Updated rspec-rails to 3.0.2 Updated selenium-webdriver --- Gemfile | 15 +- Gemfile.lock | 233 ++++++++++++++-------------- spec/features/html_reporter_spec.rb | 12 +- spec/spec_helper.rb | 4 +- 4 files changed, 135 insertions(+), 129 deletions(-) diff --git a/Gemfile b/Gemfile index 4a572a8..2561d29 100644 --- a/Gemfile +++ b/Gemfile @@ -1,22 +1,23 @@ -source "http://rubygems.org" +source 'http://rubygems.org' gemspec # used by the dummy application -gem 'rails', '3.1.0' +gem 'rails', '3.2.18' gem 'json' -gem 'coffee-rails', "~> 3.1.0" +gem 'coffee-rails' gem 'haml-rails' # used by test rails apps gem 'sqlite3' -gem 'sass-rails', "~> 3.1.0" +gem 'sass-rails' gem 'uglifier' gem 'jquery-rails' gem 'turn', :require => false, :group => :test group :development, :test do - gem "rspec-rails" - gem "capybara" - gem "aruba" + gem 'rspec-rails', '~>3.0.0' + gem 'capybara' + gem 'selenium-webdriver' + gem 'aruba' end diff --git a/Gemfile.lock b/Gemfile.lock index 1376012..eb676c1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,165 +7,169 @@ PATH GEM remote: http://rubygems.org/ specs: - actionmailer (3.1.0) - actionpack (= 3.1.0) - mail (~> 2.3.0) - actionpack (3.1.0) - activemodel (= 3.1.0) - activesupport (= 3.1.0) + actionmailer (3.2.18) + actionpack (= 3.2.18) + mail (~> 2.5.4) + actionpack (3.2.18) + activemodel (= 3.2.18) + activesupport (= 3.2.18) builder (~> 3.0.0) erubis (~> 2.7.0) - i18n (~> 0.6) - rack (~> 1.3.2) - rack-cache (~> 1.0.3) - rack-mount (~> 0.8.2) + journey (~> 1.0.4) + rack (~> 1.4.5) + rack-cache (~> 1.2) rack-test (~> 0.6.1) - sprockets (~> 2.0.0) - activemodel (3.1.0) - activesupport (= 3.1.0) - bcrypt-ruby (~> 3.0.0) + sprockets (~> 2.2.1) + activemodel (3.2.18) + activesupport (= 3.2.18) builder (~> 3.0.0) - i18n (~> 0.6) - activerecord (3.1.0) - activemodel (= 3.1.0) - activesupport (= 3.1.0) - arel (~> 2.2.1) + activerecord (3.2.18) + activemodel (= 3.2.18) + activesupport (= 3.2.18) + arel (~> 3.0.2) tzinfo (~> 0.3.29) - activeresource (3.1.0) - activemodel (= 3.1.0) - activesupport (= 3.1.0) - activesupport (3.1.0) + activeresource (3.2.18) + activemodel (= 3.2.18) + activesupport (= 3.2.18) + activesupport (3.2.18) + i18n (~> 0.6, >= 0.6.4) multi_json (~> 1.0) ansi (1.4.3) - arel (2.2.1) - aruba (0.5.1) - childprocess (~> 0.3.6) + arel (3.0.3) + aruba (0.6.0) + childprocess (>= 0.3.6) cucumber (>= 1.1.1) rspec-expectations (>= 2.7.0) - bcrypt-ruby (3.0.1) - bcrypt-ruby (3.0.1-java) - builder (3.0.0) - capybara (2.0.2) + builder (3.0.4) + capybara (2.4.1) mime-types (>= 1.16) nokogiri (>= 1.3.3) rack (>= 1.0.0) rack-test (>= 0.5.4) - selenium-webdriver (~> 2.0) - xpath (~> 1.0.0) - childprocess (0.3.8) + xpath (~> 2.0) + childprocess (0.5.3) ffi (~> 1.0, >= 1.0.11) - coffee-rails (3.1.1) + coffee-rails (3.2.2) coffee-script (>= 2.2.0) - railties (~> 3.1.0) - coffee-script (2.2.0) + railties (~> 3.2.0) + coffee-script (2.3.0) coffee-script-source execjs - coffee-script-source (1.3.3) - cucumber (1.2.1) + coffee-script-source (1.7.1) + cucumber (1.3.16) builder (>= 2.1.2) diff-lcs (>= 1.1.3) - gherkin (~> 2.11.0) - json (>= 1.4.6) - diff-lcs (1.1.3) + gherkin (~> 2.12) + multi_json (>= 1.7.5, < 2.0) + multi_test (>= 0.1.1) + diff-lcs (1.2.5) erubis (2.7.0) - execjs (1.4.0) - multi_json (~> 1.0) - ffi (1.4.0) - ffi (1.4.0-java) - gherkin (2.11.5) - json (>= 1.4.6) - gherkin (2.11.5-java) - json (>= 1.4.6) - haml (3.1.7) - haml-rails (0.3.5) + execjs (2.2.1) + ffi (1.9.3) + ffi (1.9.3-java) + gherkin (2.12.2) + multi_json (~> 1.3) + gherkin (2.12.2-java) + multi_json (~> 1.3) + haml (4.0.5) + tilt + haml-rails (0.4) actionpack (>= 3.1, < 4.1) activesupport (>= 3.1, < 4.1) - haml (~> 3.1) + haml (>= 3.1, < 4.1) railties (>= 3.1, < 4.1) - hike (1.2.1) - i18n (0.6.0) - jquery-rails (2.2.0) + hike (1.2.3) + i18n (0.6.11) + journey (1.0.4) + jquery-rails (3.1.1) railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) - json (1.6.1) - json (1.6.1-java) - mail (2.3.0) - i18n (>= 0.4.0) + json (1.8.1) + json (1.8.1-java) + mail (2.5.4) mime-types (~> 1.16) treetop (~> 1.4.8) - mime-types (1.17.2) - multi_json (1.6.1) - nokogiri (1.5.6) - nokogiri (1.5.6-java) - polyglot (0.3.2) - rack (1.3.5) - rack-cache (1.0.3) + mime-types (1.25.1) + mini_portile (0.6.0) + minitest (4.7.5) + multi_json (1.10.1) + multi_test (0.1.1) + nokogiri (1.6.3.1) + mini_portile (= 0.6.0) + nokogiri (1.6.3.1-java) + polyglot (0.3.5) + rack (1.4.5) + rack-cache (1.2) rack (>= 0.4) - rack-mount (0.8.3) - rack (>= 1.0.0) - rack-ssl (1.3.2) + rack-ssl (1.3.4) rack - rack-test (0.6.1) + rack-test (0.6.2) rack (>= 1.0) - rails (3.1.0) - actionmailer (= 3.1.0) - actionpack (= 3.1.0) - activerecord (= 3.1.0) - activeresource (= 3.1.0) - activesupport (= 3.1.0) + rails (3.2.18) + actionmailer (= 3.2.18) + actionpack (= 3.2.18) + activerecord (= 3.2.18) + activeresource (= 3.2.18) + activesupport (= 3.2.18) bundler (~> 1.0) - railties (= 3.1.0) - railties (3.1.0) - actionpack (= 3.1.0) - activesupport (= 3.1.0) + railties (= 3.2.18) + railties (3.2.18) + actionpack (= 3.2.18) + activesupport (= 3.2.18) rack-ssl (~> 1.3.2) rake (>= 0.8.7) rdoc (~> 3.4) - thor (~> 0.14.6) - rake (0.9.2.2) - rdoc (3.11) + thor (>= 0.14.6, < 2.0) + rake (10.3.2) + rdoc (3.12.2) json (~> 1.4) - rspec-core (2.12.2) - rspec-expectations (2.12.1) - diff-lcs (~> 1.1.3) - rspec-mocks (2.12.1) - rspec-rails (2.12.2) + rspec-core (3.0.3) + rspec-support (~> 3.0.0) + rspec-expectations (3.0.3) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.0.0) + rspec-mocks (3.0.3) + rspec-support (~> 3.0.0) + rspec-rails (3.0.2) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 2.12.0) - rspec-expectations (~> 2.12.0) - rspec-mocks (~> 2.12.0) - rubyzip (0.9.9) - sass (3.2.5) - sass-rails (3.1.7) - actionpack (~> 3.1.0) - railties (~> 3.1.0) + rspec-core (~> 3.0.0) + rspec-expectations (~> 3.0.0) + rspec-mocks (~> 3.0.0) + rspec-support (~> 3.0.0) + rspec-support (3.0.3) + rubyzip (1.1.6) + sass (3.3.14) + sass-rails (3.2.6) + railties (~> 3.2.0) sass (>= 3.1.10) - tilt (~> 1.3.2) - selenium-webdriver (2.30.0) - childprocess (>= 0.2.5) + tilt (~> 1.3) + selenium-webdriver (2.42.0) + childprocess (>= 0.5.0) multi_json (~> 1.0) - rubyzip + rubyzip (~> 1.0) websocket (~> 1.0.4) - sprockets (2.0.3) + sprockets (2.2.2) hike (~> 1.2) + multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - sqlite3 (1.3.7) - thor (0.14.6) - tilt (1.3.3) - treetop (1.4.10) + sqlite3 (1.3.9) + thor (0.19.1) + tilt (1.4.1) + treetop (1.4.15) polyglot polyglot (>= 0.3.1) - turn (0.9.6) + turn (0.9.7) ansi - tzinfo (0.3.30) - uglifier (1.3.0) + minitest (~> 4) + tzinfo (0.3.41) + uglifier (2.5.3) execjs (>= 0.3.0) - multi_json (~> 1.0, >= 1.0.2) + json (>= 1.8.0) websocket (1.0.7) - xpath (1.0.0) + xpath (2.0.0) nokogiri (~> 1.3) PLATFORMS @@ -175,14 +179,15 @@ PLATFORMS DEPENDENCIES aruba capybara - coffee-rails (~> 3.1.0) + coffee-rails haml-rails jasminerice! jquery-rails json - rails (= 3.1.0) - rspec-rails - sass-rails (~> 3.1.0) + rails (= 3.2.18) + rspec-rails (~> 3.0.0) + sass-rails + selenium-webdriver sqlite3 turn uglifier diff --git a/spec/features/html_reporter_spec.rb b/spec/features/html_reporter_spec.rb index ed143e8..9951a38 100644 --- a/spec/features/html_reporter_spec.rb +++ b/spec/features/html_reporter_spec.rb @@ -1,11 +1,11 @@ -require "spec_helper" +require 'spec_helper' -feature "Testing in the browser", :js => true do +feature 'Testing in the browser', :js => true do - scenario "gives me the expected results" do - visit "/jasmine" + scenario 'gives me the expected results' do + visit '/jasmine' - expect(page.all(".symbolSummary .passed").length).to be(2) - expect(find('.passingAlert.bar')).to have_text("Passing 2 specs") + expect(page.all('.symbol-summary .passed').count).to eq 2 + expect(find('.bar.passed')).to have_text('2 specs, 0 failures') end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 09c9124..0983e82 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,10 +6,10 @@ require "rspec/autorun" require "capybara/rails" require "aruba/api" +require "aruba/reporting" Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |f| require f } RSpec.configure do |config| - config.infer_base_class_for_anonymous_controllers = false - config.order = "random" + config.infer_spec_type_from_file_location! end From 1512f75cb87dc2a5730c36f6faaa5b3602987afb Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Mon, 11 Aug 2014 21:37:10 +1000 Subject: [PATCH 11/16] Fixed some tests that were using the old 'should' rspec format --- spec/controllers/spec_controller_spec.rb | 6 +++--- spec/jasminerice/engine_spec.rb | 2 +- spec/spec_helper.rb | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/spec/controllers/spec_controller_spec.rb b/spec/controllers/spec_controller_spec.rb index b844215..dabc5ef 100644 --- a/spec/controllers/spec_controller_spec.rb +++ b/spec/controllers/spec_controller_spec.rb @@ -1,14 +1,14 @@ require 'spec_helper' describe Jasminerice::SpecController do - describe "view paths" do + describe 'view paths' do before do - Jasminerice::SpecController.any_instance.stub(:render) { @view_paths = controller.view_paths } + allow_any_instance_of(Jasminerice::SpecController).to receive(:render) { @view_paths = controller.view_paths } get 'fixtures', :use_route => :jasminerice end subject { @view_paths.map(&:original_path_set).flatten.map(&:to_s) } - it { should include Rails.root.to_s } + it { is_expected.to include Rails.root.to_s } end end \ No newline at end of file diff --git a/spec/jasminerice/engine_spec.rb b/spec/jasminerice/engine_spec.rb index 70c46f4..489f669 100644 --- a/spec/jasminerice/engine_spec.rb +++ b/spec/jasminerice/engine_spec.rb @@ -3,7 +3,7 @@ describe Jasminerice::Engine do it "is a class" do - Jasminerice::Engine.should be_a(Class) + expect(Jasminerice::Engine).to be_a Class end it "has been isolated with a name" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 0983e82..ba7802f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,7 +3,6 @@ require File.expand_path("../dummy/config/environment", __FILE__) require "rspec/rails" -require "rspec/autorun" require "capybara/rails" require "aruba/api" require "aruba/reporting" From ac5d4f2162991f515a4d93265800d45bbd501dcb Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Tue, 12 Aug 2014 07:43:34 +1000 Subject: [PATCH 12/16] Added support for switching between Jasmine versions --- Gemfile | 2 +- Gemfile.lock | 27 +- README.md | 11 + app/assets/javascripts/jasminerice.js.erb | 2 + app/assets/stylesheets/jasmine.css.erb | 1 + .../jasminerice/templates/jasminerice.rb | 3 + lib/jasminerice.rb | 3 + spec/features/html_reporter_spec.rb | 32 +- .../javascripts/jasmine_1_3/jasmine-html.js | 681 +++++ .../javascripts/jasmine_1_3/jasmine-jquery.js | 663 +++++ .../assets/javascripts/jasmine_1_3/jasmine.js | 2600 +++++++++++++++++ .../jasmine_1_3/jasminerice.js.coffee | 34 + .../javascripts/{ => jasmine_2_0}/boot.js | 0 .../{ => jasmine_2_0}/jasmine-html.js | 0 .../{ => jasmine_2_0}/jasmine-jquery.js | 0 .../javascripts/{ => jasmine_2_0}/jasmine.js | 0 .../jasmine_2_0}/jasminerice.js.coffee | 11 +- .../stylesheets/jasmine_1_3/jasmine.css | 82 + .../stylesheets/{ => jasmine_2_0}/jasmine.css | 0 19 files changed, 4127 insertions(+), 25 deletions(-) create mode 100644 app/assets/javascripts/jasminerice.js.erb create mode 100644 app/assets/stylesheets/jasmine.css.erb create mode 100644 vendor/assets/javascripts/jasmine_1_3/jasmine-html.js create mode 100644 vendor/assets/javascripts/jasmine_1_3/jasmine-jquery.js create mode 100644 vendor/assets/javascripts/jasmine_1_3/jasmine.js create mode 100644 vendor/assets/javascripts/jasmine_1_3/jasminerice.js.coffee rename vendor/assets/javascripts/{ => jasmine_2_0}/boot.js (100%) rename vendor/assets/javascripts/{ => jasmine_2_0}/jasmine-html.js (100%) rename vendor/assets/javascripts/{ => jasmine_2_0}/jasmine-jquery.js (100%) rename vendor/assets/javascripts/{ => jasmine_2_0}/jasmine.js (100%) rename {app/assets/javascripts => vendor/assets/javascripts/jasmine_2_0}/jasminerice.js.coffee (59%) create mode 100644 vendor/assets/stylesheets/jasmine_1_3/jasmine.css rename vendor/assets/stylesheets/{ => jasmine_2_0}/jasmine.css (100%) diff --git a/Gemfile b/Gemfile index 2561d29..0896077 100644 --- a/Gemfile +++ b/Gemfile @@ -16,7 +16,7 @@ gem 'jquery-rails' gem 'turn', :require => false, :group => :test group :development, :test do - gem 'rspec-rails', '~>3.0.0' + gem 'rspec-rails', '2.99.0' gem 'capybara' gem 'selenium-webdriver' gem 'aruba' diff --git a/Gemfile.lock b/Gemfile.lock index eb676c1..ac3572e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -123,22 +123,21 @@ GEM rake (10.3.2) rdoc (3.12.2) json (~> 1.4) - rspec-core (3.0.3) - rspec-support (~> 3.0.0) - rspec-expectations (3.0.3) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.0.0) - rspec-mocks (3.0.3) - rspec-support (~> 3.0.0) - rspec-rails (3.0.2) + rspec-collection_matchers (1.0.0) + rspec-expectations (>= 2.99.0.beta1) + rspec-core (2.99.1) + rspec-expectations (2.99.2) + diff-lcs (>= 1.1.3, < 2.0) + rspec-mocks (2.99.2) + rspec-rails (2.99.0) actionpack (>= 3.0) + activemodel (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.0.0) - rspec-expectations (~> 3.0.0) - rspec-mocks (~> 3.0.0) - rspec-support (~> 3.0.0) - rspec-support (3.0.3) + rspec-collection_matchers + rspec-core (~> 2.99.0) + rspec-expectations (~> 2.99.0) + rspec-mocks (~> 2.99.0) rubyzip (1.1.6) sass (3.3.14) sass-rails (3.2.6) @@ -185,7 +184,7 @@ DEPENDENCIES jquery-rails json rails (= 3.2.18) - rspec-rails (~> 3.0.0) + rspec-rails (= 2.99.0) sass-rails selenium-webdriver sqlite3 diff --git a/README.md b/README.md index db8547e..2638f2e 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,17 @@ This will add the required `spec.js.coffee`, an example spec, and fixture to hel ## Usage +### Jasmine version selection + +By default Jasminerice will use Jasmine 1.3. To select Jasmine 2.0 simply add the follow line in `config/initializers/jasminerice.rb`: + +```ruby +Jasminerice.setup do |config| + config.jasmine_version = '2_0' +end +``` + + ### CoffeeScripts Create a file `spec/javascripts/spec.js.coffee` (or run the install generator), and add the following content. diff --git a/app/assets/javascripts/jasminerice.js.erb b/app/assets/javascripts/jasminerice.js.erb new file mode 100644 index 0000000..6304a55 --- /dev/null +++ b/app/assets/javascripts/jasminerice.js.erb @@ -0,0 +1,2 @@ +<% require_asset "jasmine_#{Jasminerice.jasmine_version}/jasminerice" %> +console.log('<%= Jasminerice.jasmine_version %>'); \ No newline at end of file diff --git a/app/assets/stylesheets/jasmine.css.erb b/app/assets/stylesheets/jasmine.css.erb new file mode 100644 index 0000000..beeb98e --- /dev/null +++ b/app/assets/stylesheets/jasmine.css.erb @@ -0,0 +1 @@ +<% require_asset "jasmine_#{Jasminerice.jasmine_version}/jasmine" %> diff --git a/lib/generators/jasminerice/templates/jasminerice.rb b/lib/generators/jasminerice/templates/jasminerice.rb index 042238b..1e2e8a7 100644 --- a/lib/generators/jasminerice/templates/jasminerice.rb +++ b/lib/generators/jasminerice/templates/jasminerice.rb @@ -13,6 +13,9 @@ # Specify a path where your specs can be found. Defaults to 'spec' #config.spec_path = 'spec' + # Specify the version of Jasmine you want to use (1_3 or 2_0 are supported with 1_3 being the default) + #config.jasmine_version = '2_0' + # Specify a path where your fixutures can be found. Defaults to 'spec/javascripts/fixtures' #config.fixture_path = 'spec/javascripts/fixtures' end diff --git a/lib/jasminerice.rb b/lib/jasminerice.rb index b06357f..182ba26 100644 --- a/lib/jasminerice.rb +++ b/lib/jasminerice.rb @@ -15,6 +15,9 @@ module Jasminerice mattr_accessor :fixture_path @@fixture_path = 'spec/javascripts/fixtures' + mattr_accessor :jasmine_version + @@jasmine_version = '1_3' + # Default way to setup Jasminerice. Run rails generate jasminerice:install to create # a fresh initializer with all configuration values. def self.setup diff --git a/spec/features/html_reporter_spec.rb b/spec/features/html_reporter_spec.rb index 9951a38..e0c0d36 100644 --- a/spec/features/html_reporter_spec.rb +++ b/spec/features/html_reporter_spec.rb @@ -1,11 +1,33 @@ require 'spec_helper' -feature 'Testing in the browser', :js => true do +describe 'Testing in the browser', :js => true do + context 'for jasmine 2.0' do + before do + Jasminerice.jasmine_version = '2_0' + end - scenario 'gives me the expected results' do - visit '/jasmine' + it 'will respond with the expected results' do + visit '/jasmine' - expect(page.all('.symbol-summary .passed').count).to eq 2 - expect(find('.bar.passed')).to have_text('2 specs, 0 failures') + expect(page.all('.symbol-summary .passed').count).to eq 2 + expect(find('.bar.passed')).to have_text('2 specs, 0 failures') + end + end + + context 'for jasmine 1.3' do + skip 'This needs a creative solution for restarting rails' do + # This does work however it cannot be run directly after the test for setting 2.0. + # The reason it fails is due to the mechanism for selection being already compiled (see app/assets/javascripts/jasminerice.js.erb) + before do + Jasminerice.jasmine_version = '1_3' + end + + it 'will respond with the expected results' do + visit '/jasmine' + + expect(page.all('.symbolSummary .passed').count).to eq 2 + expect(find('.passingAlert.bar')).to have_text('Passing 2 specs') + end + end end end diff --git a/vendor/assets/javascripts/jasmine_1_3/jasmine-html.js b/vendor/assets/javascripts/jasmine_1_3/jasmine-html.js new file mode 100644 index 0000000..543d569 --- /dev/null +++ b/vendor/assets/javascripts/jasmine_1_3/jasmine-html.js @@ -0,0 +1,681 @@ +jasmine.HtmlReporterHelpers = {}; + +jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + if (child) { + el.appendChild(child); + } + } + } + + for (var attr in attrs) { + if (attr == "className") { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; +}; + +jasmine.HtmlReporterHelpers.getSpecStatus = function(child) { + var results = child.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.skipped) { + status = 'skipped'; + } + + return status; +}; + +jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) { + var parentDiv = this.dom.summary; + var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite'; + var parent = child[parentSuite]; + + if (parent) { + if (typeof this.views.suites[parent.id] == 'undefined') { + this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views); + } + parentDiv = this.views.suites[parent.id].element; + } + + parentDiv.appendChild(childElement); +}; + + +jasmine.HtmlReporterHelpers.addHelpers = function(ctor) { + for(var fn in jasmine.HtmlReporterHelpers) { + ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn]; + } +}; + +jasmine.HtmlReporter = function(_doc) { + var self = this; + var doc = _doc || window.document; + + var reporterView; + + var dom = {}; + + // Jasmine Reporter Public Interface + self.logRunningSpecs = false; + + self.reportRunnerStarting = function(runner) { + var specs = runner.specs() || []; + + if (specs.length == 0) { + return; + } + + createReporterDom(runner.env.versionString()); + doc.body.appendChild(dom.reporter); + setExceptionHandling(); + + reporterView = new jasmine.HtmlReporter.ReporterView(dom); + reporterView.addSpecs(specs, self.specFilter); + }; + + self.reportRunnerResults = function(runner) { + reporterView && reporterView.complete(); + }; + + self.reportSuiteResults = function(suite) { + reporterView.suiteComplete(suite); + }; + + self.reportSpecStarting = function(spec) { + if (self.logRunningSpecs) { + self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); + } + }; + + self.reportSpecResults = function(spec) { + reporterView.specComplete(spec); + }; + + self.log = function() { + var console = jasmine.getGlobal().console; + if (console && console.log) { + if (console.log.apply) { + console.log.apply(console, arguments); + } else { + console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + } + } + }; + + self.specFilter = function(spec) { + if (!focusedSpecName()) { + return true; + } + + return spec.getFullName().indexOf(focusedSpecName()) === 0; + }; + + return self; + + function focusedSpecName() { + var specName; + + (function memoizeFocusedSpec() { + if (specName) { + return; + } + + var paramMap = []; + var params = jasmine.HtmlReporter.parameters(doc); + + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + } + + specName = paramMap.spec; + })(); + + return specName; + } + + function createReporterDom(version) { + dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' }, + dom.banner = self.createDom('div', { className: 'banner' }, + self.createDom('span', { className: 'title' }, "Jasmine "), + self.createDom('span', { className: 'version' }, version)), + + dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}), + 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.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; + this.passedCount = 0; + this.failedCount = 0; + this.skippedCount = 0; + + this.createResultsMenu = function() { + this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'}, + this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'), + ' | ', + this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing')); + + this.summaryMenuItem.onclick = function() { + dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, ''); + }; + + this.detailsMenuItem.onclick = function() { + showDetails(); + }; + }; + + this.addSpecs = function(specs, specFilter) { + this.totalSpecCount = specs.length; + + this.views = { + specs: {}, + suites: {} + }; + + for (var i = 0; i < specs.length; i++) { + var spec = specs[i]; + this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views); + if (specFilter(spec)) { + this.runningSpecCount++; + } + } + }; + + this.specComplete = function(spec) { + this.completeSpecCount++; + + if (isUndefined(this.views.specs[spec.id])) { + this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom); + } + + var specView = this.views.specs[spec.id]; + + switch (specView.status()) { + case 'passed': + this.passedCount++; + break; + + case 'failed': + this.failedCount++; + break; + + case 'skipped': + this.skippedCount++; + break; + } + + specView.refresh(); + this.refresh(); + }; + + this.suiteComplete = function(suite) { + var suiteView = this.views.suites[suite.id]; + if (isUndefined(suiteView)) { + return; + } + suiteView.refresh(); + }; + + this.refresh = function() { + + if (isUndefined(this.resultsMenu)) { + this.createResultsMenu(); + } + + // currently running UI + if (isUndefined(this.runningAlert)) { + 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: jasmine.HtmlReporter.sectionLink(), className: "skippedAlert bar" }); + } + + this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; + + if (this.skippedCount === 1 && isDefined(dom.alert)) { + dom.alert.appendChild(this.skippedAlert); + } + + // passing specs UI + if (isUndefined(this.passedAlert)) { + this.passedAlert = this.createDom('span', { href: jasmine.HtmlReporter.sectionLink(), className: "passingAlert bar" }); + } + this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount); + + // failing specs UI + if (isUndefined(this.failedAlert)) { + this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"}); + } + this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount); + + if (this.failedCount === 1 && isDefined(dom.alert)) { + dom.alert.appendChild(this.failedAlert); + dom.alert.appendChild(this.resultsMenu); + } + + // summary info + this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount); + this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing"; + }; + + this.complete = function() { + dom.alert.removeChild(this.runningAlert); + + this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; + + if (this.failedCount === 0) { + dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount))); + } else { + showDetails(); + } + + dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s")); + }; + + return this; + + function showDetails() { + if (dom.reporter.className.search(/showDetails/) === -1) { + dom.reporter.className += " showDetails"; + } + } + + function isUndefined(obj) { + return typeof obj === 'undefined'; + } + + function isDefined(obj) { + return !isUndefined(obj); + } + + function specPluralizedFor(count) { + var str = count + " spec"; + if (count > 1) { + str += "s" + } + return str; + } + +}; + +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView); + + +jasmine.HtmlReporter.SpecView = function(spec, dom, views) { + this.spec = spec; + this.dom = dom; + this.views = views; + + this.symbol = this.createDom('li', { className: 'pending' }); + this.dom.symbolSummary.appendChild(this.symbol); + + this.summary = this.createDom('div', { className: 'specSummary' }, + 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' }, + this.createDom('a', { + className: 'description', + href: '?spec=' + encodeURIComponent(this.spec.getFullName()), + title: this.spec.getFullName() + }, this.spec.getFullName()) + ); +}; + +jasmine.HtmlReporter.SpecView.prototype.status = function() { + return this.getSpecStatus(this.spec); +}; + +jasmine.HtmlReporter.SpecView.prototype.refresh = function() { + this.symbol.className = this.status(); + + switch (this.status()) { + case 'skipped': + break; + + case 'passed': + this.appendSummaryToSuiteDiv(); + break; + + case 'failed': + this.appendSummaryToSuiteDiv(); + this.appendFailureDetail(); + break; + } +}; + +jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() { + this.summary.className += ' ' + this.status(); + this.appendToSummary(this.spec, this.summary); +}; + +jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() { + this.detail.className += ' ' + this.status(); + + var resultItems = this.spec.results().getItems(); + var messagesDiv = this.createDom('div', { className: 'messages' }); + + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'log') { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); + } else if (result.type == 'expect' && result.passed && !result.passed()) { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); + + if (result.trace.stack) { + messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + } + + if (messagesDiv.childNodes.length > 0) { + this.detail.appendChild(messagesDiv); + this.dom.details.appendChild(this.detail); + } +}; + +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) { + this.suite = suite; + this.dom = dom; + this.views = views; + + this.element = this.createDom('div', { className: 'suite' }, + this.createDom('a', { className: 'description', href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()) }, this.suite.description) + ); + + this.appendToSummary(this.suite, this.element); +}; + +jasmine.HtmlReporter.SuiteView.prototype.status = function() { + return this.getSpecStatus(this.suite); +}; + +jasmine.HtmlReporter.SuiteView.prototype.refresh = function() { + this.element.className += " " + this.status(); +}; + +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView); + +/* @deprecated Use jasmine.HtmlReporter instead + */ +jasmine.TrivialReporter = function(doc) { + this.document = doc || document; + this.suiteDivs = {}; + this.logRunningSpecs = false; +}; + +jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + if (child) { el.appendChild(child); } + } + } + + for (var attr in attrs) { + if (attr == "className") { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; +}; + +jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { + var showPassed, showSkipped; + + this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' }, + this.createDom('div', { className: 'banner' }, + this.createDom('div', { className: 'logo' }, + this.createDom('span', { className: 'title' }, "Jasmine"), + this.createDom('span', { className: 'version' }, runner.env.versionString())), + this.createDom('div', { className: 'options' }, + "Show ", + showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), + showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") + ) + ), + + this.runnerDiv = this.createDom('div', { className: 'runner running' }, + this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), + this.runnerMessageSpan = this.createDom('span', {}, "Running..."), + this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) + ); + + this.document.body.appendChild(this.outerDiv); + + var suites = runner.suites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + var suiteDiv = this.createDom('div', { className: 'suite' }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), + this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); + this.suiteDivs[suite.id] = suiteDiv; + var parentDiv = this.outerDiv; + if (suite.parentSuite) { + parentDiv = this.suiteDivs[suite.parentSuite.id]; + } + parentDiv.appendChild(suiteDiv); + } + + this.startedAt = new Date(); + + var self = this; + showPassed.onclick = function(evt) { + if (showPassed.checked) { + self.outerDiv.className += ' show-passed'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); + } + }; + + showSkipped.onclick = function(evt) { + if (showSkipped.checked) { + self.outerDiv.className += ' show-skipped'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); + } + }; +}; + +jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { + var results = runner.results(); + var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; + this.runnerDiv.setAttribute("class", className); + //do it twice for IE + this.runnerDiv.setAttribute("className", className); + var specs = runner.specs(); + var specCount = 0; + for (var i = 0; i < specs.length; i++) { + if (this.specFilter(specs[i])) { + specCount++; + } + } + var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); + message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; + this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); + + this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); +}; + +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 + status = 'skipped'; + } + this.suiteDivs[suite.id].className += " " + status; +}; + +jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { + if (this.logRunningSpecs) { + this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); + } +}; + +jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { + var results = spec.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.skipped) { + status = 'skipped'; + } + var specDiv = this.createDom('div', { className: 'spec ' + status }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), + this.createDom('a', { + className: 'description', + href: '?spec=' + encodeURIComponent(spec.getFullName()), + title: spec.getFullName() + }, spec.description)); + + + var resultItems = results.getItems(); + var messagesDiv = this.createDom('div', { className: 'messages' }); + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'log') { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); + } else if (result.type == 'expect' && result.passed && !result.passed()) { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); + + if (result.trace.stack) { + messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + } + + if (messagesDiv.childNodes.length > 0) { + specDiv.appendChild(messagesDiv); + } + + this.suiteDivs[spec.suite.id].appendChild(specDiv); +}; + +jasmine.TrivialReporter.prototype.log = function() { + var console = jasmine.getGlobal().console; + if (console && console.log) { + if (console.log.apply) { + console.log.apply(console, arguments); + } else { + console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + } + } +}; + +jasmine.TrivialReporter.prototype.getLocation = function() { + return this.document.location; +}; + +jasmine.TrivialReporter.prototype.specFilter = function(spec) { + var paramMap = {}; + var params = this.getLocation().search.substring(1).split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + } + + if (!paramMap.spec) { + return true; + } + return spec.getFullName().indexOf(paramMap.spec) === 0; +}; diff --git a/vendor/assets/javascripts/jasmine_1_3/jasmine-jquery.js b/vendor/assets/javascripts/jasmine_1_3/jasmine-jquery.js new file mode 100644 index 0000000..7552b20 --- /dev/null +++ b/vendor/assets/javascripts/jasmine_1_3/jasmine-jquery.js @@ -0,0 +1,663 @@ +/*! + Jasmine-jQuery: a set of jQuery helpers for Jasmine tests. + + Version 1.5.4 + + https://github.com/velesin/jasmine-jquery + + Copyright (c) 2010-2013 Wojciech Zawistowski, Travis Jeffery + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +var readFixtures = function() { + return jasmine.getFixtures().proxyCallTo_('read', arguments) +} + +var preloadFixtures = function() { + jasmine.getFixtures().proxyCallTo_('preload', arguments) +} + +var loadFixtures = function() { + jasmine.getFixtures().proxyCallTo_('load', arguments) +} + +var appendLoadFixtures = function() { + jasmine.getFixtures().proxyCallTo_('appendLoad', arguments) +} + +var setFixtures = function(html) { + jasmine.getFixtures().proxyCallTo_('set', arguments) +} + +var appendSetFixtures = function() { + jasmine.getFixtures().proxyCallTo_('appendSet', arguments) +} + +var sandbox = function(attributes) { + return jasmine.getFixtures().sandbox(attributes) +} + +var spyOnEvent = function(selector, eventName) { + return jasmine.JQuery.events.spyOn(selector, eventName) +} + +var preloadStyleFixtures = function() { + jasmine.getStyleFixtures().proxyCallTo_('preload', arguments) +} + +var loadStyleFixtures = function() { + jasmine.getStyleFixtures().proxyCallTo_('load', arguments) +} + +var appendLoadStyleFixtures = function() { + jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments) +} + +var setStyleFixtures = function(html) { + jasmine.getStyleFixtures().proxyCallTo_('set', arguments) +} + +var appendSetStyleFixtures = function(html) { + jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments) +} + +var loadJSONFixtures = function() { + return jasmine.getJSONFixtures().proxyCallTo_('load', arguments) +} + +var getJSONFixture = function(url) { + return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url] +} + +jasmine.spiedEventsKey = function (selector, eventName) { + return [$(selector).selector, eventName].toString() +} + +jasmine.getFixtures = function() { + return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures() +} + +jasmine.getStyleFixtures = function() { + return jasmine.currentStyleFixtures_ = jasmine.currentStyleFixtures_ || new jasmine.StyleFixtures() +} + +jasmine.Fixtures = function() { + this.containerId = 'jasmine-fixtures' + this.fixturesCache_ = {} + this.fixturesPath = 'spec/javascripts/fixtures' +} + +jasmine.Fixtures.prototype.set = function(html) { + this.cleanUp() + this.createContainer_(html) +} + +jasmine.Fixtures.prototype.appendSet= function(html) { + this.addToContainer_(html) +} + +jasmine.Fixtures.prototype.preload = function() { + this.read.apply(this, arguments) +} + +jasmine.Fixtures.prototype.load = function() { + this.cleanUp() + this.createContainer_(this.read.apply(this, arguments)) +} + +jasmine.Fixtures.prototype.appendLoad = function() { + this.addToContainer_(this.read.apply(this, arguments)) +} + +jasmine.Fixtures.prototype.read = function() { + var htmlChunks = [] + + var fixtureUrls = arguments + for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { + htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex])) + } + + return htmlChunks.join('') +} + +jasmine.Fixtures.prototype.clearCache = function() { + this.fixturesCache_ = {} +} + +jasmine.Fixtures.prototype.cleanUp = function() { + $('#' + this.containerId).remove() +} + +jasmine.Fixtures.prototype.sandbox = function(attributes) { + var attributesToSet = attributes || {} + return $('
').attr(attributesToSet) +} + +jasmine.Fixtures.prototype.createContainer_ = function(html) { + var container + if(html instanceof $) { + container = $('
') + container.html(html) + } else { + container = '
' + html + '
' + } + $(document.body).append(container) +} + +jasmine.Fixtures.prototype.addToContainer_ = function(html){ + var container = $(document.body).find('#'+this.containerId).append(html) + if(!container.length){ + this.createContainer_(html) + } +} + +jasmine.Fixtures.prototype.getFixtureHtml_ = function(url) { + if (typeof this.fixturesCache_[url] === 'undefined') { + this.loadFixtureIntoCache_(url) + } + return this.fixturesCache_[url] +} + +jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) { + var url = this.makeFixtureUrl_(relativeUrl) + var request = $.ajax({ + type: "GET", + url: url + "?" + new Date().getTime(), + async: false + }) + this.fixturesCache_[relativeUrl] = request.responseText +} + +jasmine.Fixtures.prototype.makeFixtureUrl_ = function(relativeUrl){ + return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl +} + +jasmine.Fixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) { + return this[methodName].apply(this, passedArguments) +} + + +jasmine.StyleFixtures = function() { + this.fixturesCache_ = {} + this.fixturesNodes_ = [] + this.fixturesPath = 'spec/javascripts/fixtures' +} + +jasmine.StyleFixtures.prototype.set = function(css) { + this.cleanUp() + this.createStyle_(css) +} + +jasmine.StyleFixtures.prototype.appendSet = function(css) { + this.createStyle_(css) +} + +jasmine.StyleFixtures.prototype.preload = function() { + this.read_.apply(this, arguments) +} + +jasmine.StyleFixtures.prototype.load = function() { + this.cleanUp() + this.createStyle_(this.read_.apply(this, arguments)) +} + +jasmine.StyleFixtures.prototype.appendLoad = function() { + this.createStyle_(this.read_.apply(this, arguments)) +} + +jasmine.StyleFixtures.prototype.cleanUp = function() { + while(this.fixturesNodes_.length) { + this.fixturesNodes_.pop().remove() + } +} + +jasmine.StyleFixtures.prototype.createStyle_ = function(html) { + var styleText = $('
').html(html).text(), + style = $('') + + this.fixturesNodes_.push(style) + + $('head').append(style) +} + +jasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache + +jasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read + +jasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_ + +jasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_ + +jasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_ + +jasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_ + +jasmine.getJSONFixtures = function() { + return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures() +} + +jasmine.JSONFixtures = function() { + this.fixturesCache_ = {} + this.fixturesPath = 'spec/javascripts/fixtures/json' +} + +jasmine.JSONFixtures.prototype.load = function() { + this.read.apply(this, arguments) + return this.fixturesCache_ +} + +jasmine.JSONFixtures.prototype.read = function() { + var fixtureUrls = arguments + for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { + this.getFixtureData_(fixtureUrls[urlIndex]) + } + return this.fixturesCache_ +} + +jasmine.JSONFixtures.prototype.clearCache = function() { + this.fixturesCache_ = {} +} + +jasmine.JSONFixtures.prototype.getFixtureData_ = function(url) { + this.loadFixtureIntoCache_(url) + return this.fixturesCache_[url] +} + +jasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) { + var self = this + var url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl + $.ajax({ + async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded + cache: false, + dataType: 'json', + url: url, + success: function(data) { + self.fixturesCache_[relativeUrl] = data + }, + error: function(jqXHR, status, errorThrown) { + throw Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')') + } + }) +} + +jasmine.JSONFixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) { + return this[methodName].apply(this, passedArguments) +} + +jasmine.JQuery = function() {} + +jasmine.JQuery.browserTagCaseIndependentHtml = function(html) { + return $('
').append(html).html() +} + +jasmine.JQuery.elementToString = function(element) { + var domEl = $(element).get(0) + if (domEl == undefined || domEl.cloneNode) + return $('
').append($(element).clone()).html() + else + return element.toString() +} + +jasmine.JQuery.matchersClass = {} + +!function(namespace) { + var data = { + spiedEvents: {}, + handlers: [] + } + + namespace.events = { + spyOn: function(selector, eventName) { + var handler = function(e) { + data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = jasmine.util.argsToArray(arguments) + } + $(selector).on(eventName, handler) + data.handlers.push(handler) + return { + selector: selector, + eventName: eventName, + handler: handler, + reset: function(){ + delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] + } + } + }, + + args: function(selector, eventName) { + var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]; + + if (!actualArgs) { + throw "There is no spy for " + eventName + " on " + selector.toString() + ". Make sure to create a spy using spyOnEvent."; + } + + return actualArgs; + }, + + wasTriggered: function(selector, eventName) { + return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]) + }, + + wasTriggeredWith: function(selector, eventName, expectedArgs, env) { + var actualArgs = jasmine.JQuery.events.args(selector, eventName).slice(1); + if (Object.prototype.toString.call(expectedArgs) !== '[object Array]') { + actualArgs = actualArgs[0]; + } + return env.equals_(expectedArgs, actualArgs); + }, + + wasPrevented: function(selector, eventName) { + var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)], + e = args ? args[0] : undefined; + return e && e.isDefaultPrevented() + }, + + wasStopped: function(selector, eventName) { + var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)], + e = args ? args[0] : undefined; + return e && e.isPropagationStopped() + }, + + cleanUp: function() { + data.spiedEvents = {} + data.handlers = [] + } + } +}(jasmine.JQuery) + +!function(){ + var jQueryMatchers = { + toHaveClass: function(className) { + return this.actual.hasClass(className) + }, + + toHaveCss: function(css){ + for (var prop in css){ + if (this.actual.css(prop) !== css[prop]) return false + } + return true + }, + + toBeVisible: function() { + return this.actual.is(':visible') + }, + + toBeHidden: function() { + return this.actual.is(':hidden') + }, + + toBeSelected: function() { + return this.actual.is(':selected') + }, + + toBeChecked: function() { + return this.actual.is(':checked') + }, + + toBeEmpty: function() { + return this.actual.is(':empty') + }, + + toExist: function() { + return $(document).find(this.actual).length + }, + + toHaveLength: function(length) { + return this.actual.length === length + }, + + toHaveAttr: function(attributeName, expectedAttributeValue) { + return hasProperty(this.actual.attr(attributeName), expectedAttributeValue) + }, + + toHaveProp: function(propertyName, expectedPropertyValue) { + return hasProperty(this.actual.prop(propertyName), expectedPropertyValue) + }, + + toHaveId: function(id) { + return this.actual.attr('id') == id + }, + + toHaveHtml: function(html) { + return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html) + }, + + toContainHtml: function(html){ + var actualHtml = this.actual.html() + var expectedHtml = jasmine.JQuery.browserTagCaseIndependentHtml(html) + return (actualHtml.indexOf(expectedHtml) >= 0) + }, + + toHaveText: function(text) { + var trimmedText = $.trim(this.actual.text()) + if (text && $.isFunction(text.test)) { + return text.test(trimmedText) + } else { + return trimmedText == text + } + }, + + toContainText: function(text) { + var trimmedText = $.trim(this.actual.text()) + if (text && $.isFunction(text.test)) { + return text.test(trimmedText) + } else { + return trimmedText.indexOf(text) != -1; + } + }, + + toHaveValue: function(value) { + return this.actual.val() === value + }, + + toHaveData: function(key, expectedValue) { + return hasProperty(this.actual.data(key), expectedValue) + }, + + toBe: function(selector) { + return this.actual.is(selector) + }, + + toContain: function(selector) { + return this.actual.find(selector).length + }, + + toSelect: function(selector) { + return this.actual.filter(selector).length + }, + + toBeDisabled: function(selector){ + return this.actual.is(':disabled') + }, + + toBeFocused: function(selector) { + return this.actual[0] === this.actual[0].ownerDocument.activeElement + }, + + toHandle: function(event) { + + var events = $._data(this.actual.get(0), "events") + + if(!events || !event || typeof event !== "string") { + return false + } + + var namespaces = event.split(".") + var eventType = namespaces.shift() + var sortedNamespaces = namespaces.slice(0).sort() + var namespaceRegExp = new RegExp("(^|\\.)" + sortedNamespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") + + if(events[eventType] && namespaces.length) { + for(var i = 0; i < events[eventType].length; i++) { + var namespace = events[eventType][i].namespace + if(namespaceRegExp.test(namespace)) { + return true + } + } + } else { + return events[eventType] && events[eventType].length > 0 + } + }, + + // tests the existence of a specific event binding + handler + toHandleWith: function(eventName, eventHandler) { + var stack = $._data(this.actual.get(0), "events")[eventName] + for (var i = 0; i < stack.length; i++) { + if (stack[i].handler == eventHandler) return true + } + return false + } + } + + var hasProperty = function(actualValue, expectedValue) { + if (expectedValue === undefined) return actualValue !== undefined + return actualValue == expectedValue + } + + var bindMatcher = function(methodName) { + var builtInMatcher = jasmine.Matchers.prototype[methodName] + + jasmine.JQuery.matchersClass[methodName] = function() { + if (this.actual + && (this.actual instanceof $ + || jasmine.isDomNode(this.actual))) { + this.actual = $(this.actual) + var result = jQueryMatchers[methodName].apply(this, arguments) + var element + if (this.actual.get && (element = this.actual.get()[0]) && !$.isWindow(element) && element.tagName !== "HTML") + this.actual = jasmine.JQuery.elementToString(this.actual) + return result + } + + if (builtInMatcher) { + return builtInMatcher.apply(this, arguments) + } + + return false + } + } + + for(var methodName in jQueryMatchers) { + bindMatcher(methodName) + } +}() + +beforeEach(function() { + this.addMatchers(jasmine.JQuery.matchersClass) + this.addMatchers({ + toHaveBeenTriggeredOn: function(selector) { + this.message = function() { + return [ + "Expected event " + this.actual + " to have been triggered on " + selector, + "Expected event " + this.actual + " not to have been triggered on " + selector + ] + } + return jasmine.JQuery.events.wasTriggered(selector, this.actual) + } + }) + this.addMatchers({ + toHaveBeenTriggered: function(){ + var eventName = this.actual.eventName, + selector = this.actual.selector + this.message = function() { + return [ + "Expected event " + eventName + " to have been triggered on " + selector, + "Expected event " + eventName + " not to have been triggered on " + selector + ] + } + return jasmine.JQuery.events.wasTriggered(selector, eventName) + } + }) + this.addMatchers({ + toHaveBeenTriggeredOnAndWith: function() { + var selector = arguments[0], + expectedArgs = arguments[1], + wasTriggered = jasmine.JQuery.events.wasTriggered(selector, this.actual); + this.message = function() { + if (wasTriggered) { + var actualArgs = jasmine.JQuery.events.args(selector, this.actual, expectedArgs)[1]; + return [ + "Expected event " + this.actual + " to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs), + "Expected event " + this.actual + " not to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) + ] + } else { + return [ + "Expected event " + this.actual + " to have been triggered on " + selector, + "Expected event " + this.actual + " not to have been triggered on " + selector + ] + } + } + return wasTriggered && jasmine.JQuery.events.wasTriggeredWith(selector, this.actual, expectedArgs, this.env); + } + }) + this.addMatchers({ + toHaveBeenPreventedOn: function(selector) { + this.message = function() { + return [ + "Expected event " + this.actual + " to have been prevented on " + selector, + "Expected event " + this.actual + " not to have been prevented on " + selector + ] + } + return jasmine.JQuery.events.wasPrevented(selector, this.actual) + } + }) + this.addMatchers({ + toHaveBeenPrevented: function() { + var eventName = this.actual.eventName, + selector = this.actual.selector + this.message = function() { + return [ + "Expected event " + eventName + " to have been prevented on " + selector, + "Expected event " + eventName + " not to have been prevented on " + selector + ] + } + return jasmine.JQuery.events.wasPrevented(selector, eventName) + } + }) + this.addMatchers({ + toHaveBeenStoppedOn: function(selector) { + this.message = function() { + return [ + "Expected event " + this.actual + " to have been stopped on " + selector, + "Expected event " + this.actual + " not to have been stopped on " + selector + ] + } + return jasmine.JQuery.events.wasStopped(selector, this.actual) + } + }) + this.addMatchers({ + toHaveBeenStopped: function() { + var eventName = this.actual.eventName, + selector = this.actual.selector + this.message = function() { + return [ + "Expected event " + eventName + " to have been stopped on " + selector, + "Expected event " + eventName + " not to have been stopped on " + selector + ] + } + return jasmine.JQuery.events.wasStopped(selector, eventName) + } + }) +}) + +afterEach(function() { + jasmine.getFixtures().cleanUp() + jasmine.getStyleFixtures().cleanUp() + jasmine.JQuery.events.cleanUp() +}) \ No newline at end of file diff --git a/vendor/assets/javascripts/jasmine_1_3/jasmine.js b/vendor/assets/javascripts/jasmine_1_3/jasmine.js new file mode 100644 index 0000000..6b3459b --- /dev/null +++ b/vendor/assets/javascripts/jasmine_1_3/jasmine.js @@ -0,0 +1,2600 @@ +var isCommonJS = typeof window == "undefined" && typeof exports == "object"; + +/** + * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. + * + * @namespace + */ +var jasmine = {}; +if (isCommonJS) exports.jasmine = jasmine; +/** + * @private + */ +jasmine.unimplementedMethod_ = function() { + throw new Error("unimplemented method"); +}; + +/** + * Use jasmine.undefined instead of undefined, since undefined is just + * a plain old variable and may be redefined by somebody else. + * + * @private + */ +jasmine.undefined = jasmine.___undefined___; + +/** + * Show diagnostic messages in the console if set to true + * + */ +jasmine.VERBOSE = false; + +/** + * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. + * + */ +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; + } + + return getGlobal(); +}; + +/** + * Allows for bound functions to be compared. Internal use only. + * + * @ignore + * @private + * @param base {Object} bound 'this' for the function + * @param name {Function} function to find + */ +jasmine.bindOriginal_ = function(base, name) { + var original = base[name]; + if (original.apply) { + return function() { + return original.apply(base, arguments); + }; + } else { + // IE support + return jasmine.getGlobal()[name]; + } +}; + +jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); +jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); +jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); +jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); + +jasmine.MessageResult = function(values) { + this.type = 'log'; + this.values = values; + this.trace = new Error(); // todo: test better +}; + +jasmine.MessageResult.prototype.toString = function() { + var text = ""; + for (var i = 0; i < this.values.length; i++) { + if (i > 0) text += " "; + if (jasmine.isString_(this.values[i])) { + text += this.values[i]; + } else { + text += jasmine.pp(this.values[i]); + } + } + return text; +}; + +jasmine.ExpectationResult = function(params) { + this.type = 'expect'; + this.matcherName = params.matcherName; + this.passed_ = params.passed; + this.expected = params.expected; + this.actual = params.actual; + this.message = this.passed_ ? 'Passed.' : params.message; + + var trace = (params.trace || new Error(this.message)); + this.trace = this.passed_ ? '' : trace; +}; + +jasmine.ExpectationResult.prototype.toString = function () { + return this.message; +}; + +jasmine.ExpectationResult.prototype.passed = function () { + return this.passed_; +}; + +/** + * Getter for the Jasmine environment. Ensures one gets created + */ +jasmine.getEnv = function() { + var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); + return env; +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isArray_ = function(value) { + return jasmine.isA_("Array", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isString_ = function(value) { + return jasmine.isA_("String", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isNumber_ = function(value) { + return jasmine.isA_("Number", value); +}; + +/** + * @ignore + * @private + * @param {String} typeName + * @param value + * @returns {Boolean} + */ +jasmine.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; +}; + +/** + * Pretty printer for expecations. Takes any object and turns it into a human-readable string. + * + * @param value {Object} an object to be outputted + * @returns {String} + */ +jasmine.pp = function(value) { + var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; +}; + +/** + * Returns true if the object is a DOM Node. + * + * @param {Object} obj object to check + * @returns {Boolean} + */ +jasmine.isDomNode = function(obj) { + return obj.nodeType > 0; +}; + +/** + * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. + * + * @example + * // don't care about which function is passed in, as long as it's a function + * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); + * + * @param {Class} clazz + * @returns matchable object of the type clazz + */ +jasmine.any = function(clazz) { + return new jasmine.Matchers.Any(clazz); +}; + +/** + * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the + * attributes on the object. + * + * @example + * // don't care about any other attributes than foo. + * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"}); + * + * @param sample {Object} sample + * @returns matchable object for the sample + */ +jasmine.objectContaining = function (sample) { + return new jasmine.Matchers.ObjectContaining(sample); +}; + +/** + * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. + * + * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine + * expectation syntax. Spies can be checked if they were called or not and what the calling params were. + * + * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). + * + * Spies are torn down at the end of every spec. + * + * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. + * + * @example + * // a stub + * var myStub = jasmine.createSpy('myStub'); // can be used anywhere + * + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // actual foo.not will not be called, execution stops + * spyOn(foo, 'not'); + + // foo.not spied upon, execution will continue to implementation + * spyOn(foo, 'not').andCallThrough(); + * + * // fake example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // foo.not(val) will return val + * spyOn(foo, 'not').andCallFake(function(value) {return value;}); + * + * // mock example + * foo.not(7 == 7); + * expect(foo.not).toHaveBeenCalled(); + * expect(foo.not).toHaveBeenCalledWith(true); + * + * @constructor + * @see spyOn, jasmine.createSpy, jasmine.createSpyObj + * @param {String} name + */ +jasmine.Spy = function(name) { + /** + * The name of the spy, if provided. + */ + this.identity = name || 'unknown'; + /** + * Is this Object a spy? + */ + this.isSpy = true; + /** + * The actual function this spy stubs. + */ + this.plan = function() { + }; + /** + * Tracking of the most recent call to the spy. + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy.mostRecentCall.args = [1, 2]; + */ + this.mostRecentCall = {}; + + /** + * Holds arguments for each call to the spy, indexed by call count + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy(7, 8); + * mySpy.mostRecentCall.args = [7, 8]; + * mySpy.argsForCall[0] = [1, 2]; + * mySpy.argsForCall[1] = [7, 8]; + */ + this.argsForCall = []; + this.calls = []; +}; + +/** + * Tells a spy to call through to the actual implemenatation. + * + * @example + * var foo = { + * bar: function() { // do some stuff } + * } + * + * // defining a spy on an existing property: foo.bar + * spyOn(foo, 'bar').andCallThrough(); + */ +jasmine.Spy.prototype.andCallThrough = function() { + this.plan = this.originalValue; + return this; +}; + +/** + * For setting the return value of a spy. + * + * @example + * // defining a spy from scratch: foo() returns 'baz' + * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); + * + * // defining a spy on an existing property: foo.bar() returns 'baz' + * spyOn(foo, 'bar').andReturn('baz'); + * + * @param {Object} value + */ +jasmine.Spy.prototype.andReturn = function(value) { + this.plan = function() { + return value; + }; + return this; +}; + +/** + * For throwing an exception when a spy is called. + * + * @example + * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' + * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); + * + * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' + * spyOn(foo, 'bar').andThrow('baz'); + * + * @param {String} exceptionMsg + */ +jasmine.Spy.prototype.andThrow = function(exceptionMsg) { + this.plan = function() { + throw exceptionMsg; + }; + return this; +}; + +/** + * Calls an alternate implementation when a spy is called. + * + * @example + * var baz = function() { + * // do some stuff, return something + * } + * // defining a spy from scratch: foo() calls the function baz + * var foo = jasmine.createSpy('spy on foo').andCall(baz); + * + * // defining a spy on an existing property: foo.bar() calls an anonymnous function + * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); + * + * @param {Function} fakeFunc + */ +jasmine.Spy.prototype.andCallFake = function(fakeFunc) { + this.plan = fakeFunc; + return this; +}; + +/** + * Resets all of a spy's the tracking variables so that it can be used again. + * + * @example + * spyOn(foo, 'bar'); + * + * foo.bar(); + * + * expect(foo.bar.callCount).toEqual(1); + * + * foo.bar.reset(); + * + * expect(foo.bar.callCount).toEqual(0); + */ +jasmine.Spy.prototype.reset = function() { + this.wasCalled = false; + this.callCount = 0; + this.argsForCall = []; + this.calls = []; + this.mostRecentCall = {}; +}; + +jasmine.createSpy = function(name) { + + var spyObj = function() { + spyObj.wasCalled = true; + spyObj.callCount++; + var args = jasmine.util.argsToArray(arguments); + spyObj.mostRecentCall.object = this; + spyObj.mostRecentCall.args = args; + spyObj.argsForCall.push(args); + spyObj.calls.push({object: this, args: args}); + return spyObj.plan.apply(this, arguments); + }; + + var spy = new jasmine.Spy(name); + + for (var prop in spy) { + spyObj[prop] = spy[prop]; + } + + spyObj.reset(); + + return spyObj; +}; + +/** + * Determines whether an object is a spy. + * + * @param {jasmine.Spy|Object} putativeSpy + * @returns {Boolean} + */ +jasmine.isSpy = function(putativeSpy) { + return putativeSpy && putativeSpy.isSpy; +}; + +/** + * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something + * large in one call. + * + * @param {String} baseName name of spy class + * @param {Array} methodNames array of names of methods to make spies + */ +jasmine.createSpyObj = function(baseName, methodNames) { + 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 = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); + } + return obj; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the current spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.log = function() { + var spec = jasmine.getEnv().currentSpec; + spec.log.apply(spec, arguments); +}; + +/** + * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. + * + * @example + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops + * + * @see jasmine.createSpy + * @param obj + * @param methodName + * @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); +}; +if (isCommonJS) exports.spyOn = spyOn; + +/** + * Creates a Jasmine spec that will be added to the current suite. + * + * // TODO: pending tests + * + * @example + * it('should be true', function() { + * expect(true).toEqual(true); + * }); + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var it = function(desc, func) { + return jasmine.getEnv().it(desc, func); +}; +if (isCommonJS) exports.it = it; + +/** + * Creates a disabled Jasmine spec. + * + * A convenience method that allows existing specs to be disabled temporarily during development. + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var xit = function(desc, func) { + return jasmine.getEnv().xit(desc, func); +}; +if (isCommonJS) exports.xit = xit; + +/** + * Starts a chain for a Jasmine expectation. + * + * It is passed an Object that is the actual value and should chain to one of the many + * 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); +}; +if (isCommonJS) exports.expect = expect; + +/** + * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. + * + * @param {Function} func Function that defines part of a jasmine spec. + */ +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. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +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. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_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. + * + * Used for spec setup, including validating assumptions. + * + * @param {Function} beforeEachFunction + */ +var beforeEach = function(beforeEachFunction) { + jasmine.getEnv().beforeEach(beforeEachFunction); +}; +if (isCommonJS) exports.beforeEach = beforeEach; + +/** + * A function that is called after each spec in a suite. + * + * Used for restoring any state that is hijacked during spec execution. + * + * @param {Function} afterEachFunction + */ +var afterEach = function(afterEachFunction) { + jasmine.getEnv().afterEach(afterEachFunction); +}; +if (isCommonJS) exports.afterEach = afterEach; + +/** + * Defines a suite of specifications. + * + * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared + * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization + * of setup in some tests. + * + * @example + * // TODO: a simple suite + * + * // TODO: a simple suite with a nested describe block + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +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. + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +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() { + function tryIt(f) { + try { + return f(); + } catch(e) { + } + return null; + } + + 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 + */ +jasmine.util = {}; + +/** + * Declare that a child class inherit it's prototype from the parent class. + * + * @private + * @param {Function} childClass + * @param {Function} parentClass + */ +jasmine.util.inherit = function(childClass, parentClass) { + /** + * @private + */ + var subclass = function() { + }; + subclass.prototype = parentClass.prototype; + childClass.prototype = new subclass(); +}; + +jasmine.util.formatException = function(e) { + var lineNumber; + if (e.line) { + lineNumber = e.line; + } + else if (e.lineNumber) { + lineNumber = e.lineNumber; + } + + var file; + + if (e.sourceURL) { + file = e.sourceURL; + } + else if (e.fileName) { + file = e.fileName; + } + + var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); + + if (file && lineNumber) { + message += ' in ' + file + ' (line ' + lineNumber + ')'; + } + + return message; +}; + +jasmine.util.htmlEscape = function(str) { + if (!str) return str; + return str.replace(/&/g, '&') + .replace(//g, '>'); +}; + +jasmine.util.argsToArray = function(args) { + var arrayOfArgs = []; + for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); + return arrayOfArgs; +}; + +jasmine.util.extend = function(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; +}; + +/** + * Environment for Jasmine + * + * @constructor + */ +jasmine.Env = function() { + this.currentSpec = null; + this.currentSuite = null; + this.currentRunner_ = new jasmine.Runner(this); + + this.reporter = new jasmine.MultiReporter(); + + this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; + this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; + this.lastUpdate = 0; + this.specFilter = function() { + return true; + }; + + this.nextSpecId_ = 0; + this.nextSuiteId_ = 0; + this.equalityTesters_ = []; + + // wrap matchers + this.matchersClass = function() { + jasmine.Matchers.apply(this, arguments); + }; + jasmine.util.inherit(this.matchersClass, jasmine.Matchers); + + jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); +}; + + +jasmine.Env.prototype.setTimeout = jasmine.setTimeout; +jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; +jasmine.Env.prototype.setInterval = jasmine.setInterval; +jasmine.Env.prototype.clearInterval = jasmine.clearInterval; + +/** + * @returns an object containing jasmine version build info, if set. + */ +jasmine.Env.prototype.version = function () { + if (jasmine.version_) { + return jasmine.version_; + } else { + throw new Error('Version not set'); + } +}; + +/** + * @returns string containing jasmine version build info, if set. + */ +jasmine.Env.prototype.versionString = function() { + if (!jasmine.version_) { + return "version unknown"; + } + + var version = this.version(); + var versionString = version.major + "." + version.minor + "." + version.build; + if (version.release_candidate) { + versionString += ".rc" + version.release_candidate; + } + versionString += " revision " + version.revision; + return versionString; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSpecId = function () { + return this.nextSpecId_++; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSuiteId = function () { + return this.nextSuiteId_++; +}; + +/** + * Register a reporter to receive status updates from Jasmine. + * @param {jasmine.Reporter} reporter An object which will receive status updates. + */ +jasmine.Env.prototype.addReporter = function(reporter) { + this.reporter.addReporter(reporter); +}; + +jasmine.Env.prototype.execute = function() { + this.currentRunner_.execute(); +}; + +jasmine.Env.prototype.describe = function(description, specDefinitions) { + var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); + + var parentSuite = this.currentSuite; + if (parentSuite) { + parentSuite.add(suite); + } else { + this.currentRunner_.add(suite); + } + + this.currentSuite = suite; + + var declarationError = null; + try { + specDefinitions.call(suite); + } catch(e) { + declarationError = e; + } + + if (declarationError) { + this.it("encountered a declaration exception", function() { + throw declarationError; + }); + } + + this.currentSuite = parentSuite; + + return suite; +}; + +jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { + if (this.currentSuite) { + this.currentSuite.beforeEach(beforeEachFunction); + } else { + this.currentRunner_.beforeEach(beforeEachFunction); + } +}; + +jasmine.Env.prototype.currentRunner = function () { + return this.currentRunner_; +}; + +jasmine.Env.prototype.afterEach = function(afterEachFunction) { + if (this.currentSuite) { + this.currentSuite.afterEach(afterEachFunction); + } else { + this.currentRunner_.afterEach(afterEachFunction); + } + +}; + +jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { + return { + execute: function() { + } + }; +}; + +jasmine.Env.prototype.it = function(description, func) { + var spec = new jasmine.Spec(this, this.currentSuite, description); + this.currentSuite.add(spec); + this.currentSpec = spec; + + if (func) { + spec.runs(func); + } + + return spec; +}; + +jasmine.Env.prototype.xit = function(desc, func) { + return { + id: this.nextSpecId(), + runs: function() { + } + }; +}; + +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; + } + + a.__Jasmine_been_here_before__ = b; + b.__Jasmine_been_here_before__ = a; + + var hasKey = function(obj, keyName) { + return obj !== null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in b) { + if (!hasKey(a, property) && hasKey(b, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + } + for (property in a) { + if (!hasKey(b, property) && hasKey(a, property)) { + mismatchKeys.push("expected missing key '" + property + "', but present in actual."); + } + } + for (property in b) { + if (property == '__Jasmine_been_here_before__') continue; + if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); + } + } + + if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { + mismatchValues.push("arrays were not the same length"); + } + + delete a.__Jasmine_been_here_before__; + delete b.__Jasmine_been_here_before__; + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + for (var i = 0; i < this.equalityTesters_.length; i++) { + var equalityTester = this.equalityTesters_[i]; + var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); + if (result !== jasmine.undefined) return result; + } + + if (a === b) return true; + + if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { + return (a == jasmine.undefined && b == jasmine.undefined); + } + + if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { + return a === b; + } + + if (a instanceof Date && b instanceof Date) { + return a.getTime() == b.getTime(); + } + + if (a.jasmineMatches) { + return a.jasmineMatches(b); + } + + if (b.jasmineMatches) { + return b.jasmineMatches(a); + } + + if (a instanceof jasmine.Matchers.ObjectContaining) { + return a.matches(b); + } + + if (b instanceof jasmine.Matchers.ObjectContaining) { + return b.matches(a); + } + + if (jasmine.isString_(a) && jasmine.isString_(b)) { + return (a == b); + } + + if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { + 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); + } + + //Straight check + return (a === b); +}; + +jasmine.Env.prototype.contains_ = function(haystack, needle) { + if (jasmine.isArray_(haystack)) { + for (var i = 0; i < haystack.length; i++) { + if (this.equals_(haystack[i], needle)) return true; + } + return false; + } + return haystack.indexOf(needle) >= 0; +}; + +jasmine.Env.prototype.addEqualityTester = function(equalityTester) { + this.equalityTesters_.push(equalityTester); +}; +/** No-op base class for Jasmine reporters. + * + * @constructor + */ +jasmine.Reporter = function() { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerResults = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecStarting = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecResults = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.log = function(str) { +}; + +/** + * Blocks are functions with executable code that make up a spec. + * + * @constructor + * @param {jasmine.Env} env + * @param {Function} func + * @param {jasmine.Spec} spec + */ +jasmine.Block = function(env, func, spec) { + this.env = env; + this.func = func; + this.spec = spec; +}; + +jasmine.Block.prototype.execute = function(onComplete) { + if (!jasmine.CATCH_EXCEPTIONS) { + this.func.apply(this.spec); + } + else { + try { + this.func.apply(this.spec); + } catch (e) { + this.spec.fail(e); + } + } + onComplete(); +}; +/** JavaScript API reporter. + * + * @constructor + */ +jasmine.JsApiReporter = function() { + this.started = false; + this.finished = false; + this.suites_ = []; + this.results_ = {}; +}; + +jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { + this.started = true; + var suites = runner.topLevelSuites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + this.suites_.push(this.summarize_(suite)); + } +}; + +jasmine.JsApiReporter.prototype.suites = function() { + return this.suites_; +}; + +jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { + var isSuite = suiteOrSpec instanceof jasmine.Suite; + var summary = { + id: suiteOrSpec.id, + name: suiteOrSpec.description, + type: isSuite ? 'suite' : 'spec', + children: [] + }; + + if (isSuite) { + var children = suiteOrSpec.children(); + for (var i = 0; i < children.length; i++) { + summary.children.push(this.summarize_(children[i])); + } + } + return summary; +}; + +jasmine.JsApiReporter.prototype.results = function() { + return this.results_; +}; + +jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { + return this.results_[specId]; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { + this.finished = true; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { + this.results_[spec.id] = { + messages: spec.results().getItems(), + result: spec.results().failedCount > 0 ? "failed" : "passed" + }; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.log = function(str) { +}; + +jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ + var results = {}; + for (var i = 0; i < specIds.length; i++) { + var specId = specIds[i]; + results[specId] = this.summarizeResult_(this.results_[specId]); + } + return results; +}; + +jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ + var summaryMessages = []; + var messagesLength = result.messages.length; + for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { + var resultMessage = result.messages[messageIndex]; + summaryMessages.push({ + text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, + passed: resultMessage.passed ? resultMessage.passed() : true, + type: resultMessage.type, + message: resultMessage.message, + trace: { + stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined + } + }); + } + + return { + result : result.result, + messages : summaryMessages + }; +}; + +/** + * @constructor + * @param {jasmine.Env} env + * @param actual + * @param {jasmine.Spec} spec + */ +jasmine.Matchers = function(env, actual, spec, opt_isNot) { + this.env = env; + this.actual = actual; + this.spec = spec; + this.isNot = opt_isNot || false; + this.reportWasCalled_ = false; +}; + +// todo: @deprecated as of Jasmine 0.11, remove soon [xw] +jasmine.Matchers.pp = function(str) { + throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); +}; + +// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] +jasmine.Matchers.prototype.report = function(result, failing_message, details) { + throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); +}; + +jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { + for (var methodName in prototype) { + if (methodName == 'report') continue; + var orig = prototype[methodName]; + matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); + } +}; + +jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { + return function() { + var matcherArgs = jasmine.util.argsToArray(arguments); + var result = matcherFunction.apply(this, arguments); + + if (this.isNot) { + result = !result; + } + + if (this.reportWasCalled_) return result; + + var message; + if (!result) { + if (this.message) { + message = this.message.apply(this, arguments); + if (jasmine.isArray_(message)) { + message = message[this.isNot ? 1 : 0]; + } + } else { + var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); + message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; + if (matcherArgs.length > 0) { + for (var i = 0; i < matcherArgs.length; i++) { + if (i > 0) message += ","; + message += " " + jasmine.pp(matcherArgs[i]); + } + } + message += "."; + } + } + var expectationResult = new jasmine.ExpectationResult({ + matcherName: matcherName, + passed: result, + expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], + actual: this.actual, + message: message + }); + this.spec.addMatcherResult(expectationResult); + return jasmine.undefined; + }; +}; + + + + +/** + * toBe: compares the actual to the expected using === + * @param expected + */ +jasmine.Matchers.prototype.toBe = function(expected) { + return this.actual === expected; +}; + +/** + * toNotBe: compares the actual to the expected using !== + * @param expected + * @deprecated as of 1.0. Use not.toBe() instead. + */ +jasmine.Matchers.prototype.toNotBe = function(expected) { + return this.actual !== expected; +}; + +/** + * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. + * + * @param expected + */ +jasmine.Matchers.prototype.toEqual = function(expected) { + return this.env.equals_(this.actual, expected); +}; + +/** + * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual + * @param expected + * @deprecated as of 1.0. Use not.toEqual() instead. + */ +jasmine.Matchers.prototype.toNotEqual = function(expected) { + return !this.env.equals_(this.actual, expected); +}; + +/** + * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes + * a pattern or a String. + * + * @param expected + */ +jasmine.Matchers.prototype.toMatch = function(expected) { + return new RegExp(expected).test(this.actual); +}; + +/** + * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch + * @param expected + * @deprecated as of 1.0. Use not.toMatch() instead. + */ +jasmine.Matchers.prototype.toNotMatch = function(expected) { + return !(new RegExp(expected).test(this.actual)); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeDefined = function() { + return (this.actual !== jasmine.undefined); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeUndefined = function() { + return (this.actual === jasmine.undefined); +}; + +/** + * Matcher that compares the actual to null. + */ +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. + */ +jasmine.Matchers.prototype.toBeTruthy = function() { + return !!this.actual; +}; + + +/** + * Matcher that boolean nots the actual. + */ +jasmine.Matchers.prototype.toBeFalsy = function() { + return !this.actual; +}; + + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called. + */ +jasmine.Matchers.prototype.toHaveBeenCalled = function() { + if (arguments.length > 0) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to have been called.", + "Expected spy " + this.actual.identity + " not to have been called." + ]; + }; + + return this.actual.wasCalled; +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ +jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was not called. + * + * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead + */ +jasmine.Matchers.prototype.wasNotCalled = function() { + if (arguments.length > 0) { + throw new Error('wasNotCalled does not take arguments'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to not have been called.", + "Expected spy " + this.actual.identity + " to have been called." + ]; + }; + + return !this.actual.wasCalled; +}; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. + * + * @example + * + */ +jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + 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) { + positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called."; + } else { + 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); +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; + +/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasNotCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = 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); +}; + +/** + * Matcher that checks that the expected item is an element in the actual Array. + * + * @param {Object} expected + */ +jasmine.Matchers.prototype.toContain = function(expected) { + return this.env.contains_(this.actual, expected); +}; + +/** + * Matcher that checks that the expected item is NOT an element in the actual Array. + * + * @param {Object} expected + * @deprecated as of 1.0. Use not.toContain() instead. + */ +jasmine.Matchers.prototype.toNotContain = function(expected) { + return !this.env.contains_(this.actual, expected); +}; + +jasmine.Matchers.prototype.toBeLessThan = function(expected) { + return this.actual < expected; +}; + +jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { + return this.actual > expected; +}; + +/** + * Matcher that checks that the expected item is equal to the actual item + * up to a given level of decimal precision (default 2). + * + * @param {Number} expected + * @param {Number} precision, as number of decimal places + */ +jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { + if (!(precision === 0)) { + precision = precision || 2; + } + 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] + */ +jasmine.Matchers.prototype.toThrow = function(expected) { + var result = false; + var exception; + if (typeof this.actual != 'function') { + throw new Error('Actual is not a function'); + } + try { + this.actual(); + } catch (e) { + exception = e; + } + if (exception) { + result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); + } + + var not = this.isNot ? "not " : ""; + + 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(' '); + } else { + return "Expected function to throw an exception."; + } + }; + + return result; +}; + +jasmine.Matchers.Any = function(expectedClass) { + this.expectedClass = expectedClass; +}; + +jasmine.Matchers.Any.prototype.jasmineMatches = function(other) { + if (this.expectedClass == String) { + return typeof other == 'string' || other instanceof String; + } + + if (this.expectedClass == Number) { + return typeof other == 'number' || other instanceof Number; + } + + if (this.expectedClass == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedClass == Object) { + return typeof other == 'object'; + } + + return other instanceof this.expectedClass; +}; + +jasmine.Matchers.Any.prototype.jasmineToString = function() { + return ''; +}; + +jasmine.Matchers.ObjectContaining = function (sample) { + this.sample = sample; +}; + +jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + var env = jasmine.getEnv(); + + var hasKey = function(obj, keyName) { + return obj != null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in this.sample) { + if (!hasKey(other, property) && hasKey(this.sample, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual."); + } + } + + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () { + return ""; +}; +// Mock setTimeout, clearTimeout +// Contributed by Pivotal Computer Systems, www.pivotalsf.com + +jasmine.FakeTimer = function() { + this.reset(); + + var self = this; + self.setTimeout = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); + return self.timeoutsMade; + }; + + self.setInterval = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); + return self.timeoutsMade; + }; + + self.clearTimeout = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + + self.clearInterval = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + +}; + +jasmine.FakeTimer.prototype.reset = function() { + this.timeoutsMade = 0; + this.scheduledFunctions = {}; + this.nowMillis = 0; +}; + +jasmine.FakeTimer.prototype.tick = function(millis) { + var oldMillis = this.nowMillis; + var newMillis = oldMillis + millis; + this.runFunctionsWithinRange(oldMillis, newMillis); + this.nowMillis = newMillis; +}; + +jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { + var scheduledFunc; + var funcsToRun = []; + for (var timeoutKey in this.scheduledFunctions) { + scheduledFunc = this.scheduledFunctions[timeoutKey]; + if (scheduledFunc != jasmine.undefined && + scheduledFunc.runAtMillis >= oldMillis && + scheduledFunc.runAtMillis <= nowMillis) { + funcsToRun.push(scheduledFunc); + this.scheduledFunctions[timeoutKey] = jasmine.undefined; + } + } + + if (funcsToRun.length > 0) { + funcsToRun.sort(function(a, b) { + return a.runAtMillis - b.runAtMillis; + }); + for (var i = 0; i < funcsToRun.length; ++i) { + try { + var funcToRun = funcsToRun[i]; + this.nowMillis = funcToRun.runAtMillis; + funcToRun.funcToCall(); + if (funcToRun.recurring) { + this.scheduleFunction(funcToRun.timeoutKey, + funcToRun.funcToCall, + funcToRun.millis, + true); + } + } catch(e) { + } + } + this.runFunctionsWithinRange(oldMillis, nowMillis); + } +}; + +jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { + this.scheduledFunctions[timeoutKey] = { + runAtMillis: this.nowMillis + millis, + funcToCall: funcToCall, + recurring: recurring, + timeoutKey: timeoutKey, + millis: millis + }; +}; + +/** + * @namespace + */ +jasmine.Clock = { + defaultFakeTimer: new jasmine.FakeTimer(), + + reset: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.reset(); + }, + + tick: function(millis) { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.tick(millis); + }, + + runFunctionsWithinRange: function(oldMillis, nowMillis) { + jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); + }, + + scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { + jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); + }, + + useMock: function() { + if (!jasmine.Clock.isInstalled()) { + var spec = jasmine.getEnv().currentSpec; + spec.after(jasmine.Clock.uninstallMock); + + jasmine.Clock.installMock(); + } + }, + + installMock: function() { + jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; + }, + + uninstallMock: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.installed = jasmine.Clock.real; + }, + + real: { + setTimeout: jasmine.getGlobal().setTimeout, + clearTimeout: jasmine.getGlobal().clearTimeout, + setInterval: jasmine.getGlobal().setInterval, + clearInterval: jasmine.getGlobal().clearInterval + }, + + assertInstalled: function() { + if (!jasmine.Clock.isInstalled()) { + throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); + } + }, + + isInstalled: function() { + return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; + }, + + installed: null +}; +jasmine.Clock.installed = jasmine.Clock.real; + +//else for IE support +jasmine.getGlobal().setTimeout = function(funcToCall, millis) { + if (jasmine.Clock.installed.setTimeout.apply) { + return jasmine.Clock.installed.setTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.setTimeout(funcToCall, millis); + } +}; + +jasmine.getGlobal().setInterval = function(funcToCall, millis) { + if (jasmine.Clock.installed.setInterval.apply) { + return jasmine.Clock.installed.setInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.setInterval(funcToCall, millis); + } +}; + +jasmine.getGlobal().clearTimeout = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearTimeout(timeoutKey); + } +}; + +jasmine.getGlobal().clearInterval = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearInterval(timeoutKey); + } +}; + +/** + * @constructor + */ +jasmine.MultiReporter = function() { + this.subReporters_ = []; +}; +jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); + +jasmine.MultiReporter.prototype.addReporter = function(reporter) { + this.subReporters_.push(reporter); +}; + +(function() { + var functionNames = [ + "reportRunnerStarting", + "reportRunnerResults", + "reportSuiteResults", + "reportSpecStarting", + "reportSpecResults", + "log" + ]; + for (var i = 0; i < functionNames.length; i++) { + var functionName = functionNames[i]; + jasmine.MultiReporter.prototype[functionName] = (function(functionName) { + return function() { + for (var j = 0; j < this.subReporters_.length; j++) { + var subReporter = this.subReporters_[j]; + if (subReporter[functionName]) { + subReporter[functionName].apply(subReporter, arguments); + } + } + }; + })(functionName); + } +})(); +/** + * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults + * + * @constructor + */ +jasmine.NestedResults = function() { + /** + * The total count of results + */ + this.totalCount = 0; + /** + * Number of passed results + */ + this.passedCount = 0; + /** + * Number of failed results + */ + this.failedCount = 0; + /** + * Was this suite/spec skipped? + */ + this.skipped = false; + /** + * @ignore + */ + this.items_ = []; +}; + +/** + * Roll up the result counts. + * + * @param result + */ +jasmine.NestedResults.prototype.rollupCounts = function(result) { + this.totalCount += result.totalCount; + this.passedCount += result.passedCount; + this.failedCount += result.failedCount; +}; + +/** + * Adds a log message. + * @param values Array of message parts which will be concatenated later. + */ +jasmine.NestedResults.prototype.log = function(values) { + this.items_.push(new jasmine.MessageResult(values)); +}; + +/** + * Getter for the results: message & results. + */ +jasmine.NestedResults.prototype.getItems = function() { + return this.items_; +}; + +/** + * Adds a result, tracking counts (total, passed, & failed) + * @param {jasmine.ExpectationResult|jasmine.NestedResults} result + */ +jasmine.NestedResults.prototype.addResult = function(result) { + if (result.type != 'log') { + if (result.items_) { + this.rollupCounts(result); + } else { + this.totalCount++; + if (result.passed()) { + this.passedCount++; + } else { + this.failedCount++; + } + } + } + this.items_.push(result); +}; + +/** + * @returns {Boolean} True if everything below passed + */ +jasmine.NestedResults.prototype.passed = function() { + return this.passedCount === this.totalCount; +}; +/** + * Base class for pretty printing for expectation results. + */ +jasmine.PrettyPrinter = function() { + this.ppNestLevel_ = 0; +}; + +/** + * Formats a value in a nice, human-readable string. + * + * @param value + */ +jasmine.PrettyPrinter.prototype.format = function(value) { + this.ppNestLevel_++; + try { + if (value === jasmine.undefined) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === jasmine.getGlobal()) { + this.emitScalar(''); + } else if (value.jasmineToString) { + this.emitScalar(value.jasmineToString()); + } else if (typeof value === 'string') { + this.emitString(value); + } else if (jasmine.isSpy(value)) { + this.emitScalar("spy on " + value.identity); + } else if (value instanceof RegExp) { + this.emitScalar(value.toString()); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (value.__Jasmine_been_here_before__) { + this.emitScalar(''); + } else if (jasmine.isArray_(value) || typeof value == 'object') { + value.__Jasmine_been_here_before__ = true; + if (jasmine.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + delete value.__Jasmine_been_here_before__; + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } +}; + +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); + } +}; + +jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; + +jasmine.StringPrettyPrinter = function() { + jasmine.PrettyPrinter.call(this); + + this.string = ''; +}; +jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); + +jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); +}; + +jasmine.StringPrettyPrinter.prototype.emitString = function(value) { + this.append("'" + 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) { + this.append(', '); + } + this.format(array[i]); + } + this.append(' ]'); +}; + +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; + + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } + + self.append(property); + self.append(' : '); + if (isGetter) { + self.append(''); + } else { + self.format(obj[property]); + } + }); + + this.append(' }'); +}; + +jasmine.StringPrettyPrinter.prototype.append = function(value) { + this.string += 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; + this.offset = 0; + this.abort = false; +}; + +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, ensure) { + if (ensure === jasmine.undefined) { + ensure = false; + } + + this.blocks.push(block); + this.ensured.push(ensure); +}; + +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++; +}; + +jasmine.Queue.prototype.start = function(onComplete) { + this.running = true; + this.onComplete = onComplete; + this.next_(); +}; + +jasmine.Queue.prototype.isRunning = function() { + return this.running; +}; + +jasmine.Queue.LOOP_DONT_RECURSE = true; + +jasmine.Queue.prototype.next_ = function() { + var self = this; + var goAgain = true; + + while (goAgain) { + goAgain = false; + + if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) { + var calledSynchronously = true; + var completedSynchronously = false; + + var onComplete = function () { + if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { + completedSynchronously = true; + return; + } + + if (self.blocks[self.index].abort) { + self.abort = true; + } + + self.offset = 0; + self.index++; + + var now = new Date().getTime(); + if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { + self.env.lastUpdate = now; + self.env.setTimeout(function() { + self.next_(); + }, 0); + } else { + if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { + goAgain = true; + } else { + self.next_(); + } + } + }; + self.blocks[self.index].execute(onComplete); + + calledSynchronously = false; + if (completedSynchronously) { + onComplete(); + } + + } else { + self.running = false; + if (self.onComplete) { + self.onComplete(); + } + } + } +}; + +jasmine.Queue.prototype.results = function() { + var results = new jasmine.NestedResults(); + for (var i = 0; i < this.blocks.length; i++) { + if (this.blocks[i].results) { + results.addResult(this.blocks[i].results()); + } + } + return results; +}; + + +/** + * Runner + * + * @constructor + * @param {jasmine.Env} env + */ +jasmine.Runner = function(env) { + var self = this; + self.env = env; + self.queue = new jasmine.Queue(env); + self.before_ = []; + self.after_ = []; + self.suites_ = []; +}; + +jasmine.Runner.prototype.execute = function() { + var self = this; + if (self.env.reporter.reportRunnerStarting) { + self.env.reporter.reportRunnerStarting(this); + } + self.queue.start(function () { + self.finishCallback(); + }); +}; + +jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.splice(0,0,beforeEachFunction); +}; + +jasmine.Runner.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.splice(0,0,afterEachFunction); +}; + + +jasmine.Runner.prototype.finishCallback = function() { + this.env.reporter.reportRunnerResults(this); +}; + +jasmine.Runner.prototype.addSuite = function(suite) { + this.suites_.push(suite); +}; + +jasmine.Runner.prototype.add = function(block) { + if (block instanceof jasmine.Suite) { + this.addSuite(block); + } + this.queue.add(block); +}; + +jasmine.Runner.prototype.specs = function () { + var suites = this.suites(); + var specs = []; + for (var i = 0; i < suites.length; i++) { + specs = specs.concat(suites[i].specs()); + } + return specs; +}; + +jasmine.Runner.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Runner.prototype.topLevelSuites = function() { + var topLevelSuites = []; + for (var i = 0; i < this.suites_.length; i++) { + if (!this.suites_[i].parentSuite) { + topLevelSuites.push(this.suites_[i]); + } + } + return topLevelSuites; +}; + +jasmine.Runner.prototype.results = function() { + return this.queue.results(); +}; +/** + * Internal representation of a Jasmine specification, or test. + * + * @constructor + * @param {jasmine.Env} env + * @param {jasmine.Suite} suite + * @param {String} description + */ +jasmine.Spec = function(env, suite, description) { + if (!env) { + throw new Error('jasmine.Env() required'); + } + if (!suite) { + throw new Error('jasmine.Suite() required'); + } + var spec = this; + spec.id = env.nextSpecId ? env.nextSpecId() : null; + spec.env = env; + spec.suite = suite; + spec.description = description; + spec.queue = new jasmine.Queue(env); + + spec.afterCallbacks = []; + spec.spies_ = []; + + spec.results_ = new jasmine.NestedResults(); + spec.results_.description = description; + spec.matchersClass = null; +}; + +jasmine.Spec.prototype.getFullName = function() { + return this.suite.getFullName() + ' ' + this.description + '.'; +}; + + +jasmine.Spec.prototype.results = function() { + return this.results_; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.Spec.prototype.log = function() { + return this.results_.log(arguments); +}; + +jasmine.Spec.prototype.runs = function (func) { + var block = new jasmine.Block(this.env, func, this); + this.addToQueue(block); + return this; +}; + +jasmine.Spec.prototype.addToQueue = function (block) { + if (this.queue.isRunning()) { + this.queue.insertNext(block); + } else { + this.queue.add(block); + } +}; + +/** + * @param {jasmine.ExpectationResult} result + */ +jasmine.Spec.prototype.addMatcherResult = function(result) { + this.results_.addResult(result); +}; + +jasmine.Spec.prototype.expect = function(actual) { + var positive = new (this.getMatchersClass_())(this.env, actual, this); + positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); + return positive; +}; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +jasmine.Spec.prototype.waits = function(timeout) { + var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); + this.addToQueue(waitsFunc); + return this; +}; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + var latchFunction_ = null; + var optional_timeoutMessage_ = null; + var optional_timeout_ = null; + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + switch (typeof arg) { + case 'function': + latchFunction_ = arg; + break; + case 'string': + optional_timeoutMessage_ = arg; + break; + case 'number': + optional_timeout_ = arg; + break; + } + } + + var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); + this.addToQueue(waitsForFunc); + return this; +}; + +jasmine.Spec.prototype.fail = function (e) { + var expectationResult = new jasmine.ExpectationResult({ + passed: false, + message: e ? jasmine.util.formatException(e) : 'Exception', + trace: { stack: e.stack } + }); + this.results_.addResult(expectationResult); +}; + +jasmine.Spec.prototype.getMatchersClass_ = function() { + return this.matchersClass || this.env.matchersClass; +}; + +jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { + var parent = this.getMatchersClass_(); + var newMatchersClass = function() { + parent.apply(this, arguments); + }; + jasmine.util.inherit(newMatchersClass, parent); + jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); + this.matchersClass = newMatchersClass; +}; + +jasmine.Spec.prototype.finishCallback = function() { + this.env.reporter.reportSpecResults(this); +}; + +jasmine.Spec.prototype.finish = function(onComplete) { + this.removeAllSpies(); + this.finishCallback(); + if (onComplete) { + onComplete(); + } +}; + +jasmine.Spec.prototype.after = function(doAfter) { + if (this.queue.isRunning()) { + this.queue.add(new jasmine.Block(this.env, doAfter, this), true); + } else { + this.afterCallbacks.unshift(doAfter); + } +}; + +jasmine.Spec.prototype.execute = function(onComplete) { + var spec = this; + if (!spec.env.specFilter(spec)) { + spec.results_.skipped = true; + spec.finish(onComplete); + return; + } + + this.env.reporter.reportSpecStarting(this); + + spec.env.currentSpec = spec; + + spec.addBeforesAndAftersToQueue(); + + spec.queue.start(function () { + spec.finish(onComplete); + }); +}; + +jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { + var runner = this.env.currentRunner(); + var i; + + for (var suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); + } + } + for (i = 0; i < runner.before_.length; i++) { + 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), 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), true); + } + } + for (i = 0; i < runner.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true); + } +}; + +jasmine.Spec.prototype.explodes = function() { + throw 'explodes function should not have been called'; +}; + +jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { + if (obj == jasmine.undefined) { + throw "spyOn could not find an object to spy upon for " + methodName + "()"; + } + + if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { + throw methodName + '() method does not exist'; + } + + if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { + throw new Error(methodName + ' has already been spied upon'); + } + + var spyObj = jasmine.createSpy(methodName); + + this.spies_.push(spyObj); + spyObj.baseObj = obj; + spyObj.methodName = methodName; + spyObj.originalValue = obj[methodName]; + + obj[methodName] = spyObj; + + return spyObj; +}; + +jasmine.Spec.prototype.removeAllSpies = function() { + for (var i = 0; i < this.spies_.length; i++) { + var spy = this.spies_[i]; + spy.baseObj[spy.methodName] = spy.originalValue; + } + this.spies_ = []; +}; + +/** + * Internal representation of a Jasmine suite. + * + * @constructor + * @param {jasmine.Env} env + * @param {String} description + * @param {Function} specDefinitions + * @param {jasmine.Suite} parentSuite + */ +jasmine.Suite = function(env, description, specDefinitions, parentSuite) { + var self = this; + self.id = env.nextSuiteId ? env.nextSuiteId() : null; + self.description = description; + self.queue = new jasmine.Queue(env); + self.parentSuite = parentSuite; + self.env = env; + self.before_ = []; + self.after_ = []; + self.children_ = []; + self.suites_ = []; + self.specs_ = []; +}; + +jasmine.Suite.prototype.getFullName = function() { + var fullName = this.description; + for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + fullName = parentSuite.description + ' ' + fullName; + } + return fullName; +}; + +jasmine.Suite.prototype.finish = function(onComplete) { + this.env.reporter.reportSuiteResults(this); + this.finished = true; + if (typeof(onComplete) == 'function') { + onComplete(); + } +}; + +jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.unshift(beforeEachFunction); +}; + +jasmine.Suite.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.unshift(afterEachFunction); +}; + +jasmine.Suite.prototype.results = function() { + return this.queue.results(); +}; + +jasmine.Suite.prototype.add = function(suiteOrSpec) { + this.children_.push(suiteOrSpec); + if (suiteOrSpec instanceof jasmine.Suite) { + this.suites_.push(suiteOrSpec); + this.env.currentRunner().addSuite(suiteOrSpec); + } else { + this.specs_.push(suiteOrSpec); + } + this.queue.add(suiteOrSpec); +}; + +jasmine.Suite.prototype.specs = function() { + return this.specs_; +}; + +jasmine.Suite.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Suite.prototype.children = function() { + return this.children_; +}; + +jasmine.Suite.prototype.execute = function(onComplete) { + var self = this; + this.queue.start(function () { + self.finish(onComplete); + }); +}; +jasmine.WaitsBlock = function(env, timeout, spec) { + this.timeout = timeout; + jasmine.Block.call(this, env, null, spec); +}; + +jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); + +jasmine.WaitsBlock.prototype.execute = function (onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); + } + this.env.setTimeout(function () { + onComplete(); + }, this.timeout); +}; +/** + * A block which waits for some condition to become true, with timeout. + * + * @constructor + * @extends jasmine.Block + * @param {jasmine.Env} env The Jasmine environment. + * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. + * @param {Function} latchFunction A function which returns true when the desired condition has been met. + * @param {String} message The message to display if the desired condition hasn't been met within the given time period. + * @param {jasmine.Spec} spec The Jasmine spec. + */ +jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { + this.timeout = timeout || env.defaultTimeoutInterval; + this.latchFunction = latchFunction; + this.message = message; + this.totalTimeSpentWaitingForLatch = 0; + jasmine.Block.call(this, env, null, spec); +}; +jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); + +jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; + +jasmine.WaitsForBlock.prototype.execute = function(onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); + } + var latchFunctionResult; + try { + latchFunctionResult = this.latchFunction.apply(this.spec); + } catch (e) { + this.spec.fail(e); + onComplete(); + return; + } + + if (latchFunctionResult) { + onComplete(); + } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { + var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); + this.spec.fail({ + name: 'timeout', + message: message + }); + + this.abort = true; + onComplete(); + } else { + this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; + var self = this; + this.env.setTimeout(function() { + self.execute(onComplete); + }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); + } +}; + +jasmine.version_= { + "major": 1, + "minor": 3, + "build": 1, + "revision": 1354556913 +}; diff --git a/vendor/assets/javascripts/jasmine_1_3/jasminerice.js.coffee b/vendor/assets/javascripts/jasmine_1_3/jasminerice.js.coffee new file mode 100644 index 0000000..bd1105a --- /dev/null +++ b/vendor/assets/javascripts/jasmine_1_3/jasminerice.js.coffee @@ -0,0 +1,34 @@ +#=require jasmine_1_3/jasmine +#=require jasmine_1_3/jasmine-html +#=require jasmine_1_3/jasmine-jquery + +console.log('running V1.3') + +(-> + execJasmine = -> + jasmineEnv.execute() + jasmineEnv = jasmine.getEnv() + jasmineEnv.updateInterval = 1000 + + window.jsApiReporter = new jasmine.JsApiReporter() + htmlReporter = new jasmine.HtmlReporter() + + jasmineEnv.addReporter htmlReporter + jasmineEnv.addReporter jsApiReporter + + jasmineEnv.specFilter = (spec) -> + htmlReporter.specFilter spec + + jasmine.getFixtures().fixturesPath = 'jasmine/fixtures' + jasmine.getStyleFixtures().fixturesPath = 'jasmine/fixtures' + jasmine.getJSONFixtures().fixturesPath = 'jasmine/fixtures/json' + + jasmine.rice = {} + jasmine.rice.autoExecute = true + + currentWindowOnload = window.onload + window.onload = -> + currentWindowOnload() if currentWindowOnload + if jasmine.rice.autoExecute + execJasmine() +)() diff --git a/vendor/assets/javascripts/boot.js b/vendor/assets/javascripts/jasmine_2_0/boot.js similarity index 100% rename from vendor/assets/javascripts/boot.js rename to vendor/assets/javascripts/jasmine_2_0/boot.js diff --git a/vendor/assets/javascripts/jasmine-html.js b/vendor/assets/javascripts/jasmine_2_0/jasmine-html.js similarity index 100% rename from vendor/assets/javascripts/jasmine-html.js rename to vendor/assets/javascripts/jasmine_2_0/jasmine-html.js diff --git a/vendor/assets/javascripts/jasmine-jquery.js b/vendor/assets/javascripts/jasmine_2_0/jasmine-jquery.js similarity index 100% rename from vendor/assets/javascripts/jasmine-jquery.js rename to vendor/assets/javascripts/jasmine_2_0/jasmine-jquery.js diff --git a/vendor/assets/javascripts/jasmine.js b/vendor/assets/javascripts/jasmine_2_0/jasmine.js similarity index 100% rename from vendor/assets/javascripts/jasmine.js rename to vendor/assets/javascripts/jasmine_2_0/jasmine.js diff --git a/app/assets/javascripts/jasminerice.js.coffee b/vendor/assets/javascripts/jasmine_2_0/jasminerice.js.coffee similarity index 59% rename from app/assets/javascripts/jasminerice.js.coffee rename to vendor/assets/javascripts/jasmine_2_0/jasminerice.js.coffee index 595da94..3124c84 100644 --- a/app/assets/javascripts/jasminerice.js.coffee +++ b/vendor/assets/javascripts/jasmine_2_0/jasminerice.js.coffee @@ -1,11 +1,12 @@ -#=require jasmine -#=require jasmine-html -#=require boot +#=require jasmine_2_0/jasmine +#=require jasmine_2_0/jasmine-html +#=require jasmine_2_0/boot #=require jquery -#=require jasmine-jquery.js +#=require jasmine_2_0/jasmine-jquery + +console.log('running V2.0') # Override the fixture paths jasmine.getFixtures().fixturesPath = 'jasmine/fixtures' jasmine.getStyleFixtures().fixturesPath = 'jasmine/fixtures' jasmine.getJSONFixtures().fixturesPath = 'jasmine/fixtures/json' - diff --git a/vendor/assets/stylesheets/jasmine_1_3/jasmine.css b/vendor/assets/stylesheets/jasmine_1_3/jasmine.css new file mode 100644 index 0000000..8c008dc --- /dev/null +++ b/vendor/assets/stylesheets/jasmine_1_3/jasmine.css @@ -0,0 +1,82 @@ +body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } + +#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } +#HTMLReporter a { text-decoration: none; } +#HTMLReporter a:hover { text-decoration: underline; } +#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; } +#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; } +#HTMLReporter #jasmine_content { position: fixed; right: 100%; } +#HTMLReporter .version { color: #aaaaaa; } +#HTMLReporter .banner { margin-top: 14px; } +#HTMLReporter .duration { color: #aaaaaa; float: right; } +#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; } +#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; } +#HTMLReporter .symbolSummary li.passed { font-size: 14px; } +#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; } +#HTMLReporter .symbolSummary li.failed { line-height: 9px; } +#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; } +#HTMLReporter .symbolSummary li.skipped { font-size: 14px; } +#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; } +#HTMLReporter .skippedAlert:first-child { background-color: #333333; } +#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; } +#HTMLReporter .passingAlert { background-color: #a6b779; } +#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; } +#HTMLReporter .failingAlert { background-color: #cf867e; } +#HTMLReporter .failingAlert:first-child { background-color: #b03911; } +#HTMLReporter .results { margin-top: 14px; } +#HTMLReporter #details { display: none; } +#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; } +#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } +#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } +#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } +#HTMLReporter.showDetails .summary { display: none; } +#HTMLReporter.showDetails #details { display: block; } +#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } +#HTMLReporter .summary { margin-top: 14px; } +#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; } +#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; } +#HTMLReporter .summary .specSummary.failed a { color: #b03911; } +#HTMLReporter .description + .suite { margin-top: 0; } +#HTMLReporter .suite { margin-top: 14px; } +#HTMLReporter .suite a { color: #333333; } +#HTMLReporter #details .specDetail { margin-bottom: 28px; } +#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; } +#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; } +#HTMLReporter .resultMessage span.result { display: block; } +#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } + +#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ } +#TrivialReporter a:visited, #TrivialReporter a { color: #303; } +#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; } +#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; } +#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; } +#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; } +#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; } +#TrivialReporter .runner.running { background-color: yellow; } +#TrivialReporter .options { text-align: right; font-size: .8em; } +#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; } +#TrivialReporter .suite .suite { margin: 5px; } +#TrivialReporter .suite.passed { background-color: #dfd; } +#TrivialReporter .suite.failed { background-color: #fdd; } +#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; } +#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; } +#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; } +#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; } +#TrivialReporter .spec.skipped { background-color: #bbb; } +#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; } +#TrivialReporter .passed { background-color: #cfc; display: none; } +#TrivialReporter .failed { background-color: #fbb; } +#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; } +#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; } +#TrivialReporter .resultMessage .mismatch { color: black; } +#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; } +#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; } +#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; } +#TrivialReporter #jasmine_content { position: fixed; right: 100%; } +#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; } diff --git a/vendor/assets/stylesheets/jasmine.css b/vendor/assets/stylesheets/jasmine_2_0/jasmine.css similarity index 100% rename from vendor/assets/stylesheets/jasmine.css rename to vendor/assets/stylesheets/jasmine_2_0/jasmine.css From a8cb4e15e51f18f8ddc8ecc5b1361103d1a71f5b Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Thu, 15 Jan 2015 11:13:53 +1000 Subject: [PATCH 13/16] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2638f2e..0588067 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Just include it in your `Gemfile`: ```ruby group :development, :test do - gem "jasminerice", :git => 'https://github.com/bradphelan/jasminerice.git' + gem "jasminerice", :git => 'https://github.com/michael-harrison/jasminerice.git' end ``` From 5b18865753ece7d1e716f08ea370678cd06f2d10 Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Fri, 6 Mar 2015 09:42:00 +1000 Subject: [PATCH 14/16] Upgraded to Jasmine 2.0.3 Upgraded to Jasmin jQuery 2.0.7 Updated selenium-webdriver for testing --- .gitignore | 7 + Gemfile.lock | 18 +- vendor/assets/javascripts/jasmine_2_0/boot.js | 63 +- .../assets/javascripts/jasmine_2_0/console.js | 166 +++++ .../javascripts/jasmine_2_0/jasmine-html.js | 177 +++-- .../javascripts/jasmine_2_0/jasmine-jquery.js | 195 ++--- .../assets/javascripts/jasmine_2_0/jasmine.js | 703 +++++++++++------- 7 files changed, 841 insertions(+), 488 deletions(-) create mode 100755 vendor/assets/javascripts/jasmine_2_0/console.js diff --git a/.gitignore b/.gitignore index d5afca3..63c99b2 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,10 @@ public/system *.*.gz Session.vim err.txt + +# RubyMine project files +.idea + +# Mac finder artifacts +.DS_Store + diff --git a/Gemfile.lock b/Gemfile.lock index ac3572e..03e2b78 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -47,7 +47,7 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) - childprocess (0.5.3) + childprocess (0.5.5) ffi (~> 1.0, >= 1.0.11) coffee-rails (3.2.2) coffee-script (>= 2.2.0) @@ -65,8 +65,8 @@ GEM diff-lcs (1.2.5) erubis (2.7.0) execjs (2.2.1) - ffi (1.9.3) - ffi (1.9.3-java) + ffi (1.9.6) + ffi (1.9.6-java) gherkin (2.12.2) multi_json (~> 1.3) gherkin (2.12.2-java) @@ -92,7 +92,7 @@ GEM mime-types (1.25.1) mini_portile (0.6.0) minitest (4.7.5) - multi_json (1.10.1) + multi_json (1.11.0) multi_test (0.1.1) nokogiri (1.6.3.1) mini_portile (= 0.6.0) @@ -138,17 +138,17 @@ GEM rspec-core (~> 2.99.0) rspec-expectations (~> 2.99.0) rspec-mocks (~> 2.99.0) - rubyzip (1.1.6) + rubyzip (1.1.7) sass (3.3.14) sass-rails (3.2.6) railties (~> 3.2.0) sass (>= 3.1.10) tilt (~> 1.3) - selenium-webdriver (2.42.0) - childprocess (>= 0.5.0) + selenium-webdriver (2.45.0) + childprocess (~> 0.5) multi_json (~> 1.0) rubyzip (~> 1.0) - websocket (~> 1.0.4) + websocket (~> 1.0) sprockets (2.2.2) hike (~> 1.2) multi_json (~> 1.0) @@ -167,7 +167,7 @@ GEM uglifier (2.5.3) execjs (>= 0.3.0) json (>= 1.8.0) - websocket (1.0.7) + websocket (1.2.1) xpath (2.0.0) nokogiri (~> 1.3) diff --git a/vendor/assets/javascripts/jasmine_2_0/boot.js b/vendor/assets/javascripts/jasmine_2_0/boot.js index ec8baa0..406145e 100755 --- a/vendor/assets/javascripts/jasmine_2_0/boot.js +++ b/vendor/assets/javascripts/jasmine_2_0/boot.js @@ -32,47 +32,7 @@ * * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged. */ - var jasmineInterface = { - describe: function(description, specDefinitions) { - return env.describe(description, specDefinitions); - }, - - xdescribe: function(description, specDefinitions) { - return env.xdescribe(description, specDefinitions); - }, - - it: function(desc, func) { - return env.it(desc, func); - }, - - xit: function(desc, func) { - return env.xit(desc, func); - }, - - beforeEach: function(beforeEachFunction) { - return env.beforeEach(beforeEachFunction); - }, - - afterEach: function(afterEachFunction) { - return env.afterEach(afterEachFunction); - }, - - expect: function(actual) { - return env.expect(actual); - }, - - pending: function() { - return env.pending(); - }, - - spyOn: function(obj, methodName) { - return env.spyOn(obj, methodName); - }, - - jsApiReporter: new jasmine.JsApiReporter({ - timer: new jasmine.Timer() - }) - }; + var jasmineInterface = jasmineRequire.interface(jasmine, env); /** * Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`. @@ -83,27 +43,6 @@ extend(window, jasmineInterface); } - /** - * Expose the interface for adding custom equality testers. - */ - jasmine.addCustomEqualityTester = function(tester) { - env.addCustomEqualityTester(tester); - }; - - /** - * Expose the interface for adding custom expectation matchers - */ - jasmine.addMatchers = function(matchers) { - return env.addMatchers(matchers); - }; - - /** - * Expose the mock interface for the JavaScript timeout functions - */ - jasmine.clock = function() { - return env.clock; - }; - /** * ## Runner Parameters * diff --git a/vendor/assets/javascripts/jasmine_2_0/console.js b/vendor/assets/javascripts/jasmine_2_0/console.js new file mode 100755 index 0000000..78b5615 --- /dev/null +++ b/vendor/assets/javascripts/jasmine_2_0/console.js @@ -0,0 +1,166 @@ +/* +Copyright (c) 2008-2014 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +function getJasmineRequireObj() { + if (typeof module !== 'undefined' && module.exports) { + return exports; + } else { + window.jasmineRequire = window.jasmineRequire || {}; + return window.jasmineRequire; + } +} + +getJasmineRequireObj().console = function(jRequire, j$) { + j$.ConsoleReporter = jRequire.ConsoleReporter(); +}; + +getJasmineRequireObj().ConsoleReporter = function() { + + var noopTimer = { + start: function(){}, + elapsed: function(){ return 0; } + }; + + function ConsoleReporter(options) { + var print = options.print, + showColors = options.showColors || false, + onComplete = options.onComplete || function() {}, + timer = options.timer || noopTimer, + specCount, + failureCount, + failedSpecs = [], + pendingCount, + ansi = { + green: '\x1B[32m', + red: '\x1B[31m', + yellow: '\x1B[33m', + none: '\x1B[0m' + }; + + this.jasmineStarted = function() { + specCount = 0; + failureCount = 0; + pendingCount = 0; + print('Started'); + printNewline(); + timer.start(); + }; + + this.jasmineDone = function() { + printNewline(); + for (var i = 0; i < failedSpecs.length; i++) { + specFailureDetails(failedSpecs[i]); + } + + if(specCount > 0) { + printNewline(); + + var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' + + failureCount + ' ' + plural('failure', failureCount); + + if (pendingCount) { + specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount); + } + + print(specCounts); + } else { + print('No specs found'); + } + + printNewline(); + var seconds = timer.elapsed() / 1000; + print('Finished in ' + seconds + ' ' + plural('second', seconds)); + + printNewline(); + + onComplete(failureCount === 0); + }; + + this.specDone = function(result) { + specCount++; + + if (result.status == 'pending') { + pendingCount++; + print(colored('yellow', '*')); + return; + } + + if (result.status == 'passed') { + print(colored('green', '.')); + return; + } + + if (result.status == 'failed') { + failureCount++; + failedSpecs.push(result); + print(colored('red', 'F')); + } + }; + + return this; + + function printNewline() { + print('\n'); + } + + function colored(color, str) { + return showColors ? (ansi[color] + str + ansi.none) : str; + } + + function plural(str, count) { + return count == 1 ? str : str + 's'; + } + + function repeat(thing, times) { + var arr = []; + for (var i = 0; i < times; i++) { + arr.push(thing); + } + return arr; + } + + function indent(str, spaces) { + var lines = (str || '').split('\n'); + var newArr = []; + for (var i = 0; i < lines.length; i++) { + newArr.push(repeat(' ', spaces).join('') + lines[i]); + } + return newArr.join('\n'); + } + + function specFailureDetails(result) { + printNewline(); + print(result.fullName); + + for (var i = 0; i < result.failedExpectations.length; i++) { + var failedExpectation = result.failedExpectations[i]; + printNewline(); + print(indent(failedExpectation.message, 2)); + print(indent(failedExpectation.stack, 2)); + } + + printNewline(); + } + } + + return ConsoleReporter; +}; diff --git a/vendor/assets/javascripts/jasmine_2_0/jasmine-html.js b/vendor/assets/javascripts/jasmine_2_0/jasmine-html.js index 985d0d1..9d95903 100755 --- a/vendor/assets/javascripts/jasmine_2_0/jasmine-html.js +++ b/vendor/assets/javascripts/jasmine_2_0/jasmine-html.js @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2013 Pivotal Labs +Copyright (c) 2008-2014 Pivotal Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -49,20 +49,21 @@ jasmineRequire.HtmlReporter = function(j$) { symbols; this.initialize = function() { - htmlReporterMain = createDom("div", {className: "html-reporter"}, - createDom("div", {className: "banner"}, - createDom("span", {className: "title"}, "Jasmine"), - createDom("span", {className: "version"}, j$.version) + clearPrior(); + htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'}, + createDom('div', {className: 'banner'}, + createDom('a', {className: 'title', href: 'http://jasmine.github.io/', target: '_blank'}), + createDom('span', {className: 'version'}, j$.version) ), - createDom("ul", {className: "symbol-summary"}), - createDom("div", {className: "alert"}), - createDom("div", {className: "results"}, - createDom("div", {className: "failures"}) + createDom('ul', {className: 'symbol-summary'}), + createDom('div', {className: 'alert'}), + createDom('div', {className: 'results'}, + createDom('div', {className: 'failures'}) ) ); getContainer().appendChild(htmlReporterMain); - symbols = find(".symbol-summary"); + symbols = find('.symbol-summary'); }; var totalSpecsDefined; @@ -71,13 +72,13 @@ jasmineRequire.HtmlReporter = function(j$) { timer.start(); }; - var summary = createDom("div", {className: "summary"}); + var summary = createDom('div', {className: 'summary'}); - var topResults = new j$.ResultsNode({}, "", null), + var topResults = new j$.ResultsNode({}, '', null), currentParent = topResults; this.suiteStarted = function(result) { - currentParent.addChild(result, "suite"); + currentParent.addChild(result, 'suite'); currentParent = currentParent.last(); }; @@ -90,82 +91,94 @@ jasmineRequire.HtmlReporter = function(j$) { }; this.specStarted = function(result) { - currentParent.addChild(result, "spec"); + currentParent.addChild(result, 'spec'); }; var failures = []; this.specDone = function(result) { - if (result.status != "disabled") { + if(noExpectations(result) && console && console.error) { + console.error('Spec \'' + result.fullName + '\' has no expectations.'); + } + + if (result.status != 'disabled') { specsExecuted++; } - symbols.appendChild(createDom("li", { - className: result.status, - id: "spec_" + result.id, + symbols.appendChild(createDom('li', { + className: noExpectations(result) ? 'empty' : result.status, + id: 'spec_' + result.id, title: result.fullName } )); - if (result.status == "failed") { + if (result.status == 'failed') { failureCount++; var failure = - createDom("div", {className: "spec-detail failed"}, - createDom("div", {className: "description"}, - createDom("a", {title: result.fullName, href: specHref(result)}, result.fullName) + createDom('div', {className: 'spec-detail failed'}, + createDom('div', {className: 'description'}, + createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) ), - createDom("div", {className: "messages"}) + createDom('div', {className: 'messages'}) ); var messages = failure.childNodes[1]; for (var i = 0; i < result.failedExpectations.length; i++) { var expectation = result.failedExpectations[i]; - messages.appendChild(createDom("div", {className: "result-message"}, expectation.message)); - messages.appendChild(createDom("div", {className: "stack-trace"}, expectation.stack)); + messages.appendChild(createDom('div', {className: 'result-message'}, expectation.message)); + messages.appendChild(createDom('div', {className: 'stack-trace'}, expectation.stack)); } failures.push(failure); } - if (result.status == "pending") { + if (result.status == 'pending') { pendingSpecCount++; } }; this.jasmineDone = function() { - var banner = find(".banner"); - banner.appendChild(createDom("span", {className: "duration"}, "finished in " + timer.elapsed() / 1000 + "s")); + var banner = find('.banner'); + banner.appendChild(createDom('span', {className: 'duration'}, 'finished in ' + timer.elapsed() / 1000 + 's')); - var alert = find(".alert"); + var alert = find('.alert'); - alert.appendChild(createDom("span", { className: "exceptions" }, - createDom("label", { className: "label", 'for': "raise-exceptions" }, "raise exceptions"), - createDom("input", { - className: "raise", - id: "raise-exceptions", - type: "checkbox" + alert.appendChild(createDom('span', { className: 'exceptions' }, + createDom('label', { className: 'label', 'for': 'raise-exceptions' }, 'raise exceptions'), + createDom('input', { + className: 'raise', + id: 'raise-exceptions', + type: 'checkbox' }) )); - var checkbox = find("input"); + var checkbox = find('#raise-exceptions'); checkbox.checked = !env.catchingExceptions(); checkbox.onclick = onRaiseExceptionsClick; if (specsExecuted < totalSpecsDefined) { - var skippedMessage = "Ran " + specsExecuted + " of " + totalSpecsDefined + " specs - run all"; + var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all'; alert.appendChild( - createDom("span", {className: "bar skipped"}, - createDom("a", {href: "?", title: "Run all specs"}, skippedMessage) + createDom('span', {className: 'bar skipped'}, + createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage) ) ); } - var statusBarMessage = "" + pluralize("spec", specsExecuted) + ", " + pluralize("failure", failureCount); - if (pendingSpecCount) { statusBarMessage += ", " + pluralize("pending spec", pendingSpecCount); } + var statusBarMessage = ''; + var statusBarClassName = 'bar '; + + if (totalSpecsDefined > 0) { + statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount); + if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); } + statusBarClassName += (failureCount > 0) ? 'failed' : 'passed'; + } else { + statusBarClassName += 'skipped'; + statusBarMessage += 'No specs found'; + } - var statusBarClassName = "bar " + ((failureCount > 0) ? "failed" : "passed"); - alert.appendChild(createDom("span", {className: statusBarClassName}, statusBarMessage)); + alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage)); - var results = find(".results"); + var results = find('.results'); results.appendChild(summary); summaryList(topResults, summary); @@ -174,27 +187,31 @@ jasmineRequire.HtmlReporter = function(j$) { var specListNode; for (var i = 0; i < resultsTree.children.length; i++) { var resultNode = resultsTree.children[i]; - if (resultNode.type == "suite") { - var suiteListNode = createDom("ul", {className: "suite", id: "suite-" + resultNode.result.id}, - createDom("li", {className: "suite-detail"}, - createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description) + if (resultNode.type == 'suite') { + var suiteListNode = createDom('ul', {className: 'suite', id: 'suite-' + resultNode.result.id}, + createDom('li', {className: 'suite-detail'}, + createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) ) ); summaryList(resultNode, suiteListNode); domParent.appendChild(suiteListNode); } - if (resultNode.type == "spec") { - if (domParent.getAttribute("class") != "specs") { - specListNode = createDom("ul", {className: "specs"}); + if (resultNode.type == 'spec') { + if (domParent.getAttribute('class') != 'specs') { + specListNode = createDom('ul', {className: 'specs'}); domParent.appendChild(specListNode); } + var specDescription = resultNode.result.description; + if(noExpectations(resultNode.result)) { + specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; + } specListNode.appendChild( - createDom("li", { + createDom('li', { className: resultNode.result.status, - id: "spec-" + resultNode.result.id + id: 'spec-' + resultNode.result.id }, - createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description) + createDom('a', {href: specHref(resultNode.result)}, specDescription) ) ); } @@ -203,24 +220,24 @@ jasmineRequire.HtmlReporter = function(j$) { if (failures.length) { alert.appendChild( - createDom('span', {className: "menu bar spec-list"}, - createDom("span", {}, "Spec List | "), - createDom('a', {className: "failures-menu", href: "#"}, "Failures"))); + createDom('span', {className: 'menu bar spec-list'}, + createDom('span', {}, 'Spec List | '), + createDom('a', {className: 'failures-menu', href: '#'}, 'Failures'))); alert.appendChild( - createDom('span', {className: "menu bar failure-list"}, - createDom('a', {className: "spec-list-menu", href: "#"}, "Spec List"), - createDom("span", {}, " | Failures "))); + createDom('span', {className: 'menu bar failure-list'}, + createDom('a', {className: 'spec-list-menu', href: '#'}, 'Spec List'), + createDom('span', {}, ' | Failures '))); - find(".failures-menu").onclick = function() { + find('.failures-menu').onclick = function() { setMenuModeTo('failure-list'); }; - find(".spec-list-menu").onclick = function() { + find('.spec-list-menu').onclick = function() { setMenuModeTo('spec-list'); }; setMenuModeTo('failure-list'); - var failureNode = find(".failures"); + var failureNode = find('.failures'); for (var i = 0; i < failures.length; i++) { failureNode.appendChild(failures[i]); } @@ -230,7 +247,16 @@ jasmineRequire.HtmlReporter = function(j$) { return this; function find(selector) { - return getContainer().querySelector(selector); + return getContainer().querySelector('.jasmine_html-reporter ' + selector); + } + + function clearPrior() { + // return the reporter + var oldReporter = find(''); + + if(oldReporter) { + getContainer().removeChild(oldReporter); + } } function createDom(type, attrs, childrenVarArgs) { @@ -249,7 +275,7 @@ jasmineRequire.HtmlReporter = function(j$) { } for (var attr in attrs) { - if (attr == "className") { + if (attr == 'className') { el[attr] = attrs[attr]; } else { el.setAttribute(attr, attrs[attr]); @@ -260,17 +286,22 @@ jasmineRequire.HtmlReporter = function(j$) { } function pluralize(singular, count) { - var word = (count == 1 ? singular : singular + "s"); + var word = (count == 1 ? singular : singular + 's'); - return "" + count + " " + word; + return '' + count + ' ' + word; } function specHref(result) { - return "?spec=" + encodeURIComponent(result.fullName); + return '?spec=' + encodeURIComponent(result.fullName); } function setMenuModeTo(mode) { - htmlReporterMain.setAttribute("class", "html-reporter " + mode); + htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode); + } + + function noExpectations(result) { + return (result.failedExpectations.length + result.passedExpectations.length) === 0 && + result.status === 'passed'; } } @@ -279,7 +310,7 @@ jasmineRequire.HtmlReporter = function(j$) { jasmineRequire.HtmlSpecFilter = function() { function HtmlSpecFilter(options) { - var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); var filterPattern = new RegExp(filterString); this.matches = function(specName) { @@ -328,9 +359,9 @@ jasmineRequire.QueryString = function() { function toQueryString(paramMap) { var qStrPairs = []; for (var prop in paramMap) { - qStrPairs.push(encodeURIComponent(prop) + "=" + encodeURIComponent(paramMap[prop])); + qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])); } - return "?" + qStrPairs.join('&'); + return '?' + qStrPairs.join('&'); } function queryStringToParamMap() { @@ -343,7 +374,7 @@ jasmineRequire.QueryString = function() { for (var i = 0; i < params.length; i++) { var p = params[i].split('='); var value = decodeURIComponent(p[1]); - if (value === "true" || value === "false") { + if (value === 'true' || value === 'false') { value = JSON.parse(value); } paramMap[decodeURIComponent(p[0])] = value; diff --git a/vendor/assets/javascripts/jasmine_2_0/jasmine-jquery.js b/vendor/assets/javascripts/jasmine_2_0/jasmine-jquery.js index f4dcb2a..6e3209b 100644 --- a/vendor/assets/javascripts/jasmine_2_0/jasmine-jquery.js +++ b/vendor/assets/javascripts/jasmine_2_0/jasmine-jquery.js @@ -1,31 +1,31 @@ /*! -Jasmine-jQuery: a set of jQuery helpers for Jasmine tests. + Jasmine-jQuery: a set of jQuery helpers for Jasmine tests. -Version 2.0.5 + Version 2.0.7 -https://github.com/velesin/jasmine-jquery + https://github.com/velesin/jasmine-jquery -Copyright (c) 2010-2014 Wojciech Zawistowski, Travis Jeffery + Copyright (c) 2010-2014 Wojciech Zawistowski, Travis Jeffery -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +function (window, jasmine, $) { "use strict"; @@ -95,8 +95,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. jasmine.Fixtures.prototype.createContainer_ = function (html) { var container = $('
') - .attr('id', this.containerId) - .html(html) + .attr('id', this.containerId) + .html(html) $(document.body).append(container) return container @@ -125,31 +125,32 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded cache: false, url: url, + dataType: 'html', success: function (data, status, $xhr) { htmlText = $xhr.responseText } }).fail(function ($xhr, status, err) { - throw new Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')') + throw new Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')') }) - var scripts = $($.parseHTML(htmlText, true)).find('script[src]') || []; - - scripts.each(function(){ - $.ajax({ - async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded - cache: false, - dataType: 'script', - url: $(this).attr('src'), - success: function (data, status, $xhr) { - htmlText += '' - }, - error: function ($xhr, status, err) { - throw new Error('Script could not be loaded: ' + scriptSrc + ' (status: ' + status + ', message: ' + err.message + ')') - } - }); - }) + var scripts = $($.parseHTML(htmlText, true)).find('script[src]') || []; + + scripts.each(function(){ + $.ajax({ + async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded + cache: false, + dataType: 'script', + url: $(this).attr('src'), + success: function (data, status, $xhr) { + htmlText += '' + }, + error: function ($xhr, status, err) { + throw new Error('Script could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')') + } + }); + }) - self.fixturesCache_[relativeUrl] = htmlText; + self.fixturesCache_[relativeUrl] = htmlText; } jasmine.Fixtures.prototype.makeFixtureUrl_ = function (relativeUrl){ @@ -276,14 +277,18 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. } var data = { - spiedEvents: {} + spiedEvents: {} , handlers: [] } jasmine.jQuery.events = { spyOn: function (selector, eventName) { var handler = function (e) { - data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = jasmine.util.argsToArray(arguments) + var calls = (typeof data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] !== 'undefined') ? data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0 + data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = { + args: jasmine.util.argsToArray(arguments), + calls: ++calls + } } $(selector).on(eventName, handler) @@ -295,12 +300,22 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. handler: handler, reset: function (){ delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] + }, + calls: { + count: function () { + return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ? + data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0; + }, + any: function () { + return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ? + !!data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : false; + } } } }, args: function (selector, eventName) { - var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] + var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].args if (!actualArgs) { throw "There is no spy for " + eventName + " on " + selector.toString() + ". Make sure to create a spy using spyOnEvent." @@ -319,19 +334,22 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. if (Object.prototype.toString.call(expectedArgs) !== '[object Array]') actualArgs = actualArgs[0] - return util.equals(expectedArgs, actualArgs, customEqualityTesters) + return util.equals(actualArgs, expectedArgs, customEqualityTesters) }, wasPrevented: function (selector, eventName) { - var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] + var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] + , args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args , e = args ? args[0] : undefined return e && e.isDefaultPrevented() }, wasStopped: function (selector, eventName) { - var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] + var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] + , args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args , e = args ? args[0] : undefined + return e && e.isPropagationStopped() }, @@ -364,7 +382,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. for (var prop in css){ var value = css[prop] // see issue #147 on gh - ;if (value === 'auto' && $(actual).get(0).style[prop] === 'auto') continue + ;if (value === 'auto' && $(actual).get(0).style[prop] === 'auto') continue if ($(actual).css(prop) !== value) return { pass: false } } return { pass: true } @@ -527,7 +545,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. toContainElement: function () { return { compare: function (actual, selector) { - if (window.debug) debugger return { pass: $(actual).find(selector).length } } } @@ -560,6 +577,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. toHandle: function () { return { compare: function (actual, event) { + if ( !actual || actual.length === 0 ) return { pass: false }; var events = $._data($(actual).get(0), "events") if (!events || !event || typeof event !== "string") { @@ -590,6 +608,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. toHandleWith: function () { return { compare: function (actual, eventName, eventHandler) { + if ( !actual || actual.length === 0 ) return { pass: false }; var normalizedEventName = eventName.split('.')[0] , stack = $._data($(actual).get(0), "events")[normalizedEventName] @@ -608,8 +627,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var result = { pass: jasmine.jQuery.events.wasTriggered(selector, actual) } result.message = result.pass ? - "Expected event " + $(actual) + " not to have been triggered on " + selector : - "Expected event " + $(actual) + " to have been triggered on " + selector + "Expected event " + $(actual) + " not to have been triggered on " + selector : + "Expected event " + $(actual) + " to have been triggered on " + selector return result; } @@ -625,7 +644,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. result.message = result.pass ? "Expected event " + eventName + " not to have been triggered on " + selector : - "Expected event " + eventName + " to have been triggered on " + selector + "Expected event " + eventName + " to have been triggered on " + selector return result } @@ -638,20 +657,20 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var wasTriggered = jasmine.jQuery.events.wasTriggered(selector, actual) , result = { pass: wasTriggered && jasmine.jQuery.events.wasTriggeredWith(selector, actual, expectedArgs, j$, customEqualityTesters) } - if (wasTriggered) { - var actualArgs = jasmine.jQuery.events.args(selector, actual, expectedArgs)[1] - result.message = result.pass ? - "Expected event " + actual + " not to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) : - "Expected event " + actual + " to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) - - } else { - // todo check on this - result.message = result.pass ? - "Expected event " + actual + " not to have been triggered on " + selector : - "Expected event " + actual + " to have been triggered on " + selector - } + if (wasTriggered) { + var actualArgs = jasmine.jQuery.events.args(selector, actual, expectedArgs)[1] + result.message = result.pass ? + "Expected event " + actual + " not to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) : + "Expected event " + actual + " to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) + + } else { + // todo check on this + result.message = result.pass ? + "Expected event " + actual + " not to have been triggered on " + selector : + "Expected event " + actual + " to have been triggered on " + selector + } - return result + return result } } }, @@ -662,8 +681,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var result = { pass: jasmine.jQuery.events.wasPrevented(selector, actual) } result.message = result.pass ? - "Expected event " + actual + " not to have been prevented on " + selector : - "Expected event " + actual + " to have been prevented on " + selector + "Expected event " + actual + " not to have been prevented on " + selector : + "Expected event " + actual + " to have been prevented on " + selector return result } @@ -678,8 +697,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. , result = { pass: jasmine.jQuery.events.wasPrevented(selector, eventName) } result.message = result.pass ? - "Expected event " + eventName + " not to have been prevented on " + selector : - "Expected event " + eventName + " to have been prevented on " + selector + "Expected event " + eventName + " not to have been prevented on " + selector : + "Expected event " + eventName + " to have been prevented on " + selector return result } @@ -692,8 +711,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var result = { pass: jasmine.jQuery.events.wasStopped(selector, actual) } result.message = result.pass ? - "Expected event " + actual + " not to have been stopped on " + selector : - "Expected event " + actual + " to have been stopped on " + selector + "Expected event " + actual + " not to have been stopped on " + selector : + "Expected event " + actual + " to have been stopped on " + selector return result; } @@ -708,8 +727,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. , result = { pass: jasmine.jQuery.events.wasStopped(selector, eventName) } result.message = result.pass ? - "Expected event " + eventName + " not to have been stopped on " + selector : - "Expected event " + eventName + " to have been stopped on " + selector + "Expected event " + eventName + " not to have been stopped on " + selector : + "Expected event " + eventName + " to have been stopped on " + selector return result } @@ -718,29 +737,29 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. }) jasmine.getEnv().addCustomEqualityTester(function(a, b) { - if (a && b) { - if (a instanceof $ || jasmine.isDomNode(a)) { - var $a = $(a) + if (a && b) { + if (a instanceof $ || jasmine.isDomNode(a)) { + var $a = $(a) - if (b instanceof $) - return $a.length == b.length && a.is(b) + if (b instanceof $) + return $a.length == b.length && a.is(b) - return $a.is(b); - } + return $a.is(b); + } - if (b instanceof $ || jasmine.isDomNode(b)) { - var $b = $(b) + if (b instanceof $ || jasmine.isDomNode(b)) { + var $b = $(b) - if (a instanceof $) - return a.length == $b.length && $b.is(a) + if (a instanceof $) + return a.length == $b.length && $b.is(a) - return $(b).is(a); - } - } + return $(b).is(a); + } + } }) jasmine.getEnv().addCustomEqualityTester(function (a, b) { - if (a instanceof $ && b instanceof $ && a.size() == b.size()) + if (a instanceof $ && b instanceof $ && a.size() == b.size()) return a.is(b) }) }) diff --git a/vendor/assets/javascripts/jasmine_2_0/jasmine.js b/vendor/assets/javascripts/jasmine_2_0/jasmine.js index 24463ec..8fc3dcb 100755 --- a/vendor/assets/javascripts/jasmine_2_0/jasmine.js +++ b/vendor/assets/javascripts/jasmine_2_0/jasmine.js @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2013 Pivotal Labs +Copyright (c) 2008-2014 Pivotal Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ function getJasmineRequireObj() { - if (typeof module !== "undefined" && module.exports) { + if (typeof module !== 'undefined' && module.exports) { return exports; } else { window.jasmineRequire = window.jasmineRequire || {}; @@ -36,6 +36,7 @@ getJasmineRequireObj().core = function(jRequire) { j$.util = jRequire.util(); j$.Any = jRequire.Any(); j$.CallTracker = jRequire.CallTracker(); + j$.MockDate = jRequire.MockDate(); j$.Clock = jRequire.Clock(); j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(); j$.Env = jRequire.Env(j$); @@ -46,7 +47,7 @@ getJasmineRequireObj().core = function(jRequire) { j$.matchersUtil = jRequire.matchersUtil(j$); j$.ObjectContaining = jRequire.ObjectContaining(j$); j$.pp = jRequire.pp(j$); - j$.QueueRunner = jRequire.QueueRunner(); + j$.QueueRunner = jRequire.QueueRunner(j$); j$.ReportDispatcher = jRequire.ReportDispatcher(); j$.Spec = jRequire.Spec(j$); j$.SpyStrategy = jRequire.SpyStrategy(); @@ -61,23 +62,23 @@ getJasmineRequireObj().core = function(jRequire) { getJasmineRequireObj().requireMatchers = function(jRequire, j$) { var availableMatchers = [ - "toBe", - "toBeCloseTo", - "toBeDefined", - "toBeFalsy", - "toBeGreaterThan", - "toBeLessThan", - "toBeNaN", - "toBeNull", - "toBeTruthy", - "toBeUndefined", - "toContain", - "toEqual", - "toHaveBeenCalled", - "toHaveBeenCalledWith", - "toMatch", - "toThrow", - "toThrowError" + 'toBe', + 'toBeCloseTo', + 'toBeDefined', + 'toBeFalsy', + 'toBeGreaterThan', + 'toBeLessThan', + 'toBeNaN', + 'toBeNull', + 'toBeTruthy', + 'toBeUndefined', + 'toContain', + 'toEqual', + 'toHaveBeenCalled', + 'toHaveBeenCalledWith', + 'toMatch', + 'toThrow', + 'toThrowError' ], matchers = {}; @@ -89,104 +90,108 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) { return matchers; }; -getJasmineRequireObj().base = function(j$) { - j$.unimplementedMethod_ = function() { - throw new Error("unimplemented method"); - }; +getJasmineRequireObj().base = (function (jasmineGlobal) { + if (typeof module !== 'undefined' && module.exports) { + jasmineGlobal = global; + } - j$.MAX_PRETTY_PRINT_DEPTH = 40; - j$.DEFAULT_TIMEOUT_INTERVAL = 5000; + return function(j$) { + j$.unimplementedMethod_ = function() { + throw new Error('unimplemented method'); + }; - j$.getGlobal = (function() { - var jasmineGlobal = eval.call(null, "this"); - return function() { + j$.MAX_PRETTY_PRINT_DEPTH = 40; + j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100; + j$.DEFAULT_TIMEOUT_INTERVAL = 5000; + + j$.getGlobal = function() { return jasmineGlobal; }; - })(); - j$.getEnv = function(options) { - var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options); - //jasmine. singletons in here (setTimeout blah blah). - return env; - }; + j$.getEnv = function(options) { + var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options); + //jasmine. singletons in here (setTimeout blah blah). + return env; + }; - j$.isArray_ = function(value) { - return j$.isA_("Array", value); - }; + j$.isArray_ = function(value) { + return j$.isA_('Array', value); + }; - j$.isString_ = function(value) { - return j$.isA_("String", value); - }; + j$.isString_ = function(value) { + return j$.isA_('String', value); + }; - j$.isNumber_ = function(value) { - return j$.isA_("Number", value); - }; + j$.isNumber_ = function(value) { + return j$.isA_('Number', value); + }; - j$.isA_ = function(typeName, value) { - return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; - }; + j$.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; + }; - j$.isDomNode = function(obj) { - return obj.nodeType > 0; - }; + j$.isDomNode = function(obj) { + return obj.nodeType > 0; + }; - j$.any = function(clazz) { - return new j$.Any(clazz); - }; + j$.any = function(clazz) { + return new j$.Any(clazz); + }; - j$.objectContaining = function(sample) { - return new j$.ObjectContaining(sample); - }; + j$.objectContaining = function(sample) { + return new j$.ObjectContaining(sample); + }; - j$.createSpy = function(name, originalFn) { - - var spyStrategy = new j$.SpyStrategy({ - name: name, - fn: originalFn, - getSpy: function() { return spy; } - }), - callTracker = new j$.CallTracker(), - spy = function() { - callTracker.track({ - object: this, - args: Array.prototype.slice.apply(arguments) - }); - return spyStrategy.exec.apply(this, arguments); - }; + j$.createSpy = function(name, originalFn) { - for (var prop in originalFn) { - if (prop === 'and' || prop === 'calls') { - throw new Error("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon"); - } + var spyStrategy = new j$.SpyStrategy({ + name: name, + fn: originalFn, + getSpy: function() { return spy; } + }), + callTracker = new j$.CallTracker(), + spy = function() { + callTracker.track({ + object: this, + args: Array.prototype.slice.apply(arguments) + }); + return spyStrategy.exec.apply(this, arguments); + }; - spy[prop] = originalFn[prop]; - } + for (var prop in originalFn) { + if (prop === 'and' || prop === 'calls') { + throw new Error('Jasmine spies would overwrite the \'and\' and \'calls\' properties on the object being spied upon'); + } - spy.and = spyStrategy; - spy.calls = callTracker; + spy[prop] = originalFn[prop]; + } - return spy; - }; + spy.and = spyStrategy; + spy.calls = callTracker; - j$.isSpy = function(putativeSpy) { - if (!putativeSpy) { - return false; - } - return putativeSpy.and instanceof j$.SpyStrategy && - putativeSpy.calls instanceof j$.CallTracker; - }; + return spy; + }; - j$.createSpyObj = function(baseName, methodNames) { - if (!j$.isArray_(methodNames) || methodNames.length === 0) { - throw "createSpyObj requires a non-empty array of method names to create spies for"; - } - var obj = {}; - for (var i = 0; i < methodNames.length; i++) { - obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]); - } - return obj; + j$.isSpy = function(putativeSpy) { + if (!putativeSpy) { + return false; + } + return putativeSpy.and instanceof j$.SpyStrategy && + putativeSpy.calls instanceof j$.CallTracker; + }; + + j$.createSpyObj = function(baseName, methodNames) { + if (!j$.isArray_(methodNames) || methodNames.length === 0) { + throw 'createSpyObj requires a non-empty array of method names to create spies for'; + } + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]); + } + return obj; + }; }; -}; +})(this); getJasmineRequireObj().util = function() { @@ -220,6 +225,16 @@ getJasmineRequireObj().util = function() { return obj === void 0; }; + util.arrayContains = function(array, search) { + var i = array.length; + while (i--) { + if (array[i] == search) { + return true; + } + } + return false; + }; + return util; }; @@ -239,8 +254,6 @@ getJasmineRequireObj().Spec = function(j$) { this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; - this.timer = attrs.timer || {setTimeout: setTimeout, clearTimeout: clearTimeout}; - if (!this.fn) { this.pend(); } @@ -249,15 +262,18 @@ getJasmineRequireObj().Spec = function(j$) { id: this.id, description: this.description, fullName: this.getFullName(), - failedExpectations: [] + failedExpectations: [], + passedExpectations: [] }; } Spec.prototype.addExpectationResult = function(passed, data) { + var expectationResult = this.expectationResultFactory(data); if (passed) { - return; + this.result.passedExpectations.push(expectationResult); + } else { + this.result.failedExpectations.push(expectationResult); } - this.result.failedExpectations.push(this.expectationResultFactory(data)); }; Spec.prototype.expect = function(actual) { @@ -265,8 +281,7 @@ getJasmineRequireObj().Spec = function(j$) { }; Spec.prototype.execute = function(onComplete) { - var self = this, - timeout; + var self = this; this.onStart(this); @@ -275,52 +290,26 @@ getJasmineRequireObj().Spec = function(j$) { return; } - function timeoutable(fn) { - return function(done) { - timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() { - onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.')); - done(); - }, j$.DEFAULT_TIMEOUT_INTERVAL]]); - - var callDone = function() { - clearTimeoutable(); - done(); - }; - - fn.call(this, callDone); //TODO: do we care about more than 1 arg? - }; - } - - function clearTimeoutable() { - Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]); - timeout = void 0; - } - - var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()), - allTimeoutableFns = []; - for (var i = 0; i < allFns.length; i++) { - var fn = allFns[i]; - allTimeoutableFns.push(fn.length > 0 ? timeoutable(fn) : fn); - } + var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns()); this.queueRunnerFactory({ - fns: allTimeoutableFns, + fns: allFns, onException: onException, - onComplete: complete + onComplete: complete, + enforceTimeout: function() { return true; } }); function onException(e) { - clearTimeoutable(); if (Spec.isPendingSpecException(e)) { self.pend(); return; } self.addExpectationResult(false, { - matcherName: "", + matcherName: '', passed: false, - expected: "", - actual: "", + expected: '', + actual: '', error: e }); } @@ -363,16 +352,16 @@ getJasmineRequireObj().Spec = function(j$) { return this.getSpecName(this); }; - Spec.pendingSpecExceptionMessage = "=> marked Pending"; + Spec.pendingSpecExceptionMessage = '=> marked Pending'; Spec.isPendingSpecException = function(e) { - return e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1; + return !!(e && e.toString && e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1); }; return Spec; }; -if (typeof window == void 0 && typeof exports == "object") { +if (typeof window == void 0 && typeof exports == 'object') { exports.Spec = jasmineRequire.Spec; } @@ -389,7 +378,7 @@ getJasmineRequireObj().Env = function(j$) { var realSetTimeout = j$.getGlobal().setTimeout; var realClearTimeout = j$.getGlobal().clearTimeout; - this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler()); + this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler(), new j$.MockDate(global)); var runnableLookupTable = {}; @@ -399,12 +388,12 @@ getJasmineRequireObj().Env = function(j$) { var currentSuite = null; var reporter = new j$.ReportDispatcher([ - "jasmineStarted", - "jasmineDone", - "suiteStarted", - "suiteDone", - "specStarted", - "specDone" + 'jasmineStarted', + 'jasmineDone', + 'suiteStarted', + 'suiteDone', + 'specStarted', + 'specDone' ]); this.specFilter = function() { @@ -514,6 +503,7 @@ getJasmineRequireObj().Env = function(j$) { var queueRunnerFactory = function(options) { options.catchException = catchException; options.clearStack = options.clearStack || clearStack; + options.timer = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}; new j$.QueueRunner(options).execute(); }; @@ -558,7 +548,7 @@ getJasmineRequireObj().Env = function(j$) { this.spyOn = function(obj, methodName) { if (j$.util.isUndefined(obj)) { - throw new Error("spyOn could not find an object to spy upon for " + methodName + "()"); + throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()'); } if (j$.util.isUndefined(obj[methodName])) { @@ -616,7 +606,7 @@ getJasmineRequireObj().Env = function(j$) { } if (declarationError) { - this.it("encountered a declaration exception", function() { + this.it('encountered a declaration exception', function() { throw declarationError; }); } @@ -649,8 +639,7 @@ getJasmineRequireObj().Env = function(j$) { description: description, expectationResultFactory: expectationResultFactory, queueRunnerFactory: queueRunnerFactory, - fn: fn, - timer: {setTimeout: realSetTimeout, clearTimeout: realClearTimeout} + fn: fn }); runnableLookupTable[spec.id] = spec; @@ -695,6 +684,10 @@ getJasmineRequireObj().Env = function(j$) { }; this.expect = function(actual) { + if (!currentSpec) { + throw new Error('\'expect\' was used when there was no current spec, this could be because an asynchronous test timed out'); + } + return currentSpec.expect(actual); }; @@ -723,7 +716,7 @@ getJasmineRequireObj().JsApiReporter = function() { function JsApiReporter(options) { var timer = options.timer || noopTimer, - status = "loaded"; + status = 'loaded'; this.started = false; this.finished = false; @@ -819,7 +812,7 @@ getJasmineRequireObj().Any = function() { }; Any.prototype.jasmineToString = function() { - return ''; + return ''; }; return Any; @@ -877,7 +870,7 @@ getJasmineRequireObj().CallTracker = function() { }; getJasmineRequireObj().Clock = function() { - function Clock(global, delayedFunctionScheduler) { + function Clock(global, delayedFunctionScheduler, mockDate) { var self = this, realTimingFunctions = { setTimeout: global.setTimeout, @@ -894,23 +887,32 @@ getJasmineRequireObj().Clock = function() { installed = false, timer; + self.install = function() { replace(global, fakeTimingFunctions); timer = fakeTimingFunctions; installed = true; + + return self; }; self.uninstall = function() { delayedFunctionScheduler.reset(); + mockDate.uninstall(); replace(global, realTimingFunctions); + timer = realTimingFunctions; installed = false; }; + self.mockDate = function(initialDate) { + mockDate.install(initialDate); + }; + self.setTimeout = function(fn, delay, params) { if (legacyIE()) { if (arguments.length > 2) { - throw new Error("IE < 9 cannot support extra params to setTimeout without a polyfill"); + throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill'); } return timer.setTimeout(fn, delay); } @@ -920,7 +922,7 @@ getJasmineRequireObj().Clock = function() { self.setInterval = function(fn, delay, params) { if (legacyIE()) { if (arguments.length > 2) { - throw new Error("IE < 9 cannot support extra params to setInterval without a polyfill"); + throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill'); } return timer.setInterval(fn, delay); } @@ -937,9 +939,10 @@ getJasmineRequireObj().Clock = function() { self.tick = function(millis) { if (installed) { + mockDate.tick(millis); delayedFunctionScheduler.tick(millis); } else { - throw new Error("Mock clock is not installed, use jasmine.clock().install()"); + throw new Error('Mock clock is not installed, use jasmine.clock().install()'); } }; @@ -973,7 +976,7 @@ getJasmineRequireObj().Clock = function() { } function argSlice(argsObj, n) { - return Array.prototype.slice.call(argsObj, 2); + return Array.prototype.slice.call(argsObj, n); } } @@ -1129,16 +1132,20 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() { getJasmineRequireObj().ExceptionFormatter = function() { function ExceptionFormatter() { this.message = function(error) { - var message = error.name + - ': ' + - error.message; + var message = ''; + + if (error.name && error.message) { + message += error.name + ': ' + error.message; + } else { + message += error.toString() + ' thrown'; + } if (error.fileName || error.sourceURL) { - message += " in " + (error.fileName || error.sourceURL); + message += ' in ' + (error.fileName || error.sourceURL); } if (error.line || error.lineNumber) { - message += " (line " + (error.line || error.lineNumber) + ")"; + message += ' (line ' + (error.line || error.lineNumber) + ')'; } return message; @@ -1172,7 +1179,7 @@ getJasmineRequireObj().Expectation = function() { return function() { var args = Array.prototype.slice.call(arguments, 0), expected = args.slice(0), - message = ""; + message = ''; args.unshift(this.actual); @@ -1197,7 +1204,11 @@ getJasmineRequireObj().Expectation = function() { args.unshift(name); message = this.util.buildFailureMessage.apply(null, args); } else { - message = result.message; + if (Object.prototype.toString.apply(result.message) === '[object Function]') { + message = result.message(); + } else { + message = result.message; + } } } @@ -1273,18 +1284,18 @@ getJasmineRequireObj().buildExpectationResult = function() { function message() { if (options.passed) { - return "Passed."; + return 'Passed.'; } else if (options.message) { return options.message; } else if (options.error) { return messageFormatter(options.error); } - return ""; + return ''; } function stack() { if (options.passed) { - return ""; + return ''; } var error = options.error; @@ -1302,6 +1313,88 @@ getJasmineRequireObj().buildExpectationResult = function() { return buildExpectationResult; }; +getJasmineRequireObj().MockDate = function() { + function MockDate(global) { + var self = this; + var currentTime = 0; + + if (!global || !global.Date) { + self.install = function() {}; + self.tick = function() {}; + self.uninstall = function() {}; + return self; + } + + var GlobalDate = global.Date; + + self.install = function(mockDate) { + if (mockDate instanceof GlobalDate) { + currentTime = mockDate.getTime(); + } else { + currentTime = new GlobalDate().getTime(); + } + + global.Date = FakeDate; + }; + + self.tick = function(millis) { + millis = millis || 0; + currentTime = currentTime + millis; + }; + + self.uninstall = function() { + currentTime = 0; + global.Date = GlobalDate; + }; + + createDateProperties(); + + return self; + + function FakeDate() { + switch(arguments.length) { + case 0: + return new GlobalDate(currentTime); + case 1: + return new GlobalDate(arguments[0]); + case 2: + return new GlobalDate(arguments[0], arguments[1]); + case 3: + return new GlobalDate(arguments[0], arguments[1], arguments[2]); + case 4: + return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3]); + case 5: + return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], + arguments[4]); + case 6: + return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], + arguments[4], arguments[5]); + case 7: + return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], + arguments[4], arguments[5], arguments[6]); + } + } + + function createDateProperties() { + + FakeDate.now = function() { + if (GlobalDate.now) { + return currentTime; + } else { + throw new Error('Browser does not support Date.now()'); + } + }; + + FakeDate.toSource = GlobalDate.toSource; + FakeDate.toString = GlobalDate.toString; + FakeDate.parse = GlobalDate.parse; + FakeDate.UTC = GlobalDate.UTC; + } + } + + return MockDate; +}; + getJasmineRequireObj().ObjectContaining = function(j$) { function ObjectContaining(sample) { @@ -1309,7 +1402,7 @@ getJasmineRequireObj().ObjectContaining = function(j$) { } ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) { - if (typeof(this.sample) !== "object") { throw new Error("You must provide an object to objectContaining, not '"+this.sample+"'."); } + if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); } mismatchKeys = mismatchKeys || []; mismatchValues = mismatchValues || []; @@ -1320,10 +1413,10 @@ getJasmineRequireObj().ObjectContaining = function(j$) { for (var property in this.sample) { if (!hasKey(other, property) && hasKey(this.sample, property)) { - mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + mismatchKeys.push('expected has key \'' + property + '\', but missing from actual.'); } - else if (!j$.matchersUtil.equals(this.sample[property], other[property])) { - mismatchValues.push("'" + property + "' was '" + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + "' in actual, but was '" + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in expected."); + else if (!j$.matchersUtil.equals(other[property], this.sample[property])) { + mismatchValues.push('\'' + property + '\' was \'' + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + '\' in actual, but was \'' + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + '\' in expected.'); } } @@ -1331,7 +1424,7 @@ getJasmineRequireObj().ObjectContaining = function(j$) { }; ObjectContaining.prototype.jasmineToString = function() { - return ""; + return ''; }; return ObjectContaining; @@ -1341,6 +1434,7 @@ getJasmineRequireObj().pp = function(j$) { function PrettyPrinter() { this.ppNestLevel_ = 0; + this.seen = []; } PrettyPrinter.prototype.format = function(value) { @@ -1350,6 +1444,8 @@ getJasmineRequireObj().pp = function(j$) { this.emitScalar('undefined'); } else if (value === null) { this.emitScalar('null'); + } else if (value === 0 && 1/value === -Infinity) { + this.emitScalar('-0'); } else if (value === j$.getGlobal()) { this.emitScalar(''); } else if (value.jasmineToString) { @@ -1357,7 +1453,7 @@ getJasmineRequireObj().pp = function(j$) { } else if (typeof value === 'string') { this.emitString(value); } else if (j$.isSpy(value)) { - this.emitScalar("spy on " + value.and.identity()); + this.emitScalar('spy on ' + value.and.identity()); } else if (value instanceof RegExp) { this.emitScalar(value.toString()); } else if (typeof value === 'function') { @@ -1366,16 +1462,16 @@ getJasmineRequireObj().pp = function(j$) { this.emitScalar('HTMLNode'); } else if (value instanceof Date) { this.emitScalar('Date(' + value + ')'); - } else if (value.__Jasmine_been_here_before__) { + } else if (j$.util.arrayContains(this.seen, value)) { this.emitScalar(''); } else if (j$.isArray_(value) || j$.isA_('Object', value)) { - value.__Jasmine_been_here_before__ = true; + this.seen.push(value); if (j$.isArray_(value)) { this.emitArray(value); } else { this.emitObject(value); } - delete value.__Jasmine_been_here_before__; + this.seen.pop(); } else { this.emitScalar(value.toString()); } @@ -1386,8 +1482,7 @@ getJasmineRequireObj().pp = function(j$) { PrettyPrinter.prototype.iterateObject = function(obj, fn) { for (var property in obj) { - if (!obj.hasOwnProperty(property)) { continue; } - if (property == '__Jasmine_been_here_before__') { continue; } + if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; } fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && obj.__lookupGetter__(property) !== null) : false); } @@ -1411,28 +1506,31 @@ getJasmineRequireObj().pp = function(j$) { }; StringPrettyPrinter.prototype.emitString = function(value) { - this.append("'" + value + "'"); + this.append('\'' + value + '\''); }; StringPrettyPrinter.prototype.emitArray = function(array) { if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { - this.append("Array"); + this.append('Array'); return; } - + var length = Math.min(array.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); this.append('[ '); - for (var i = 0; i < array.length; i++) { + for (var i = 0; i < length; i++) { if (i > 0) { this.append(', '); } this.format(array[i]); } + if(array.length > length){ + this.append(', ...'); + } this.append(' ]'); }; StringPrettyPrinter.prototype.emitObject = function(obj) { if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { - this.append("Object"); + this.append('Object'); return; } @@ -1448,7 +1546,7 @@ getJasmineRequireObj().pp = function(j$) { } self.append(property); - self.append(' : '); + self.append(': '); if (isGetter) { self.append(''); } else { @@ -1470,7 +1568,17 @@ getJasmineRequireObj().pp = function(j$) { }; }; -getJasmineRequireObj().QueueRunner = function() { +getJasmineRequireObj().QueueRunner = function(j$) { + + function once(fn) { + var called = false; + return function() { + if (!called) { + called = true; + fn(); + } + }; + } function QueueRunner(attrs) { this.fns = attrs.fns || []; @@ -1478,7 +1586,9 @@ getJasmineRequireObj().QueueRunner = function() { this.clearStack = attrs.clearStack || function(fn) {fn();}; this.onException = attrs.onException || function() {}; this.catchException = attrs.catchException || function() { return true; }; + this.enforceTimeout = attrs.enforceTimeout || function() { return false; }; this.userContext = {}; + this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; } QueueRunner.prototype.execute = function() { @@ -1514,7 +1624,21 @@ getJasmineRequireObj().QueueRunner = function() { } function attemptAsync(fn) { - var next = function () { self.run(fns, iterativeIndex + 1); }; + var clearTimeout = function () { + Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeoutId]]); + }, + next = once(function () { + clearTimeout(timeoutId); + self.run(fns, iterativeIndex + 1); + }), + timeoutId; + + if (self.enforceTimeout()) { + timeoutId = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() { + self.onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.')); + next(); + }, j$.DEFAULT_TIMEOUT_INTERVAL]]); + } try { fn.call(self.userContext, next); @@ -1578,7 +1702,7 @@ getJasmineRequireObj().SpyStrategy = function() { function SpyStrategy(options) { options = options || {}; - var identity = options.name || "unknown", + var identity = options.name || 'unknown', originalFn = options.fn || function() {}, getSpy = options.getSpy || function() {}, plan = function() {}; @@ -1662,6 +1786,7 @@ getJasmineRequireObj().Suite = function() { Suite.prototype.disable = function() { this.disabled = true; + this.result.status = 'disabled'; }; Suite.prototype.beforeEach = function(fn) { @@ -1678,6 +1803,9 @@ getJasmineRequireObj().Suite = function() { Suite.prototype.execute = function(onComplete) { var self = this; + + this.onStart(this); + if (this.disabled) { complete(); return; @@ -1689,8 +1817,6 @@ getJasmineRequireObj().Suite = function() { allFns.push(wrapChildAsAsync(this.children[i])); } - this.onStart(this); - this.queueRunner({ fns: allFns, onComplete: complete @@ -1712,16 +1838,20 @@ getJasmineRequireObj().Suite = function() { return Suite; }; -if (typeof window == void 0 && typeof exports == "object") { +if (typeof window == void 0 && typeof exports == 'object') { exports.Suite = jasmineRequire.Suite; } getJasmineRequireObj().Timer = function() { + var defaultNow = (function(Date) { + return function() { return new Date().getTime(); }; + })(Date); + function Timer(options) { options = options || {}; - var now = options.now || function() { return new Date().getTime(); }, - startTime; + var now = options.now || defaultNow, + startTime; this.start = function() { startTime = now(); @@ -1748,7 +1878,7 @@ getJasmineRequireObj().matchersUtil = function(j$) { contains: function(haystack, needle, customTesters) { customTesters = customTesters || []; - if (Object.prototype.toString.apply(haystack) === "[object Array]") { + if (Object.prototype.toString.apply(haystack) === '[object Array]') { for (var i = 0; i < haystack.length; i++) { if (eq(haystack[i], needle, [], [], customTesters)) { return true; @@ -1756,7 +1886,7 @@ getJasmineRequireObj().matchersUtil = function(j$) { } return false; } - return haystack.indexOf(needle) >= 0; + return !!haystack && haystack.indexOf(needle) >= 0; }, buildFailureMessage: function() { @@ -1767,21 +1897,21 @@ getJasmineRequireObj().matchersUtil = function(j$) { expected = args.slice(3), englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); - var message = "Expected " + + var message = 'Expected ' + j$.pp(actual) + - (isNot ? " not " : " ") + + (isNot ? ' not ' : ' ') + englishyPredicate; if (expected.length > 0) { for (var i = 0; i < expected.length; i++) { if (i > 0) { - message += ","; + message += ','; } - message += " " + j$.pp(expected[i]); + message += ' ' + j$.pp(expected[i]); } } - return message + "."; + return message + '.'; } }; @@ -2018,9 +2148,9 @@ getJasmineRequireObj().toBeNaN = function(j$) { }; if (result.pass) { - result.message = "Expected actual not to be NaN."; + result.message = 'Expected actual not to be NaN.'; } else { - result.message = "Expected " + j$.pp(actual) + " to be NaN."; + result.message = function() { return 'Expected ' + j$.pp(actual) + ' to be NaN.'; }; } return result; @@ -2132,8 +2262,8 @@ getJasmineRequireObj().toHaveBeenCalled = function(j$) { result.pass = actual.calls.any(); result.message = result.pass ? - "Expected spy " + actual.and.identity() + " not to have been called." : - "Expected spy " + actual.and.identity() + " to have been called."; + 'Expected spy ' + actual.and.identity() + ' not to have been called.' : + 'Expected spy ' + actual.and.identity() + ' to have been called.'; return result; } @@ -2145,7 +2275,7 @@ getJasmineRequireObj().toHaveBeenCalled = function(j$) { getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { - function toHaveBeenCalledWith(util) { + function toHaveBeenCalledWith(util, customEqualityTesters) { return { compare: function() { var args = Array.prototype.slice.call(arguments, 0), @@ -2158,15 +2288,15 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { } if (!actual.calls.any()) { - result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but it was never called."; + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but it was never called.'; }; return result; } - if (util.contains(actual.calls.allArgs(), expectedArgs)) { + if (util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) { result.pass = true; - result.message = "Expected spy " + actual.and.identity() + " not to have been called with " + j$.pp(expectedArgs) + " but it was."; + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' not to have been called with ' + j$.pp(expectedArgs) + ' but it was.'; }; } else { - result.message = "Expected spy " + actual.and.identity() + " to have been called with " + j$.pp(expectedArgs) + " but actual calls were " + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + "."; + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but actual calls were ' + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + '.'; }; } return result; @@ -2203,8 +2333,8 @@ getJasmineRequireObj().toThrow = function(j$) { threw = false, thrown; - if (typeof actual != "function") { - throw new Error("Actual is not a Function"); + if (typeof actual != 'function') { + throw new Error('Actual is not a Function'); } try { @@ -2215,22 +2345,22 @@ getJasmineRequireObj().toThrow = function(j$) { } if (!threw) { - result.message = "Expected function to throw an exception."; + result.message = 'Expected function to throw an exception.'; return result; } if (arguments.length == 1) { result.pass = true; - result.message = "Expected function not to throw, but it threw " + j$.pp(thrown) + "."; + result.message = function() { return 'Expected function not to throw, but it threw ' + j$.pp(thrown) + '.'; }; return result; } if (util.equals(thrown, expected)) { result.pass = true; - result.message = "Expected function not to throw " + j$.pp(expected) + "."; + result.message = function() { return 'Expected function not to throw ' + j$.pp(expected) + '.'; }; } else { - result.message = "Expected function to throw " + j$.pp(expected) + ", but it threw " + j$.pp(thrown) + "."; + result.message = function() { return 'Expected function to throw ' + j$.pp(expected) + ', but it threw ' + j$.pp(thrown) + '.'; }; } return result; @@ -2246,6 +2376,8 @@ getJasmineRequireObj().toThrowError = function(j$) { return { compare: function(actual) { var threw = false, + pass = {pass: true}, + fail = {pass: false}, thrown, errorType, message, @@ -2253,8 +2385,8 @@ getJasmineRequireObj().toThrowError = function(j$) { name, constructorName; - if (typeof actual != "function") { - throw new Error("Actual is not a Function"); + if (typeof actual != 'function') { + throw new Error('Actual is not a Function'); } extractExpectedParams.apply(null, arguments); @@ -2267,15 +2399,18 @@ getJasmineRequireObj().toThrowError = function(j$) { } if (!threw) { - return fail("Expected function to throw an Error."); + fail.message = 'Expected function to throw an Error.'; + return fail; } if (!(thrown instanceof Error)) { - return fail("Expected function to throw an Error, but it threw " + thrown + "."); + fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; }; + return fail; } if (arguments.length == 1) { - return pass("Expected function not to throw an Error, but it threw " + fnNameFor(thrown) + "."); + pass.message = 'Expected function not to throw an Error, but it threw ' + fnNameFor(thrown) + '.'; + return pass; } if (errorType) { @@ -2285,45 +2420,55 @@ getJasmineRequireObj().toThrowError = function(j$) { if (errorType && message) { if (thrown.constructor == errorType && util.equals(thrown.message, message)) { - return pass("Expected function not to throw " + name + " with message \"" + message + "\"."); + pass.message = function() { return 'Expected function not to throw ' + name + ' with message ' + j$.pp(message) + '.'; }; + return pass; } else { - return fail("Expected function to throw " + name + " with message \"" + message + - "\", but it threw " + constructorName + " with message \"" + thrown.message + "\"."); + fail.message = function() { return 'Expected function to throw ' + name + ' with message ' + j$.pp(message) + + ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; }; + return fail; } } if (errorType && regexp) { if (thrown.constructor == errorType && regexp.test(thrown.message)) { - return pass("Expected function not to throw " + name + " with message matching " + regexp + "."); + pass.message = function() { return 'Expected function not to throw ' + name + ' with message matching ' + j$.pp(regexp) + '.'; }; + return pass; } else { - return fail("Expected function to throw " + name + " with message matching " + regexp + - ", but it threw " + constructorName + " with message \"" + thrown.message + "\"."); + fail.message = function() { return 'Expected function to throw ' + name + ' with message matching ' + j$.pp(regexp) + + ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; }; + return fail; } } if (errorType) { if (thrown.constructor == errorType) { - return pass("Expected function not to throw " + name + "."); + pass.message = 'Expected function not to throw ' + name + '.'; + return pass; } else { - return fail("Expected function to throw " + name + ", but it threw " + constructorName + "."); + fail.message = 'Expected function to throw ' + name + ', but it threw ' + constructorName + '.'; + return fail; } } if (message) { if (thrown.message == message) { - return pass("Expected function not to throw an exception with message " + j$.pp(message) + "."); + pass.message = function() { return 'Expected function not to throw an exception with message ' + j$.pp(message) + '.'; }; + return pass; } else { - return fail("Expected function to throw an exception with message " + j$.pp(message) + - ", but it threw an exception with message " + j$.pp(thrown.message) + "."); + fail.message = function() { return 'Expected function to throw an exception with message ' + j$.pp(message) + + ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; }; + return fail; } } if (regexp) { if (regexp.test(thrown.message)) { - return pass("Expected function not to throw an exception with a message matching " + j$.pp(regexp) + "."); + pass.message = function() { return 'Expected function not to throw an exception with a message matching ' + j$.pp(regexp) + '.'; }; + return pass; } else { - return fail("Expected function to throw an exception with a message matching " + j$.pp(regexp) + - ", but it threw an exception with message " + j$.pp(thrown.message) + "."); + fail.message = function() { return 'Expected function to throw an exception with a message matching ' + j$.pp(regexp) + + ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; }; + return fail; } } @@ -2331,20 +2476,6 @@ getJasmineRequireObj().toThrowError = function(j$) { return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1]; } - function pass(notMessage) { - return { - pass: true, - message: notMessage - }; - } - - function fail(message) { - return { - pass: false, - message: message - }; - } - function extractExpectedParams() { if (arguments.length == 1) { return; @@ -2355,34 +2486,34 @@ getJasmineRequireObj().toThrowError = function(j$) { if (expected instanceof RegExp) { regexp = expected; - } else if (typeof expected == "string") { + } else if (typeof expected == 'string') { message = expected; } else if (checkForAnErrorType(expected)) { errorType = expected; } if (!(errorType || message || regexp)) { - throw new Error("Expected is not an Error, string, or RegExp."); + throw new Error('Expected is not an Error, string, or RegExp.'); } } else { if (checkForAnErrorType(arguments[1])) { errorType = arguments[1]; } else { - throw new Error("Expected error type is not an Error."); + throw new Error('Expected error type is not an Error.'); } if (arguments[2] instanceof RegExp) { regexp = arguments[2]; - } else if (typeof arguments[2] == "string") { + } else if (typeof arguments[2] == 'string') { message = arguments[2]; } else { - throw new Error("Expected error message is not a string or RegExp."); + throw new Error('Expected error message is not a string or RegExp.'); } } } function checkForAnErrorType(type) { - if (typeof type !== "function") { + if (typeof type !== 'function') { return false; } @@ -2397,6 +2528,66 @@ getJasmineRequireObj().toThrowError = function(j$) { return toThrowError; }; +getJasmineRequireObj().interface = function(jasmine, env) { + var jasmineInterface = { + describe: function(description, specDefinitions) { + return env.describe(description, specDefinitions); + }, + + xdescribe: function(description, specDefinitions) { + return env.xdescribe(description, specDefinitions); + }, + + it: function(desc, func) { + return env.it(desc, func); + }, + + xit: function(desc, func) { + return env.xit(desc, func); + }, + + beforeEach: function(beforeEachFunction) { + return env.beforeEach(beforeEachFunction); + }, + + afterEach: function(afterEachFunction) { + return env.afterEach(afterEachFunction); + }, + + expect: function(actual) { + return env.expect(actual); + }, + + pending: function() { + return env.pending(); + }, + + spyOn: function(obj, methodName) { + return env.spyOn(obj, methodName); + }, + + jsApiReporter: new jasmine.JsApiReporter({ + timer: new jasmine.Timer() + }), + + jasmine: jasmine + }; + + jasmine.addCustomEqualityTester = function(tester) { + env.addCustomEqualityTester(tester); + }; + + jasmine.addMatchers = function(matchers) { + return env.addMatchers(matchers); + }; + + jasmine.clock = function() { + return env.clock; + }; + + return jasmineInterface; +}; + getJasmineRequireObj().version = function() { - return "2.0.0"; + return '2.0.3'; }; From e05bd42efe4de4572f1aa09312c13c1d5f85b075 Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Fri, 6 Mar 2015 09:43:02 +1000 Subject: [PATCH 15/16] Upgraded to Jasmine 2.0.3 CSS --- .../stylesheets/jasmine_2_0/jasmine.css | 114 +++++++++--------- .../jasmine_2_0/jasmine_favicon.png | Bin 0 -> 1486 bytes 2 files changed, 60 insertions(+), 54 deletions(-) create mode 100755 vendor/assets/stylesheets/jasmine_2_0/jasmine_favicon.png diff --git a/vendor/assets/stylesheets/jasmine_2_0/jasmine.css b/vendor/assets/stylesheets/jasmine_2_0/jasmine.css index f4d35b6..fb2afd1 100755 --- a/vendor/assets/stylesheets/jasmine_2_0/jasmine.css +++ b/vendor/assets/stylesheets/jasmine_2_0/jasmine.css @@ -1,55 +1,61 @@ -body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } +body { overflow-y: scroll; } -.html-reporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } -.html-reporter a { text-decoration: none; } -.html-reporter a:hover { text-decoration: underline; } -.html-reporter p, .html-reporter h1, .html-reporter h2, .html-reporter h3, .html-reporter h4, .html-reporter h5, .html-reporter h6 { margin: 0; line-height: 14px; } -.html-reporter .banner, .html-reporter .symbol-summary, .html-reporter .summary, .html-reporter .result-message, .html-reporter .spec .description, .html-reporter .spec-detail .description, .html-reporter .alert .bar, .html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; } -.html-reporter .banner .version { margin-left: 14px; } -.html-reporter #jasmine_content { position: fixed; right: 100%; } -.html-reporter .version { color: #aaaaaa; } -.html-reporter .banner { margin-top: 14px; } -.html-reporter .duration { color: #aaaaaa; float: right; } -.html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; } -.html-reporter .symbol-summary li { display: inline-block; height: 8px; width: 14px; font-size: 16px; } -.html-reporter .symbol-summary li.passed { font-size: 14px; } -.html-reporter .symbol-summary li.passed:before { color: #5e7d00; content: "\02022"; } -.html-reporter .symbol-summary li.failed { line-height: 9px; } -.html-reporter .symbol-summary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; } -.html-reporter .symbol-summary li.disabled { font-size: 14px; } -.html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; } -.html-reporter .symbol-summary li.pending { line-height: 17px; } -.html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; } -.html-reporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; } -.html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } -.html-reporter .bar.failed { background-color: #b03911; } -.html-reporter .bar.passed { background-color: #a6b779; } -.html-reporter .bar.skipped { background-color: #bababa; } -.html-reporter .bar.menu { background-color: #fff; color: #aaaaaa; } -.html-reporter .bar.menu a { color: #333333; } -.html-reporter .bar a { color: white; } -.html-reporter.spec-list .bar.menu.failure-list, .html-reporter.spec-list .results .failures { display: none; } -.html-reporter.failure-list .bar.menu.spec-list, .html-reporter.failure-list .summary { display: none; } -.html-reporter .running-alert { background-color: #666666; } -.html-reporter .results { margin-top: 14px; } -.html-reporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } -.html-reporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } -.html-reporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } -.html-reporter.showDetails .summary { display: none; } -.html-reporter.showDetails #details { display: block; } -.html-reporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } -.html-reporter .summary { margin-top: 14px; } -.html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; } -.html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; } -.html-reporter .summary li.passed a { color: #5e7d00; } -.html-reporter .summary li.failed a { color: #b03911; } -.html-reporter .summary li.pending a { color: #ba9d37; } -.html-reporter .description + .suite { margin-top: 0; } -.html-reporter .suite { margin-top: 14px; } -.html-reporter .suite a { color: #333333; } -.html-reporter .failures .spec-detail { margin-bottom: 28px; } -.html-reporter .failures .spec-detail .description { background-color: #b03911; } -.html-reporter .failures .spec-detail .description a { color: white; } -.html-reporter .result-message { padding-top: 14px; color: #333333; white-space: pre; } -.html-reporter .result-message span.result { display: block; } -.html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } +.jasmine_html-reporter { background-color: #eeeeee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } +.jasmine_html-reporter a { text-decoration: none; } +.jasmine_html-reporter a:hover { text-decoration: underline; } +.jasmine_html-reporter p, .jasmine_html-reporter h1, .jasmine_html-reporter h2, .jasmine_html-reporter h3, .jasmine_html-reporter h4, .jasmine_html-reporter h5, .jasmine_html-reporter h6 { margin: 0; line-height: 14px; } +.jasmine_html-reporter .banner, .jasmine_html-reporter .symbol-summary, .jasmine_html-reporter .summary, .jasmine_html-reporter .result-message, .jasmine_html-reporter .spec .description, .jasmine_html-reporter .spec-detail .description, .jasmine_html-reporter .alert .bar, .jasmine_html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; } +.jasmine_html-reporter .banner { position: relative; } +.jasmine_html-reporter .banner .title { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAZCAMAAACGusnyAAACdlBMVEX/////AP+AgICqVaqAQICZM5mAVYCSSZKAQICOOY6ATYCLRouAQICJO4mSSYCIRIiPQICHPIeOR4CGQ4aMQICGPYaLRoCFQ4WKQICPPYWJRYCOQoSJQICNPoSIRICMQoSHQICHRICKQoOHQICKPoOJO4OJQYOMQICMQ4CIQYKLQICIPoKLQ4CKQICNPoKJQISMQ4KJQoSLQYKJQISLQ4KIQoSKQYKIQICIQISMQoSKQYKLQIOLQoOJQYGLQIOKQIOMQoGKQYOLQYGKQIOLQoGJQYOJQIOKQYGJQIOKQoGKQIGLQIKLQ4KKQoGLQYKJQIGKQYKJQIGKQIKJQoGKQYKLQIGKQYKLQIOJQoKKQoOJQYKKQIOJQoKKQoOKQIOLQoKKQYOLQYKJQIOKQoKKQYKKQoKJQYOKQYKLQIOKQoKLQYOKQYKLQIOJQoGKQYKJQYGJQoGKQYKLQoGLQYGKQoGJQYKKQYGJQIKKQoGJQYKLQIKKQYGLQYKKQYGKQYGKQYKJQYOKQoKJQYOKQYKLQYOLQYOKQYKLQYOKQoKKQYKKQYOKQYOJQYKKQYKLQYKKQIKKQoKKQYKKQYKKQoKJQIKKQYKLQYKKQYKKQIKKQYKKQYKKQYKKQIKKQYKJQYGLQYGKQYKKQYKKQYGKQIKKQYGKQYOJQoKKQYOLQYKKQYOKQoKKQYKKQoKKQYKKQYKJQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKJQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKmIDpEAAAA0XRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAiIyQlJycoKissLS4wMTQ1Njc4OTo7PDw+P0BCQ0RISUpLTE1OUFNUVVdYWFlaW15fYGFiY2ZnaGlqa2xtb3BxcnN0dnh5ent8fX5/gIGChIWIioyNjo+QkZOUlZaYmZqbnJ2eoKGio6WmqKmsra6vsLGztre4ubq7vL2+wMHDxMjJysvNzs/Q0dLU1tfY2dvc3t/g4eLj5ebn6Onq6+zt7u/w8vP09fb3+Pn6+/z9/vkVQXAAAAMaSURBVHhe5dXxV1N1GMfxz2ABbDgIAm5VDJOyVDIJLUMaVpBWUZUaGbmqoGpZRSiGiRWp6KoZ5AB0ZY50RImZQIlahKkMYXv/R90dBvET/rJfOr3Ouc8v99zPec59zvf56j+vYKlViSf7250X4Mr3O29Tgq08BdGB4DhcekEJ5YkQKFsgWZdtj9JpV+I8xPjLFqkrsEIqO8PHSpis36jWazcqjEsfJjkvRssVU37SdIOu4XCf5vEJPsnwJpnRNU9JmxhMk8l1gehIrq7hTFjzOD+Vf88629qKMJVNltInFeRexRQyJlNeqd1iGDlSzrIUIyXbyFfm3RYprcQRe7lqtWyGYbfc6dT0R2vmdOOkX3u55C1rP37ftiH+tDby4r/RBT0w8TyEkr+epB9XgPDmSYYWbrhCuFYaIyw3fDQAXTnSkh+ANofiHmWf9l+FY1I90FdQTetstO00o23novzVsJ7uB3/C5TkbjRwZ5JerwV4iRWq9HFbFMaK/d0TYqayRiQPuIxxS3Bu8JWU90/60tKi7vkhaznez0a/TbVOKj5CaOZh6fWG6/Lyv9B/ZLR1gw/S/fpbeVD3MCW1li6SvWDOn65tr99/uvWtBS0XDm4s1t+sOHpG0kpBKx/l77wOSnxLpcx6TXmXLTPQOKYOf9Q1dfr8/SJ2mFdCvl1Yl93DiHUZvXeLJbGSzYu5gVJ2slbSakOR8dxCq5adQ2oFLqsE9Ex3L4qQO0eOPeU5x56bypXp4onSEb5OkICX6lDat55TeoztNKQcJaakrz9KCb95oD69IKq+yKW4XPjknaS52V0TZqE2cTtXjcHSCRmUO88e+85hj3EP74i9p8pylw7lxgMDyyl6OV7ZejnjNMfatu87LxRbH0IS35gt2a4ZjmGpVBdKK3Wr6INk8jWWSGqbA55CKgjBRC6E9w78ydTg3ABS3AFV1QN0Y4Aa2pgEjWnQURj9L0ayK6R2ysEqxHUKzYnLvvyU+i9KM2JHJzE4vyZOyDcOwOsySajeLPc8sNvPJkFlyJd20wpqAzZeAfZ3oWybxd+P/3j+SG3uSBdf2VQAAAABJRU5ErkJggg==') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -webkit-background-size: 100%; -moz-background-size: 100%; -o-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; } +.jasmine_html-reporter .banner .version { margin-left: 14px; position: relative; top: 6px; } +.jasmine_html-reporter .banner .duration { position: absolute; right: 14px; top: 6px; } +.jasmine_html-reporter #jasmine_content { position: fixed; right: 100%; } +.jasmine_html-reporter .version { color: #aaaaaa; } +.jasmine_html-reporter .banner { margin-top: 14px; } +.jasmine_html-reporter .duration { color: #aaaaaa; float: right; } +.jasmine_html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; } +.jasmine_html-reporter .symbol-summary li { display: inline-block; height: 8px; width: 14px; font-size: 16px; } +.jasmine_html-reporter .symbol-summary li.passed { font-size: 14px; } +.jasmine_html-reporter .symbol-summary li.passed:before { color: #007069; content: "\02022"; } +.jasmine_html-reporter .symbol-summary li.failed { line-height: 9px; } +.jasmine_html-reporter .symbol-summary li.failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; } +.jasmine_html-reporter .symbol-summary li.disabled { font-size: 14px; } +.jasmine_html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; } +.jasmine_html-reporter .symbol-summary li.pending { line-height: 17px; } +.jasmine_html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; } +.jasmine_html-reporter .symbol-summary li.empty { font-size: 14px; } +.jasmine_html-reporter .symbol-summary li.empty:before { color: #ba9d37; content: "\02022"; } +.jasmine_html-reporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; } +.jasmine_html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } +.jasmine_html-reporter .bar.failed { background-color: #ca3a11; } +.jasmine_html-reporter .bar.passed { background-color: #007069; } +.jasmine_html-reporter .bar.skipped { background-color: #bababa; } +.jasmine_html-reporter .bar.menu { background-color: #fff; color: #aaaaaa; } +.jasmine_html-reporter .bar.menu a { color: #333333; } +.jasmine_html-reporter .bar a { color: white; } +.jasmine_html-reporter.spec-list .bar.menu.failure-list, .jasmine_html-reporter.spec-list .results .failures { display: none; } +.jasmine_html-reporter.failure-list .bar.menu.spec-list, .jasmine_html-reporter.failure-list .summary { display: none; } +.jasmine_html-reporter .running-alert { background-color: #666666; } +.jasmine_html-reporter .results { margin-top: 14px; } +.jasmine_html-reporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } +.jasmine_html-reporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } +.jasmine_html-reporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } +.jasmine_html-reporter.showDetails .summary { display: none; } +.jasmine_html-reporter.showDetails #details { display: block; } +.jasmine_html-reporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } +.jasmine_html-reporter .summary { margin-top: 14px; } +.jasmine_html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; } +.jasmine_html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; } +.jasmine_html-reporter .summary li.passed a { color: #007069; } +.jasmine_html-reporter .summary li.failed a { color: #ca3a11; } +.jasmine_html-reporter .summary li.empty a { color: #ba9d37; } +.jasmine_html-reporter .summary li.pending a { color: #ba9d37; } +.jasmine_html-reporter .description + .suite { margin-top: 0; } +.jasmine_html-reporter .suite { margin-top: 14px; } +.jasmine_html-reporter .suite a { color: #333333; } +.jasmine_html-reporter .failures .spec-detail { margin-bottom: 28px; } +.jasmine_html-reporter .failures .spec-detail .description { background-color: #ca3a11; } +.jasmine_html-reporter .failures .spec-detail .description a { color: white; } +.jasmine_html-reporter .result-message { padding-top: 14px; color: #333333; white-space: pre; } +.jasmine_html-reporter .result-message span.result { display: block; } +.jasmine_html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } diff --git a/vendor/assets/stylesheets/jasmine_2_0/jasmine_favicon.png b/vendor/assets/stylesheets/jasmine_2_0/jasmine_favicon.png new file mode 100755 index 0000000000000000000000000000000000000000..3b84583be4b9d5ae9cd5cae07b2dbaa5ebb0ad1c GIT binary patch literal 1486 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabRA=0VDb;}332@o1PuQh8X8uGu4-^- zn3*=SA+%wV=cI;&hMB$%-Lc(MLmN8%IwwUpbcA;F2Q;)twND9bn-tpC9oR4-vb8I; zp+Bg#FSKP+P(yD-%f!%zo}iZgh=%Ua=KkP@iNVbiLYsSn8~VeW`+}P$1~&ACHcbd_ z=nZb_32o{NZkZ6&1k^hrxT!a&r8lIdAIJ@9nh?|iRMsET+#A%`AKKg-(%2K)*cZ|~ zA-J&*$PEUH08MM`4Q=iVY3vVfhN$TUscGs5sR8P31X|G_+SnTcv<0XVC=Rr!u|K4# zHyCJU6UYRR;%2BtKv^I=q#2|DECn_k@wXU|=@ zeD&J(8#iy=zH|5fgNKiwJbm`!<*V0k-oF3v@zdvTKYsrD^Y>rGdNDU(R>|^oaSW-5 z%f0Y2x+hSk{p0&HA;E60Oq1S3r7U;(X3MH#?W9nxXzk)srlC4P;cZYe&v*G}mgi%< ze(bTl{@&_)cX8b-kvX%ff9D22e*M~7edm|;|Jb8m2JBzkzKiSBKR0n*?XSyM6fxZY zJ4bb;vGKRiKP(ztq3sJx9iq$Re`-EEQU0KE$sdyqayzp6H-7x+oGKZ_6;hQ_Y|p&y z7o`N7g@ z8Yl1HKL;mFo4BdxljF1}KbfMR6nNdLyPnEap1MqBdI?{g$L58$P8+wftLX5R70)7n`#pwItnbma$w{%`M(`wpsu2rJ60rdGCc> z+~lm)viMYM`=uXwK_$`#_UtRZMO=2-IV)l2vc~)doyPvg-RmxtACQ#v{7}5$&isV+ zPws~n?@yNGy#H1=vTI?;CAl9~9#VgqJ+7`4y~R+Wyj0U+){?lm9r6mtf0gl_VmUW^ z%eje%?jM%^eLuUg#ybXaQM{yQy&8UgiQ`HQ+=iTpjfd0iJ@ ssyFi&dF4%9dEry;pNN)Q>$jg_dr3r;PHA*CFc&d+y85}Sb4q9e0J812W&i*H literal 0 HcmV?d00001 From 2ff026fb3e827ae5f27e5b6cb902b500f46f4c5c Mon Sep 17 00:00:00 2001 From: Michael Harrison Date: Fri, 6 Mar 2015 09:45:57 +1000 Subject: [PATCH 16/16] Updated version to match latest Jasmine version --- Gemfile.lock | 2 +- jasminerice.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 03e2b78..6d5cfad 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - jasminerice (2.0.0) + jasminerice (2.0.3) coffee-rails GEM diff --git a/jasminerice.gemspec b/jasminerice.gemspec index 5974c00..c7794dc 100644 --- a/jasminerice.gemspec +++ b/jasminerice.gemspec @@ -2,7 +2,7 @@ # project in your rails apps through git. Gem::Specification.new do |s| s.name = "jasminerice" - s.version = "2.0.0" + s.version = "2.0.3" s.authors = ["Brad Phelan"] s.summary = "Pain free coffeescript unit testing for Rails using jasmine" s.description = "Full support for the Rails asset pipeline when bdd'ing your coffeescript or javascript using jasmine"