Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

Commit 5018547

Browse files
authored
Merge pull request #701 from sapzape/take-element-screenshot
Add take element screenshot command
2 parents 0bf4f38 + 0c36f13 commit 5018547

File tree

6 files changed

+89
-1
lines changed

6 files changed

+89
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ This project versioning adheres to [Semantic Versioning](http://semver.org/).
55

66
### Added
77
- Experimental W3C WebDriver protocol support. The protocol will be used automatically when remote end (like Geckodriver, newer Chromedriver etc.) supports it.
8-
- `getStatus()` method of RemoteWebDriver to get information about remote-end readiness to create new sessions.
8+
- `getStatus()` method of `RemoteWebDriver` to get information about remote-end readiness to create new sessions.
9+
- `takeElementScreenshot()` method of `RemoteWebElement` to do the obvious - take screenshot of the particular element.
910

1011
### Changed
1112
- Revert no longer needed workaround for Chromedriver bug [2943](https://bugs.chromium.org/p/chromedriver/issues/detail?id=2943).

lib/Remote/DriverCommand.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ class DriverCommand
149149
// W3C specific
150150
const ACTIONS = 'actions';
151151
const GET_ELEMENT_PROPERTY = 'getElementProperty';
152+
const TAKE_ELEMENT_SCREENSHOT = 'takeElementScreenshot';
152153

153154
private function __construct()
154155
{

lib/Remote/HttpCommandExecutor.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ class HttpCommandExecutor implements WebDriverCommandExecutor
129129
DriverCommand::STATUS => ['method' => 'GET', 'url' => '/status'],
130130
DriverCommand::SUBMIT_ELEMENT => ['method' => 'POST', 'url' => '/session/:sessionId/element/:id/submit'],
131131
DriverCommand::SCREENSHOT => ['method' => 'GET', 'url' => '/session/:sessionId/screenshot'],
132+
DriverCommand::TAKE_ELEMENT_SCREENSHOT => [
133+
'method' => 'GET',
134+
'url' => '/session/:sessionId/element/:id/screenshot',
135+
],
132136
DriverCommand::TOUCH_SINGLE_TAP => ['method' => 'POST', 'url' => '/session/:sessionId/touch/click'],
133137
DriverCommand::TOUCH_DOWN => ['method' => 'POST', 'url' => '/session/:sessionId/touch/down'],
134138
DriverCommand::TOUCH_DOUBLE_TAP => ['method' => 'POST', 'url' => '/session/:sessionId/touch/doubleclick'],

lib/Remote/RemoteWebElement.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,33 @@ public function getID()
431431
return $this->id;
432432
}
433433

434+
/**
435+
* Take screenshot of a specific element.
436+
*
437+
* @param string $save_as The path of the screenshot to be saved.
438+
* @return string The screenshot in PNG format.
439+
*/
440+
public function takeElementScreenshot($save_as = null)
441+
{
442+
$screenshot = base64_decode(
443+
$this->executor->execute(
444+
DriverCommand::TAKE_ELEMENT_SCREENSHOT,
445+
[':id' => $this->id]
446+
)
447+
);
448+
449+
if ($save_as) {
450+
$directoryPath = dirname($save_as);
451+
if (!file_exists($directoryPath)) {
452+
mkdir($directoryPath, 0777, true);
453+
}
454+
455+
file_put_contents($save_as, $screenshot);
456+
}
457+
458+
return $screenshot;
459+
}
460+
434461
/**
435462
* Test if two element IDs refer to the same DOM element.
436463
*

lib/WebDriverElement.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,13 @@ public function submit();
132132
* @return string The opaque ID.
133133
*/
134134
public function getID();
135+
136+
/**
137+
* Take screenshot of a specific element.
138+
*
139+
* @param string $save_as The path of the screenshot to be saved.
140+
* @return string The screenshot in PNG format.
141+
* @todo Add in next major release (BC)
142+
*/
143+
//public function takeElementScreenshot($save_as = null);
135144
}

tests/functional/RemoteWebElementTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
use Facebook\WebDriver\Exception\NoSuchElementException;
1919
use Facebook\WebDriver\Remote\RemoteWebElement;
20+
use Facebook\WebDriver\Remote\WebDriverBrowserType;
2021

2122
/**
2223
* @coversDefaultClass \Facebook\WebDriver\Remote\RemoteWebElement
@@ -336,4 +337,49 @@ public function testShouldFindMultipleChildElements()
336337
$this->assertCount(3, $childElements); // but we should find only subelements of one <ul>
337338
$this->assertContainsOnlyInstancesOf(RemoteWebElement::class, $childElements);
338339
}
340+
341+
/**
342+
* @covers ::takeElementScreenshot
343+
* @group exclude-saucelabs
344+
*/
345+
public function testShouldTakeAndSaveElementScreenshot()
346+
{
347+
self::skipForJsonWireProtocol('Take element screenshot is only part of W3C protocol');
348+
349+
if (!extension_loaded('gd')) {
350+
$this->markTestSkipped('GD extension must be enabled');
351+
}
352+
if ($this->desiredCapabilities->getBrowserName() === WebDriverBrowserType::HTMLUNIT) {
353+
$this->markTestSkipped('Screenshots are not supported by HtmlUnit browser');
354+
}
355+
356+
// Intentionally save screenshot to subdirectory to tests it is being created
357+
$screenshotPath = sys_get_temp_dir() . '/' . uniqid('php-webdriver-') . '/element-screenshot.png';
358+
359+
$this->driver->get($this->getTestPageUrl('index.html'));
360+
361+
$element = $this->driver->findElement(WebDriverBy::id('red-box'));
362+
363+
$outputPngString = $element->takeElementScreenshot($screenshotPath);
364+
365+
// Assert file output
366+
$imageFromFile = imagecreatefrompng($screenshotPath);
367+
$this->assertEquals(5, imagesx($imageFromFile));
368+
$this->assertEquals(5, imagesy($imageFromFile));
369+
370+
// Validate element is actually red
371+
$this->assertSame(
372+
['red' => 255, 'green' => 0, 'blue' => 0, 'alpha' => 0],
373+
imagecolorsforindex($imageFromFile, imagecolorat($imageFromFile, 0, 0))
374+
);
375+
376+
// Assert string output
377+
$imageFromString = imagecreatefromstring($outputPngString);
378+
$this->assertInternalType('resource', $imageFromString);
379+
$this->assertEquals(5, imagesx($imageFromString));
380+
$this->assertEquals(5, imagesy($imageFromString));
381+
382+
unlink($screenshotPath);
383+
rmdir(dirname($screenshotPath));
384+
}
339385
}

0 commit comments

Comments
 (0)