## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require --dev behat/mink-bundle
Add the bundle to config/bundles.php:
return [
// ...
Behat\MinkBundle\MinkBundle::class => ['test' => true],
];
Configure config/packages/test/mink.yaml (Symfony 4+):
mink:
base_url: 'http://localhost:8000'
browser_name: 'goutte' # Default for headless testing
goutte: ~
selenium2: ~
First Use Case:
Inject Mink into a test class and use it to interact with pages:
use Behat\Mink\Mink;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class ExampleTest extends WebTestCase
{
private Mink $mink;
protected function setUp(): void
{
$this->mink = static::createClient()->getContainer()->get('mink');
}
public function testHomepage()
{
$this->mink->visit('/');
$this->assertEquals('Welcome', $this->mink->getPage()->getTitle());
}
}
Key Classes to Know:
Mink (main interface)Session (e.g., goutte, selenium2)Page (represents a page, methods like getTitle(), find())Element (interact with DOM elements, e.g., click(), fillField()).// Visit a page
$this->mink->visit('/dashboard');
// Assert content
$this->assertEquals('Dashboard', $this->mink->getPage()->getTitle());
// Find and interact with elements
$link = $this->mink->getSession()->getPage()->find('link', ['text' => 'Profile']);
$link->click();
$page = $this->mink->getPage();
$page->fillField('email', 'user@example.com');
$page->fillField('password', 'secret123');
$page->pressButton('Login');
Configure multiple drivers in mink.yaml and switch via setDefaultDriver():
mink:
drivers:
goutte: ~
selenium2:
wd_host: 'http://localhost:4444/wd/hub'
// In test
$this->mink->setDefaultDriver('selenium2'); // Switch to Selenium2
$this->mink->visit('/');
Create a Page class to encapsulate interactions:
class DashboardPage
{
private $mink;
public function __construct(Mink $mink)
{
$this->mink = $mink;
}
public function open()
{
$this->mink->visit('/dashboard');
}
public function getUserName(): string
{
return $this->mink->getSession()->getPage()->find('css', '.username')->getText();
}
}
Use setUp() and tearDown() to manage the Mink instance:
protected function setUp(): void
{
$this->mink = static::createClient()->getContainer()->get('mink');
$this->mink->start();
}
protected function tearDown(): void
{
$this->mink->stop();
}
Configure Selenium2 in mink.yaml:
mink:
drivers:
selenium2:
wd_host: 'http://localhost:4444/wd/hub'
capabilities: { 'browserName': 'chrome' }
Use in tests:
$this->mink->setDefaultDriver('selenium2');
$this->mink->visit('/');
$this->assertEquals('Dynamic Title', $this->mink->getPage()->getTitle());
Service Container Integration: MinkBundle is designed for Symfony, but you can manually integrate it into Laravel by:
Mink and Session to the Laravel container.$this->app->bind('mink', function () {
return new Mink(new \Behat\Mink\Driver\Goutte\Driver());
});
Testing Laravel Routes:
Use visit() with Laravel’s URL generator:
$this->mink->visit(route('dashboard'));
Artisan Commands: Create a custom command to run Mink tests:
use Behat\Mink\Mink;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class RunMinkTests extends Command
{
protected function execute(InputInterface $input, OutputInterface $output)
{
$mink = $this->getContainer()->get('mink');
// Run tests...
}
}
Parallel Testing:
Use parallel_lint or custom scripts to run tests in parallel, as MinkBundle doesn’t natively support it.
Deprecated Package:
mink (standalone) + symfony/mink-bundle (if available) or migrate to modern alternatives like:
Selenium2/Zombie Bugs:
goutte for headless testing or selenium2 with a stable WebDriver setup.Configuration Overrides:
parameters.yml do not override config_test.yml by default. Use:
# config/packages/test/mink.yaml
mink:
base_url: '%env(MINK_BASE_URL)%'
Then set the env var:
MINK_BASE_URL="http://staging.example.com" php artisan test
Session Management:
$this->mink->getSession()->reset();
or use start()/stop() in setUp()/tearDown().CSS Selector Quirks:
$element = $this->mink->getSession()->getPage()->find('xpath', '//*[@id="dynamic-id"]');
JavaScript Limitations:
Enable Verbose Output: Configure Mink to log requests/responses:
mink:
goutte:
client:
options:
debug: true
Inspect the DOM: Dump the current page HTML for debugging:
$html = $this->mink->getSession()->getPage()->getContent();
file_put_contents('debug.html', $html);
Selenium2 Logs: Enable WebDriver logs:
mink:
selenium2:
wd_host: 'http://localhost:4444/wd/hub'
capabilities: { 'browserName': 'chrome', 'loggingPrefs': { 'browser': 'ALL' } }
Handle Stale Elements:
Use wait() to handle AJAX-loaded content:
$this->mink->getSession()->wait(5000, "page contains 'Expected Content'");
Custom Drivers:
Extend Behat\Mink\Driver\DriverInterface to create a custom driver (e.g., for a headless Chrome instance).
Event Listeners:
Attach listeners to Mink events (e.g., Mink\Event\BeforeScenarioEvent) for pre/post-test hooks.
Mocking Sessions:
For unit testing, mock the Session interface:
$mockSession = $this->createMock(Session::class);
$mockSession->method('getPage')->willReturn($this->create
How can I help you explore Laravel packages today?