From 7d71e14909a68b5067ae553d9a8c42f3e89c5622 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 7 Apr 2024 19:24:33 +0300 Subject: [PATCH 1/6] Harden window closing code upon session reset --- src/WebdriverClassicDriver.php | 11 ++++-- tests/Custom/SessionResetTest.php | 62 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 tests/Custom/SessionResetTest.php diff --git a/src/WebdriverClassicDriver.php b/src/WebdriverClassicDriver.php index eb532f4..d1d66ff 100644 --- a/src/WebdriverClassicDriver.php +++ b/src/WebdriverClassicDriver.php @@ -138,14 +138,19 @@ public function reset(): void { // switch to default window.. $this->switchToWindow(); + $actualInitialWindowName = $this->getWindowName(); // Account for initial window rename. + $webDriver = $this->getWebDriver(); + // ..and close all other windows foreach ($this->getWindowNames() as $name) { - if ($name !== $this->initialWindowName) { - $this->withWindow($name, fn() => $this->getWebDriver()->close()); + if ($name !== $actualInitialWindowName) { + $this->switchToWindow($name); + $webDriver->close(); + $this->switchToWindow(); } } - $this->getWebDriver()->manage()->deleteAllCookies(); + $webDriver->manage()->deleteAllCookies(); } public function visit(string $url): void diff --git a/tests/Custom/SessionResetTest.php b/tests/Custom/SessionResetTest.php new file mode 100644 index 0000000..b5e019a --- /dev/null +++ b/tests/Custom/SessionResetTest.php @@ -0,0 +1,62 @@ +getSession(); + $session->visit($this->pathTo('/window.html')); + + if (null !== $initialWindowName) { + $session->executeScript('window.name = "'.$initialWindowName.'";'); + } + + $page = $session->getPage(); + + $page->clickLink('Popup #1'); + $page->clickLink('Popup #2'); + + $expectedInitialWindowName = $session->evaluateScript('window.name'); + + $windowNames = $session->getWindowNames(); + $this->assertCount(3, $windowNames); + + $session->reset(); + + $windowNames = $session->getWindowNames(); + $this->assertCount(1, $windowNames); + + $actualInitialWindowName = $session->evaluateScript('window.name'); + $this->assertEquals($expectedInitialWindowName, $actualInitialWindowName); + } + + public static function initialWindowNameDataProvider(): array + { + return array( + 'no name' => array(null), + 'non-empty name' => array('initial-window'), + ); + } + + /** + * @after + */ + protected function resetSessions() + { + $session = $this->getSession(); + + // Stop the session instead of resetting, because resetting behavior is being tested. + if ($session->isStarted()) { + $session->stop(); + } + + parent::resetSessions(); + } +} From 32704591f1036e5cf3664c6a161d7933c97e93f0 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 8 Apr 2024 21:20:18 +0300 Subject: [PATCH 2/6] Rewritten implementation to window handles directly (avoids name-to-handle conversion code) --- src/WebdriverClassicDriver.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/WebdriverClassicDriver.php b/src/WebdriverClassicDriver.php index d1d66ff..31357bd 100644 --- a/src/WebdriverClassicDriver.php +++ b/src/WebdriverClassicDriver.php @@ -136,17 +136,18 @@ public function stop(): void */ public function reset(): void { - // switch to default window.. - $this->switchToWindow(); - $actualInitialWindowName = $this->getWindowName(); // Account for initial window rename. $webDriver = $this->getWebDriver(); + // switch to default window.. + $initialWindow = substr((string)$this->initialWindowName, strlen(self::W3C_WINDOW_HANDLE_PREFIX)); + $webDriver->switchTo()->window($initialWindow); + // ..and close all other windows - foreach ($this->getWindowNames() as $name) { - if ($name !== $actualInitialWindowName) { - $this->switchToWindow($name); + foreach ($webDriver->getWindowHandles() as $tempWindow) { + if ($tempWindow !== $initialWindow) { + $webDriver->switchTo()->window($tempWindow); $webDriver->close(); - $this->switchToWindow(); + $webDriver->switchTo()->window($initialWindow); } } From da234b21241f08af0902c8fe5aa09f9bed3cf7e4 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 9 Apr 2024 09:12:18 +0300 Subject: [PATCH 3/6] Use initial window handle instead of name --- src/WebdriverClassicDriver.php | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/WebdriverClassicDriver.php b/src/WebdriverClassicDriver.php index 31357bd..65f6966 100644 --- a/src/WebdriverClassicDriver.php +++ b/src/WebdriverClassicDriver.php @@ -78,7 +78,7 @@ class WebdriverClassicDriver extends CoreDriver private string $webDriverHost; - private ?string $initialWindowName = null; + private ?string $initialWindowHandle = null; /** * @param string $browserName One of 'edge', 'firefox', 'chrome' or any one of {@see WebDriverBrowserType} constants. @@ -104,7 +104,7 @@ public function start(): void try { $this->webDriver = RemoteWebDriver::create($this->webDriverHost, $this->desiredCapabilities); $this->applyTimeouts(); - $this->initialWindowName = $this->getWindowName(); + $this->initialWindowHandle = $this->getWebDriver()->getWindowHandle(); } catch (\Throwable $e) { throw new DriverException("Could not start driver: {$e->getMessage()}", 0, $e); } @@ -138,17 +138,18 @@ public function reset(): void { $webDriver = $this->getWebDriver(); - // switch to default window.. - $initialWindow = substr((string)$this->initialWindowName, strlen(self::W3C_WINDOW_HANDLE_PREFIX)); - $webDriver->switchTo()->window($initialWindow); + // Switch to default window. + $this->switchToWindow(); - // ..and close all other windows - foreach ($webDriver->getWindowHandles() as $tempWindow) { - if ($tempWindow !== $initialWindow) { - $webDriver->switchTo()->window($tempWindow); - $webDriver->close(); - $webDriver->switchTo()->window($initialWindow); + // Close all windows except the initial one. + foreach ($webDriver->getWindowHandles() as $windowHandle) { + if ($windowHandle === $this->initialWindowHandle) { + continue; } + + $webDriver->switchTo()->window($windowHandle); + $webDriver->close(); + $this->switchToWindow(); } $webDriver->manage()->deleteAllCookies(); @@ -181,13 +182,9 @@ public function back(): void public function switchToWindow(?string $name = null): void { - if ($name === null) { - $name = $this->initialWindowName; - } - - if (is_string($name)) { - $name = $this->getWindowHandleFromName($name); - } + $name = $name === null + ? $this->initialWindowHandle + : $this->getWindowHandleFromName($name); $this->getWebDriver()->switchTo()->window((string)$name); } From e58c490012d9497ba33cbd1af72ffb86a42da931 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 9 Apr 2024 15:27:41 +0300 Subject: [PATCH 4/6] Simplify window closing code upon session reset --- src/WebdriverClassicDriver.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/WebdriverClassicDriver.php b/src/WebdriverClassicDriver.php index 65f6966..2277912 100644 --- a/src/WebdriverClassicDriver.php +++ b/src/WebdriverClassicDriver.php @@ -138,9 +138,6 @@ public function reset(): void { $webDriver = $this->getWebDriver(); - // Switch to default window. - $this->switchToWindow(); - // Close all windows except the initial one. foreach ($webDriver->getWindowHandles() as $windowHandle) { if ($windowHandle === $this->initialWindowHandle) { @@ -149,9 +146,9 @@ public function reset(): void $webDriver->switchTo()->window($windowHandle); $webDriver->close(); - $this->switchToWindow(); } + $this->switchToWindow(); $webDriver->manage()->deleteAllCookies(); } From 43666a6985ec0a6ff9935be393a2ea527e07814f Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 9 Apr 2024 15:57:23 +0300 Subject: [PATCH 5/6] Moving window closing upon session reset test into the `driver-testsuite` --- tests/Custom/SessionResetTest.php | 62 ------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 tests/Custom/SessionResetTest.php diff --git a/tests/Custom/SessionResetTest.php b/tests/Custom/SessionResetTest.php deleted file mode 100644 index b5e019a..0000000 --- a/tests/Custom/SessionResetTest.php +++ /dev/null @@ -1,62 +0,0 @@ -getSession(); - $session->visit($this->pathTo('/window.html')); - - if (null !== $initialWindowName) { - $session->executeScript('window.name = "'.$initialWindowName.'";'); - } - - $page = $session->getPage(); - - $page->clickLink('Popup #1'); - $page->clickLink('Popup #2'); - - $expectedInitialWindowName = $session->evaluateScript('window.name'); - - $windowNames = $session->getWindowNames(); - $this->assertCount(3, $windowNames); - - $session->reset(); - - $windowNames = $session->getWindowNames(); - $this->assertCount(1, $windowNames); - - $actualInitialWindowName = $session->evaluateScript('window.name'); - $this->assertEquals($expectedInitialWindowName, $actualInitialWindowName); - } - - public static function initialWindowNameDataProvider(): array - { - return array( - 'no name' => array(null), - 'non-empty name' => array('initial-window'), - ); - } - - /** - * @after - */ - protected function resetSessions() - { - $session = $this->getSession(); - - // Stop the session instead of resetting, because resetting behavior is being tested. - if ($session->isStarted()) { - $session->stop(); - } - - parent::resetSessions(); - } -} From d04dfda3cfc42baf1fe7302cc4e79a6183e6b130 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 28 Jun 2024 12:31:48 +0300 Subject: [PATCH 6/6] Renamed variables in the "switchToWindow" method to better explain code logic --- src/WebdriverClassicDriver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WebdriverClassicDriver.php b/src/WebdriverClassicDriver.php index 2277912..07c8438 100644 --- a/src/WebdriverClassicDriver.php +++ b/src/WebdriverClassicDriver.php @@ -179,11 +179,11 @@ public function back(): void public function switchToWindow(?string $name = null): void { - $name = $name === null + $handle = $name === null ? $this->initialWindowHandle : $this->getWindowHandleFromName($name); - $this->getWebDriver()->switchTo()->window((string)$name); + $this->getWebDriver()->switchTo()->window((string)$handle); } public function switchToIFrame(?string $name = null): void