TestCafe
02 / 02

Roles, Request Mocking & CI

Roles, Request Mocking & CI

Roles — Reusable Auth

import { Role, Selector } from 'testcafe';

const regularUser = Role('https://example.com/login', async t => {
  await t
    .typeText('#email', 'user@example.com')
    .typeText('#password', 'secret123')
    .click('button[type=submit]');
});

test('authenticated user sees dashboard', async t => {
  await t.useRole(regularUser);  // TestCafe caches/reuses the login state
  await t.expect(Selector('.dashboard').exists).ok();
});

Mocking API Responses

import { RequestMock } from 'testcafe';

// Deterministically test error-handling UI without needing the real
// backend to actually be coaxed into a 500 error state
const mockServerError = RequestMock()
  .onRequestTo('https://api.example.com/orders')
  .respond({ error: 'Internal Server Error' }, 500);

test.requestHooks(mockServerError)('shows error banner on API failure', async t => {
  await t.expect(Selector('.error-banner').innerText).contains('Something went wrong');
});

Screenshots & Debugging

test('checkout flow', async t => {
  await t.click('#add-to-cart');
  await t.takeScreenshot();  // saved to the configured screenshots directory
  // TestCafe can also auto-screenshot on test failure via CLI config —
  // useful for debugging a CI run after the fact

Concurrency & Test Isolation

Running with -c N against a shared test environment/database risks concurrent tests interfering with each other — two tests creating a user with the same expected username, or one test's cleanup deleting data another still needs. Generate unique, randomly-suffixed test data per run and avoid shared mutable fixtures between concurrently-running tests.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free