Grow your CSS skills. Land your dream job.

Prefilling Forms with a Custom Bookmarklet

Published by Chris Coyier

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.

Comments

  1. Great blog post. A few weeks ago I made something related to this – a bookmarklet that lets you enable autocomplete on forms when it is explicitly disabled. Some sites disable autocomplete for – I assume – security reasons – and that bugs me. :)

    • colin wiseman
      Permalink to comment#

      With many forms being used on public spaces it makes sense to me. And for the number of times I spell things wrong and fill up autocomplete with junk… :D

  2. Nice for some quick and dirty tests but you’ll eventually want to automate that further with something like Selenium. https://saucelabs.com/selenium

  3. colin wiseman
    Permalink to comment#

    Although really good for error finding and fixing, nothing beats going through a form manually to see if it’s to long, if the tabs are in the right place, does the flow make sense etc… But great idea that will be used :-)

  4. Great job! I can’t wait for somebody to pick this up and build a library/bookmarklet that recognizes the fields on a page and fills them automatically, without manually linking each field

  5. Jen
    Permalink to comment#

    Thanks for posting this, Adam!

  6. Billy Batts
    Permalink to comment#

    Cool post, but seems like more work than just using Selenium.

  7. Ajaj
    Permalink to comment#

    Thanks.. Good stuff… Really useful

  8. Mark Carney
    Permalink to comment#

    You could also use the Form Filler extension for Chrome, which does pretty much what you need.

  9. Jimmy
    Permalink to comment#

    jQuery, for a bookmarklet? Are you kidding!

    • No? And in fact, BECAUSE it’s a bookmarklet, It might as well use 10 copies of jQuery and a 300k picture of a baby dancing because whatever you can do whatever you want it’s just for yourself.

  10. Tim VO
    Permalink to comment#

    Great idea, has the potential to really help out the QA team. But I’ve run into a bit of a snag.

    I can get it to work fine with IE 9 & 10, but for some reason, the bookmarklet never even fires in IE 11. I don’t get an error message in the developer tools javascript console, the .js file that the bookmarklet is trying to load is never even loaded.

    Are you aware of anything peculiar with IE 11 that would prevent the bookmarklet from firing or loading the .js file?

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".