> Markdown version of [Test User Interactions](https://vaadin.com/docs/next/building-apps/testing/browserless/test-user-interactions). Section index: [llms.txt](https://vaadin.com/docs/next/building-apps/llms.txt)

# Test User Interactions

The examples in this guide use the plain Java setup. For another framework, change the base class as described in [Use the Examples with Your Framework](https://vaadin.com/docs/next/building-apps/testing/browserless.md#use-examples-with-your-framework). Each example belongs inside a test method unless shown otherwise.

## <a id="how-a-browserless-test-works"></a>How a Browserless Test Works

Each setup guide ends with a test for the same `HelloWorldView`. The test navigates to the view, enters a name, clicks a button, and checks the notification that appears:

```java
final HelloWorldView helloView = navigate(HelloWorldView.class);

test(helloView.name).setValue("Test");
test(helloView.sayHello).click();

Notification notification = find(Notification.class).single();
Assertions.assertEquals("Hello Test", test(notification).getText());
```

The following sections explain each step. They work the same way with every setup; only the test base class differs.

### <a id="navigate-to-a-view"></a>Navigate to a View

The `navigate()` method opens a view, as a user would navigate to it in the browser. It returns the view instance so you can interact with it directly.

```java
final HelloWorldView helloView = navigate(HelloWorldView.class);
```

### <a id="use-the-java-api-directly"></a>Use the Java API Directly

Since the test runs on the server side, it has direct access to the Java component API. The `TextField` and `Button` fields of `HelloWorldView` are package-private, so a test in the same Java package can read them — for example, if the view is in `src/main/java/com/example/app/`, put the test in `src/test/java/com/example/app/`.

```java
// Read a component's value directly
String currentValue = helloView.name.getValue();

// Check component state
boolean isEnabled = helloView.sayHello.isEnabled();
boolean isVisible = helloView.name.isVisible();
```

### <a id="simulate-user-actions-with-testers"></a>Simulate User Actions with Testers

To simulate how a user interacts with a component, wrap it with `test()`. This returns a component-specific tester that provides methods like `setValue()`, `click()`, and `getText()`. Unlike calling the Java API directly, tester methods also verify that the component is in a usable state — visible, enabled, and attached to the UI.

```java
// Simulate typing into a text field
test(helloView.name).setValue("Test");

// Simulate clicking a button
test(helloView.sayHello).click();

// Read the text a user would see
String text = test(notification).getText();
```

Each Vaadin component has a tester tailored to its behavior. For example, a `CheckboxTester` uses `click()` to toggle checked state, a `ComboBoxTester` has `selectItem()`, and a `GridTester` has `getRow()`. See [Component Testers](https://vaadin.com/docs/next/flow/testing/browserless/component-testers.md) for supported operations and [Test a Custom Component](https://vaadin.com/docs/next/building-apps/testing/browserless/test-custom-components.md) to build your own tester.

### <a id="find-components"></a>Find Components

Not every component is stored in a view field. For example, the `Notification` in the test is created inside a click listener and isn’t referenced anywhere in the view. Use the `find()` query method to find components in the UI by their type:

```java
// Find the single Notification currently open
Notification notification = find(Notification.class).single();
```

The query API supports filtering by properties, predicates, and scoping to specific parts of the component tree. See [Querying Components](https://vaadin.com/docs/next/flow/testing/browserless/component-query.md) for details.

## <a id="find-the-component-to-exercise"></a>Find the Component to Exercise

Use a label or visible text when it identifies the component unambiguously. When the same field appears more than once, for example in the view and in an open dialog, scope the query to the view:

```java
TextField name = findInView(TextField.class)
        .withLabel("First name").single();
test(name).setValue("Ada");
Assertions.assertEquals("Ada", name.getValue());
```

Use `find(Type.class, container)` to restrict a query to a particular container. A component inside a Grid renderer may need to be obtained through `test(grid).getCellComponent(…​)` before it can be exercised. If a top-level query finds nothing, the component may be inside a renderer or a closed overlay, which queries don’t reach. See [Query Boundaries](https://vaadin.com/docs/next/flow/testing/browserless/component-query.md#components-a-query-cannot-find) and [Component Queries](https://vaadin.com/docs/next/flow/testing/browserless/component-query.md) for the full behavior.

## <a id="fill-in-and-submit-a-form"></a>Fill In and Submit a Form

Set each field through its tester, then click the submit button. For a `SignUpView` with a **Name** text field, an **Email** email field, and a **Sign up** button that shows a welcome notification:

```java
navigate(SignUpView.class);
test(find(TextField.class).withLabel("Name").single()).setValue("Ada");
test(find(EmailField.class).withLabel("Email").single())
        .setValue("ada@example.com");
test(find(Button.class).withText("Sign up").single()).click();

Assertions.assertEquals("Welcome, Ada",
        test(find(Notification.class).single()).getText());
```

A tester sets the value the way a user does, so the field’s validation runs as it would in the browser:

```java
EmailField email = find(EmailField.class).withLabel("Email").single();
test(email).setValue("not an email");
Assertions.assertTrue(email.isInvalid());
```

## <a id="select-a-grid-row"></a>Select a Grid Row

Use the Grid tester to read rows and select items. For a `PersonListView` with a `people` grid of `Person` items and a `details` span that shows the selected person:

```java
var view = navigate(PersonListView.class);
var grid = test(view.people);
Assertions.assertEquals(3, grid.size());
Assertions.assertEquals("Ada", grid.getCellText(0, 0));

grid.select(0);
Assertions.assertEquals("Selected: Ada", view.details.getText());
```

The tester also has `clickRow()` for views that react to item clicks, and `getRow()` for reading the item on a row. See [Component Testers](https://vaadin.com/docs/next/flow/testing/browserless/component-testers.md) for the other Grid operations.

## <a id="confirm-a-dialog"></a>Confirm a Dialog

An open dialog is attached to the UI, so a top-level query finds it. For an `AccountView` whose **Delete account** button opens a `ConfirmDialog`, and whose `status` span reports the result:

```java
var view = navigate(AccountView.class);
test(find(Button.class).withText("Delete account").single()).click();

var dialog = test(find(ConfirmDialog.class).single());
Assertions.assertEquals("Delete account?", dialog.getHeader());
dialog.confirm();

Assertions.assertEquals("Account deleted", view.status.getText());
```

Call `cancel()` or `reject()` on the tester to click the dialog’s other buttons. For a `Dialog`, find its buttons with `find()` while the dialog is open.

## <a id="test-ids"></a>Use Test IDs

Use `Component.setTestId()` to assign a stable identifier to a component for use in tests. This sets the `data-testid` HTML attribute on the component’s element, which can also be used by browser-based testing frameworks:

```java
Button submitButton = new Button("Submit");
submitButton.setTestId("submit-button");

// Later, retrieve the test ID
String testId = submitButton.getTestId(); // "submit-button"
```

Use a test ID when a label or visible text would be ambiguous or would change with translations. Keep the identifier independent of styling and layout.

Browserless tests can use the same identifier: the `testId()` terminal operator and the `withTestId()` filter (since V25.2) look up components by their test ID:

```java
Button submit = find(Button.class).testId("submit-button");
```

See [Querying Components](https://vaadin.com/docs/next/flow/testing/browserless/component-query.md#test-ids) for details.

## <a id="use-locators-for-repeated-interactions"></a>Use Locators for Repeated Interactions

If your test extends a base class, implement `Locators` to combine lookup and interaction in one call:

`CartViewLocatorsTest.java`

```java
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import com.vaadin.browserless.BrowserlessTest;
import com.vaadin.browserless.locator.Locators;

class CartViewLocatorsTest extends BrowserlessTest implements Locators {
    @Test
    void addItem_increasesCartSize() {
        navigate(CartView.class);
        findButton().withText("Add to cart").click();
        Assertions.assertEquals("1 item",
                findSpan().withId("cart-size").getText());
    }
}
```

This example assumes a `CartView` with an **Add to cart** button and a span with the ID `cart-size` that shows the number of items. With Java EE/CDI, add `implements Locators` to your `AbstractCdiViewTest` subclass. For locator reuse and invalidation rules, see [Locator Resolution](https://vaadin.com/docs/next/flow/testing/browserless/locators.md#resolution).

## <a id="test-navigation"></a>Test Navigation

Navigate by location when the outcome may be a redirect, and pass the view class you expect to end up in. The call fails if navigation ends in another view:

```java
navigate("protected", LoginView.class);
```

A location can also carry a query string and fragment; for example, `navigate("orders/123?tab=history#details", OrderView.class)` (since V25.3). Assert the state selected by those parameters after navigation.

For route parameters and other navigation forms, see [Navigation](https://vaadin.com/docs/next/flow/testing/browserless/test-environment.md#navigating-to-views).

## <a id="test-keyboard-shortcuts"></a>Test Keyboard Shortcuts

Fire a shortcut with `fireShortcut()`, then assert the same outcome as the matching button click. For a form with a `Ctrl`+`S` save shortcut:

```java
fireShortcut(Key.KEY_S, KeyModifier.CONTROL);
// Assert the saved state or the confirmation shown by your view.
```

## <a id="test-menu-actions"></a>Test Menu Actions

Use a menu tester to reach overlay content. For a view exposing a `contextMenu` field with a checkable **Bold** item:

```java
var view = navigate(EditorView.class);
var menu = test(view.contextMenu);
menu.open();
menu.clickItem("Bold");
Assertions.assertTrue(menu.isItemChecked("Bold"));
```

Open the menu before clicking items or reading their state; the tester throws an exception for a closed menu. For nested actions, pass a text path such as `clickItem("Share", "Email")`. For a menu containing custom components, call `test(menuComponent).find(…​)`. This query also works while the menu is closed, but the components it returns stay detached until the menu opens. See [Overlay Component Testers](https://vaadin.com/docs/next/flow/testing/browserless/overlay-components.md) for indexing and attachment semantics.

`BDC6250E-E9D6-44DD-9B67-777C0F7E98AA`
