Intro
So here's the thing, we all know we hate forms, the only thing we hate more than forms themselves is actually filling out forms. But the forms are the interface to our web apps, so we cannot do without them. What we would love to do without, but can't, is skip the application testing part where you fill out forms like there's no tomorrow, just to make sure your app is rock solid.
And filling out forms is a pain. So for some time I wanted to get my hands on a little something that can fill out a form, any form, with a click of a button. JavaScript is ideal for such a task and the best sort of a "little something" is probably a bookmarklet. That is how this bookmark was born.
What is it, what it does?
This is a bookmarklet. You go to page that has one or more forms and you click the bookmarklet. It completes the form for you with some random data. The whole thinking was to have a form ready to be submitted and generating as less validation errors as possible. Here are some details:
- All defaults are kept as they are
- All passwords fields are completed with the same password, in case there is a password/password confirmation combo. The default password is "secret"
- If a text field has the string "email" in its name, the auto-generated value would be a random string @ example.org
- If a text field has the string "name" in its name, a name-looking value will be generated.
- All checkboxes will be checked (who knows which one of them might be "Accept terms" or anything else that is required)
- Multi-selects will have a random number of random options selected
Install
Right-click and bookmark or drag to your personal bookmarks toolbar.
Demo
The code
The demo and the code below are "normal" code, with proper indentation and all. The actual bookmark though has to be on one line and as small as possible, so it's pretty much unreadable. Ah, and while the demo will work in IE, the bookmarklet won't, because it's too big for IE. IE allows up to about 500 characters in the URL (or a bookmarklet) while mine is about 2000 "compressed" or 3000 cleaner. So unless I do something heroic in compressing the script, it won't work on IE. No biggie I'd say, since you'll be testing your application and most likely you use Firefox anyway.
The big picture
Using JSON, the class/object is called auto
and it has the following interface:
var auto ={ // a list of names that will be used to generate // normal looking names names: "Steve Buscemi Catherine Keener ...", // this is where all the random words will come from blurb: "phpBB is a free...", // default password to be used in all password fields password: "secret", // the main function that does all fillerup: function() {}, // helper function, returns randomly selected words // coming from this.blurb getRandomString: function (how_many_words) {}, // helper function, returns randomly selected names // coming from this.names getRandomName: function () {}, // returns this.password getPassword: function () {}, // returns a random int from 0 to count getRand: function (count) {} }
The actual form fill-out is initiated by calling auto.fillerup()
As you can probably guess, the only interesting function is fillerup()
, so let me show you what it does.
fillerup()
In case you're wondering, the name of the function comes from a Sting song:
Fill'er up, son, unleaded.
I need a full tank of gas where I'm headed ...
The function starts by identifying all the elements candidate to be completed:
var all_inputs = document.getElementsByTagName('input'); var all_selects = document.getElementsByTagName('select'); var all_textareas = document.getElementsByTagName('textarea');
OK, we have our work cut out for us, let's start by looping through the select
s:
// selects for (var i = 0, max = all_selects.length; i < max; i++) { var sel = all_selects[i]; // current element if (sel.selectedIndex != -1 && sel.options[sel.selectedIndex].value) { continue; // has a default value, skip it } var howmany = 1; // how many options we'll select if (sel.type == 'select-multiple') { // multiple selects // random number of options will be selected var howmany = 1 + this.getRand(sel.options.length - 1); } for (var j = 0; j < howmany; j++) { var index = this.getRand(sel.options.length - 1); sel.options[index].selected = 'selected'; // @todo - Check if the selected index actually // has a value otherwise try again } }
Then - textarea
s, they cannot be simpler. We only check if there isn't already a value and if there's none, we get two "paragraphs" of 10 words each.
// textareas for (var i = 0, max = all_textareas.length; i < max; i++) { var ta = all_textareas[i]; if (!ta.value) { ta.value = this.getRandomString(10) + '\\n\\n' + this.getRandomString(10); } }
Next (and last), come the input
s. They are a bit more complicated as there are too many of them. Here's the overall code with the skipped details for each input type.
// inputs for (var i = 0, max = all_inputs.length; i < max; i++) { var inp = all_inputs[i]; var type = inp.getAttribute('type'); if (!type) { type = 'text'; // default is 'text'' } if (type == 'checkbox') {...} if (type == 'radio') {...} if (type == 'password') {...} if (type == 'text') {...} }
We're absolutely unforgiving when it comes to checkboxes - just check them all, no questions asked, take no prisoners.
if (type == 'checkbox') { // check'em all // who knows which ones are required inp.setAttribute('checked', 'checked'); /* ... ooor random check-off if (!inp.getAttribute('checked')) { if (Math.round(Math.random())) { // 0 or 1 inp.setAttribute('checked', 'checked'); } } */ }
Next, do the radio
s. They are a bit more complicated, because once we have an element, before checking it, we need to verify that there are no other radios with the same name (and in the same form) are already selected and checked.
if (type == 'radio') { var to_update = true; // we assume this radio needs to be checked // but in any event we'll check first var name = inp.name; var input_array = inp.form.elements[inp.name]; for (var j = 0; j < input_array.length; j++) { if (input_array[j].checked) { // match! already has a value to_update = false; continue; } } if (to_update) { // ok, ok, checking the radio // only ... randomly var index = this.getRand(input_array.length - 1); input_array[index].setAttribute('checked', 'checked'); } }
Passwords - trivial, just make sure you always set the same password.
if (type == 'password') { if (!inp.value) { inp.value = this.getPassword(); } }
And finally - the text inputs. We try to guess the nature of the text field by its name. Here there's plenty of room for improvement and more guesses.
if (type == 'text') { if (!inp.value) { // try to be smart about some stuff // like email and name if (inp.name.indexOf('name') != -1) { // name inp.value = this.getRandomName() + ' ' + this.getRandomName(); } else if (inp.name.indexOf('email') != -1) { // email address inp.value = this.getRandomString(1) + '@example.org'; } else { inp.value = this.getRandomString(1); } } }
C'est tout
That's it, hope you liked it and start using it 😉 Any comment or suggestions - let me know.
Comments? Find me on BlueSky, Mastodon, LinkedIn, Threads, Twitter