Chain modifiers

Chain modifier are added to manipulate and check for specific aspects of test subjects or change the behavior of test operations.

Subjects can be found in test subjects.


List of chain modifiers:

  • contain - check if subject contains an expected string
  • endWith - check if subject ends with an expected string
  • equal - check is subject is equal to expected value
  • exist - check if subject exists
  • hasExited - check if application has exited
  • interval - set interval between chain executions
  • isPaused - check if the state of video is paused
  • isPlaying - check if the state of video is playing
  • isStopped - check if the state of video is stopped
  • match - compare state of element to defined values
  • matchJS - check if subject matches JS expression
  • matchRepo - compare state of element with element repository state
  • not - universal negation
  • repeat - repeat execution of a chain
  • requestMatches - check if network request matches data
  • responseMatches - check if network response matches data
  • startWith - check if subject starts with an expected string
  • timeout - timeout to wait until chain becomes resolved
  • until - execute chain until condition is satisfied
  • visible - check if an element is visible
  • wasMade - network requests in entire request log
  • willBeMade - network requests excluding previously matched requests

contain

Checks if subject (as a string) contains an expected string.

Alias .contains().

/**
 * @param {string} expectedValue
 * @throws {SuitestError} if subject is unavailable
 * @returns {ChainablePromise.<void|boolean>}
 */
async function contain(expectedValue) {}

await suitest
    .cookie('cookieName')
    .contains('someValue');

endWith

Checks if subject (as a string) ends with an expected string.

Alias .endsWith().

/**
 * @param {string} expectedValue
 * @throws {SuitestError} if subject is unavailable
 * @returns {ChainablePromise.<void|boolean>}
 */
async function endsWith(expectedValue) {}

await suitest
    .cookie('cookieName')
    .endsWith('someValue');

equal

Checks if a subject is equal to an expected value.

Alias .equals().

/**
 * @param {string} expectedValue
 * @throws {SuitestError} if subject is unavailable
 * @returns {ChainablePromise.<void|boolean>}
 */
async function equal(expectedValue) {}

await suitest
    .cookie('cookieName')
    .equals('Some Value');

exist

Checks if a subject exists. Can be used with not to change to "does not exist".

Alias .exists().

/**
 * @returns {ChainablePromise.<void|boolean>}
 */
async function exists() {}

// Check if element exists
await suitest
    .element('Element name')
    .exists();

// Check if cookie does not exist
await suitest
    .cookie('cookieName')
    .doesNot()
    .exist();

hasExited

Checks if the application has exited. hasExited can only be used on application.

/**
 * @throws {SuitestError} in case subject is different from application
 * @returns {Promise.<void|boolean>}
 */
async function hasExited() {}

// Wait until application has exited but at most 2s
await suitest
    .application()
    .hasExited();

interval

Set interval (in ms) between chain executions, used in conjunction with press, click, sendText and repeat.

/**
 * @param {number} ms
 * @returns {ChainablePromise.<void|boolean>}
 */
async function interval(ms) {}

// Press OK 10x every 10s
await suitest.press(suitest.VRC.OK)
    .repeat(10)
    .interval(10000);

isPaused

Used in conjunction with video, checks video status.

const isVideoPaused = await suitest.video().isPaused();

await suitest.assert.video().isPaused();

isPlaying

Used in conjunction with video, checks video status.

const isVideoPlaying = await suitest.video().isPlaying();

await suitest.assert.video().isPlaying();

isStopped

Used in conjunction with video, checks video status.

const isVideoStopped = await suitest.video().isStopped();

await suitest.assert.video().isStopped();

match

match is used in conjunction with element and video, it compares the state of the element with the defined properties set.

For the properties available refer to constant element properties.

For properties with enumerable values (VIDEO_STATE, VISIBILITY_STATE, CONTENT_MODE, ELEMENT_STATE, TEXT_ALIGNMENT, BORDER_STYLE) value must be provided as Suitest constant.

Alias .matches().

/**
 * @param {Symbol} name - properties to match against
 * @param {string|number|Symbol} [val] - properties to match against. Defaults to VALUE.REPO
 * @param {string} [type] - how to compare property, defaults to COMP.EQUAL
 * @param {string} [deviation] - how accurate type should be, only if value is of type number and type is COMP.APPROX
 * @returns {ChainablePromise.<void|boolean>}
 */
async function match(name, val, type, deviation) {}
async function match({name, val, type, deviation}) {}
async function match([{name, val, type, deviation}/*, ...*/]) {}

// Check if element's width and height match snapshot from element repo, top position as in repo +- 20px and custom background color
const element = suitest.element('repo-id');

await element.matches(suitest.PROP.WIDTH);
await element.matches(suitest.PROP.HEIGHT);
await element.matches(suitest.PROP.TOP, suitest.VALUE.REPO, suitest.COMP.APPROX, 20);
await element.matches(suitest.PROP.BG_COLOR, '#F00');

