Easy automation of JavaScript form testing

If you are writing unit tests that provide coverage for HTML forms then there is an easy, pure JavaScript way to automate testing of the underlying code that works on modern browsers. The nice thing about this approach is you don’t have to manually load a file every time you run the tests. You still need to test the HTML interface components but that’s a topic for a different blog post.

The concept is straightforward in that you need to emulate the underlying functionality of an HTML form. The good news is you don’t have to programmatically create an HTML Form or Input element. Here’s the pattern you need to follow:

  1. Create an xhr request to retrieve the file. Be sure to set the response type as blob.
  2. Take the xhr.response and create a new File Object using the File API.
  3. Inject the File Object into a fake Form Object or,
  4. You can also use FormData() to create an actual Form Object.
  5. The fake Form Object is now ready to pass into your unit tests. Cool!

Here’s how you create a JavaScript FormData Object. Depending on what data your code expects you can add additional key/value pairs using append():

var formData = new FormData();
formData.append("files",/* file array */files);

And, here’s what the basic pattern looks like to retrieve the file, process it and then make it available for your unit tests:


var formNode; // Unit tests can access form node via this global

function retrieveFile(){

    var xhr = new XMLHttpRequest();
    xhr.open("GET","images/blue-pin.png",true); //set path to any file
    xhr.responseType = "blob"; 

    xhr.onload = function()
    {
        if( xhr.status === 200)
        {
            var files = []; // This is our files array

            // Manually create the guts of the File
            var blob = new Blob([this.response],{type: this.response.type});
            var bits = [blob,"test", new ArrayBuffer(blob.size)];

            // Put the pieces together to create the File.
            // Typically the raw response Object won't contain the file name
            // so you may have to manually add that as a property.
            var file = new File(bits,"blue-pin.png",{
                lastModified: new Date(0),
                type: this.response.type
            });

            files.push(file);

            // In this pattern we are faking a form object
            // and adding the files array to it.
            formNode = {
                elements:[
                    {type:"file",
                        files:files}
                ]
            };

            // Last, now run your unit tests
            runYourUnitTestsNow();
        }
        else
        {
            console.log("Retrieve file failed");
        }
    };
    xhr.onerror = function(e)
    {
        console.log("Retrieved file failed: " + JSON.stringify(e));
    };

    xhr.send(null);
}

The problem with JavaScript Obfuscators and Minification – Tracking down errors

JavaScript obfuscators and minifiers do their job well. In fact, some obfuscators have anti-debugging features. However, if you are a legitimate developer building applications against one of these libraries, chances are you’ve gotten an indecipherable error such as “z=null line 14300” and it brings your development efforts to a halt. Error messages like this provide no useful information on what the problem really is, or give any hints on how you might be able solve it. You’ve probably even looked at the jumbled source code in a last ditch attempt to make some sense out of the error. And, whether it’s your own library or a mainstream ones as jQuery or Dojo, it doesn’t matter. The amount of productivity lost because of these errors in probably very large, not to mention the frustration it causes.

I hope the the developers of these obfuscators are reading this…because I have a proposed solution to the problem.

Now, I want to start out by mentioning that I fully understand why obfuscators exist for reasons such as source code protection and decreasing download size. What I propose takes this fully into account, yet makes your library developer friendly in a secure way:

During the obfuscation process create an index file that maps each variable, function and class to a real line number and store this file in a web folder.  Then create a small html file that lets you search the index and return the real line number. Provide an option for return the variable, function or class name, too.

The concept is that if there is an error, like the  “z=null line 14300” I mentioned above, developers can then at least have some hope of narrowing down the general area of the code where it might be occurring.

The bonus is, if you own an obfuscated commercial library, now your tech support people can also look up the general area where a customer might be having a problem. For security reasons you don’t have to share the index file, But, even then, there isn’t enough information in it to de-compile the library. Now, if I post my error to the forum:  What is “z=null line 14300”? Tech support will be able to tell me that I’m missing a custom property on a widget’s HTML DIV element. It’s a win-win situation.

What do you think?

7 required improvements for the Web, HTML and JavaScript

Here’s my 2012 web developer wish list for improvements that I’d like to see happen in the web developer world. If HTML and JavaScript want to be considered enterprise ready for commercial-grade deployments then here’s some things that are needed today.

For clarity, I consider a commercial software deployment to be one that contains over one thousand lines of code, at least two custom .js libraries and involves at least two developers and some sort of code versioning system.

  1. Refactoring. Not having this capability continues to be a huge productivity issue for large projects. Try refactoring across six JavaScript libraries and 1200 lines of code using Notepad++.
  2. Even stronger scope enforcement in JavaScript classes. One wrong misspelling and you can spend fun filled hours (or days) tracking down a private variable that turned itself into a global variable.
  3. Built-in support for code comments. Visual Studio does a fine job, for example. But, it’s still kind of a hack to make it work. I’d like the built-in ability to create comments for methods and classes directly and then be able to access those comments via intellisense throughout any file in the project. Again, this is all about productivity by having this information accessible at your fingertips.
  4. Better built-in JavaScript checking for IDEs. I’d like to see built-in JSLint-like capabilities that have been updated to the latest HTML, JavaScript and CSS3 versions, and not some third party plug-in that’s optional.
  5. Best practice whitepapers. These would be whitepapers written by the browser vendors that provide guidelines on the correct patterns to use when building apps against their browsers. Seriously, it’s been roughly 21 years since we started using browsers and there’s no guidance at all from the powers that be.  Honestly, I’m stunned that these don’t exist. That would be similar to Microsoft publishing .NET and then not providing any conceptual help documentation.
  6. Official tools for browser certification and testing. The folks that build the browsers don’t give us a way to verify if we are building our apps in the best way possible. If these items existed, then quality could get a lot better, and we’d all learn a lot too.
  7. Slower browser release cycles. A slower release cycle for browsers and more improved security and stability. I already blogged about this here.