/* * Copyright 2000-2016 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.testbench.elements; import java.util.List; import java.util.NoSuchElementException; import org.openqa.selenium.By; import org.openqa.selenium.Point; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; import com.vaadin.testbench.elementsbase.ServerClass; @ServerClass("com.vaadin.ui.MenuBar") public class MenuBarElement extends AbstractComponentElement { private Point lastItemLocationMovedTo = null; /** * Clicks on a visible item.<br> * If the item is a top level menu, the submenu is opened if it was closed, * or closed if it was opened.<br> * If the item is another submenu, that submenu is opened.<br> * If the item is not a submenu, it will be clicked and trigger any actions * associated to it. * * @param item * name of the item to click * @throws NullPointerException * if item does not exist or is not visible */ private void clickItem(String item) { WebElement webElement = getVisibleItem("#" + item); if (webElement == null) { throw new NoSuchElementException( "Menu item " + item + " is not available."); } activateOrOpenSubmenu(webElement, true); } /** * Clicks the item specified by a full path given as variable arguments.<br> * Fails if path given is not full (ie: last submenu is already opened, and * path given is last item only). * <p> * Example: * </p> * * <pre> * // clicks on "File" item * menuBarElement.click("File"); * // clicks on "Copy" item in "File" top level menu. * menuBarElement.click("File", "Copy"); * </pre> * * @param path * Array of items to click through */ public void clickItem(String... path) { if (path.length > 1) { closeAll(); } for (String itemName : path) { clickItem(itemName); } } /** * Closes all submenus, if any is open.<br> * This is done by clicking on the currently selected top level item. */ private void closeAll() { lastItemLocationMovedTo = null; WebElement selectedItem = getSelectedTopLevelItem(); if (selectedItem != null) { activateOrOpenSubmenu(selectedItem, true); } } private WebElement getSelectedTopLevelItem() { List<WebElement> selectedItems = findElements( By.className("v-menubar-menuitem-selected")); if (selectedItems.size() == 0) { return null; } return selectedItems.get(0); } private WebElement getVisibleItem(String item) { return findElement(com.vaadin.testbench.By.vaadin(item)); } private void activateOrOpenSubmenu(WebElement item, boolean alwaysClick) { if (lastItemLocationMovedTo == null || !isAnySubmenuVisible()) { item.click(); if (hasSubmenu(item)) { lastItemLocationMovedTo = item.getLocation(); } return; } // Assumes mouse is still at position of last clicked element Actions action = new Actions(getDriver()); action.moveToElement(item); action.build().perform(); if (isLeaf(item) || isSelectedTopLevelItem(item)) { lastItemLocationMovedTo = null; } else { lastItemLocationMovedTo = item.getLocation(); } if (alwaysClick || isLeaf(item) || !isAnySubmenuVisible()) { action = new Actions(getDriver()); action.click(); action.build().perform(); } } private boolean isSelectedTopLevelItem(WebElement item) { WebElement selectedItem = getSelectedTopLevelItem(); if (selectedItem == null) { return false; } String itemCaption = item .findElements(By.className("v-menubar-menuitem-caption")).get(0) .getAttribute("innerHTML"); String selectedItemCaption = selectedItem .findElements(By.className("v-menubar-menuitem-caption")).get(0) .getAttribute("innerHTML"); return itemCaption.equals(selectedItemCaption); } private boolean isAnySubmenuVisible() { WebElement selectedItem = getSelectedTopLevelItem(); if (selectedItem == null) { return false; } return hasSubmenu(selectedItem); } private boolean hasSubmenu(WebElement item) { List<WebElement> submenuIndicatorElements = item .findElements(By.className("v-menubar-submenu-indicator")); return submenuIndicatorElements.size() != 0; } private boolean isLeaf(WebElement item) { return !hasSubmenu(item); } }