Skip to content

Commit 530f9bc

Browse files
committed
Merge pull request #39 from magento-qmt/develop
[Mavericks] Added a scroll up in case of element overlap and passing window handler to selectWindow()
2 parents 84e30a1 + 74ed69b commit 530f9bc

File tree

7 files changed

+240
-36
lines changed

7 files changed

+240
-36
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
1.0.0-rc.43
2+
===========
3+
* Added an ability scroll to up if element is overlapped by another element
4+
* Changed README.md to be consistent with devdocs
5+
* Added an ability to pass window handle to SelectWindow() method
6+
17
1.0.0-rc.42
28
===========
39
* Added date and time prefix to file artifacts name

Magento/Mtf/Client/Browser.php

+28-6
Original file line numberDiff line numberDiff line change
@@ -125,23 +125,45 @@ public function switchToFrame(Locator $locator = null)
125125
}
126126

127127
/**
128-
* Close the current window
128+
* Close the current window or specified one.
129129
*
130+
* @param string|null $handle [optional]
130131
* @return void
131132
*/
132-
public function closeWindow()
133+
public function closeWindow($handle = null)
133134
{
134-
$this->driver->closeWindow();
135+
$this->driver->closeWindow($handle);
135136
}
136137

137138
/**
138-
* Select window by its name
139+
* Changes the focus to the specified window or to the latest one.
139140
*
141+
* @param string|null $handle [optional]
140142
* @return void
141143
*/
142-
public function selectWindow()
144+
public function selectWindow($handle = null)
143145
{
144-
$this->driver->selectWindow();
146+
$this->driver->selectWindow($handle);
147+
}
148+
149+
/**
150+
* Retrieves the current window handle.
151+
*
152+
* @return string
153+
*/
154+
public function getCurrentWindow()
155+
{
156+
return $this->driver->getCurrentWindow();
157+
}
158+
159+
/**
160+
* Retrieves a list of all available window handles.
161+
*
162+
* @return array
163+
*/
164+
public function getWindowHandles()
165+
{
166+
return $this->driver->getWindowHandles();
145167
}
146168

147169
/**

Magento/Mtf/Client/BrowserInterface.php

+20-4
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,34 @@ public function reopen();
6060
public function switchToFrame(Locator $locator = null);
6161

6262
/**
63-
* Close the current window
63+
* Close the current window or specified one.
6464
*
65+
* @param string|null $handle [optional]
6566
* @return void
6667
*/
67-
public function closeWindow();
68+
public function closeWindow($handle = null);
6869

6970
/**
70-
* Select window by its name
71+
* Changes the focus to the specified window or to the latest one.
7172
*
73+
* @param string|null $handle [optional]
7274
* @return void
7375
*/
74-
public function selectWindow();
76+
public function selectWindow($handle = null);
77+
78+
/**
79+
* Retrieves the current window handle.
80+
*
81+
* @return string
82+
*/
83+
public function getCurrentWindow();
84+
85+
/**
86+
* Retrieves a list of all available window handles.
87+
*
88+
* @return array
89+
*/
90+
public function getWindowHandles();
7591

7692
/**
7793
* Find element on the page

Magento/Mtf/Client/Driver/Facebook/Driver.php

+37-6
Original file line numberDiff line numberDiff line change
@@ -589,24 +589,55 @@ public function switchToFrame(Locator $locator = null)
589589
}
590590

591591
/**
592-
* Close the current window
592+
* Close the current window or specified one.
593593
*
594+
* @param string|null $handle [optional]
594595
* @return void
595596
*/
596-
public function closeWindow()
597+
public function closeWindow($handle = null)
597598
{
598-
$this->driver->quit();
599+
$windowHandles = $this->driver->getWindowHandles();
600+
if (count($windowHandles) > 1) {
601+
$windowHandle = $handle !== null ? $handle : end($windowHandles);
602+
$this->driver->switchTo()->window($windowHandle);
603+
$this->driver->quit();
604+
$this->driver->switchTo()->window(reset($windowHandles));
605+
} else {
606+
$this->driver->quit();
607+
}
599608
}
600609

