Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -444,10 +444,17 @@ test(menu).open();
find(Div.class).withText("Rename").all(); // one match
```

`ContextMenuTester` works either way: `clickItem("Rename")` and
`test(menu).find(Div.class)` read the server-side menu state and need no
`open()` at all; `open()` additionally attaches the menu to the UI, which is
what makes a top-level `find()` see the items.
A closed menu is not attached to the UI, so, as in the browser, its items
cannot be interacted with: `clickItem("Rename")`, `isItemChecked(...)` and
`getItemTooltipText(...)` throw an `IllegalStateException` until the menu is
opened. The tester-scoped `test(menu).find(Div.class)` is the exception, since
it reads the menu contents rather than the UI; it finds the items whether the
menu is open or not, and returns them detached while it is closed.

A `GridContextMenu` is always about a row, so its tester takes one:
`test(grid).contextMenu(row)` targets a row without opening the menu, `open()`
then opens it there, and `clickItem("Rename")` clicks an item of the open menu.
`GridContextMenuTester.open(row)` opens the menu on a row directly.

## Per-test Vaadin configuration

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,9 @@ public <T extends Component> T navigate(String location,
* the tree until then, and the lookup returns an empty result rather than
* failing, so reach those components through the owning component tester
* instead: {@code GridTester.getCellComponent(row, column)} for grid cells,
* {@code ContextMenuTester.open()} or {@code clickItem(...)} for menus.
* {@code ContextMenuTester.open()} and then {@code clickItem(...)} for a
* context menu, and {@code GridTester.contextMenu(row).open()} for a grid
* context menu.
*
* @param type
* component type to search for
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,9 +460,13 @@ void find_menuContent_notInTheUiTreeUntilTheMenuIsOpened() {
@Test
void openAndFind_ContextMenuItemsCanBeAccessed() {
var menuTester = test(view.menu);
menuTester.open();
var div = menuTester.find(Div.class).withText("Component Item")
.single();
Assertions.assertFalse(div.isAttached(),
"items of a menu that was never opened should be found, but detached");

menuTester.open();
div = menuTester.find(Div.class).withText("Component Item").single();
Assertions.assertTrue(div.isAttached());

menuTester.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,15 @@ void basicGrid_doubleClick() {

}

@Test
void find_componentRenderedByColumn_notInComponentTree() {
// a component rendered per item does not exist until the renderer is
// asked to render that item, so the finder cannot see it. The cell
// component is reached through the tester instead.
Assertions.assertTrue(find(Button.class).all().isEmpty(),
"component column cells should not be part of the component tree");
}

@Test
void getCellComponent_columnByKey_canClickAButton() {
final Component cellComponent = test(view.basicGrid).getCellComponent(1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,9 @@ public <T extends ComponentTester<Y>, Y extends Component> T test(
* the tree until then, and the lookup returns an empty result rather than
* failing, so reach those components through the owning component tester
* instead: {@code GridTester.getCellComponent(row, column)} for grid cells,
* {@code ContextMenuTester.open()} or {@code clickItem(...)} for menus.
* {@code ContextMenuTester.open()} and then {@code clickItem(...)} for a
* context menu, and {@code GridTester.contextMenu(row).open()} for a grid
* context menu.
*
* @param componentType
* the type of the component(s) to search for
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,9 @@ public static BrowserlessUIContext forComponent(
* the tree until then, and the lookup returns an empty result rather than
* failing, so reach those components through the owning component tester
* instead: {@code GridTester.getCellComponent(row, column)} for grid cells,
* {@code ContextMenuTester.open()} or {@code clickItem(...)} for menus.
* {@code ContextMenuTester.open()} and then {@code clickItem(...)} for a
* context menu, and {@code GridTester.contextMenu(row).open()} for a grid
* context menu.
*
* @param componentType
* the type of component to search for
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@
* instance which searches through the whole component tree, or a
* {@link com.vaadin.flow.component.Component} instance, which limits the search
* to the component subtree.
* <p>
* Not everything a view shows is in that tree. A component that another
* component renders per item, and the content of an overlay that is not open,
* are reached through the tester of the component that owns them:
* {@code GridTester.getCellComponent(row, column)} for grid cells,
* {@code ContextMenuTester.open()} or {@code GridTester.contextMenu(row)} for
* menus. A query returns an empty result rather than failing, so such a
* component reads as if it was never created.
*
* @param <T>
* the type of the component(s) to search for
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,9 @@ public void setModal(boolean modal) {
* the tree until then, and the lookup returns an empty result rather than
* failing, so reach those components through the owning component tester
* instead: {@code GridTester.getCellComponent(row, column)} for grid cells,
* {@code ContextMenuTester.open()} or {@code clickItem(...)} for menus.
* {@code ContextMenuTester.open()} and then {@code clickItem(...)} for a
* context menu, and {@code GridTester.contextMenu(row).open()} for a grid
* context menu.
*
* @param componentType
* type of the component to search.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,13 @@ public ContextMenuTester(T component) {
* simulates the server-side state changes that would occur when a user
* opens the menu in the browser.
* <p>
* Calling {@link #open()} is not required before using
* {@code clickItem(...)} or {@code find(Class)} methods. Those methods
* operate on the server component state and can be used regardless of the
* menu {@code opened} state. Use {@link #open()} only if you want to
* explicitly simulate the act of opening.
* A closed context menu is not attached to the UI, so, exactly as in the
* browser, its items cannot be interacted with: open the menu before
* calling {@code clickItem(...)}, {@code isItemChecked(...)} or
* {@code getItemTooltipText(...)}, otherwise they throw an
* {@link IllegalStateException}. Only {@code find(Class)} works on a closed
* menu, since it queries the menu contents instead of the UI; the
* components it returns are detached until the menu is opened.
* <p>
* A top level {@code find(...)} on the UI is a different matter: the menu
* content is attached to the UI only while the menu is open, so it is found
Expand Down Expand Up @@ -120,8 +122,8 @@ public void close() {
* }
* </pre>
*
* Note: Opening the menu via {@link #open()} is not required before
* invoking this method; the lookup operates on server-side state.
* Note: the menu must be opened with {@link #open()} before an item can be
* clicked, since a closed menu is not attached to the UI.
*
* @param topLevelText
* the text content of the top level menu item, not
Expand All @@ -131,8 +133,9 @@ public void close() {
* @throws IllegalArgumentException
* if the provided text does not identify a menu item.
* @throws IllegalStateException
* if there are multiple visible matching items at any level, or
* if the item at the given path is disabled or not visible.
* if the menu is not opened, if there are multiple visible
* matching items at any level, or if the item at the given path
* is disabled or not visible.
*/
public void clickItem(String topLevelText, String... nestedItemsText) {
ensureComponentIsUsable();
Expand Down Expand Up @@ -171,8 +174,8 @@ public void clickItem(String topLevelText, String... nestedItemsText) {
* }
* </pre>
*
* Note: Opening the menu via {@link #open()} is not required before
* invoking this method; the lookup operates on server-side state.
* Note: the menu must be opened with {@link #open()} before an item can be
* clicked, since a closed menu is not attached to the UI.
*
* @param topLevelPosition
* the zero-based position of the item in the menu, as it will be
Expand All @@ -183,7 +186,8 @@ public void clickItem(String topLevelText, String... nestedItemsText) {
* @throws IllegalArgumentException
* if the provided position does not identify a menu item.
* @throws IllegalStateException
* if the item at the given position is disabled or not visible.
* if the menu is not opened, or if the item at the given
* position is disabled or not visible.
*/
public void clickItem(int topLevelPosition, int... nestedItemsPositions) {
ensureComponentIsUsable();
Expand Down Expand Up @@ -228,7 +232,8 @@ public void clickItem(int topLevelPosition, int... nestedItemsPositions) {
* if the provided text does not identify a menu item or if the
* menu item is not checkable.
* @throws IllegalStateException
* if the item at given path is not usable.
* if the menu is not opened, or if the item at given path is
* not usable.
*/
public boolean isItemChecked(String topLevelText,
String... nestedItemsText) {
Expand Down Expand Up @@ -278,7 +283,8 @@ public boolean isItemChecked(String topLevelText,
* if the provided position does not identify a menu item or if
* the menu item is not checkable.
* @throws IllegalStateException
* if the item at given position is not usable.
* if the menu is not opened, or if the item at given position
* is not usable.
*/
public boolean isItemChecked(int topLevelPosition,
int... nestedItemsPositions) {
Expand Down Expand Up @@ -324,7 +330,8 @@ public boolean isItemChecked(int topLevelPosition,
* @throws IllegalArgumentException
* if the provided text does not identify a menu item.
* @throws IllegalStateException
* if the item at given path is not usable.
* if the menu is not opened, or if the item at given path is
* not usable.
* @since 1.1
*/
public String getItemTooltipText(String topLevelText,
Expand Down Expand Up @@ -372,7 +379,8 @@ public String getItemTooltipText(String topLevelText,
* @throws IllegalArgumentException
* if the provided position does not identify a menu item.
* @throws IllegalStateException
* if the item at given position is not usable.
* if the menu is not opened, or if the item at given position
* is not usable.
* @since 1.1
*/
public String getItemTooltipText(int topLevelPosition,
Expand Down
Loading