Skip to content

jmix-create-test: two things that make a @UiTest silently lie #45

Description

@fractal3000

Found while following the skill on a Jmix 2.8.2 project.

Problem: silent — the instructions say nothing about either case.

Task

UI tests for an Order detail view: a button that lives inside a <tabSheet> tab which is not the selected one, and a button whose visibility depends on whether the CURRENT user is the one assigned to the record.

Where

jmix-create-test, the "UI Integration Test Pattern" section. It shows navigation and UiTestUtils.getComponent, and from there it is implied that the found component behaves the way it does in a browser.

What happened

UiTestUtils.getComponent(view, "editButton") FINDS the button — it is in the component tree, the @ViewComponent field is injected, nothing fails. But the content of a non-selected tab is not attached (getElement().getNode().isAttached() == false), Vaadin treats a detached component as disabled, and Button.click() never reaches the handler — silently, with no exception and no warning.

The test then looks exactly as if @Subscribe had never been wired: the handler does not run, the caption does not change. I wrote a workaround (ComponentUtil.fireEvent) with the WRONG explanation attached to it, and then reasoned from that wrong explanation to a wrong conclusion about the browser. So the gap cost not only time but a false diagnosis, which had to be disproved by an actual browser walk.

Caught by the Gate-3 browser walk; before it, both explanations looked equally plausible.

Also seen — inside @UiTest the current user is the system user, absent from the database

Same section. "Security Test Pattern" shows systemAuthenticator.withUser(...) for results that depend on security policies; the UI pattern shows plain navigation with no authentication and never says who is logged in. Inside @UiTest it is the SYSTEM user, and it has no row in the database. Any code resolving the current user through the user repository or DataManager finds nobody and quietly takes the "not me" branch, so a test over correct application logic goes red — no exception, just a different branch, which reads as an application defect rather than a property of the harness.

Caught by a red test on correct logic; the cause found only by reading a neighbouring test, in a comment left by a person who had already hit it.

Suggested fix

Two additions to "UI Integration Test Pattern":

  1. Components on non-selected tabSheet tabs are not attached, so click() on them is a silent no-op. Either select the tab first, or fire the event directly (ComponentUtil.fireEvent(button, new ClickEvent<>(button))) — and in both cases say WHY in the test, otherwise the workaround reads as an admission that the handler is broken. State explicitly that a silent click() in a test does NOT prove the button is broken in the browser.
  2. One line: inside @UiTest the current user is the system user and has no row in the database; when the behaviour under test depends on WHO is looking, wrap the navigation and the assertions in systemAuthenticator.withUser("admin", () -> { ... }). Same tool as in "Security Test Pattern", different reason — not access policies, but whether the user exists at all.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions