Write scripted browsers

You can use New Relic Synthetics' scripted browsers to emulate and monitor a custom user experience by scripting browsers that navigate your website, take specific actions, and ensure specific elements are present.

Scripted monitors are driven by Selenium WebDriverJS. Each time your script runs, Synthetics creates a fully virtualized Selenium-driven Google Chrome browser that navigates your website and follows each step of the script. Synthetics includes an IDE-style script editor which suggests functions, locators, and other elements to simplify scripting.

For a list of all the available functions, see Scripted browser reference.

Visit a URL

All scripts begin by specifying which URL the monitor should navigate to. To specify a URL, call $browser.get("url"):

$browser.get("https://mywebsite.com");

Sequence actions

Because WebDriverJS is asynchronous, scripting actions can sometimes execute out of order. To force script actions to execute in order, wrap each action in a then(function(){}) call:

$browser.get("https://my-website.com").then(function(){
    return $browser.findElement($driver.By.linkText("Configuration Panel"));
});

To connect multiple actions in sequence, wrap each action in a then(function(){}) call, and chain the calls together:

$browser.get("https://my-website.com").then(function(){
    return $browser.findElement($driver.By.linkText("Configuration Panel"));
}).then(function(){
    return $browser.findElement($driver.By.partialLinkText("Configuration Pa"));
});

Locate elements

Once you have specified a URL to monitor, you will usually want to locate a particular element on the page. Locating an element verifies its presence on the page, and also allows you to interact with page elements.

You can locate elements by their class, id, link text, name or even XPath. To find these attributes, use your browser's developer tools or view your website's source code. For a list of all locator functions, see Locators: Find page elements.

Locate by CSS class

Locate an element by its HTML class (for example, class="button"). A class is usually specified for CSS styling. When locating an element by class, the monitor will select the first element on the page that has that class:

$browser.findElement($driver.By.className("button"));
Locate by HTML ID

Locate an element by its exact HTML id (for example, id="edit-submit"). This is a very straightforward way to locate page elements, but be careful to specify an id that is not likely to change.

$browser.findElement($driver.By.id("edit-submit"));

For an example of locating an element by its id, see Wait for a page element.

Locate an element by its displayed link text. For example, Your Link Text Here in <a href="http://example.com>your link text here</a>. You can locate by the exact link text ($driver.By.linkText) or by partial match ($driver.By.partialLinkText):

$browser.findElement($driver.By.linkText("Configuration Panel"));
$browser.findElement($driver.By.partialLinkText("Configuration Pa"));

For an example of locating a link by its link text, see Navigate to a link.

Locate by name

Locate an element by its exact HTML name (for example, name="search-query-field"). This is most commonly used with input fields such as a search box:

$browser.findElement($driver.By.name("search-query-field"));

For an example of locating an element by its name, see Log in to a website.

Locate by XPath

For more complex page structures, you can use XPath to locate the target element:

$browser.findElement($driver.By.xpath("//input[@placeholder = 'search-query-field']"));

To quickly find the XPath for a particular element, use the Google Chrome developer tools:

  1. In Chrome, navigate to the target website.
  2. Right-click the target element, then select Inspect element.
  3. From the Developer Tools panel that opens automatically, look for the highlighted target element.
  4. Right-click the target element, then select Copy XPath.

Use this XPath in scripts. If your website changes frequently, this method may cause your monitor to fail when your page structure changes. For an example of locating an element by its xpath, see Search a website.

Interact with elements

Because a scripted monitor drives a real, Selenium-powered Google Chrome browser, scripted monitors can interact with page elements in the same way a user would. For example, the monitor can click a link, enter text in a search box, and so on. For a list of available actions, see ActionSequence: Link multiple actions.

First, locate the page element, then call an interaction function:

Click page elements

To click on a link or other page element, locate the element and call the click() function:

$browser.findElement($driver.By.linkText("Configuration Panel")).click();
$browser.findElement($driver.By.className("config-panel-02")).click();

For an example of clicking a located element, see Navigate to a link.

You can control the mouse in other ways with the doubleClick(), dragAndDrop(), mouseDown, mouseUp, and mouseMove functions.

