Skip to content

Drama Finder

๐Ÿ“– Documentation: https://parttio.github.io/dramafinder/ ยท Javadoc ยท API reference

Documentation

The documentation is published at https://parttio.github.io/dramafinder/, with the Javadoc. Its sources are the Markdown files in this repository.

API reference (and offline agents)

The complete public API โ€” test setup, every element wrapper, every signature โ€” is generated from source into skills/vaadin-playwright-test/api-reference.md.

The same file ships inside the jar, so it is readable with no network and no checkout. That is the copy to reach for in a consumer project, and the reason there is never a need to run javap on the classes:

JAR=$(ls ~/.m2/repository/org/vaadin/addons/dramafinder/*/dramafinder-*.jar | tail -1)
unzip -p "$JAR" META-INF/dramafinder/START-HERE.md          # short guide, ~4 KB
unzip -p "$JAR" META-INF/dramafinder/api-reference.md       # every signature
unzip -p "$JAR" META-INF/dramafinder/agent-api-reference.md # screenshot helpers
unzip -p "$JAR" META-INF/dramafinder/MIGRATION-2.0.md       # upgrading from 1.x

Upgrading from 1.x

DramaFinder 2.0 changes how components are found:

  • label lookups match exactly by default: the whole label, case-sensitively, with no first-match fallback;
  • a label is the visible label: getByLabel no longer matches an aria-label or a placeholder. Find those with the query builder, find(page, TextFieldElement.class).withAccessibleName("Search") or .withPlaceholder("Street");
  • every element action waits for the Vaadin server round-trip it triggers.

Most 1.x tests compile unchanged; lookups that relied on the old matching fail at runtime. The migration guide lists every changed method, what no longer compiles, and how to rewrite each lookup.

Spring Boot

A Spring Boot app's tests extend org.vaadin.addons.dramafinder.spring.SpringPlaywrightIT, which starts the app on a random port and builds getUrl() from it. Spring is optional: DramaFinder declares it provided and never adds it to the classpath; a project without Spring extends AbstractBasePlaywrightIT and overrides getUrl().

With Spring Security, a test starts signed in as the user of Spring Security Test's @WithMockUser or @WithUserDetails (on the test method or class) without going through the login view; loginAs("alice", "ADMIN") switches user during a test and newPageAs("bob") opens the view as a second user in its own browser context. The user goes into the HTTP session through an endpoint registered only in the test's Spring context. It needs spring-security-test in test scope.

Claude Code skills

This repository ships two Claude Code skills. Install them as plugins:

/plugin marketplace add parttio/dramafinder
/plugin install vaadin-playwright-test@dramafinder
/plugin install vaadin-playwright-screenshot@dramafinder
  • vaadin-playwright-test โ€” generates Playwright integration tests for Vaadin views using Drama Finder.
  • vaadin-playwright-screenshot โ€” captures screenshots of UI changes by writing a temporary Drama Finder test that batch-captures every key visual state against the running app in one run. Backed by the org.vaadin.addons.dramafinder.agent helpers (VisualVerificationTest, AgentReporting, ComponentSnapshot, ViewOutline), which write a screenshot, semantic component snapshot, view outline (each component with a verified DramaFinder lookup), and stack trace to target/agent-report/ on failure. Tests extending AbstractBasePlaywrightIT get the same failure report, per test, under target/agent-report/<TestClass>/<testMethod>/; disable it with -Ddramafinder.agentReport=false. Call ViewOutline.write(page) in a throwaway test to get view-outline.txt before writing lookups for a view.

To get later updates, run /plugin marketplace update dramafinder.

Usage

Drama Finder is a set of helper classes to test a Vaadin application using Playwright. It gives you access to a list of assertions and actions you can do for our components.

For example:

@Test
public void testTooltip() {
    // get the text field whose visible label is "Textfield"
    TextFieldElement textfield = TextFieldElement.getByLabel(page, "Textfield");
    // assert that is visible
    textfield.assertVisible();
    // assert that the textfield has a tooltip
    textfield.assertTooltipHasText("Tooltip for textfield");
}

It also gives you some inner locators.

@Test
public void testHelper() {
    // get the text field whose visible label is "TextField with helper component"
    TextFieldElement textfield = TextFieldElement.getByLabel(page, "TextField with helper component");
    // Use the helperLocator to get the TextField added as a helper component
    TextFieldElement helperComponent = new TextFieldElement(textfield.getHelperLocator());
    // You can use Playwright assertions
    assertThat(helperComponent.getHelperLocator()).hasText("Internal helper");
    // or reuse the locator with the API

}

Getting started

Add the addon as a test dependency.

<dependency>
    <groupId>org.vaadin.addons</groupId>
    <artifactId>dramafinder</artifactId>
    <version>2.0.0</version>
    <scope>test</scope>
</dependency>

The Drama Finder element classes are built around a plain Playwright Page (or Locator). They have no dependency on any particular test base class, so you can use them with whatever Playwright setup you already have. Just hand a Page to the factory helpers (e.g. getByLabel) or to an element constructor.

The simplest way to get started is to let Spring Boot start the server for you with @SpringBootTest(webEnvironment = RANDOM_PORT) and manage the Playwright Page yourself:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SimpleExampleViewIT {

    @LocalServerPort
    private int port;

    Playwright playwright;
    Browser browser;
    Page page;

    @BeforeEach
    public void setup() {
        playwright = Playwright.create();
        browser = playwright.chromium().launch();
        page = browser.newPage();
        page.navigate(String.format("http://localhost:%d/", port));
    }

    @AfterEach
    public void tearDown() {
        browser.close();
        playwright.close();
    }

    @Test
    public void testTooltip() {
        // The only thing the element API needs is a Playwright Page
        TextFieldElement textfield = TextFieldElement.getByLabel(page, "Textfield");
        textfield.assertVisible();
        textfield.assertTooltipHasText("Tooltip for textfield");
    }
}

Letting @SpringBootTest start the server is not the only option. You can also write the tests as plain integration tests (e.g. classes ending in IT.java run by the maven-failsafe-plugin) and start/stop the server separately with Maven โ€” for example using the spring-boot:start and spring-boot:stop goals bound to the pre-integration-test / post-integration-test phases โ€” before the ITs execute. In that case the test simply navigates to the externally started server's URL. Either way, the element API only ever needs a Playwright Page, so you are free to obtain it however suits your project.

Optional: AbstractBasePlaywrightIT convenience base class

If you don't already have a Playwright setup, Drama Finder ships an optional AbstractBasePlaywrightIT base class that handles the boilerplate for you: creating and closing the Playwright/Browser, opening a fresh page and navigating to your view before each test, waiting for Vaadin to finish loading, sensible default timeouts, and headless toggling (via the headless system property or HEADLESS environment variable). Extending it is purely a convenience โ€” it is never required to use the element API.

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SimpleExampleViewIT extends AbstractBasePlaywrightIT {

    @LocalServerPort
    private int port;

    @Override
    public String getUrl() {
        return String.format("http://localhost:%d/", port);
    }

    @Test
    public void testTooltip() {
        TextFieldElement textfield = TextFieldElement.getByLabel(page, "Textfield");
        textfield.assertVisible();
        textfield.assertTooltipHasText("Tooltip for textfield");
    }
}

Note

Drama Finder covers most of the Vaadin components (see TODO.md for the list of supported components and the remaining gaps) and follows semantic versioning since 1.0. It is built and tested against Vaadin 25.

If you notice something missing please create a ticket or a Pull Request.

The integration tests in this repository are not meant to be a best practice since they are primarily here to test the API. For example they test getters like getMinLength without waiting, which is a bad practice.

@Test
public void testPattern() {
    // use Playwright assertion to wait
    textfield.assertMinLength(6);
    // doesn't wait but will test `getMinLength`, use the previous in your code
    assertEquals(6, textfield.getMinLength());
}

Development instructions

There is no standalone demo application. The views used to exercise the library are test-only (src/test/java/.../tests/testuis/) and are served by the Spring Boot test harness (@SpringBootTest) when the *IT.java tests run.

Documentation site

The Documentation site workflow publishes the Markdown documentation and the Javadoc to GitHub Pages on every push to master. site/build.py collects the published files (listed in its NAV) without moving them; to preview locally:

pip install -r site/requirements.txt
python3 site/build.py && mkdocs serve -f target/docs-site/mkdocs.yml

Javadoc

Public APIs in the dramafinder library are documented with concise Javadoc:

  • Element classes include a short summary referencing the underlying Vaadin tag (e.g., vaadin-text-field) and any noteworthy behaviors.
  • Public methods document parameters, return values, and null semantics.
  • Factory helpers (e.g., getByLabel) note the ARIA role used to locate the element.

Running tests

To run the unit tests, execute the following command:

mvn test

Integration tests

The integration tests are built using Spring Boot, Playwright, and Axe-core. The tests are located in files ending with IT.java under src/test/java. The tests are run with the maven-failsafe-plugin when the it profile is activated.

To run the integration tests, execute the following command:

mvn -Pit verify

To debug the UI with a visible browser, disable headless mode using either the headless property or the debug-ui profile:

# system property
mvn -Dit.test=ContextMenuViewIT -Dheadless=false verify

# convenient profile
mvn -Pdebug-ui -Dit.test=ContextMenuViewIT verify

You will need to add the profile in your pom.xml:

<profile>
    <id>debug-ui</id>
    <properties>
        <headless>false</headless>
    </properties>
</profile>

Cutting a release

Before cutting a release, make sure the build passes properly locally and in GitHub Actions based verification build.

To tag a release and increment versions, issue:

mvn release:prepare release:clean

Answer questions, defaults most often fine. Note that release:perform is not needed as there is a GitHub Action is set up build and to push release to Maven Central automatically.

Directory will automatically pick up new releases within about half an hour, but if browser or Vaadin version support change, be sure to adjust the metadata in Vaadin Directory UI.