diff --git a/vaadin-context-menu-flow-parent/vaadin-context-menu-flow-integration-tests/pom.xml b/vaadin-context-menu-flow-parent/vaadin-context-menu-flow-integration-tests/pom.xml
index 35e5626929d..d85af99cdee 100644
--- a/vaadin-context-menu-flow-parent/vaadin-context-menu-flow-integration-tests/pom.xml
+++ b/vaadin-context-menu-flow-parent/vaadin-context-menu-flow-integration-tests/pom.xml
@@ -36,6 +36,21 @@
             vaadin-checkbox-flow
             ${project.version}
         
+        
+            com.vaadin
+            vaadin-button-flow
+            ${project.version}
+        
+        
+            com.vaadin
+            vaadin-menu-bar-flow
+            ${project.version}
+        
+        
+            com.vaadin
+            vaadin-notification-flow
+            ${project.version}
+        
         
             com.vaadin
             vaadin-ordered-layout-flow
@@ -60,6 +75,24 @@
             ${project.version}
             test
         
+        
+            com.vaadin
+            vaadin-menu-bar-testbench
+            ${project.version}
+            test
+        
+        
+            com.vaadin
+            vaadin-button-testbench
+            ${project.version}
+            test
+        
+        
+            com.vaadin
+            vaadin-notification-testbench
+            ${project.version}
+            test
+        
         
             com.vaadin
             flow-html-components-testbench