// Same with object syntax
await suitest.element('repo-id').matches({
    name: suitest.PROP.WIDTH,
});
await suitest.element('repo-id').matches({
    name: suitest.PROP.HEIGHT,
});
await suitest.element('repo-id').matches({
    name: suitest.PROP.TOP,
    val: suitest.VALUE.REPO,
    type: suitest.COMP.APPROX,
    deviation: 20,
});
await suitest.element('repo-id').matches({
    name: suitest.PROP.BG_COLOR,
    val: '#F00',
});
await suitest.element({css: '#repo-id'}).matches({
    [PROP.BG_COLOR]: 'red',
    [PROP.HREF]: 'http://somelink',
    borderWidth: 233,
});

// Preferred syntax as only one command and one server communication request is executed.
await suitest.element('repo-id').matches([
    PROP.WIDTH,
    PROP.HEIGHT,
    {
        name: PROP.TOP,
        val: VALUE.REPO, // could be omitted
        type: COMP.APPROX,
        deviation: 20,
    },
    {
        name: PROP.BG_COLOR,
        val: '#F00',
    },
    {
        [PROP.CLASS]: 'friendlyClass',
        [PROP.TEXT_CONTENT]: 'Lorem ipsum',
    }
]);

.match method can accept objects with name property, conflicts may occur in .match arguments due to the dictionary being able to contain name key as well.

matchJS

Checks if subject matches a JS expression. Can be used on the following subjects: element, video, location and cookie.

Alias .matchesJS().

/**
 * @param {string|Function} matcher
 * @throws {SuitestError} if subject is unavailable
 * @throws {TypeError} if matcher produced error
 * @returns {ChainablePromise.<void|boolean>}
 */
async function matchesJS(matcher) {}

// Pass function as parameter
await suitest
    .cookie('cookieName')
    .matchesJS(function(cookieValue) { return /foo|bar/i.test(cookieValue); });

// Pass string as parameter
await suitest
    .cookie('cookieName')
    .matchesJS('function (cookieValue) { return /foo|bar/i.test(cookieValue) }');

matchRepo

matchRepo is used in conjunction with element and video, it compares the state of the element with the state in the Element Repository with the current state within the app.

For the properties available refer to constant element properties.

Alias .matchesRepo().

/**
 * @param {Symbol} name - properties to match against
 * @param {string} [type] - how to compare property, defaults to COMP.EQUAL
 * @param {string} [deviation] - how accurate type should be, only if value is of type number and type is COMP.APPROX
 * @returns {ChainablePromise.<void|boolean>}
 */
async function matchRepo(name, type, deviation) {}
async function matchRepo({name, type, deviation}) {}
async function matchRepo([{name, type, deviation}/*, ...*/]) {}

// Alias for repo-only elements - same syntax as matches, except "value" argument is always omitted
await suitest
    .element('repo-id')
    .matchesRepo([
        {
            name: suitest.PROP.BG_COLOR,
            val: '#F00', // invalid, value is always taken from repo. Use matches for this
        },
        {
            name: suitest.PROP.LEFT,
            type: suitest.COMP.EQUAL,
        },
    ]);

not

Universal negation of other chain commands. Can be used with equal, contain, starWith, endWith, exist, matchJs, jsExpression wasMade and willBeMade.

Aliases .doesNot() and .isNot().

/**
 * @returns {ChainablePromise.<void|boolean>}
 */
async function not() {}

// Wait until cookie does not equal '1', but at most 3s
await suitest
    .cookie('cookieName')
    .doesNot()
    .equal('1')
    .timeout(3000);

repeat

Repeat sets how many times a chain is executed, used in conjunction with press, click, sendText and interval.

/**
 * @param {number} times
 * @returns {ChainablePromise.<void|boolean>}
 */
async function repeat(times) {}

// Press OK 10x every 10s
await suitest.press(suitest.VRC.OK)
    .repeat(10)
    .interval(10000);

requestMatches

requestMatches is used in conjunction with networkRequest.

/**
 * @param {string|Symbol} name - properties to match against (some of names can be found in NETWORK_PROP)
 * @param {string|number} value - properties to match against.
 * @param {string} [type] - how to compare property, defaults to COMP.EQUAL
 * @returns {ChainablePromise.<void|boolean>}
 */
async function requestMatches(name, value, type);
async function requestMatches({name, value, type});
async function requestMatches([{name, val, type}/*, ...*/]);
/**
 * @param {Object.<name, value>} keyValueHash
 * @param {string|Symbol} name - properties to match against (some of names can be found in NETWORK_PROP)
 * @param {string|number} value - properties to match against.
 * @returns {ChainablePromise.<void|boolean>}
 */
async function requestMatches(keyValueHash);
await networkRequest().requestMatches('propName', 'propVal');

await networkRequest().requestMatches('propName', 'propVal', COMP.NOT_CONTAIN);

await networkRequest().requestMatches(NETWORK_PROP.METHOD, NETWORK_METHOD.GET);

