Testland
Browse all skills & agents

testcafe-testing

Authors TestCafe E2E tests - `npm install testcafe`, fixture/test syntax, `Selector` API for queries, automatic-waits, no WebDriver required (TestCafe injects scripts via a proxy), supports any browser including remote / cloud farms. Use when the team prefers a no-WebDriver architecture and one of TestCafe's specific features (e.g., role-based auth) matters.

Install with skills.sh (any agent)

npx skills add testland/qa --skill testcafe-testing
View source

testcafe-testing

Overview

TestCafe (DevExpress) is an alternative E2E framework that doesn't use WebDriver. Instead, it injects a JavaScript proxy into the browser; tests run in Node and the proxy synchronizes browser state.

This means:

  • No WebDriver installation.
  • Cross-browser without per-browser setup.
  • No per-browser binary downloads.

The trade-off: the proxy approach has its own quirks; less mainstream than Playwright / Cypress / Selenium.

When to use

  • The team has invested in TestCafe.
  • A no-WebDriver architecture is preferred (e.g., shared CI environments where installing browser drivers is constrained).
  • TestCafe's role-based auth feature is valuable (manage multi-user scenarios cleanly).

For new projects in 2026+: Playwright is the broader-supported choice.

Step 1 - Install

npm install --save-dev testcafe

No browser-driver setup; TestCafe uses installed browsers directly.

Step 2 - Author a test

// tests/checkout.test.js
import { Selector } from 'testcafe';

fixture('Checkout flow').page('http://localhost:3000');

test('completes checkout', async (t) => {
  await t
    .typeText('[data-testid=email]', 'user@example.com')
    .typeText('[data-testid=password]', 'pwd')
    .click('button[type=submit]');

  await t.expect(Selector('h1').withText('Welcome').exists).ok();

  await t
    .navigateTo('/products/BOOK-001')
    .click('[data-testid=add-to-cart]');

  await t.expect(Selector('[data-testid=cart-count]').textContent).eql('1');
});

The fluent API (t.X.Y.Z) auto-waits.

Step 3 - Selector API

// Basic
const heading = Selector('h1');

// CSS
const button = Selector('button[type=submit]');

// By text
const submitButton = Selector('button').withText('Submit');

// By attribute
const cartCount = Selector('[data-testid=cart-count]');

// Chained
const linkInsideHeader = Selector('header').find('a').withText('Sign in');

// With state (visible, focused, etc.)
const visibleError = Selector('.error').filterVisible();

Step 4 - Roles (multi-user auth)

TestCafe's distinguishing feature: Roles - encapsulated auth state for switching between users in tests.

import { Role } from 'testcafe';

const adminUser = Role('http://localhost:3000/login', async t => {
  await t
    .typeText('[data-testid=email]', 'admin@example.com')
    .typeText('[data-testid=password]', 'admin-pwd')
    .click('button[type=submit]');
});

const regularUser = Role('http://localhost:3000/login', async t => {
  await t
    .typeText('[data-testid=email]', 'user@example.com')
    .typeText('[data-testid=password]', 'user-pwd')
    .click('button[type=submit]');
});

test('admin sees admin panel', async t => {
  await t.useRole(adminUser).expect(Selector('a').withText('Admin').exists).ok();
});

test('regular user does not see admin panel', async t => {
  await t.useRole(regularUser).expect(Selector('a').withText('Admin').exists).notOk();
});

Roles cache the auth state - subsequent useRole calls don't re-run the login.

Step 5 - Run

# All tests, default browser (Chrome)
npx testcafe chrome tests/

# Multiple browsers
npx testcafe chrome,firefox tests/

# Headless
npx testcafe chrome:headless tests/

# Specific test
npx testcafe chrome tests/checkout.test.js

Step 6 - Reporters

# JUnit XML (CI-friendly)
npx testcafe chrome:headless tests/ --reporter junit:reports/junit.xml

# Multiple reporters
npx testcafe chrome:headless tests/ --reporter spec,junit:reports/junit.xml

Step 7 - Network mocking

import { Selector, RequestMock } from 'testcafe';

const mock = RequestMock()
  .onRequestTo('https://api.example.com/orders/123')
  .respond({ orderId: 123, status: 'shipped' }, 200, {
    'access-control-allow-origin': '*',
  });

fixture('Order page').page('http://localhost:3000').requestHooks(mock);

test('shows shipped status', async (t) => {
  await t.expect(Selector('[data-testid=status]').textContent).eql('shipped');
});

Step 8 - CI integration

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v4
        with: { node-version: '22' }
      - run: npm ci
      - run: npx testcafe chrome:headless tests/ --reporter junit:reports/junit.xml
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: testcafe-reports
          path: reports/

The JUnit XML feeds junit-xml-analysis (in the qa-test-reporting plugin).

Anti-patterns

Anti-patternWhy it failsFix
Manual await new Promise(r => setTimeout(r, 2000))Defeats auto-wait; flaky.Trust TestCafe's automatic synchronization.
Inline credentials in testsSecrets in code.Roles + env vars (Step 4).
Skipping --reporterDefault spec output not CI-parseable.--reporter junit:reports/... (Step 6).
Using TestCafe for unit-test-shaped scopeE2E framework overhead for unit tests.Use the unit framework (Jest, etc.) for unit tests.

