Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored to have a consistent interface. #146

Merged
merged 1 commit into from
Jan 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,13 @@
*/
public function initializeContext(Context $context): void {
if ($context instanceof ScreenshotAwareContextInterface) {
$dir = $this->resolveScreenshotDir();
$dir = getenv('BEHAT_SCREENSHOT_DIR') ?: $this->dir;

Check warning on line 59 in src/DrevOps/BehatScreenshotExtension/Context/Initializer/ScreenshotContextInitializer.php

View check run for this annotation

Codecov / codecov/patch

src/DrevOps/BehatScreenshotExtension/Context/Initializer/ScreenshotContextInitializer.php#L59

Added line #L59 was not covered by tests

if ($this->shouldPurge() && $this->needsPurging) {
$this->purgeFilesInDir($dir);
if ((getenv('BEHAT_SCREENSHOT_PURGE') || $this->purge) && $this->needsPurging) {
$fs = new Filesystem();
if ($fs->exists($dir)) {
$fs->remove((new Finder())->files()->in($dir));

Check warning on line 64 in src/DrevOps/BehatScreenshotExtension/Context/Initializer/ScreenshotContextInitializer.php

View check run for this annotation

Codecov / codecov/patch

src/DrevOps/BehatScreenshotExtension/Context/Initializer/ScreenshotContextInitializer.php#L61-L64

Added lines #L61 - L64 were not covered by tests
}
$this->needsPurging = FALSE;
}

Expand All @@ -74,43 +77,4 @@
}
}

/**
* Remove files in directory.
*
* @param string $dir
* Directory to purge files in.
*/
protected function purgeFilesInDir(string $dir): void {
$fs = new Filesystem();
$finder = new Finder();
if ($fs->exists($dir)) {
$fs->remove($finder->files()->in($dir));
}
}

/**
* Resolve directory using one of supported paths.
*
* @return string
* Path to the screenshots directory.
*/
protected function resolveScreenshotDir(): string {
$dir = getenv('BEHAT_SCREENSHOT_DIR');
if (!empty($dir)) {
return $dir;
}

return $this->dir;
}

/**
* Decide if 'purge' flag was set.
*
* @return bool
* TRUE if should purge, FALSE otherwise.
*/
protected function shouldPurge(): bool {
return getenv('BEHAT_SCREENSHOT_PURGE') || $this->purge;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,30 @@ interface ScreenshotAwareContextInterface extends Context {
*/
public function setScreenshotParameters(string $dir, bool $fail, string $fail_prefix, string $filename_pattern, string $filename_pattern_failed, array $info_types): static;

/**
* Save screenshot content into a file.
*
* @param array<string,mixed> $options
* Contextual options.
*/
public function iSaveScreenshot(array $options): void;

/**
* Adds information to context.
*
* @param string $label
* Debug information label.
* @param string $value
* Debug information value.
*/
public function appendInfo(string $label, string $value): void;

/**
* Render information.
*
* @return string
* Rendered debug information.
*/
public function renderInfo(): string;

}
136 changes: 54 additions & 82 deletions src/DrevOps/BehatScreenshotExtension/Context/ScreenshotContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,25 @@
return $this;
}

/**
* Get screenshot directory.
*
* @return string
* Screenshot directory.
*/
public function getDir(): string {
return $this->dir;
}

/**
* Init values required for screenshots.
*
* @param \Behat\Behat\Hook\Scope\BeforeScenarioScope $scope
* Scenario scope.
*
* @BeforeScenario
* @BeforeScenario @javascript
*/
public function beforeScenarioInit(BeforeScenarioScope $scope): void {
if (!$scope->getScenario()->hasTag('javascript')) {
return;
}

$driver = $this->getSession()->getDriver();

try {
Expand Down Expand Up @@ -130,33 +136,25 @@
*/
public function printLastResponseOnError(AfterStepScope $event): void {
if (!$event->getTestResult()->isPassed() && $this->fail) {
$this->iSaveScreenshot(TRUE);
$this->iSaveScreenshot(['is_failure' => TRUE]);
}
}

/**
* Save screenshot content into a file.
*
* @param bool $is_failure
* Denotes if this was called in a context of the failed
* test.
* @param string|null $filename
* File name.
*
* @throws \Behat\Mink\Exception\DriverException
* @throws \Behat\Mink\Exception\UnsupportedDriverActionException
* {@inheritdoc}
*
* @When save screenshot
* @When I save screenshot
* @Then save screenshot
*/
public function iSaveScreenshot(bool $is_failure = FALSE, ?string $filename = NULL): void {
$file_name = $this->makeFileName('html', $filename, $is_failure);
public function iSaveScreenshot(array $options = []): void {
$filename = isset($options['filename']) && is_scalar($options['filename']) ? strval($options['filename']) : NULL;
$is_failure = isset($options['is_failure']) && is_scalar($options['is_failure']) && $options['is_failure'];

$driver = $this->getSession()->getDriver();
$info = $this->renderInfo();

try {
$driver = $this->getSession()->getDriver();
$content = $driver->getContent();

$info = $this->renderInfo();
$content = empty($info) ? $content : nl2br($info) . "<hr/>\n" . $content;
}
catch (DriverException) {
Expand All @@ -165,25 +163,26 @@
return;
}

$this->saveScreenshotContent($file_name, $content);
$filename_html = $this->makeFileName('html', $filename, $is_failure);
$this->saveScreenshotContent($filename_html, $content);

// Drivers that do not support making screenshots, including Goutte
// driver that is shipped with Behat, throw exception. For such drivers,
// driver which is shipped with Behat, throw exception. For such drivers,
// screenshot stored as an HTML page (without referenced assets).
try {
$driver = $this->getSession()->getDriver();
$content = $driver->getScreenshot();
// Preserve filename, but change the extension - this is to group
// content and screenshot files together by name.
$file_name = $this->makeFileName('png', $filename, $is_failure);
$this->saveScreenshotContent($file_name, $content);
}
// @codeCoverageIgnoreStart
catch (UnsupportedDriverActionException) {
// Nothing to do here - drivers without support for screenshots
// simply do not have them created.
return;
}
// @codeCoverageIgnoreEnd
// Re-create the filename with a different extension to group content
// and screenshot files together by name.
$filename_png = $this->makeFileName('png', $filename, $is_failure);
$this->saveScreenshotContent($filename_png, $content);
}

/**
Expand All @@ -196,9 +195,10 @@
* @throws \Behat\Mink\Exception\UnsupportedDriverActionException
*
* @When I save screenshot with name :filename
* @Then save screenshot with name :filename
*/
public function iSaveScreenshotWithName(string $filename): void {
$this->iSaveScreenshot(FALSE, $filename);
$this->iSaveScreenshot(['filename' => $filename]);
}

/**
Expand All @@ -212,8 +212,8 @@
* @throws \Behat\Mink\Exception\DriverException
* @throws \Behat\Mink\Exception\UnsupportedDriverActionException
*
* @When save :width x :height screenshot
* @When I save :width x :height screenshot
* @Then save :width x :height screenshot
*/
public function iSaveSizedScreenshot(string|int $width = 1440, string|int $height = 900): void {
try {
Expand All @@ -226,6 +226,22 @@
$this->iSaveScreenshot();
}

/**
* Save screenshot content into a file.
*
* @param string $filename
* File name to write.
* @param string $content
* Content to write into a file.
*/
public function saveScreenshotContent(string $filename, string $content): void {
(new Filesystem())->mkdir($this->dir, 0755);
$success = file_put_contents($this->dir . DIRECTORY_SEPARATOR . $filename, $content);
if ($success === FALSE) {
throw new \RuntimeException(sprintf('Failed to save screenshot to %s', $filename));

Check warning on line 241 in src/DrevOps/BehatScreenshotExtension/Context/ScreenshotContext.php

View check run for this annotation

Codecov / codecov/patch

src/DrevOps/BehatScreenshotExtension/Context/ScreenshotContext.php#L241

Added line #L241 was not covered by tests
}
}

/**
* Get before step scope.
*
Expand All @@ -237,22 +253,14 @@
}

/**
* Adds information to context.
*
* @param string $label
* Debug information label.
* @param string $value
* Debug information value.
* {@inheritdoc}
*/
public function appendInfo(string $label, string $value): void {
$this->info[$label] = $value;
}

/**
* Render information.
*
* @return string
* Rendered debug information.
* {@inheritdoc}
*/
public function renderInfo(): string {
$this->compileInfo();
Expand Down Expand Up @@ -286,16 +294,6 @@
}
}

/**
* Get screenshot directory.
*
* @return string
* Screenshot directory.
*/
public function getDir(): string {
return $this->dir;
}

/**
* Get current timestamp.
*
Expand All @@ -304,36 +302,10 @@
*
* @codeCoverageIgnore
*/
public function getCurrentTime(): int {
protected function getCurrentTime(): int {
return time();
}

/**
* Save screenshot content into a file.
*
* @param string $filename
* File name to write.
* @param string $content
* Content to write into a file.
*/
protected function saveScreenshotContent(string $filename, string $content): void {
$this->prepareDir($this->dir);
$success = file_put_contents($this->dir . DIRECTORY_SEPARATOR . $filename, $content);
if ($success === FALSE) {
throw new \RuntimeException(sprintf('Failed to save screenshot to %s', $filename));
}
}

/**
* Prepare directory.
*
* @param string $dir
* Name of preparing directory.
*/
protected function prepareDir(string $dir): void {
(new Filesystem())->mkdir($dir, 0755);
}

/**
* Make screenshot filename.
*
Expand Down Expand Up @@ -385,12 +357,12 @@

$data = [
'ext' => $ext,
'step_name' => $step->getText(),
'step_line' => $step->getLine(),
'fail_prefix' => $this->failPrefix,
'feature_file' => $feature->getFile(),
'url' => $url,
'step_line' => $step->getLine(),
'step_name' => $step->getText(),
'timestamp' => $this->getCurrentTime(),
'fail_prefix' => $this->failPrefix,
'url' => $url,
];

return Tokenizer::replaceTokens($filename, $data);
Expand Down
Loading