diff options
Diffstat (limited to 'plugins/org.apache.cordova.file/test/autotest')
14 files changed, 7030 insertions, 0 deletions
diff --git a/plugins/org.apache.cordova.file/test/autotest/html/HtmlReporter.js b/plugins/org.apache.cordova.file/test/autotest/html/HtmlReporter.js new file mode 100644 index 00000000..7d9d9240 --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/html/HtmlReporter.js @@ -0,0 +1,101 @@ +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); + + 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 = doc.location.search.substring(1).split('&'); + + 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'}), + dom.results = self.createDom('div', {className: 'results'}, + dom.summary = self.createDom('div', { className: 'summary' }), + dom.details = self.createDom('div', { id: 'details' })) + ); + } +}; +jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter); diff --git a/plugins/org.apache.cordova.file/test/autotest/html/HtmlReporterHelpers.js b/plugins/org.apache.cordova.file/test/autotest/html/HtmlReporterHelpers.js new file mode 100644 index 00000000..745e1e09 --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/html/HtmlReporterHelpers.js @@ -0,0 +1,60 @@ +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]; + } +}; + diff --git a/plugins/org.apache.cordova.file/test/autotest/html/ReporterView.js b/plugins/org.apache.cordova.file/test/autotest/html/ReporterView.js new file mode 100644 index 00000000..6a6d0056 --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/html/ReporterView.js @@ -0,0 +1,164 @@ +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: "?", className: "runningAlert bar"}); + dom.alert.appendChild(this.runningAlert); + } + this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount); + + // skipped specs UI + if (isUndefined(this.skippedAlert)) { + this.skippedAlert = this.createDom('a', {href: "?", className: "skippedAlert bar"}); + } + + this.skippedAlert.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: "?", 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); + + diff --git a/plugins/org.apache.cordova.file/test/autotest/html/SpecView.js b/plugins/org.apache.cordova.file/test/autotest/html/SpecView.js new file mode 100644 index 00000000..e8a3c23d --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/html/SpecView.js @@ -0,0 +1,79 @@ +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: '?spec=' + encodeURIComponent(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); diff --git a/plugins/org.apache.cordova.file/test/autotest/html/SuiteView.js b/plugins/org.apache.cordova.file/test/autotest/html/SuiteView.js new file mode 100644 index 00000000..19a1efaf --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/html/SuiteView.js @@ -0,0 +1,22 @@ +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: '?spec=' + encodeURIComponent(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); + diff --git a/plugins/org.apache.cordova.file/test/autotest/html/TrivialReporter.js b/plugins/org.apache.cordova.file/test/autotest/html/TrivialReporter.js new file mode 100644 index 00000000..167ac506 --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/html/TrivialReporter.js @@ -0,0 +1,192 @@ +/* @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/plugins/org.apache.cordova.file/test/autotest/index.html b/plugins/org.apache.cordova.file/test/autotest/index.html new file mode 100644 index 00000000..6ebccbd0 --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/index.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<!-- + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +--> + + +<html> + <head> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> + <meta name="viewport" content="width=device-width, height=device-height, user-scalable=yes, initial-scale=1.0;" /> + + <title>Cordova API Specs</title> + + <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8"> + <script type="text/javascript" src="../cordova-incl.js"></script> + </head> + <body id="stage" class="theme"> + <h1>Cordova API Specs</h1> + + <a href="pages/all.html" class="btn large" style="width:100%;">Run All Tests</a> + <a href="pages/accelerometer.html" class="btn large" style="width:100%;">Run Accelerometer Tests</a> + <a href="pages/battery.html" class="btn large" style="width:100%;">Run Battery Tests</a> + <a href="pages/camera.html" class="btn large" style="width:100%;">Run Camera Tests</a> + <a href="pages/capture.html" class="btn large" style="width:100%;">Run Capture Tests</a> + <a href="pages/compass.html" class="btn large" style="width:100%;">Run Compass Tests</a> + <a href="pages/contacts.html" class="btn large" style="width:100%;">Run Contacts Tests</a> + <a href="pages/datauri.html" class="btn large" style="width:100%;">Run Data URI Tests</a> + <a href="pages/device.html" class="btn large" style="width:100%;">Run Device Tests</a> + <a href="pages/file.html" class="btn large" style="width:100%;">Run File Tests</a> + <a href="pages/filetransfer.html" class="btn large" style="width:100%;">Run FileTransfer Tests</a> + <a href="pages/geolocation.html" class="btn large" style="width:100%;">Run Geolocation Tests</a> + <a href="pages/globalization.html" class="btn large" style="width:100%;">Run Globalization Tests</a> + <a href="pages/media.html" class="btn large" style="width:100%;">Run Media Tests</a> + <a href="pages/network.html" class="btn large" style="width:100%;">Run Network Tests</a> + <a href="pages/notification.html" class="btn large" style="width:100%;">Run Notification Tests</a> + <a href="pages/platform.html" class="btn large" style="width:100%;">Run Platform Tests</a> + <a href="pages/storage.html" class="btn large" style="width:100%;">Run Storage Tests</a> + <a href="pages/bridge.html" class="btn large" style="width:100%;">Run Bridge Tests</a> + + <h2> </h2><div class="backBtn" onclick="backHome();">Back</div> + </body> +</html> diff --git a/plugins/org.apache.cordova.file/test/autotest/jasmine.css b/plugins/org.apache.cordova.file/test/autotest/jasmine.css new file mode 100644 index 00000000..826e5753 --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/jasmine.css @@ -0,0 +1,81 @@ +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 .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/plugins/org.apache.cordova.file/test/autotest/jasmine.js b/plugins/org.apache.cordova.file/test/autotest/jasmine.js new file mode 100644 index 00000000..9f284260 --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/jasmine.js @@ -0,0 +1,2530 @@ +var isCommonJS = typeof window == "undefined"; + +/** + * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. + * + * @namespace + */ +var jasmine = {}; +if (isCommonJS) exports.jasmine = jasmine; +/** + * @private + */ +jasmine.unimplementedMethod_ = function() { + throw new Error("unimplemented method"); +}; + +/** + * Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> 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; + +/** + * Default timeout interval in milliseconds for waitsFor() blocks. + */ +jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; + +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 <b>not</b> 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 <code>jasmine.log</code> 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 + * @returns 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 <em>disabled</em> 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 + */ +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, '<') + .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.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 (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) { + 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 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() { + if (this.actual.callCount === 0) { + // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw] + return [ + "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.", + "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was." + ]; + } else { + return [ + "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall), + "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall) + ]; + } + }; + + 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 + */ +jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { + if (!(precision === 0)) { + precision = precision || 2; + } + var multiplier = Math.pow(10, precision); + var actual = Math.round(this.actual * multiplier); + expected = Math.round(expected * multiplier); + return expected == actual; +}; + +/** + * 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.any(' + this.expectedClass + ')>'; +}; + +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 "<jasmine.objectContaining(" + jasmine.pp(this.sample) + ")>"; +}; +// 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 <b>everything</b> 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) { + if (this.ppNestLevel_ > 40) { + throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); + } + + this.ppNestLevel_++; + try { + if (value === jasmine.undefined) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === jasmine.getGlobal()) { + this.emitScalar('<global>'); + } 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('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>'); + } 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 (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) { + 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) { + 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('<getter>'); + } else { + self.format(obj[property]); + } + }); + + this.append(' }'); +}; + +jasmine.StringPrettyPrinter.prototype.append = function(value) { + this.string += value; +}; +jasmine.Queue = function(env) { + this.env = env; + this.blocks = []; + this.running = false; + this.index = 0; + this.offset = 0; + this.abort = false; +}; + +jasmine.Queue.prototype.addBefore = function(block) { + this.blocks.unshift(block); +}; + +jasmine.Queue.prototype.add = function(block) { + this.blocks.push(block); +}; + +jasmine.Queue.prototype.insertNext = function(block) { + 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) { + 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 <code>jasmine.log</code> 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)); + } 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)); + } + 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)); + } + } + for (i = 0; i < runner.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, runner.after_[i], this)); + } +}; + +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": 2, + "build": 0, + "revision": 1333310630, + "release_candidate": 1 +}; diff --git a/plugins/org.apache.cordova.file/test/autotest/pages/.DS_Store b/plugins/org.apache.cordova.file/test/autotest/pages/.DS_Store Binary files differnew file mode 100644 index 00000000..5008ddfc --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/pages/.DS_Store diff --git a/plugins/org.apache.cordova.file/test/autotest/pages/file.html b/plugins/org.apache.cordova.file/test/autotest/pages/file.html new file mode 100644 index 00000000..d143c744 --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/pages/file.html @@ -0,0 +1,90 @@ +<!DOCTYPE html> +<!-- + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +--> + + +<html> +<head> + <title>Cordova: File API Specs</title> + + <meta name="viewport" content="width=device-width, height=device-height, user-scalable=yes, initial-scale=1.0;" /> + <!-- Load jasmine --> + <link href="../jasmine.css" rel="stylesheet"/> + <script type="text/javascript" src="../jasmine.js"></script> + <script type="text/javascript" src="../html/HtmlReporterHelpers.js"></script> + <script type="text/javascript" src="../html/HtmlReporter.js"></script> + <script type="text/javascript" src="../html/ReporterView.js"></script> + <script type="text/javascript" src="../html/SpecView.js"></script> + <script type="text/javascript" src="../html/SuiteView.js"></script> + <script type="text/javascript" src="../html/TrivialReporter.js"></script> + + <!-- Source --> + <script type="text/javascript" src="../../cordova-incl.js"></script> + + <!-- Load Test Runner --> + <script type="text/javascript" src="../test-runner.js"></script> + + <!-- Tests --> + <script type="text/javascript" src="../tests/file.tests.js"></script> + + <script type="text/javascript"> + var root, temp_root, persistent_root; + + document.addEventListener('deviceready', function () { + // one-time retrieval of the root file system entry + var onError = function(e) { + console.log('[ERROR] Problem setting up root filesystem for test running! Error to follow.'); + console.log(JSON.stringify(e)); + }; + + window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, + function(fileSystem) { + console.log('File API test Init: Setting PERSISTENT FS.'); + root = fileSystem.root; // set in file.tests.js + persistent_root = root; + + // Once root is set up, fire off tests + var jasmineEnv = jasmine.getEnv(); + jasmineEnv.updateInterval = 1000; + + var htmlReporter = new jasmine.HtmlReporter(); + + jasmineEnv.addReporter(htmlReporter); + + jasmineEnv.specFilter = function(spec) { + return htmlReporter.specFilter(spec); + }; + + jasmineEnv.execute(); + }, onError); + window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, + function(fileSystem) { + console.log('File API test Init: Setting TEMPORARY FS.'); + temp_root = fileSystem.root; // set in file.tests.js + }, onError); + }, false); + </script> +</head> + +<body> + <a href="javascript:" class="backBtn" onclick="backHome();">Back</a> +</body> +</html> diff --git a/plugins/org.apache.cordova.file/test/autotest/test-runner.js b/plugins/org.apache.cordova.file/test/autotest/test-runner.js new file mode 100644 index 00000000..f72b3cc5 --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/test-runner.js @@ -0,0 +1,62 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * +*/ + +if (window.sessionStorage != null) { + window.sessionStorage.clear(); +} + +// Timeout is 2 seconds to allow physical devices enough +// time to query the response. This is important for some +// Android devices. +var Tests = function() {}; +Tests.TEST_TIMEOUT = 7500; + +// Creates a spy that will fail if called. +function createDoNotCallSpy(name, opt_extraMessage) { + return jasmine.createSpy().andCallFake(function() { + var errorMessage = name + ' should not have been called.'; + if (arguments.length) { + errorMessage += ' Got args: ' + JSON.stringify(arguments); + } + if (opt_extraMessage) { + errorMessage += '\n' + opt_extraMessage; + } + expect(false).toBe(true, errorMessage); + }); +} + +// Waits for any of the given spys to be called. +// Last param may be a custom timeout duration. +function waitsForAny() { + var spys = [].slice.call(arguments); + var timeout = Tests.TEST_TIMEOUT; + if (typeof spys[spys.length - 1] == 'number') { + timeout = spys.pop(); + } + waitsFor(function() { + for (var i = 0; i < spys.length; ++i) { + if (spys[i].wasCalled) { + return true; + } + } + return false; + }, "Expecting callbacks to be called.", timeout); +} diff --git a/plugins/org.apache.cordova.file/test/autotest/tests/.DS_Store b/plugins/org.apache.cordova.file/test/autotest/tests/.DS_Store Binary files differnew file mode 100644 index 00000000..5008ddfc --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/tests/.DS_Store diff --git a/plugins/org.apache.cordova.file/test/autotest/tests/file.tests.js b/plugins/org.apache.cordova.file/test/autotest/tests/file.tests.js new file mode 100644 index 00000000..3ebaffcc --- /dev/null +++ b/plugins/org.apache.cordova.file/test/autotest/tests/file.tests.js @@ -0,0 +1,3590 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * +*/ + +describe('File API', function() { + // Adding a Jasmine helper matcher, to report errors when comparing to FileError better. + var fileErrorMap = { + 1: 'NOT_FOUND_ERR', + 2: 'SECURITY_ERR', + 3: 'ABORT_ERR', + 4: 'NOT_READABLE_ERR', + 5: 'ENCODING_ERR', + 6: 'NO_MODIFICATION_ALLOWED_ERR', + 7: 'INVALID_STATE_ERR', + 8: 'SYNTAX_ERR', + 9: 'INVALID_MODIFICATION_ERR', + 10:'QUOTA_EXCEEDED_ERR', + 11:'TYPE_MISMATCH_ERR', + 12:'PATH_EXISTS_ERR' + }; + beforeEach(function() { + this.addMatchers({ + toBeFileError: function(code) { + var error = this.actual; + this.message = function(){ + return "Expected FileError with code " + fileErrorMap[error.code] + " (" + error.code + ") to be " + fileErrorMap[code] + "(" + code + ")"; + }; + return (error.code == code); + }, + toCanonicallyMatch:function(path){ + this.message = function(){ + return "Expected paths to match : " + path + " should be " + this.actual; + }; + + var a = path.split("/").join("").split("\\").join(""); + var b = this.actual.split("/").join("").split("\\").join(""); + + return a == b; + } + }); + }); + + // HELPER FUNCTIONS + + // deletes specified file or directory + var deleteEntry = function(name, success, error) { + // deletes entry, if it exists + window.resolveLocalFileSystemURI(root.toURL() + '/' + name, + function(entry) { + if (entry.isDirectory === true) { + entry.removeRecursively(success, error); + } else { + entry.remove(success, error); + } + }, success); + }; + // deletes file, if it exists, then invokes callback + var deleteFile = function(fileName, callback) { + root.getFile(fileName, null, + // remove file system entry + function(entry) { + entry.remove(callback, function() { console.log('[ERROR] deleteFile cleanup method invoked fail callback.'); }); + }, + // doesn't exist + callback); + }; + // deletes and re-creates the specified file + var createFile = function(fileName, success, error) { + deleteEntry(fileName, function() { + root.getFile(fileName, {create: true}, success, error); + }, error); + }; + // deletes and re-creates the specified directory + var createDirectory = function(dirName, success, error) { + deleteEntry(dirName, function() { + root.getDirectory(dirName, {create: true}, success, error); + }, error); + }; + + var createFail = function(module) { + return jasmine.createSpy().andCallFake(function(err) { + console.log('[ERROR ' + module + '] ' + JSON.stringify(err)); + }); + }; + + var createWin = function(module) { + return jasmine.createSpy().andCallFake(function() { + console.log('[ERROR ' + module + '] Unexpected success callback'); + }); + }; + + describe('FileError object', function() { + it("file.spec.1 should define FileError constants", function() { + expect(FileError.NOT_FOUND_ERR).toBe(1); + expect(FileError.SECURITY_ERR).toBe(2); + expect(FileError.ABORT_ERR).toBe(3); + expect(FileError.NOT_READABLE_ERR).toBe(4); + expect(FileError.ENCODING_ERR).toBe(5); + expect(FileError.NO_MODIFICATION_ALLOWED_ERR).toBe(6); + expect(FileError.INVALID_STATE_ERR).toBe(7); + expect(FileError.SYNTAX_ERR).toBe(8); + expect(FileError.INVALID_MODIFICATION_ERR).toBe(9); + expect(FileError.QUOTA_EXCEEDED_ERR).toBe(10); + expect(FileError.TYPE_MISMATCH_ERR).toBe(11); + expect(FileError.PATH_EXISTS_ERR).toBe(12); + }); + }); + + describe('LocalFileSystem', function() { + + it("file.spec.2 should define LocalFileSystem constants", function() { + expect(LocalFileSystem.TEMPORARY).toBe(0); + expect(LocalFileSystem.PERSISTENT).toBe(1); + }); + + describe('window.requestFileSystem', function() { + it("file.spec.3 should be defined", function() { + expect(window.requestFileSystem).toBeDefined(); + }); + it("file.spec.4 should be able to retrieve a PERSISTENT file system", function() { + var win = jasmine.createSpy().andCallFake(function(fileSystem) { + expect(fileSystem).toBeDefined(); + expect(fileSystem.name).toBeDefined(); + expect(fileSystem.name).toBe("persistent"); + expect(fileSystem.root).toBeDefined(); + }), + fail = createFail('window.requestFileSystem'); + + // retrieve PERSISTENT file system + runs(function() { + window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "success callback never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).not.toHaveBeenCalled(); + expect(win).toHaveBeenCalled(); + }); + }); + it("file.spec.5 should be able to retrieve a TEMPORARY file system", function() { + var win = jasmine.createSpy().andCallFake(function(fileSystem) { + expect(fileSystem).toBeDefined(); + expect(fileSystem.name).toBeDefined(); + expect(fileSystem.name).toBe("temporary"); + expect(fileSystem.root).toBeDefined(); + }), + fail = createFail('window.requestFileSystem'); + + // Request the file system + runs(function() { + window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "success callback never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).not.toHaveBeenCalled(); + expect(win).toHaveBeenCalled(); + }); + }); + it("file.spec.6 should error if you request a file system that is too large", function() { + var fail = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.QUOTA_EXCEEDED_ERR); + }), + win = createWin('window.requestFileSystem'); + + // Request the file system + runs(function() { + window.requestFileSystem(LocalFileSystem.TEMPORARY, 1000000000000000, win, fail); + }); + + waitsFor(function() { return fail.wasCalled; }, "error callback never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).not.toHaveBeenCalled(); + expect(fail).toHaveBeenCalled(); + }); + }); + it("file.spec.7 should error out if you request a file system that does not exist", function() { + var fail = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.SYNTAX_ERR); + }), + win = createWin('window.requestFileSystem'); + + // Request the file system + runs(function() { + window.requestFileSystem(-1, 0, win, fail); + }); + + waitsFor(function() { return fail.wasCalled; }, "error callback never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).not.toHaveBeenCalled(); + expect(fail).toHaveBeenCalled(); + }); + }); + }); + + describe('window.resolveLocalFileSystemURI', function() { + it("file.spec.3 should be defined", function() { + expect(window.resolveLocalFileSystemURI).toBeDefined(); + }); + it("file.spec.9 should resolve a valid file name", function() { + var fileName = "resolve.file.uri", + win = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.name).toCanonicallyMatch(fileName); + + // cleanup + deleteEntry(fileName); + }), + fail = createFail('window.resolveLocalFileSystemURI'); + resolveCallback = jasmine.createSpy().andCallFake(function(entry) { + // lookup file system entry + runs(function() { + window.resolveLocalFileSystemURI(entry.toURL(), win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "resolveLocalFileSystemURI callback never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + + // create a new file entry + runs(function() { + createFile(fileName, resolveCallback, fail); + }); + + waitsFor(function() { return resolveCallback.wasCalled; }, "createFile callback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.10 resolve valid file name with parameters", function() { + var fileName = "resolve.file.uri.params", + win = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.name).toBe(fileName); + + // cleanup + deleteEntry(fileName); + }), + fail = createFail('window.resolveLocalFileSystemURI'); + resolveCallback = jasmine.createSpy().andCallFake(function(entry) { + // lookup file system entry + runs(function() { + window.resolveLocalFileSystemURI(entry.toURL() + "?1234567890", win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "resolveLocalFileSystemURI callback never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + + // create a new file entry + runs(function() { + createFile(fileName, resolveCallback, fail); + }); + + waitsFor(function() { return resolveCallback.wasCalled; }, "createFile callback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.11 should error (NOT_FOUND_ERR) when resolving (non-existent) invalid file name", function() { + var fail = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + }), + win = createWin('window.resolveLocalFileSystemURI'); + + // lookup file system entry + runs(function() { + window.resolveLocalFileSystemURI("file:///this.is.not.a.valid.file.txt", win, fail); + }); + + waitsFor(function() { return fail.wasCalled; }, "error callback never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + }); + it("file.spec.12 should error (ENCODING_ERR) when resolving invalid URI with leading /", function() { + var fail = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.ENCODING_ERR); + }), + win = createWin('window.resolveLocalFileSystemURI'); + + // lookup file system entry + runs(function() { + window.resolveLocalFileSystemURI("/this.is.not.a.valid.url", win, fail); + }); + + waitsFor(function() { return fail.wasCalled; }, "error callback never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + }); + }); + }); + + describe('Metadata interface', function() { + it("file.spec.13 should exist and have the right properties", function() { + var metadata = new Metadata(); + expect(metadata).toBeDefined(); + expect(metadata.modificationTime).toBeDefined(); + }); + }); + + describe('Flags interface', function() { + it("file.spec.13 should exist and have the right properties", function() { + var flags = new Flags(false, true); + expect(flags).toBeDefined(); + expect(flags.create).toBeDefined(); + expect(flags.create).toBe(false); + expect(flags.exclusive).toBeDefined(); + expect(flags.exclusive).toBe(true); + }); + }); + + describe('FileSystem interface', function() { + it("file.spec.15 should have a root that is a DirectoryEntry", function() { + var win = jasmine.createSpy().andCallFake(function(entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(false); + expect(entry.isDirectory).toBe(true); + expect(entry.name).toBeDefined(); + expect(entry.fullPath).toBeDefined(); + expect(entry.getMetadata).toBeDefined(); + expect(entry.moveTo).toBeDefined(); + expect(entry.copyTo).toBeDefined(); + expect(entry.toURL).toBeDefined(); + expect(entry.remove).toBeDefined(); + expect(entry.getParent).toBeDefined(); + expect(entry.createReader).toBeDefined(); + expect(entry.getFile).toBeDefined(); + expect(entry.getDirectory).toBeDefined(); + expect(entry.removeRecursively).toBeDefined(); + }), + fail = createFail('FileSystem'); + + runs(function() { + window.resolveLocalFileSystemURI(root.toURL(), win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "success callback never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).not.toHaveBeenCalled(); + expect(win).toHaveBeenCalled(); + }); + }); + }); + + describe('DirectoryEntry', function() { + it("file.spec.16 getFile: get Entry for file that does not exist", function() { + var fileName = "de.no.file", + filePath = root.fullPath + '/' + fileName, + fail = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + }), + win = createWin('DirectoryEntry'); + + // create:false, exclusive:false, file does not exist + runs(function() { + root.getFile(fileName, {create:false}, win, fail); + }); + + waitsFor(function() { return fail.wasCalled; }, "error callback never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + }); + it("file.spec.17 etFile: create new file", function() { + var fileName = "de.create.file", + filePath = root.fullPath + '/' + fileName, + win = jasmine.createSpy().andCallFake(function(entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(fileName); + expect(entry.fullPath).toBe(filePath); + // cleanup + entry.remove(null, null); + }), + fail = createFail('DirectoryEntry'); + + // create:true, exclusive:false, file does not exist + runs(function() { + root.getFile(fileName, {create: true}, win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "success callback never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.18 getFile: create new file (exclusive)", function() { + var fileName = "de.create.exclusive.file", + filePath = root.fullPath + '/' + fileName, + win = jasmine.createSpy().andCallFake(function(entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toBe(fileName); + expect(entry.fullPath).toBe(filePath); + + // cleanup + entry.remove(null, null); + }), + fail = createFail('DirectoryEntry'); + + // create:true, exclusive:true, file does not exist + runs(function() { + root.getFile(fileName, {create: true, exclusive:true}, win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "success callback never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.19 getFile: create file that already exists", function() { + var fileName = "de.create.existing.file", + filePath = root.fullPath + '/' + fileName, + getFile = jasmine.createSpy().andCallFake(function(file) { + // create:true, exclusive:false, file exists + runs(function() { + root.getFile(fileName, {create:true}, win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "win was never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + fail = createFail('DirectoryEntry'), + win = jasmine.createSpy().andCallFake(function(entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(fileName); + expect(entry.fullPath).toBe(filePath); + + // cleanup + entry.remove(null, fail); + }); + // create file to kick off it + runs(function() { + root.getFile(fileName, {create:true}, getFile, fail); + }); + + waitsFor(function() { return getFile.wasCalled; }, "getFile was never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.20 getFile: create file that already exists (exclusive)", function() { + var fileName = "de.create.exclusive.existing.file", + filePath = root.fullPath + '/' + fileName, + existingFile, + getFile = jasmine.createSpy().andCallFake(function(file) { + existingFile = file; + // create:true, exclusive:true, file exists + runs(function() { + root.getFile(fileName, {create:true, exclusive:true}, win, fail); + }); + + waitsFor(function() { return fail.wasCalled; }, "fail never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + }), + fail = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.PATH_EXISTS_ERR); + + // cleanup + existingFile.remove(null, fail); + }), + win = createWin('DirectoryEntry'); + + // create file to kick off it + runs(function() { + root.getFile(fileName, {create:true}, getFile, fail); + }); + + waitsFor(function() { return getFile.wasCalled; }, "getFile never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.21 getFile: get Entry for existing file", function() { + var fileName = "de.get.file", + filePath = root.fullPath + '/' + fileName, + win = jasmine.createSpy().andCallFake(function(entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(fileName); + expect(entry.fullPath).toCanonicallyMatch(filePath); + + entry.remove(null, fail); //clean up + }), + fail = createFail('DirectoryEntry'), + getFile = jasmine.createSpy().andCallFake(function(file) { + // create:false, exclusive:false, file exists + runs(function() { + root.getFile(fileName, {create:false}, win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "getFile success callback", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + + // create file to kick off it + runs(function() { + root.getFile(fileName, {create:true}, getFile, fail); + }); + + waitsFor(function() { return getFile.wasCalled; }, "file creation", Tests.TEST_TIMEOUT); + }); + it("file.spec.22 DirectoryEntry.getFile: get FileEntry for invalid path", function() { + var fileName = "de:invalid:path", + fail = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.ENCODING_ERR); + }), + win = createWin('DirectoryEntry'); + + // create:false, exclusive:false, invalid path + runs(function() { + root.getFile(fileName, {create:false}, win, fail); + }); + + waitsFor(function() { return fail.wasCalled; }, "fail never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + + }); + it("file.spec.23 DirectoryEntry.getDirectory: get Entry for directory that does not exist", function() { + var dirName = "de.no.dir", + dirPath = root.fullPath + '/' + dirName, + fail = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + }), + win = createWin('DirectoryEntry'); + + // create:false, exclusive:false, directory does not exist + runs(function() { + root.getDirectory(dirName, {create:false}, win, fail); + }); + + waitsFor(function() { return fail.wasCalled; }, "fail never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + }); + it("file.spec.24 DirectoryEntry.getDirectory: create new dir with space then resolveFileSystemURI", function() { + var dirName = "de create dir", + dirPath = root.fullPath + '/' + dirName, + getDir = jasmine.createSpy().andCallFake(function(dirEntry) { + var dirURI = dirEntry.toURL(); + // now encode URI and try to resolve + runs(function() { + window.resolveLocalFileSystemURI(dirURI, win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + + }), win = jasmine.createSpy().andCallFake(function(directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(dirName); + expect(directory.fullPath).toCanonicallyMatch(dirPath); + + // cleanup + directory.remove(null, fail); + }), + fail = createFail('DirectoryEntry'); + + // create:true, exclusive:false, directory does not exist + runs(function() { + root.getDirectory(dirName, {create: true}, getDir, fail); + }); + + waitsFor(function() { return getDir.wasCalled; }, "getDir never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.25 DirectoryEntry.getDirectory: create new dir with space resolveFileSystemURI with encoded URI", function() { + var dirName = "de create dir", + dirPath = root.fullPath + '/' + dirName, + getDir = jasmine.createSpy().andCallFake(function(dirEntry) { + var dirURI = dirEntry.toURL(); + // now encode URI and try to resolve + runs(function() { + window.resolveLocalFileSystemURI(encodeURI(dirURI), win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + win = jasmine.createSpy().andCallFake(function(directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(dirName); + expect(directory.fullPath).toCanonicallyMatch(dirPath); + // cleanup + directory.remove(null, fail); + }), + fail = createFail('DirectoryEntry'); + + // create:true, exclusive:false, directory does not exist + runs(function() { + root.getDirectory(dirName, {create: true}, getDir, fail); + }); + + waitsFor(function() { return getDir.wasCalled; }, "getDir never called", Tests.TEST_TIMEOUT); + }); + + it("file.spec.26 DirectoryEntry.getDirectory: create new directory", function() { + var dirName = "de.create.dir", + dirPath = root.fullPath + '/' + dirName, + win = jasmine.createSpy().andCallFake(function(directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(dirName); + expect(directory.fullPath).toCanonicallyMatch(dirPath); + + // cleanup + directory.remove(null, fail); + }), + fail = createFail('DirectoryEntry'); + + // create:true, exclusive:false, directory does not exist + runs(function() { + root.getDirectory(dirName, {create: true}, win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + + it("file.spec.27 DirectoryEntry.getDirectory: create new directory (exclusive)", function() { + var dirName = "de.create.exclusive.dir", + dirPath = root.fullPath + '/' + dirName, + win = jasmine.createSpy().andCallFake(function(directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(dirName); + expect(directory.fullPath).toCanonicallyMatch(dirPath); + + // cleanup + directory.remove(null, fail); + }), + fail = createFail('DirectoryEntry'); + // create:true, exclusive:true, directory does not exist + runs(function() { + root.getDirectory(dirName, {create: true, exclusive:true}, win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.28 DirectoryEntry.getDirectory: create directory that already exists", function() { + var dirName = "de.create.existing.dir", + dirPath = root.fullPath + '/' + dirName, + getDir = jasmine.createSpy().andCallFake(function(directory) { + // create:true, exclusive:false, directory exists + runs(function() { + root.getDirectory(dirName, {create:true}, win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + win = jasmine.createSpy().andCallFake(function(directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(dirName); + expect(directory.fullPath).toCanonicallyMatch(dirPath); + + // cleanup + directory.remove(null, fail); + }), + fail = createFail('DirectoryEntry'); + + // create directory to kick off it + runs(function() { + root.getDirectory(dirName, {create:true}, getDir, this.fail); + }); + + waitsFor(function() { return getDir.wasCalled; }, "getDir never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.29 DirectoryEntry.getDirectory: create directory that already exists (exclusive)", function() { + var dirName = "de.create.exclusive.existing.dir", + dirPath = root.fullPath + '/' + dirName, + existingDir, + getDir = jasmine.createSpy().andCallFake(function(directory) { + existingDir = directory; + // create:true, exclusive:true, directory exists + runs(function() { + root.getDirectory(dirName, {create:true, exclusive:true}, win, fail); + }); + + waitsFor(function() { return fail.wasCalled; }, "fail never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + }), + fail = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.PATH_EXISTS_ERR); + + // cleanup + existingDir.remove(null, fail); + }), + win = createWin('DirectoryEntry'); + + // create directory to kick off it + runs(function() { + root.getDirectory(dirName, {create:true}, getDir, fail); + }); + + waitsFor(function() { return getDir.wasCalled; }, "getDir never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.30 DirectoryEntry.getDirectory: get Entry for existing directory", function() { + var dirName = "de.get.dir", + dirPath = root.fullPath + '/' + dirName, + getDir = jasmine.createSpy().andCallFake(function(directory) { + // create:false, exclusive:false, directory exists + runs(function() { + root.getDirectory(dirName, {create:false}, win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + win = jasmine.createSpy().andCallFake(function(directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(dirName); + + expect(directory.fullPath).toCanonicallyMatch(dirPath); + + // cleanup + directory.remove(null, fail); + }), + fail = createFail('DirectoryEntry'); + + // create directory to kick off it + root.getDirectory(dirName, {create:true}, getDir, fail); + }); + it("file.spec.31 DirectoryEntry.getDirectory: get DirectoryEntry for invalid path", function() { + var dirName = "de:invalid:path", + fail = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.ENCODING_ERR); + }), + win = createWin('DirectoryEntry'); + + // create:false, exclusive:false, invalid path + runs(function() { + root.getDirectory(dirName, {create:false}, win, fail); + }); + + waitsFor(function() { return fail.wasCalled; }, "fail never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + }); + it("file.spec.32 DirectoryEntry.getDirectory: get DirectoryEntry for existing file", function() { + var fileName = "de.existing.file", + existingFile, + filePath = root.fullPath + '/' + fileName, + getDir = jasmine.createSpy().andCallFake(function(file) { + existingFile = file; + // create:false, exclusive:false, existing file + runs(function() { + root.getDirectory(fileName, {create:false}, win, fail); + }); + + waitsFor(function() { return fail.wasCalled; }, "fail never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + }), + fail = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.TYPE_MISMATCH_ERR); + + // cleanup + existingFile.remove(null, null); + }), + win = createWin('DirectoryEntry'); + + // create file to kick off it + runs(function() { + root.getFile(fileName, {create:true}, getDir, fail); + }); + + waitsFor(function() { return getDir.wasCalled; }, "getDir was called", Tests.TEST_TIMEOUT); + }); + it("file.spec.33 DirectoryEntry.getFile: get FileEntry for existing directory", function() { + var dirName = "de.existing.dir", + existingDir, + dirPath = root.fullPath + '/' + dirName, + getFile = jasmine.createSpy().andCallFake(function(directory) { + existingDir = directory; + // create:false, exclusive:false, existing directory + runs(function() { + root.getFile(dirName, {create:false}, win, fail); + }); + + waitsFor(function() { return fail.wasCalled; }, "fail never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + }), + fail = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.TYPE_MISMATCH_ERR); + + // cleanup + existingDir.remove(null, null); + }), + win = createWin('DirectoryEntry'); + + // create directory to kick off it + runs(function() { + root.getDirectory(dirName, {create:true}, getFile, fail); + }); + + waitsFor(function() { return getFile.wasCalled; }, "getFile never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.34 DirectoryEntry.removeRecursively on directory", function() { + var dirName = "de.removeRecursively", + subDirName = "dir", + dirPath = root.fullPath + '/' + dirName, + //subDirPath = this.root.fullPath + '/' + subDirName, + subDirPath = dirPath + '/' + subDirName, + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + // delete directory + var deleteDirectory = jasmine.createSpy().andCallFake(function(directory) { + runs(function() { + entry.removeRecursively(remove, fail); + }); + + waitsFor(function() { return remove.wasCalled; }, "remove never called", Tests.TEST_TIMEOUT); + }); + // create a sub-directory within directory + runs(function() { + entry.getDirectory(subDirName, {create: true}, deleteDirectory, fail); + }); + + waitsFor(function() { return deleteDirectory.wasCalled; }, "deleteDirectory never called", Tests.TEST_TIMEOUT); + }), + remove = jasmine.createSpy().andCallFake(function() { + // it that removed directory no longer exists + runs(function() { + root.getDirectory(dirName, {create:false}, win, dirExists); + }); + + waitsFor(function() { return dirExists.wasCalled; }, "dirExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(dirExists).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + }), + dirExists = jasmine.createSpy().andCallFake(function(error){ + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + }), + fail = createFail('DirectoryEntry'), + win = createWin('DirectoryEntry'); + + // create a new directory entry to kick off it + runs(function() { + root.getDirectory(dirName, {create:true}, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.35 createReader: create reader on existing directory", function() { + // create reader for root directory + var reader = root.createReader(); + expect(reader).toBeDefined(); + expect(typeof reader.readEntries).toBe('function'); + }); + it("file.spec.36 removeRecursively on root file system", function() { + var remove = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NO_MODIFICATION_ALLOWED_ERR); + }), + win = createWin('DirectoryEntry'); + + // remove root file system + runs(function() { + root.removeRecursively(win, remove); + }); + + waitsFor(function() { return remove.wasCalled; }, "remove never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).not.toHaveBeenCalled(); + expect(remove).toHaveBeenCalled(); + }); + }); + }); + + describe('DirectoryReader interface', function() { + describe("readEntries", function() { + it("file.spec.37 should read contents of existing directory", function() { + var reader, + win = jasmine.createSpy().andCallFake(function(entries) { + expect(entries).toBeDefined(); + expect(entries instanceof Array).toBe(true); + }), + fail = createFail('DirectoryReader'); + + // create reader for root directory + reader = root.createReader(); + // read entries + runs(function() { + reader.readEntries(win, fail); + }); + + waitsFor(function() { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.38 should read contents of directory that has been removed", function() { + var dirName = "de.createReader.notfound", + dirPath = root.fullPath + '/' + dirName, + entryCallback = jasmine.createSpy().andCallFake(function(directory) { + // read entries + var readEntries = jasmine.createSpy().andCallFake(function() { + var reader = directory.createReader(); + + runs(function() { + reader.readEntries(win, itReader); + }); + + waitsFor(function() { return itReader.wasCalled; }, "itReader never called", Tests.TEST_TIMEOUT); + }); + // delete directory + runs(function() { + directory.removeRecursively(readEntries, fail); + }); + + waitsFor(function() { return readEntries.wasCalled; }, "readEntries never called", Tests.TEST_TIMEOUT); + }), + itReader = jasmine.createSpy().andCallFake(function(error) { + var itDirectoryExists = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + }); + + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + + runs(function() { + root.getDirectory(dirName, {create:false}, win, itDirectoryExists); + }); + + waitsFor(function() { return itDirectoryExists.wasCalled; }, "itDirectoryExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itDirectoryExists).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + }), + fail = createFail('DirectoryReader'), + win = createWin('DirectoryReader'); + + // create a new directory entry to kick off it + runs(function() { + root.getDirectory(dirName, {create:true}, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + }); + }); + + describe('File', function() { + it("file.spec.39 constructor should be defined", function() { + expect(File).toBeDefined(); + expect(typeof File).toBe('function'); + }); + it("file.spec.40 should be define File attributes", function() { + var file = new File(); + expect(file.name).toBeDefined(); + expect(file.fullPath).toBeDefined(); + expect(file.type).toBeDefined(); + expect(file.lastModifiedDate).toBeDefined(); + expect(file.size).toBeDefined(); + }); + }); + + describe('FileEntry', function() { + it("file.spec.41 should be define FileEntry methods", function() { + var fileName = "fe.methods", + itFileEntry = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(typeof fileEntry.createWriter).toBe('function'); + expect(typeof fileEntry.file).toBe('function'); + + // cleanup + fileEntry.remove(null, fail); + }), + fail = createFail('FileEntry'); + + // create a new file entry to kick off it + runs(function() { + root.getFile(fileName, {create:true}, itFileEntry, fail); + }); + + waitsFor(function() { return itFileEntry.wasCalled; }, "itFileEntry never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itFileEntry).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.42 createWriter should return a FileWriter object", function() { + var fileName = "fe.createWriter", + itFile, + entryCallback = jasmine.createSpy().andCallFake(function(fileEntry) { + itFile = fileEntry; + + runs(function() { + fileEntry.createWriter(itWriter, fail); + }); + + waitsFor(function() { return itWriter.wasCalled; }, "itWriter", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itWriter).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + itWriter = jasmine.createSpy().andCallFake(function(writer) { + expect(writer).toBeDefined(); + expect(writer instanceof FileWriter).toBe(true); + + // cleanup + itFile.remove(null, fail); + }), + fail = createFail('FileEntry'); + + // create a new file entry to kick off it + runs(function() { + root.getFile(fileName, {create:true}, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.43 file should return a File object", function() { + var fileName = "fe.file", + newFile, + entryCallback = jasmine.createSpy().andCallFake(function(fileEntry) { + newFile = fileEntry; + + runs(function() { + fileEntry.file(itFile, fail); + }); + + waitsFor(function() { return itFile.wasCalled; }, "itFile never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itFile).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + itFile = jasmine.createSpy().andCallFake(function(file) { + expect(file).toBeDefined(); + expect(file instanceof File).toBe(true); + + // cleanup + newFile.remove(null, fail); + }), + fail = createFail('FileEntry'); + + // create a new file entry to kick off it + runs(function() { + root.getFile(fileName, {create:true}, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.44 file: on File that has been removed", function() { + var fileName = "fe.no.file", + entryCallback = jasmine.createSpy().andCallFake(function(fileEntry) { + // create File object + var getFile = jasmine.createSpy().andCallFake(function() { + runs(function() { + fileEntry.file(win, itFile); + }); + + waitsFor(function() { return itFile.wasCalled; }, "itFile never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itFile).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + }); + // delete file + runs(function() { + fileEntry.remove(getFile, fail); + }); + + waitsFor(function() { return getFile.wasCalled; }, "getFile never called", Tests.TEST_TIMEOUT); + }), + itFile = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + }), + fail = createFail('FileEntry'), + win = createWin('FileEntry'); + + // create a new file entry to kick off it + runs(function() { + root.getFile(fileName, {create:true}, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + }); + describe('Entry', function() { + it("file.spec.45 Entry object", function() { + var fileName = "entry", + fullPath = root.fullPath + '/' + fileName, + fail = createFail('Entry'), + itEntry = jasmine.createSpy().andCallFake(function(entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(fileName); + expect(entry.fullPath).toCanonicallyMatch(fullPath); + expect(typeof entry.getMetadata).toBe('function'); + expect(typeof entry.setMetadata).toBe('function'); + expect(typeof entry.moveTo).toBe('function'); + expect(typeof entry.copyTo).toBe('function'); + expect(typeof entry.toURL).toBe('function'); + expect(typeof entry.remove).toBe('function'); + expect(typeof entry.getParent).toBe('function'); + expect(typeof entry.createWriter).toBe('function'); + expect(typeof entry.file).toBe('function'); + + // cleanup + deleteEntry(fileName); + }); + + // create a new file entry + runs(function() { + createFile(fileName, itEntry, fail); + }); + + waitsFor(function() { return itEntry.wasCalled; }, "itEntry", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itEntry).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.46 Entry.getMetadata on file", function() { + var fileName = "entry.metadata.file", + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + runs(function() { + entry.getMetadata(itMetadata, fail); + }); + + waitsFor(function() { return itMetadata.wasCalled; }, "itMetadata never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itMetadata).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + fail = createFail('Entry'), + itMetadata = jasmine.createSpy().andCallFake(function(metadata) { + expect(metadata).toBeDefined(); + expect(metadata.modificationTime instanceof Date).toBe(true); + + // cleanup + deleteEntry(fileName); + }); + + // create a new file entry + createFile(fileName, entryCallback, fail); + }); + it("file.spec.47 Entry.getMetadata on directory", function() { + var dirName = "entry.metadata.dir", + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + runs(function() { + entry.getMetadata(itMetadata, fail); + }); + + waitsFor(function() { return itMetadata.wasCalled; }, "itMetadata never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itMetadata).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + fail = createFail('Entry'), + itMetadata = jasmine.createSpy().andCallFake(function(metadata) { + expect(metadata).toBeDefined(); + expect(metadata.modificationTime instanceof Date).toBe(true); + + // cleanup + deleteEntry(dirName); + }); + + // create a new directory entry + runs(function() { + createDirectory(dirName, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.48 Entry.getParent on file in root file system", function() { + var fileName = "entry.parent.file", + rootPath = root.fullPath, + fail = createFail('Entry'), + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + runs(function() { + entry.getParent(itParent, fail); + }); + + waitsFor(function() { return itParent.wasCalled; }, "itCalled never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itParent).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + itParent = jasmine.createSpy().andCallFake(function(parent) { + expect(parent).toBeDefined(); + expect(parent.fullPath).toCanonicallyMatch(rootPath); + + // cleanup + deleteEntry(fileName); + }); + + // create a new file entry + runs(function() { + createFile(fileName, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.49 Entry.getParent on directory in root file system", function() { + var dirName = "entry.parent.dir", + rootPath = root.fullPath, + fail = createFail('Entry'), + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + runs(function() { + entry.getParent(itParent, fail); + }); + + waitsFor(function() { return itParent.wasCalled; }, "itParent never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itParent).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + itParent = jasmine.createSpy().andCallFake(function(parent) { + expect(parent).toBeDefined(); + expect(parent.fullPath).toCanonicallyMatch(rootPath); + + // cleanup + deleteEntry(dirName); + }); + + // create a new directory entry + runs(function() { + createDirectory(dirName, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.50 Entry.getParent on root file system", function() { + var rootPath = root.fullPath, + itParent = jasmine.createSpy().andCallFake(function(parent) { + expect(parent).toBeDefined(); + expect(parent.fullPath).toCanonicallyMatch(rootPath); + }), + fail = createFail('Entry'); + + // create a new directory entry + runs(function() { + root.getParent(itParent, fail); + }); + + waitsFor(function() { return itParent.wasCalled; }, "itParent never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itParent).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.51 Entry.toURL on file", function() { + var fileName = "entry.uri.file", + rootPath = root.fullPath, + itURI = jasmine.createSpy().andCallFake(function(entry) { + var uri = entry.toURL(); + expect(uri).toBeDefined(); + expect(uri.indexOf(rootPath)).not.toBe(-1); + + // cleanup + deleteEntry(fileName); + }), + fail = createFail('Entry'); + + // create a new file entry + runs(function() { + createFile(fileName, itURI, fail); + }); + + waitsFor(function() { return itURI.wasCalled; }, "itURI never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itURI).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.52 Entry.toURL on directory", function() { + var dirName = "entry.uri.dir", + rootPath = root.fullPath, + itURI = jasmine.createSpy().andCallFake(function(entry) { + var uri = entry.toURL(); + expect(uri).toBeDefined(); + expect(uri.indexOf(rootPath)).not.toBe(-1); + + // cleanup + deleteEntry(dirName); + }), + fail = createFail('Entry'); + + // create a new directory entry + runs(function() { + createDirectory(dirName, itURI, fail); + }); + + waitsFor(function() { return itURI.wasCalled; }, "itURI never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itURI).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.53 Entry.remove on file", function() { + var fileName = "entry.rm.file", + fullPath = root.fullPath + '/' + fileName, + win = createWin('Entry'), + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + var checkRemove = jasmine.createSpy().andCallFake(function() { + runs(function() { + root.getFile(fileName, null, win, itRemove); + }); + + waitsFor(function() { return itRemove.wasCalled; }, "itRemove never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + expect(itRemove).toHaveBeenCalled(); + }); + }); + expect(entry).toBeDefined(); + + runs(function() { + entry.remove(checkRemove, fail); + }); + + waitsFor(function() { return checkRemove.wasCalled; }, "checkRemove never called", Tests.TEST_TIMEOUT); + }), + itRemove = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + // cleanup + deleteEntry(fileName); + }), + fail = createFail('Entry'); + + // create a new file entry + runs(function() { + createFile(fileName, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.54 remove on empty directory", function() { + var dirName = "entry.rm.dir", + fullPath = root.fullPath + '/' + dirName, + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + var checkRemove = jasmine.createSpy().andCallFake(function() { + runs(function() { + root.getDirectory(dirName, null, win, itRemove); + }); + + waitsFor(function() { return itRemove.wasCalled; }, "itRemove never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itRemove).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + + expect(entry).toBeDefined(); + + runs(function() { + entry.remove(checkRemove, fail); + }); + + waitsFor(function() { return checkRemove.wasCalled; }, "checkRemove never called", Tests.TEST_TIMEOUT); + }), + itRemove = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + // cleanup + deleteEntry(dirName); + }), + win = createWin('Entry'), + fail = createFail('Entry'); + + // create a new directory entry + runs(function() { + createDirectory(dirName, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.55 remove on non-empty directory", function() { + var dirName = "entry.rm.dir.not.empty", + fullPath = root.fullPath + '/' + dirName, + fileName = "remove.txt", + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + var checkFile = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + // verify that dir still exists + runs(function() { + root.getDirectory(dirName, null, itRemove, fail); + }); + + waitsFor(function() { return itRemove.wasCalled; }, "itRemove never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + expect(itRemove).toHaveBeenCalled(); + }); + }); + // delete directory + var deleteDirectory = jasmine.createSpy().andCallFake(function(fileEntry) { + runs(function() { + entry.remove(win, checkFile); + }); + + waitsFor(function() { return checkFile.wasCalled; }, "checkFile never called", Tests.TEST_TIMEOUT); + }); + // create a file within directory, then try to delete directory + runs(function() { + entry.getFile(fileName, {create: true}, deleteDirectory, fail); + }); + + waitsFor(function() { return deleteDirectory.wasCalled; }, "deleteDirectory never called", Tests.TEST_TIMEOUT); + }), + itRemove = jasmine.createSpy().andCallFake(function(entry) { + expect(entry).toBeDefined(); + expect(entry.fullPath).toCanonicallyMatch(fullPath); + // cleanup + deleteEntry(dirName); + }), + win = createWin('Entry'), + fail = createFail('Entry'); + + // create a new directory entry + runs(function() { + createDirectory(dirName, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.56 remove on root file system", function() { + var itRemove = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NO_MODIFICATION_ALLOWED_ERR); + }), + win = createWin('Entry'); + + // remove entry that doesn't exist + runs(function() { + root.remove(win, itRemove); + }); + + waitsFor(function() { return itRemove.wasCalled; }, "itRemove never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).not.toHaveBeenCalled(); + expect(itRemove).toHaveBeenCalled(); + }); + }); + it("file.spec.57 copyTo: file", function() { + var file1 = "entry.copy.file1", + file2 = "entry.copy.file2", + fullPath = root.fullPath + '/' + file2, + fail = createFail('Entry'), + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + // copy file1 to file2 + runs(function() { + entry.copyTo(root, file2, itCopy, fail); + }); + + waitsFor(function() { return itCopy.wasCalled; }, "itCopy never called", Tests.TEST_TIMEOUT); + }), + itCopy = jasmine.createSpy().andCallFake(function(entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.fullPath).toCanonicallyMatch(fullPath); + expect(entry.name).toCanonicallyMatch(file2); + + runs(function() { + root.getFile(file2, {create:false}, itFileExists, fail); + }); + + waitsFor(function() { return itFileExists.wasCalled; }, "itFileExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).not.toHaveBeenCalled(); + expect(itFileExists).toHaveBeenCalled(); + }); + }), + itFileExists = jasmine.createSpy().andCallFake(function(entry2) { + // a bit redundant since copy returned this entry already + expect(entry2).toBeDefined(); + expect(entry2.isFile).toBe(true); + expect(entry2.isDirectory).toBe(false); + expect(entry2.fullPath).toCanonicallyMatch(fullPath); + expect(entry2.name).toCanonicallyMatch(file2); + + // cleanup + deleteEntry(file1); + deleteEntry(file2); + }); + + // create a new file entry to kick off it + runs(function() { + createFile(file1, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.58 copyTo: file onto itself", function() { + var file1 = "entry.copy.fos.file1", + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + // copy file1 onto itself + runs(function() { + entry.copyTo(root, null, win, itCopy); + }); + + waitsFor(function() { return itCopy.wasCalled; }, "itCopy never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itCopy).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + }); + }), + fail = createFail('Entry'), + win = createWin('Entry'), + itCopy = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + + // cleanup + deleteEntry(file1); + }); + + // create a new file entry to kick off it + runs(function() { + createFile(file1, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.59 copyTo: directory", function() { + var file1 = "file1", + srcDir = "entry.copy.srcDir", + dstDir = "entry.copy.dstDir", + dstPath = root.fullPath + '/' + dstDir, + filePath = dstPath + '/' + file1, + entryCallback = jasmine.createSpy().andCallFake(function(directory) { + var copyDir = jasmine.createSpy().andCallFake(function(fileEntry) { + // copy srcDir to dstDir + runs(function() { + directory.copyTo(root, dstDir, itCopy, fail); + }); + + waitsFor(function() { return itCopy.wasCalled; }, "itCopy never called", Tests.TEST_TIMEOUT); + }); + + // create a file within new directory + runs(function() { + directory.getFile(file1, {create: true}, copyDir, fail); + }); + + waitsFor(function() { return copyDir.wasCalled; }, "copyDir never called", Tests.TEST_TIMEOUT); + }), + itCopy = jasmine.createSpy().andCallFake(function(directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.fullPath).toCanonicallyMatch(dstPath); + expect(directory.name).toCanonicallyMatch(dstDir); + + runs(function() { + root.getDirectory(dstDir, {create:false}, itDirExists, fail); + }); + + waitsFor(function() { return itDirExists.wasCalled; }, "itDirExists never called", Tests.TEST_TIMEOUT); + }), + itDirExists = jasmine.createSpy().andCallFake(function(dirEntry) { + expect(dirEntry).toBeDefined(); + expect(dirEntry.isFile).toBe(false); + expect(dirEntry.isDirectory).toBe(true); + expect(dirEntry.fullPath).toCanonicallyMatch(dstPath); + expect(dirEntry.name).toCanonicallyMatch(dstDir); + + runs(function() { + dirEntry.getFile(file1, {create:false}, itFileExists, fail); + }); + + waitsFor(function() { return itFileExists.wasCalled; }, "itFileExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itFileExists).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + itFileExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.isFile).toBe(true); + expect(fileEntry.isDirectory).toBe(false); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + expect(fileEntry.name).toCanonicallyMatch(file1); + + // cleanup + deleteEntry(srcDir); + deleteEntry(dstDir); + }), + fail = createFail('Entry'); + + // create a new directory entry to kick off it + runs(function() { + createDirectory(srcDir, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.60 copyTo: directory to backup at same root directory", function() { + var file1 = "file1", + srcDir = "entry.copy.srcDirSame", + dstDir = "entry.copy.srcDirSame-backup", + dstPath = root.fullPath + '/' + dstDir, + filePath = dstPath + '/' + file1, + fail = createFail('Entry copyTo: directory to backup at same root'), + entryCallback = function(directory) { + var copyDir = function(fileEntry) { + // copy srcDir to dstDir + directory.copyTo(root, dstDir, itCopy, fail); + }; + // create a file within new directory + directory.getFile(file1, {create: true}, copyDir, fail); + }, + itCopy = function(directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.fullPath).toCanonicallyMatch(dstPath); + expect(directory.name).toCanonicallyMatch(dstDir); + + root.getDirectory(dstDir, {create:false}, itDirExists, fail); + }, + itDirExists = function(dirEntry) { + expect(dirEntry).toBeDefined(); + expect(dirEntry.isFile).toBe(false); + expect(dirEntry.isDirectory).toBe(true); + expect(dirEntry.fullPath).toCanonicallyMatch(dstPath); + expect(dirEntry.name).toCanonicallyMatch(dstDir); + + dirEntry.getFile(file1, {create:false}, itFileExists, fail); + }, + itFileExists = jasmine.createSpy().andCallFake(function(fileEntry) { + var cleanSrc = jasmine.createSpy(); + var cleanDst = jasmine.createSpy(); + runs(function() { + expect(fileEntry).toBeDefined(); + expect(fileEntry.isFile).toBe(true); + expect(fileEntry.isDirectory).toBe(false); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + expect(fileEntry.name).toCanonicallyMatch(file1); + expect(fail).not.toHaveBeenCalled(); + + // cleanup + deleteEntry(srcDir, cleanSrc); + deleteEntry(dstDir, cleanDst); + }); + + waitsFor(function() { return cleanSrc.wasCalled && cleanDst.wasCalled; }, "cleanSrc and cleanDst cleanup methods", Tests.TEST_TIMEOUT); + }); + + // create a new directory entry to kick off it + runs(function() { + createDirectory(srcDir, entryCallback, fail); + }); + + waitsFor(function() { return itFileExists.wasCalled; }, "itFileExists", 10000); + }); + it("file.spec.61 copyTo: directory onto itself", function() { + var file1 = "file1", + srcDir = "entry.copy.dos.srcDir", + srcPath = root.fullPath + '/' + srcDir, + filePath = srcPath + '/' + file1, + win = createWin('Entry'), + fail = createFail('Entry copyTo: directory onto itself'), + entryCallback = jasmine.createSpy().andCallFake(function(directory) { + var copyDir = jasmine.createSpy().andCallFake(function(fileEntry) { + // copy srcDir onto itself + runs(function() { + directory.copyTo(root, null, win, itCopy); + }); + + waitsFor(function() { return itCopy.wasCalled; }, "itCopy never called", Tests.TEST_TIMEOUT); + }); + // create a file within new directory + runs(function() { + directory.getFile(file1, {create: true}, copyDir, fail); + }); + + waitsFor(function() { return copyDir.wasCalled; }, "copyDir never called", Tests.TEST_TIMEOUT); + }), + itCopy = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + + runs(function() { + root.getDirectory(srcDir, {create:false}, itDirectoryExists, fail); + }); + + waitsFor(function() { return itDirectoryExists.wasCalled; }, "itDirectoryExists", Tests.TEST_TIMEOUT); + }), + itDirectoryExists = jasmine.createSpy().andCallFake(function(dirEntry) { + // returning confirms existence so just check fullPath entry + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(srcPath); + + runs(function() { + dirEntry.getFile(file1, {create:false}, itFileExists, fail); + }); + + waitsFor(function() { return itFileExists.wasCalled; }, "itFileExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + expect(itFileExists).toHaveBeenCalled(); + }); + }), + itFileExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + + // cleanup + deleteEntry(srcDir); + }); + + // create a new directory entry to kick off it + runs(function() { + createDirectory(srcDir, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.62 copyTo: directory into itself", function() { + var srcDir = "entry.copy.dis.srcDir", + dstDir = "entry.copy.dis.dstDir", + fail = createFail('Entry'), + win = createWin('Entry'), + srcPath = root.fullPath + '/' + srcDir, + entryCallback = jasmine.createSpy().andCallFake(function(directory) { + // copy source directory into itself + runs(function() { + directory.copyTo(directory, dstDir, win, itCopy); + }); + + waitsFor(function() { return itCopy.wasCalled; }, "itCopy", Tests.TEST_TIMEOUT); + }), + itCopy = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + + runs(function() { + root.getDirectory(srcDir, {create:false}, itDirectoryExists, fail); + }); + + waitsFor(function() { return itDirectoryExists.wasCalled; }, "itDirectoryExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itDirectoryExists).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + itDirectoryExists = jasmine.createSpy().andCallFake(function(dirEntry) { + // returning confirms existence so just check fullPath entry + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(srcPath); + + // cleanup + deleteEntry(srcDir); + }); + + // create a new directory entry to kick off it + runs(function() { + createDirectory(srcDir, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.63 copyTo: directory that does not exist", function() { + var file1 = "entry.copy.dnf.file1", + dstDir = "entry.copy.dnf.dstDir", + filePath = root.fullPath + '/' + file1, + dstPath = root.fullPath + '/' + dstDir, + win = createWin('Entry'), + fail = createFail('Entry'), + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + // copy file to target directory that does not exist + runs(function() { + directory = new DirectoryEntry(); + directory.fullPath = dstPath; + entry.copyTo(directory, null, win, itCopy); + }); + + waitsFor(function() { return itCopy.wasCalled; }, "itCopy never called", Tests.TEST_TIMEOUT); + }), + itCopy = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + runs(function() { + root.getFile(file1, {create: false}, itFileExists, fail); + }); + + waitsFor(function() { return itFileExists.wasCalled; }, "itFileExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itFileExists).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + itFileExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + + // cleanup + deleteEntry(file1); + }); + + // create a new file entry to kick off it + runs(function() { + createFile(file1, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.64 copyTo: invalid target name", function() { + var file1 = "entry.copy.itn.file1", + file2 = "bad:file:name", + filePath = root.fullPath + '/' + file1, + fail = createFail('Entry'), + win = createWin('Entry'), + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + // copy file1 to file2 + runs(function() { + entry.copyTo(root, file2, win, itCopy); + }); + + waitsFor(function() { return itCopy.wasCalled; }, "itCopy never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).not.toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(itCopy).toHaveBeenCalled(); + }); + }), + itCopy = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.ENCODING_ERR); + + // cleanup + deleteEntry(file1); + }); + + // create a new file entry + runs(function() { + createFile(file1, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.65 moveTo: file to same parent", function() { + var file1 = "entry.move.fsp.file1", + file2 = "entry.move.fsp.file2", + srcPath = root.fullPath + '/' + file1, + dstPath = root.fullPath + '/' + file2, + fail = createFail('Entry'), + win = createWin('Entry'), + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + // move file1 to file2 + runs(function() { + entry.moveTo(root, file2, itMove, fail); + }); + + waitsFor(function() { return itMove.wasCalled; }, "itMove never called", Tests.TEST_TIMEOUT); + }), + itMove = jasmine.createSpy().andCallFake(function(entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.fullPath).toCanonicallyMatch(dstPath); + expect(entry.name).toCanonicallyMatch(file2); + + runs(function() { + root.getFile(file2, {create:false}, itMovedExists, fail); + }); + + waitsFor(function() { return itMovedExists.wasCalled; }, "itMovedExists never called", Tests.TEST_TIMEOUT); + }), + itMovedExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(dstPath); + + runs(function() { + root.getFile(file1, {create:false}, win, itOrig); + }); + + waitsFor(function() { return itOrig.wasCalled; }, "itOrig never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + expect(itOrig).toHaveBeenCalled(); + }); + }), + itOrig = jasmine.createSpy().andCallFake(function(error) { + //expect(navigator.fileMgr.itFileExists(srcPath) === false, "original file should not exist."); + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + + // cleanup + deleteEntry(file1); + deleteEntry(file2); + }); + + // create a new file entry to kick off it + runs(function() { + createFile(file1, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.66 moveTo: file to new parent", function() { + var file1 = "entry.move.fnp.file1", + dir = "entry.move.fnp.dir", + srcPath = root.fullPath + '/' + file1, + win = createWin('Entry'), + fail = createFail('Entry'), + dstPath = root.fullPath + '/' + dir + '/' + file1, + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + // move file1 to new directory + var moveFile = jasmine.createSpy().andCallFake(function(directory) { + var itMove = jasmine.createSpy().andCallFake(function(entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.fullPath).toCanonicallyMatch(dstPath); + expect(entry.name).toCanonicallyMatch(file1); + // it the moved file exists + runs(function() { + directory.getFile(file1, {create:false}, itMovedExists, fail); + }); + + waitsFor(function() { return itMovedExists.wasCalled; }, "itMovedExists never called", Tests.TEST_TIMEOUT); + }); + // move the file + runs(function() { + entry.moveTo(directory, null, itMove, fail); + }); + + waitsFor(function() { return itMove.wasCalled; }, "itMove never called", Tests.TEST_TIMEOUT); + }); + + // create a parent directory to move file to + runs(function() { + root.getDirectory(dir, {create: true}, moveFile, fail); + }); + + waitsFor(function() { return moveFile.wasCalled; }, "moveFile never called", Tests.TEST_TIMEOUT); + }), + itMovedExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(dstPath); + + runs(function() { + root.getFile(file1, {create:false}, win, itOrig); + }); + + waitsFor(function() { return itOrig.wasCalled; }, "itOrig never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + expect(itOrig).toHaveBeenCalled(); + }); + }), + itOrig = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + + // cleanup + deleteEntry(file1); + deleteEntry(dir); + }); + + // ensure destination directory is cleaned up first + runs(function() { + deleteEntry(dir, function() { + // create a new file entry to kick off it + createFile(file1, entryCallback, fail); + }, fail); + }); + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.67 moveTo: directory to same parent", function() { + var file1 = "file1", + srcDir = "entry.move.dsp.srcDir", + dstDir = "entry.move.dsp.dstDir", + srcPath = root.fullPath + '/' + srcDir, + dstPath = root.fullPath + '/' + dstDir, + filePath = dstPath + '/' + file1, + win = createWin('Entry'), + fail = createFail('Entry'), + entryCallback = jasmine.createSpy().andCallFake(function(directory) { + var moveDir = jasmine.createSpy().andCallFake(function(fileEntry) { + // move srcDir to dstDir + runs(function() { + directory.moveTo(root, dstDir, itMove, fail); + }); + + waitsFor(function() { return itMove.wasCalled; }, "itMove never called", Tests.TEST_TIMEOUT); + }); + // create a file within directory + runs(function() { + directory.getFile(file1, {create: true}, moveDir, fail); + }); + + waitsFor(function() { return moveDir.wasCalled; }, "moveDir never called", Tests.TEST_TIMEOUT); + }), + itMove = jasmine.createSpy().andCallFake(function(directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.fullPath).toCanonicallyMatch(dstPath); + expect(directory.name).toCanonicallyMatch(dstDir); + // it that moved file exists in destination dir + + runs(function() { + directory.getFile(file1, {create:false}, itMovedExists, fail); + }); + + waitsFor(function() { return itMovedExists.wasCalled; }, "itMovedExists never called", Tests.TEST_TIMEOUT); + }), + itMovedExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + + // check that the moved file no longer exists in original dir + runs(function() { + root.getFile(file1, {create:false}, win, itOrig); + }); + + waitsFor(function() { return itOrig.wasCalled; }, "itOrig never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + expect(itOrig).toHaveBeenCalled(); + }); + }), + itOrig = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + + // cleanup + deleteEntry(srcDir); + deleteEntry(dstDir); + }); + + // ensure destination directory is cleaned up before it + runs(function() { + deleteEntry(dstDir, function() { + // create a new directory entry to kick off it + createDirectory(srcDir, entryCallback, fail); + }, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.68 moveTo: directory to same parent with same name", function() { + var file1 = "file1", + srcDir = "entry.move.dsp.srcDir", + dstDir = "entry.move.dsp.srcDir-backup", + srcPath = root.fullPath + '/' + srcDir, + dstPath = root.fullPath + '/' + dstDir, + filePath = dstPath + '/' + file1, + win = createWin('Entry'), + fail = createFail('Entry'), + entryCallback = jasmine.createSpy().andCallFake(function(directory) { + var moveDir = jasmine.createSpy().andCallFake(function(fileEntry) { + // move srcDir to dstDir + runs(function() { + directory.moveTo(root, dstDir, itMove, fail); + }); + + waitsFor(function() { return itMove.wasCalled; }, "itMove never called", Tests.TEST_TIMEOUT); + }); + // create a file within directory + runs(function() { + directory.getFile(file1, {create: true}, moveDir, fail); + }); + + waitsFor(function() { return moveDir.wasCalled; }, "moveDir never called", Tests.TEST_TIMEOUT); + }), + itMove = jasmine.createSpy().andCallFake(function(directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.fullPath).toCanonicallyMatch(dstPath); + expect(directory.name).toCanonicallyMatch(dstDir); + // check that moved file exists in destination dir + runs(function() { + directory.getFile(file1, {create:false}, itMovedExists, null); + }); + + waitsFor(function() { return itMovedExists.wasCalled; }, "itMovedExists never called", Tests.TEST_TIMEOUT); + }), + itMovedExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + // check that the moved file no longer exists in original dir + runs(function() { + root.getFile(file1, {create:false}, win, itOrig); + }); + + waitsFor(function() { return itOrig.wasCalled; }, "itOrig never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + expect(itOrig).toHaveBeenCalled(); + }); + }), + itOrig = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + + // cleanup + deleteEntry(srcDir); + deleteEntry(dstDir); + }); + + // ensure destination directory is cleaned up before it + runs(function() { + deleteEntry(dstDir, function() { + // create a new directory entry to kick off it + createDirectory(srcDir, entryCallback, fail); + }, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.69 moveTo: directory to new parent", function() { + var file1 = "file1", + srcDir = "entry.move.dnp.srcDir", + dstDir = "entry.move.dnp.dstDir", + srcPath = root.fullPath + '/' + srcDir, + dstPath = root.fullPath + '/' + dstDir, + filePath = dstPath + '/' + file1, + win = createWin('Entry'), + fail = createFail('Entry'), + entryCallback = jasmine.createSpy().andCallFake(function(directory) { + var moveDir = jasmine.createSpy().andCallFake(function(fileEntry) { + // move srcDir to dstDir + runs(function() { + directory.moveTo(root, dstDir, itMove, fail); + }); + + waitsFor(function() { return itMove.wasCalled; }, "itMove never called", Tests.TEST_TIMEOUT); + }); + // create a file within directory + runs(function() { + directory.getFile(file1, {create: true}, moveDir, fail); + }); + + waitsFor(function() { return moveDir.wasCalled; }, "moveDir never called", Tests.TEST_TIMEOUT); + }), + itMove = jasmine.createSpy().andCallFake(function(directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.fullPath).toCanonicallyMatch(dstPath); + expect(directory.name).toCanonicallyMatch(dstDir); + // it that moved file exists in destination dir + runs(function() { + directory.getFile(file1, {create:false}, itMovedExists, fail); + }); + + waitsFor(function() { return itMovedExists.wasCalled; }, "itMovedExists never called", Tests.TEST_TIMEOUT); + }), + itMovedExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + // it that the moved file no longer exists in original dir + runs(function() { + root.getFile(file1, {create:false}, win, itOrig); + }); + + waitsFor(function() { return itOrig.wasCalled; }, "itOrig never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + expect(itOrig).toHaveBeenCalled(); + }); + }), + itOrig = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + + // cleanup + deleteEntry(srcDir); + deleteEntry(dstDir); + }); + + // ensure destination directory is cleaned up before it + runs(function() { + deleteEntry(dstDir, function() { + // create a new directory entry to kick off it + createDirectory(srcDir, entryCallback, fail); + }, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.70 moveTo: directory onto itself", function() { + var file1 = "file1", + srcDir = "entry.move.dos.srcDir", + srcPath = root.fullPath + '/' + srcDir, + filePath = srcPath + '/' + file1, + fail = createFail('Entry'), + win = createWin('Entry'), + entryCallback = jasmine.createSpy().andCallFake(function(directory) { + var moveDir = jasmine.createSpy().andCallFake(function(fileEntry) { + // move srcDir onto itself + runs(function() { + directory.moveTo(root, null, win, itMove); + }); + + waitsFor(function() { return itMove.wasCalled; }, "itMove never called", Tests.TEST_TIMEOUT); + }); + // create a file within new directory + runs(function() { + directory.getFile(file1, {create: true}, moveDir, fail); + }); + + waitsFor(function() { return moveDir.wasCalled; }, "moveDir never called", Tests.TEST_TIMEOUT); + }), + itMove = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + + // it that original dir still exists + runs(function() { + root.getDirectory(srcDir, {create:false}, itDirectoryExists, fail); + }); + + waitsFor(function() { return itDirectoryExists.wasCalled; }, "itDirectoryExists", Tests.TEST_TIMEOUT); + }), + itDirectoryExists = jasmine.createSpy().andCallFake(function(dirEntry) { + // returning confirms existence so just check fullPath entry + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(srcPath); + + runs(function() { + dirEntry.getFile(file1, {create:false}, itFileExists, fail); + }); + + waitsFor(function() { return itFileExists.wasCalled; }, "itFileExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itFileExists).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + itFileExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + + // cleanup + deleteEntry(srcDir); + }); + + // create a new directory entry to kick off it + runs(function() { + createDirectory(srcDir, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.71 moveTo: directory into itself", function() { + var srcDir = "entry.move.dis.srcDir", + dstDir = "entry.move.dis.dstDir", + srcPath = root.fullPath + '/' + srcDir, + win = createWin('Entry'), + fail = createFail('Entry'), + entryCallback = jasmine.createSpy().andCallFake(function(directory) { + // move source directory into itself + runs(function() { + directory.moveTo(directory, dstDir, win, itMove); + }); + + waitsFor(function() { return itMove.wasCalled; }, "itMove never called", Tests.TEST_TIMEOUT); + }), + itMove = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + // make sure original directory still exists + runs(function() { + root.getDirectory(srcDir, {create:false}, itDirectoryExists, fail); + }); + + waitsFor(function() { return itDirectoryExists.wasCalled; }, "itDirectoryExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).not.toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(itDirectoryExists).toHaveBeenCalled(); + }); + }), + itDirectoryExists = jasmine.createSpy().andCallFake(function(entry) { + expect(entry).toBeDefined(); + expect(entry.fullPath).toCanonicallyMatch(srcPath); + + // cleanup + deleteEntry(srcDir); + }); + + // create a new directory entry to kick off it + runs(function() { + createDirectory(srcDir, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.72 moveTo: file onto itself", function() { + var file1 = "entry.move.fos.file1", + filePath = root.fullPath + '/' + file1, + win = createWin('Entry'), + fail = createFail('Entry'), + entryCallback = jasmine.createSpy().andCallFake(function(entry) { + // move file1 onto itself + runs(function() { + entry.moveTo(root, null, win, itMove); + }); + + waitsFor(function() { return itMove.wasCalled; }, "itMove never called", Tests.TEST_TIMEOUT); + }), + itMove = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + + //it that original file still exists + runs(function() { + root.getFile(file1, {create:false}, itFileExists, fail); + }); + + waitsFor(function() { return itFileExists.wasCalled; }, "itFileExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itFileExists).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }), + itFileExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + + // cleanup + deleteEntry(file1); + }); + + // create a new file entry to kick off it + runs(function() { + createFile(file1, entryCallback, fail); + }); + + waitsFor(function() { return entryCallback.wasCalled; }, "entryCallback never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.73 moveTo: file onto existing directory", function() { + var file1 = "entry.move.fod.file1", + dstDir = "entry.move.fod.dstDir", + subDir = "subDir", + dirPath = root.fullPath + '/' + dstDir + '/' + subDir, + filePath = root.fullPath + '/' + file1, + win = createWin('Entry'), + fail = createFail('Entry'), + entryCallback = function(entry) { + var createSubDirectory = function(directory) { + var moveFile = function(subDirectory) { + var itMove = function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + // check that original dir still exists + directory.getDirectory(subDir, {create:false}, itDirectoryExists, fail); + }; + // move file1 onto sub-directory + entry.moveTo(directory, subDir, win, itMove); + }; + // create sub-directory + directory.getDirectory(subDir, {create: true}, moveFile, fail); + }; + // create top level directory + root.getDirectory(dstDir, {create: true}, createSubDirectory, fail); + }, + itDirectoryExists = function(dirEntry) { + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(dirPath); + // check that original file still exists + root.getFile(file1, {create:false},itFileExists, fail); + }, + itFileExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + + // cleanup + deleteEntry(file1); + deleteEntry(dstDir); + }); + + // ensure destination directory is cleaned up before it + runs(function() { + deleteEntry(dstDir, function() { + // create a new file entry to kick off it + createFile(file1, entryCallback, fail); + }, fail); + }); + + waitsFor(function() { return itFileExists.wasCalled; }, "itFileExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itFileExists).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.74 moveTo: directory onto existing file", function() { + var file1 = "entry.move.dof.file1", + srcDir = "entry.move.dof.srcDir", + dirPath = root.fullPath + '/' + srcDir, + filePath = root.fullPath + '/' + file1, + win = createWin('Entry'), + fail = createFail('Entry'), + entryCallback = function(entry) { + var moveDir = function(fileEntry) { + // move directory onto file + entry.moveTo(root, file1, win, itMove); + }; + // create file + root.getFile(file1, {create: true}, moveDir, fail); + }, + itMove = function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + // it that original directory exists + root.getDirectory(srcDir, {create:false}, itDirectoryExists, fail); + }, + itDirectoryExists = function(dirEntry) { + // returning confirms existence so just check fullPath entry + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(dirPath); + // it that original file exists + root.getFile(file1, {create:false}, itFileExists, fail); + }, + itFileExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + + // cleanup + deleteEntry(file1); + deleteEntry(srcDir); + }); + + // create a new directory entry to kick off it + runs(function() { + createDirectory(srcDir, entryCallback, fail); + }); + + waitsFor(function() { return itFileExists.wasCalled; }, "itFileExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itFileExists).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.75 copyTo: directory onto existing file", function() { + var file1 = "entry.copy.dof.file1", + srcDir = "entry.copy.dof.srcDir", + dirPath = root.fullPath + '/' + srcDir, + filePath = root.fullPath + '/' + file1, + win = createWin('Entry'), + fail = createFail('Entry'), + entryCallback = function(entry) { + var copyDir = function(fileEntry) { + // move directory onto file + entry.copyTo(root, file1, win, itMove); + }; + // create file + root.getFile(file1, {create: true}, copyDir, fail); + }, + itMove = function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + //check that original dir still exists + root.getDirectory(srcDir, {create:false}, itDirectoryExists, fail); + }, + itDirectoryExists = function(dirEntry) { + // returning confirms existence so just check fullPath entry + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(dirPath); + // it that original file still exists + root.getFile(file1, {create:false}, itFileExists, fail); + }, + itFileExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + + // cleanup + deleteEntry(file1); + deleteEntry(srcDir); + }); + + // create a new directory entry to kick off it + runs(function() { + createDirectory(srcDir, entryCallback, fail); + }); + + waitsFor(function() { return itFileExists.wasCalled; }, "itFileExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itFileExists).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.76 moveTo: directory onto directory that is not empty", function() { + var srcDir = "entry.move.dod.srcDir", + dstDir = "entry.move.dod.dstDir", + subDir = "subDir", + srcPath = root.fullPath + '/' + srcDir, + dstPath = root.fullPath + '/' + dstDir + '/' + subDir, + win = createWin('Entry'), + fail = createFail('Entry'), + entryCallback = function(entry) { + var createSubDirectory = function(directory) { + var moveDir = function(subDirectory) { + // move srcDir onto dstDir (not empty) + entry.moveTo(root, dstDir, win, itMove); + }; + var itMove = function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + + // it that destination directory still exists + directory.getDirectory(subDir, {create:false}, itDirectoryExists, fail); + }; + // create sub-directory + directory.getDirectory(subDir, {create: true}, moveDir, fail); + }; + // create top level directory + root.getDirectory(dstDir, {create: true}, createSubDirectory, fail); + }, + itDirectoryExists = function(dirEntry) { + // returning confirms existence so just check fullPath entry + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(dstPath); + // it that source directory exists + root.getDirectory(srcDir,{create:false}, itSrcDirectoryExists, fail); + }, + itSrcDirectoryExists = jasmine.createSpy().andCallFake(function(srcEntry){ + expect(srcEntry).toBeDefined(); + expect(srcEntry.fullPath).toCanonicallyMatch(srcPath); + // cleanup + deleteEntry(srcDir); + deleteEntry(dstDir); + }); + + // ensure destination directory is cleaned up before it + runs(function() { + deleteEntry(dstDir, function() { + // create a new file entry to kick off it + createDirectory(srcDir, entryCallback, fail); + }, fail); + }); + + waitsFor(function() { return itSrcDirectoryExists.wasCalled; }, "itSrcDirectoryExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itSrcDirectoryExists).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.77 moveTo: file replace existing file", function() { + var file1 = "entry.move.frf.file1", + file2 = "entry.move.frf.file2", + file1Path = root.fullPath + '/' + file1, + file2Path = root.fullPath + '/' + file2, + win = createWin('Entry'), + fail = createFail('Entry'), + entryCallback = function(entry) { + var moveFile = function(fileEntry) { + // replace file2 with file1 + entry.moveTo(root, file2, itMove, fail); + }; + // create file + root.getFile(file2, {create: true}, moveFile,fail); + }, + itMove = function(entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.fullPath).toCanonicallyMatch(file2Path); + expect(entry.name).toCanonicallyMatch(file2); + + // it that old file does not exists + root.getFile(file1, {create:false}, win, itFileMoved); + }, + itFileMoved = function(error){ + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + // it that new file exists + root.getFile(file2, {create:false}, itFileExists, fail); + }, + itFileExists = jasmine.createSpy().andCallFake(function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(file2Path); + + // cleanup + deleteEntry(file1); + deleteEntry(file2); + }); + + // create a new directory entry to kick off it + runs(function() { + createFile(file1, entryCallback, fail); + }); + + waitsFor(function() { return itFileExists.wasCalled; }, "itFileExists never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itFileExists).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.78 moveTo: directory replace empty directory", function() { + var file1 = "file1", + srcDir = "entry.move.drd.srcDir", + dstDir = "entry.move.drd.dstDir", + srcPath = root.fullPath + '/' + srcDir, + dstPath = root.fullPath + '/' + dstDir, + win = createWin('Entry'), + fail = createFail('Entry'), + filePath = dstPath + '/' + file1, + entryCallback = function(directory) { + var mkdir = function(fileEntry) { + // create destination directory + root.getDirectory(dstDir, {create: true}, moveDir, fail); + }; + var moveDir = function(fileEntry) { + // move srcDir to dstDir + directory.moveTo(root, dstDir, itMove, fail); + }; + // create a file within source directory + directory.getFile(file1, {create: true}, mkdir, fail); + }, + itMove = function(directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.fullPath).toCanonicallyMatch(dstPath); + expect(directory.name).toCanonicallyMatch(dstDir); + // check that old directory contents have been moved + directory.getFile(file1, {create:false}, itFileExists, fail); + }, + itFileExists = function(fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + + // check that old directory no longer exists + root.getDirectory(srcDir, {create:false}, win, itRemoved); + }, + itRemoved = jasmine.createSpy().andCallFake(function(error){ + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + + // cleanup + deleteEntry(srcDir); + deleteEntry(dstDir); + }); + + // ensure destination directory is cleaned up before it + runs(function() { + deleteEntry(dstDir, function() { + // create a new directory entry to kick off it + createDirectory(srcDir, entryCallback, fail); + }, fail); + }); + + waitsFor(function() { return itRemoved.wasCalled; }, "itRemoved never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itRemoved).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.79 moveTo: directory that does not exist", function() { + var file1 = "entry.move.dnf.file1", + dstDir = "entry.move.dnf.dstDir", + filePath = root.fullPath + '/' + file1, + dstPath = root.fullPath + '/' + dstDir, + win = createWin('Entry'), + fail = createFail('Entry'), + entryCallback = function(entry) { + // move file to directory that does not exist + directory = new DirectoryEntry(); + directory.fullPath = dstPath; + entry.moveTo(directory, null, win, itMove); + }, + itMove = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); + + // cleanup + deleteEntry(file1); + }); + + // create a new file entry to kick off it + runs(function() { + createFile(file1, entryCallback, fail); + }); + + waitsFor(function() { return itMove.wasCalled; }, "itMove never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itMove).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.80 moveTo: invalid target name", function() { + var file1 = "entry.move.itn.file1", + file2 = "bad:file:name", + filePath = root.fullPath + '/' + file1, + win = createWin('Entry'), + fail = createFail('Entry'), + entryCallback = function(entry) { + // move file1 to file2 + entry.moveTo(root, file2, win, itMove); + }, + itMove = jasmine.createSpy().andCallFake(function(error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.ENCODING_ERR); + + // cleanup + deleteEntry(file1); + }); + + // create a new file entry to kick off it + runs(function() { + createFile(file1,entryCallback, fail); + }); + + waitsFor(function() { return itMove.wasCalled; }, "itMove never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(itMove).toHaveBeenCalled(); + expect(win).not.toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + }); + + describe('FileReader', function() { + it("file.spec.81 should have correct methods", function() { + var reader = new FileReader(); + expect(reader).toBeDefined(); + expect(typeof reader.readAsBinaryString).toBe('function'); + expect(typeof reader.readAsDataURL).toBe('function'); + expect(typeof reader.readAsText).toBe('function'); + expect(typeof reader.readAsArrayBuffer).toBe('function'); + expect(typeof reader.abort).toBe('function'); + }); + }); + + describe('read method', function(){ + it("file.spec.82 should error out on non-existent file", function() { + var reader = new FileReader(); + var verifier = jasmine.createSpy().andCallFake(function(evt) { + expect(evt).toBeDefined(); + expect(evt.target.error).toBeFileError(FileError.NOT_FOUND_ERR); + }); + reader.onerror = verifier; + var myFile = new File(); + myFile.fullPath = root.fullPath + '/' + "doesnotexist.err"; + + reader.readAsText(myFile); + + waitsFor(function() { return verifier.wasCalled; }, "verifier never called", Tests.TEST_TIMEOUT); + }); + it("file.spec.83 should be able to read native blob objects", function() { + // Skip test if blobs are not supported (e.g.: Android 2.3). + if (typeof window.Blob == 'undefined' || typeof window.Uint8Array == 'undefined') { + return; + } + var contents = 'asdf'; + var uint8Array = new Uint8Array(contents.length); + for (var i = 0; i < contents.length; ++i) { + uint8Array[i] = contents.charCodeAt(i); + } + var Builder = window.BlobBuilder || window.WebKitBlobBuilder; + var blob; + if (Builder) { + var builder = new Builder(); + builder.append(uint8Array.buffer); + builder.append(contents); + blob = builder.getBlob("text/plain"); + } else { + try { + // iOS 6 does not support Views, so pass in the buffer. + blob = new Blob([uint8Array.buffer, contents]); + } catch (e) { + // Skip the test if we can't create a blob (e.g.: iOS 5). + if (e instanceof TypeError) { + return; + } + throw e; + } + } + var verifier = jasmine.createSpy().andCallFake(function(evt) { + expect(evt).toBeDefined(); + expect(evt.target.result).toBe('asdfasdf'); + }); + var reader = new FileReader(); + reader.onloadend = verifier; + reader.readAsText(blob); + + waitsFor(function() { return verifier.wasCalled; }, "verifier never called", 300); + }); + + function writeDummyFile(writeBinary, callback) { + var fileName = "dummy.txt", + fileEntry = null, + writerFail = createFail('createWriter'), + getFileFail = createFail('getFile'), + fileFail = createFail('file'), + callback = jasmine.createSpy().andCallFake(callback), + fileData = '\u20AC\xEB - There is an exception to every rule. Except this one.', + fileDataAsBinaryString = '\xe2\x82\xac\xc3\xab - There is an exception to every rule. Except this one.', + createWriter = function(fe) { + fileEntry = fe; + fileEntry.createWriter(writeFile, writerFail); + }, + // writes file and reads it back in + writeFile = function(writer) { + writer.onwriteend = function() { + fileEntry.file(function(f) { + callback(fileEntry, f, fileData, fileDataAsBinaryString); + }, fileFail); + }; + writer.write(fileData); + }; + fileData += writeBinary ? 'bin:\x01\x00' : ''; + fileDataAsBinaryString += writeBinary ? 'bin:\x01\x00' : ''; + // create a file, write to it, and read it in again + root.getFile(fileName, {create: true}, createWriter, getFileFail); + waitsForAny(getFileFail, writerFail, fileFail, callback); + } + + function runReaderTest(funcName, writeBinary, verifierFunc, sliceStart, sliceEnd) { + writeDummyFile(writeBinary, function(fileEntry, file, fileData, fileDataAsBinaryString) { + var readWin = jasmine.createSpy().andCallFake(function(evt) { + expect(evt).toBeDefined(); + verifierFunc(evt, fileData, fileDataAsBinaryString); + }); + + var reader = new FileReader(); + var readFail = createFail(funcName); + reader.onload = readWin; + reader.onerror = readFail; + if (sliceEnd !== undefined) { + file = file.slice(sliceStart, sliceEnd); + } else if (sliceStart !== undefined) { + file = file.slice(sliceStart); + } + reader[funcName](file); + + waitsForAny(readWin, readFail); + }); + } + + function arrayBufferEqualsString(buf, str) { + var buf = new Uint8Array(ab); + var match = buf.length == str.length; + + for (var i = 0; match && i < buf.length; i++) { + match = buf[i] == str.charCodeAt(i); + } + return match; + } + + it("file.spec.84 should read file properly, readAsText", function() { + runReaderTest('readAsText', false, function(evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(fileData); + }); + }); + it("file.spec.85 should read file properly, Data URI", function() { + runReaderTest('readAsDataURL', true, function(evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result.substr(0,23)).toBe("data:text/plain;base64,"); + expect(evt.target.result.slice(23)).toBe(atob(fileData)); + }); + }); + it("file.spec.86 should read file properly, readAsBinaryString", function() { + runReaderTest('readAsBinaryString', true, function(evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(fileDataAsBinaryString); + }); + }); + it("file.spec.87 should read file properly, readAsArrayBuffer", function() { + // Skip test if ArrayBuffers are not supported (e.g.: Android 2.3). + if (typeof window.ArrayBuffer == 'undefined') { + return; + } + runReaderTest('readAsArrayBuffer', true, function(evt, fileData, fileDataAsBinaryString) { + expect(arrayBufferEqualsString(evt.target.result, fileDataAsBinaryString)).toBe(true); + }); + }); + it("file.spec.88 should read sliced file: readAsText", function() { + runReaderTest('readAsText', false, function(evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(fileDataAsBinaryString.slice(10, 40)); + }, 10, 40); + }); + it("file.spec.89 should read sliced file: slice past eof", function() { + runReaderTest('readAsText', false, function(evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(fileData.slice(-5, 9999)); + }, -5, 9999); + }); + it("file.spec.90 should read sliced file: slice to eof", function() { + runReaderTest('readAsText', false, function(evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(fileData.slice(-5)); + }, -5); + }); + it("file.spec.91 should read empty slice", function() { + runReaderTest('readAsText', false, function(evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(''); + }, 0, 0); + }); + it("file.spec.92 should read sliced file properly, readAsDataURL", function() { + runReaderTest('readAsDataURL', true, function(evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result.slice(0, 23)).toBe("data:text/plain;base64,"); + expect(evt.target.result.slice(23)).toBe(atob(fileDataAsBinaryString.slice( 10, -3))); + }, 10, -3); + }); + it("file.spec.93 should read sliced file properly, readAsBinaryString", function() { + runReaderTest('readAsBinaryString', true, function(evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(fileDataAsBinaryString.slice(-10, -5)); + }, -10, -5); + }); + it("file.spec.94 should read sliced file properly, readAsArrayBuffer", function() { + // Skip test if ArrayBuffers are not supported (e.g.: Android 2.3). + if (typeof window.ArrayBuffer == 'undefined') { + return; + } + runReaderTest('readAsArrayBuffer', true, function(evt, fileData, fileDataAsBinaryString) { + expect(arrayBufferEqualsString(evt.target.result, fileDataAsBinaryString.slice(0, -1))).toBe(true); + }, 0, -1); + }); + }); + + describe('FileWriter', function(){ + it("file.spec.81 should have correct methods", function() { + // retrieve a FileWriter object + var fileName = "writer.methods", + fail = createFail('FileWriter'), + verifier = jasmine.createSpy().andCallFake(function(writer) { + expect(writer).toBeDefined(); + expect(typeof writer.write).toBe('function'); + expect(typeof writer.seek).toBe('function'); + expect(typeof writer.truncate).toBe('function'); + expect(typeof writer.abort).toBe('function'); + + // cleanup + deleteFile(fileName); + }), + it_writer = function(fileEntry) { + fileEntry.createWriter(verifier, fail); + }; + + // it FileWriter + runs(function() { + root.getFile(fileName, {create: true}, it_writer, fail); + }); + + waitsFor(function() { return verifier.wasCalled; }, "verifier never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).not.toHaveBeenCalled(); + expect(verifier).toHaveBeenCalled(); + }); + }); + it("file.spec.96 should be able to write and append to file, createWriter", function() { + var fileName = "writer.append", + theWriter, + filePath = root.fullPath + '/' + fileName, + // file content + rule = "There is an exception to every rule.", + // for checkin file length + length = rule.length, + fail = createFail('FileWriter'), + verifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.length).toBe(length); + expect(theWriter.position).toBe(length); + + // append some more stuff + var exception = " Except this one."; + theWriter.onwriteend = anotherVerifier; + length += exception.length; + theWriter.seek(theWriter.length); + theWriter.write(exception); + }), + anotherVerifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.length).toBe(length); + expect(theWriter.position).toBe(length); + + // cleanup + deleteFile(fileName); + }), + // writes initial file content + write_file = function(fileEntry) { + fileEntry.createWriter(function(writer) { + theWriter = writer; + writer.onwriteend = verifier; + writer.write(rule); + }, fail); + }; + + // create file, then write and append to it + runs(function() { + createFile(fileName, write_file); + }); + + waitsFor(function() { return anotherVerifier.wasCalled; }, "verifier never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(fail).not.toHaveBeenCalled(); + expect(verifier).toHaveBeenCalled(); + expect(anotherVerifier).toHaveBeenCalled(); + }); + }); + it("file.spec.97 should be able to write and append to file, File object", function() { + var fileName = "writer.append", + theWriter, + filePath = root.fullPath + '/' + fileName, + // file content + rule = "There is an exception to every rule.", + // for checking file length + length = rule.length, + verifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.length).toBe(length); + expect(theWriter.position).toBe(length); + + // append some more stuff + var exception = " Except this one."; + theWriter.onwriteend = anotherVerifier; + length += exception.length; + theWriter.seek(theWriter.length); + theWriter.write(exception); + }), + anotherVerifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.length).toBe(length); + expect(theWriter.position).toBe(length); + + // cleanup + deleteFile(fileName); + }), + // writes initial file content + write_file = function(file) { + theWriter = new FileWriter(file); + theWriter.onwriteend = verifier; + theWriter.write(rule); + }; + + // create file, then write and append to it + runs(function() { + var file = new File(); + file.fullPath = filePath; + write_file(file); + }); + + waitsFor(function() { return anotherVerifier.wasCalled; }, "verifier", Tests.TEST_TIMEOUT); + + runs(function() { + expect(verifier).toHaveBeenCalled(); + expect(anotherVerifier).toHaveBeenCalled(); + }); + }); + it("file.spec.98 should be able to seek to the middle of the file and write more data than file.length", function() { + var fileName = "writer.seek.write", + filePath = root.fullPath + '/' + fileName, + theWriter, + // file content + rule = "This is our sentence.", + // for iting file length + length = rule.length, + fail = createFail('FileWriter'), + verifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.length).toBe(length); + expect(theWriter.position).toBe(length); + + // append some more stuff + var exception = "newer sentence."; + theWriter.onwriteend = anotherVerifier; + length = 12 + exception.length; + theWriter.seek(12); + theWriter.write(exception); + }), + anotherVerifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.length).toBe(length); + expect(theWriter.position).toBe(length); + + // cleanup + deleteFile(fileName); + }), + // writes initial file content + write_file = function(fileEntry) { + fileEntry.createWriter(function(writer) { + theWriter = writer; + theWriter.onwriteend = verifier; + theWriter.write(rule); + }, fail); + }; + + // create file, then write and append to it + runs(function() { + createFile(fileName, write_file); + }); + + waitsFor(function() { return anotherVerifier.wasCalled; }, "verifier never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(verifier).toHaveBeenCalled(); + expect(anotherVerifier).toHaveBeenCalled(); + }); + }); + it("file.spec.99 should be able to seek to the middle of the file and write less data than file.length", function() { + var fileName = "writer.seek.write2", + filePath = root.fullPath + '/' + fileName, + // file content + rule = "This is our sentence.", + theWriter, + fail = createFail('FileWriter'), + // for iting file length + length = rule.length, + verifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.length).toBe(length); + expect(theWriter.position).toBe(length); + + // append some more stuff + var exception = "new."; + theWriter.onwriteend = anotherVerifier; + length = 8 + exception.length; + theWriter.seek(8); + theWriter.write(exception); + }), + anotherVerifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.length).toBe(length); + expect(theWriter.position).toBe(length); + + // cleanup + deleteFile(fileName); + }), + // writes initial file content + write_file = function(fileEntry) { + fileEntry.createWriter(function(writer) { + theWriter = writer; + theWriter.onwriteend = verifier; + theWriter.write(rule); + }, fail); + }; + + // create file, then write and append to it + runs(function() { + createFile(fileName, write_file); + }); + + waitsFor(function() { return anotherVerifier.wasCalled; }, "verifier never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(verifier).toHaveBeenCalled(); + expect(anotherVerifier).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.100 should be able to write XML data", function() { + var fileName = "writer.xml", + filePath = root.fullPath + '/' + fileName, + fail = createFail('FileWriter'), + theWriter, + // file content + rule = '<?xml version="1.0" encoding="UTF-8"?>\n<it prop="ack">\nData\n</it>\n', + // for iting file length + length = rule.length, + verifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.length).toBe(length); + expect(theWriter.position).toBe(length); + + // cleanup + deleteFile(fileName); + }), + // writes file content + write_file = function(fileEntry) { + fileEntry.createWriter(function(writer) { + theWriter = writer; + theWriter.onwriteend = verifier; + theWriter.write(rule); + }, fail); + }; + + // creates file, then write XML data + runs(function() { + createFile(fileName, write_file); + }); + + waitsFor(function() { return verifier.wasCalled; }, "verifier", Tests.TEST_TIMEOUT); + + runs(function() { + expect(verifier).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.101 should be able to write JSON data", function() { + var fileName = "writer.json", + filePath = root.fullPath + '/' + fileName, + theWriter, + // file content + rule = '{ "name": "Guy Incognito", "email": "here@there.com" }', + fail = createFail('FileWriter'), + // for iting file length + length = rule.length, + verifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.length).toBe(length); + expect(theWriter.position).toBe(length); + + // cleanup + deleteFile(fileName); + }), + // writes file content + write_file = function(fileEntry) { + fileEntry.createWriter(function(writer) { + theWriter = writer; + theWriter.onwriteend = verifier; + theWriter.write(rule); + }, fail); + }; + + // creates file, then write JSON content + runs(function() { + createFile(fileName, write_file); + }); + + waitsFor(function() { return verifier.wasCalled; }, "verifier", Tests.TEST_TIMEOUT); + + runs(function() { + expect(verifier).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.102 should be able to seek", function() { + var fileName = "writer.seek", + // file content + rule = "There is an exception to every rule. Except this one.", + theWriter, + // for iting file length + length = rule.length, + fail = createFail('FileWriter'), + verifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.position).toBe(length); + theWriter.seek(-5); + expect(theWriter.position).toBe(length-5); + theWriter.seek(length + 100); + expect(theWriter.position).toBe(length); + theWriter.seek(10); + expect(theWriter.position).toBe(10); + + // cleanup + deleteFile(fileName); + }), + // writes file content and its writer.seek + seek_file = function(fileEntry) { + fileEntry.createWriter(function(writer) { + theWriter = writer; + theWriter.onwriteend = verifier; + theWriter.seek(-100); + expect(theWriter.position).toBe(0); + theWriter.write(rule); + }, fail); + }; + + // creates file, then write JSON content + runs(function() { + createFile(fileName, seek_file); + }); + + waitsFor(function() { return verifier.wasCalled; }, "verifier never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(verifier).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.103 should be able to truncate", function() { + var fileName = "writer.truncate", + rule = "There is an exception to every rule. Except this one.", + fail = createFail('FileWriter'), + theWriter, + // writes file content + write_file = function(fileEntry) { + fileEntry.createWriter(function(writer) { + theWriter = writer; + theWriter.onwriteend = function(evt) { + truncate_file(theWriter); + }; + theWriter.write(rule); + }, fail); + }, + verifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.length).toBe(36); + expect(theWriter.position).toBe(36); + + // cleanup + deleteFile(fileName); + }), + // and its writer.truncate + truncate_file = function(writer) { + writer.onwriteend = verifier; + writer.truncate(36); + }; + + // creates file, writes to it, then truncates it + runs(function() { + createFile(fileName, write_file); + }); + + waitsFor(function() { return verifier.wasCalled; }, "verifier never called", Tests.TEST_TIMEOUT); + + runs(function() { + expect(verifier).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.104 should be able to write binary data from an ArrayBuffer", function() { + // Skip test if ArrayBuffers are not supported (e.g.: Android 2.3). + if (typeof window.ArrayBuffer == 'undefined') { + return; + } + var fileName = "bufferwriter.bin", + filePath = root.fullPath + '/' + fileName, + theWriter, + // file content + data = new ArrayBuffer(32), + dataView = new Int8Array(data), + fail = createFail('FileWriter'), + // for verifying file length + length = 32, + verifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.length).toBe(length); + expect(theWriter.position).toBe(length); + + // cleanup + deleteFile(fileName); + }), + // writes file content + write_file = function(fileEntry) { + fileEntry.createWriter(function(writer) { + theWriter = writer; + theWriter.onwriteend = verifier; + theWriter.write(data); + }, fail); + }; + + for (i=0; i < dataView.length; i++) { + dataView[i] = i; + } + + // creates file, then write content + runs(function() { + createFile(fileName, write_file); + }); + + waitsFor(function() { return verifier.wasCalled; }, "verifier", Tests.TEST_TIMEOUT); + + runs(function() { + expect(verifier).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + it("file.spec.105 should be able to write binary data from a Blob", function() { + // Skip test if Blobs are not supported (e.g.: Android 2.3). + if (typeof window.Blob == 'undefined' || typeof window.ArrayBuffer == 'undefined') { + return; + } + var fileName = "blobwriter.bin", + filePath = root.fullPath + '/' + fileName, + theWriter, + fail = createFail('FileWriter'), + // file content + data = new ArrayBuffer(32), + dataView = new Int8Array(data), + blob, + // for verifying file length + length = 32, + verifier = jasmine.createSpy().andCallFake(function(evt) { + expect(theWriter.length).toBe(length); + expect(theWriter.position).toBe(length); + + // cleanup + deleteFile(fileName); + }), + // writes file content + write_file = function(fileEntry) { + fileEntry.createWriter(function(writer) { + theWriter = writer; + theWriter.onwriteend = verifier; + theWriter.write(blob); + }, fail); + }; + for (i=0; i < dataView.length; i++) { + dataView[i] = i; + } + try { + // Mobile Safari: Use Blob constructor + blob = new Blob([data], {"type": "application/octet-stream"}) + } catch(e) { + if (window.WebKitBlobBuilder) { + // Android Browser: Use deprecated BlobBuilder + var builder = new WebKitBlobBuilder() + builder.append(data) + blob = builder.getBlob('application/octet-stream'); + } else { + // We have no way defined to create a Blob, so fail + fail(); + } + } + + // creates file, then write content + runs(function() { + createFile(fileName, write_file); + }); + + waitsFor(function() { return verifier.wasCalled; }, "verifier", Tests.TEST_TIMEOUT); + + runs(function() { + expect(verifier).toHaveBeenCalled(); + expect(fail).not.toHaveBeenCalled(); + }); + }); + }); +}); |
