Common Testing Scenarios

A collection of common scenarios that come up while browser testing

Search our documentation:

Toggle Documentation Menu

Common Testing Scenarios

Jump to...

Testing Stripe checkout

Stripe is a common payment platform used across the web. They offer various ways of capturing payments, one of which is a drop-in JavaScript + iFrame checkout module for your website. Ghost Inspector is fully capable of testing checkout flows that use this payment module. However, due to the form validation involved and the dynamic ID attribute tags, small tweaks will need to be applied after your test is recorded.

The are multiple interations of Stripe's checkout code available and the required changes vary slightly between some of them. We've broken them down by "New" and "Old" versions. If you're setting up a new test, we recommend assuming you have the new version first. If the suggested tweaks below don't work, please take a look at the older version. In both cases, we recommend using the "PhantomJS 2" browser option because it provides better access methods into Stripe's <iframe> module.

Stripe Checkout (New)

This version of Stripe's checkout uses dynamic ID attributes which change on each page load. The Chrome recorder will attempt to detect and avoid using these IDs, but may not always succeed. When it does avoid them, the alternative selectors are often ugly and unclear:

Recorded Stripe checkout steps

After recording the test, these selectors above can be updated to use cleaner methods, including the use of :contains() for semantic targeting:

Updated Stripe checkout steps

You can see that we're using iframe[name="stripe_checkout_app"] div:contains("Card number") input style selectors to match the input field using it's label. This provides a much cleaner selector that avoids using the ID attribute or other awkward means of matching the field.

Once these changes are made and the "PhantomJS 2" browser is selected, the test should interact with the Stripe checkout module properly.

Stripe Checkout (Old)

By default, Ghost Inspector will record the assignment of the Stripe credit card number and expiration date with “Assign” commands. Due to Stripe’s validation logic, these assignments will be stifled. JavaScript will need to be used to assign the values instead.

First, find the Assign step that assigns "4242 4242 4242 4242" into iframe[name="stripe_checkout_app"] #card_number and replace it with an Execute JavaScript step that executes the following code:

var input = $('iframe[name="stripe_checkout_app"]').contents().find("#card_number");
input.val('4242 4242 4242 4242');

Next, find the Assign step that assigns "03 / 20" (or whatever date you’re using) into iframe[name="stripe_checkout_app"] #cc-exp and replace it with an Execute JavaScript step that executes the following code:

var input = $('iframe[name="stripe_checkout_app"]').contents().find("#cc-exp");
input.val('03 / 20');

Ghost Inspector should now assign those values properly so that the checkout process can complete.


A/B Testing

Dealing with A/B testing can be a little tricky since Ghost Inspector can be sent down different routes which may prevent the test steps from working as expected. However, we do have some options to work around it.