Limitations

  • Smaller community than Playwright / Cypress. Stack Overflow hit rate lower.
  • Proxy-based architecture has quirks. Some sites that block iframe / proxy techniques don't work cleanly.
  • No native mobile support. Mobile via emulation only.
  • Roles cache may stale. Re-evaluate cache invalidation when auth changes.

References

  • TestCafe at testcafe.io.
  • playwright-testing, cypress-testing, selenium-testing - alternatives.

Related skills

browserstack-automate

Author and run E2E tests on BrowserStack Automate - cloud grid covering 3000+ real device + browser combinations. Covers BROWSERSTACK_USERNAME + ACCESS_KEY auth, hub URL https://hub-cloud.browserstack.com/wd/hub, W3C capabilities + bstack:options (projectName, buildName, sessionName), BrowserStackLocal for testing against localhost / internal environments, parallel session limits, and CI integration. Use for cross-browser regression on real devices + browsers - distinct from running a single test framework locally, and from a matrix runner limited to the browser engines bundled on the local machine.

cypress-testing

Authors and improves Cypress E2E tests - installs Cypress, configures `cypress.config.ts`, authors `cy.*` command chains, refactors existing specs (`cy.wait(ms)` sleeps into assertions, repeated flows into `cy.session` custom commands), and debugs with the time-travel GUI; Cypress Cloud for parallel runs and recording. Use for both greenfield test authoring and improving hand-written specs already in the codebase. For automated refactor of raw Cypress Studio recordings specifically, use a dedicated codegen-review pass.

lambdatest-automate

Author and run E2E tests on LambdaTest - cloud grid for cross-browser + real-device testing with W3C WebDriver, Cypress, Playwright, and Appium support. Covers LT_USERNAME + LT_ACCESS_KEY auth, hub URL hub.lambdatest.com/wd/hub, W3C capabilities + LT:Options dict (build, name, project, smartUI, network, console, video, tunnel), LambdaTest Tunnel for internal apps. Use for cross-browser regression with LambdaTest as the cloud grid; complements BrowserStack + Sauce Labs.

playwright-testing

Authors and remediates Playwright E2E tests across Chromium, Firefox, WebKit - `npm init playwright@latest` scaffolding, `playwright.config.ts` browser projects, accessibility-first locators (`getByRole`/`getByLabelText`) to replace brittle CSS selectors, web-first assertions to eliminate `waitForTimeout` flakiness, Page Object pattern, trace viewer debugging, sharded parallel execution with merged HTML reporting, and GitHub Actions CI integration. Use for new test authoring, flakiness remediation, and CI setup; for reviewing codegen output specifically, use a dedicated codegen-review pass.

puppeteer-testing

Authors browser automation scripts using Puppeteer - Chrome / Chromium-only headless / headed automation, Page object via `page.*` API, network interception, PDF generation, screenshot capture, scraping. Distinct from Playwright (Puppeteer's older sibling, Chrome-only) - use Puppeteer for Chrome-only browser automation tasks (scraping, generating PDFs from HTML, screenshot pipelines) where Playwright's multi-browser support is unneeded overhead. Use when a project already depends on `puppeteer` / `puppeteer-core`, or when a Chrome-only script must emit PDFs, screenshots, or scraped data rather than assert on a page.

saucelabs-automate

Author and run E2E tests on Sauce Labs - cloud grid for cross-browser + real-device testing with W3C WebDriver, Cypress, Playwright, and Appium support. Covers SAUCE_USERNAME + SAUCE_ACCESS_KEY auth, regional hub URLs (us-west-1 / us-east-4 / eu-central-1), W3C capabilities, sauce:options dict (build, name, screenResolution, tunnelName), Sauce Connect Proxy for internal-environment testing. Use for cross-browser regression with Sauce Labs as the cloud grid; complements BrowserStack + LambdaTest as alternative providers.

selenium-testing

Authors Selenium WebDriver tests in any of its 6+ supported languages (Java, Python, JavaScript, C#, Ruby, Kotlin, PHP) - picks the appropriate language binding, configures WebDriver per browser, uses `By.*` locators with the team's accessibility-first preference where supported, runs locally + via Selenium Grid for distributed execution, parses results to JUnit XML. Use for legacy Selenium-locked stacks; new projects pick Playwright or Cypress.

web-e2e-overview

Teaches web end-to-end testing from first principles: what browser-driven E2E covers and how it differs from unit and integration tests, a decision table for choosing between Playwright, Cypress, Selenium WebDriver, WebdriverIO, Puppeteer, TestCafe and the BrowserStack / Sauce Labs / LambdaTest cloud grids based on files already present in the repo, install and first-run commands for each, and the flakiness traps (fixed sleeps, CSS and XPath selectors, state shared between tests) that sink new suites. Use when a web application has no E2E coverage yet, when picking or replacing an E2E framework, or when a first browser test needs to go green end to end.

webdriverio-testing

Authors WebdriverIO E2E tests - `npm init wdio@latest` scaffolding, services architecture (sauce, browserstack, appium, devtools), reporters (spec, allure, junit), built-in Mocha/Jasmine/Cucumber framework integrations. WebdriverIO sits between Selenium (W3C protocol) and Playwright (modern API) - Selenium-protocol-compatible with rich plugin ecosystem. Use when the team needs WebDriver protocol + service-based device-farm integration.