org.assertj.swing.driver.JMenuItemDriver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of assertj-swing Show documentation
Show all versions of assertj-swing Show documentation
Fluent interface for functional GUI testing
/*
* Created on Jan 30, 2008
*
* 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.
*
* Copyright @2008-2013 the original author or authors.
*/
package org.assertj.swing.driver;
import static java.lang.Boolean.getBoolean;
import static org.assertj.core.util.Preconditions.checkNotNull;
import static org.assertj.core.util.Strings.concat;
import static org.assertj.swing.core.WindowAncestorFinder.windowAncestorOf;
import static org.assertj.swing.driver.ComponentPreconditions.checkEnabledAndShowing;
import static org.assertj.swing.driver.JMenuPopupMenuQuery.popupMenuOf;
import static org.assertj.swing.driver.WindowMoveToFrontTask.toFront;
import static org.assertj.swing.edt.GuiActionRunner.execute;
import static org.assertj.swing.exception.ActionFailedException.actionFailure;
import static org.assertj.swing.format.Formatting.format;
import static org.assertj.swing.timing.Pause.pause;
import static org.assertj.swing.util.Platform.isOSX;
import java.awt.Component;
import java.awt.Window;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import org.assertj.swing.annotation.RunsInEDT;
import org.assertj.swing.core.Robot;
import org.assertj.swing.edt.GuiQuery;
import org.assertj.swing.edt.GuiTask;
import org.assertj.swing.exception.ActionFailedException;
import org.assertj.swing.internal.annotation.InternalApi;
/**
*
* Supports functional testing of {@code JMenuItem}s.
*
*
*
* Note: This class is intended for internal use only. Please use the classes in the package
* {@link org.assertj.swing.fixture} in your tests.
*
*
* @author Alex Ruiz
* @author Yvonne Wang
*/
@InternalApi
public class JMenuItemDriver extends JComponentDriver {
/**
* Creates a new {@link JMenuItemDriver}.
*
* @param robot the robot to use to simulate user input.
*/
public JMenuItemDriver(@Nonnull Robot robot) {
super(robot);
}
@Override
public void click(Component c) {
/*
* Since our internal methods now all call click(Component) this is used to route the method calls to the correct
* method (either the parent method or the click(JMenuItem)).
*/
if (c instanceof JMenuItem) {
click((JMenuItem) c);
} else {
super.click(c);
}
}
/**
* Finds and selects the given {@code JMenuItem}.
*
* @param menuItem the {@code JMenuItem} to select.
* @throws IllegalStateException if the menu to select is disabled.
* @throws IllegalStateException if the menu to select is not showing on the screen.
* @throws ActionFailedException if the menu has a pop-up and it fails to show up.
*/
@RunsInEDT
public void click(@Nonnull JMenuItem menuItem) {
show(menuItem);
doClick(menuItem);
ensurePopupIsShowing(menuItem);
}
@RunsInEDT
private void show(@Nonnull JMenuItem menuItem) {
JMenuItemLocation location = locationOf(menuItem);
activateParentIfIsMenu(location);
moveParentWindowToFront(location);
if (menuItem instanceof JMenu && !location.inMenuBar()) {
waitForSubMenuToShow();
}
}
@RunsInEDT
private static @Nonnull JMenuItemLocation locationOf(final @Nonnull JMenuItem menuItem) {
JMenuItemLocation result = execute(new GuiQuery() {
@Override
protected JMenuItemLocation executeInEDT() {
return new JMenuItemLocation(menuItem);
}
});
return checkNotNull(result);
}
@RunsInEDT
private void activateParentIfIsMenu(@Nonnull JMenuItemLocation location) {
if (!location.isParentAMenu()) {
return;
}
Component c = location.parentOrInvoker();
if (c instanceof JMenuItem) {
click((JMenuItem) c);
}
}
@RunsInEDT
private void moveParentWindowToFront(@Nonnull JMenuItemLocation location) {
if (!location.inMenuBar()) {
return;
}
// TODO windowAncestorOf is not being called in EDT
moveToFront(windowAncestorOf(location.parentOrInvoker()));
}
@RunsInEDT
private void doClick(@Nonnull JMenuItem menuItem) {
if (isMacOSMenuBar()) {
validateAndDoClick(menuItem);
return;
}
super.click(menuItem);
robot.waitForIdle();
}
private boolean isMacOSMenuBar() {
return isOSX() && (getBoolean("apple.laf.useScreenMenuBar") || getBoolean("com.apple.macos.useScreenMenuBar"));
}
@RunsInEDT
private static void validateAndDoClick(final @Nonnull JMenuItem menuItem) {
execute(new GuiTask() {
@Override
protected void executeInEDT() {
checkEnabledAndShowing(menuItem);
menuItem.doClick();
}
});
}
@RunsInEDT
private void ensurePopupIsShowing(@Nonnull JMenuItem menuItem) {
if (!(menuItem instanceof JMenu)) {
return;
}
JPopupMenu popup = popupMenuOf((JMenu) menuItem);
// TODO review EDT access
if (!waitForShowing(popup, robot.settings().timeoutToFindPopup())) {
throw actionFailure(concat("Clicking on menu item <", format(menuItem), "> never showed a pop-up menu"));
}
waitForSubMenuToShow();
}
private void waitForSubMenuToShow() {
pause(robot.settings().timeoutToFindSubMenu());
}
@RunsInEDT
private void moveToFront(@Nullable Window w) {
if (w == null) {
return;
}
// Make sure the window is in front, or its menus may be obscured by another window.
toFront(w);
robot.waitForIdle();
robot.moveMouse(w);
}
}