If you're able to control the A/B test's variations with some kind of parameters (like a GET parameter in the start URL or a custom HTTP header which can be set in your test's settings), you could then just duplicate the test for each variation and select them explicitly.

If you're doing the A/B testing by loading a JavaScript file, you can use a network filter to simply block the script from loading. For example, if you're using something like Optimizely, you can typically just add the string "optimizely" to the network filter. You can get as specific as you want with the matching. This will prevent the script from loading in the browser session, and thus the A/B switching will not happen. This approach is nice and easy, though it may limit you to a single (default) variation in the test.


Date Pickers

Date picker widgets often present both the challenge of dealing with a complex UI and the need to keep the selection current, so that it doesn't become "stale" as time progresses. Selecting tomorrow's date for a hotel booking today may be acceptable, but could result in an error 2 days from now when that date has passed. Unfortunately Ghost Inspector's Chrome recorder extension isn't able to determine intentions while recording, so it will typically generate a selector which matches the exact date you chose. This will need to be adjusted in the test editor after the test is recorded.

In many cases, selecting the next available date is acceptable for testing purposes. Fortunately, most date picker widgets include classes that make it fairly easy to target the next available day with a selector like .datepicker td.day.available. It's worth investigating the DOM around your date picker widget to see if a simple, durable selector can be created to always target the next available day.


Select2 Menus

Ghost Inspector supports interacting with Select2 menus, but your steps may need a bit of tweaking in the editor after being recorded. Select2 will often use dynamic ID attributes, meaning that it will assign an ID attribute that changes on each page load. When this happens, the Ghost Inspector test runs can't find the element you've recorded because it's constantly changing.

Typically the selector using that ID attribute needs to be swapped out for something more sustainable. Using the :contains() pseudo-selector (which Ghost Inspector supports) can often be handy here. You can update the Select2 click step to target the selection like this (where "Option Label" is the text label of the menu item):

.select2-container--open li[role="treeitem"]:contains("Option Label")


iFrame & Frame Support

Ghost Inspector supports both iframes and traditional frames, but you must use iframe in the selector for the step target. For instance, consider a DOM that looks like this:

<div class="abc">
    <iframe name="xyz">
        <button class="btn">Click me</button>
    </iframe>
</div>
‚Äč

You cannot target the button with simply .abc .btn. You need to target it with something like iframe[name="xyz"] .btn or even just iframe .btn. The iframe element must be targeted specifically in the selector with iframe to tip off the system. The same applies to traditional frame elements.

The Chrome recorder extension should do this automatically, though it may occasionally need to be tweaked afterwards.


Popup Window Support

Popup windows are supported and you're able to record directly inside them with the Chrome recorder extension. When running tests, we don't have a specific syntax for targeting popups. Instead, our system will first check the main window for the element you've specified. If it doesn't find the element, it'll begin cycling through any open popups looking for the element there.

This means that if you're targeting an element in a popup, you need to make sure the selector used in the step doesn't accidentally match an element inside of the main window or another popup. It needs to be unique enough to ensure that only a match within the popup exists. In some cases you may need to tweak the CSS selector generated by the Chrome recorder extension and make it a bit more specific to avoid collision.

If a popup window is created during your test, Ghost Inspector will not show it in the video until you interact with an element in that window (as outlined above). It will not automatically show up in the video simply by being present. Ghost Inspector always shifts focus back to the main window between each step, so your test will need to explicitly target an element that exists only in the popup window in order to see it in the video.


Injecting and Using jQuery

jQuery is a useful JavaScript library which can help you carry out actions on a web page. We do not inject jQuery on the page for you. However, you can access it within JavaScript steps if it's already present, or you can inject it yourself.

If jQuery is already present on the page you're interacting with, you can typically access it using the standard $() function. In some cases, jQuery is only available through it's proper function name: jQuery() instead of $().

If you would like to use jQuery and it's not present on the page, you can load it yourself with an Execute JavaScript step and this code (which adds jQuery v2.2.4 to the page):

var resource = document.createElement('script');
resource.src = "https://code.jquery.com/jquery-2.2.4.min.js";
var script = document.getElementsByTagName('script')[0];
script.parentNode.insertBefore(resource, script);

We recommend adding a 5 second (5000ms) "Pause" step afterwards to ensure that the library has time to download. Once complete, you can then use the injected jQuery with window.$() in future JavaScript steps on that page. Note that if you change pages during the test you will need to inject jQuery again.


Google Analytics

Google Analytics is a common on-page analytics system used by many websites. In some cases, you may want to check to ensure that Google Analytics is setup properly. In other cases, you may wish to exclude Ghost Inspector's traffic to ensure that it doesn't affect your analytics.

Check for Google Analytics on a Page

It's relatively easy to check for Google Analytics with a JavaScript returns true assertion that checks for it in the global window object using code like this:

return (typeof window.ga === "function")
That assertion will pass if Google Analytics is setup and fail if it isn't. We recommend adding a 5 second (5000ms) "Pause" step before performing this check, since Google Analytics is typically loaded asynchronously.

Exclude Ghost Inspector Traffic from Google Analytics

We provide the IP addresses that our service uses to test your website, which you can exclude from your Google analytics data. Assuming that you're just using our "Northern Virginia, USA" region (which is the default), you'll just need to exclude the 4 IP addresses that we list at the top of the page. If you're using other geolocations, you'll need to exclude those IPs as well.


CAPTCHAs

A CAPTCHA is a program or system intended to distinguish human from machine input, typically as a way of thwarting spam and automated extraction of data from websites. CAPTCHAs are a bit tough to deal with during automated testing since they're specifically designed to prevent bots and automation from getting through — including something like Ghost Inspector. They cannot be solved in an automated way, so they need to be worked around or disabled during testing. Here are some options for dealing with CAPTCHAs:


Embedded Editors

Embedded editors like CKEditor often make use of contenteditable elements, which are challenging for Ghost Inspector to interact with directly. Simple "Assign" steps cannot be used. Fortunately, CKEditor (and most other editors) provide a JavaScript API for interacting. This means you can add an Execute JavaScript step via our test editor and interact with the editor using JavaScript.

CKEditor

CKEDITOR.instances["instance-name-here"].setData("This is sample text.");

Draft.js

When interacting with Draft.js, you can use a normal "Assign" step and set the CSS target to .public-DraftEditor-content.

Kendo UI Editor

$("#editor").data("kendoEditor").value("This is sample text.");

TinyMCE

tinyMCE.activeEditor.setContent("This is sample text.");

Note: These examples generally let most users accomplish what they need to accomplish — though you'll need to experiment with it. We recommend keeping interactions inside of embedded editors to minimum to avoid complexity.


Scrolling a page within a test

Some websites use lazy loading techniques to trigger events and reveal elements as the user scrolls down the page. By default, our browsers do not manually scroll down and trigger these events. However, if necessary, that effect can be achieved through the combination of a JavaScript step and Pause step.

First, add a new step and set the operation to “Execute JavaScript”. Add this code to your step:

var body = document.documentElement || document.body;
body.scrollTop = 0;
setInterval(function(){
  body.scrollTop += 500;
}, 500);

The code above scrolls the page by 500 pixels every 500 milliseconds (a total of 1000 pixels per second).

Next, add a “Pause” step so that the Javascript code has time to scroll all the way down the page. Pause steps use milliseconds, and since the ratio of pixels to milliseconds is 1:1, we can simply set the pause value to the height of our page in pixels. If our page is 10000px, set the pause value to 10000.

Once complete, your steps should look like the screenshot below and scroll all the way down your page — triggering any events along the way.

Scroll steps in test editor
Note: Scrolling will not be captured in the test video due to the way we capture video frames. However, the scrolling is taking place.


Ensure that an image has loaded properly

You can check to see if an image has loaded during a test by checking the "naturalWidth" field of the image element. If this field is equal to 0, then the image has not loaded. A non-zero value means that the image has loaded. This means that you can use a JavaScript returns true assertion to check whether an image has loaded with code like this:

return (document.querySelector('.image-selector').naturalWidth !== 0);

(Where ".image-selector" is the selector for the image element.)

This assertion will pass if the image loads and fail if it does not.