Skip to main content
Writing tests with TestDriver is intuitive and straightforward. No more brittle CSS selectors or complex XPath expressions - just describe what you want in plain English.

Natural Language Selectors

Find elements the way humans think about them:
// ✅ Readable and maintainable
await testdriver.find('submit button').click();
await testdriver.find('email input in the login form').type('[email protected]');
await testdriver.find('delete button in the top right corner').click();
Natural language selectors are resilient to UI changes. If a button moves or the DOM structure changes, the same description often still works.

Chainable API

Write cleaner, more readable test code with method chaining:
// Find and interact in one fluid motion
await testdriver.find('Login button').click();
await testdriver.find('username field').type('admin');
await testdriver.find('password field').type('secret', { secret: true });
await testdriver.find('submit').click();

// Also works with hover interactions
await testdriver.find('Products menu').hover();
await testdriver.find('Laptops submenu').click();

// And other actions
await testdriver.find('checkbox item').doubleClick();
await testdriver.find('context menu item').rightClick();
All element methods are chainable:
  • .click() - Click the element
  • .hover() - Hover over the element
  • .doubleClick() - Double-click the element
  • .rightClick() - Right-click the element
  • .mouseDown() - Press mouse button down
  • .mouseUp() - Release mouse button
  • .type(text) - Type text into the element

Familiar Syntax

TestDriver integrates seamlessly with the test frameworks you already know and love:
  • Vitest
  • Jest
  • Mocha
import { test } from 'vitest';
import { chrome } from 'testdriverai/presets';

test('my test', async (context) => {
  const { testdriver } = await chrome(context, {
    url: 'https://example.com'
  });

  await testdriver.find('button').click();
});
No need to learn a new DSL or configuration format. TestDriver works with your existing test infrastructure.

Full TypeScript Support

First-class TypeScript support with complete IntelliSense and type safety:
import { test } from 'vitest';
import { chrome } from 'testdriverai/presets';

test('typed test', async (context) => {
  const { testdriver } = await chrome(context, {
    url: 'https://example.com'
  });

  const element = await testdriver.find('button');

  // ✅ Autocomplete works perfectly
  element.coordinates.x;
  element.coordinates.y;
  element.text;
  element.confidence;

  // ❌ TypeScript catches errors at compile time
  element.invalidProperty; // Error: Property 'invalidProperty' does not exist
});

Type Definitions

TestDriver includes comprehensive TypeScript definitions for all APIs, methods, and return types. Your IDE will provide intelligent autocomplete and inline documentation.

AI-Powered Assertions

Verify application state using natural language:
// Verify UI state
await testdriver.assert('the login page is displayed');
await testdriver.assert('submit button is visible and enabled');

// Verify content
await testdriver.assert('the page title is "Welcome"');
await testdriver.assert('success message says "Account created successfully"');

// Verify interactions
await testdriver.assert('the checkbox is checked');
await testdriver.assert('the dropdown shows "United States"');

// Verify visual state
await testdriver.assert('the button is blue');
await testdriver.assert('the loading spinner is not visible');
No need to write complex selectors and assertions. Just describe what should be true.

Clean Test Code

Compare the readability of TestDriver vs traditional approaches:
test('user can login', async (context) => {
  const { testdriver } = await chrome(context, {
    url: 'https://myapp.com/login'
  });

  await testdriver.find('email input').type('[email protected]');
  await testdriver.find('password input').type('secret', { secret: true });
  await testdriver.find('Login button').click();

  await testdriver.assert('Dashboard is visible');
});

Progressive Complexity

Choose your level of control:

Presets (Easiest)

One-line setup for common scenarios:
const { testdriver } = await chrome(context, {
  url: 'https://example.com'
});
Learn more

Hooks (Flexible)

More control with composable hooks:
const client = useTestDriver(context);
const dashcam = useDashcam(context, client);
Learn more

Core (Full Control)

Manual control over everything:
const client = new TestDriver(apiKey);
await client.connect();
await client.find('button');
Learn more

Zero Boilerplate

Presets handle all the setup and teardown automatically:
test('minimal test', async (context) => {
  // One line to set up everything:
  // - Authentication
  // - Sandbox provisioning
  // - Browser launch
  // - Navigation
  // - Dashcam recording
  // - Automatic cleanup
  const { testdriver } = await chrome(context, {
    url: 'https://example.com'
  });

  // Write your test
  await testdriver.find('button').click();

  // No cleanup needed - automatic!
});
The preset automatically disconnects and cleans up resources when your test completes, even if it fails.

Real-World Example

Here’s a complete, real-world test that showcases TestDriver’s simplicity:
import { test, expect } from 'vitest';
import { chrome } from 'testdriverai/presets';

test('user can checkout', async (context) => {
  const { testdriver } = await chrome(context, {
    url: 'https://shop.example.com'
  });

  // Add items to cart
  await testdriver.find('Add to Cart button on the first product').click();
  await testdriver.assert('Cart badge shows 1 item');

  // Go to checkout
  await testdriver.find('Cart icon').click();
  await testdriver.find('Checkout button').click();

  // Fill shipping form
  await testdriver.find('Full name input').type('John Doe');
  await testdriver.find('Address input').type('123 Main St');
  await testdriver.find('City input').type('Springfield');
  await testdriver.find('State dropdown').click();
  await testdriver.find('California option').click();

  // Submit order
  await testdriver.find('Place Order button').click();

  // Verify success
  await testdriver.assert('Order confirmation page is displayed');
  await testdriver.assert('Thank you message is visible');
});
Notice:
  • No CSS selectors or IDs
  • No explicit waits
  • No manual setup/teardown
  • Reads like a test plan
  • Self-documenting code

Get Started