TestComplete lets you write tests in JavaScript. JavaScript in TestComplete is powered by V8 engine v. 5.8. This topic describes the specifics of using JavaScript in TestComplete.
Not Available on Windows XP and Windows Server 2003
The TestComplete JavaScript engine does not support Windows XP and Windows Server 2003, so the JavaScript modules are not installed on these Windows versions. You can still open and view your JavaScript projects on Windows XP and Windows Server 2003, but TestComplete will not run JavaScript code -- both the code in the script units and in the Run Code Snippet operations in keyword tests.
Unsupported Features
JavaScript in TestComplete does not support the ECMAScript Internationalization API.
var vs. let
In JavaScript, you can declare variables using var and let.
let declares a block-scope variable:
JavaScript
function Test()
{
let number = 5;
{
let number = 42; // This variable is different from the one above
let str = "test";
Log.Message(number); // 42
Log.Message(str); // "test"
}
Log.Message(number); // 5
Log.Message(str); // ReferenceError: str is not defined
}
You would typically use let
for variables local to a loop or a branch in if...then...else
:
JavaScript
for (let i = 0; i < 5; i++)
Log.Message(i);
var declares a function-level variable, that is, a variable that is visible throughout the entire function:
JavaScript
function Test()
{
for (var i = 0; i < 5; i++)
{
// do something
}
// "i" is still visible here
Log.Message(i);
}
When used outside functions, or at the top of a function, var
and let
work in the same way.
JavaScript
var str1 = "hello";
let str2 = "world";
function main()
{
Log.Message(str1 + " " + str2);
}
Any variables declared without var
or let
are implicitly global, as if they were defined outside of any function.
JavaScript
function main()
{
a = 5; // global variable
var b = 7; // local variable
foo();
}
function foo()
{
Log.Message(a); // 5
Log.Message(b); // ReferenceError: b is not defined
}
Implicit global variables may have unwanted side effects in your code, so we recommend that you define all global variables explicitly.
Equality Comparison
JavaScript equality operations, ==
and ===
, may lead to incorrect results when comparing values obtained from:
- Objects in a tested application,
- TestComplete scripting objects (such as
aqEnvironment
), - COM objects.
For example (but not limited to), when comparing these values to null
, undefined
or objects.
To avoid issues, use the equal()
and strictEqual()
functions instead of == and ===.
Instead of ... | Use ... |
---|---|
if (something == null) if (something != null) if (something === null) if (something !== null) |
if (equal(something, null)) if (!equal(something, null)) if (strictEqual(something, null)) if (!strictEqual(something, null)) |
if (typeof something == "undefined") if (typeof something != "undefined") if (typeof something === "undefined") if (typeof something !== "undefined") |
if (equal(something, undefined)) if (!equal(something, undefined)) if (strictEqual(something, undefined)) if (!strictEqual(something, undefined)) |
if (objA == objB) if (objA != objB) if (objA === objB) if (objA !== objB) |
if (equal(objA, objB)) if (!equal(objA, objB)) if (strictEqual(objA, objB)) if (!strictEqual(objA, objB)) |
Indexed Properties
In TestComplete, the properties of some test objects have parameters, such as list.wItem(index)
or grid.wValue(row, column)
. JavaScript cannot assign a value to an indexed property directly. You need to use the $set
method instead:
JavaScript
// This won't work
gridObj.wValue(0, "Customer Name") = "Samuel Clemens";
// This works
gridObj.$set("wValue", 0, "Customer Name", "Samuel Clemens");
To get an indexed property with the default parameter values, use empty parentheses after the property name:
JavaScript
let value1 = obj.property(param1, param2);
let value2 = obj.property(); // with default parameters
Working With COM Objects
To obtain COM objects in JavaScript tests, use the getActiveXObject
function. This function was introduced in TestComplete 12.4. It works faster than the Sys.OleObject
property that you used in earlier versions.
If you have multiple (more than several hundred) calls to methods and properties of COM objects, and you experience performance issues, you can use the special $get
, $set
and $call
methods (see below). They will make the calls faster. Otherwise, use the usual object-name.method-name
syntax. This way, your code will be easier to read and maintain.
$get, $set and $call
TestComplete adds extra methods $get
, $set
, and $call
to objects in JavaScript tests. These methods are added to:
- Test objects (objects in your tested application),
- TestComplete scripting objects (
aqFileSystem
and others), - COM objects.
Normally, you do not need to use these methods, only for assigning an indexed property (see above).
Referencing Other Script Units
You can use the require()
function to import functions and variables from other JavaScript units in your test project. The referenced unit must explicitly export the needed functions and variables via module.exports
. For details, see JavaScript - Calling Routines and Variables Declared in Another Unit.
JavaScript
// [CommonUnit]
var answer = 42;
function hello()
{
Log.Message("Hello, world!");
}
module.exports.hello = hello;
module.exports.answer = answer;
// [MainUnit]
var common = require("CommonUnit");
function main()
{
common.hello();
Log.Message(common.answer);
}
The TestComplete //USEUNIT
directive is also supported, but with some limitations.
instanceof Operator
The instanceof
operator returns an incorrect value if the checked objects are passed between script units. Suppose you have the following code:
JavaScript
function fooA()
{
throw new Error(10, "This is an error."); // Simulates exception
}
function fooB()
{
try
{
fooA();
}
catch (err)
{
let res = err instanceof Error;
Log.Message("err instanceof Error = " + res);
}
}
If both fooA
and fooB
reside in the same script unit, the res
variable in the fooB
function will be true
. If you place fooB
to another unit, then the res
variable will be false
.
typeof Operator
In TestComplete, when the operand of the typeof
operator is a regular expression, you have to use parentheses:
JavaScript
// Log.Message(typeof /s/); Syntax error
Log.Message(typeof(/s/));
Using Iterable Objects
You can use the for...of
loop to iterate over an iterable object:
JavaScript
for (let process of Sys)
Log.Message(process.ProcessName);
The for...of
loop works with any test object that has the _NewEnum
property in the Object Browser.
Note: | The Enumerator object is also supported for compatibility with code ported from JScript. |
Accessing Collection Items
COM objects can have properties that return a collection object. Some scripting languages like VBScript allow accessing collection items directly, for example, obj.Cells(i, j)
rather than obj.Cells.Item(i, j)
. JavaScript does not support this. To access items of a collection object, you should specify the appropriate property (Item
, Items
) explicitly:
JavaScript
Log.Message(Excel.Cells.Item(i, j));
JSON
The JSON.stringify
, JSON.parse
and toJSON
methods work only with native JavaScript objects. They are not supported for TestComplete objects, for example, Aliases.browser.MyPage.
Passing Parameters by Reference
JavaScript does not support passing function parameters by reference. However, you may be able to call such functions by using the OutParameterWrapper extension.
This restriction also applies to calling DLL functions. However, when an object is passed through a function’s parameters in JavaScript, the function actually obtains a reference to the object. If the callee routine modifies some members of such an object passed through its parameters, the caller routine can access the updated object after the routine execution is over. Therefore, when a custom structure, array or string value created by the DLL.New
or IDLLAccessProcess.New
method (see Using Custom Data Structures in DLL Function Calls, Using Arrays in DLL Function Calls and Using String Parameters in DLL Function Calls) is passed from your JavaScript test to a DLL routine, you can access the modified structure, array or string after the routine execution is over. The point is that the New
method creates a wrapper object for such structures, arrays and strings and such an object is passed to a DLL routine by reference. So, such structures, arrays and strings can be modified and returned from the routine to which they are passed from JavaScript tests.
Prototype Methods
JavaScript supports extending objects with custom methods declared as prototype methods. The way you call prototype methods of such objects from TestComplete units depends on the corresponding object. If you created a custom scripting object manually, you can call its prototype methods from any unit in a project. Prototype methods of JavaScript built-in objects (such as Array) can be called only in the same unit where these methods are declared; these custom methods are not available in other units.
To work around this limitation, export the constructor of an object from the unit that contains the prototype method declaration. The code below demonstrates this approach:
JavaScript
// [MainUnit]
var CommonUnit = require("CommonUnit")
function Main()
{
// This won’t work:
let arr = new Array(6, 7, 8, 9);
arr.logIndexByItem(7); // Error: "The object does not support this property or method"
// This will work:
let arr2 = new CommonUnit.NewArray(1, 2, 3, 4, 5);
arr2.logIndexByItem(3);
}
// [CommonUnit]
// Prototype method declaration
Array.prototype.logIndexByItem = function(item)
{
for (let i = 0; i < this.length; i++)
{
if ((i in this) && (equal(this[i], item)))
{
Log.Message(i);
return;
}
}
Log.Message("Item was not find");
}
// Exports the constructor of the modified Array object
exports.NewArray = Array;
Debugging
-
JavaScript’s
debugger
statement has no effect in TestComplete. To pause the script execution and activate the debugger, use theRunner.Pause
method. -
The Set Next Statement command is not supported for JavaScript.
-
You cannot change the values of local variables in the Evaluate dialog and in the Watch List.
-
If arrays and typed arrays contain many items, the debugger panels and dialogs group them by 100 for convenient presentation.
See Also
Specifics of Usage Common for All Languages
JavaScript for JScript Users
Script Tests
Writing Scripts - Overview
Selecting the Scripting Language