Hooks

Note

This article describes test hooks. Read the Request Interception Guide for more information on request hooks.

Hooks are reusable code sequences that run before or after tests and fixtures. They often set up the testing environment (e.g., authenticate the user) or restore the testing environment after the end of a test (e.g., remove a database object).

You can add hooks to individual test definitions and fixture definitions. Additionally, you can define hooks that apply to your entire test suite inside a JavaScript configuration file.

Test Hooks

Specify hooks for individual tests with the test.before and test.after methods. Test hooks run after the browser loads the test web page. Test Hooks allow for the same types of actions as the test body.

test
    .before( async t => {
        await t
            .useRole(admin)
            .click('#open-management-console');
    })
    ('MyTest', async t => { /* ... */ })
    .after( async t => {
        await t.click('#delete-data');
    });

Specify a beforeEach/afterEach hook fixture hook to attach the same hook to all tests in the fixture. Individual test hooks override fixture-wide hooks.

Fixture Hooks

There are two kinds of fixture hooks.

  • The beforeEach and afterEach hooks run before or after each of the tests in the fixture. They can access the test page and perform browser actions, just like regular test hooks.
  • The before and after fixture hooks run before or after the contents of the fixture. They cannot access the browser.

beforeEach/afterEach

If you want to execute an action sequence every time a test from a particular fixture begins or ends, attach a beforeEach / afterEach hook to that fixture.

fixture `My fixture`
    .page `http://example.com`
    .beforeEach( async t => {
        await t
            .useRole(admin)
            .click('#open-management-console');
    })
    ('MyTest', async t => { /* ... */ })
    .afterEach( async t => {
        await t.click('#delete-data');
    });

before/after

If you want to execute a sequence of actions before or after the contents of the fixture, attach a before or after hook to that fixture.

Unlike test hooks, fixture hooks run in between tests and do not have access to the test page. Use them to perform server-side operations.

Specify hooks for individual fixtures with the fixture.before and fixture.after methods.

import { utils } from './my-utils.js';

fixture `My fixture`
    .page `http://example.com`
    .before( async ctx => {
        utils.populateDb(ctx.dbName);
    })
    .after( async ctx => {
        utils.dropDb(ctx.dbName);
    });

Global Hooks

You can define global before and after hooks in a JavaScript configuration file. TestCafe executes these hooks for every test or fixture in the test suite, before it executes other hooks.

module.exports = {
    hooks: {
        fixture: {
            before: async (ctx) => {
                // your code
            },
            after: async (ctx) => {
                // your code
            }
        },
        test: {
            before: async (t) => {
                // your code
            },
            after: async (t) => {
                // your code
            }
        }
    }
};

Test Hook Order and Priority

TestCafe executes global before and after hooks prior to other before and after hooks. Global hooks do not stop the execution of other test hooks.

Test-specific before and after hooks override fixture-wide beforeEach and afterEach hooks.

Share Data Between Hooks and Test Code

Fixture objects and test objects contain the ctx (context) property.

You can use the ctx property to store and access data across hooks and tests.

Access the test context object in the main body of the test and all of its hooks — test hooks, fixture-wide hooks and global hooks.

You can access the fixture context object anywhere inside the fixture: in fixture hooks, test hooks, and all the tests.

Use the t.ctx method to access test context.

fixture `Fixture1`
    .beforeEach(async t  => {
        t.ctx.someProp = 123;
    });

test
    ('Test1', async t => {
        console.log(t.ctx.someProp); // > 123
    })
    .after(async t => {
         console.log(t.ctx.someProp); // > 123
    });

Use the t.fixtureCtx property to access fixture context.

fixture `Fixture1`
    .before(async ctx  => {
        ctx.someProp = 123;
    })
    .after(async ctx  => {
        console.log(ctx.newProp); // > abc
    });

test('Test1', async t => {
    console.log(t.fixtureCtx.someProp); // > 123
});

test('Test2', async t => {
    t.fixtureCtx.newProp = 'abc';
});