Run JavaScript on Web Pages

Applies to TestComplete 14.40, last modified on April 22, 2021

The information in this topic applies both to default and cross-platform web tests.

In your web tests, you can run custom JavaScript code on web pages and get its results as part of your tests. For example, if your tested web application uses a custom JavaScript framework such as jQuery, you can use the framework’s utility functions to analyze and process web page elements.

You can execute JavaScript on web pages regardless of the scripting language of your test project - VBScript, JScript, Python, DelphiScript, C++Script or C#Script. However, there are some specifics of doing this in VBScript and DelphiScript projects that are explained in this topic.

Cross-Platform Web Tests Limitations

  • In cross-platform web tests, you can only call scripts that return values of a simple type (a string, an integer, or a Boolean). If a script returns a value of a complex type, for example, an object or a collection, TestComplete will convert it into a string.

  • To call a property or a method of a scripting object, for example, of an object returned by a script expression, use the eval syntax. See below.

How To Run Scripts on Web Pages

You can access scripts on web pages using the contentDocument.Script property of the Page test object. It provides access to both functions defined directly on the web page as well as in external JavaScript scripts loaded by using <script src="filename.js"/>.

Application-Defined Script Functions

Call application-defined script functions directly by their name via the contentDocument.Script object and the dot notation (in VBScript, JScript, Python and DelphiScript) or bracket notation (in C++Script and C#Script):

JavaScript, JScript

// Calling a function with no return value
pageObj.contentDocument.Script.functionName();

// Calling a function with a return value
var res = pageObj.contentDocument.Script.functionName(param1, ..., paramN);

Python

# Calling a function with no return value
pageObj.contentDocument.Script.functionName();

# Calling a function with a return value
res = pageObj.contentDocument.Script.functionName(param1, ..., paramN);

VBScript

' Calling a function with no return value
pageObj.contentDocument.Script.functionName()

' Calling a function with a return value
res = pageObj.contentDocument.Script.functionName(param1, ..., paramN)

DelphiScript

// Calling a function with no return value
pageObj.contentDocument.Script.functionName();

// Calling a function with a return value
res := pageObj.contentDocument.Script.functionName(param1, ..., paramN);

C++Script, C#Script

// Calling a function with no return value
pageObj["contentDocument"]["Script"]["functionName"]();

// Calling a function with a return value
var res = pageObj["contentDocument"]["Script"]["functionName"](param1, ..., paramN);

For example, if a web page contains the following function:

HTML, JavaScript

<script>
function sum(a, b)
{
  return a + b;
}
</script>

you can call this function from your test as follows:

JavaScript, JScript

var sum = pageObj.contentDocument.Script.sum(3, 4);

Python

sum = pageObj.contentDocument.Script.sum(3, 4);

VBScript

sum = pageObj.contentDocument.Script.sum(3, 4)

DelphiScript

sum := pageObj.contentDocument.Script.sum(3, 4);

C++Script, C#Script

var sum = pageObj["contentDocument"]["Script"]["sum"](3, 4);

Note:

Due to limitations of Chrome’s native messaging protocol, the size of parameters passed to web page scripts cannot exceed 1 megabyte.

Arbitrary JavaScript Code

To run custom JavaScript code on a web page, you can use the following syntax:

JavaScript, JScript

pageObj.contentDocument.Script.eval("functionName()");

var res = pageObj.contentDocument.Script.eval("functionName(param1, ..., paramN)");

Python

pageObj.contentDocument.Script.eval("functionName()");

res = pageObj.contentDocument.Script.eval("functionName(param1, ..., paramN)");

VBScript

pageObj.contentDocument.Script.eval("functionName()")

res = pageObj.contentDocument.Script.eval("functionName(param1, ..., paramN)")

DelphiScript

pageObj.contentDocument.Script.eval('functionName()');

res := pageObj.contentDocument.Script.eval('functionName(param1, ..., paramN)');

C++Script, C#Script

pageObj["contentDocument"]["Script"]["eval"]("functionName()");

var res = pageObj["contentDocument"]["Script"]["eval"]("functionName(param1, ..., paramN)");

The eval approach is useful for calling:

  • DOM methods, such as history.back(), location.reload(), window.alert() and so on:

    JavaScript, JScript

    pageObj.contentDocument.Script.eval("history.back()");

    Python

    pageObj.contentDocument.Script.eval("history.back()");

    VBScript

    pageObj.contentDocument.Script.eval("history.back()")

    DelphiScript

    pageObj.contentDocument.Script.eval('history.back()');

    C++Script, C#Script

    pageObj["contentDocument"]["Script"]["eval"]("history.back()");

  • arbitrary JavaScript expressions:

    JavaScript, JScript

    pageObj.contentDocument.Script.eval("var i = 5; alert(i);");

    Python

    pageObj.contentDocument.Script.eval("var i = 5; alert(i);");

    VBScript

    pageObj.contentDocument.Script.eval("var i = 5; alert(i);")

    DelphiScript

    pageObj.contentDocument.Script.eval('var i = 5; alert(i);');

    C++Script, C#Script

    pageObj["contentDocument"]["Script"]["eval"]("var i = 5; alert(i);");

Example: Using jQuery to Find Web Page Elements

The following example uses the jQuery function $ and a CSS selector to find all elements of the container class on the main page of the SmartBear website and hide them.

To run this example from a keyword test, use the Run Script Routine operation.

Default

JavaScript, JScript

function UsejQuery()
{
  var url = "https://smartbear.com/";
  Browsers.Item(btIExplorer).Run(url);
  var page = Sys.Browser().Page(url);

  page.contentDocument.Script.$(".container").hide();
}

Python

def UsejQuery():
  url = "https://smartbear.com/"
  Browsers.Item[btIExplorer].Run(url)
  page = Sys.Browser().Page(url)

  # Note we use the full function name - jQuery,
  # because the short name $ isn't a valid identifier in Python code
  page.contentDocument.Script.jQuery(".container").hide()

VBScript

Sub UsejQuery
  Dim url, page

  url = "https://smartbear.com/"
  Browsers.Item(btIExplorer).Run url
  Set page = Sys.Browser.Page(url)

  ' Note we use the full function name - jQuery,
  'because the short name $ isn't a valid identifier in VBScript code

  page.contentDocument.Script.jQuery(".container").hide()
End Sub

DelphiScript

procedure UsejQuery;
var url, page;
begin
  url := 'https://smartbear.com/';
  Browsers.Item[btIExplorer].Run(url);
  page := Sys.Browser.Page(url);

  // Note we use the full function name - jQuery,
  // because the short name $ isn't a valid identifier in DelphiScript code

  page.contentDocument.Script.jQuery('.container').hide();
end;

C++Script, C#Script

function UsejQuery()
{
  var url = "https://smartbear.com/";
  Browsers["Item"](btIExplorer)["Run"](url);
  var page = Sys["Browser"]()["Page"](url);

  page["contentDocument"]["Script"]["$"](".container")["hide"]();
}

Cross-Platform

JavaScript, JScript

function UsejQuery()
{
  var url = "https://smartbear.com/";
  Browsers.CurrentBrowser.Navigate(url);
  var page = Sys.Browser().Page(url);

  page.contentDocument.Script.eval("$(\".container\").hide()");
}

Python

def UsejQuery():
  url = "https://smartbear.com/"
  Browsers.CurrentBrowser.Navigate(url)
  page = Sys.Browser().Page(url)

  # Note we use the full function name - jQuery,
  # because the short name $ isn't a valid identifier in Python code
  page.contentDocument.Script.eval("jQuery('.container').hide()")

VBScript

Sub UsejQuery
  Dim url, page

  url = "https://smartbear.com/"
  Browsers.CurrentBrowser.Navigate url
  Set page = Sys.Browser.Page(url)

  ' Note we use the full function name - jQuery,
  'because the short name $ isn't a valid identifier in VBScript code

  page.contentDocument.Script.eval("jQuery('.container').hide()")
End Sub

DelphiScript

procedure UsejQuery;
var url, page;
begin
  url := 'https://smartbear.com/';
  Browsers.CurrentBrowser.Navigate(url);
  page := Sys.Browser.Page(url);

  // Note we use the full function name - jQuery,
  // because the short name $ isn't a valid identifier in DelphiScript code

  page.contentDocument.Script.eval('jQuery(''.container'').hide()');
end;

C++Script, C#Script

function UsejQuery()
{
  var url = "https://smartbear.com/";
  Browsers["CurrentBrowser"]["Navigate"](url);
  var page = Sys["Browser"]()["Page"](url);

  page["contentDocument"]["Script"]["eval"]("$(\".container\").hide()");
}

Specifics of Calling Web Page Scripts

Running JavaScript in Frames in Google Chrome

In Google Chrome, to call a function defined on a web page frame, use the following syntax:

JavaScript, JScript

frameObj.contentDocument.Script.FunctionName();

Python

frameObj.contentDocument.Script.FunctionName();

VBScript

frameObj.contentDocument.Script.FunctionName()

DelphiScript

frameObj.contentDocument.Script.FunctionName();

C++Script, C#Script

frameObj["contentDocument"]["Script"]["FunctionName()"];

To execute arbitrary JavaScript code inside a frame using eval, use the following syntax with the frame ID and double eval:

JavaScript, JScript

frameObj.contentDocument.Script.eval("frameID.eval('var i = 5; alert(i);')");

Python

frameObj.contentDocument.Script.eval("frameID.eval('var i = 5; alert(i);')");

VBScript

frameObj.contentDocument.Script.eval("frameID.eval('var i = 5; alert(i);')")

DelphiScript

frameObj.contentDocument.Script.eval('frameID.eval("var i = 5; alert(i);")');

C++Script, C#Script

frameObj["contentDocument"]["Script"]["eval"]('frameID.eval("var i = 5; alert(i);")');

Using Parentheses in Function Calls in VBScript and DelphiScript

VBScript and DelphiScript let you omit parentheses when calling procedures and functions that do not take any parameters. However, when calling parameterless functions on web pages, do not omit parentheses:

VBScript

pageObj.contentDocument.Script.doSomething  ' Incorrect!
pageObj.contentDocument.Script.doSomething() ' Correct

DelphiScript

pageObj.contentDocument.Script.doSomething;  // Incorrect!
pageObj.contentDocument.Script.doSomething(); // Correct

This is because the syntax without parentheses does not execute the specified function. Instead, it returns the JavaScript Function object corresponding to this function.

Using Arrays in VBScript, Python and DelphiScript

Note: In cross-platform web tests, you can only call functions that return simple type data (strings, integers, and Booleans).

The VBScript, Python and DelphiScript array format is incompatible with the JavaScript array format. As a result, you cannot directly pass arrays between your VBScript or DelphiScript tests and JavaScript scripts on web pages; you should use a specific approach for this.

To pass an array as a parameter to a web page’s JavaScript function, call this function using eval (see above). In this way, you can specify the array elements using JavaScript's array literal syntax [elem1, elem2, ..., elemN].

Python

pageObj.contentDocument.Script.eval("processArray([1, 2, 3])");

VBScript

pageObj.contentDocument.Script.eval("processArray([1, 2, 3])")

DelphiScript

pageObj.contentDocument.Script.eval('processArray([1, 2, 3])');

To use an array returned from the web page in your VBScript, Python or DelphiScript test, you need to convert it to the compatible array format. For this purpose, you can use the following JSArrayToVariantArray function:

Python

# Converts a JavaScript array to a DelphiScript-compatible array
def JSArrayToVariantArray(JSArray):
  arr = BuiltIn.CreateVariantArray(0, JSArray.length - 1);

  for i in range (0, JSArray.length - 1):
    arr[i] = aqObject.GetPropertyValue(JSArray, i);
  return arr;

VBScript

' Converts a JavaScript array to a VBScript-compatible array
Function JSArrayToVariantArray(JSArray)
  Dim arr(), i
  ReDim arr(JSArray.length - 1)

  For i = 0 To JSArray.length - 1
    arr(i) = aqObject.GetPropertyValue(JSArray, i)
  Next

  JSArrayToVariantArray = arr
End Function

DelphiScript

// Converts a JavaScript array to a DelphiScript-compatible array
function JSArrayToVariantArray(JSArray);
var arr, i;
begin
  arr := BuiltIn.CreateVariantArray(0, JSArray.length - 1);

  for i := 0 to JSArray.length - 1 do
    arr[i] := aqObject.GetPropertyValue(JSArray, i);

  Result := arr;
end;

You can use the JSArrayToVariantArray function as follows:

Python

arr = JSArrayToVariantArray(pageObj.contentDocument.Script.eval("getJSArray()");

VBScript

arr = JSArrayToVariantArray(pageObj.contentDocument.Script.eval("getJSArray()")

DelphiScript

arr := JSArrayToVariantArray(pageObj.contentDocument.Script.eval('getJSArray()');

The array obtained in this way is compatible with VBScript, Python and DelphiScript and can be processed using native array operations and functions of these scripting languages. For example, in VBScript you can use the LBound and UBound functions to determine the array’s lower and upper bounds and access array elements using the parenthesis syntax: arr(index).

Using Callback Functions

JavaScript supports using callback functions, that is, passing functions as arguments to other functions. For example:

HTML, JavaScript

<script>
// A sample function that takes a callback function as a parameter
function forEach(arr, callback)
{
  for (var i in arr)
    callback(arr[i]);
}


// Examples of using the forEach function with different callback functions
var numbers = [1, 2, 3, 4, 5];
forEach(numbers, printNumber); // specifying existing callback function
forEach(numbers, function (n) {alert(n);}); specifying callback function inline

function printNumber(n)
{
  document.write(n);
}
</script>

To call such functions from your test and specify a callback function, use eval (see above):

JavaScript, JScript

pageObj.contentDocument.Script.eval("forEach([1, 2, 3], printNumber)");

pageObj.contentDocument.Script.eval("forEach([1, 2, 3], function (n) {alert(n);})");

Python

pageObj.contentDocument.Script.eval("forEach([1, 2, 3], printNumber)");

pageObj.contentDocument.Script.eval("forEach([1, 2, 3], function (n) {alert(n);})");

VBScript

Call pageObj.contentDocument.Script.eval("forEach([1, 2, 3], printNumber)") ' Note: printNumber is a function defined on the web page

Call pageObj.contentDocument.Script.eval("forEach([1, 2, 3], function (n) {alert(n);})")

DelphiScript

pageObj.contentDocument.Script.eval('forEach([1, 2, 3], printNumber)');

pageObj.contentDocument.Script.eval('forEach([1, 2, 3], function (n) {alert(n);})');

C++Script, C#Script

pageObj["contentDocument"]["Script"]["eval"]("forEach([1, 2, 3], printNumber)");

pageObj["contentDocument"]["Script"]["eval"]("forEach([1, 2, 3], function (n) {alert(n);})");

Getting JScript Object's Properties in VBScript

When working with JScript objects and properties from a VBScript project, you may get the Object doesn’t support this property or method runtime error message. The problem occurs when you assign a value of an object’s property to the variable, and the variable name coincides with the property name but differs by case (for example, name and Name).

Suppose we have a JScript object, Obj, with a property, propertyName. Note that the property name is case-sensitive, that is:

VBScript

' The following syntax is correct
Obj.propertyName
' The following syntax is incorrect and the property value will not be returned
Obj.PropertyName

We want to get the property value to the PropertyName variable:

VBScript

' The property value will not be returned and an error will occur
Set PropertyName = Obj.propertyName

Due to VBScript specifics, if the property name coincides with the variable name, the scripting engine passes the variable name (instead of the property name) to the object. In other words, instead of getting the propertyName property, the code above will try to get the PropertyName property (which does not exist). That is why this code throws an error.

To avoid such issues, do not specify variable names that coincide with property names. The following code will work correctly:

VBScript

' The property value will not be returned and an error will occur
Set propertyNameValue = Obj.propertyName

See Also

How To
Accessing DOM document Object

Highlight search results