601610
/**
602-
* Select window by its name
611+
* Changes the focus to the specified window or to the latest one.
603612
*
613+
* @param string|null $handle [optional]
604614
* @return void
605615
*/
606-
public function selectWindow()
616+
public function selectWindow($handle = null)
607617
{
608618
$windowHandles = $this->driver->getWindowHandles();
609-
$this->driver->switchTo()->window(end($windowHandles));
619+
$windowHandle = $handle !== null ? $handle : end($windowHandles);
620+
$this->driver->switchTo()->window($windowHandle);
621+
}
622+
623+
/**
624+
* Retrieves the current window handle.
625+
*
626+
* @return string
627+
*/
628+
public function getCurrentWindow()
629+
{
630+
return $this->driver->getWindowHandle();
631+
}
632+
633+
/**
634+
* Retrieves a list of all available window handles.
635+
*
636+
* @return array
637+
*/
638+
public function getWindowHandles()
639+
{
640+
return $this->driver->getWindowHandles();
610641
}
611642

612643
/**

Magento/Mtf/Client/Driver/Selenium/Driver.php

+120-7
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,100 @@ public function click(ElementInterface $element)
248248

249249
$wrapperElement = $this->getNativeElement($element);
250250
$this->driver->moveto($wrapperElement);
251-
$wrapperElement->click();
251+
$this->tryClick($wrapperElement);
252252

253253
$this->eventManager->dispatchEvent(['click_after'], [__METHOD__, $absoluteSelector]);
254254
}
255255

256+
/**
257+
* Try to click on element.
258+
*
259+
* @param \PHPUnit_Extensions_Selenium2TestCase_Element $element
260+
* @param int $parentDepth [optional]
261+
* @param string $blockedElementSelector [optional]
262+
* @throws \PHPUnit_Extensions_Selenium2TestCase_WebDriverException
263+
*/
264+
private function tryClick(
265+
\PHPUnit_Extensions_Selenium2TestCase_Element $element,
266+
$parentDepth = 0,
267+
$blockedElementSelector = ''
268+
) {
269+
try {
270+
$element->click();
271+
} catch (\PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {
272+
$elementSelector = $this->prepareBlockedElementSelector($e->getMessage());
273+
$js = $this->prepareJSForScrollToUpByElement($elementSelector, $parentDepth, $blockedElementSelector);
274+
// Scroll action
275+
if (!$this->driver->execute(['script' => $js, 'args' => []])) {
276+
throw $e;
277+
}
278+
279+
$this->tryClick($element, ++$parentDepth, $elementSelector);
280+
}
281+
}
282+
283+
/**
284+
* Prepare blocked element selector base on exception message.
285+
* Example return: "element[attribute1="value"][attribute2="value"]..."
286+
*
287+
* @param string $exceptionMessage
288+
* @return string
289+
*/
290+
private function prepareBlockedElementSelector($exceptionMessage)
291+
{
292+
// Get html code
293+
$htmlCode = substr($exceptionMessage, 0, strpos($exceptionMessage, 'Command duration'));
294+
// Find element name
295+
preg_match('/<(\w+)/', $htmlCode, $matches);
296+
$elementSelector = isset($matches[1]) ? $matches[1] : '*';
297+
// Find element selector
298+
if (preg_match_all('/(([^ ]+)="([^"]+)")/', $htmlCode, $matches)) {
299+
foreach ($matches[0] as $match) {
300+
$match = str_replace('\n', '', $match); // skipped '\n'
301+
$match = str_replace("'", '"', $match); // escaped quotes
302+
$elementSelector .= "[{$match}]";
303+
}
304+
}
305+
306+
return $elementSelector;
307+
}
308+
309+
/**
310+
* Prepare JS script code for scroll to up relative element.
311+
*
312+
* @param string $elementSelector
313+
* @param int $parentDepth
314+
* @param string $blockedElementSelector
315+
* @return string
316+
*/
317+
private function prepareJSForScrollToUpByElement($elementSelector, $parentDepth, $blockedElementSelector)
318+
{
319+
return "var element = document.querySelector('$elementSelector'),
320+
height = 100;
321+
322+
// If element is founded
323+
if (element !== null) {
324+
/* If attempt isn't first and previous element selector is equal current
325+
need to scroll by parent element */
326+
if ($parentDepth && '$blockedElementSelector' == '$elementSelector') {
327+
for (var i = 0; i <= $parentDepth; i++) {
328+
element = element.parentElement;
329+
}
330+
}
331+
// If element is 'body', then need scroll and throw exception
332+
if (element === document.querySelector('body')) {
333+
return false;
334+
}
335+
336+
var elementHeight = element.offsetHeight;
337+
height = (elementHeight !== null) ? elementHeight : height
338+
}
339+
340+
scrollBy(0, -height);
341+
342+
return true;";
343+
}
344+
256345
/**
257346
* Double click.
258347
*
@@ -668,15 +757,17 @@ public function switchToFrame(Locator $locator = null)
668757
}
669758

670759
/**
671-
* Close the current window.
760+
* Close the current window or specified one.
672761
*
762+
* @param string|null $handle [optional]
673763
* @return void
674764
*/
675-
public function closeWindow()
765+
public function closeWindow($handle = null)
676766
{
677767
$windowHandles = $this->driver->windowHandles();
678768
if (count($windowHandles) > 1) {
679-
$this->driver->window(end($windowHandles));
769+
$windowHandle = $handle !== null ? $handle : end($windowHandles);
770+
$this->driver->window($windowHandle);
680771
$this->driver->closeWindow();
681772
$this->driver->window(reset($windowHandles));
682773
} else {
@@ -685,14 +776,36 @@ public function closeWindow()
685776
}
686777

687778
/**
688-
* Select window by its name.
779+
* Changes the focus to the specified window or to the latest one.
689780
*
781+
* @param string|null $handle [optional]
690782
* @return void
691783
*/
692-
public function selectWindow()
784+
public function selectWindow($handle = null)
693785
{
694786
$windowHandles = $this->driver->windowHandles();
695-
$this->driver->window(end($windowHandles));
787+
$windowHandle = $handle !== null ? $handle : end($windowHandles);
788+
$this->driver->window($windowHandle);
789+
}
790+
791+
/**
792+
* Retrieves the current window handle.
793+
*
794+
* @return string
795+
*/
796+
public function getCurrentWindow()
797+
{
798+
return $this->driver->windowHandle();
799+
}
800+
801+
/**
802+
* Retrieves a list of all available window handles.
803+
*
804+
* @return array
805+
*/
806+
public function getWindowHandles()
807+
{
808+
return $this->driver->windowHandles();
696809
}
697810

698811
/**

Magento/Mtf/Client/DriverInterface.php

+20-4
Original file line numberDiff line numberDiff line change
@@ -197,18 +197,34 @@ public function reopen();
197197
public function switchToFrame(Locator $locator);
198198

199199
/**
200-
* Close the current window
200+
* Close the current window or specified one.
201201
*
202+
* @param string|null $handle [optional]
202203
* @return void
203204
*/
204-
public function closeWindow();
205+
public function closeWindow($handle = null);
205206

206207
/**
207-
* Select window by its name
208+
* Changes the focus to the specified window or to the latest one.
208209
*
210+
* @param string|null $handle [optional]
209211
* @return void
210212
*/
211-
public function selectWindow();
213+
public function selectWindow($handle = null);
214+
215+
/**
216+
* Retrieves the current window handle.
217+
*
218+
* @return string
219+
*/
220+
public function getCurrentWindow();
221+
222+
/**
223+
* Retrieves a list of all available window handles.
224+
*
225+
* @return array
226+
*/
227+
public function getWindowHandles();
212228

213229
/**
214230
* Get page title text.

0 commit comments

Comments
 (0)