/******************************************************************************* * Mission Control Technologies, Copyright (c) 2009-2012, United States Government * as represented by the Administrator of the National Aeronautics and Space * Administration. All rights reserved. * * The MCT platform is 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. * * MCT includes source code licensed under additional open source licenses. See * the MCT Open Source Licenses file included with this distribution or the About * MCT Licenses dialog available at runtime from the MCT Help menu for additional * information. *******************************************************************************/ package gov.nasa.arc.mct.gui.util; import gov.nasa.arc.mct.util.condition.Condition; import java.awt.Component; import java.awt.Container; import java.awt.EventQueue; import java.awt.Window; import java.lang.reflect.InvocationTargetException; import javax.swing.AbstractButton; /** * Utility methods useful for testing GUI objects. * * @author mrose * */ public class TestUtilities { /** * Find a descendant button in the container <code>root</code> that has * a <code>getText()</code> method that returns the given text. * * @param root the root of the hierarchy to search * @param desiredText the text of the button we're looking fore * @return the descendant found, or null */ public static AbstractButton findDescendantButtonWithText(Container root, String desiredText) { Component[] children = root.getComponents(); // Try to find a direct child first. for (int i=0; i<children.length; ++i) { if (children[i] instanceof AbstractButton) { AbstractButton button = (AbstractButton) children[i]; if (button.getText().equals(desiredText)) { return button; } } } // OK, try child containers, too. for (int i=0; i<children.length; ++i) { if (children[i] instanceof Container) { AbstractButton button = findDescendantButtonWithText((Container) children[i], desiredText); if (button != null) { return button; } } } // Not found. return null; } /** * A simple class to hold a single value. This can be used for testing * code that requires an object (for a model, e.g.) with a mutable * value. * * @author mrose * */ public static class Value { private boolean value; public Value(boolean value) { this.value = value; } public void setValue(boolean value) { this.value = value; } public boolean getValue() { return this.value; } } /** * Change a component's visibility, making the modification in the * GUI event thread. * * @param component the component to make visible or invisible * @param flag true, if the component should be made visible */ public static void setVisible(final Component component, boolean flag) { EventQueue.invokeLater(new Thread() { public void run() { component.setVisible(true); } }); } /** * Click a button, doing the click in the GUI event thread. * * @param button the button to click * @throws InvocationTargetException if the target is not a button * @throws InterruptedException if the thread was interrupted before the button could be clicked */ public static void doClick(final AbstractButton button) throws InterruptedException, InvocationTargetException { EventQueue.invokeAndWait(new Thread() { public void run() { button.doClick(); } }); } /** * Make sure a window is completely killed, so that it won't inhibit * Java from exiting. Use this method to ensure that any frames * created by test methods are destroyed at the end of testing. * (Perhaps use @BeforeMethod and @AfterMethod, e.g.) * * @param frame the top-level window to kill * @throws InvocationTargetException if the frame is not top-level window * @throws InterruptedException if the thread was interrupted before the frame could be killed */ public static void killWindow(final Window frame) throws InterruptedException, InvocationTargetException { EventQueue.invokeAndWait(new Runnable() { public void run() { frame.setVisible(false); } }); Condition.waitForCondition(5000, new Condition() { public boolean getValue() {return !frame.isVisible();} }); EventQueue.invokeAndWait(new Runnable() { public void run() { frame.dispose(); } }); Condition.waitForCondition(5000, new Condition() { public boolean getValue() {return !frame.isDisplayable();} }); } /** * Check to see if a test is being run with xvfb. We use the string ":1" as a test for its presence, * since this is recommended practice with xvfb usage. * @return */ public static boolean isXvfbTest() { String displayVar = System.getenv("DISPLAY"); if (displayVar != null && displayVar.equals(":1")) return true; else return false; } }