Service
Selenium --- HTML to Image Conversion
Selenium is used to convert HTML elements into images. Its main use case is exporting reports to PDF or capturing the current page as an image.
How it Works
Selenium operates as a persistent web browser instance that remains open and available, controllable via the php-webdriver/webdriver SDK.
- In production: The instance is accessible via a dedicated URL and must run in headless mode for performance optimization. https://admin:[email protected]
- In local development: Selenium runs in
docker-compose. It can be used in non-headless mode to visually observe actions via a VNC viewer.
Local URLs:
- http://localhost:4444/ui/ --- Selenium Dashboard
- http://localhost:7900/ --- NoVNC viewer (to view the instance)
Local URL Management
Locally, Selenium runs inside Docker and cannot reach localhost. The Docker network alias bx.feedier.test is configured so that Selenium can access the application.
[!IMPORTANT] Local Configuration Required: For Selenium to correctly capture elements, it is imperative that you run the frontend using the following command:
sail npm run dev. The use of sail here is crucial so that the asset server is accessible within the Docker network.
Docker Configuration
# docker-compose.yml
networks:
sail:
aliases:
- bx.feedier.test
- api.bx.feedier.testURL Resolution
The INTERNAL_URL environment variable is used to build URLs that Selenium can resolve:
INTERNAL_URL=http://bx.feedier.testThe URL builder in ReportDownloader handles this automatically:
protected function getInternalLink(): string
{
$token = encrypt([
'report_id' => $this->report->id,
'ttl' => now()->addSeconds(self::LINK_VALIDITY_IN_SECONDS),
'user_id' => $this->user->id,
]);
$params = [
'reportId' => $this->report->id,
'token' => $token,
'type' => 'internal',
'locale' => app()->getLocale(),
'transition' => false,
'disableAnimation' => true,
'maxPage' => self::REPORT_DOWNLOAD_MAX_PAGES,
];
if ($internalUrl = config('app.internal_url')) {
return rtrim($internalUrl, '/') . route('report.shareable', $params, false);
}
return route('report.shareable', $params, true);
}Configuration
// config/selenium.php
return [
'url' => env('SELENIUM_URL', 'http://localhost:4444'),
'browser' => [
'name' => 'firefox',
'args' => ['-headless'],
],
];Code snippet
# .env
SELENIUM_URL=http://selenium:4444Technical Implementation
Creating a Remote WebDriver Instance
$remoteDriver = RemoteWebDriver::create(
config('selenium.url'),
$this->getBrowserCapabilities()
);Viewport Settings
$remoteDriver->manage()
->window()
->setSize(new WebDriverDimension(1920, 1080));Screenshot Capture
$element->takeElementScreenshot($path);Download Pipelines
Image Capture
// app/Services/Report/Downloaders/ImageDownload.php
Bus::chain([
new ConvertHTMLElementToImage(
url: $this->getInternalLink(),
cssSelector: '[data-capture]',
savingPath: $temporaryPath,
paginate: true,
extension: $this->format->value,
user: $this->user,
taskId: $this->taskId,
maxPages: ReportDownloader::REPORT_DOWNLOAD_MAX_PAGES,
),
new FinalizeImageDownload(...),
])->dispatch();PDF Capture
The PDF pipeline chains the Selenium capture with the Dompdf merge:
// app/Services/Report/Downloaders/PdfDownload.php
Bus::chain([
new ConvertHTMLElementToImage(...),
new MergeImagesInFolderToPDF(...),
])->dispatch();Scale (Pixel Density)
The recommended viewport size follows a 16:9 ratio: 1920×1080.
The scale factor (scale) controls the pixel density:
- Debug Mode: Use a scale of 1 (default).
- Production: Use a scale of 5 (recommended minimum: 3).
A high scale factor is essential for readability. Without it, screenshots will be blurry.
Key Reference Files
config/selenium.php--- Selenium Configurationconfig/report-download.php--- Timeout Configurationapp/Jobs/Report/Download/ConvertHTMLElementToImage.php--- Main Selenium Jobapp/Services/Report/ReportDownloader.php--- URL Generatorapp/Services/Report/Downloaders/ImageDownload.php--- Image Pipelineapp/Services/Report/Downloaders/PdfDownload.php--- PDF Pipeline