diff --git a/vaadin-context-menu-flow-parent/vaadin-context-menu-flow-integration-tests/src/main/java/com/vaadin/flow/component/contextmenu/it/SubMenuHelpersPage.java b/vaadin-context-menu-flow-parent/vaadin-context-menu-flow-integration-tests/src/main/java/com/vaadin/flow/component/contextmenu/it/SubMenuHelpersPage.java
new file mode 100644
index 00000000000..9c93841d125
--- /dev/null
+++ b/vaadin-context-menu-flow-parent/vaadin-context-menu-flow-integration-tests/src/main/java/com/vaadin/flow/component/contextmenu/it/SubMenuHelpersPage.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2023 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.flow.component.contextmenu.it;
+
+import com.vaadin.flow.component.button.Button;
+import com.vaadin.flow.component.contextmenu.ContextMenu;
+import com.vaadin.flow.component.contextmenu.MenuItem;
+import com.vaadin.flow.component.contextmenu.SubMenu;
+import com.vaadin.flow.component.html.Div;
+import com.vaadin.flow.component.icon.VaadinIcon;
+import com.vaadin.flow.component.menubar.MenuBar;
+import com.vaadin.flow.component.notification.Notification;
+import com.vaadin.flow.router.Route;
+
+@Route("vaadin-context-menu/sub-menu-helpers-test")
+public class SubMenuHelpersPage extends Div {
+
+    public SubMenuHelpersPage() {
+        MenuBar menuBar = new MenuBar();
+        MenuItem menuBarItem = menuBar.addItem("Bar Item", e -> {
+            Notification.show("Bar Item");
+        });
+        MenuItem menuBarSub = menuBar.addItem("Bar Sub Menu");
+        SubMenu menuBarSubMenu = menuBarSub.getSubMenu();
+        MenuItem menuBarSubItem = menuBarSubMenu.addItem("Bar Sub Item", e -> {
+            Notification.show("Bar Sub Item");
+        });
+        MenuItem menuBarSubSub = menuBarSubMenu.addItem("Bar Sub Sub Menu");
+        SubMenu menuBarSubSubMenu = menuBarSubSub.getSubMenu();
+        MenuItem menuBarSubSubItem = menuBarSubSubMenu
+                .addItem("Bar Sub Sub Item", e -> {
+                    Notification.show("Bar Sub Sub Item");
+                });
+
+        ContextMenu contextMenu = new ContextMenu();
+        MenuItem contextMenuItem = contextMenu.addItem("Context Item", e -> {
+            Notification.show("Context Item");
+        });
+        MenuItem contextMenuSub = contextMenu.addItem("Context Sub Menu");
+        SubMenu contextBarSubMenu = contextMenuSub.getSubMenu();
+        MenuItem contextMenuSubItem = contextBarSubMenu
+                .addItem("Context Sub Item", e -> {
+                    Notification.show("Context Sub Item");
+                });
+        MenuItem contextMenuSubSub = contextBarSubMenu
+                .addItem("Context Sub Sub Menu");
+        SubMenu contextBarSubSubMenu = contextMenuSubSub.getSubMenu();
+        MenuItem contextMenuSubSubItem = contextBarSubSubMenu
+                .addItem("Context Sub Sub Item", e -> {
+                    Notification.show("Context Sub Sub Item");
+                });
+
+        Button button = new Button(VaadinIcon.MENU.create());
+        contextMenu.setTarget(button);
+
+        add(menuBar, button);
+    }
+}
diff --git a/vaadin-context-menu-flow-parent/vaadin-context-menu-flow-integration-tests/src/test/java/com/vaadin/flow/component/contextmenu/it/SubMenuHelpersIT.java b/vaadin-context-menu-flow-parent/vaadin-context-menu-flow-integration-tests/src/test/java/com/vaadin/flow/component/contextmenu/it/SubMenuHelpersIT.java
new file mode 100644
index 00000000000..16e703d9f63
--- /dev/null
+++ b/vaadin-context-menu-flow-parent/vaadin-context-menu-flow-integration-tests/src/test/java/com/vaadin/flow/component/contextmenu/it/SubMenuHelpersIT.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2000-2023 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.flow.component.contextmenu.it;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.flow.component.button.testbench.ButtonElement;
+import com.vaadin.flow.component.contextmenu.testbench.ContextMenuElement;
+import com.vaadin.flow.component.contextmenu.testbench.ContextMenuItemElement;
+import com.vaadin.flow.component.contextmenu.testbench.ContextMenuOverlayElement;
+import com.vaadin.flow.component.menubar.testbench.MenuBarElement;
+import com.vaadin.flow.component.notification.testbench.NotificationElement;
+import com.vaadin.flow.testutil.TestPath;
+import com.vaadin.tests.AbstractComponentIT;
+
+@TestPath("vaadin-context-menu/sub-menu-helpers-test")
+public class SubMenuHelpersIT extends AbstractComponentIT {
+
+    @Before
+    public void init() {
+        open();
+    }
+
+    @Test
+    public void menuBarSubMenuTest() {
+        MenuBarElement menuBar = $(MenuBarElement.class).first();
+        menuBar.getButtons().get(0).click();
+        Assert.assertEquals("Bar Item",
+                $(NotificationElement.class).last().getText());
+
+        menuBar.getButtons().get(1).click();
+        ContextMenuOverlayElement overlay = $(ContextMenuOverlayElement.class)
+                .last();
+        ContextMenuItemElement menuBarSubItem = overlay.getMenuItems().get(0);
+        Assert.assertEquals("Bar Sub Item", menuBarSubItem.getText());
+        menuBarSubItem.click();
+        Assert.assertEquals("Bar Sub Item",
+                $(NotificationElement.class).last().getText());
+
+        menuBar.getButtons().get(1).click();
+        overlay = $(ContextMenuOverlayElement.class).last();
+        overlay.getMenuItems().get(1).openSubMenu();
+        ContextMenuOverlayElement subOverlay = $(
+                ContextMenuOverlayElement.class).last();
+        subOverlay.getMenuItems().get(0).click();
+        Assert.assertEquals("Bar Sub Sub Item",
+                $(NotificationElement.class).last().getText());
+    }
+
+    @Test
+    public void contextMenuSubMenuTest() {
+        ButtonElement button = $(ButtonElement.class).first();
+        ContextMenuElement.openByRightClick(button);
+        ContextMenuOverlayElement overlay = $(ContextMenuOverlayElement.class)
+                .first();
+        overlay.getMenuItem("Context Item").get().click();
+        Assert.assertEquals("Context Item",
+                $(NotificationElement.class).last().getText());
+
+        ContextMenuElement.openByRightClick(button);
+        overlay = $(ContextMenuOverlayElement.class).first();
+        ContextMenuItemElement itemToOpen = overlay
+                .getMenuItem("Context Sub Menu").get();
+        itemToOpen.openSubMenu();
+        $(ContextMenuOverlayElement.class).last().getMenuItems().get(0).click();
+        Assert.assertEquals("Context Sub Item",
+                $(NotificationElement.class).last().getText());
+    }
+
+    @Test
+    public void contextMenuOpenCloseTest() {
+        ButtonElement button = $(ButtonElement.class).first();
+        ContextMenuElement.openByRightClick(button);
+        ContextMenuElement contextMenu = $(ContextMenuElement.class).first();
+        Assert.assertTrue(contextMenu.isOpen());
+        button.click();
+        Assert.assertFalse(contextMenu.isOpen());
+    }
+}
diff --git a/vaadin-context-menu-flow-parent/vaadin-context-menu-testbench/src/main/java/com/vaadin/flow/component/contextmenu/testbench/ContextMenuElement.java b/vaadin-context-menu-flow-parent/vaadin-context-menu-testbench/src/main/java/com/vaadin/flow/component/contextmenu/testbench/ContextMenuElement.java
index 8c89ba25083..3b8b58e71c0 100644
--- a/vaadin-context-menu-flow-parent/vaadin-context-menu-testbench/src/main/java/com/vaadin/flow/component/contextmenu/testbench/ContextMenuElement.java
+++ b/vaadin-context-menu-flow-parent/vaadin-context-menu-testbench/src/main/java/com/vaadin/flow/component/contextmenu/testbench/ContextMenuElement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2024 Vaadin Ltd.
+ * Copyright 2000-2023 Vaadin Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
@@ -15,25 +15,12 @@
  */
 package com.vaadin.flow.component.contextmenu.testbench;
 