await networkRequest().requestMatches({
    name: NETWORK_PROP.BODY,
    val: 'body'
});

await networkRequest().requestMatches({
    name: NETWORK_PROP.BODY,
    val: 'body',
    type: COMP.START
});

await networkRequest().requestMatches({
    [NETWORK_PROP.BODY]: 'some body',
    [NETWORK_PROP.METHOD]: NETWORK_METHOD.GET,
    'Any-Header': 'header-value'
});

await networkRequest().requestMatches([
    {
        name: NETWORK_PROP.METHOD,
        val: NETWORK_METHOD.GET,
    },
    {
        [NETWORK_PROP.BODY]: '{}',
        'Any-Header': 'header-value'
    }
]);

responseMatches

responseMatches is used in conjunction with networkRequest.

/**
 * @param {Object.<name, value>} keyValueHash
 * @param {string|Symbol} name - properties to match against (some of names can be found in NETWORK_PROP)
 * @param {string|number} value - properties to match against.
 * @returns {ChainablePromise.<void|boolean>}
 */
async function responseMatches(keyValueHash);
/**
 * @param {string|Symbol} name - properties to match against (some of names can be found in NETWORK_PROP)
 * @param {string|number} [value] - properties to match against.
 * @param {string} [type] - how to compare property, defaults to COMP.EQUAL
 * @returns {ChainablePromise.<void|boolean>}
 */
async function responseMatches(name, value, type);
async function responseMatches({name, value, type});
async function responseMatches([{name, val, type}/**, ...*/]);
await networkRequest().responseMatches('propName', 'propVal');

await networkRequest().responseMatches(NETWORK_PROP.STATUS, 200);

await networkRequest().responseMatches({
    name: NETWORK_PROP.BODY,
    val: 'body',
});

await networkRequest().responseMatches({
    name: NETWORK_PROP.BODY,
    val: 'body',
    type: COMP.START
});

await networkRequest().responseMatches({
    [NETWORK_PROP.BODY]: 'some body',
    [NETWORK_PROP.STATUS]: 200,
    'Any-Header': 'header-value'
});

await networkRequest().responseMatches([
    {
        name: NETWORK_PROP.STATUS,
        val: 200
    },
    {
        [NETWORK_PROP.BODY]: '{}',
        'Any-Header': 'header-value'
    }
]);

startWith

Checks if subject (as a string) starts with an expected string.

Alias .startsWith().

/**
 * @param {string} expectedValue
 * @throws {SuitestError} if subject is unavailable
 * @returns {ChainablePromise.<void|boolean>}
 */
async function startWith(expectedValue) {}

// Cookie value starts with a certain string
await suitest
    .cookie('cookieName')
    .startsWith('value');

timeout

Set a timeout (in ms) or wait time for the chain to become resolved if it's not resolved an assertion error will be thrown.

Similar to assertion with timeout in Suitest Test editor. By default the timeout is set to 2000 ms, therefore if you do not include .timeout(ms), the chain will implicitly have .timeout(2000).

/**
 * @param {number} ms - time in milliseconds
 * @throws {SuitestError} - something unexpected happened while polling chain
 * @returns {ChainablePromise.<void|boolean>}
 */
async function timeout(ms) {}

// Element exists
await suitest
    .element('Some Element')
    .exists()
    .timeout(0);

// Wait until element exists but at most 10s
await suitest
    .element('Some Element')
    .exists()
    .timeout(10000);

until

Executes the chain with given interval, max count number of repeats until evaluation chain is satisfied. Accepts another chain as only parameter.

Please note that the condition is being evaluated before each run (including the first one). Therefore the application has to be already running before the first evaluation.

/**
 * @param {ChainablePromise} conditionChain - condition chain
 * @returns {ChainablePromise.<void|boolean>}
 */
async function until(conditionChain) {}

// Check if element 'menu' appeared on a page after clicking on 'openMenuButton' element, but at most 5 times with 1 second interval
await suitest.element('openMenuButton').click().until(
    suitest.element('menu').exists()
).interval(1000).repeat(5);

// Check if application has exited after pressing 'power' button several times
await suitest.assert.press(suitest.VRC.POWER).until(
    suitest.application().hasExited()
).repeat(5).interval(2000);

visible

Use in conjunction with element and video, to check if element is visible.

async function visible() {}

await assert.element('logo').visible();

wasMade

Used in conjunction with networkRequest, check for network requests in entire request log.

/**
 * To be used with networkRequest chain - include previously made Ajax requests
 */
async function wasMade() {}

await suitest.networkRequest()
    .contains('http://suite.st')
    .wasMade();

willBeMade

Used in conjunction with networkRequest, checks for network requests excluding previously matched requests.

/**
 * To be used with networkRequest chain - exclude previously made Ajax requests
 */
async function willBeMade() {}

await suitest.networkRequest()
    .contains('http://suite.st')
    .willBeMade();