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":
- 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.
- 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.
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
Orderdetail 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 andUiTestUtils.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@ViewComponentfield 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, andButton.click()never reaches the handler — silently, with no exception and no warning.The test then looks exactly as if
@Subscribehad 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
@UiTestthe current user is the system user, absent from the databaseSame 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@UiTestit is the SYSTEM user, and it has no row in the database. Any code resolving the current user through the user repository orDataManagerfinds 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":
tabSheettabs are not attached, soclick()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 silentclick()in a test does NOT prove the button is broken in the browser.@UiTestthe 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 insystemAuthenticator.withUser("admin", () -> { ... }). Same tool as in "Security Test Pattern", different reason — not access policies, but whether the user exists at all.