Skip to main content

Scripting and tests Pro / Enterprise

With the scripting feature of Kreya, you can define JavaScript code that runs when an operation is invoked. Among other things, it allows you to create tests and view the results of them.

Defining scripts

Scripts can be defined in the Script tab. The script will run when the operation is sent. Note that the script editor supports autocompletion, simply press Ctrl+Space to bring it up.

As you can see in the screenshot, a global kreya object is provided. It currently defines two functions:

FunctionDescriptionArguments
trace(msg)Use this function to log messages to the Trace tab.
  • message: The message to log
test(name, action)Use this function to define tests.
  • name: The name of the test
  • action: The test action
sleep(millisecondsTimeout)Use this function to sleep for an certain length of time.
  • millisecondsTimeout: Milliseconds to sleep.

In addition, Kreya also includes the chai module for defining tests in JavaScript.

Environment

You may want to access the current Kreya environment in a script. This is available through the kreya.environment.active object.

PropertyDescription
content: anyContains the merged content of the active environment.
id: stringA unique id of the environment.
name: stringThe name of the environment.

User variables

Sometimes, you may need to share data between different operations. For example, if you have a process where you create an entity → update the entity → delete the entity, changing the entity ID manually each time becomes annoying. It would be much easier if you could temporarily store the ID of the created entity and reference it from the other two operations. For such use cases, user variables are the way to go.

The feature is available through the kreya.variables object.

FunctionDescriptionArguments
set(key, value)Sets a variable.
  • key: The key of the variable. Should only contain letters, numbers and underscores.
  • value: The value of the variable. Property names of nested objects are subject to the same naming restrictions as those of key.
get(key)Gets the value of a variable.
  • key: The key of the variable.
has(key)Checks whether the specified variable exists.
  • key: The key of the variable.
keys()Returns the keys of all stored variables.
delete(key)Deletes the specified variable.
  • key: The key of the variable.

User variables can also be referenced via templating, for example {{ vars.my_variable }}.

gRPC specific hooks

To write scripts and tests for gRPC, use the built-in kreyaGrpc object. It currently provides two functions:

FunctionDescriptionCallback object properties
onResponse(callback)Use this function to register a callback which will be called every time a response arrives.
  • content: The content of the response, deserialized as a JavaScript object
  • size: The response size in bytes
  • index: The zero-based response index (0 for the first response, 1 for the next one, ...)
onCallCompleted(callback)Use this function to register a callback which will be called when the gRPC call completes.
  • durationMillis: Duration of the call in milliseconds
  • status: The status of the call
  • responseCount: The count of received responses
  • headers: The received headers
  • trailers: The received trailers

gRPC example

import { expect } from 'chai';

let names = [];

kreyaGrpc.onResponse(msg => {
kreya.test('Size should be ok', () => expect(msg.size).to.be.gt(10));
kreya.test('Greeting should start with Hello', () => expect(msg.content.greeting.startsWith('Hello')).to.be.true);

// Store all received names to use them when the gRPC call completes
names.push(msg.content.greeting.substr('Hello '.length));
});

kreyaGrpc.onCallCompleted(call => {
kreya.test('Status should be ok', () => expect(call.status.code).to.equal(0));

kreya.trace(`Got ${call.responseCount} names: ${names.join(', ')}`);
});

REST specific hooks

To write scripts and tests for REST, use the built-in kreyaRest object. It currently provides one function:

FunctionDescriptionCallback object properties
onCallCompleted(callback)Use this function to register a callback which will be called when the REST call completes.
  • durationMillis: Duration of the call in milliseconds
  • status: The status of the call
  • response: Information about the received response*
  • headers: The received headers
  • trailers: The received trailers
onStreamEventReceived(callback)Use this function to register a callback which will be called when a REST streamed event is received.
  • id: The id of the server sent event
  • event: The event string of the server sent event
  • data: The data of the event

* The response object contains the following properties:

  • size: The response size in bytes
  • contentType: The content type, read from the Content-Type HTTP header
  • content: The deserialized response content as a JavaScript object
  • rawContentText: The response content as text
  • rawContentBytes: The response content as an Uint8Array
info

Accessing the content, rawContentText or rawContentBytes will throw an exception if the response size is greater than 10 MiB. Accessing the content will throw if the response content is not valid JSON or YAML.

REST example

import { expect } from 'chai';

kreyaRest.onCallCompleted(call => {
kreya.trace('The REST call completed.');

kreya.test('Status code', () => expect(call.status.code).to.equal(200));
kreya.test('status is success', () => expect(call.status.isSuccess).to.be.true);

kreya.test('Content type', () => expect(call.response.contentType).to.eq('application/json'));

const curlyBraceCharCode = '{'.charCodeAt(0);
kreya.test('Byte content first entry should be a curly brace', () => expect(call.response.rawContentBytes[0]).to.eq(curlyBraceCharCode));
kreya.test('Text content first char should be a curly brace', () => expect(call.response.rawContentText[0]).to.eq('{'));

kreya.test('Deserialized number should equal', () => expect(call.response.content.myInt).to.eq(26));
});

Viewing test results

The test results show up in the Tests tab. It will automatically show how many of the tests passed in the tab header. Should a test fail, Kreya will display the reason of the failure.

Sharing code

A typical scenario is to share test code among multiple operations. This is where importing external modules comes in handy. As an example, place a file named shared.js in the Kreya project directory with the following content:

shared.js
import { expect } from 'chai';

export function init() {
kreya.trace('hello from shared file');
}

export function addTestForSuccessfulResponse() {
kreyaRest.onCallCompleted(call => {
kreya.test('status is success', () => expect(call.status.isSuccess).to.be.true);
kreya.test('Status code', () => expect(call.status.code).to.equal(200));
});
}

Then, in the Script tab of a REST operation, we can import these shared functions:

import { init, addTestForSuccessfulResponse } from 'shared.js';

init();
addTestForSuccessfulResponse();

Importing external modules

While Kreya bundles the chai module, that may not be enough for some use cases. That is why importing external modules is also possible. Currently, only external ESM modules are supported. You may import external modules directly via URL or as local dependencies.

// Bundled with Kreya
import { expect } from 'chai';

// Imported directly from an URL
import { snakeCase } from 'https://esm.sh/change-case';

const snakeCased = snakeCase('my message');
kreya.test('Snake case', () => expect(snakeCased).to.eq('my_message'));

// Use a local module. Kreya searches in the project directory and parent directories.
// Either the module is declared in a package.json file (the module must be installed, Kreya does not perform a package restore)
// or the file is directly available as '{module-name}.js` or `{module-name}/index.js`
import { formatDistance } from 'date-fns';

const dayDistance = formatDistance(new Date(2020, 1, 1), new Date(2020, 1, 3), {
addSuffix: true,
});
kreya.test('Day distance', () => expect(dayDistance).to.eq('2 days ago'));