Заполнение форм при помощи букмарклета

Как и многие веб-разработчики, я посвящаю много времени тестированию пользовательского интерфейса сайтов, над которыми работаю.

Автоматизированное тестирование, конечно, является хорошей помощью в этом процессе, но «болевые точки» в интерфейсе зачастую невозможно выявить иным способом, кроме как использовать сайт. Ещё и ещё раз. Этот процесс может очень быстро надоедать. Особенно заполнение форм.

Я сам попал в такую ситуацию пару месяцев назад, когда мы добавляли британский фунт к поддерживаемым валютам при расчёте в Wufoo.

Для проверки необходимо было заполнить множество полей с именами, адресами, номерами кредиток и всего прочего, что подразумевается в процессе расчёта. Разумеется, значительная часть этих данных не должна была повторяться:

В конце концов, я сделал букмарклет для быстрого заполнения форм тестовыми данными. (Bookmarklet – программа на JavaScript, выполненная в виде закладки в браузере, гибрид английских слов «bookmark» – закладка и «applet» – маленькое приложение. – Прим. перев.)

Я выбрал форму букмарклета, потому что:

  • его легко передать пользователю;
  • его легко обновить без участия пользователя;
  • он запускается на любой платформе без изменений.

Вы можете легко сделать букмарклет, создав новый «загончик» на CodePen и поместив в HTML что-то вроде:

<a href="javascript: **Здесь должен быть ваш JS-код** "></a>

Пользователю достаточно перетащить получившуюся ссылку в область закладок своего браузера. Клик по закладке запустит код на текущей странице.

В этом проекте я полагался на jQuery для придания коду максимальной удобочитаемости и кроссбраузерности. Если кому-то нужна версия на чистом JavaScript, напишите мне комментарий – я постараюсь что-нибудь сообразить.

Для создания случайных данных я использовал замечательную библиотеку Faker. Её JavaScript-реализацию можно взять здесь.

Основа букмарклета

Мы можем поместить весь код прямо в ссылку. Но такой вариант будет неудобно читать и сопровождать. Кроме того, мне хотелось иметь возможность вносить исправления в код, не заставляя пользователей обновлять закладку. Так что лучше оставить в букмарклете ссылку на внешний файл.

Сам букмарклет выглядит так:

<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));
 ">Мой букмарклет</a>

В нём мы подгружаем скрипт в тело страницы и добавляем туда же ссылку на внешний файл JavaScript. Необходимо заметить, что, если букмарклет применяется к тестированию страницы, загружаемой по https, то и внешний JS-файл должен отдаваться по https, иначе браузер выдаст ошибку безопасности.

Вполне возможно, что при разработке букмарклета вы захотите воспользоваться локальным сервером. В таком случае не забудьте заменить адрес в ссылке на адрес реального сервера, когда будете распространять ваш скрипт.

Заполнение полей

Теперь, когда мы закончили с закладкой, загружающей наш скрипт, можно взяться и за сам скрипт.

Сверхважной задачей для нас будет не сломать ничего в странице, над тестированием которой будет работать наш скрипт.

Поэтому мы обернём его в самозапускающуюся анонимную функцию. Это соответствующим образом ограничит область видимости наших функций и переменных:

(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));

Мне очень нравится функция генератора псевдослучайных чисел, приведённая Крисом Койлером в этой статье. Воспользуемся ей по мере необходимости:

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

Теперь загрузим FakerJS. Поскольку наш скрипт зависит от jQuery, мы можем использовать его механизм отложенной загрузки при помощи функции $.getScript:

$.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!');
     });

Теперь, когда доступ к Faker нам обещан, мы можем использовать его методы для генерации разнообразных правдоподобных имён, мест, адресов и других тестовых данных.

Повторное использование сгенерированных данных обеспечит нам следующий конструктор:

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);
  };

Неплохо было бы протестировать также чекбоксы и радиокнопки на нашем сайте, выбирая их в случайном порядке. Для этого нам придётся несколько расширить функциональность нашего конструктора:

// 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.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');
   };

И наконец, нам нужно сопоставить генерируемые данные с различными полями тестируемых форм. Мы извлечём из нашей страницы все поля форм и заполним их данными в соответствии с их типом и CSS-классом.

В таком виде наш скрипт прекрасно реализует разделение между механизмом генерации данных и механизмом их использования:

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);
     });
      };

Вы можете отправить форму автоматически, вызвав JavaScript-функцию submit(), либо сделать это вручную. Это лишь вопрос ваших предпочтений:

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

Заключение

Таким образом, мной был написан простой и быстрый заполнитель форм в виде букмарклета для тестирования одного проекта. Определённо, существует множество способов его улучшить. Однако в условиях нехватки времени этот инструмент был использован как есть, и вполне справился со своей работой.

Если хотите, можете рассмотреть также Inline Copy Editor – ещё один мой букмарклет, код которого я открыл для команды дизайнеров SurveyMonkey.

Надеюсь, моя статья была вам полезна. Дайте знать, если появятся вопросы.

РедакцияПеревод статьи «Prefilling Forms with a Custom Bookmarklet»