14

In one of my views, I have a file upload control. It supports file uploading either via drag and drop, or via the standard file dialog opened after a button click.

How to do this in my e2e tests1?


1 Just one of the two options will be enough

Alberto
  • 5,021
  • 4
  • 46
  • 69
Tomas Grosup
  • 6,396
  • 3
  • 30
  • 44
  • What part of functionality do you exactly need to test? Is it the correct drag'n'drop behavior or just the file upload? Is it enough to send a file (e.g., `new File()`) via AJAX? – John Doe Nov 14 '12 at 09:12
  • I just need to do a file upload (with a real file), so I can continue with my other tests. – Tomas Grosup Nov 14 '12 at 10:57
  • So sending a real file via AJAX would work, sending an empty file created with new File() would not. – Tomas Grosup Nov 14 '12 at 10:58
  • If it helps, the file is a xml file and I have no problem with creating that file inside my testing code, if there is a way to do it. – Tomas Grosup Nov 14 '12 at 10:59
  • How do you write your end-to-end tests? [Selenium](http://seleniumhq.org/) supports [file uploads](https://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions#Q:_Does_WebDriver_support_file_uploads?). – wosc Dec 09 '12 at 10:51
  • I am using e2e testing which comes with AngularJS http://docs.angularjs.org/guide/dev_guide.e2e-testing – Tomas Grosup Dec 09 '12 at 15:08

1 Answers1

3

You can upload files using Javascript blobs. This requires the FileApi, which isn't compatible with older browsers (http://caniuse.com/fileapi). But since you mentioned using drag and drop uploads, which uses the FileApi, it shouldn't matter too much.

There are two ways you can upload files using the blob API. One is very easy and the other is simply a continuation of the first.

Using Javascript, you can create a new blob with:

var blob = new Blob("content", contentType);

For example, this will create a blob object that contains the text "Hello World!".

var foo = new Blob("Hello World!", {type: "text/plain"});

You could also use the following method is better for non-plaintext files, such as pdf's. You have to convert the file to Base64 (you can use something like this) and create the blob using the Base64 data.

Use this function (a slightly modified version of this) to create the blob.

function b64toBlob(b64Data, contentType, sliceSize) {
b64Data = b64Data.replace(/\s/g, '');
contentType = contentType || '';
sliceSize = sliceSize || 1024;

function charCodeFromCharacter(c) {
    return c.charCodeAt(0);
}

var byteCharacters = atob(b64Data);
var byteArrays = [];

for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    var slice = byteCharacters.slice(offset, offset + sliceSize);
    var byteNumbers = Array.prototype.map.call(slice, charCodeFromCharacter);
    var byteArray = new Uint8Array(byteNumbers);

    byteArrays.push(byteArray);
}

var blob = new Blob(byteArrays, {type: contentType});
return blob;
}

For example, this will create a PDF blob object.

var pdf = "JVBERi0xLjQKJcfsj6IKNSAwIG9...=="; //base64 encoded file as a String
var pdfBlob = b64toBlob(pdf, "application/pdf", 1024);

After you create the blob with one of the methods above, it can be treated as a file. For example, you could put the file into a FormData object (if you're doing uploads like this):

var fd = new FormData();
fd.append("uploadedFile", pdfBlob, "My PDF.pdf"*);

*Filename parameter only seems to work on Chrome as of now.

Community
  • 1
  • 1
Eric Zhang
  • 672
  • 1
  • 4
  • 13