Symfony Panther provides extensive debugging capabilities to help developers troubleshoot browser automation and web scraping issues. These tools are essential for identifying problems in end-to-end tests and understanding browser behavior during scraping operations.
Visual Debugging
Screenshots
Capture the browser's visual state at any point during execution:
// Basic screenshot
$client->takeScreenshot('debug.png');
// Screenshot with timestamp
$client->takeScreenshot('screenshot_' . date('Y-m-d_H-i-s') . '.png');
// Automatic error screenshots (set via environment)
// PANTHER_ERROR_SCREENSHOT_DIR=/path/to/screenshots
Page Source Inspection
Examine the current DOM structure and content:
// Get complete page source
$html = $client->getPageSource();
file_put_contents('page_source.html', $html);
// Get specific element content
$crawler = $client->getCrawler();
$content = $crawler->filter('body')->html();
echo $content;
Console and Log Debugging
Browser Console Logs
Access JavaScript console output for debugging client-side issues:
$logs = $client->manage()->getLog('browser');
foreach ($logs as $log) {
echo sprintf(
"[%s] %s: %s\n",
$log['level'],
date('Y-m-d H:i:s', $log['timestamp'] / 1000),
$log['message']
);
}
WebDriver Logging
Enable detailed WebDriver communication logs:
use Facebook\WebDriver\Remote\WebDriverCapabilityType;
$client = \Symfony\Component\Panther\PantherTestCase::createPantherClient([
'capabilities' => [
WebDriverCapabilityType::LOGGING_PREFS => [
'browser' => 'ALL',
'driver' => 'ALL',
'performance' => 'ALL',
],
],
]);
// Retrieve different types of logs
$browserLogs = $client->manage()->getLog('browser');
$driverLogs = $client->manage()->getLog('driver');
$performanceLogs = $client->manage()->getLog('performance');
Environment Variables for Debugging
Essential Debug Environment Variables
# Disable headless mode (show browser window)
PANTHER_NO_HEADLESS=1 ./vendor/bin/phpunit
# Automatically save error screenshots
PANTHER_ERROR_SCREENSHOT_DIR=/tmp/panther-screenshots ./vendor/bin/phpunit
# Keep browser open after test completion
PANTHER_DEVTOOLS=1 ./vendor/bin/phpunit
# Custom browser arguments for debugging
PANTHER_BROWSER_ARGS="--disable-web-security --remote-debugging-port=9222"
Complete Debug Setup
# Comprehensive debugging environment
export PANTHER_NO_HEADLESS=1
export PANTHER_ERROR_SCREENSHOT_DIR=/tmp/debug-screenshots
export PANTHER_DEVTOOLS=1
export PANTHER_NO_SANDBOX=1
./vendor/bin/phpunit tests/E2E/
Advanced Debugging Techniques
Network Request Monitoring
Track HTTP requests and responses:
// Enable network logging
$client = \Symfony\Component\Panther\PantherTestCase::createPantherClient([
'capabilities' => [
WebDriverCapabilityType::LOGGING_PREFS => [
'performance' => 'ALL',
],
],
]);
// Analyze network activity
$performanceLogs = $client->manage()->getLog('performance');
foreach ($performanceLogs as $log) {
$message = json_decode($log['message'], true);
if ($message['message']['method'] === 'Network.responseReceived') {
$response = $message['message']['params']['response'];
echo "URL: " . $response['url'] . "\n";
echo "Status: " . $response['status'] . "\n";
}
}
Wait Debugging
Debug timing and synchronization issues:
use Symfony\Component\Panther\DomCrawler\Crawler;
try {
// Wait with custom timeout and debugging
$client->waitFor('.dynamic-content', 10);
} catch (\Exception $e) {
// Take screenshot before timeout
$client->takeScreenshot('timeout_error.png');
// Check what elements are currently present
$crawler = $client->getCrawler();
$elements = $crawler->filter('*[class*="dynamic"]');
echo "Found " . $elements->count() . " dynamic elements\n";
throw $e;
}
Error Handling and Exception Debugging
Comprehensive Error Handling
use Symfony\Component\Panther\Exception\RuntimeException;
use Facebook\WebDriver\Exception\TimeoutException;
try {
$crawler = $client->request('GET', 'https://example.com');
$client->waitFor('.content');
} catch (TimeoutException $e) {
// Handle timeout specifically
$client->takeScreenshot('timeout_' . time() . '.png');
echo "Timeout waiting for element: " . $e->getMessage() . "\n";
} catch (RuntimeException $e) {
// Handle Panther-specific errors
$client->takeScreenshot('runtime_error_' . time() . '.png');
echo "Runtime error: " . $e->getMessage() . "\n";
} catch (\Throwable $e) {
// Catch-all for unexpected errors
$client->takeScreenshot('unexpected_error_' . time() . '.png');
file_put_contents('error_log.txt', $client->getPageSource());
throw $e;
}
Symfony Profiler Integration
Accessing Profiler Data
// Only available when testing Symfony applications
$profile = $client->getProfile();
if ($profile) {
// Database queries
$dbCollector = $profile->getCollector('db');
echo "Queries executed: " . $dbCollector->getQueryCount() . "\n";
// HTTP kernel information
$requestCollector = $profile->getCollector('request');
echo "Controller: " . $requestCollector->getController() . "\n";
// Memory usage
$memoryCollector = $profile->getCollector('memory');
echo "Memory usage: " . $memoryCollector->getMemory() . " bytes\n";
}
Interactive Debugging Workflow
Step-by-Step Debug Process
// 1. Enable visual debugging
$client = \Symfony\Component\Panther\PantherTestCase::createPantherClient();
// 2. Navigate and take initial screenshot
$crawler = $client->request('GET', 'https://example.com');
$client->takeScreenshot('step1_initial.png');
// 3. Check for JavaScript errors
$consoleLogs = $client->manage()->getLog('browser');
$errors = array_filter($consoleLogs, fn($log) => $log['level'] === 'SEVERE');
if (!empty($errors)) {
echo "JavaScript errors found:\n";
foreach ($errors as $error) {
echo "- " . $error['message'] . "\n";
}
}
// 4. Interact and capture state
$client->clickLink('Login');
$client->takeScreenshot('step2_after_click.png');
// 5. Fill forms with debugging
$form = $crawler->selectButton('Submit')->form();
$client->submit($form, ['username' => 'test', 'password' => 'test']);
$client->takeScreenshot('step3_form_submitted.png');
Best Practices for Debugging
- Use meaningful screenshot names with timestamps and step descriptions
- Combine multiple debugging methods for comprehensive troubleshooting
- Set up automatic error screenshots for CI/CD environments
- Monitor console logs for JavaScript-heavy applications
- Use environment variables to enable debugging only when needed
- Save page source along with screenshots for complete context
These debugging options make Symfony Panther a powerful tool for both development and production troubleshooting of browser automation tasks.