Repository navigation
Test mouse interaction with elements outside the viewport #117
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| <?php | ||
|
|
||
| namespace Behat\Mink\Tests\Driver\Js; | ||
|
|
||
| use Behat\Mink\Element\NodeElement; | ||
| use Behat\Mink\Tests\Driver\TestCase; | ||
|
|
||
| /** | ||
| * Mouse interaction with elements that are outside the viewport. | ||
| */ | ||
| final class OutsideViewportTest extends TestCase | ||
| { | ||
| /** | ||
| * @group mouse-events | ||
| */ | ||
| public function testClick(): void | ||
| { | ||
| $element = $this->findOutsideViewport('click-target'); | ||
|
|
||
| $this->scrollToTop(); | ||
| $element->click(); | ||
|
|
||
| $this->assertElementText('clicked', $element); | ||
| } | ||
|
|
||
| /** | ||
| * @group mouse-events | ||
| */ | ||
| public function testDoubleClick(): void | ||
| { | ||
| $element = $this->findOutsideViewport('double-click-target'); | ||
|
|
||
| $this->scrollToTop(); | ||
| $element->doubleClick(); | ||
|
|
||
| $this->assertElementText('double clicked', $element); | ||
| } | ||
|
|
||
| /** | ||
| * @group mouse-events | ||
| */ | ||
| public function testRightClick(): void | ||
| { | ||
| $element = $this->findOutsideViewport('right-click-target'); | ||
|
|
||
| $this->scrollToTop(); | ||
| $element->rightClick(); | ||
|
|
||
| $this->assertElementText('right clicked', $element); | ||
| } | ||
|
|
||
| /** | ||
| * @group mouse-events | ||
| */ | ||
| public function testMouseOver(): void | ||
| { | ||
| $element = $this->findOutsideViewport('mouse-over-target'); | ||
|
|
||
| $this->scrollToTop(); | ||
| $element->mouseOver(); | ||
|
|
||
| $this->assertElementText('mouse overed', $element); | ||
| } | ||
|
|
||
| private function findOutsideViewport(string $id): NodeElement | ||
| { | ||
| $this->getSession()->visit($this->pathTo('/outside_viewport.html')); | ||
|
|
||
| $this->scrollToTop(); | ||
| $this->assertTrue( | ||
| $this->getSession()->evaluateScript( | ||
| 'document.getElementById("' . $id . '").getBoundingClientRect().top >= window.innerHeight' | ||
| ), | ||
| 'The element must be outside the viewport before the test' | ||
| ); | ||
|
|
||
| return $this->findById($id); | ||
| } | ||
|
|
||
| private function scrollToTop(): void | ||
| { | ||
| $this->getSession()->executeScript('window.scrollTo(0, 0);'); | ||
| } | ||
|
|
||
| private function assertElementText(string $expected, NodeElement $element): void | ||
| { | ||
| $this->scrollToTop(); | ||
| $this->assertSame($expected, $element->getText()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <title>Outside viewport</title> | ||
| <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> | ||
| </head> | ||
| <body> | ||
| <div style="height: 3000px;"></div> | ||
|
|
||
| <!-- in a row, so the mouse is never already over the next target --> | ||
| <div style="display: flex; gap: 20px;"> | ||
| <div id="click-target">not clicked</div> | ||
| <div id="double-click-target">not double clicked</div> | ||
| <div id="right-click-target">not right clicked</div> | ||
| <div id="mouse-over-target">not mouse overed</div> | ||
| </div> | ||
|
|
||
| <script type="text/javascript"> | ||
| document.getElementById('click-target').addEventListener('click', function () { | ||
| this.textContent = 'clicked'; | ||
| }); | ||
|
|
||
| document.getElementById('double-click-target').addEventListener('dblclick', function () { | ||
| this.textContent = 'double clicked'; | ||
| }); | ||
|
|
||
| document.getElementById('right-click-target').addEventListener('contextmenu', function (event) { | ||
| event.preventDefault(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm wondering if we should add
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @uuf6429, this deserves a separate task/pr with research attached. Test suite doesn't really fail without them, but to avoid any future failing tests due to unexpected event propagation, this could be handy. |
||
| this.textContent = 'right clicked'; | ||
| }); | ||
|
|
||
| document.getElementById('mouse-over-target').addEventListener('mouseover', function () { | ||
| this.textContent = 'mouse overed'; | ||
| }); | ||
| </script> | ||
| </body> | ||
| </html> | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just thinking out loud, could it make sense to use pointer events (which also capture touch etc) instead? Or do we maybe specifically want these mouse events?
I guess it's more of a question on the mink side - that touch events should be a different API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@uuf6429, we'd better create an issue in Mink repo itself for discussing such API.
Some ideas:
mouse*event trigger matchingpointer*event and vice versa)?What I try to avoid here is by making the current mouse-api acting as point event API causing a break for desktop users. If we do introduce parallel pointer-api, then could drivers actually handle it without Syn-based magic.