Installation:
composer require --dev ibexa/behat --no-scripts --no-plugins
composer sync-recipes ibexa/behat --force -v
Ensure you have a running Ibexa DXP instance (v5.x or v4.x) and Behat installed (behat/behat).
Configure Behat: Copy the default configuration files from the package:
php vendor/bin/ibexa-behat init
This generates:
behat.yml (main config)features/ (test scenarios)src/Behat/ (custom context classes)First Test Case:
Create a feature file (features/content_creation.feature):
Feature: Content Creation
Scenario: Create a basic page
Given I am on the Ibexa admin interface
When I create a new content item of type "article"
And I fill in the title field with "Test Article"
And I publish the content
Then the content should be published successfully
Run the test:
vendor/bin/behat features/content_creation.feature
Key Files to Review:
doc/getting_started.md (official docs)src/Behat/Context/ (pre-built contexts like IbexaContext, ContentContext)config/behat_ibexa_headless.yaml (headless browser config)Context-Driven Testing:
IbexaContext or ContentContext for custom logic:
// src/Behat/Context/CustomContext.php
namespace App\Behat\Context;
use Ibexa\Behat\Context\IbexaContext;
class CustomContext extends IbexaContext {
/**
* @Given I verify the content has a specific field value
*/
public function assertContentFieldValue(string $fieldIdentifier, string $expectedValue) {
$content = $this->getContent();
$value = $content->getFieldValue($fieldIdentifier);
if ($value !== $expectedValue) {
throw new \Exception("Field '$fieldIdentifier' has value '$value', expected '$expectedValue'");
}
}
}
behat.yml:
default:
contexts:
- Ibexa\Behat\Context\IbexaContext
- App\Behat\Context\CustomContext
Data Setup/Teardown:
BeforeScenario hooks to initialize data:
/**
* @BeforeScenario
*/
public function setupContent() {
$this->createContent('article', ['title' => 'Test Article']);
}
IbexaContext::createContent() or updateContent() methods.Admin UI Automation:
Given I am on the "Content" section of the admin interface
When I click on the "Create" button
And I select the "article" content type
IbexaContext::navigateToAdmin() and IbexaContext::clickAdminButton().Headless Testing:
behat_ibexa_headless.yaml for Selenium-based tests:
default:
extensions:
Ibexa\Behat\Extension\HeadlessExtension:
selenium_server_url: "http://localhost:4444/wd/hub"
browser: "chrome"
vendor/bin/behat --config=behat_ibexa_headless.yaml
Integration with Ibexa Services:
IbexaContext:
$contentService = $this->getService('content_service');
$locationService = $this->getService('location_service');
Custom Step Definitions:
/**
* @Given I publish the content with ID :contentId
*/
public function publishContentById(int $contentId) {
$content = $this->getContentService()->loadContent($contentId);
$this->getContentService()->publishVersion($content->versionInfo);
}
Environment-Specific Configs:
behat.local.yml):
default:
extensions:
Ibexa\Behat\Extension\HeadlessExtension:
browser: "firefox"
Tagging and Filtering:
@smoke
Scenario: Smoke test for content creation
vendor/bin/behat @smoke
Database Transactions:
IbexaContext::beginTransaction() and rollback() to isolate tests:
/**
* @BeforeScenario
*/
public function beginTransaction() {
$this->beginTransaction();
}
/**
* @AfterScenario
*/
public function rollbackTransaction() {
$this->rollback();
}
Custom Fixtures:
IbexaContext::loadFixtures():
/**
* @BeforeScenario
*/
public function loadFixtures() {
$this->loadFixtures(['path/to/fixtures']);
}
Database Connection Issues:
IBEXA_SITEACCESS and IBEXA_DB_* env vars are set. Use .env.behat:
IBEXA_SITEACCESS=admin
IBEXA_DB_DATABASE=ibexa_behat
Selenium/Browser Quirks:
$this->waitForElementVisible('.some-selector', 10);
behat_ibexa_headless.yaml to adjust timeouts:
extensions:
Ibexa\Behat\Extension\HeadlessExtension:
wait_for_timeout: 15
Context Loading Order:
behat.yml order.IbexaContext first).Content Not Found:
ContentNotFoundException when loading content.$content = $this->getContentService()->loadContent($contentId, ['siteaccess' => 'admin']);
Permission Denied:
$this->getPermissionResolver()->setPermission('content', 'publish', true);
Enable Verbose Output:
vendor/bin/behat -v
Dump Services:
/**
* @Given I dump the content service
*/
public function dumpContentService() {
dump($this->getService('content_service'));
}
Screenshots on Failure:
extensions:
Ibexa\Behat\Extension\HeadlessExtension:
screenshot_path: "%paths.base%/var/behat_screenshots"
Slow Tests:
behat_ibexa_headless.yaml.Behat\Testwork\Extension\ExtensionInterface:
namespace App\Behat\Extension;
use Behat\Testwork\Extension\ExtensionInterface;
class CustomExtension implements ExtensionInterface {
public function getConfigKey() { return 'custom'; }
public function initialize(ExtensionConfiguration $extensionConfig) {}
public function configure(ContainerBuilder $container) {}
public function load(ContainerBuilder $container, Config $config) {}
}
behat.yml:
default:
How can I help you explore Laravel packages today?