Working with form fields

If we are dealing with web pages, more often than not, we will come across form fields, which are input boxes, selection lists, text areas, and buttons. PhantomJS can also be used to automate the input of data and changing field values.

One of the best examples of these scenarios is a login page. We will create a script that will automate the login process to Instagram's web profile. Again, the username and password will be passed as command-line arguments. The first argument is username, followed by password.

var system = require('system'),
var username = system.args[1];
var password = system.args[2];

Now that we have our credentials, we then open Instagram's login page at https://www.instagram.com/accounts/login.

var page = require('webpage').create();
page.open('https://instagram.com/accounts/login/',
function(status) {

With simple browser page inspection, we can check the element ID of the username field, password field, and form ID.

Working with form fields

In the following code, using the DOM selection function, we retrieve the reference to the username field. This element is an instance of HTMLInputElement, since it is a definition of the <input> element.

Working with form fields
page.evaluate(function (uid, pwd) {
  var username_field = document.getElementById('id_username'),
  username_field.value = uid;
  var password_field = document.getElementById('id_password'),
  password_field.value = pwd;
  
  var form = document.getElementById('login-form'),
  this.render('login.png'),
  form.submit();
}, username, password);

We will be working again in the context of the web page, so we enclose all other page manipulation within the evaluate() function.

There are several attributes and functions that are defined for HTMLInputElement. Please refer to the Mozilla Developer Network DOM API documentation for further details.

We set the new value of the username field by setting the value attribute of the HTMLInputElement interface. The username that was passed from the command line is assigned to the value attribute of the element. The same approach is used for the password field. If the browser is shown, both fields should have the data typed in the input boxes. We can add screen capture code (as shown in the preceding code, just before the submission of the form) to render the current status of the input boxes that are filled up for us to see it visually happening. If we are to run the script, it should create a login.png image file to capture and show that the boxes are inserted with values.

To complete our login script, we need to submit the form. Forms are also elements that can be referenced. Form elements are objects based on HTMLFormElement, and this object has a submit() function to trigger the form submission.

The following is our complete script code:

var system = require('system'),
var username = system.args[1];
var password = system.args[2];
var page = require('webpage').create();
page.open('https://instagram.com/accounts/login/', 
function(status) {
  if ( status === "success" ) {
    page.evaluate(function (uid, pwd) {
      var username_field = document.getElementById('id_username'),
      username_field.value = uid;
      var password_field = document.getElementById('id_password'),
      password_field.value = pwd;
      
      var form = document.getElementById('login-form'),
      this.render('login.png'),
      form.submit();
    }, username, password);
  } 
  phantom.exit(0);
});

Running the script will log in to Instagram's secured page using the credentials passed as arguments. The preceding script's output is as follows:

$ ./phantomjs login.js username password

$

Did we really get in and pass the authentication? Yes, we did. However, since most of the page loading takes place after you submit the form, based on our preceding code, the login process will be triggered but terminated. It is terminated because PhantomJS already receives the exit call right after submit().

When submit() is executed, a new page is requested and the loading of the next page starts in the background. As we all know, sometimes it takes a few seconds before everything is rendered after logging in.

To fix this, we need to pause the script and let PhantomJS finish loading the next page before calling the exit call. There is no built-in function to pause, so we are going to use the JavaScript setTimeout as a way of pausing the script process.

We replace the exit call using the following snippet, assuming that the login process will take about 3 seconds to complete, however, this depends on your network speed:

setTimeout( function() {
  phantom.exit(0);
}, 3000 );

Rather than exiting, we will force a 3 second or a 3000 millisecond pause in our script to let the loading happen in the background. After reaching 3 seconds, the code inside the function() callback will be performed where we placed our exit call.

To test if we really logged in, we can assert specific text or information that is found on the page after login, or we can also check if there is an error message that is shown; if yes, the login fails. The following is the page that shows an error message if an attempt to log in fails:

Working with form fields

The error message in Instagram's login page is dynamic, and will only be available if an error occurs. We can inspect the error page and get the reference element that holds this message, using it as our way for checking if we are able to log in successfully.

In the error page, an element with a class ID of alert-red will be present if an error occurs. So instead of exiting, we can insert code that will check if that element is present in the current page content. If it is, we can tell that the login failed.

setTimeout( function() {
  var error = page.evaluate(function(){
    var error = document.querySelector('.alert-red'),
    var error_message = false;
    if( error != null) {
      error_message = document.querySelector('.alert-red').innerText.trim();
    }
    
    return error_message;
  });
  page.render("login2.png");
  
  if(!error) {
    console.log('Login Successful'),
  } else {
    console.log('Login Failed: ' + error);
  }
  
  phantom.exit(0);
}, 5000 );

In the preceding code, we also retrieve the error message and display it back to the console, and after the checking the result page, we can capture the page at its current state so that we can visually check it after we run our script.

Running our script with an invalid username and password will give us the following output:

Working with form fields
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.249.220