> Markdown version of [Component Testers](https://vaadin.com/docs/latest/flow/testing/browserless/component-testers). Section index: [llms.txt](https://vaadin.com/docs/latest/flow/llms.txt)

# Component Testers

Component testers simulate user interactions in browserless tests. Each tester wraps a specific component type and provides methods that mirror what a real user can do — clicking, typing, and selecting items.

Testers provide actions such as `setValue()`, `click()`, and `selectItem()` with usability checks. Some testers also expose component-specific inspection methods, such as grid row access and notification text. The component’s Java API remains available for reading values, visibility, and other state.

## <a id="using-component-testers"></a>Using Component Testers

Wrap any component with `test()` to get a tester for it:

```java
test(textField).setValue("Jane");
test(button).click();

// Reading state is done via the component API directly
String value = textField.getValue();
```

A tester drives the component through the same path the browser uses, so a listener that branches on `isFromClient()` behaves in a test as it does in a running application.

The `test()` method returns a tester matched to the component’s type. You can also request a specific tester type explicitly:

```java
TextFieldTester tester = test(TextFieldTester.class, textField);
```

### <a id="usability-checks"></a>Usability Checks

Before performing any action, testers verify that the component is in a usable state. An action fails with a clear error message if the component is:

- Not visible

- Not enabled

- Not attached to the UI

- Behind a modal overlay

- Read-only, when it is a value component (new in V25.3)

This catches common issues where a test passes by calling the Java API directly, but the corresponding user action would be impossible in a browser.

### <a id="common-testers"></a>Common Testers

The following table shows frequently used testers and their key methods:

| Component                              | Key Tester Methods                                                                                                                                |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `TextField`                            | `setValue(String)`, `clear()`, `clickClearButton()` (new in undefined)                                                                            |
| `Button`                               | `click()`                                                                                                                                         |
| `Checkbox`                             | `click()` (toggles checked state), `check()`, `uncheck()` (new in undefined)                                                                      |
| `NumberField`                          | `setValue(double)`, `clear()`, `stepUp()`, `stepDown()`, `isValid()` (new in undefined)                                                           |
| `Select`                               | `selectItem(String)`, `selectItem(int)`                                                                                                           |
| `ComboBox`                             | `selectItem(String)`, `getSuggestionItems()`                                                                                                      |
| `DatePicker`, `TimePicker`             | `setValue(value)`, `clear()`, `clickClearButton()`, `isValid()` (new in undefined)                                                                |
| `DateTimePicker`                       | `setValue(value)`, `clear()`, `isValid()` (new in undefined)                                                                                      |
| `Grid`                                 | `getRow(index)`, `size()`, `getCellText(row, column)`, `select(int)`, `deselect(int)`, `deselectAll()` (new in undefined)                         |
| `TreeGrid` (new in undefined)          | `TreeGridTester`: `expand(int)`, `collapse(int)`, `isExpanded(int)`, `hasChildren(int)`, plus everything `GridTester` offers                      |
| `Notification`                         | `getText()`                                                                                                                                       |
| `Dialog`                               | `open()`, `close()`, `pressEscape()`, `clickOutside()` (new in undefined)                                                                         |
| `ConfirmDialog`                        | `open()`, `confirm()`, `cancel()`, `reject()`                                                                                                     |
| `Upload`                               | `upload(File)`, `uploadAll(File…​)`, `getLastUploadStatus()`, `ensureUploaded()` (new in undefined)                                               |
| `Accordion`                            | `AccordionTester`: `openDetails(String)`, `isOpen(String)`, `closeDetails()`, `closeDetails(String)`, `toggleDetails(String)` (new in undefined)  |
| `Breadcrumbs` (since undefined)        | `BreadcrumbsTester`: `getItemTexts()`, `getItemPaths()`, `clickItem(String)`, `clickItem(int)`                                                    |
| `MasterDetailLayout` (since undefined) | `MasterDetailLayoutTester`: `getMaster()`, `getDetail()`, `getDetailPlaceholder()`, `isDetailPlaceholderVisible()`                                |
| `IntegerSlider`                        | `IntegerSliderTester`: `setValue(Integer)`, `increment()`, `decrement()`, `incrementBy(int)`, `decrementBy(int)`                                  |
| `IntegerRangeSlider`                   | `IntegerRangeSliderTester`: `setValue(IntegerRangeSliderValue)`, `setStart(Integer)`, `setEnd(Integer)`, `incrementStart()`, `decrementEnd()`, …​ |
| `DecimalSlider`                        | `DecimalSliderTester`: `setValue(Double)`, `increment()`, `decrement()`, `incrementBy(int)`, `decrementBy(int)`                                   |
| `DecimalRangeSlider`                   | `DecimalRangeSliderTester`: `setValue(DecimalRangeSliderValue)`, `setStart(Double)`, `setEnd(Double)`, `incrementStart()`, `decrementEnd()`, …​   |
| `Switch` (new in undefined)            | `SwitchTester`: `isOn()`, `click()`, `switchOn()`, `switchOff()`                                                                                  |
| `GridPro` (new in undefined)           | `GridProTester`: `setValue(row, column, value)`, plus everything `GridTester` offers                                                              |
| `GridContextMenu` (new in undefined)   | `GridContextMenuTester`, obtained with `test(grid).contextMenu(row)`: `open()`, `open(row)`, `clickItem(String, String…​)`, `getItemTexts()`      |
| `LoginOverlay`                         | `openOverlay()`, `isOpen()`, `findInFooter(Class)`, `findInCustomFormArea(Class)` (new in undefined)                                              |
| `SplitLayout` (new in undefined)       | `SplitLayoutTester`: `dragSplitterTo(double)`, `getSplitterPosition()`, `getPrimaryComponent()`, `getSecondaryComponent()`                        |
| `Card` (new in undefined)              | `CardTester`: `getTitleAsText()`, `getSubtitleAsText()`, `getHeader()`, `getMedia()`, `getFooterComponents()`                                     |
| `AvatarGroup` (new in undefined)       | `AvatarGroupTester`: `getVisibleItems()`, `getOverflowItems()`, `getOverflowAbbreviation()`                                                       |
| `Dashboard` (since undefined)          | `DashboardTester`: `moveWidget(widget, toIndex)`, `resizeWidget(widget, colspan, rowspan)`, `removeWidget(widget)`                                |
| `Text` (since undefined)               | `TextTester`: `getText()`                                                                                                                         |
| `Markdown` (since undefined)           | `MarkdownTester`: `getContent()`                                                                                                                  |

> **Tip: Selection Uses String Labels**
>
> The `selectItem()` method on `SelectTester` and `ComboBoxTester` takes the **display label as a String**, not the typed item value. When using enums or other objects, pass the label that the user would see in the drop-down:
>
> ```java
> // Enum-backed Select
> Select<ExpenseCategory> categorySelect = new Select<>();
> categorySelect.setItems(ExpenseCategory.values());
> categorySelect.setItemLabelGenerator(ExpenseCategory::getLabel);
>
> // In the test, use the display label, not the enum value
> test(categorySelect).selectItem("Meals & Entertainment");
> ```

### <a id="slot-scoped-finders"></a>Slot-Scoped Finders (new in V25.3)

Components that place content in named slots expose finders scoped to a single slot, so that a query doesn’t have to sift through everything the component holds:

```java
Button save = test(dialog).findInFooter(Button.class).withText("Save").single();
Span caption = test(card).findInHeader(Span.class).single();
Button next = test(splitLayout).findInPrimary(Button.class).single();
```

`DialogTester` and `CardTester` have `findInHeader()` and `findInFooter()`, `SplitLayoutTester` has `findInPrimary()` and `findInSecondary()`, and `LoginOverlayTester` has `findInFooter()` and `findInCustomFormArea()`. These are tester methods; the generated locators don’t have them. For any other slot, filter a query with `withinSlot()` — see [Filtering by Slot](https://vaadin.com/docs/latest/flow/testing/browserless/component-query.md#slots).

### <a id="constraint-enforcement"></a>Constraint Enforcement

Testers enforce the constraints that a browser enforces, and they stop where a browser stops.

A constraint that keeps the value out of the field makes the tester throw. The maximum length of a text field and an allowed character pattern work this way, because a browser drops the keystrokes that break them:

```java
TextField code = new TextField("Code");
code.setMaxLength(5);

// Throws: a browser stops the typing at five characters
test(code).setValue("123456");
```

A constraint that only marks the field invalid works differently: a browser commits such a value, and so does the tester. (new in V25.3) This covers `min`, `max`, `step`, and a required value on `NumberField`, `DatePicker`, `TimePicker`, and `DateTimePicker`. Assert the outcome with `isValid()`, which runs the component’s own default validator and honors an invalid state set from outside, such as the state a `Binder` sets:

```java
NumberField amount = new NumberField("Amount");
amount.setMin(0);

// Committed, as in a browser, and the field is left invalid
test(amount).setValue(-5.0);

Assertions.assertFalse(test(amount).isValid());
```

To test how the application reacts to a value that no user can produce, set that value through the component’s Java API instead of the tester:

```java
// Bypass the tester to exercise the validation logic
code.setValue("123456");
```

### <a id="clearing-a-value"></a>Clearing a Value (new in V25.3)

Emptying a field works the same way in every text, number, date, and time tester. `clear()` models deleting the contents from the keyboard, which a user can do whether or not the component shows a clear button. `clickClearButton()` models clicking that button, and fails when the button is hidden:

```java
test(name).clear();            // Always available
test(name).clickClearButton(); // Requires a visible clear button
```

A field can legitimately end up invalid once emptied, a required field for instance, so `clear()` never refuses.

Selection components use their own wording for the same action: `deselectItem()` on `RadioButtonGroupTester`, `clearSelection()` on `MultiSelectListBoxTester`, and `deselectAll()` on `GridTester`. On `ComboBoxTester`, `selectItem(null)` clears the selection without a clear button.

### <a id="upload-constraints"></a>Upload Constraints (new in V25.3)

`UploadTester` puts files through the same gate the browser applies before it sends anything to the server: `setMaxFiles()`, `setMaxFileSize()`, and the accepted file types, in that order. A file that fails one of them never reaches the upload handler or receiver, and a `FileRejectedEvent` is fired, as it is in the browser.

An upload is different from a value: a refused file is no more of an error in the tester than it is in the browser, so the upload doesn’t throw. Check what became of each file with `getLastUploadStatus()`, or call `ensureUploaded()` to fail the test unless every file of the last upload went through:

```java
test(upload).upload(new File("report.pdf"));
test(upload).ensureUploaded();
```

`maxFiles` is checked against an emulated file list, so files stay in it between calls, the same way the entries the browser shows do. An `Upload` with a plain `Receiver` implicitly allows one file, which makes a second upload fail; `removeFile()` makes room for it the way the user does.

### <a id="base-methods"></a>Base Methods

All testers inherit from `ComponentTester`, which provides methods useful across component types:

| Method                                     | Description                                                                                                                                                        |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `click()`, `rightClick()`, `middleClick()` | Click the component. All variants accept optional `MetaKeys` for modifier keys.                                                                                    |
| `isUsable()`                               | Returns `true` if the component is visible, enabled, attached, and — for a value component — not read-only. Use this to check state without throwing an exception. |
| `roundTrip()`                              | Simulates a server round-trip, processing any pending client-server communication.                                                                                 |
| `fireDomEvent(String)`                     | Fires a DOM event on the component, such as `"blur"` or `"focus"`.                                                                                                 |
| `find(Class)`                              | Creates a component query scoped to the children of the wrapped component.                                                                                         |

## <a id="standalone-component-environments"></a>Standalone Component Environments (since V25.2)

`BrowserlessUIContext.forComponent(component)` creates a route-free environment and attaches the component to its UI. Closing the returned context tears down the environment. The supplier overload creates the component after installing the Vaadin thread-locals, allowing its constructor to access the current UI and session. `BrowserlessApplicationContext.forComponent(Supplier)` creates a fresh component for each new window.

## <a id="custom-tester-contracts"></a>Custom Tester Contracts

Custom testers extend `ComponentTester<C>` and declare the component type with `@Tests`. The `fqn` attribute accepts a fully qualified class name when a class literal is unsuitable. Custom action methods call `ensureComponentIsUsable()` before performing the interaction. They can delegate to other component testers.

Tester discovery scans `com.vaadin.flow.component` by default. `@ComponentTesterPackages` adds application packages to scan for testers. Extensions and application-context builders also support tester-package configuration.

For a worked example, see [Test a Custom Component](https://vaadin.com/docs/latest/building-apps/testing/browserless/test-custom-components.md).

`A1B2C3D4-E5F6-7890-ABCD-EF1234567890`
