UI Integration Tests
Jmix allows you to write tests for the UI layer. In these tests, you can open views, load data, verify the contents of UI components, make modifications, and simulate user actions such as button clicks.
| Use the New → Advanced → UI Integration Test action in the Jmix tool window to quickly create a UI integration test using Studio. |
Jmix UI tests start the complete Spring context and can interact with the database like the integration tests of the business logic. They are close to the browser-based end-to-end tests in the sense that they can check a wide range of application functionality, but at the same time they are easy to set up and are executed much faster than browser-based tests.
Every new Jmix project includes an example of a UI integration test: the UserUiTest class that verifies the user management views. Let’s take a look at the configuration and logic of the UI tests using this example.
To execute UI tests, your project should contain the dependency on the jmix-flowui-test-assist module:
testImplementation 'io.jmix.flowui:jmix-flowui-test-assist'
The example test class is shown below.
package com.company.demo.user;
import com.company.demo.DemoApplication;
import com.company.demo.entity.User;
import com.company.demo.view.user.UserDetailView;
import com.company.demo.view.user.UserListView;
import io.jmix.core.DataManager;
import io.jmix.flowui.ViewNavigators;
import io.jmix.flowui.component.UiComponentUtils;
import io.jmix.flowui.component.grid.DataGrid;
import io.jmix.flowui.component.textfield.JmixPasswordField;
import io.jmix.flowui.component.textfield.TypedTextField;
import io.jmix.flowui.data.grid.DataGridItems;
import io.jmix.flowui.kit.component.button.JmixButton;
import io.jmix.flowui.testassist.FlowuiTestAssistConfiguration;
import io.jmix.flowui.testassist.UiTest;
import io.jmix.flowui.testassist.UiTestUtils;
import io.jmix.flowui.view.View;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
/**
* Sample UI integration test for the User entity.
*/
@UiTest (1)
@SpringBootTest(classes = {DemoApplication.class, FlowuiTestAssistConfiguration.class}) (2)
public class UserUiTest {
@Autowired
DataManager dataManager; (3)
@Autowired
ViewNavigators viewNavigators;
@Test (4)
void test_createUser() {
// Navigate to user list view
viewNavigators.view(UiTestUtils.getCurrentView(), UserListView.class).navigate();
UserListView userListView = UiTestUtils.getCurrentView(); (5)
// click "Create" button
JmixButton createBtn = findComponent(userListView, "createBtn"); (6)
createBtn.click();
// Get detail view
UserDetailView userDetailView = UiTestUtils.getCurrentView();
// Set username and password in the fields
TypedTextField<String> usernameField = findComponent(userDetailView, "usernameField");
String username = "test-user-" + System.currentTimeMillis();
usernameField.setValue(username);
JmixPasswordField passwordField = findComponent(userDetailView, "passwordField");
passwordField.setValue("test-passwd");
JmixPasswordField confirmPasswordField = findComponent(userDetailView, "confirmPasswordField");
confirmPasswordField.setValue("test-passwd");
// Click "OK"
JmixButton commitAndCloseBtn = findComponent(userDetailView, "saveAndCloseBtn");
commitAndCloseBtn.click();
// Get navigated user list view
userListView = UiTestUtils.getCurrentView();
// Check the created user is shown in the table
DataGrid<User> usersDataGrid = findComponent(userListView, "usersDataGrid");
DataGridItems<User> usersDataGridItems = usersDataGrid.getItems();
Assertions.assertNotNull(usersDataGridItems);
usersDataGridItems.getItems().stream()
.filter(u -> u.getUsername().equals(username))
.findFirst()
.orElseThrow();
}
@AfterEach (7)
void tearDown() {
dataManager.load(User.class)
.query("e.username like ?1", "test-user-%")
.list()
.forEach(u -> dataManager.remove(u));
}
@SuppressWarnings("unchecked")
private static <T> T findComponent(View<?> view, String componentId) {
return (T) UiComponentUtils.getComponent(view, componentId);
}
}
| 1 | The @UiTest annotation defines a JUnit extension to start Vaadin, configure application views and set up authentication. |
| 2 | The @SpringBootTest annotation should declare the application and the jmix-flowui-test-assist module configurations. |
| 3 | You can inject any Spring beans using the @Autowired annotation. |
| 4 | The test case method. |
| 5 | UiTestUtils.getCurrentView() method returns the view currently opened by navigation. |
| 6 | The findComponent() method returns a UI component by its id. |
| 7 | The method executed after each test case can be used for test data cleanup. |
Getting a View Opened in a Dialog Window
The UiTestUtils.getCurrentView() method returns the view opened by navigation. If an action opens a view in a dialog window, for example with OpenMode.DIALOG, use DialogWindows.getOpenedDialogWindows().
In the following example, the test clicks the order creation button and obtains the detail view opened in a dialog window:
@Autowired
private ViewNavigators viewNavigators;
@Autowired
private DialogWindows dialogWindows;
@Test
void test_openCustomerDetailViewInDialog() {
viewNavigators.view(UiTestUtils.getCurrentView(), CustomerListView.class)
.navigate();
CustomerListView listView = UiTestUtils.getCurrentView();
JmixButton createDialogBtn = getComponent(listView, "createDialogBtn");
createDialogBtn.click();
CustomerDetailView detailView = dialogWindows.getOpenedDialogWindows()
.getDialogs()
.stream()
.filter(CustomerDetailView.class::isInstance)
.map(CustomerDetailView.class::cast)
.reduce((previous, current) -> current)
.orElseThrow();
Assertions.assertNotNull(detailView);
}
The getDialogs() method returns dialog views of the current UI. To get dialogs of a specific UI, use getDialogs(UI). Views are added to the list in the order they are opened, so the last opened dialog is the last item in the list.
For more information about the dialog window API, see Getting Opened Dialog Windows.