Prefilling Forms with a Custom Bookmarklet

Avatar of Chris Coyier
Chris Coyier on (Updated on )

The following is a guest post by Adam Lichtenstein. Adam works at Wufoo, a web app for building web forms, so you can imagine the need for testing forms is at least double what the rest of us need. Adam took a different road than I took, so I’ll let him share.

Like most devs, I spend a lot of time manually testing the user experience on the site I work on. Unit and integration tests are great, but there’s no easier way to find a pain-point on your site than to do it a thousand times.

With forms, this can get tedious, fast.

That’s the situation I found myself in a couple of months ago when we were adding the British Pound to our checkout currencies in Wufoo. I had multiple fields to fill out with names, emails, addresses, credit cards. You name it. And of course, a lot of the data had to be unique.

So I built a JavaScript bookmarklet to help the team quickly fill in our checkout forms for testing.

I chose a bookmarklet because:

  1. I can distribute it quickly and easily
  2. I can push updates without the users having to do anything
  3. I can run them on any environment without changing the code

You can build and distribute a Javascript bookmarklet really quickly by creating a Pen on CodePen and adding this snippet into an href:

<a href="javascript: **js goes here** "></a>

Your user only needs to drag the link into their bookmarks bar. Then click on it any time they want to run that code on the current page in the browser.

For this project, I’m going to lean on jQuery to keep the code lean and cross-browser friendly. If anyone wants a vanilla version, let me know in the comments and I’ll be happy to put something together.

I also want to insert random data for most of the fields, so I’m going to use a great library out there called Faker. We’ll use the JavaScript implementation here.

Building the Bookmarklet

We could put our code directly into the snippet. But besides being cleaner and more maintainable, we want to be able to update that code without being forced to update the actual bookmarklet. So instead, lets reference an external file.

We’ll start with our snippet code:

<a href="javascript:
(function(d) {
  var body = d.getElementsByTagName('body')[0],
      script = d.createElement('script');
      script.src = '//localhost.com/pathtomyfile.js';
      body.appendChild(script);
}(window.document));
">My Javascript Bookmarklet</a>

We’re using JavaScript to append a script tag to the body, and adding the path to our file inside. If you are testing on an https secure page, you will want to make sure your script is also https. Otherwise some browsers will throw a security error.

Note: You’ll probably use a localhost version of the file while you’re in development and replace it with a production version when you’re ready to share.

The Prefilling Script

Now that we have our bookmarklet ready to load a script file of our choice. Lets make that script file.

It’s super important to make sure your own code doesn’t conflict or break anything on the original page. So we’ll wrap the whole thing in a Self Invoking Anonymous Function. That will use scope to make sure our variables don’t change anything else on the page.

(function(win, doc, $, undefined) {
    'use strict';
    
    // Don't run if jQuery isn't loaded
    if (typeof window.jQuery === 'undefined') {
      return;
    }
    
    // Our code will go here.

  }(window, window.document, window.jQuery));

I like Chris’ randomize function from the original article. Lets use it to quickly generate random numbers when we need them.

var _rand = function(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

Next, lets load up the FakerJS script. Since we’ve decided we’ll use jQuery as a dependency, we can just use $.getScript which will return a promise when its done.

$.getScript('//cdnjs.cloudflare.com/ajax/libs/Faker/0.7.2/MinFaker.js')
    .done(function() {
      // run our functions from here
    })
    .fail(function() {
      win.console.error('ERROR: FakerJS not loaded!');
    });

Now that we have access to Faker, we can use its methods to generate all kinds of fake names, emails, addresses, etc.

We’ll make a constructor function to load that data so we can reuse it if we want to in the future.

var FormData = function(faker) {

    this.faker     = faker;
    
    this.randomWord = faker.Internet.domainWord();

    this.username  = 'fake_' + this.randomWord;
    this.username  += _rand(100,9999);

    // set this value to your password specifications
    this.password  = 'pass1234';

    this.name      = faker.Name.findName();

    this.address1  = faker.Address.streetAddress();
    this.city      = faker.Address.city();
    this.state     = faker.random.br_state_abbr();
    this.zip       = faker.Address.zipCode();

    // Chris' actual credit card number
    this.cc        = '4242 4242 4242 4242';
    this.exp1      = _rand(1,12);
    this.exp2      = _rand(14,22);
    this.cvv       = _rand(100,999);

};

I’d like to make certain field types like checkboxes and select boxes random. So lets extend the FormData object with some functions.

// Randomly select dropdown
 FormData.prototype.randomizeSelect = function(el) {
    var $el  = $(el),
        len  = $el.find('option').length - 1;

    $el.children('option')
      .prop('selected', false)
      .eq( _rand( 1,len + 1 ) )
      .prop('selected', true);
  };

  // Randomly select radio button
  FormData.prototype.randomizeRadio = function(radios) {
    radios  = radios.not('[type="hidden"]');
    var len = radios.length;

    radios
      .prop('checked', false)
      .eq( _rand( 0, len - 1 ) )
      .prop('checked', true);
  };

  // Add some lorem text for textareas
  FormData.prototype.randomizeParagraph = function(el) {
    $(el).val(this.faker.Lorem.sentence(5));
  };

  // Randomize all checkbox fields
  FormData.prototype.randomizeCheckbox = function(el) {
    var $el  = $(el);

    $el.prop('checked', false);

    if (_rand( 0,1 ) === 0) {
      $el.prop('checked', true);
    }
  };

  FormData.prototype.randomizeEmail = function(el) {
    // if we want different emails for all email fields, we can modify this
    $(el).val('chriscoyier+' + this.randomWord + '@gmail.com');
  };

And last, we just need to bind the data to the fields on our form. We’ll use jQuery to grab each of the fields, or field types where we can, and replace the value without data object. This gives us a nice separation between creating the data, and populating it.

var fillForm = function() {
    data = new FormData(window.Faker);

    $('#name').val(data.name);
    $('#username').val(data.username);
    $('#cc').val(data.cc);
    $('#exp-1').val(data.exp1);
    $('#exp-2').val(data.exp2);
    $('#cvv').val(data.cvv);
    $('#address').val(data.address1);
    $('#city').val(data.city);
    $('#state').val(data.state);
    $('#zip').val(data.zip);
    $('#pw').val(data.password);
    $('#pw-repeat').val(data.password);

    data.randomizeRadio($('[name="radio-choice"]'));

    // Randomize all select boxes
    $('select').each(function() {
      data.randomizeSelect(this);
    });

    // Randomize all checkboxes
    $('input[type="checkbox"').each(function() {
      data.randomizeCheckbox(this);
    });

    // Randomize all textareas
    $('textarea').each(function() {
      data.randomizeParagraph(this);
    });
    
    // Randomize all emails
    $('input[type="email"').each(function() {
      data.randomizeEmail(this);
    });
    
  };

You could also call submit on the form at the end to automatically send the data if you wanted. It’s just a matter of preference.

$('#form').submit();

Conclusion

That’s about all it takes to get a quick and dirty random data form filler in a javascript bookmarklet.

There’s definitely a few ways we could improve on this. But when you’re in a time crunch, it can definitely do the trick.

Check out Inline Copy Editor if you want to see another JavaScript bookmarklet I open sourced for the SurveyMonkey design team.

Hope this helps someone out. Reach out if you have any questions.

Demo

See the Pen 2cde9271cbfbeb48532c2041dbea9c5c by seethroughtrees (@seethroughtrees) on CodePen.