blob: 664618f1ef1a54baee540bd673dffe234b8f2f95 [file] [log] [blame]
/*
*
* 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('FileTransfer', function() {
// https://github.com/apache/cordova-labs/tree/cordova-filetransfer
var server = "http://cordova-filetransfer.jitsu.com";
var server_with_credentials = "http://cordova_user:cordova_password@cordova-filetransfer.jitsu.com";
// deletes and re-creates the specified content
var writeFile = function(fileName, fileContent, success, error) {
deleteFile(fileName, function() {
root.getFile(fileName, {create: true}, function(fileEntry) {
fileEntry.createWriter(function (writer) {
writer.onwrite = function(evt) {
success(fileEntry);
};
writer.onabort = function(evt) {
error(evt);
};
writer.error = function(evt) {
error(evt);
};
writer.write(fileContent + "\n");
}, error);
}, error);
});
};
var readFileEntry = function(entry, success, error) {
entry.file(function(file) {
var reader = new FileReader();
reader.onerror = error;
reader.onload = function(e) {
success(reader.result);
};
reader.readAsText(file);
}, error);
};
var getMalformedUrl = function() {
if (device.platform.match(/Android/i)) {
// bad protocol causes a MalformedUrlException on Android
return "httpssss://example.com";
} else {
// iOS doesn't care about protocol, space in hostname causes error
return "httpssss://exa mple.com";
}
};
// deletes file, if it exists, then invokes callback
var deleteFile = function(fileName, callback) {
callback = callback || function() {};
var spy = jasmine.createSpy().andCallFake(callback);
root.getFile(fileName, null,
// remove file system entry
function(entry) {
entry.remove(spy, spy);
},
// doesn't exist
spy);
waitsFor(function() { return spy.wasCalled; }, Tests.TEST_TIMEOUT);
};
it("filetransfer.spec.1 should exist and be constructable", function() {
var ft = new FileTransfer();
expect(ft).toBeDefined();
});
it("filetransfer.spec.2 should contain proper functions", function() {
var ft = new FileTransfer();
expect(typeof ft.upload).toBe('function');
expect(typeof ft.download).toBe('function');
});
describe('FileTransferError', function() {
it("filetransfer.spec.3 FileTransferError constants should be defined", function() {
expect(FileTransferError.FILE_NOT_FOUND_ERR).toBe(1);
expect(FileTransferError.INVALID_URL_ERR).toBe(2);
expect(FileTransferError.CONNECTION_ERR).toBe(3);
});
});
describe('download method', function() {
// NOTE: if download tests are failing, check the white list
//
// <access origin="httpssss://example.com"/>
// <access origin="apache.org" subdomains="true" />
// <access origin="cordova-filetransfer.jitsu.com"/>
it("filetransfer.spec.4 should be able to download a file using http", function() {
var fail = createDoNotCallSpy('downloadFail');
var fileFail = createDoNotCallSpy('downloadFail');
var remoteFile = server + "/robots.txt"
var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
var lastProgressEvent = null;
var fileWin = jasmine.createSpy().andCallFake(function(blob) {
expect(lastProgressEvent.loaded).not.toBeGreaterThan(blob.size);
});
var downloadWin = function(entry) {
expect(entry.name).toBe(localFileName);
expect(lastProgressEvent.loaded).toBeGreaterThan(1);
if (lastProgressEvent.lengthComputable) {
expect(lastProgressEvent.total).not.toBeLessThan(lastProgressEvent.loaded);
} else {
expect(lastProgressEvent.total).toBe(0);
}
entry.file(fileWin, fileFail);
};
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
var ft = new FileTransfer();
ft.onprogress = function(e) {
lastProgressEvent = e;
};
ft.download(remoteFile, root.toURL() + "/" + localFileName, downloadWin, fail);
});
waitsForAny(fileWin, fail, fileFail);
});
it("filetransfer.spec.5 should be able to download a file using http basic auth", function() {
var fail = createDoNotCallSpy('downloadFail');
var remoteFile = server_with_credentials + "/download_basic_auth"
var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
var lastProgressEvent = null;
var downloadWin = jasmine.createSpy().andCallFake(function(entry) {
expect(entry.name).toBe(localFileName);
expect(lastProgressEvent.loaded).toBeGreaterThan(1);
if (lastProgressEvent.lengthComputable) {
expect(lastProgressEvent.total).not.toBeLessThan(lastProgressEvent.loaded);
} else {
expect(lastProgressEvent.total).toBe(0);
}
});
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
var ft = new FileTransfer();
ft.onprogress = function(e) {
lastProgressEvent = e;
};
ft.download(remoteFile, root.toURL() + "/" + localFileName, downloadWin, fail);
});
waitsForAny(downloadWin, fail);
});
it("filetransfer.spec.6 should get http status on basic auth failure", function() {
var downloadWin = createDoNotCallSpy('downloadWin');
var remoteFile = server + "/download_basic_auth";
var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
var downloadFail = jasmine.createSpy().andCallFake(function(error) {
expect(error.http_status).toBe(401);
expect(error.http_status).not.toBe(404, "Ensure " + remoteFile + " is in the white list");
});
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
var ft = new FileTransfer();
ft.download(remoteFile, root.toURL() + "/" + localFileName, downloadWin, downloadFail);
});
waitsForAny(downloadWin, downloadFail);
});
it("filetransfer.spec.7 should be able to download a file using file:// (when hosted from file://)", function() {
var fail = createDoNotCallSpy('downloadFail');
var remoteFile = window.location.href.replace(/\?.*/, '').replace(/ /g, '%20');
var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
var lastProgressEvent = null;
if (!/^file/.exec(remoteFile)) {
expect(remoteFile).toMatch(/^file:/);
return;
}
var downloadWin = jasmine.createSpy().andCallFake(function(entry) {
expect(entry.name).toBe(localFileName);
expect(lastProgressEvent.loaded).toBeGreaterThan(1);
if (lastProgressEvent.lengthComputable) {
expect(lastProgressEvent.total).not.toBeLessThan(lastProgressEvent.loaded);
} else {
expect(lastProgressEvent.total).toBe(0);
}
});
this.after(function() {
deleteFile(localFileName);
});
var ft = new FileTransfer();
ft.onprogress = function(e) {
lastProgressEvent = e;
};
ft.download(remoteFile, root.toURL() + "/" + localFileName, downloadWin, fail);
waitsForAny(downloadWin, fail);
});
it("filetransfer.spec.8 should be able to download a file using https", function() {
var remoteFile = "https://www.apache.org/licenses/";
var localFileName = 'httpstest.html';
var downloadFail = createDoNotCallSpy('downloadFail', 'Ensure ' + remoteFile + ' is in the white-list');
var fileFail = createDoNotCallSpy('fileFail');
var lastProgressEvent = null;
var downloadWin = function(entry) {
readFileEntry(entry, fileWin, fileFail);
};
var fileWin = jasmine.createSpy().andCallFake(function(content) {
expect(content).toMatch(/The Apache Software Foundation/);
expect(lastProgressEvent.loaded).not.toBeGreaterThan(content.length);
});
this.after(function() {
deleteFile(localFileName);
});
var ft = new FileTransfer();
ft.onprogress = function(e) {
lastProgressEvent = e;
};
ft.download(remoteFile, root.toURL() + "/" + localFileName, downloadWin, downloadFail);
waitsForAny(fileWin, downloadFail, fileFail);
});
it("filetransfer.spec.9 should not leave partial file due to abort", function() {
var downloadWin = createDoNotCallSpy('downloadWin');
var remoteFile = 'http://cordova.apache.org/downloads/logos_2.zip';
var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
var startTime = +new Date();
var downloadFail = jasmine.createSpy().andCallFake(function(e) {
expect(e.code).toBe(FileTransferError.ABORT_ERR);
var didNotExistSpy = jasmine.createSpy();
var existedSpy = createDoNotCallSpy('file existed after abort');
root.getFile(localFileName, null, existedSpy, didNotExistSpy);
waitsForAny(didNotExistSpy, existedSpy);
});
runs(function() {
var ft = new FileTransfer();
ft.onprogress = function(e) {
if (e.loaded > 0) {
ft.abort();
}
};
ft.download(remoteFile, root.toURL() + "/" + localFileName, downloadWin, downloadFail);
});
waitsForAny(downloadWin, downloadFail);
});
it("filetransfer.spec.10 should be stopped by abort() right away", function() {
var downloadWin = createDoNotCallSpy('downloadWin');
var remoteFile = 'http://cordova.apache.org/downloads/BlueZedEx.mp3';
var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
var startTime = +new Date();
var downloadFail = jasmine.createSpy().andCallFake(function(e) {
expect(e.code).toBe(FileTransferError.ABORT_ERR);
expect(new Date() - startTime).toBeLessThan(300);
});
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
var ft = new FileTransfer();
ft.abort(); // should be a no-op.
ft.download(remoteFile, root.toURL() + "/" + localFileName, downloadWin, downloadFail);
ft.abort();
ft.abort(); // should be a no-op.
});
waitsForAny(downloadWin, downloadFail);
});
it("filetransfer.spec.11 should call the error callback on abort()", function() {
var downloadWin = createDoNotCallSpy('downloadWin');
var downloadFail = jasmine.createSpy().andCallFake(function(e) { console.log("Abort called") });
var remoteFile = 'http://cordova.apache.org/downloads/BlueZedEx.mp3';
var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
var startTime = +new Date();
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
var ft = new FileTransfer();
ft.abort(); // should be a no-op.
ft.download(remoteFile, root.toURL() + "/" + localFileName, downloadWin, downloadFail);
ft.abort();
ft.abort(); // should be a no-op.
});
waitsForAny(downloadFail);
});
it("filetransfer.spec.12 should get http status on failure", function() {
var downloadWin = createDoNotCallSpy('downloadWin');
var remoteFile = server + "/404";
var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
var downloadFail = jasmine.createSpy().andCallFake(function(error) {
expect(error.http_status).toBe(404);
expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
});
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
var ft = new FileTransfer();
ft.download(remoteFile, root.toURL() + "/" + localFileName, downloadWin, downloadFail);
});
waitsForAny(downloadWin, downloadFail);
});
it("filetransfer.spec.13 should get response body on failure", function() {
var downloadWin = createDoNotCallSpy('downloadWin');
var remoteFile = server + "/404";
var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
var downloadFail = jasmine.createSpy().andCallFake(function(error) {
expect(error.body).toBeDefined();
expect(error.body).toMatch('You requested a 404');
});
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
var ft = new FileTransfer();
ft.download(remoteFile, root.toURL() + "/" + localFileName, downloadWin, downloadFail);
});
waitsForAny(downloadWin, downloadFail);
});
it("filetransfer.spec.14 should handle malformed urls", function() {
var downloadWin = createDoNotCallSpy('downloadWin');
var remoteFile = getMalformedUrl();
var localFileName = "download_malformed_url.txt";
var downloadFail = jasmine.createSpy().andCallFake(function(error) {
// Note: Android needs the bad protocol to be added to the access list
// <access origin=".*"/> won't match because ^https?:// is prepended to the regex
// The bad protocol must begin with http to avoid automatic prefix
expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
expect(error.code).toBe(FileTransferError.INVALID_URL_ERR);
});
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
var ft = new FileTransfer();
ft.download(remoteFile, root.toURL() + "/" + localFileName, downloadWin, downloadFail);
});
waitsForAny(downloadWin, downloadFail);
});
it("filetransfer.spec.15 should handle unknown host", function() {
var downloadWin = createDoNotCallSpy('downloadWin');
var remoteFile = "http://foobar.apache.org/index.html";
var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
var downloadFail = jasmine.createSpy().andCallFake(function(error) {
expect(error.code).toBe(FileTransferError.CONNECTION_ERR);
});
runs(function() {
var ft = new FileTransfer();
ft.download(remoteFile, root.toURL() + "/" + localFileName, downloadWin, downloadFail);
});
waitsForAny(downloadWin, downloadFail);
});
it("filetransfer.spec.16 should handle bad file path", function() {
var downloadWin = createDoNotCallSpy('downloadWin');
var remoteFile = server;
var badFilePath = "c:\\54321";
var downloadFail = jasmine.createSpy();
runs(function() {
var ft = new FileTransfer();
ft.download(remoteFile, badFilePath, downloadWin, downloadFail);
});
waitsForAny(downloadWin, downloadFail);
});
it("filetransfer.spec.17 progress should work with gzip encoding", function() {
var downloadFail = createDoNotCallSpy('downloadFail');
var remoteFile = "http://www.apache.org/";
var localFileName = "index.html";
var lastProgressEvent = null;
var downloadWin = jasmine.createSpy().andCallFake(function(entry) {
expect(entry.name).toBe(localFileName);
expect(lastProgressEvent.loaded).toBeGreaterThan(1, 'loaded');
expect(lastProgressEvent.total).not.toBeLessThan(lastProgressEvent.loaded);
expect(lastProgressEvent.lengthComputable).toBe(true, 'lengthComputable');
});
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
var ft = new FileTransfer();
ft.onprogress = function(e) {
lastProgressEvent = e;
};
ft.download(remoteFile, root.toURL() + "/" + localFileName, downloadWin, downloadFail);
});
waitsForAny(downloadWin, downloadFail);
});
});
describe('upload method', function() {
it("filetransfer.spec.18 should be able to upload a file", function() {
var remoteFile = server + "/upload";
var localFileName = "upload.txt";
var fileContents = 'This file should upload';
var fileFail = createDoNotCallSpy('fileFail');
var uploadFail = createDoNotCallSpy('uploadFail', "Ensure " + remoteFile + " is in the white list");
var lastProgressEvent = null;
var uploadWin = jasmine.createSpy().andCallFake(function(uploadResult) {
expect(uploadResult.bytesSent).toBeGreaterThan(0);
expect(uploadResult.responseCode).toBe(200);
expect(uploadResult.response).toMatch(/fields:\s*{\s*value1.*/);
expect(lastProgressEvent).not.toBeNull('expected progress events');
});
var fileWin = function(fileEntry) {
ft = new FileTransfer();
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = localFileName;
options.mimeType = "text/plain";
var params = new Object();
params.value1 = "test";
params.value2 = "param";
options.params = params;
ft.onprogress = function(e) {
lastProgressEvent = e;
expect(e.lengthComputable).toBe(true);
expect(e.total).toBeGreaterThan(0);
expect(e.loaded).toBeGreaterThan(0);
expect(lastProgressEvent.total).not.toBeLessThan(lastProgressEvent.loaded);
};
// removing options cause Android to timeout
ft.upload(fileEntry.toURL(), remoteFile, uploadWin, uploadFail, options);
};
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
writeFile(localFileName, fileContents, fileWin, fileFail);
});
waitsForAny(uploadWin, uploadFail, fileFail);
});
it("filetransfer.spec.19 should be able to upload a file with http basic auth", function() {
var remoteFile = server_with_credentials + "/upload_basic_auth";
var localFileName = "upload.txt";
var fileContents = 'This file should upload';
var fileFail = createDoNotCallSpy('fileFail');
var uploadFail = createDoNotCallSpy('uploadFail', "Ensure " + remoteFile + " is in the white list");
var lastProgressEvent = null;
var uploadWin = jasmine.createSpy().andCallFake(function(uploadResult) {
expect(uploadResult.bytesSent).toBeGreaterThan(0);
expect(uploadResult.responseCode).toBe(200);
expect(uploadResult.response).toMatch(/fields:\s*{\s*value1.*/);
});
var fileWin = function(fileEntry) {
ft = new FileTransfer();
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = localFileName;
options.mimeType = "text/plain";
var params = new Object();
params.value1 = "test";
params.value2 = "param";
options.params = params;
ft.onprogress = function(e) {
expect(e.lengthComputable).toBe(true);
expect(e.total).toBeGreaterThan(0);
expect(e.loaded).toBeGreaterThan(0);
lastProgressEvent = e;
};
// removing options cause Android to timeout
ft.upload(fileEntry.toURL(), remoteFile, uploadWin, uploadFail, options);
};
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
writeFile(localFileName, fileContents, fileWin, fileFail);
});
waitsForAny(uploadWin, uploadFail, fileFail);
runs(function() {
expect(lastProgressEvent).not.toBeNull('expected progress events');
expect(lastProgressEvent.loaded).toBeGreaterThan(1, 'loaded');
expect(lastProgressEvent.total).not.toBeLessThan(lastProgressEvent.loaded);
});
});
it("filetransfer.spec.6 should get http status on basic auth failure", function() {
var fileFail = createDoNotCallSpy('fileFail');
var uploadWin = createDoNotCallSpy('uploadWin');
var remoteFile = server + "/upload_basic_auth";
var localFileName = "upload_expect_fail.txt";
var uploadFail = jasmine.createSpy().andCallFake(function(error) {
expect(error.http_status).toBe(401);
expect(error.http_status).not.toBe(404, "Ensure " + remoteFile + " is in the white list");
});
var fileWin = function(fileEntry) {
var ft = new FileTransfer();
var options = new FileUploadOptions();
options.fileKey="file";
options.fileName=fileEntry.name;
options.mimeType="text/plain";
ft.upload(fileEntry.toURL(), remoteFile, uploadWin, uploadFail, options);
};
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
writeFile(localFileName, "this file should fail to upload", fileWin, fileFail);
});
waitsForAny(uploadWin, uploadFail, fileFail);
});
it("filetransfer.spec.21 should be stopped by abort() right away.", function() {
var remoteFile = server + "/upload";
var localFileName = "upload.txt";
var fileFail = createDoNotCallSpy('fileFail');
var uploadWin = createDoNotCallSpy('uploadWin', 'Should have been aborted');
var startTime;
var uploadFail = jasmine.createSpy().andCallFake(function(e) {
expect(e.code).toBe(FileTransferError.ABORT_ERR);
expect(new Date() - startTime).toBeLessThan(300);
});
var fileWin = function(fileEntry) {
ft = new FileTransfer();
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = localFileName;
options.mimeType = "text/plain";
startTime = +new Date();
// removing options cause Android to timeout
ft.abort(); // should be a no-op.
ft.upload(fileEntry.toURL(), remoteFile, uploadWin, uploadFail, options);
ft.abort();
ft.abort(); // should be a no-op.
};
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
writeFile(localFileName, new Array(10000).join('aborttest!'), fileWin, fileFail);
});
waitsForAny(uploadWin, uploadFail, fileFail);
});
it("filetransfer.spec.12 should get http status on failure", function() {
var fileFail = createDoNotCallSpy('fileFail');
var uploadWin = createDoNotCallSpy('uploadWin');
var remoteFile = server + "/403";
var localFileName = "upload_expect_fail.txt";
var uploadFail = jasmine.createSpy().andCallFake(function(error) {
expect(error.http_status).toBe(403);
expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
});
var fileWin = function(fileEntry) {
var ft = new FileTransfer();
var options = new FileUploadOptions();
options.fileKey="file";
options.fileName=fileEntry.name;
options.mimeType="text/plain";
ft.upload(fileEntry.toURL(), remoteFile, uploadWin, uploadFail, options);
};
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
writeFile(localFileName, "this file should fail to upload", fileWin, fileFail);
});
waitsForAny(uploadWin, uploadFail, fileFail);
});
it("filetransfer.spec.14 should handle malformed urls", function() {
var fileFail = createDoNotCallSpy('fileFail');
var uploadWin = createDoNotCallSpy('uploadWin');
var remoteFile = getMalformedUrl();
var localFileName = "malformed_url.txt";
var uploadFail = jasmine.createSpy().andCallFake(function(error) {
expect(error.code).toBe(FileTransferError.INVALID_URL_ERR);
expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
});
var fileWin = function(fileEntry) {
var ft = new FileTransfer();
ft.upload(fileEntry.toURL(), remoteFile, uploadWin, uploadFail, {});
};
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
writeFile(localFileName, "Some content", fileWin, fileFail);
});
waitsForAny(uploadWin, uploadFail, fileFail);
});
it("filetransfer.spec.15 should handle unknown host", function() {
var fileFail = createDoNotCallSpy('fileFail');
var uploadWin = createDoNotCallSpy('uploadWin');
var remoteFile = "http://foobar.apache.org/robots.txt";
var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
var uploadFail = jasmine.createSpy().andCallFake(function(error) {
expect(error.code).toBe(FileTransferError.CONNECTION_ERR);
expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
});
var fileWin = function(fileEntry) {
var ft = new FileTransfer();
ft.upload(fileEntry.toURL(), remoteFile, uploadWin, uploadFail, {});
};
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
writeFile(localFileName, "# allow all", fileWin, fileFail);
});
waitsForAny(uploadWin, uploadFail, fileFail);
});
it("filetransfer.spec.25 should handle missing file", function() {
var uploadWin = createDoNotCallSpy('uploadWin');
var remoteFile = server + "/upload";
var localFileName = "does_not_exist.txt";
var uploadFail = jasmine.createSpy().andCallFake(function(error) {
expect(error.code).toBe(FileTransferError.FILE_NOT_FOUND_ERR);
expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
});
runs(function() {
var ft = new FileTransfer();
ft.upload(root.toURL() + "/" + localFileName, remoteFile, uploadWin, uploadFail);
});
waitsForAny(uploadWin, uploadFail);
});
it("filetransfer.spec.16 should handle bad file path", function() {
var uploadWin = createDoNotCallSpy('uploadWin');
var remoteFile = server + "/upload";
var uploadFail = jasmine.createSpy().andCallFake(function(error) {
expect(error.http_status).not.toBe(401, "Ensure " + remoteFile + " is in the white list");
});
runs(function() {
var ft = new FileTransfer();
ft.upload("/usr/local/bad/file/path.txt", remoteFile, uploadWin, uploadFail);
});
waitsForAny(uploadWin, uploadFail);
});
it("filetransfer.spec.27 should be able to set custom headers", function() {
var remoteFile = "http://whatheaders.com";
var localFileName = "upload.txt";
var fileFail = function() {};
var uploadFail = createDoNotCallSpy('uploadFail', "Ensure " + remoteFile + " is in the white list and that Content-Length header is being set.");
var uploadWin = jasmine.createSpy().andCallFake(function(uploadResult) {
expect(uploadResult.bytesSent).toBeGreaterThan(0);
expect(uploadResult.responseCode).toBe(200);
expect(uploadResult.response).toBeDefined();
var responseHtml = decodeURIComponent(uploadResult.response);
expect(responseHtml).toMatch(/CustomHeader1[\s\S]*CustomValue1/i);
expect(responseHtml).toMatch(/CustomHeader2[\s\S]*CustomValue2[\s\S]*CustomValue3/i, "Should allow array values");
});
var fileWin = function(fileEntry) {
ft = new FileTransfer();
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = localFileName;
options.mimeType = "text/plain";
var params = new Object();
params.value1 = "test";
params.value2 = "param";
options.params = params;
options.headers = {
"CustomHeader1": "CustomValue1",
"CustomHeader2": ["CustomValue2", "CustomValue3"],
};
// removing options cause Android to timeout
ft.upload(fileEntry.toURL(), remoteFile, uploadWin, uploadFail, options);
};
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
writeFile(localFileName, "this file should upload", fileWin, fileFail);
});
waitsForAny(uploadWin, uploadFail);
});
});
describe('Backwards compatibility', function() {
/* These specs exist to test that the previously supported API still works with
* the new version of file-transfer.
* They rely on an undocumented interface to File which provides absolute file
* paths, which are not used internally anymore.
* If that interface is not present, then these tests will silently succeed.
*/
it("filetransfer.spec.28 should be able to download a file using local paths", function() {
var fail = createDoNotCallSpy('downloadFail');
var remoteFile = server + "/robots.txt"
var localFileName = remoteFile.substring(remoteFile.lastIndexOf('/')+1);
var localURL = root.toURL() + "/" + localFileName;
var lastProgressEvent = null;
var downloadWin = jasmine.createSpy().andCallFake(function(entry) {
expect(entry.name).toBe(localFileName);
expect(lastProgressEvent.loaded).toBeGreaterThan(1);
});
var unsupportedOperation = jasmine.createSpy("Operation not supported");
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
/* This is an undocumented interface to File which exists only for testing
* backwards compatibilty. By obtaining the raw filesystem path of the download
* location, we can pass that to ft.download() to make sure that previously-stored
* paths are still valid.
*/
cordova.exec(function(localPath) {
var ft = new FileTransfer();
ft.onprogress = function(e) {
lastProgressEvent = e;
if (lastProgressEvent.lengthComputable) {
expect(lastProgressEvent.total).not.toBeLessThan(lastProgressEvent.loaded);
} else {
expect(lastProgressEvent.total).toBe(0);
}
};
ft.download(remoteFile, localPath, downloadWin, fail);
}, unsupportedOperation, 'File', '_getLocalFilesystemPath', [localURL]);
});
waitsForAny(downloadWin, fail, unsupportedOperation);
});
it("filetransfer.spec.29 should be able to upload a file using local paths", function() {
var remoteFile = server + "/upload";
var localFileName = "upload.txt";
var fileContents = 'This file should upload';
var fileFail = createDoNotCallSpy('fileFail');
var uploadFail = createDoNotCallSpy('uploadFail', "Ensure " + remoteFile + " is in the white list");
var unsupportedOperation = jasmine.createSpy("Operation not supported");
var lastProgressEvent = null;
var uploadWin = jasmine.createSpy().andCallFake(function(uploadResult) {
expect(uploadResult.bytesSent).toBeGreaterThan(0);
expect(uploadResult.responseCode).toBe(200);
expect(uploadResult.response).toMatch(/fields:\s*{\s*value1.*/);
});
var fileWin = function(fileEntry) {
ft = new FileTransfer();
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = localFileName;
options.mimeType = "text/plain";
var params = new Object();
params.value1 = "test";
params.value2 = "param";
options.params = params;
ft.onprogress = function(e) {
expect(e.lengthComputable).toBe(true);
expect(e.total).toBeGreaterThan(0);
expect(e.loaded).toBeGreaterThan(0);
lastProgressEvent = e;
};
// removing options cause Android to timeout
/* This is an undocumented interface to File which exists only for testing
* backwards compatibilty. By obtaining the raw filesystem path of the download
* location, we can pass that to ft.download() to make sure that previously-stored
* paths are still valid.
*/
cordova.exec(function(localPath) {
ft.upload(localPath, remoteFile, uploadWin, uploadFail, options);
}, unsupportedOperation, 'File', '_getLocalFilesystemPath', [fileEntry.toURL()]);
};
this.after(function() {
deleteFile(localFileName);
});
runs(function() {
writeFile(localFileName, fileContents, fileWin, fileFail);
});
waitsForAny(uploadWin, uploadFail, fileFail, unsupportedOperation);
runs(function() {
if (!unsupportedOperation.wasCalled) {
expect(lastProgressEvent).not.toBeNull('expected progress events');
expect(lastProgressEvent.loaded).toBeGreaterThan(1);
expect(lastProgressEvent.total).not.toBeLessThan(lastProgressEvent.loaded);
}
});
});
});
});