Yes, Symfony Panther enables comprehensive interaction with web page elements, including clicking buttons, links, filling forms, and performing complex user interactions. As a PHP library built on the WebDriver protocol, it provides full browser automation capabilities for testing and web scraping.
Installation
First, install Symfony Panther via Composer:
composer require symfony/panther
Basic Element Interactions
Clicking Links and Buttons
<?php
require __DIR__.'/vendor/autoload.php';
use Symfony\Component\Panther\PantherTestCase;
class ElementInteractionTest extends PantherTestCase
{
public function testElementInteractions()
{
$client = static::createPantherClient();
$client->request('GET', 'https://example.com');
$crawler = $client->getCrawler();
// Click a link by text
$link = $crawler->selectLink('About Us')->link();
$client->click($link);
// Click a button by ID
$button = $crawler->filter('#submit-btn')->first();
$button->click();
// Click using CSS selector
$client->getCrawler()->filter('button.primary')->first()->click();
// Click by XPath
$client->getCrawler()->filterXPath('//button[@data-action="save"]')->first()->click();
}
}
Form Interactions
public function testFormSubmission()
{
$client = static::createPantherClient();
$client->request('GET', 'https://example.com/contact');
$crawler = $client->getCrawler();
// Fill and submit a form
$form = $crawler->selectButton('Submit')->form([
'name' => 'John Doe',
'email' => 'john@example.com',
'message' => 'Hello from Symfony Panther!'
]);
$client->submit($form);
// Alternative: Fill form fields individually
$crawler->filter('input[name="username"]')->sendKeys('myusername');
$crawler->filter('input[name="password"]')->sendKeys('mypassword');
$crawler->filter('input[type="submit"]')->click();
}
Advanced Interactions
Dropdown Selection
public function testDropdownSelection()
{
$client = static::createPantherClient();
$client->request('GET', 'https://example.com/form');
$crawler = $client->getCrawler();
// Select dropdown option by value
$form = $crawler->selectButton('Submit')->form();
$form['country']->select('US');
$client->submit($form);
// Or interact with dropdown directly
$crawler->filter('select[name="category"]')->selectOption('technology');
}
Checkbox and Radio Button Handling
public function testCheckboxAndRadio()
{
$client = static::createPantherClient();
$client->request('GET', 'https://example.com/preferences');
$crawler = $client->getCrawler();
// Check/uncheck checkboxes
$form = $crawler->selectButton('Save')->form();
$form['newsletter']->tick(); // Check checkbox
$form['promotions']->untick(); // Uncheck checkbox
// Select radio button
$form['gender']->select('male');
$client->submit($form);
}
File Upload
public function testFileUpload()
{
$client = static::createPantherClient();
$client->request('GET', 'https://example.com/upload');
$crawler = $client->getCrawler();
$form = $crawler->selectButton('Upload')->form();
$form['file']->upload('/path/to/your/file.pdf');
$client->submit($form);
}
Non-Test Context Usage
For standalone scripts outside of test classes:
<?php
require __DIR__.'/vendor/autoload.php';
use Symfony\Component\Panther\Client;
// Create client directly
$client = Client::createChromeClient();
// Navigate and interact
$client->request('GET', 'https://example.com');
// Click elements
$client->getCrawler()->filter('a.download-link')->first()->click();
// Fill forms
$client->getCrawler()->filter('input[name="search"]')->sendKeys('symfony panther');
$client->getCrawler()->filter('button[type="submit"]')->click();
// Wait for elements to appear
$client->waitFor('.results');
// Extract data after interaction
$title = $client->getCrawler()->filter('h1')->text();
echo "Page title: " . $title;
$client->quit();
Waiting and Synchronization
Handle dynamic content with wait methods:
public function testWithWaiting()
{
$client = static::createPantherClient();
$client->request('GET', 'https://example.com/dynamic-content');
// Wait for element to appear
$client->waitFor('.dynamic-element');
// Wait for element to disappear
$client->waitForInvisibility('.loading-spinner');
// Wait for specific text
$client->waitForText('Data loaded successfully');
// Then interact with the element
$client->getCrawler()->filter('.dynamic-element button')->click();
}
Best Practices
- Always refresh the crawler after page changes:
$client->click($link);
$crawler = $client->refreshCrawler(); // Get updated DOM
- Use explicit waits for dynamic content:
$client->waitFor('.ajax-content');
- Handle errors gracefully:
try {
$element = $crawler->filter('#optional-element')->first();
if ($element->count() > 0) {
$element->click();
}
} catch (\Exception $e) {
// Handle missing element
}
- Close the browser when done:
$client->quit();
Symfony Panther provides a comprehensive solution for browser automation, enabling you to perform virtually any user interaction programmatically while maintaining the full context of a real browser session.