Error Handling Guide

Learn how to handle various types of errors and implement robust error recovery in your Chekov tests.

Types of Errors

API Errors

ErrorDescriptionHow to Handle
Rate Limit (429)Too many requestsImplement backoff and retry
Authentication (401/403)Invalid or missing API keyVerify API key configuration
Service Error (500)Internal server errorRetry with exponential backoff

Page Errors

  • Element not found
  • Element not clickable
  • Navigation timeout
  • Network errors

Basic Error Handling

import { test } from '@playwright/test';
import { ai } from '@chekov/core';

test('handle basic errors', async ({ page }) => {
  try {
    await ai('Click the submit button', { page });
  } catch (error) {
    // Handle specific error types
    if (error.message.includes('Element not found')) {
      console.log('Button not found, retrying after wait...');
      await page.waitForTimeout(1000);
      await ai('Click the submit button', { page });
    } else {
      throw error; // Re-throw unhandled errors
    }
  }
});

Retry Mechanisms

Basic Retry

async function withRetry(action: () => Promise<void>, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      await action();
      return;
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
    }
  }
}

Using with Chekov

test('retry example', async ({ page }) => {
  await withRetry(async () => {
    await ai('Click the dynamic button', { page });
  });
});

Common Scenarios

Dynamic Content

test('handle dynamic content', async ({ page }) => {
  // Wait for content to load
  await ai('Wait for the dashboard to load', { page });
  
  try {
    await ai('Click the first item in the list', { page });
  } catch (error) {
    if (error.message.includes('Element not found')) {
      // Refresh and retry
      await page.reload();
      await ai('Wait for the dashboard to load', { page });
      await ai('Click the first item in the list', { page });
    }
  }
});

Network Issues

test('handle network issues', async ({ page }) => {
  // Simulate offline mode
  await page.context().setOffline(true);
  
  try {
    await ai('Submit the form', { page });
  } catch (error) {
    // Handle network error
    await page.context().setOffline(false);
    await ai('Verify the error message is shown', { page });
    await ai('Wait for network recovery', { page });
    await ai('Submit the form again', { page });
  }
});

Error Recovery Patterns

Progressive Enhancement

test('progressive enhancement', async ({ page }) => {
  // Try modern approach first
  try {
    await ai('Click the React button', { page });
  } catch {
    // Fall back to traditional approach
    await ai('Click the regular button', { page });
  }
});

State Recovery

test('recover from error state', async ({ page }) => {
  try {
    await ai('Complete the purchase', { page });
  } catch (error) {
    // Save current state
    const cartItems = await page.evaluate(() => 
      localStorage.getItem('cart')
    );
    
    // Refresh page
    await page.reload();
    
    // Restore state
    await page.evaluate(
      (items) => localStorage.setItem('cart', items),
      cartItems
    );
    
    // Retry operation
    await ai('Complete the purchase', { page });
  }
});

Best Practices

  • Specific Error Handling: Handle specific error types differently
  • Retry with Backoff: Implement exponential backoff for retries
  • State Management: Save and restore state when recovering from errors
  • Logging: Log errors with sufficient context for debugging
  • Cleanup: Always clean up resources in finally blocks

Error Prevention

  • Wait Conditions: Use appropriate wait conditions for dynamic content
  • State Verification: Verify state before performing actions
  • Network Conditions: Test with various network conditions
  • Data Setup: Ensure proper test data setup before running tests

Debugging Tips

  • Use page.screenshot() to capture the state when errors occur
  • Enable Playwright's debug mode with PWDEBUG=1
  • Add detailed error messages to help with troubleshooting
  • Use Playwright's trace viewer for detailed debugging

Remember: Good error handling makes your tests more reliable and easier to maintain. Always plan for failure cases and implement appropriate recovery mechanisms.

Next Steps