// AI agents can autonomously write and run testsimport { test } from 'vitest';import { chrome } from 'testdriverai/presets';test('ai-generated test', async (context) => { const { testdriver } = await chrome(context, { url: 'https://example.com' }); await testdriver.find('More information link').click(); await testdriver.assert('IANA page is visible');});
AI-powered element location, assertions, and instructions:
Element Location
Assertions
Instructions
Copy
// Describe elements naturallyawait testdriver.find('submit button');await testdriver.find('email input in the login form');await testdriver.find('delete button in the top right corner');await testdriver.find('first product card in the grid');
Copy
// Assert application state naturallyawait testdriver.assert('the login page is displayed');await testdriver.assert('success message says "Welcome back"');await testdriver.assert('the form is empty');await testdriver.assert('the button is blue and enabled');await testdriver.assert('loading spinner is not visible');
Copy
// Complex interactions described naturallyawait testdriver.find('Products menu').hover();await testdriver.find('Laptops submenu item in the Products dropdown').click();await testdriver.find('Sort by dropdown').click();await testdriver.find('Price: Low to High option').click();
Feed natural language requirements directly to Claude Code to generate complete test suites:
1
Ask Claude Code to Generate Tests
Provide the requirements to Claude Code with context about your testing setup:
Copy
Generate a TestDriver test using Vitest for these requirements:Test the login flow:1. Navigate to login page2. Enter valid credentials3. Click submit4. Verify dashboard appearsUse the chrome preset and target https://myapp.com/login
2
Claude Generates Complete Tests
Claude Code will create production-ready test files:
Copy
import { test } from 'vitest';import { chrome } from 'testdriverai/presets';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('password', { secret: true }); await testdriver.find('Login button').click(); await testdriver.assert('Dashboard is visible');});
3
Run Tests and Iterate
Ask Claude Code to run the tests and refine based on results:
Copy
Run these tests and fix any failures. Then add tests for:- Invalid credentials- Empty form submission- Password visibility toggle
Claude will execute the tests, analyze failures, and automatically refine the test code.
Claude Code understands TestDriver’s natural language API and will automatically use appropriate selectors, assertions, and best practices like secret: true for passwords.
AI agents can reconnect to sandboxes for debugging:
Copy
// Initial test attempttest('initial attempt', async () => { const testdriver = new TestDriver({ apiKey: process.env.TD_API_KEY }); const instance = await testdriver.connect(); console.log('Sandbox ID:', instance.instanceId); // Save this ID for reconnection try { await testdriver.find('difficult selector').click(); } catch (error) { console.error('Failed:', error); // Keep sandbox alive for debugging }});// Reconnect to same sandboxtest('reconnect attempt', async () => { const testdriver = new TestDriver({ apiKey: process.env.TD_API_KEY }); // Manually specify the sandbox ID from previous test await testdriver.connect({ sandboxId: 'your-sandbox-id-here', newSandbox: false }); // Try alternative selector await testdriver.find('alternative selector').click(); await testdriver.disconnect();});
Automatic Sandbox Tracking
TestDriver automatically saves the last sandbox ID to ~/.testdriverai-last-sandbox. By default, newSandbox: true, so each connection creates a new sandbox. Set newSandbox: false and provide a sandboxId to reconnect to an existing sandbox.
// Future MCP interactivityawait testdriver.mcp.query("What is the CPU usage of my app?");await testdriver.mcp.query("Show me memory leaks in the last test run");await testdriver.mcp.query("What tests are flakiest this week?");await testdriver.mcp.query("Compare performance between branches");
MCP (Model Context Protocol) integration is planned for Q1 2025.
// AI analyzes how close the match wastry { await testdriver.find('submit button');} catch (error) { if (error.similarity > 0.8) { console.log('Very close match - likely wrong selector specificity'); } else if (error.similarity > 0.5) { console.log('Partial match - element might be present but different'); } else { console.log('No match - element likely not on screen'); }}
Visual Debugging
Copy
// Get debug screenshot for AI analysistry { await testdriver.find('button');} catch (error) { // AI can analyze the debug screenshot const screenshot = error.debugScreenshot; // Base64 image // Send to vision model for analysis const analysis = await visionModel.analyze(screenshot, "Why can't we find the submit button?" );}
// ✅ Good - specific and contextualawait testdriver.find('blue submit button below the login form');// ❌ Bad - too vagueawait testdriver.find('button');
2. Always Use secret: true for Passwords
Copy
// ✅ Protected from loggingawait testdriver.type('MyPassword123', { secret: true });// ❌ Password will be loggedawait testdriver.type('MyPassword123');
3. Handle Errors Gracefully
Copy
// ✅ Try alternative approachestry { await testdriver.find('optional element').click();} catch (error) { console.log('Element not found, trying alternative...'); await testdriver.find('alternative element').click();}
4. Save Sandbox IDs
Copy
// ✅ Enable reconnectionconst instance = await testdriver.connect();console.log('Sandbox ID:', instance.instanceId);// Save for debugging later