Four Kitchens
Insights

Simulate user actions with CasperJS

5 Min. ReadDevelopment

In part one we ran functional tests on Picturefill by measuring the behavior of the script in response to the browser’s viewport width changing. In part two we explored Casper’s ability to execute any JS code you write as if you did it within the browser console. However, both of these examples were only using Casper to read data from the page, instead of interacting with the user interface. In this article we will simulate user behavior in order to change the state of the interface.

A preview of the test

As with each of these articles, let’s start with the successful test output so you’ll know what we’re working toward:

The image depicts console output displaying four successful Casper JS tests. The tests report that this blog post was loaded, navigation via mouse to Fourkitchens.com was successful, navigation via keyboard to the Contact form was successful, and the form was filled with our test data. The test concludes by reporting: PASS 4 tests executed in 8.855 seconds, 4 passed, 0 failed, 0 dubious, 0 skipped.

Clicking UI elements

One of the most common actions a user can take is clicking or tapping, depending on your device. Either way, most people do this hundreds of times per day. Whether it’s navigating a menu, following a link, or filling out a form, many people will click elements in order to use web pages. Let’s look at the process of clicking a link. We’ll use this blog post as a starting point, and we’ll click the “Four Kitchens” link in the header which should take Casper to our main website.

Note: if your source code shows little boxes instead of a clock inside the Casper comment, it’s because your browser doesn’t display emoji properly. It doesn’t affect the test because it’s just a visual cue that a momentary pause is expected while the test runs.

  // To start, load this blog post in CasperJS.
  casper.start(config.url, function() {

    // Click the fourkitchens.com link in the header.
    this.click('header p a:first-child');

    // Log the click to the console so we know why it's pausing momentarily.
    test.comment('⌚️  Clicking the Fourkitchens.com link...');
  });

  casper.then(function() {
    // Check the URL to confirm that navigation was successful.
    test.assertUrlMatch(///fourkitchens.com/, 'New location is ' + this.getCurrentUrl());
  });

The final step for this process is to test that Casper ended up where we expected. That is the purpose of assertUrlMatch(). Using a regular expression, we check the current URL and verify that we’ve navigated to the intended location. Since this blog post is on a subdomain (fourword.fourkitchens.com), and we are trying to navigate to our plain website (fourkitchens.com), all we have to do is add two slashes at the beginning to ensure that both HTTP and HTTPS are valid results.

Pressing keys

Another common activity is pressing keys. Maybe the mouse is impossible or uncomfortable to use, or a user just prefers keyboard interaction over a mouse. Here is an example that shows how Casper can use keyboard navigation made available by specifying an accesskey on various links in your HTML.

My build of PhantomJS (which I installed on a Mac using Homebrew) uses the same keyboard combination as Safari 4+: Ctrl, Opt, and then the accesskey which I wish to visit. This might vary between platforms, but I have not tested the script anywhere except my local copy of CasperJS. I referenced the Wikipedia article about access keys to find the common keyboard combinations for accesskey navigation.

// Follow a specific menu item whose `accesskey` attribute is "c"
this.sendKeys('body', 'c', {modifiers: 'ctrl+alt'});

Since this example is only using keyboard nav and not interacting with any JavaScript event listeners, using body as my selector for sendKeys() was sufficient. Depending on your code, you might need to target a specific element.

To confirm that the link was followed, we use a very similar test to the previous one. In this case, since we did not switch domains, all we need to do is look for the string contact in our URL:

test.assertUrlMatch(/contact/, 'New location is ' + this.getCurrentUrl());

Filling and submitting forms

Sending data back to the server is often done with forms. Whether we want to adjust our preferences, add content into a CMS, or sign up for a newsletter, the HTML form is a tried and true method of transmitting data to a web server. Casper deftly handles forms, and it comes with some nice sugar to make scripts shorter and more readable.

Now that we’ve navigated to the Four Kitchens contact form using keyboard shortcuts, why don’t we fill it out? There are two steps: create your form data, and then submit it.

Creating form data is as easy as writing JSON. Just use the name attribute from each form item as your JSON property. Assuming we have a simple form with four items and a previously declared config variable, the JSON looks like this:

config.form = {
  "name": "Chris Ruppel",
  "email": "chris@fourkitchens.com",
  "project-title": "CasperJS Test Project",
  "project-desc": "CasperJS Test Project Description"
};

Now use Casper to submit the values. As usual, the first argument is a selector to target your form. The second argument is the JSON we just wrote. The third argument tells Casper whether you want to submit the form or not. By setting the third argument to false in this example, we are choosing to avoid submitting the form.

casper.fill('#contact', config.form, false);

In a later post, we will flip this boolean and actually submit the form, then check a 3rd party API to confirm that the form submission was successful. Stay tuned!

Example code

If you’d like to inspect a fully-commented working example, download this gist. The examples use this specific blog post plus our public-facing website at FourKitchens.com so it should work exactly as described in this post.

View full code example

Wrapping up

Now that you have the basics covered, try experimenting with your own websites and see if you can manage to navigate them. We intentionally examined some very simple examples, so don’t be surprised if your app is a bit harder to navigate with code than expected. A tool like Casper can expose how mouse-centric some interfaces are. If that is the case for your site, hopefully this exercise will encourage you to think about other forms of access, including keyboard users.

Either way, CasperJS offers a great set of tools for testing interfaces and making sure they react to specific user behaviors. Next up is a deeper dive into user actions, using a vanilla Drupal install as an example.

Testing Drupal with CasperJS