+import org.openqa.selenium.StaleElementReferenceException;
+import org.openqa.selenium.interactions.Actions;
+
 import com.vaadin.testbench.TestBenchElement;
 import com.vaadin.testbench.elementsbase.Element;
 
-/*
- * Copyright 2000-2022 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
 /**
  * A TestBench element representing a <vaadin-context-menu>
  * element.
@@ -44,4 +31,29 @@
 @Element("vaadin-context-menu")
 public class ContextMenuElement extends TestBenchElement {
 
+    /**
+     * This is an utility method, which will produce context click on the target
+     * element. If the target had ContextMenu, after opening the last
+     * ContextMenuOverlayElement can be used to find its menu items.
+     *
+     * @param target
+     *            The element to which the ContextMenu has been hooked to.
+     */
+    public static void openByRightClick(TestBenchElement target) {
+        Actions action = new Actions(target.getDriver());
+        action.contextClick(target).perform();
+    }
+
+    /**
+     * Check if the ContextMenu is open.
+     *
+     * @return boolean True if menu is open.
+     */
+    public boolean isOpen() {
+        try {
+            return getAttribute("opened").equals("true");
+        } catch (StaleElementReferenceException e) {
+            return false;
+        }
+    }
 }
diff --git a/vaadin-context-menu-flow-parent/vaadin-context-menu-testbench/src/main/java/com/vaadin/flow/component/contextmenu/testbench/ContextMenuItemElement.java b/vaadin-context-menu-flow-parent/vaadin-context-menu-testbench/src/main/java/com/vaadin/flow/component/contextmenu/testbench/ContextMenuItemElement.java
new file mode 100644
index 00000000000..2182f3b6b81
--- /dev/null
+++ b/vaadin-context-menu-flow-parent/vaadin-context-menu-testbench/src/main/java/com/vaadin/flow/component/contextmenu/testbench/ContextMenuItemElement.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2023 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.flow.component.contextmenu.testbench;
+
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.Element;
+
+/**
+ * A TestBench element representing a <vaadin-context-menu>
+ * element.
+ *
+ * @author Vaadin Ltd
+ *
+ */
+@Element("vaadin-context-menu-item")
+public class ContextMenuItemElement extends TestBenchElement {
+
+    /**
+     * Open the potential sub menu of the this item by hovering. If there was a
+     * submenu, after opening the last ContextMenuOverlayElement can be used to
+     * find its menu items.
+     */
+    public void openSubMenu() {
+        hoverOn(this);
+    }
+
+    protected void hoverOn(WebElement element) {
+        Actions action = new Actions(getDriver());
+        action.moveToElement(element).perform();
+    }
+
+}
diff --git a/vaadin-context-menu-flow-parent/vaadin-context-menu-testbench/src/main/java/com/vaadin/flow/component/contextmenu/testbench/ContextMenuOverlayElement.java b/vaadin-context-menu-flow-parent/vaadin-context-menu-testbench/src/main/java/com/vaadin/flow/component/contextmenu/testbench/ContextMenuOverlayElement.java
new file mode 100644
index 00000000000..45c9ced4391
--- /dev/null
+++ b/vaadin-context-menu-flow-parent/vaadin-context-menu-testbench/src/main/java/com/vaadin/flow/component/contextmenu/testbench/ContextMenuOverlayElement.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2023 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.flow.component.contextmenu.testbench;
+
+import java.util.List;
+import java.util.Optional;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elementsbase.Element;
+
+/**
+ * A TestBench element representing a
+ * <vaadin-context-menu-overlay> element.
+ *
+ * @author Vaadin Ltd
+ *
+ */
+@Element("vaadin-context-menu-overlay")
+public class ContextMenuOverlayElement extends TestBenchElement {
+
+    /**
+     * Get the first menu item matching the caption.
+     *
+     * @return Optional menu item.
+     */
+    public Optional getMenuItem(String caption) {
+        return getMenuItems().stream()
+                .filter(item -> item.getText().equals(caption)).findFirst();
+    }
+
+    /**
+     * Get the MenuItems of this ContextMenuOverlayElement.
+     *
+     * @return List of ContextMenuItemElement.
+     */
+    public List getMenuItems() {
+        return $(ContextMenuItemElement.class).all();
+    }
+}