Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright (C) 2000-2026 Vaadin Ltd
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See <https://vaadin.com/commercial-license-and-service-terms> for the full
* license.
*/
package com.vaadin.testUI;

import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.NativeButton;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.router.Route;

@Route("ButtonView")
public class ButtonView extends Div {

public ButtonView() {
NativeButton button = new NativeButton("Click me");
button.setId("test-button");
button.addSingleClickListener(event -> {
Span newSpan = new Span(
"Button single clicked: " + event.getClickCount());
newSpan.setId("single-click");
add(newSpan);
});
button.addDoubleClickListener(event -> {
Span newSpan = new Span(
"Button double clicked: " + event.getClickCount());
newSpan.setId("double-click");
add(newSpan);
});
button.addFocusListener(event -> {
Span newSpan = new Span("Button focused");
newSpan.setId("focus-event");
add(newSpan);
});
add(button);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* Copyright (C) 2000-2026 Vaadin Ltd
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See <https://vaadin.com/commercial-license-and-service-terms> for the full
* license.
*/
package com.vaadin.tests.elements;

import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;

import com.vaadin.flow.component.Component;
import com.vaadin.testUI.ButtonView;
import com.vaadin.tests.AbstractTB6Test;

import static org.junit.Assert.assertEquals;

public class ButtonIT extends AbstractTB6Test {

@Override
protected Class<? extends Component> getTestView() {
return ButtonView.class;
}

@Before
public void openAndFindElement() {
openTestURL();
}

@Test
public void buttonClick_singleClick() {
$(NativeButtonElement.class).id("test-button").click();
assertEquals("Button single clicked: 1",
findElement(By.id("single-click")).getText());
assertEquals("Button focused",
findElement(By.id("focus-event")).getText());
}

@Test
public void buttonClick_doubleClick() {
$(NativeButtonElement.class).id("test-button").doubleClick();
assertEquals("Button double clicked: 2",
findElement(By.id("double-click")).getText());
assertEquals("Button focused",
findElement(By.id("focus-event")).getText());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -191,23 +191,9 @@ public boolean isFocused() {

@Override
public void click() {
// JS call to click does not focus element, hence ensure focus
focus();
try {
// Avoid strange "element not clickable at point" problems
callFunction("click");
} catch (Exception e) {
if (e.getMessage()
.contains("Inspected target navigated or closed")) {
// This happens with chromedriver although e.g. navigation
// succeeds
return;
}
// SVG elements and maybe others do not have a 'click' method
autoScrollIntoView();
waitForVaadin();
wrappedElement.click();
}
autoScrollIntoView();
waitForVaadin();
new Actions(getDriver()).click(wrappedElement).build().perform();
}

@Override
Expand Down Expand Up @@ -363,12 +349,20 @@ public void click(int x, int y, Keys... modifiers) {
actions.build().perform();
}

/**
* Performs a double-click action on this element.
*
* @see click()
*/
public void doubleClick() {
autoScrollIntoView();
waitForVaadin();
new Actions(getDriver()).doubleClick(wrappedElement).build().perform();
}

/**
* Performs a context-click (right click) action on this element.
*/
public void contextClick() {
autoScrollIntoView();
waitForVaadin();
Expand Down Expand Up @@ -520,7 +514,20 @@ public boolean compareScreen(BufferedImage reference, String referenceName)
(TakesScreenshot) this, (HasCapabilities) getDriver());
}

/***
/**
* Scrolls the element into the visible area of the browser window with the
* given options. Check
* https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
* for more information on the options.
*
* @param options
* the parameters for scrolling into view
*/
public void scrollIntoView(Map<String, Object> options) {
callFunction("scrollIntoView", options);
}

/**
* Scrolls the element into the visible area of the browser window
*/
public void scrollIntoView() {
Expand All @@ -534,15 +541,65 @@ public void scrollIntoView() {
*/
private void autoScrollIntoView() {
try {
if (getCommandExecutor().isAutoScrollIntoView()) {
if (!wrappedElement.isDisplayed()) {
scrollIntoView();
}
if (getCommandExecutor().isAutoScrollIntoView()
&& !isElementInViewport()) {
var params = Map.<String, Object> of("block", "end", "inline",
"end");
scrollIntoView(params);
}
} catch (Exception e) {
}
}

private boolean isElementInViewport() {
try {
Boolean result = (Boolean) executeScript(
"""
function isVisible(elem) {
// Check if element has zero dimensions (truly hidden)
if (!elem.offsetParent && elem.offsetWidth === 0 && elem.offsetHeight === 0) {
return false;
}

var rect = elem.getBoundingClientRect();
if (rect.width === 0 || rect.height === 0) {
return false;
}

// Check if element intersects with viewport
var windowHeight = window.innerHeight || document.documentElement.clientHeight;
var windowWidth = window.innerWidth || document.documentElement.clientWidth;
if (rect.bottom < 0 || rect.top > windowHeight || rect.right < 0 || rect.left > windowWidth) {
return false;
}

// Check if clipped by any scrollable ancestor
var parent = elem.parentElement;
while (parent && parent !== document.body) {
var style = window.getComputedStyle(parent);
var overflow = style.overflow + style.overflowX + style.overflowY;

if (overflow.includes('hidden') || overflow.includes('scroll') || overflow.includes('auto')) {
var parentRect = parent.getBoundingClientRect();
// Check if element is outside parent's visible area
if (rect.bottom < parentRect.top || rect.top > parentRect.bottom ||
rect.right < parentRect.left || rect.left > parentRect.right) {
return false;
}
}
parent = parent.parentElement;
}
return true;
}
return isVisible(arguments[0]);
""",
this);
return result != null && result;
} catch (Exception e) {
return true; // Assume visible on error
}
}

/**
* Waits the given number of seconds for the given condition to become
* neither null nor false. {@link NotFoundException}s are ignored by
Expand Down
Loading