AI Unified Process plugin for the Vaadin/jOOQ stack
97
93%
Does it follow best practices?
Impact
98%
1.30xAverage score across 10 eval scenarios
Passed
No known issues
Legacy skill — no longer recommended for new code. Since Vaadin 25.1 the official Vaadin Browserless Testing framework (
com.vaadin:browserless-test-junit6) is free and open source under Apache 2.0. It supersedes the community Karibu Testing library. Prefer/browserless-testfor new test classes. Use this skill only when extending an existing Karibu-based test suite.
Create Karibu unit tests for Vaadin views based on the use case $ARGUMENTS. Karibu Testing allows server-side testing of Vaadin components without a browser.
If the KaribuTesting MCP server (https://karibu-testing-mcp.martinelli.ch/mcp) is configured, use it for documentation and code generation; otherwise rely on your own knowledge and the documentation links below. See the MCP setup rule to configure this optional server.
@UseCase AnnotationKaribu tests are use case tests. Each test class verifies the behavior of exactly one use case
from the use case specification (docs/use-cases/UC-XXX-*.md).
Test classes must be named after the use case using the pattern
UC<id><PascalCaseUseCaseName>Test — for example UC001RegisterPersonTest for use case UC-001
"Register Person". This is the convention the AIUP IntelliJ Navigator plugin relies on to link
specs and tests.
@UseCase annotationEvery test method must be annotated with @UseCase(id = "UC-XXX", ...) so the
AIUP IntelliJ Navigator plugin can wire up
gutter icons and Find Usages between the Markdown spec and the Java tests.
Bootstrap step. Before writing any tests, check whether the project already contains an
annotation type named UseCase (search the project for @interface UseCase). If it does not,
create it. The package does not matter — the plugin resolves the annotation by short name — but a
conventional location is src/main/java/<group>/<artifact>/usecase/UseCase.java. The annotation
must have exactly this shape:
package com.example.app.usecase;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface UseCase {
String id();
String scenario() default "Main Success Scenario";
String[] businessRules() default {};
}Annotate each test method with the use case ID and (when applicable) the scenario and business
rules it covers. The values must match headings in the corresponding UC-XXX-*.md spec:
| Attribute | Maps to spec heading | Default |
|---|---|---|
id | **Use Case ID:** UC-XXX | (required) |
scenario | ## Main Success Scenario or ### A1: … | "Main Success Scenario" |
businessRules | ### BR-XXX headings inside the same UC | {} |
@Test
@UseCase(id = "UC-001")
void register_person_with_valid_data() { ... }
@Test
@UseCase(id = "UC-001", scenario = "A1: Email Already Exists")
void registration_fails_when_email_already_exists() { ... }
@Test
@UseCase(id = "UC-001", scenario = "A2: Invalid Postal Code", businessRules = {"BR-003"})
void registration_fails_when_postal_code_invalid() { ... }Create test data using Flyway migrations in src/test/resources/db/migration.
| Approach | Location | Purpose |
|---|---|---|
| Flyway migration | src/test/resources/db/migration/V*.sql | Populate test data |
| Manual cleanup | @AfterEach method | Remove test-created data |
| Class | Purpose |
|---|---|
| com.github.mvysny.kaributesting.v10.LocatorJ | Find components |
| com.github.mvysny.kaributesting.v10.GridKt | Grid assertions and interactions |
| com.github.mvysny.kaributesting.v10.NotificationsKt | Notification assertions |
| com.github.mvysny.kaributesting.v10.pro.ConfirmDialogKt | ConfirmDialog interactions |
Use references/UC001ManagePersonsTest.java as the test
class structure. It demonstrates the UC<id><Name>Test class naming, the @UseCase annotation on
every test method, and how to map alternative flows (scenario = "A1: …") and business rules
(businessRules = {"BR-…"}) onto the spec headings.
UI.getCurrent().navigate(PersonView.class);// Find by type
var grid = _get(Grid.class);
var button = _get(Button.class, spec -> spec.withCaption("Save"));
var textField = _get(TextField.class, spec -> spec.withLabel("Name"));
// Find all matching
List<Button> buttons = _find(Button.class);// Get grid size
assertThat(GridKt._size(grid)).isEqualTo(100);
// Get selected items
Set<PersonRecord> selected = grid.getSelectedItems();
// Select a row
GridKt._selectRow(grid, 0);
// Get cell component (for action buttons)
GridKt._getCellComponent(grid, 0, "actions")
.getChildren()
.filter(Button.class::isInstance)
.findFirst()
.map(Button.class::cast)
.ifPresent(Button::click);
// Get cell value
String name = GridKt._getFormattedRow(grid, 0).get("name");// Set field values
_get(TextField.class, spec -> spec.withLabel("Name"))._setValue("John");
_get(ComboBox.class, spec -> spec.withLabel("Country"))._setValue(country);
_get(DatePicker.class, spec -> spec.withLabel("Birth Date"))._setValue(LocalDate.of(1990, 1, 1));
// Click button
_get(Button.class, spec -> spec.withCaption("Save"))._click();// Expect notification
expectNotifications("Record saved successfully");
// Assert no notifications
assertThat(NotificationsKt.getNotifications()).isEmpty();// Click confirm in dialog
ConfirmDialogKt._fireConfirm(_get(ConfirmDialog.class));
// Click cancel
ConfirmDialogKt._fireCancel(_get(ConfirmDialog.class));Use AssertJ or Karibu Testing assertions:
| Assertion Type | Example |
|---|---|
| Grid size | assertThat(GridKt._size(grid)).isEqualTo(10) |
| Component visible | assertThat(button.isVisible()).isTrue() |
| Component enabled | assertThat(button.isEnabled()).isTrue() |
| Field value | assertThat(textField.getValue()).isEqualTo("x") |
| Collection size | assertThat(items).hasSize(5) |
| Notifications | expectNotifications("Success") |
docs/use-cases/UC-XXX-*.md) to identify the main success
scenario, alternative flows (A1, A2, …), and referenced business rules (BR-XXX)UseCase annotation type already exists in the project. If not, create
UseCase.java with the canonical shape shown aboveUC<id><PascalCaseUseCaseName>Test using the template@UseCase(id = "UC-XXX", scenario = "…", businessRules = {"BR-…"})
mirroring the spec headings_dump() to inspect the component tree@UseCase annotation contract): https://github.com/AI-Unified-Process/intellij-pluginhttps://karibu-testing-mcp.martinelli.ch/mcp)