Fixtures, Selectors & Actions
Basic Test Structure
import { Selector } from 'testcafe';
fixture('Login Page')
.page('https://example.com/login');
test('user can log in', async t => {
await t
.typeText(Selector('#email'), 'user@example.com')
.typeText(Selector('#password'), 'secret123')
.click(Selector('button[type=submit]'))
.expect(Selector('h1').innerText).eql('Welcome');
});
// No WebDriver, no driver binaries — TestCafe injects test code into
// the page via a local proxy. No explicit waitForSelector needed here:
// actions automatically wait for the target element to exist/become
// actionable before running.ClientFunction
import { ClientFunction } from 'testcafe';
const getCurrentUrl = ClientFunction(() => window.location.href);
const getLocalStorageItem = ClientFunction((key) => window.localStorage.getItem(key));
test('redirects after login', async t => {
await t.click(Selector('button[type=submit]'));
await t.expect(getCurrentUrl()).contains('/dashboard');
await t.expect(getLocalStorageItem('authToken')).notEql(null);
});Running Tests
testcafe chrome tests/ # single browser
testcafe chrome,firefox tests/ # multiple browsers, one run
testcafe chrome:headless tests/ # no visible window — good for CI
testcafe chrome tests/ -c 4 # 4 concurrent browser instances —
# tests must be independent for this to be safeKeep your own version of these notes — editable, searchable, and organised by your stack.
Start free