Back to docs

Natural Language Tests

Write tests in plain English. CBrowser parses and executes them. (v6.1.0)


Why Natural Language?

Traditional test code:

await page.goto('https://example.com');
await page.locator('[data-testid="login-btn"]').click();
await page.locator('#email').fill('[email protected]');
await expect(page).toHaveURL(/dashboard/);

Natural language equivalent:

go to https://example.com
click the login button
type "[email protected]" in email field
verify url contains "dashboard"

Benefits:

  • Readable by non-developers - QA, PMs, stakeholders can write tests
  • Self-documenting - The test IS the documentation
  • Portable - Not tied to any framework's syntax
  • AI-friendly - Easy for AI to generate and modify

Test File Format

Create a .txt file with your tests:

# Test: Login Flow
go to https://example.com
click the login button
type "[email protected]" in email field
type "password123" in password field
click submit
verify url contains "/dashboard"
verify page contains "Welcome back"

# Test: Search Functionality
go to https://example.com/search
type "test query" in search box
click search button
verify page contains "results"
take screenshot

Syntax Rules

  • Lines starting with # are comments or test names
  • # Test: Name starts a new test case
  • Empty lines are ignored
  • One instruction per line

Supported Instructions

Instruction Examples
Go to URL go to https://example.com
Navigate navigate to https://example.com/page
Open open https://example.com

Clicking

Instruction Examples
Click by text click the login button
Click by description click submit
Click specific click "Sign Up"
Press key press Enter

Filling Forms

Instruction Examples
Type in field type "[email protected]" in email field
Fill field fill username with "john"
Enter value enter "password123" in password input

Selecting

Instruction Examples
Select option select "Option A" from dropdown
Choose choose "California" from state selector

Scrolling

Instruction Examples
Scroll down scroll down
Scroll up scroll up
Scroll multiple scroll down 5 times

Waiting

Instruction Examples
Wait seconds wait 2 seconds
Wait for element wait for "Loading" to disappear
Wait for text wait for "Success" to appear

Assertions

Instruction Examples
Verify content verify page contains "Welcome"
Verify URL verify url contains "/dashboard"
Verify title verify title is "Home Page"
Verify element verify "Submit" button exists

Screenshots

Instruction Examples
Take screenshot take screenshot
Screenshot named take screenshot "after-login"

Running Tests

From File

npx cbrowser test-suite tests.txt

Inline Tests

npx cbrowser test-suite --inline "go to https://example.com ; click login ; verify url contains /dashboard"

Options

# Continue after failures
npx cbrowser test-suite tests.txt \
  --continue-on-failure

# Save JSON report
npx cbrowser test-suite tests.txt \
  --output results.json

# Generate HTML report
npx cbrowser test-suite tests.txt \
  --html

# Visible browser (default: headless)
npx cbrowser test-suite tests.txt \
  --no-headless

# Run as a phone, in another timezone
npx cbrowser test-suite tests.txt \
  --device iphone-16 \
  --timezone Asia/Tokyo

test-suite accepts only the flags it reads. Since 20.0 any other flag, such as --persona, exits 1 and lists the accepted ones instead of being ignored.

Export and Webhooks

Every run is saved under the CBrowser data directory by suite name (the file name without its extension), so you can export the last run:

npx cbrowser test-suite login.txt
npx cbrowser export junit login
npx cbrowser export tap login \
  results.tap

A run also sends test.pass or test.fail to the webhooks you have added. The sender posts JSON with a 10 second timeout and no retries, and a failed send never fails the run:

npx cbrowser webhook add ci-alerts \
  https://hooks.example.com/cb \
  --events test.fail --format slack

Output

Console Output

πŸ“‹ Running Test Suite: My Tests

─────────────────────────────────────────────
TEST: Login Flow
─────────────────────────────────────────────
  βœ“ go to https://example.com (1.2s)
  βœ“ click the login button (0.3s)
  βœ“ type "[email protected]" in email field (0.5s)
  βœ“ type "password123" in password field (0.4s)
  βœ“ click submit (0.2s)
  βœ“ verify url contains "/dashboard" (0.1s)
  βœ“ verify page contains "Welcome back" (0.1s)

  βœ… PASSED (2.8s)

─────────────────────────────────────────────
TEST: Search Functionality
─────────────────────────────────────────────
  βœ“ go to https://example.com/search (0.9s)
  βœ“ type "test query" in search box (0.4s)
  βœ“ click search button (0.2s)
  βœ— verify page contains "results"
    Expected: page to contain "results"
    Actual: page contains "No matches found"

  ❌ FAILED (1.5s)

═════════════════════════════════════════════
SUMMARY
═════════════════════════════════════════════
  Total: 2 tests
  Passed: 1
  Failed: 1
  Pass Rate: 50%
  Duration: 4.3s

JSON Report

{
  "suiteName": "My Tests",
  "timestamp": "2025-01-30T12:00:00Z",
  "duration": 4300,
  "summary": {
    "total": 2,
    "passed": 1,
    "failed": 1,
    "passRate": 50
  },
  "tests": [
    {
      "name": "Login Flow",
      "passed": true,
      "duration": 2800,
      "steps": [...]
    }
  ]
}

API Usage

import { parseNLTestSuite, runNLTestSuite, formatNLTestReport } from 'cbrowser';

// Parse test file content
const suite = parseNLTestSuite(`
  # Test: Homepage
  go to https://example.com
  verify title contains "Example"
  click the about link
  verify url contains "/about"
`, "My Test Suite");

// Run the tests
const result = await runNLTestSuite(suite, {
  continueOnFailure: true,
  screenshotOnFailure: true,
  headless: true,
});

// Format output
console.log(formatNLTestReport(result));

// Access detailed results
for (const test of result.testResults) {
  console.log(`${test.name}: ${test.passed ? 'PASS' : 'FAIL'}`);
  for (const step of test.stepResults) {
    console.log(`  ${step.passed ? 'βœ“' : 'βœ—'} ${step.instruction}`);
  }
}

Combining with Other Features

With Flaky Detection

# Run tests multiple times to find unreliable ones
npx cbrowser flaky-check tests.txt --runs 10

With AI Repair

# Automatically fix broken tests
npx cbrowser repair-tests tests.txt --auto-apply

With Personas

test-suite has no persona option (--persona exits 1). To see how different personas get through the same flow, run cognitive journeys instead (needs an Anthropic API key):

npx cbrowser compare-personas \
  --start "https://example.com" \
  --goal "log in" \
  --personas first-timer,elderly-user

Best Practices

  1. One assertion per test - Makes failures easy to diagnose
  2. Use descriptive test names - # Test: User can reset password
  3. Add waits after navigation - Pages need time to load
  4. Take screenshots at key points - Helps debug failures
  5. Keep tests independent - Don't rely on previous test state


Copyright: (c) 2026 Alexa Eden.

License: MIT License

Contact: [email protected]

From the Blog