/** * 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 2012-2015 the original author or authors. */ package org.assertj.swing.core; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.swing.edt.GuiActionRunner.execute; import java.awt.Component; import java.util.ArrayList; import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import org.assertj.swing.annotation.RunsInEDT; import org.junit.Test; /** * Tests for {@link BasicRobot#findActivePopupMenu()}. * * @author Yvonne Wang * @author Alex Ruiz * @author DaveBrad */ public class BasicRobot_findActivePopupMenu_Test extends BasicRobot_TestCase { @RunsInEDT final JPopupMenu[] addPopupMenuToTextFieldWithCascade(int cascadePosition) { return createAndSetPopupMenuWithCascade(cascadePosition, window().textField(), "Luke", "Leia"); } /** * Create a single cascade arrangement as this is a closed circuit of * cascade. * * @param cascadePosition the menu-selection items position in the * inner-popup that is the JMenu which is a cascade * @param c the root component for the popup to be applied on * @param itemOne menuItem1 (a selectable item) * @param itemTwo menuItem2 (a selectable item)\ * * @return the built popup menu with the cascade inserted at the * cascadePosition */ @RunsInEDT public static JPopupMenu[] createAndSetPopupMenuWithCascade( final int cascadePosition, final JComponent c, final String itemOne, final String itemTwo) { return execute(() -> { // build the outer cascade popup JMenu outerMenu = new JMenu("cascade test"); outerMenu.add(new JMenuItem("cascade line 1")); outerMenu.add(new JMenuItem("cascade line 2")); // build the root popup, with dynamic position JPopupMenu popupMenu = new JPopupMenu(); // place the outer menu at different locations in popup menu order so // as to test for unknown boundaries(also because showPopupMenu positions // to the middle of the popup and causes an automatic sub-menu launch) switch (cascadePosition) { case 1: popupMenu.add(outerMenu); popupMenu.add(new JMenuItem(itemOne)); popupMenu.add(new JMenuItem(itemTwo)); break; default: case 2: popupMenu.add(new JMenuItem(itemOne)); popupMenu.add(outerMenu); popupMenu.add(new JMenuItem(itemTwo)); break; case 3: popupMenu.add(new JMenuItem(itemOne)); popupMenu.add(new JMenuItem(itemTwo)); popupMenu.add(outerMenu); break; } // record the positions of the popup in order of cascade-position ArrayList<JPopupMenu> popupArr = new ArrayList<>(); popupArr.add(popupMenu); // root popup, is inner popupArr.add(outerMenu.getPopupMenu()); // cascade 1 popup, is inner c.setComponentPopupMenu(popupMenu); return popupArr.toArray(new JPopupMenu[popupArr.size()]); }); } @RunsInEDT final JPopupMenu[] addPopupMenuToTextFieldWithCascadeWithCascade(int cascadeCascadePosition) { return createAndSetPopupMenuWithCascadeWithCascade(cascadeCascadePosition, window().textField(), "Luke2", "Leia2"); } /** * Create a multiple cascade arrangement as a more complex arrangement. * * @param cascadePosition the menu-selection items position in the * inner-popup that is the JMenu which is a cascade * @param c the root component for the popup to be applied on * @param itemOne menuItem1 (a selectable item) * @param itemTwo menuItem2 (a selectable item)\ * * @return the built popup menu with the cascade inserted at the * cascadeCascadePosition */ @RunsInEDT public static JPopupMenu[] createAndSetPopupMenuWithCascadeWithCascade( final int cascadeCascadePosition, final JComponent c, final String itemOne, final String itemTwo) { return execute(() -> { JMenu outerMenu = new JMenu("cascade2 test"); outerMenu.add(new JMenuItem("cascade2 1")); outerMenu.add(new JMenuItem("cascade2 2")); // associate the outer with the inner1 for testing purposes at // the provided menu position // although this may be done with set menu item to index, the comments // in Java source code suggest this is prone to error (OpenJDK 8 u77) JMenu inner1Menu = new JMenu("cascade1 test"); // place the outer menu at different locations in popup menu order so // as to test for unknown boundaries(also because showPopupMenu positions // to the middle of the popup and causes an automatic sub-menu launch) switch (cascadeCascadePosition) { case 1: inner1Menu.add(outerMenu); inner1Menu.add(new JMenuItem("cascade1 1")); inner1Menu.add(new JMenuItem("cascade1 2")); break; default: case 2: inner1Menu.add(new JMenuItem("cascade1 1")); inner1Menu.add(outerMenu); inner1Menu.add(new JMenuItem("cascade1 2")); break; case 3: inner1Menu.add(new JMenuItem("cascade1 1")); inner1Menu.add(new JMenuItem("cascade1 2")); inner1Menu.add(outerMenu); break; } // build the root popup, adding the inner stuff JPopupMenu popupMenu = new JPopupMenu(); popupMenu.add(new JMenuItem(itemOne)); popupMenu.add(inner1Menu); popupMenu.add(new JMenuItem(itemTwo)); // record the positions of the popup in order of cascade-position ArrayList<JPopupMenu> popupArr = new ArrayList<>(); // root popup, is inner popupArr.add(popupMenu); // cascade 1 popup, is inner popupArr.add(inner1Menu.getPopupMenu()); // cascade 2 popup, is outer popupArr.add(outerMenu.getPopupMenu()); c.setComponentPopupMenu(popupMenu); return popupArr.toArray(new JPopupMenu[popupArr.size()]); }); } @RunsInEDT public static JPopupMenu createAndSetPopupMenuWithCascade(final JComponent c, final String itemOne, final String itemTwo) { return execute(() -> { JPopupMenu popupMenu = new JPopupMenu(); JPopupMenu outerMenu = new JPopupMenu("cascade test"); outerMenu.add(new JMenuItem("cascade line 1")); outerMenu.add(new JMenuItem("cascade line 2")); popupMenu.add(new JMenuItem(itemOne)); popupMenu.add(outerMenu); popupMenu.add(new JMenuItem(itemTwo)); c.setComponentPopupMenu(popupMenu); return outerMenu; }); } /** Perform the single cascade test for the popup in the N position. */ private void should_Return_Outer_PopupMenu_When_Having_A_CascadingPopup_Select_N(int selectMenu) throws InterruptedException { int selectMenuIdx = selectMenu - 1; // build the popup to be tested against JPopupMenu[] popupMenuArray = addPopupMenuToTextFieldWithCascade(selectMenu); // show-popup-menu will launch the popup and select the menu item that // is at the middle of the list // HOWEVER, the middle selection is done after a pause robot().showPopupMenu(window().textField()); JPopupMenu found = robot().findActivePopupMenu(); assertThat(found).isSameAs(popupMenuArray[0]); // crude but effect way to get the cascade Component o = found.getComponent(selectMenuIdx); robot().focus(o); pauseYieldForFocusChange(); // after the HOWEVER will expect the cascade to be presented found = robot().findActivePopupMenu(); assertThat(found).isSameAs(popupMenuArray[1]); } /** Perform the cascade cascade test for the popup in the N position. */ private void should_Return_Outer_PopupMenu_When_Having_A_CascadingCascadePopup_Select_N(int selectMenu) throws InterruptedException { int selectMenuIdx = selectMenu - 1; // build the popup to be tested against JPopupMenu[] popupMenuArray = addPopupMenuToTextFieldWithCascadeWithCascade(selectMenu); // show-popup-menu will launch the popup and select the menu item that // is at the middle of the list // HOWEVER, the middle selection is done after a pause robot().showPopupMenu(window().textField()); JPopupMenu found = robot().findActivePopupMenu(); assertThat(found).isSameAs(popupMenuArray[0]); // crude but effect way to get the cascade Component o = found.getComponent(1); robot().focus(o); // need a pause to allow the focus request to happen and new popup to be shown pauseYieldForFocusChange(); // after the HOWEVER will expect the cascade to be presented found = robot().findActivePopupMenu(); // crude but effect way to get the cascade o = found.getComponent(selectMenuIdx); robot().focus(o); pauseYieldForFocusChange(); found = robot().findActivePopupMenu(); assertThat(found).isSameAs(popupMenuArray[2]); } /** Crude pause to allow the robot focus change event to propagate to a component. */ private void pauseYieldForFocusChange() throws InterruptedException { // need a pause to allow the focus request to happen and new popup to be shown // (focus and wait does not seem to happen, suspect the thread is not // yielding to allow the focus change to happen) // 300-500 works consistently, < 300 is if for test pass condition { 500 // is better choice for slower machines that may be farmed into testing versus development) Thread.sleep(500); } @Test public void should_Return_Outer_PopupMenu_When_Having_A_CascadingPopup_Select_3() throws InterruptedException { should_Return_Outer_PopupMenu_When_Having_A_CascadingPopup_Select_N(3); } @Test public void should_Return_Outer_PopupMenu_When_Having_A_CascadingPopup_Select_2() throws InterruptedException { should_Return_Outer_PopupMenu_When_Having_A_CascadingPopup_Select_N(2); } @Test public void should_Return_Outer_PopupMenu_When_Having_A_CascadingPopup_Select_1() throws InterruptedException { should_Return_Outer_PopupMenu_When_Having_A_CascadingPopup_Select_N(1); } @Test public void should_Return_Outer_PopupMenu_When_Having_A_CascadingCascadePopup_Select_3() throws InterruptedException { should_Return_Outer_PopupMenu_When_Having_A_CascadingCascadePopup_Select_N(3); } @Test public void should_Return_Outer_PopupMenu_When_Having_A_CascadingCascadePopup_Select_2() throws InterruptedException { should_Return_Outer_PopupMenu_When_Having_A_CascadingCascadePopup_Select_N(2); } @Test public void should_Return_Outer_PopupMenu_When_Having_A_CascadingCascadePopup_Select_1() throws InterruptedException { should_Return_Outer_PopupMenu_When_Having_A_CascadingCascadePopup_Select_N(1); } @Test public void should_Return_Active_PopupMenu() { JPopupMenu popupMenu = addPopupMenuToTextField(); robot().showPopupMenu(window().textField()); JPopupMenu found = robot().findActivePopupMenu(); assertThat(found).isSameAs(popupMenu); } @Test public void should_Return_Null_If_Active_PopupMenu_Not_Found() { JPopupMenu found = robot().findActivePopupMenu(); assertThat(found).isNull(); } }