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

Fixing window switching on Selenium 3 #384

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
122 changes: 110 additions & 12 deletions src/Selenium2Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
*/
class Selenium2Driver extends CoreDriver
{
private const W3C_WINDOW_HANDLE_PREFIX = 'w3cwh:';

/**
* Whether the browser has been started
* @var bool
Expand Down Expand Up @@ -64,6 +66,11 @@ class Selenium2Driver extends CoreDriver
*/
private $timeouts = array();

/**
* @var string|null
*/
private $initialWindowHandle = null;

/**
* @var Escaper
*/
Expand Down Expand Up @@ -340,6 +347,7 @@ public function start()
$this->started = true;

$this->applyTimeouts();
$this->initialWindowHandle = $this->getWebDriverSession()->window_handle();
}

/**
Expand Down Expand Up @@ -395,7 +403,20 @@ public function stop()

public function reset()
{
$this->getWebDriverSession()->deleteAllCookies();
$webDriverSession = $this->getWebDriverSession();

// Close all windows except the initial one.
foreach ($webDriverSession->window_handles() as $windowHandle) {
if ($windowHandle === $this->initialWindowHandle) {
continue;
}

$webDriverSession->focusWindow($windowHandle);
$webDriverSession->deleteWindow();
}

$this->switchToWindow();
$webDriverSession->deleteAllCookies();
}

public function visit(string $url)
Expand Down Expand Up @@ -425,7 +446,40 @@ public function back()

public function switchToWindow(?string $name = null)
{
$this->getWebDriverSession()->focusWindow($name ?: '');
$handle = $name === null
? $this->initialWindowHandle
: $this->getWindowHandleFromName($name);

$this->getWebDriverSession()->focusWindow($handle);
}

/**
* @throws DriverException
*/
private function getWindowHandleFromName(string $name): string
{
// if name is actually prefixed window handle, just remove the prefix
if (strpos($name, self::W3C_WINDOW_HANDLE_PREFIX) === 0) {
return substr($name, strlen(self::W3C_WINDOW_HANDLE_PREFIX));
}

// ..otherwise check if any existing window has the specified name

$origWindowHandle = $this->getWebDriverSession()->window_handle();

try {
foreach ($this->getWebDriverSession()->window_handles() as $handle) {
aik099 marked this conversation as resolved.
Show resolved Hide resolved
$this->getWebDriverSession()->focusWindow($handle);

if ($this->evaluateScript('window.name') === $name) {
return $handle;
}
}

throw new DriverException("Could not find handle of window named \"$name\"");
} finally {
$this->getWebDriverSession()->focusWindow($origWindowHandle);
}
}

public function switchToIFrame(?string $name = null)
Expand Down Expand Up @@ -492,12 +546,29 @@ public function getScreenshot()

public function getWindowNames()
{
return $this->getWebDriverSession()->window_handles();
$origWindow = $this->getWebDriverSession()->window_handle();

try {
$result = array();
foreach ($this->getWebDriverSession()->window_handles() as $tempWindow) {
$this->getWebDriverSession()->focusWindow($tempWindow);
aik099 marked this conversation as resolved.
Show resolved Hide resolved
$result[] = $this->getWindowName();
}
return $result;
} finally {
$this->getWebDriverSession()->focusWindow($origWindow);
}
}

public function getWindowName()
{
return $this->getWebDriverSession()->window_handle();
$name = (string) $this->evaluateScript('window.name');

if ($name === '') {
$name = self::W3C_WINDOW_HANDLE_PREFIX . $this->getWebDriverSession()->window_handle();
}

return $name;
}

/**
Expand Down Expand Up @@ -921,11 +992,13 @@ public function wait(int $timeout, string $condition)

public function resizeWindow(int $width, int $height, ?string $name = null)
{
$window = $this->getWebDriverSession()->window($name ?: 'current');
\assert($window instanceof Window);
$window->postSize(
array('width' => $width, 'height' => $height)
);
$this->withWindow($name, function () use ($width, $height) {
$window = $this->getWebDriverSession()->window('current');
\assert($window instanceof Window);
$window->postSize(
array('width' => $width, 'height' => $height)
);
});
}

public function submitForm(string $xpath)
Expand All @@ -935,9 +1008,34 @@ public function submitForm(string $xpath)

public function maximizeWindow(?string $name = null)
{
$window = $this->getWebDriverSession()->window($name ?: 'current');
\assert($window instanceof Window);
$window->maximize();
$this->withWindow($name, function () {
$window = $this->getWebDriverSession()->window('current');
\assert($window instanceof Window);
$window->maximize();
});
}

private function withWindow(?string $name, callable $callback): void
{
if ($name === null) {
$callback();

return;
}

$origName = $this->getWindowName();

try {
if ($origName !== $name) {
$this->switchToWindow($name);
}

$callback();
} finally {
if ($origName !== $name) {
$this->switchToWindow($origName);
}
}
}

/**
Expand Down
Loading