Enter text

To enter text in a field, locate the field and call the sendKeys() function:

$browser.findElement($driver.By.name("search-query-field")).sendKeys("EXAMPLE USER NAME");
$browser.findElement($driver.By.id("search-q-box")).sendKeys("EXAMPLE USER NAME");

Some fields may have default text in them. Clear these fields before sending text to them:

$browser.findElement($driver.By.name("search-query-field")).clear();
$browser.findElement($driver.By.id("search-q-box")).clear();

For an example of entering text in a field, see Search a website.

You can add modifier keys (such as ALT and SHIFT) with the keyDown() and keyUp() functions.

Waiting and timeouts

Large page elements, such as images or complex dynamic content, can take a long time to load. This can cause your script to fail when the monitor attempts to interact with or locate an element that hasn't been loaded yet.

To avoid these issues, set wait conditions that will pause the script until the specified page element is present, or sequence actions manually. For a list of conditions, see Conditions: Pause and wait for conditions.

Wait for page title

Instruct the monitor to wait for the page title to match a certain value. This ensures that the browser has at least received some data from the target page. To wait for page title, specify an expected title and a timeout value in milliseconds:

//Call the wait function
$browser.wait(function() {
//Tell the monitor to get the page title, then run a function on that title.
  return $browser.getTitle().then(function(title) {
//Specify the expected page title.
    return title === "Your Page Title Here";
    });
//If the condition is not satisfied within a timeout of 1000 milliseconds (1 second), proceed anyway.
}, 1000);

For an example of waiting for page title, see Wait for a page to load.

Wait for a specific element

Instruct the monitor to wait for a page element to be present. This is useful when an element your script depends on takes a long time to load, or simply to ensure that a page element is present before your script clicks on it.

Use any of the locate functions with the wait function below. Use your desired function instead of the $driver.By.linkText function used below:

//Tell the monitor to wait up to 7,500 milliseconds (7.5 seconds) for a link whose text is `Your Link Text Here`.
$browser.waitForAndFindElement($driver.By.linkText("Your Link Text Here"), 7500);

For an example of waiting for a specific page element to load, see Wait for a page element.

After a maximum run time of three minutes, Synthetics manually stops the script.

Log script results

You can also manually log monitor results to the script log. Use logging to troubleshoot a script: to discover which step of your script is failing, include a log function along with each key step in your script.

Log static text

To log a line of static text, call console.log():

//Send `That's one small step for man.` to the console log.
console.log('That\'s one small step for man.');

This results in the output:

// ----------------------------------- Console log
That's one small step for man.
Pass a variable to the log function

In addition to logging static text, you can also pass variables to console.log():

//Declare the variable `WEBSITE_URL`
var assert = require('assert'),
  WEBSITE_URL = 'https://my-website.com/';

console.log('That's one small step for man.');
//Load the website specified in `WEBSITE_URL`
$browser.get(WEBSITE_URL);
//Log our success to the console
console.log('One giant leap for', WEBSITE_URL);

Look for these results:

// ----------------------------------- Console log
That's one small step for man.
One giant leap for https://my-website.com/

Unblock analytics services

Synthetics blocks popular analytics services' scripts from running by default. You can allow scripts to run for a specified service(s). This allows the service's scripts to run and collect data like it would for a real user.

//Allow Google Analytics scripts to run
$browser.addHostnameToWhitelist(hostnameArr: ['google-analytics.com']);

//Visit https://my-website.com
$browser.get('https://my-website.com');

Customize the user agent

You can customize the scripted browser's user agent to ensure any browser-specific fixes in your app are working properly, or to bypass a security mechanism in order to filter an internal site.

//Simulate Internet Explorer 10.6
$browser.addHeader('User-Agent', 'Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0');

//Visit http://httpbin.org/user-agent
$browser.get('http://httpbin.org/user-agent');

This only spoofs the user-agent HTTP header for the request to the server. It does not change the value of navigator.userAgent.

Import optional modules

You can also import many popular Node.js modules to enhance your test suite, automate the insertion of test data, and simplify complex functions. For more information, see Importing Node.js modules.

For more help

Additional resources include:

Recommendations for learning more: