Script
This is a node that runs JavaScript scripts. It is going to help you solve the following tasks:
- create complex tests to check the results of one or several nodes;
- generate test data;
- change other nodes' variables;
- perform operations to bring the tested system to a specific state (set_up, tear_down);
- debug and access all nodes' states.
The script node editing window is divided into two parts: the code editor and the console output window. To close the console window click the
button.

You can use the toolbar above the output window to manage the console behavior:
/
- choose what to do with the console output.
- clear the window every time you run a script,
- display all previous outputs.




- - auto scroll to the last line of the output
- - clear the console window
Click the
RUN
button to execute the script. The execution continues to the last line of the code and finishes when all asynchronous tasks are done (e.g.setTimeout
). The execution is successful if:- there are no syntax errors in the code;
- the exceptions raised had been handled;
- the execution took no more than 30 seconds (otherwise the execution will be terminated).
Since the call to the script is wrapped in a function, you need to use the
return;
command to avoid errors while terminating the script.To get an error after script termination raise an exception with
throw new Error('Something went wrong');
The script is executed in the Node.js virtual environment. Some Node.js modules and all standard JavaScript features supported by V8 are available.
The ECMAScript 6 standard is supported as well.
Objects and functions of the script's global scope are listed below.
Every module stated above is automatically added to the execution context and is available in the global scope.
_.sum([1, 2, 3, 4]) // 10

const now = moment(new Date()).format();

const hash = crypto.MD5('Message');

const randomEngine = new random.Random();
const shuffledArray = randomEngine.shuffle([1,2,3,4,5]);

const person = {
'name': faker.name.findName(),
'email': faker.internet.email()
};

const foo = 'bar';
// success
assert.equal(foo, 'bar');
expect(foo).to.equal('bar');
// failure
assert.equal(1, 0);

The
request
library doesn't provide an interface for working with async/await. One possible solution is wrapping request
call in Promise
objectawait new Promise((resolve, reject) => {
request('https://docs-ru.testmace.com', (error, response, body) => {
try {
assert.equal(error, null);
assert.equal(response.statusCode, 206);
assert.notEqual(body, null);
resolve();
} catch(e) {
reject(e);
}
});
})

await axios.get('https://api.ipify.org?format=json')

There are different console output methods, such as log, info, warn, error, debug, exception.
Their signatures are equal to the signatures of their standard versions. In the console every method type is highlighted in different color. Each colored line contains the particular row and column where the output method is called. Events of the exception type are displayed along with the stack trace.

In previous versions, TestMace tried to automatically determine if the script had been finished. In new versions, this feature and finish() function were removed.
A script can contain asynchronous calls (e.g. Promise, setTimeout, addEventListener, built-in modules callbacks, etc.). JavaScript provides a convenient mechanism for working with asynchronous operations - async/await. TestMace has full support of async/await and use this mechanism while performing asynchronous operations to determine if the script had been finished. Let's consider the following example:
console.log('1');
setTimeout(() => console.log('2'), 100);
console.log('3');
Console output:
1
3
To fix this you should explicitly mark the operation as an asynchronous usind
await
keyword. For convenience, we've added delay
function that will allow you to pause the script. This function is compatible with async/await:console.log('1');
await delay(100);
console.log('2');
console.log('3');
New console output:
1
2
3
For further information about async/await we recommend to read a documentation. Following modules support async/await:
fs.promises
axios
Finally, it can be mentioned that script execution can take up to 30 seconds. If it takes more then the error will be thrown.
There is an object used to access the project and the current Script node. It is called
tm
and it is available in the global scope. currentNode: nodeAPI
- the current Script node APIproject: nodeAPI
- the project node APIenv: envAPI
- the API for accessing the environment variablescookies: cookie[]
- a list of cookies used in the projectsystem: object
- an object, which contains the system's environment variables
parent: nodeAPI
- returns a parent node API and null for the project nodename: string
- the given node nametype: string
- the given node typepath: string
- the path to the given node starting with the project rootchildren: nodeAPI[]
- a list of child nodes APIsfindChild(name: string): nodeAPI
- searches for the child node using its name and returns null if the node doesn't existnext: nodeAPI
- the API of the next node in the group. If the given node is the last one, null is returnedprev: nodeAPI
- the API of the previous node in the group. If the given node is the first one, null is returnednextNodes: nodeAPI[]
- a list of all next nodes in the group. If the given node is the last one, an empty list is returnedprevNodes: nodeAPI[]
- a list of all previous nodes in the group. If the given node is the first one, an empty list is returnedvars: object
- the object that stores all static variables of the given nodedynamicVars: object
- the object that stores all dynamic variables of the given nodesetDynamicVar(name: string, value: any): void
- sets the name dynamic variable with a certain value for the given node
The interface of a
RequestStep
node is more advanced.request: object
- the object that stores the node's request configurationresponse: object
- the object that stores the results of the last request
active: string
- the active environment titlevars: object
- the object that stores the current environment variables
The code below shows how to pass data to all children of the current node.
const current = tm.currentNode;
const parent = current.parent;
if (!parent) {
console.warn(`Parent of ${current.path} not found`);
return;
}
const value = parent.vars['ID'];
if (!value) {
console.warn(`Node ${parent.path} hasn't have value for ID`);
return;
}
console.log(`Parent ID = ${value}`);
const setIDToNode = (node) => {
node.setDynamicVar('ID', value);
};
const traverseDescendants = (node, func, depth) => {
node.children.forEach((child) => {
func(node);
indent = '\t'.repeat(depth);
console.debug(
`${indent}${child.path}`,
`${indent}Value: ${child.dynamicVars['ID']}`
);
traverseDescendants(child, func, depth+1);
});
};
traverseDescendants(parent, setIDToNode, 0);
You can find a child node by its name using the
findChild
method:const current = tm.currentNode;
const scriptNode = current.parent.findChild(current.name);
assert.equal(current, scriptNode);
Here is how you can generate a random string identifier using the
faker
library and setting as the next node's dynamic variable UUI
. Once you've run the script, you can reference this variable in an URL, request body, etc.const current = tm.currentNode;
const uuid = faker.random.uuid();
const anotherNode = current.next;
anotherNode.setDynamicVar('UUID', uuid);
{
"type": "object",
"properties": {
"type": {
"description": "Type of Script node",
"const": "Script",
"type": "string"
},
"script": {
"description": "Javascript code",
"type": "string"
},
"children": {
"description": "List of children names",
"type": "array",
"items": {
"type": "string"
},
"default": []
},
"variables": {
"$ref": "#/definitions/NodeVariables",
"description": "Node variables dictionary"
},
"name": {
"description": "Node name",
"type": "string"
}
},
"required": [
"children",
"name",
"script",
"type",
"variables"
],
"definitions": {
"NodeVariables": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}
Last modified 3yr ago