Client Functions

TestCafe allows you to create client functions that can return any serializable value from the client side, such as the current URL or custom data calculated by a client script.


Do not modify the tested webpage within client functions. Instead, use test actions to interact with the page.

Client Function Constructor

Use the ClientFunction constructor to create a client function.

import { ClientFunction } from 'testcafe';
const getWindowLocation = ClientFunction(() => window.location);


Client functions cannot return DOM nodes. Instead, use selectors.

Run Asynchronous Client Code

TestCafe allows you to create client functions that run asynchronous code.

Pass a function that returns a Promise to the ClientFunction constructor. In this instance, the client function will complete only when the Promise resolves.

import { ClientFunction } from 'testcafe';

const performAsyncOperation = ClientFunction(() => {
    return new Promise(resolve => {
        window.setTimeout(resolve, 500); // some async operations

Execute Client Functions

Call the client function with the await keyword to execute it.

import { ClientFunction } from 'testcafe';

const getWindowLocation = ClientFunction(() => window.location);

fixture `My fixture`
    .page ``;

test('My Test', async t => {
    const location = await getWindowLocation();

Pass Parameters to Client Functions

This example shows the getLocationPart client function that returns a Location property value. The property name is passed as the locationPart parameter.

import { ClientFunction } from 'testcafe';

fixture `Parameterized Client Functions`

const getLocationPart = ClientFunction(locationPart => {
    return window.location[locationPart];

test('Parameterized Client Functions', async t => {
    await t

Overwrite Client Function Options

Overwrite client function options via the ClientFunction’s with method.

const cfWithDependency = cfWithoutDependency.with({
    dependencies: { foo: 'bar' }

One-Time Client Code Execution

To create a client function and execute it immediately (without saving), use the test controller’s eval method.

fixture `My fixture`
    .page ``;

test('My Test', async t => {
    const docURI = await t.eval(() => document.documentURI);

Import Functions to be Used as Client Function Dependencies

Assume you have a JS file (utils.js) with a function to be used as a client-function dependency in your test file.


export function getDocumentURI() {
    return document.documentURI;

Note that TestCafe processes test files with Babel internally. To avoid code transpiling issues, use the require function instead of the import statement to import client function dependencies.


import { ClientFunction } from 'testcafe';

const getDocumentURI = require('./utils.js').getDocumentURI;

fixture `My fixture`
    .page ``;

test('My test', async t => {
    const getUri = ClientFunction(() => {
        return getDocumentURI();
    }, { dependencies: { getDocumentURI } });

    const uri = await getUri();

    await t.expect(uri).eql('');

Call Client Functions from Node.js Callbacks

Client functions need access to the test controller to be executed. When called directly from a test function, they implicitly obtain the test controller.

However, if you need to call a client function from a Node.js callback that fires during a test run, you need to manually bind this function to the test controller.

You can use the boundTestRun option to do this.

import fs from 'fs';
import { ClientFunction } from 'testcafe';

fixture `My fixture`
    .page ``;

const getDataFromClient = ClientFunction(() => getSomeData());

test('Check client data', async t => {
    const boundGetDataFromClient = getDataFromClient.with({ boundTestRun: t });

    const equal = await new Promise(resolve => {
        fs.readFile('/home/user/tests/reference/clientData.json', (err, data) => {
            boundGetDataFromClient().then(clientData => {
                resolve(JSON.stringify(clientData) === data);

    await t.expect(equal).ok();

This approach only works for Node.js callbacks that fire during a test run. To ensure that the test function does not finish before the callback, suspend the test until the callback fires. You can introduce a promise and synchronously wait for it to complete, as shown in the example above.


The boundTestRun option requires the same test controller instance that is passed to the function used in the test declaration. It cannot work with imported test controllers.

For more information on imported test controllers, refer to the following section: Implicit Test Controller Use.

Client Function Limitations

Client function code does not support the following syntax and capabilities:

  • Generators or async/await syntax;

  • Access to variables defined in outer scope;


    You can use arguments to pass data within these functions, except for self-invoking functions that do not accept outside parameters.

    The return value is the only way to obtain data from client functions.

  • Iterable destructuring (e.g., spread, rest operators) on non-array objects (e.g. NodeList, HTMLCollection);

  • Property shorthands in the dependencies option;

  • Array methods Array.from(), Array.of();

  • Keyed collections: Map, Set, WeakMap, WeakSet;

  • Property shorthand for imported values.

Access Console Messages

The tested web application or a framework it uses may output log, warning, error and information messages into the browser console. TestCafe allows you to access them from test code with the t.getBrowserConsoleMessages method.

For instance, consider the React’s typechecking feature, PropTypes. You can use it to check that you assign valid values to the component’s props. If a PropTypes rule is violated, React posts an error into the JavaScript console.

The following example shows how to check the React prop types for errors with the t.getBrowserConsoleMessages method.

// check-prop-types.js
import { t } from 'testcafe';

export default async function () {
    const { error } = await t.getBrowserConsoleMessages();

    await t.expect(error[0]).notOk();

// test.js
import { Selector } from 'testcafe';
import checkPropTypes from './check-prop-types';

fixture `react example`
    .page `http://localhost:8080/`  //
    .afterEach(() => checkPropTypes());

test('test', async t => {
    await t
        .typeText(Selector('.form-control'), 'devexpress')


Check a Page URL

Certain test actions (clicks on buttons or links) can redirect a browser to another page. You may need to check if the desired page is open. For example, a login form test may need to verify if a particular web page opens after a user logs in.

You can create a client function and use the window.location.href property within it to return the URL of a page that is open on the client and then verify if the actual page URL matches the expected one using an assertion. The sample below demonstrates how to do this.

import { ClientFunction } from 'testcafe';

fixture `My Fixture`
    .page ``;

//Returns the URL of the current web page
const getPageUrl = ClientFunction(() => window.location.href);

test('Check the page URL', async t => {
    await t
        .typeText('#developer-name', 'John Smith')
        .click('#submit-button') //Redirects to the 'Thank you' page
        .expect(getPageUrl()).contains('thank-you'); //Checks if the current page URL contains the 'thank-you' string

Obtain a Browser Alias Within a Test

Sometimes you may need to determine a browser’s alias from within a test. For example, you configured a test tasks using the testCafe.createRunner function and specified several browsers where the test should run: runner.browsers(['safari','chrome']). However, the test logic should be different for different browsers. To do this, you need to detect which test instance corresponds to safari and which one corresponds to chrome.

To obtain a browser’s alias, create a client function that uses the navigator.userAgent property. This function returns the browser’s user-agent header, and you can use external modules (for example, ua-parser-js) to parse this header.

The following sample demonstrates how to create a conditional test logic based on the browser. Before running this test, install ua-parser-js by running npm install ua-parser-js.

import { ClientFunction } from 'testcafe';
import uaParser from 'ua-parser-js';

fixture `My fixture`
    .page ``;

//Returns a user-agent header sent by the browser
const getUA = ClientFunction(() => navigator.userAgent);

test('My test', async t => {
    const ua = await getUA();
    const browserAlias =uaParser(ua);

    //Some common actions

    //Conditional logic
    if (browserAlias === 'Chrome'){
        //Test logic for Chrome
        console.log('The browser is Chrome');
    else if (browserAlias === 'Safari'){
        //Test logic for Safari
        console.log('The browser is Safari');

Complex DOM Queries

Client functions can be helpful for complex DOM queries. For example, a tested page contains a table with some data, and you need to validate data from two columns only. To do this, obtain data from these columns and push them to an array. You can then compare the expected and returned arrays.

Below is a sample test for the page that contains a grid. The sample demonstrates how to create a client function that returns an array containing data from the grid’s Customer and Sale Amount columns.

import { ClientFunction } from 'testcafe';

fixture `Get sale amount`

    const getSalesAmount = ClientFunction(() => {
        const grid      = document.querySelector('.dx-datagrid-rowsview');
        const rowCount  = grid.querySelectorAll('.dx-data-row').length;
        const sales     = grid.querySelectorAll('td:nth-child(3)');
        const customers = grid.querySelectorAll('td:nth-child(7)');

        const array = [];

        for (let i = 0; i < rowCount; i++) {
                sales: sales[i].textContent,
                customer: customers[i].textContent

        return array;

test('My test', async t => {
    await t
            { sales: '$6,370', customer: 'Renewable Supplies' },
            { sales: '$4,530', customer: 'Apollo Inc' },
            { sales: '$1,110', customer: 'Johnson & Assoc' },
            { sales: '$6,600', customer: 'Global Services' },
            { sales: '$2,830', customer: 'Health Plus Inc' },
            { sales: '$6,770', customer: 'Gemini Stores' },
            { sales: '$1,460', customer: 'Discovery Systems' }

Use TestCafe Selector queries instead of native querySelector and querySelectorAll methods. You can pass Selector queries as client function dependencies. Chain selector methods for simpler query syntax.